Source code for iamlistening.main
"""
IAmListening Main
"""
import asyncio
import importlib
from loguru import logger
from iamlistening import __version__
from iamlistening.config import settings
[docs]
class Listener:
"""
Listener Class for IAmListening.
This class provides methods for
starting and stopping the listener
for each platform.
Methods:
_create_client(self, **kwargs)
get_all_client_classes(self)
get_info(self)
start(self)
stop(self)
"""
[docs]
def __init__(self):
"""
Initializes the class instance by creating and appending clients
based on the configuration in `settings.platform`.
Checks if the module is enabled by looking at `settings.iamlistening_enabled`.
If the module is disabled, no clients will be created.
Creates a mapping of library names to client classes.
This mapping is used to create new clients based on the configuration.
If a client's configuration exists in `settings.platform` and its "enabled"
key is truthy, it will be created.
Clients are not created if their name is "template" or empty string.
If a client is successfully created, it is appended to the `clients` list.
If a client fails to be created, a message is logged with the name of the
client and the error that occurred.
Parameters:
None
Returns:
None
"""
# Check if the module is enabled
self.enabled = settings.iamlistening_enabled
# Create a mapping of library names to client classes
self.client_classes = self.get_all_client_classes()
# logger.debug("client_classes available {}", self.client_classes)
if not self.enabled:
logger.info("Module is disabled. No Client will be created.")
return
self.clients = []
# Use .get() for safer access to the nested table
platform_config_table = settings.get('platform', {})
if not platform_config_table:
logger.warning("No 'platform' configuration table found in settings.")
# Create a client for each client in the retrieved table
for name, client_config in platform_config_table.items():
if (
# Skip empty client configs
client_config is None
# Skip non-dict client configs
or not isinstance(client_config, dict)
# Skip template and empty string client names
or name in ["", "template"]
# Skip disabled clients
or not client_config.get("enabled")
):
continue
# Create the client
logger.debug("Creating client {}", name)
client = self._create_client(**client_config, name=name)
# If the client has a valid client attribute, append it to the list
if client and getattr(client, "client", None):
self.clients.append(client)
# Log the number of clients that were created
logger.info(f"Loaded {len(self.clients)} clients")
if not self.clients:
logger.warning(
"No Client were created. Check your settings or disable the module."
)
[docs]
def _create_client(self, **kwargs):
"""
Create a client based on the given protocol.
This function takes in a dictionary of keyword arguments, `kwargs`,
containing the necessary information to create a client. The required
key in `kwargs` is "library", which specifies the protocol to use for
communication with the LLM. The value of "platform" must match one of the
libraries supported by iamlistening.
This function retrieves the class used to create the client based on the
value of "library" from the mapping of library names to client classes
stored in `self.client_classes`. If the value of "library" does not
match any of the libraries supported, the function logs an error message
and returns None.
If the class used to create the client is found, the function creates a
new instance of the class using the keyword arguments in `kwargs` and
returns it.
The function returns a client object based on the specified protocol
or None if the library is not supported.
Parameters:
**kwargs (dict): A dictionary of keyword arguments containing the
necessary information for creating the client. The required key is
"platform".
Returns:
A client object based on the specified protocol or None if the
library is not supported.
"""
library = (
kwargs.get("library")
or kwargs.get("platform")
or kwargs.get("protocol")
or kwargs.get("parser_library")
or "telegram"
)
cls = self.client_classes.get((f"{library.capitalize()}Handler"))
return None if cls is None else cls(**kwargs)
[docs]
def get_all_client_classes(self):
"""
Retrieves all client classes from the `iamlistening.protocol` module.
This function imports the `iamlistening.protocol` module and retrieves
all the classes defined in it.
The function returns a dictionary where the keys are the
names of the classes and the values are the corresponding
class objects.
Returns:
dict: A dictionary containing all the client classes
from the `iamlistening.protocol` module.
"""
provider_module = importlib.import_module("iamlistening.handler")
return {
name: cls
for name, cls in provider_module.__dict__.items()
if isinstance(cls, type)
}
[docs]
async def get_info(self):
"""
Retrieves information about the exchange
and the account.
:return: A formatted string containing
the exchange name and the account information.
:rtype: str
"""
version_info = f"âšī¸ {type(self).__name__} {__version__}\n"
client_info = "".join(f"đ {client.platform}\n" for client in self.clients)
return version_info + client_info.strip()
[docs]
async def start(self):
"""
Asynchronously start the listener.
This method starts the chat managers for each platform
and logs the status.
"""
logger.debug("Listener starting")
if not self.clients:
logger.warning("No client to start")
return
tasks = [client.start() for client in self.clients]
await asyncio.gather(*tasks)
[docs]
def stop(self):
"""
Stop the listener.
This method stops the chat managers for each platform.
"""
for client in self.clients:
client.stop()