2022-04-24 12:38:09 +02:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
|
|
|
# A library that provides a Python interface to the Telegram Bot API
|
2024-02-19 20:06:25 +01:00
|
|
|
# Copyright (C) 2015-2024
|
2022-04-24 12:38:09 +02:00
|
|
|
# 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 a class that holds the parameters of a request to the Bot API."""
|
2022-05-19 12:47:53 +02:00
|
|
|
import json
|
2023-06-29 18:17:47 +02:00
|
|
|
from typing import Any, Dict, List, Optional, Union, final
|
2022-04-24 12:38:09 +02:00
|
|
|
from urllib.parse import urlencode
|
|
|
|
|
2024-07-21 21:13:30 +02:00
|
|
|
from telegram._utils.strings import TextEncoding
|
2022-04-24 12:38:09 +02:00
|
|
|
from telegram._utils.types import UploadFileDict
|
|
|
|
from telegram.request._requestparameter import RequestParameter
|
|
|
|
|
|
|
|
|
2023-06-29 18:17:47 +02:00
|
|
|
@final
|
2022-04-24 12:38:09 +02:00
|
|
|
class RequestData:
|
|
|
|
"""Instances of this class collect the data needed for one request to the Bot API, including
|
|
|
|
all parameters and files to be sent along with the request.
|
|
|
|
|
2022-05-06 17:15:23 +02:00
|
|
|
.. versionadded:: 20.0
|
2022-04-24 12:38:09 +02:00
|
|
|
|
|
|
|
Warning:
|
2023-07-09 11:22:08 +02:00
|
|
|
How exactly instances of this are created should be considered an implementation detail
|
|
|
|
and not part of PTBs public API. Users should exclusively rely on the documented
|
2022-04-24 12:38:09 +02:00
|
|
|
attributes, properties and methods.
|
|
|
|
|
|
|
|
Attributes:
|
|
|
|
contains_files (:obj:`bool`): Whether this object contains files to be uploaded via
|
|
|
|
``multipart/form-data``.
|
|
|
|
"""
|
|
|
|
|
|
|
|
__slots__ = ("_parameters", "contains_files")
|
|
|
|
|
2023-05-18 07:57:59 +02:00
|
|
|
def __init__(self, parameters: Optional[List[RequestParameter]] = None):
|
2023-02-02 18:55:07 +01:00
|
|
|
self._parameters: List[RequestParameter] = parameters or []
|
|
|
|
self.contains_files: bool = any(param.input_files for param in self._parameters)
|
2022-04-24 12:38:09 +02:00
|
|
|
|
|
|
|
@property
|
2023-02-02 18:55:07 +01:00
|
|
|
def parameters(self) -> Dict[str, Union[str, int, List[Any], Dict[Any, Any]]]:
|
2022-04-24 12:38:09 +02:00
|
|
|
"""Gives the parameters as mapping of parameter name to the parameter value, which can be
|
|
|
|
a single object of type :obj:`int`, :obj:`float`, :obj:`str` or :obj:`bool` or any
|
|
|
|
(possibly nested) composition of lists, tuples and dictionaries, where each entry, key
|
|
|
|
and value is of one of the mentioned types.
|
2024-08-02 13:41:39 +02:00
|
|
|
|
|
|
|
Returns:
|
|
|
|
Dict[:obj:`str`, Union[:obj:`str`, :obj:`int`, List[any], Dict[any, any]]]
|
2022-04-24 12:38:09 +02:00
|
|
|
"""
|
|
|
|
return {
|
|
|
|
param.name: param.value # type: ignore[misc]
|
|
|
|
for param in self._parameters
|
|
|
|
if param.value is not None
|
|
|
|
}
|
|
|
|
|
|
|
|
@property
|
|
|
|
def json_parameters(self) -> Dict[str, str]:
|
|
|
|
"""Gives the parameters as mapping of parameter name to the respective JSON encoded
|
|
|
|
value.
|
2022-06-01 21:26:18 +02:00
|
|
|
|
|
|
|
Tip:
|
|
|
|
By default, this property uses the standard library's :func:`json.dumps`.
|
|
|
|
To use a custom library for JSON encoding, you can directly encode the keys of
|
|
|
|
:attr:`parameters` - note that string valued keys should not be JSON encoded.
|
2024-08-02 13:41:39 +02:00
|
|
|
|
|
|
|
Returns:
|
|
|
|
Dict[:obj:`str`, :obj:`str`]
|
2022-04-24 12:38:09 +02:00
|
|
|
"""
|
|
|
|
return {
|
|
|
|
param.name: param.json_value
|
|
|
|
for param in self._parameters
|
|
|
|
if param.json_value is not None
|
|
|
|
}
|
|
|
|
|
2023-05-18 07:57:59 +02:00
|
|
|
def url_encoded_parameters(self, encode_kwargs: Optional[Dict[str, Any]] = None) -> str:
|
2022-04-24 12:38:09 +02:00
|
|
|
"""Encodes the parameters with :func:`urllib.parse.urlencode`.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
encode_kwargs (Dict[:obj:`str`, any], optional): Additional keyword arguments to pass
|
|
|
|
along to :func:`urllib.parse.urlencode`.
|
2024-08-02 13:41:39 +02:00
|
|
|
|
|
|
|
Returns:
|
|
|
|
:obj:`str`
|
2022-04-24 12:38:09 +02:00
|
|
|
"""
|
|
|
|
if encode_kwargs:
|
|
|
|
return urlencode(self.json_parameters, **encode_kwargs)
|
|
|
|
return urlencode(self.json_parameters)
|
|
|
|
|
2023-05-18 07:57:59 +02:00
|
|
|
def parametrized_url(self, url: str, encode_kwargs: Optional[Dict[str, Any]] = None) -> str:
|
2022-04-24 12:38:09 +02:00
|
|
|
"""Shortcut for attaching the return value of :meth:`url_encoded_parameters` to the
|
|
|
|
:paramref:`url`.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
url (:obj:`str`): The URL the parameters will be attached to.
|
|
|
|
encode_kwargs (Dict[:obj:`str`, any], optional): Additional keyword arguments to pass
|
|
|
|
along to :func:`urllib.parse.urlencode`.
|
2024-08-02 13:41:39 +02:00
|
|
|
|
|
|
|
Returns:
|
|
|
|
:obj:`str`
|
2022-04-24 12:38:09 +02:00
|
|
|
"""
|
|
|
|
url_parameters = self.url_encoded_parameters(encode_kwargs=encode_kwargs)
|
|
|
|
return f"{url}?{url_parameters}"
|
|
|
|
|
|
|
|
@property
|
|
|
|
def json_payload(self) -> bytes:
|
2022-06-01 21:26:18 +02:00
|
|
|
"""The :attr:`parameters` as UTF-8 encoded JSON payload.
|
|
|
|
|
|
|
|
Tip:
|
|
|
|
By default, this property uses the standard library's :func:`json.dumps`.
|
|
|
|
To use a custom library for JSON encoding, you can directly encode the keys of
|
|
|
|
:attr:`parameters` - note that string valued keys should not be JSON encoded.
|
2024-08-02 13:41:39 +02:00
|
|
|
|
|
|
|
Returns:
|
|
|
|
:obj:`bytes`
|
2022-06-01 21:26:18 +02:00
|
|
|
"""
|
2024-07-21 21:13:30 +02:00
|
|
|
return json.dumps(self.json_parameters).encode(TextEncoding.UTF_8)
|
2022-04-24 12:38:09 +02:00
|
|
|
|
|
|
|
@property
|
|
|
|
def multipart_data(self) -> UploadFileDict:
|
2024-08-02 22:28:38 +02:00
|
|
|
"""Gives the files contained in this object as mapping of part name to encoded content.
|
|
|
|
|
2024-09-01 15:25:34 +02:00
|
|
|
.. versionchanged:: 21.5
|
2024-08-02 22:28:38 +02:00
|
|
|
Content may now be a file handle.
|
|
|
|
"""
|
2022-04-24 12:38:09 +02:00
|
|
|
multipart_data: UploadFileDict = {}
|
|
|
|
for param in self._parameters:
|
|
|
|
m_data = param.multipart_data
|
|
|
|
if m_data:
|
|
|
|
multipart_data.update(m_data)
|
|
|
|
return multipart_data
|