Files
PsAgentAI/venv/lib/python3.11/site-packages/telegram/_utils/files.py
T
marcocosta10000 6b3b6541a7 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.
2026-10-25 17:05:13 -03:00

153 lines
5.6 KiB
Python

#!/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 helper functions related to handling of files.
.. versionchanged:: 20.0
Previously, the contents of this module were available through the (no longer existing)
module ``telegram._utils.helpers``.
Warning:
Contents of this module are intended to be used internally by the library and *not* by the
user. Changes to this module are not considered breaking changes and may not be documented in
the changelog.
"""
from pathlib import Path
from typing import IO, TYPE_CHECKING, Any, Optional, Tuple, Type, TypeVar, Union, cast, overload
from telegram._utils.types import FileInput, FilePathInput
if TYPE_CHECKING:
from telegram import InputFile, TelegramObject
_T = TypeVar("_T", bound=Union[bytes, "InputFile", str, Path, None])
@overload
def load_file(obj: IO[bytes]) -> Tuple[Optional[str], bytes]:
...
@overload
def load_file(obj: _T) -> Tuple[None, _T]:
...
def load_file(
obj: Optional[FileInput],
) -> Tuple[Optional[str], Union[bytes, "InputFile", str, Path, None]]:
"""If the input is a file handle, read the data and name and return it. Otherwise, return
the input unchanged.
"""
if obj is None:
return None, None
try:
contents = obj.read() # type: ignore[union-attr]
except AttributeError:
return None, cast(Union[bytes, "InputFile", str, Path], obj)
if hasattr(obj, "name") and not isinstance(obj.name, int):
filename = Path(obj.name).name
else:
filename = None
return filename, contents
def is_local_file(obj: Optional[FilePathInput]) -> bool:
"""
Checks if a given string is a file on local system.
Args:
obj (:obj:`str`): The string to check.
"""
if obj is None:
return False
path = Path(obj)
try:
return path.is_file()
except Exception:
return False
def parse_file_input( # pylint: disable=too-many-return-statements
file_input: Union[FileInput, "TelegramObject"],
tg_type: Optional[Type["TelegramObject"]] = None,
filename: Optional[str] = None,
attach: bool = False,
local_mode: bool = False,
) -> Union[str, "InputFile", Any]:
"""
Parses input for sending files:
* For string input, if the input is an absolute path of a local file:
* if ``local_mode`` is ``True``, adds the ``file://`` prefix. If the input is a relative
path of a local file, computes the absolute path and adds the ``file://`` prefix.
* if ``local_mode`` is ``False``, loads the file as binary data and builds an
:class:`InputFile` from that
Returns the input unchanged, otherwise.
* :class:`pathlib.Path` objects are treated the same way as strings.
* For IO and bytes input, returns an :class:`telegram.InputFile`.
* If :attr:`tg_type` is specified and the input is of that type, returns the ``file_id``
attribute.
Args:
file_input (:obj:`str` | :obj:`bytes` | :term:`file object` | Telegram media object): The
input to parse.
tg_type (:obj:`type`, optional): The Telegram media type the input can be. E.g.
:class:`telegram.Animation`.
filename (:obj:`str`, optional): The filename. Only relevant in case an
:class:`telegram.InputFile` is returned.
attach (:obj:`bool`, optional): Pass :obj:`True` if the parameter this file belongs to in
the request to Telegram should point to the multipart data via an ``attach://`` URI.
Defaults to `False`. Only relevant if an :class:`telegram.InputFile` is returned.
local_mode (:obj:`bool`, optional): Pass :obj:`True` if the bot is running an api server
in ``--local`` mode.
Returns:
:obj:`str` | :class:`telegram.InputFile` | :obj:`object`: The parsed input or the untouched
:attr:`file_input`, in case it's no valid file input.
"""
# Importing on file-level yields cyclic Import Errors
from telegram import InputFile # pylint: disable=import-outside-toplevel
if isinstance(file_input, str) and file_input.startswith("file://"):
if not local_mode:
raise ValueError("Specified file input is a file URI, but local mode is not enabled.")
return file_input
if isinstance(file_input, (str, Path)):
if is_local_file(file_input):
path = Path(file_input)
if local_mode:
return path.absolute().as_uri()
return InputFile(path.open(mode="rb"), filename=filename, attach=attach)
return file_input
if isinstance(file_input, bytes):
return InputFile(file_input, filename=filename, attach=attach)
if hasattr(file_input, "read"):
return InputFile(cast(IO, file_input), filename=filename, attach=attach)
if tg_type and isinstance(file_input, tg_type):
return file_input.file_id # type: ignore[attr-defined]
return file_input