HEX
Server: LiteSpeed
System: Linux s787.bom1.mysecurecloudhost.com 4.18.0-477.13.1.lve.el8.x86_64 #1 SMP Thu Jun 1 16:40:47 EDT 2023 x86_64
User: mobilech (5348)
PHP: 8.1.34
Disabled: NONE
Upload Files
File: //proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/beacons/telegram_bot_msg.py
"""
Beacon to emit Telegram messages

Requires the python-telegram-bot library

"""

import asyncio
import inspect
import logging

import salt.utils.beacons

try:
    import telegram

    logging.getLogger("telegram").setLevel(logging.CRITICAL)
    HAS_TELEGRAM = True
except ImportError:
    HAS_TELEGRAM = False

log = logging.getLogger(__name__)


__virtualname__ = "telegram_bot_msg"


async def _async_get_updates(token, **kwargs):
    """
    Asynchronous helper to get updates from Telegram Bot
    """
    async with telegram.Bot(token) as bot:
        return await bot.get_updates(**kwargs)


def _get_updates(token, **kwargs):
    """
    Synchronous wrapper for getting updates, handles both v13 and v20+
    """
    if HAS_TELEGRAM and inspect.iscoroutinefunction(telegram.Bot.get_updates):
        return asyncio.run(_async_get_updates(token, **kwargs))
    else:
        bot = telegram.Bot(token)
        return bot.get_updates(**kwargs)


def __virtual__():
    if HAS_TELEGRAM:
        return __virtualname__
    else:
        err_msg = "telegram library is missing."
        log.error("Unable to load %s beacon: %s", __virtualname__, err_msg)
        return False, err_msg


def validate(config):
    """
    Validate the beacon configuration
    """
    if not isinstance(config, list):
        return False, "Configuration for telegram_bot_msg beacon must be a list."

    config = salt.utils.beacons.list_to_dict(config)

    if not all(
        config.get(required_config) for required_config in ["token", "accept_from"]
    ):
        return (
            False,
            "Not all required configuration for telegram_bot_msg are set.",
        )

    if not isinstance(config.get("accept_from"), list):
        return (
            False,
            "Configuration for telegram_bot_msg, "
            "accept_from must be a list of usernames.",
        )

    return True, "Valid beacon configuration."


def beacon(config):
    """
    Emit a dict with a key "msgs" whose value is a list of messages
    sent to the configured bot by one of the allowed usernames.

    .. code-block:: yaml

        beacons:
          telegram_bot_msg:
            - token: "<bot access token>"
            - accept_from:
              - "<valid username>"
            - interval: 10

    """

    config = salt.utils.beacons.list_to_dict(config)

    log.debug("telegram_bot_msg beacon starting")
    ret = []
    output = {}
    output["msgs"] = []

    updates = _get_updates(config["token"], limit=100, timeout=0)

    log.debug("Num updates: %d", len(updates))
    if not updates:
        log.debug("Telegram Bot beacon has no new messages")
        return ret

    latest_update_id = 0
    for update in updates:
        message = update.message

        if update.update_id > latest_update_id:
            latest_update_id = update.update_id

        if message.chat.username in config["accept_from"]:
            output["msgs"].append(message.to_dict())

    # mark in the server that previous messages are processed
    _get_updates(config["token"], offset=latest_update_id + 1)

    log.debug("Emitting %d messages.", len(output["msgs"]))
    if output["msgs"]:
        ret.append(output)
    return ret