feat: add psagentai agent with deployment and configuration

Initial project setup including the main agent script, configuration
files, profile JSON state, systemd service unit, startup script,
deployment documentation, and Python dependencies.

Includes .env, venv/, and __pycache__/ which should likely be
excluded via .gitignore to avoid committing secrets and artifacts.
This commit is contained in:
2026-10-25 17:05:13 -03:00
commit 6b3b6541a7
3792 changed files with 805563 additions and 0 deletions
@@ -0,0 +1,241 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the class Defaults, which allows passing default values to Application."""
import datetime
from typing import Any, Dict, NoReturn, Optional, final
from telegram._utils.datetime import UTC
@final
class Defaults:
"""Convenience Class to gather all parameters with a (user defined) default value
.. seealso:: :wiki:`Architecture Overview <Architecture>`,
:wiki:`Adding Defaults to Your Bot <Adding-defaults-to-your-bot>`
.. versionchanged:: 20.0
Removed the argument and attribute ``timeout``. Specify default timeout behavior for the
networking backend directly via :class:`telegram.ext.ApplicationBuilder` instead.
Parameters:
parse_mode (:obj:`str`, optional): |parse_mode|
disable_notification (:obj:`bool`, optional): |disable_notification|
disable_web_page_preview (:obj:`bool`, optional): Disables link previews for links in this
message.
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
quote (:obj:`bool`, optional): If set to :obj:`True`, the reply is sent as an actual reply
to the message. If ``reply_to_message_id`` is passed, this parameter will
be ignored. Default: :obj:`True` in group chats and :obj:`False` in private chats.
tzinfo (:class:`datetime.tzinfo`, optional): A timezone to be used for all date(time)
inputs appearing throughout PTB, i.e. if a timezone naive date(time) object is passed
somewhere, it will be assumed to be in :paramref:`tzinfo`. If the
:class:`telegram.ext.JobQueue` is used, this must be a timezone provided
by the ``pytz`` module. Defaults to ``pytz.utc``, if available, and
:attr:`datetime.timezone.utc` otherwise.
block (:obj:`bool`, optional): Default setting for the :paramref:`BaseHandler.block`
parameter
of handlers and error handlers registered through :meth:`Application.add_handler` and
:meth:`Application.add_error_handler`. Defaults to :obj:`True`.
protect_content (:obj:`bool`, optional): |protect_content|
.. versionadded:: 20.0
"""
__slots__ = (
"_tzinfo",
"_disable_web_page_preview",
"_block",
"_quote",
"_disable_notification",
"_allow_sending_without_reply",
"_parse_mode",
"_api_defaults",
"_protect_content",
)
def __init__(
self,
parse_mode: Optional[str] = None,
disable_notification: Optional[bool] = None,
disable_web_page_preview: Optional[bool] = None,
quote: Optional[bool] = None,
tzinfo: datetime.tzinfo = UTC,
block: bool = True,
allow_sending_without_reply: Optional[bool] = None,
protect_content: Optional[bool] = None,
):
self._parse_mode: Optional[str] = parse_mode
self._disable_notification: Optional[bool] = disable_notification
self._disable_web_page_preview: Optional[bool] = disable_web_page_preview
self._allow_sending_without_reply: Optional[bool] = allow_sending_without_reply
self._quote: Optional[bool] = quote
self._tzinfo: datetime.tzinfo = tzinfo
self._block: bool = block
self._protect_content: Optional[bool] = protect_content
# Gather all defaults that actually have a default value
self._api_defaults = {}
for kwarg in (
"parse_mode",
"explanation_parse_mode",
"disable_notification",
"disable_web_page_preview",
"allow_sending_without_reply",
"protect_content",
):
value = getattr(self, kwarg)
if value is not None:
self._api_defaults[kwarg] = value
def __hash__(self) -> int:
return hash(
(
self._parse_mode,
self._disable_notification,
self._disable_web_page_preview,
self._allow_sending_without_reply,
self._quote,
self._tzinfo,
self._block,
self._protect_content,
)
)
def __eq__(self, other: object) -> bool:
if isinstance(other, Defaults):
return all(getattr(self, attr) == getattr(other, attr) for attr in self.__slots__)
return False
@property
def api_defaults(self) -> Dict[str, Any]: # skip-cq: PY-D0003
return self._api_defaults
@property
def parse_mode(self) -> Optional[str]:
""":obj:`str`: Optional. Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or URLs in your bot's message.
"""
return self._parse_mode
@parse_mode.setter
def parse_mode(self, value: object) -> NoReturn:
raise AttributeError("You can not assign a new value to parse_mode after initialization.")
@property
def explanation_parse_mode(self) -> Optional[str]:
""":obj:`str`: Optional. Alias for :attr:`parse_mode`, used for
the corresponding parameter of :meth:`telegram.Bot.send_poll`.
"""
return self._parse_mode
@explanation_parse_mode.setter
def explanation_parse_mode(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to explanation_parse_mode after initialization."
)
@property
def disable_notification(self) -> Optional[bool]:
""":obj:`bool`: Optional. Sends the message silently. Users will
receive a notification with no sound.
"""
return self._disable_notification
@disable_notification.setter
def disable_notification(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to disable_notification after initialization."
)
@property
def disable_web_page_preview(self) -> Optional[bool]:
""":obj:`bool`: Optional. Disables link previews for links in this
message.
"""
return self._disable_web_page_preview
@disable_web_page_preview.setter
def disable_web_page_preview(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to disable_web_page_preview after initialization."
)
@property
def allow_sending_without_reply(self) -> Optional[bool]:
""":obj:`bool`: Optional. Pass :obj:`True`, if the message
should be sent even if the specified replied-to message is not found.
"""
return self._allow_sending_without_reply
@allow_sending_without_reply.setter
def allow_sending_without_reply(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to allow_sending_without_reply after initialization."
)
@property
def quote(self) -> Optional[bool]:
""":obj:`bool`: Optional. If set to :obj:`True`, the reply is sent as an actual reply
to the message. If ``reply_to_message_id`` is passed, this parameter will
be ignored. Default: :obj:`True` in group chats and :obj:`False` in private chats.
"""
return self._quote
@quote.setter
def quote(self, value: object) -> NoReturn:
raise AttributeError("You can not assign a new value to quote after initialization.")
@property
def tzinfo(self) -> datetime.tzinfo:
""":obj:`tzinfo`: A timezone to be used for all date(time) objects appearing
throughout PTB.
"""
return self._tzinfo
@tzinfo.setter
def tzinfo(self, value: object) -> NoReturn:
raise AttributeError("You can not assign a new value to tzinfo after initialization.")
@property
def block(self) -> bool:
""":obj:`bool`: Optional. Default setting for the :paramref:`BaseHandler.block` parameter
of handlers and error handlers registered through :meth:`Application.add_handler` and
:meth:`Application.add_error_handler`.
"""
return self._block
@block.setter
def block(self, value: object) -> NoReturn:
raise AttributeError("You can not assign a new value to block after initialization.")
@property
def protect_content(self) -> Optional[bool]:
""":obj:`bool`: Optional. Protects the contents of the sent message from forwarding and
saving.
.. versionadded:: 20.0
"""
return self._protect_content
@protect_content.setter
def protect_content(self, value: object) -> NoReturn:
raise AttributeError(
"You can't assign a new value to protect_content after initialization."
)