Compare commits

..

No commits in common. "main" and "v2.3.8" have entirely different histories.
main ... v2.3.8

706 changed files with 4479 additions and 31536 deletions

3
.github/FUNDING.yml vendored
View file

@ -1,2 +1,3 @@
github: Mayuri-Chan github: Mayuri-Chan
custom: ["https://t.me/Mayuri17_bot?start=donate"] ko_fi: wulan17
custom: ["https://saweria.co/wulan17", "https://paypal.me/wulan17", "https://trakteer.id/wulan17"]

View file

@ -6,11 +6,11 @@ body:
label: Checklist label: Checklist
description: Invalid, incomplete or inadequate issue reports may not be taken into consideration description: Invalid, incomplete or inadequate issue reports may not be taken into consideration
options: options:
- label: I am sure the error is coming from Pyrofork's code and not elsewhere - label: I am sure the error is coming from Pyrogram's code and not elsewhere
required: true required: true
- label: I have searched in the issue tracker for similar bug reports, including closed ones - label: I have searched in the issue tracker for similar bug reports, including closed ones
required: true required: true
- label: I ran `pip3 install -U git+https://github.com/Mayuri-Chan/pyrofork` and reproduced the issue using the latest development version - label: I ran `pip3 install -U https://github.com/Mayuri-Chan/pyrofork/archive/master.zip` and reproduced the issue using the latest development version
required: true required: true
- type: textarea - type: textarea

View file

@ -1,8 +1,8 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: Ask Pyrofork related questions - name: Ask Pyrogram related questions
url: https://stackoverflow.com/questions/tagged/pyrofork url: https://stackoverflow.com/questions/tagged/pyrogram
about: This place is only for reporting issues about Pyrofork. You can ask questions at StackOverflow. about: This place is only for reporting issues about Pyrogram. You can ask questions at StackOverflow.
- name: Join the Telegram Chat - name: Join the Telegram channel
url: https://t.me/MayuriChan_Chat url: https://t.me/pyrogram
about: Join the official Chat and stay tuned for news, updates and announcements. about: Join the official channel and stay tuned for news, updates and announcements.

View file

@ -3,10 +3,7 @@ name: Build-docs
on: on:
push: push:
tags: tags:
- "*" - '*'
branches:
- staging
- dev/*
jobs: jobs:
build: build:
@ -14,25 +11,8 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Checkout repository - uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Configure
run: bash build-docs.sh configure
- name: Cleanup
run: bash build-docs.sh cleanup
- name: Create virtual environment
run: bash build-docs.sh virtualenv
- name: Build - name: Build
run: bash build-docs.sh build run: bash build-docs.sh
- name: Clone gh-pages repository
run: bash build-docs.sh clone
env: env:
DOCS_KEY: ${{ secrets.DOCS_KEY }} DOCS_KEY: ${{ secrets.DOCS_KEY }}
- name: Push changes
run: bash build-docs.sh push

View file

@ -20,21 +20,22 @@ jobs:
deploy: deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: release
permissions:
id-token: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5 uses: actions/setup-python@v3
with: with:
python-version: '3.10' python-version: '3.10'
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install -e '.[dev]' pip install build twine
- name: Build package - name: Build package
run: hatch build run: python -m build
- name: Publish package - name: Publish package
uses: pypa/gh-action-pypi-publish@release/v1 env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
twine upload dist/*

View file

@ -1,4 +1,4 @@
name: Pyrofork name: Pyrogram
on: [push, pull_request] on: [push, pull_request]
@ -9,13 +9,13 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest] os: [ubuntu-latest, macos-latest]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5 uses: actions/setup-python@v2
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
@ -31,4 +31,4 @@ jobs:
- name: Run tests - name: Run tests
run: | run: |
tox tox

651
.pylintrc
View file

@ -1,651 +0,0 @@
[MAIN]
# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no
# Clear in-memory caches upon conclusion of linting. Useful if running pylint
# in a server-like mode.
clear-cache-post-run=no
# Load and enable all available extensions. Use --list-extensions to see a list
# all available extensions.
#enable-all-extensions=
# In error mode, messages with a category besides ERROR or FATAL are
# suppressed, and no reports are done by default. Error mode is compatible with
# disabling specific errors.
#errors-only=
# Always return a 0 (non-error) status code, even if lint errors are found.
# This is primarily useful in continuous integration scripts.
#exit-zero=
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code.
extension-pkg-allow-list=
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code. (This is an alternative name to extension-pkg-allow-list
# for backward compatibility.)
extension-pkg-whitelist=
# Return non-zero exit code if any of these messages/categories are detected,
# even if score is above --fail-under value. Syntax same as enable. Messages
# specified are enabled, while categories only check already-enabled messages.
fail-on=
# Specify a score threshold under which the program will exit with error.
fail-under=10
# Interpret the stdin as a python script, whose filename needs to be passed as
# the module_or_package argument.
#from-stdin=
# Files or directories to be skipped. They should be base names, not paths.
ignore=CVS
# Add files or directories matching the regular expressions patterns to the
# ignore-list. The regex matches against paths and can be in Posix or Windows
# format. Because '\\' represents the directory delimiter on Windows systems,
# it can't be used as an escape character.
ignore-paths=
# Files or directories matching the regular expression patterns are skipped.
# The regex matches against base names, not paths. The default value ignores
# Emacs file locks
ignore-patterns=^\.#
# List of module names for which member attributes should not be checked and
# will not be imported (useful for modules/projects where namespaces are
# manipulated during runtime and thus existing member attributes cannot be
# deduced by static analysis). It supports qualified module names, as well as
# Unix pattern matching.
ignored-modules=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
# number of processors available to use, and will cap the count on Windows to
# avoid hangs.
jobs=1
# Control the amount of potential inferred values when inferring a single
# object. This can help the performance when dealing with large functions or
# complex, nested conditions.
limit-inference-results=100
# List of plugins (as comma separated values of python module names) to load,
# usually to register additional checkers.
load-plugins=
# Pickle collected data for later comparisons.
persistent=yes
# Resolve imports to .pyi stubs if available. May reduce no-member messages and
# increase not-an-iterable messages.
prefer-stubs=no
# Minimum Python version to use for version dependent checks. Will default to
# the version used to run pylint.
py-version=3.13
# Discover python modules and packages in the file system subtree.
recursive=no
# Add paths to the list of the source roots. Supports globbing patterns. The
# source root is an absolute path or a path relative to the current working
# directory used to determine a package namespace for modules located under the
# source root.
source-roots=
# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages.
suggestion-mode=yes
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
# In verbose mode, extra non-checker-related info will be displayed.
#verbose=
[BASIC]
# Naming style matching correct argument names.
argument-naming-style=snake_case
# Regular expression matching correct argument names. Overrides argument-
# naming-style. If left empty, argument names will be checked with the set
# naming style.
#argument-rgx=
# Naming style matching correct attribute names.
attr-naming-style=snake_case
# Regular expression matching correct attribute names. Overrides attr-naming-
# style. If left empty, attribute names will be checked with the set naming
# style.
#attr-rgx=
# Bad variable names which should always be refused, separated by a comma.
bad-names=foo,
bar,
baz,
toto,
tutu,
tata
# Bad variable names regexes, separated by a comma. If names match any regex,
# they will always be refused
bad-names-rgxs=
# Naming style matching correct class attribute names.
class-attribute-naming-style=any
# Regular expression matching correct class attribute names. Overrides class-
# attribute-naming-style. If left empty, class attribute names will be checked
# with the set naming style.
#class-attribute-rgx=
# Naming style matching correct class constant names.
class-const-naming-style=UPPER_CASE
# Regular expression matching correct class constant names. Overrides class-
# const-naming-style. If left empty, class constant names will be checked with
# the set naming style.
#class-const-rgx=
# Naming style matching correct class names.
class-naming-style=PascalCase
# Regular expression matching correct class names. Overrides class-naming-
# style. If left empty, class names will be checked with the set naming style.
#class-rgx=
# Naming style matching correct constant names.
const-naming-style=UPPER_CASE
# Regular expression matching correct constant names. Overrides const-naming-
# style. If left empty, constant names will be checked with the set naming
# style.
#const-rgx=
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
# Naming style matching correct function names.
function-naming-style=snake_case
# Regular expression matching correct function names. Overrides function-
# naming-style. If left empty, function names will be checked with the set
# naming style.
#function-rgx=
# Good variable names which should always be accepted, separated by a comma.
good-names=i,
j,
k,
ex,
Run,
_
# Good variable names regexes, separated by a comma. If names match any regex,
# they will always be accepted
good-names-rgxs=
# Include a hint for the correct naming format with invalid-name.
include-naming-hint=no
# Naming style matching correct inline iteration names.
inlinevar-naming-style=any
# Regular expression matching correct inline iteration names. Overrides
# inlinevar-naming-style. If left empty, inline iteration names will be checked
# with the set naming style.
#inlinevar-rgx=
# Naming style matching correct method names.
method-naming-style=snake_case
# Regular expression matching correct method names. Overrides method-naming-
# style. If left empty, method names will be checked with the set naming style.
#method-rgx=
# Naming style matching correct module names.
module-naming-style=snake_case
# Regular expression matching correct module names. Overrides module-naming-
# style. If left empty, module names will be checked with the set naming style.
#module-rgx=
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_
# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties.
# These decorators are taken in consideration only for invalid-name.
property-classes=abc.abstractproperty
# Regular expression matching correct type alias names. If left empty, type
# alias names will be checked with the set naming style.
#typealias-rgx=
# Regular expression matching correct type variable names. If left empty, type
# variable names will be checked with the set naming style.
#typevar-rgx=
# Naming style matching correct variable names.
variable-naming-style=snake_case
# Regular expression matching correct variable names. Overrides variable-
# naming-style. If left empty, variable names will be checked with the set
# naming style.
#variable-rgx=
[CLASSES]
# Warn about protected attribute access inside special methods
check-protected-access-in-special-methods=no
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,
__new__,
setUp,
asyncSetUp,
__post_init__
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
[DESIGN]
# List of regular expressions of class ancestor names to ignore when counting
# public methods (see R0903)
exclude-too-few-public-methods=
# List of qualified class names to ignore when counting class parents (see
# R0901)
ignored-parents=
# Maximum number of arguments for function / method.
max-args=5
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Maximum number of boolean expressions in an if statement (see R0916).
max-bool-expr=5
# Maximum number of branch for function / method body.
max-branches=12
# Maximum number of locals for function / method body.
max-locals=15
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of positional arguments for function / method.
max-positional-arguments=5
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of return / yield for function / method body.
max-returns=6
# Maximum number of statements in function / method body.
max-statements=50
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
[EXCEPTIONS]
# Exceptions that will emit a warning when caught.
overgeneral-exceptions=builtins.BaseException,builtins.Exception
[FORMAT]
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Maximum number of characters on a single line.
max-line-length=100
# Maximum number of lines in a module.
max-module-lines=1000
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
[IMPORTS]
# List of modules that can be imported at any level, not just the top level
# one.
allow-any-import-level=
# Allow explicit reexports by alias from a package __init__.
allow-reexport-from-package=no
# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no
# Deprecated modules which should not be used, separated by a comma.
deprecated-modules=
# Output a graph (.gv or any supported image format) of external dependencies
# to the given file (report RP0402 must not be disabled).
ext-import-graph=
# Output a graph (.gv or any supported image format) of all (i.e. internal and
# external) dependencies to the given file (report RP0402 must not be
# disabled).
import-graph=
# Output a graph (.gv or any supported image format) of internal dependencies
# to the given file (report RP0402 must not be disabled).
int-import-graph=
# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=
# Force import order to recognize a module as part of a third party library.
known-third-party=enchant
# Couples of modules and preferred modules, separated by a comma.
preferred-modules=
[LOGGING]
# The type of string formatting that logging methods do. `old` means using %
# formatting, `new` is for `{}` formatting.
logging-format-style=old
# Logging modules to check that the string format arguments are in logging
# function parameter format.
logging-modules=logging
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
# UNDEFINED.
confidence=HIGH,
CONTROL_FLOW,
INFERENCE,
INFERENCE_FAILURE,
UNDEFINED
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once). You can also use "--disable=all" to
# disable everything first and then re-enable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable=raw-checker-failed,
bad-inline-option,
locally-disabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
use-implicit-booleaness-not-comparison-to-string,
use-implicit-booleaness-not-comparison-to-zero,
use-symbolic-message-instead,
missing-module-docstring,
missing-class-docstring,
missing-function-docstring,
redefined-builtin
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=
[METHOD_ARGS]
# List of qualified names (i.e., library.method) which require a timeout
# parameter e.g. 'requests.api.get,requests.api.post'
timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,
XXX,
TODO
# Regular expression of note tags to take in consideration.
notes-rgx=
[REFACTORING]
# Maximum number of nested blocks for function / method body
max-nested-blocks=5
# Complete name of functions that never returns. When checking for
# inconsistent-return-statements if a never returning function is called then
# it will be considered as an explicit return statement and no message will be
# printed.
never-returning-functions=sys.exit,argparse.parse_error
# Let 'consider-using-join' be raised when the separator to join on would be
# non-empty (resulting in expected fixes of the type: ``"- " + " -
# ".join(items)``)
suggest-join-with-non-empty-separator=yes
[REPORTS]
# Python expression which should return a score less than or equal to 10. You
# have access to the variables 'fatal', 'error', 'warning', 'refactor',
# 'convention', and 'info' which contain the number of messages in each
# category, as well as 'statement' which is the total number of statements
# analyzed. This score is used by the global evaluation report (RP0004).
evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details.
msg-template=
# Set the output format. Available formats are: 'text', 'parseable',
# 'colorized', 'json2' (improved json format), 'json' (old json format), msvs
# (visual studio) and 'github' (GitHub actions). You can also give a reporter
# class, e.g. mypackage.mymodule.MyReporterClass.
#output-format=
# Tells whether to display a full report or only the messages.
reports=no
# Activate the evaluation score.
score=yes
[SIMILARITIES]
# Comments are removed from the similarity computation
ignore-comments=yes
# Docstrings are removed from the similarity computation
ignore-docstrings=yes
# Imports are removed from the similarity computation
ignore-imports=yes
# Signatures are removed from the similarity computation
ignore-signatures=yes
# Minimum lines number of a similarity.
min-similarity-lines=4
[SPELLING]
# Limits count of emitted suggestions for spelling mistakes.
max-spelling-suggestions=4
# Spelling dictionary name. No available dictionaries : You need to install
# both the python package and the system dependency for enchant to work.
spelling-dict=
# List of comma separated words that should be considered directives if they
# appear at the beginning of a comment and should not be checked.
spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains the private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to the private dictionary (see the
# --spelling-private-dict-file option) instead of raising a message.
spelling-store-unknown-words=no
[STRING]
# This flag controls whether inconsistent-quotes generates a warning when the
# character used as a quote delimiter is used inconsistently within a module.
check-quote-consistency=no
# This flag controls whether the implicit-str-concat should generate a warning
# on implicit string concatenation in sequences defined over several lines.
check-str-concat-over-line-jumps=no
[TYPECHECK]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
# Tells whether to warn about missing members when the owner of the attribute
# is inferred to be None.
ignore-none=yes
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes
# List of symbolic message names to ignore for Mixin members.
ignored-checks-for-mixins=no-member,
not-async-context-manager,
not-context-manager,
attribute-defined-outside-init
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace
# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes
# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1
# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1
# Regex pattern to define which classes are considered mixins.
mixin-class-rgx=.*[Mm]ixin
# List of decorators that change the signature of a decorated function.
signature-mutators=
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid defining new builtins when possible.
additional-builtins=
# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes
# List of names allowed to shadow builtins
allowed-redefined-builtins=
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,
_cb
# A regular expression matching the name of dummy variables (i.e. expected to
# not be used).
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
# Argument names that match this expression will be ignored.
ignored-argument-names=_.*|^ignored_|^unused_
# Tells whether we should check for unused import in __init__ files.
init-import=no
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io

View file

@ -1,5 +1,5 @@
## Include ## Include
include README.md COPYING COPYING.lesser NOTICE include README.md COPYING COPYING.lesser NOTICE requirements.txt
recursive-include compiler *.py *.tl *.tsv *.txt recursive-include compiler *.py *.tl *.tsv *.txt
recursive-include tests *.py recursive-include tests *.py

View file

@ -11,7 +11,7 @@ venv:
$(RM) $(VENV) $(RM) $(VENV)
python3 -m venv $(VENV) python3 -m venv $(VENV)
$(PYTHON) -m pip install -U pip wheel setuptools $(PYTHON) -m pip install -U pip wheel setuptools
$(PYTHON) -m pip install -U -e . $(PYTHON) -m pip install -U -r requirements.txt -r dev-requirements.txt
@echo "Created venv with $$($(PYTHON) --version)" @echo "Created venv with $$($(PYTHON) --version)"
clean-docs: clean-docs:

View file

@ -5,25 +5,9 @@
<br> <br>
<b>Telegram MTProto API Framework for Python</b> <b>Telegram MTProto API Framework for Python</b>
<br> <br>
<a href="https://github.com/Mayuri-Chan"> <a href="https://pyrofork.mayuri.my.id">
Homepage
</a>
<a href="https://pyrofork.wulan17.dev">
Documentation Documentation
</a> </a>
<a href="https://github.com/Mayuri-Chan/pyrofork/issues">
Issues
</a>
<a href="https://t.me/MayuriChan_Chat">
Support Chat
</a>
<a href="https://t.me/Pyrofork_CH">
News/Releases
</a>
</p> </p>
## Pyrofork ## Pyrofork
@ -44,7 +28,7 @@ async def hello(client, message):
app.run() app.run()
``` ```
**Pyrofork** is a modern, elegant and asynchronous [MTProto API](https://pyrofork.wulan17.dev/main/topics/mtproto-vs-botapi) **Pyrofork** is a modern, elegant and asynchronous [MTProto API](https://pyrofork.mayuri.my.id/topics/mtproto-vs-botapi)
framework. It enables you to easily interact with the main Telegram API through a user account (custom client) or a bot framework. It enables you to easily interact with the main Telegram API through a user account (custom client) or a bot
identity (bot API alternative) using Python. identity (bot API alternative) using Python.
@ -72,6 +56,6 @@ pip3 install pyrofork
### Resources ### Resources
- Check out the docs at https://pyrofork.wulan17.dev to learn more about Pyrofork, get started right - Check out the docs at https://pyrofork.mayuri.my.id to learn more about Pyrofork, get started right
away and discover more in-depth material for building your client applications. away and discover more in-depth material for building your client applications.
- Join the official group at https://t.me/MayuriChan_Chat and stay tuned for news, updates and announcements. - Join the official group at https://t.me/MayuriChan_Chat and stay tuned for news, updates and announcements.

View file

@ -1,87 +1,20 @@
#!/bin/bash #!/bin/bash
export DOCS_KEY
export VENV=$(pwd)/venv
# Check if config.sh exists make clean
if [ -f config.sh ]; then make clean-docs
source config.sh make venv
fi make api
"$VENV"/bin/pip install -r docs/requirements.txt
function parse_parameters() { cd compiler/docs && "$VENV"/bin/python compiler.py
while (($#)); do cd ../..
case $1 in "$VENV"/bin/sphinx-build -b html "docs/source" "docs/build/html" -j auto
all | configure | cleanup | virtualenv | build | clone | push ) action=$1 ;; git clone https://wulan17:"$DOCS_KEY"@github.com/Mayuri-Chan/pyrofork-docs.git
*) exit 33 ;; cp -r docs/build/html/* pyrofork-docs
esac cd pyrofork-docs
shift git config --local user.name "Mayuri-Chan"
done git config --local user.email "mayuri@mayuri.my.id"
} git add --all
git commit -a -m "docs: Update docs $(date '+%Y-%m-%d | %H:%m:%S %p %Z')" --signoff
function do_configure() { git push -u origin --all
echo "#!/bin/bash" > config.sh
echo "export VENV=\"$(pwd)/venv\"" >> config.sh
if [[ "$(echo "$GITHUB_REF" | cut -d '/' -f "1 2")" == "refs/tags" ]]; then
echo "export BRANCH=\"main\"" >> config.sh
elif [[ "$GITHUB_REF" == "refs/heads/staging" ]]; then
echo "export BRANCH=\"staging\"" >> config.sh
else
b="$(echo "$GITHUB_REF" | cut -d '/' -f '3 4')"
if [[ $(echo "$b" | cut -d '/' -f 1 ) == "dev" ]]; then
b="$(echo "$b" | cut -d '/' -f 2)"
if [[ "$b" =~ ^[0-9]\.[0-9]\.x ]]; then
echo "export BRANCH=\"$b\"" >> config.sh
else
exit 0
fi
else
exit 0
fi
fi
chmod +x config.sh
}
function do_cleanup() {
make clean
make clean-docs
}
function do_virtualenv() {
make venv
make api
"$VENV"/bin/pip install -e '.[docs]'
}
function do_build() {
cd compiler/docs || exit 1 && "$VENV"/bin/python compiler.py
cd ../.. || exit 1
"$VENV"/bin/sphinx-build -b html "docs/source" "docs/build/html" -j auto
}
function do_clone() {
git clone https://wulan17:"$DOCS_KEY"@github.com/Mayuri-Chan/pyrofork-docs.git
}
function do_push() {
cd pyrofork-docs || exit 1
mkdir -p "$BRANCH"
cd "$BRANCH" || exit 1
rm -rf _includes api genindex.html intro py-modindex.html sitemap.xml support.html topics _static faq index.html objects.inv searchindex.js start telegram
cp -r ../../docs/build/html/* .
git config --local user.name "Mayuri-Chan"
git config --local user.email "mayuri@mayuri.my.id"
git add --all
git commit -a -m "docs: $BRANCH: Update docs $(date '+%Y-%m-%d | %H:%m:%S %p %Z')" --signoff
git push -u origin --all
}
function do_all() {
do_configure
source config.sh
do_cleanup
do_virtualenv
do_build
do_clone
do_push
}
parse_parameters "$@"
do_"${action:=all}"

View file

@ -130,7 +130,7 @@ def get_type_hint(type: str) -> str:
return f"Optional[{type}] = None" if is_flag else type return f"Optional[{type}] = None" if is_flag else type
else: else:
ns, name = type.split(".") if "." in type else ("", type) ns, name = type.split(".") if "." in type else ("", type)
type = '"raw.base.' + ".".join([ns, name]).strip(".") + '"' type = f'"raw.base.' + ".".join([ns, name]).strip(".") + '"'
return f'{type}{" = None" if is_flag else ""}' return f'{type}{" = None" if is_flag else ""}'
@ -259,14 +259,11 @@ def start(format: bool = False):
args = ARGS_RE.findall(line) args = ARGS_RE.findall(line)
# Fix arg name being reserved python keyword # Fix arg name being "self" (reserved python keyword)
for i, item in enumerate(args): for i, item in enumerate(args):
if item[0] == "self": if item[0] == "self":
args[i] = ("is_self", item[1]) args[i] = ("is_self", item[1])
if item[0] == "from":
args[i] = ("from_peer", item[1])
combinator = Combinator( combinator = Combinator(
section=section, section=section,
qualname=qualname, qualname=qualname,
@ -430,11 +427,11 @@ def start(format: bool = False):
if function_docs: if function_docs:
docstring += function_docs["desc"] + "\n" docstring += function_docs["desc"] + "\n"
else: else:
docstring += "Telegram API function." docstring += f"Telegram API function."
docstring += f"\n\n Details:\n - Layer: ``{layer}``\n - ID: ``{c.id[2:].upper()}``\n\n" docstring += f"\n\n Details:\n - Layer: ``{layer}``\n - ID: ``{c.id[2:].upper()}``\n\n"
docstring += " Parameters:\n " + \ docstring += f" Parameters:\n " + \
("\n ".join(docstring_args) if docstring_args else "No parameters required.\n") (f"\n ".join(docstring_args) if docstring_args else "No parameters required.\n")
if c.section == "functions": if c.section == "functions":
docstring += "\n Returns:\n " + get_docstring_arg_type(c.qualtype) docstring += "\n Returns:\n " + get_docstring_arg_type(c.qualtype)
@ -442,12 +439,12 @@ def start(format: bool = False):
references, count = get_references(c.qualname, "constructors") references, count = get_references(c.qualname, "constructors")
if references: if references:
docstring += "\n Functions:\n This object can be returned by " \ docstring += f"\n Functions:\n This object can be returned by " \
f"{count} function{'s' if count > 1 else ''}.\n\n" \ f"{count} function{'s' if count > 1 else ''}.\n\n" \
" .. currentmodule:: pyrogram.raw.functions\n\n" \ f" .. currentmodule:: pyrogram.raw.functions\n\n" \
" .. autosummary::\n" \ f" .. autosummary::\n" \
" :nosignatures:\n\n" \ f" :nosignatures:\n\n" \
" " + references f" " + references
write_types = read_types = "" if c.has_flags else "# No flags\n " write_types = read_types = "" if c.has_flags else "# No flags\n "

File diff suppressed because it is too large Load diff

View file

@ -20,4 +20,4 @@ class {name}: # type: ignore
raise TypeError("Base types can only be used for type checking purposes: " raise TypeError("Base types can only be used for type checking purposes: "
"you tried to use a base type instance as argument, " "you tried to use a base type instance as argument, "
"but you need to instantiate one of its constructors instead. " "but you need to instantiate one of its constructors instead. "
"More info: https://pyrofork.wulan17.dev/telegram/base/{doc_name}") "More info: https://pyrofork.mayuri.my.id/telegram/base/{doc_name}")

View file

@ -146,28 +146,10 @@ def pyrogram_api():
stop_transmission stop_transmission
export_session_string export_session_string
set_parse_mode set_parse_mode
ping
""",
conversation="""
Conversation
ask
listen
get_listener_matching_with_data
get_listener_matching_with_identifier_pattern
get_many_listeners_matching_with_data
get_many_listeners_matching_with_identifier_pattern
register_next_step_handler
remove_listener
stop_listener
stop_listening
wait_for_callback_query
wait_for_message
""", """,
messages=""" messages="""
Messages Messages
add_task_to_todo
send_message send_message
forward_media_group
forward_messages forward_messages
copy_message copy_message
copy_media_group copy_media_group
@ -175,19 +157,16 @@ def pyrogram_api():
send_audio send_audio
send_document send_document
send_sticker send_sticker
send_todo
send_video send_video
send_animation send_animation
send_voice send_voice
send_video_note send_video_note
send_web_page
send_media_group send_media_group
send_location send_location
send_venue send_venue
send_contact send_contact
send_cached_media send_cached_media
send_reaction send_reaction
set_todo_tasks_completion
edit_message_text edit_message_text
edit_message_caption edit_message_caption
edit_message_media edit_message_media
@ -198,11 +177,7 @@ def pyrogram_api():
edit_inline_reply_markup edit_inline_reply_markup
send_chat_action send_chat_action
delete_messages delete_messages
delete_scheduled_messages
get_available_effects
get_messages get_messages
get_message_read_participants
get_scheduled_messages
get_media_group get_media_group
get_chat_history get_chat_history
get_chat_history_count get_chat_history_count
@ -216,18 +191,12 @@ def pyrogram_api():
search_messages_count search_messages_count
search_global search_global
search_global_count search_global_count
search_global_hashtag_messages
search_global_hashtag_messages_count
download_media download_media
stream_media stream_media
get_discussion_message get_discussion_message
get_discussion_replies get_discussion_replies
get_discussion_replies_count get_discussion_replies_count
get_custom_emoji_stickers get_custom_emoji_stickers
transcribe_audio
translate_message_text
start_bot
delete_chat_history
""", """,
chats=""" chats="""
Chats Chats
@ -240,9 +209,6 @@ def pyrogram_api():
set_administrator_title set_administrator_title
set_chat_photo set_chat_photo
delete_chat_photo delete_chat_photo
delete_folder
export_folder_link
update_folder
set_chat_title set_chat_title
set_chat_description set_chat_description
set_chat_permissions set_chat_permissions
@ -255,11 +221,10 @@ def pyrogram_api():
get_chat_members_count get_chat_members_count
get_dialogs get_dialogs
get_dialogs_count get_dialogs_count
get_folders
get_forum_topics get_forum_topics
get_forum_topics_by_id get_forum_topics_by_id
get_forum_topics_count
set_chat_username set_chat_username
get_nearby_chats
archive_chats archive_chats
unarchive_chats unarchive_chats
add_chat_members add_chat_members
@ -285,10 +250,7 @@ def pyrogram_api():
hide_general_topic hide_general_topic
reopen_forum_topic reopen_forum_topic
reopen_general_topic reopen_general_topic
transfer_chat_ownership
unhide_general_topic unhide_general_topic
update_color
update_folder
""", """,
users=""" users="""
Users Users
@ -299,8 +261,6 @@ def pyrogram_api():
set_profile_photo set_profile_photo
delete_profile_photos delete_profile_photos
set_username set_username
update_birthday
update_personal_chat
update_profile update_profile
block_user block_user
unblock_user unblock_user
@ -313,7 +273,6 @@ def pyrogram_api():
delete_stories delete_stories
edit_story edit_story
export_story_link export_story_link
forward_story
get_all_stories get_all_stories
get_stories get_stories
get_stories_history get_stories_history
@ -354,39 +313,6 @@ def pyrogram_api():
get_contacts get_contacts
get_contacts_count get_contacts_count
""", """,
payments="""
Payments
apply_gift_code
check_gift_code
convert_gift
create_invoice_link
get_payment_form
get_stars_transactions
get_stars_transactions_by_id
get_available_gifts
get_upgraded_gift
get_chat_gifts_count
get_chat_gifts
hide_gift
refund_star_payment
search_gifts_for_resale
send_invoice
send_paid_media
send_paid_reaction
send_payment_form
send_gift
send_resold_gift
set_gift_resale_price
set_pinned_gifts
show_gift
transfer_gift
upgrade_gift
get_stars_balance
""",
phone="""
Phone
get_call_members
""",
password=""" password="""
Password Password
enable_cloud_password enable_cloud_password
@ -413,19 +339,6 @@ def pyrogram_api():
answer_web_app_query answer_web_app_query
get_bot_info get_bot_info
set_bot_info set_bot_info
get_collectible_item_info
get_owned_bots
get_similar_bots
""",
business="""
Telegram Business
answer_pre_checkout_query
answer_shipping_query
delete_business_messages
get_business_connection
get_business_account_gifts
get_business_account_star_balance
transfer_business_account_stars
""", """,
authorization=""" authorization="""
Authorization Authorization
@ -437,13 +350,13 @@ def pyrogram_api():
resend_code resend_code
sign_in sign_in
sign_in_bot sign_in_bot
sign_in_qrcode sign_up
get_password_hint get_password_hint
check_password check_password
send_recovery_code send_recovery_code
recover_password recover_password
accept_terms_of_service
log_out log_out
get_active_sessions
""", """,
advanced=""" advanced="""
Advanced Advanced
@ -465,7 +378,7 @@ def pyrogram_api():
fmt_keys = {} fmt_keys = {}
for k, v in categories.items(): for k, v in categories.items():
_, *methods = get_title_list(v) name, *methods = get_title_list(v)
fmt_keys.update({k: "\n ".join("{0} <{0}>".format(m) for m in methods)}) fmt_keys.update({k: "\n ".join("{0} <{0}>".format(m) for m in methods)})
for method in methods: for method in methods:
@ -491,15 +404,7 @@ def pyrogram_api():
categories = dict( categories = dict(
users_chats=""" users_chats="""
Users & Chats Users & Chats
Birthday
BusinessInfo
BusinessMessage
BusinessRecipients
BusinessSchedule
BusinessWeeklyOpen
BusinessWorkingHours
User User
Username
Chat Chat
ChatPreview ChatPreview
ChatPhoto ChatPhoto
@ -515,41 +420,21 @@ def pyrogram_api():
ChatJoinedByRequest ChatJoinedByRequest
ChatJoiner ChatJoiner
Dialog Dialog
Folder
Restriction Restriction
EmojiStatus EmojiStatus
ExportedFolderLink
ForumTopic ForumTopic
PeerUser PeerUser
PeerChannel PeerChannel
BotInfo BotInfo
GroupCallMember
ChatColor
CollectibleItemInfo
BotVerification
""", """,
messages_media=""" messages_media="""
Messages & Media Messages & Media
Message Message
MessageEntity MessageEntity
MessageOriginChannel
MessageOriginChat
MessageOriginHiddenUser
MessageOriginImport
MessageOriginUser
MessageOrigin
Photo Photo
Thumbnail Thumbnail
TodoList
TodoTask
TodoTasksAdded
TodoTasksCompleted
TodoTasksIncompleted
Audio Audio
AvailableEffect
Document Document
ExternalReplyInfo
AlternativeVideo
Animation Animation
Video Video
Voice Voice
@ -560,18 +445,8 @@ def pyrogram_api():
Sticker Sticker
StickerSet StickerSet
Game Game
Gift
GiftAttribute
Giveaway
GiveawayLaunched
GiveawayResult
MessageStory MessageStory
WebPage WebPage
WebPageEmpty
WebPagePreview
TranscribedAudio
TranslatedText
TextQuote
Poll Poll
PollOption PollOption
Dice Dice
@ -582,70 +457,21 @@ def pyrogram_api():
VideoChatMembersInvited VideoChatMembersInvited
WebAppData WebAppData
MessageReactions MessageReactions
MessageReactor
ChatReactions ChatReactions
ForumTopicCreated ForumTopicCreated
ForumTopicEdited ForumTopicEdited
ForumTopicClosed ForumTopicClosed
ForumTopicDeleted
ForumTopicReopened ForumTopicReopened
GeneralTopicHidden GeneralTopicHidden
GeneralTopicUnhidden GeneralTopicUnhidden
Reaction
MessageReactionUpdated
MessageReactionCountUpdated
ExportedStoryLink
ChatTheme
ChatWallpaper
ContactRegistered
ReadParticipant
ScreenshotTaken
Wallpaper
WallpaperSettings
""", """,
stories=""" stories="""
Stories Stories
Story Story
StoryDeleted StoryDeleted
StoryForwardHeader
StorySkipped StorySkipped
StoriesPrivacyRules StoriesPrivacyRules
StoryViews StoryViews
MediaArea
MediaAreaChannelPost
MediaAreaCoordinates
InputMediaArea
InputMediaAreaChannelPost
""",
payment="""
Payment
CheckedGiftCode
ExtendedMediaPreview
GiftCode
GiftedPremium
InputStarsTransaction
Invoice
LabeledPrice
PaidMedia
PaidMessagePriceChanged
PaymentForm
PaymentInfo
PaymentRefunded
PurchasedPaidMedia
StarsStatus
StarsTransaction
SuccessfulPayment
""",
pyromod="""
Pyromod
Identifier
Listener
""",
bot="""
Bot
BotAllowed
BotApp
BotBusinessConnection
""", """,
bot_keyboards=""" bot_keyboards="""
Bot keyboards Bot keyboards
@ -654,13 +480,9 @@ def pyrogram_api():
ReplyKeyboardRemove ReplyKeyboardRemove
InlineKeyboardMarkup InlineKeyboardMarkup
InlineKeyboardButton InlineKeyboardButton
InlineKeyboardButtonBuy
RequestPeerTypeChannel RequestPeerTypeChannel
RequestPeerTypeChat RequestPeerTypeChat
RequestPeerTypeUser RequestPeerTypeUser
RequestedChats
RequestedChat
RequestedUser
LoginUrl LoginUrl
ForceReply ForceReply
CallbackQuery CallbackQuery
@ -685,13 +507,6 @@ def pyrogram_api():
BotCommandScopeChatAdministrators BotCommandScopeChatAdministrators
BotCommandScopeChatMember BotCommandScopeChatMember
""", """,
business="""
Telegram Business
PreCheckoutQuery
ShippingAddress
ShippingOption
ShippingQuery
""",
input_media=""" input_media="""
Input Media Input Media
InputMedia InputMedia
@ -725,32 +540,15 @@ def pyrogram_api():
InlineQueryResultVoice InlineQueryResultVoice
ChosenInlineResult ChosenInlineResult
""", """,
pre_checkout_query="""
PreCheckoutQuery
PreCheckoutQuery.answer
""",
shipping_query="""
ShippingQuery
ShippingQuery.answer
""",
input_message_content=""" input_message_content="""
InputMessageContent InputMessageContent
InputMessageContent InputMessageContent
InputReplyToMessage InputReplyToMessage
InputReplyToMonoforum
InputReplyToStory InputReplyToStory
InputTextMessageContent InputTextMessageContent
InputLocationMessageContent
InputVenueMessageContent
InputContactMessageContent
InputInvoiceMessageContent
InputTodoTask
""", """,
authorization=""" authorization="""
Authorization Authorization
ActiveSession
ActiveSessions
LoginToken
SentCode SentCode
TermsOfService TermsOfService
""" """
@ -768,7 +566,7 @@ def pyrogram_api():
fmt_keys = {} fmt_keys = {}
for k, v in categories.items(): for k, v in categories.items():
_, *types = get_title_list(v) name, *types = get_title_list(v)
fmt_keys.update({k: "\n ".join(types)}) fmt_keys.update({k: "\n ".join(types)})
@ -787,7 +585,6 @@ def pyrogram_api():
categories = dict( categories = dict(
message=""" message="""
Message Message
Message.ask
Message.click Message.click
Message.delete Message.delete
Message.download Message.download
@ -819,18 +616,11 @@ def pyrogram_api():
Message.reply_video Message.reply_video
Message.reply_video_note Message.reply_video_note
Message.reply_voice Message.reply_voice
Message.reply_web_page
Message.get_media_group Message.get_media_group
Message.react Message.react
Message.transcribe
Message.translate
Message.wait_for_click
""", """,
chat=""" chat="""
Chat Chat
Chat.ask
Chat.listen
Chat.stop_listening
Chat.archive Chat.archive
Chat.unarchive Chat.unarchive
Chat.set_title Chat.set_title
@ -851,9 +641,6 @@ def pyrogram_api():
""", """,
user=""" user="""
User User
User.ask
User.listen
User.stop_listening
User.archive User.archive
User.unarchive User.unarchive
User.block User.block
@ -862,7 +649,6 @@ def pyrogram_api():
story=""" story="""
Story Story
Story.delete Story.delete
Story.download
Story.edit Story.edit
Story.edit_animation Story.edit_animation
Story.edit_caption Story.edit_caption
@ -870,7 +656,6 @@ def pyrogram_api():
Story.edit_privacy Story.edit_privacy
Story.edit_video Story.edit_video
Story.export_link Story.export_link
Story.forward
Story.reply_text Story.reply_text
Story.reply_animation Story.reply_animation
Story.reply_audio Story.reply_audio
@ -882,26 +667,6 @@ def pyrogram_api():
Story.reply_video_note Story.reply_video_note
Story.reply_voice Story.reply_voice
""", """,
folder="""
Folder
Folder.delete
Folder.update
Folder.include_chat
Folder.exclude_chat
Folder.update_color
Folder.pin_chat
Folder.remove_chat
Folder.export_link
""",
gift="""
Gift
Gift.show
Gift.hide
Gift.convert
Gift.upgrade
Gift.transfer
Gift.wear
""",
callback_query=""" callback_query="""
Callback Query Callback Query
CallbackQuery.answer CallbackQuery.answer
@ -914,14 +679,6 @@ def pyrogram_api():
InlineQuery InlineQuery
InlineQuery.answer InlineQuery.answer
""", """,
pre_checkout_query="""
PreCheckoutQuery
PreCheckoutQuery.answer
""",
shipping_query="""
ShippingQuery
ShippingQuery.answer
""",
chat_join_request=""" chat_join_request="""
ChatJoinRequest ChatJoinRequest
ChatJoinRequest.approve ChatJoinRequest.approve

View file

@ -101,32 +101,6 @@ InlineQuery
{inline_query_toctree} {inline_query_toctree}
PreCheckoutQuery
----------------
.. hlist::
:columns: 2
{pre_checkout_query_hlist}
.. toctree::
:hidden:
{pre_checkout_query_toctree}
ShippingQuery
-------------
.. hlist::
:columns: 2
{shipping_query_hlist}
.. toctree::
:hidden:
{shipping_query_toctree}
ChatJoinRequest ChatJoinRequest
--------------- ---------------
@ -140,28 +114,3 @@ ChatJoinRequest
{chat_join_request_toctree} {chat_join_request_toctree}
Folder
---------------
.. hlist::
:columns: 2
{folder_hlist}
.. toctree::
:hidden:
{folder_toctree}
Gift
---------------
.. hlist::
:columns: 2
{gift_hlist}
.. toctree::
:hidden:
{gift_toctree}

View file

@ -47,19 +47,6 @@ Utilities
.. currentmodule:: pyrogram.Client .. currentmodule:: pyrogram.Client
Conversation
------------
.. autosummary::
:nosignatures:
{conversation}
.. toctree::
:hidden:
{conversation}
Messages Messages
-------- --------
@ -100,7 +87,7 @@ Chats
{chats} {chats}
Stickers Stickers
-------- -----
.. autosummary:: .. autosummary::
:nosignatures: :nosignatures:
@ -112,19 +99,6 @@ Stickers
{stickers} {stickers}
Telegram Business
-------------
.. autosummary::
:nosignatures:
{business}
.. toctree::
:hidden:
{business}
Users Users
----- -----
@ -190,19 +164,6 @@ Bots
{bots} {bots}
Payments
----
.. autosummary::
:nosignatures:
{payments}
.. toctree::
:hidden:
{payments}
Authorization Authorization
------------- -------------
@ -230,4 +191,4 @@ Learn more about how to use the raw API at :doc:`Advanced Usage <../../topics/ad
.. toctree:: .. toctree::
:hidden: :hidden:
{advanced} {advanced}

View file

@ -60,32 +60,6 @@ Stories
{stories} {stories}
Pyromod
-------
.. autosummary::
:nosignatures:
{pyromod}
.. toctree::
:hidden:
{pyromod}
Bot
---
.. autosummary::
:nosignatures:
{bot}
.. toctree::
:hidden:
{bot}
Bot keyboards Bot keyboards
------------- -------------
@ -112,19 +86,6 @@ Bot commands
{bot_commands} {bot_commands}
Telegram Business
-------------
.. autosummary::
:nosignatures:
{business}
.. toctree::
:hidden:
{business}
Input Media Input Media
----------- -----------
@ -164,45 +125,6 @@ InputMessageContent
{input_message_content} {input_message_content}
ShippingQuery
-------------------
.. autosummary::
:nosignatures:
{shipping_query}
.. toctree::
:hidden:
{shipping_query}
PreCheckoutQuery
-------------------
.. autosummary::
:nosignatures:
{pre_checkout_query}
.. toctree::
:hidden:
{pre_checkout_query}
Payment
-------------------
.. autosummary::
:nosignatures:
{payment}
.. toctree::
:hidden:
{payment}
Authorization Authorization
------------- -------------
@ -214,4 +136,4 @@ Authorization
.. toctree:: .. toctree::
:hidden: :hidden:
{authorization} {authorization}

View file

@ -17,7 +17,6 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
import ast
import csv import csv
import os import os
import re import re
@ -38,13 +37,6 @@ def caml(s):
s = snek(s).split("_") s = snek(s).split("_")
return "".join([str(i.title()) for i in s]) return "".join([str(i.title()) for i in s])
def get_classes_from_file(file_path):
with open(file_path, "r", encoding="utf-8") as f:
tree = ast.parse(f.read())
classes = [node.name for node in ast.walk(tree) if isinstance(node, ast.ClassDef)]
return classes
def start(): def start():
shutil.rmtree(DEST, ignore_errors=True) shutil.rmtree(DEST, ignore_errors=True)
@ -135,20 +127,6 @@ def start():
f_all.write(" },\n") f_all.write(" },\n")
f_all.write("}\n") f_all.write("}\n")
with open(init, "a", encoding="utf-8") as f_init:
f_init.write("\n")
all_classes = []
for i in files:
code, name = re.search(r"(\d+)_([A-Z_]+)", i).groups()
classes = get_classes_from_file("{}/{}_{}.py".format(DEST, name.lower(), code))
for j in classes:
if j not in ["BaseException", "Exception", "PyrogramException"]:
all_classes.append(j)
f_init.write("__all__ = [\n")
all_classes = sorted(set(all_classes))
for i in all_classes:
f_init.write(" \"{}\",\n".format(i))
f_init.write("]\n")
with open("{}/all.py".format(DEST), encoding="utf-8") as f: with open("{}/all.py".format(DEST), encoding="utf-8") as f:
content = f.read() content = f.read()

View file

@ -2,40 +2,30 @@ id message
ABOUT_TOO_LONG The provided about/bio text is too long ABOUT_TOO_LONG The provided about/bio text is too long
ACCESS_TOKEN_EXPIRED The bot token has expired ACCESS_TOKEN_EXPIRED The bot token has expired
ACCESS_TOKEN_INVALID The bot access token is invalid ACCESS_TOKEN_INVALID The bot access token is invalid
ADDRESS_INVALID The specified geopoint address is invalid.
ADMINS_TOO_MUCH The chat has too many administrators ADMINS_TOO_MUCH The chat has too many administrators
ADMIN_ID_INVALID The specified admin ID is invalid
ADMIN_RANK_EMOJI_NOT_ALLOWED Emoji are not allowed in custom administrator titles ADMIN_RANK_EMOJI_NOT_ALLOWED Emoji are not allowed in custom administrator titles
ADMIN_RANK_INVALID The custom administrator title is invalid or too long ADMIN_RANK_INVALID The custom administrator title is invalid or too long
ADMIN_RIGHTS_EMPTY The chatAdminRights constructor passed in keyboardButtonRequestPeer.peer_type.user_admin_rights has no rights set (i.e. flags is 0).
ALBUM_PHOTOS_TOO_MANY Too many photos were included in the album ALBUM_PHOTOS_TOO_MANY Too many photos were included in the album
API_ID_INVALID The api_id/api_hash combination is invalid API_ID_INVALID The api_id/api_hash combination is invalid
API_ID_PUBLISHED_FLOOD You are using an API key that is limited on the server side because it was published somewhere API_ID_PUBLISHED_FLOOD You are using an API key that is limited on the server side because it was published somewhere
ARTICLE_TITLE_EMPTY The article title is empty ARTICLE_TITLE_EMPTY The article title is empty
AUDIO_CONTENT_URL_EMPTY The remote URL specified in the content field is empty
AUDIO_TITLE_EMPTY The title attribute of the audio is empty AUDIO_TITLE_EMPTY The title attribute of the audio is empty
AUTH_BYTES_INVALID The authorization bytes are invalid AUTH_BYTES_INVALID The authorization bytes are invalid
AUTH_TOKEN_ALREADY_ACCEPTED The authorization token was already used AUTH_TOKEN_ALREADY_ACCEPTED The authorization token was already used
AUTH_TOKEN_EXCEPTION An error occurred while importing the auth token
AUTH_TOKEN_EXPIRED The provided authorization token has expired and the updated QR-code must be re-scanned AUTH_TOKEN_EXPIRED The provided authorization token has expired and the updated QR-code must be re-scanned
AUTH_TOKEN_INVALID An invalid authorization token was provided AUTH_TOKEN_INVALID An invalid authorization token was provided
AUTH_TOKEN_INVALID2 An invalid authorization token was provided
AUTH_TOKEN_INVALIDX The specified auth token is invalid
AUTOARCHIVE_NOT_AVAILABLE This feature is not yet enabled for your account due to it not receiving too many private messages from strangers AUTOARCHIVE_NOT_AVAILABLE This feature is not yet enabled for your account due to it not receiving too many private messages from strangers
BANK_CARD_NUMBER_INVALID The credit card number is invalid BANK_CARD_NUMBER_INVALID The credit card number is invalid
BANNED_RIGHTS_INVALID You provided a set of restrictions that is invalid BANNED_RIGHTS_INVALID You provided a set of restrictions that is invalid
BASE_PORT_LOC_INVALID The base port location is invalid BASE_PORT_LOC_INVALID The base port location is invalid
BIRTHDAY_INVALID The age should be less than 150 year old in Telegram
BOTS_TOO_MUCH The chat has too many bots BOTS_TOO_MUCH The chat has too many bots
BOT_CHANNELS_NA Bots can't edit admin privileges BOT_CHANNELS_NA Bots can't edit admin privileges
BOT_COMMAND_DESCRIPTION_INVALID The command description was empty, too long or had invalid characters BOT_COMMAND_DESCRIPTION_INVALID The command description was empty, too long or had invalid characters
BOT_COMMAND_INVALID The specified command is invalid
BOT_DOMAIN_INVALID The domain used for the auth button does not match the one configured in @BotFather BOT_DOMAIN_INVALID The domain used for the auth button does not match the one configured in @BotFather
BOT_GAMES_DISABLED Bot games cannot be used in this type of chat BOT_GAMES_DISABLED Bot games cannot be used in this type of chat
BOT_GROUPS_BLOCKED This bot can't be added to groups BOT_GROUPS_BLOCKED This bot can't be added to groups
BOT_INLINE_DISABLED The inline feature of the bot is disabled BOT_INLINE_DISABLED The inline feature of the bot is disabled
BOT_INVALID This is not a valid bot BOT_INVALID This is not a valid bot
BOT_INVOICE_INVALID The provided invoice is invalid
BOT_METHOD_INVALID The method can't be used by bots BOT_METHOD_INVALID The method can't be used by bots
BOT_MISSING This method can only be run by a bot BOT_MISSING This method can only be run by a bot
BOT_ONESIDE_NOT_AVAIL Bots can't pin messages for one side only in private chats BOT_ONESIDE_NOT_AVAIL Bots can't pin messages for one side only in private chats
@ -43,14 +33,10 @@ BOT_PAYMENTS_DISABLED This method can only be run by a bot
BOT_POLLS_DISABLED Sending polls by bots has been disabled BOT_POLLS_DISABLED Sending polls by bots has been disabled
BOT_RESPONSE_TIMEOUT The bot did not answer to the callback query in time BOT_RESPONSE_TIMEOUT The bot did not answer to the callback query in time
BOT_SCORE_NOT_MODIFIED The bot score was not modified BOT_SCORE_NOT_MODIFIED The bot score was not modified
BROADCAST_CALLS_DISABLED Broadcast calls disabled
BROADCAST_ID_INVALID The channel is invalid BROADCAST_ID_INVALID The channel is invalid
BROADCAST_PUBLIC_VOTERS_FORBIDDEN Polls with public voters cannot be sent in channels BROADCAST_PUBLIC_VOTERS_FORBIDDEN Polls with public voters cannot be sent in channels
BROADCAST_REQUIRED The request can only be used with a channel BROADCAST_REQUIRED The request can only be used with a channel
BUSINESS_BOT_MISSING Business bot missing
BUTTON_DATA_INVALID The button callback data is invalid or too large BUTTON_DATA_INVALID The button callback data is invalid or too large
BUTTON_ID_INVALID The button_id parameter is invalid
BUTTON_TEXT_INVALID The specified button text is invalid
BUTTON_TYPE_INVALID The type of one of the buttons you provided is invalid BUTTON_TYPE_INVALID The type of one of the buttons you provided is invalid
BUTTON_URL_INVALID The button url is invalid BUTTON_URL_INVALID The button url is invalid
BUTTON_USER_PRIVACY_RESTRICTED The privacy settings of the user specified in a keyboard button do not allow creating such button BUTTON_USER_PRIVACY_RESTRICTED The privacy settings of the user specified in a keyboard button do not allow creating such button
@ -59,20 +45,13 @@ CALL_ALREADY_DECLINED The call is already declined
CALL_PEER_INVALID The provided call peer object is invalid CALL_PEER_INVALID The provided call peer object is invalid
CALL_PROTOCOL_FLAGS_INVALID Call protocol flags invalid CALL_PROTOCOL_FLAGS_INVALID Call protocol flags invalid
CDN_METHOD_INVALID The method can't be used on CDN DCs CDN_METHOD_INVALID The method can't be used on CDN DCs
CHANNELS_ADMIN_LOCATED_TOO_MUCH The user has reached the limit of public geogroups
CHANNELS_ADMIN_PUBLIC_TOO_MUCH You are an administrator of too many public channels CHANNELS_ADMIN_PUBLIC_TOO_MUCH You are an administrator of too many public channels
CHANNELS_TOO_MUCH You have joined too many channels or supergroups, leave some and try again CHANNELS_TOO_MUCH You have joined too many channels or supergroups, leave some and try again
CHANNEL_ADD_INVALID Internal error. CHANNEL_ADD_INVALID Internal error.
CHANNEL_BANNED The channel is banned CHANNEL_BANNED The channel is banned
CHANNEL_ID_INVALID The specified supergroup ID is invalid.
CHANNEL_INVALID The channel parameter is invalid CHANNEL_INVALID The channel parameter is invalid
CHANNEL_PARICIPANT_MISSING The current user is not in the channel
CHANNEL_PRIVATE The channel/supergroup is not accessible CHANNEL_PRIVATE The channel/supergroup is not accessible
CHANNEL_TOO_BIG The channel too big CHANNEL_TOO_LARGE The channel is too large
CHANNEL_TOO_LARGE "Channel is too large to be deleted; this error is issued when trying to delete channels with more than 1000 members (subject to change)."
CHARGE_ALREADY_REFUNDED The charge id was already used for a refund.
CHARGE_NOT_FOUND The charge id was not found.
CHATLIST_EXCLUDE_INVALID The specified `exclude_peers` are invalid.
CHAT_ABOUT_NOT_MODIFIED The chat about text was not modified because you tried to edit it using the same content CHAT_ABOUT_NOT_MODIFIED The chat about text was not modified because you tried to edit it using the same content
CHAT_ABOUT_TOO_LONG The chat about text is too long CHAT_ABOUT_TOO_LONG The chat about text is too long
CHAT_ADMIN_REQUIRED The method requires chat admin privileges CHAT_ADMIN_REQUIRED The method requires chat admin privileges
@ -85,14 +64,12 @@ CHAT_INVITE_PERMANENT The chat invite link is primary
CHAT_LINK_EXISTS The action failed because the supergroup is linked to a channel CHAT_LINK_EXISTS The action failed because the supergroup is linked to a channel
CHAT_NOT_MODIFIED The chat settings (title, permissions, photo, etc..) were not modified because you tried to edit them using the same content CHAT_NOT_MODIFIED The chat settings (title, permissions, photo, etc..) were not modified because you tried to edit them using the same content
CHAT_RESTRICTED The chat is restricted and cannot be used CHAT_RESTRICTED The chat is restricted and cannot be used
CHAT_REVOKE_DATE_UNSUPPORTED `min_date` and `max_date` are not available for using with non-user peers
CHAT_SEND_INLINE_FORBIDDEN You cannot use inline bots to send messages in this chat CHAT_SEND_INLINE_FORBIDDEN You cannot use inline bots to send messages in this chat
CHAT_TITLE_EMPTY The chat title is empty CHAT_TITLE_EMPTY The chat title is empty
CHAT_TOO_BIG The chat is too big for this action CHAT_TOO_BIG The chat is too big for this action
CODE_EMPTY The provided code is empty CODE_EMPTY The provided code is empty
CODE_HASH_INVALID The provided code hash invalid CODE_HASH_INVALID The provided code hash invalid
CODE_INVALID The provided code is invalid (i.e. from email) CODE_INVALID The provided code is invalid (i.e. from email)
COLOR_INVALID The provided color is invalid
CONNECTION_API_ID_INVALID The provided API id is invalid CONNECTION_API_ID_INVALID The provided API id is invalid
CONNECTION_APP_VERSION_EMPTY App version is empty CONNECTION_APP_VERSION_EMPTY App version is empty
CONNECTION_DEVICE_MODEL_EMPTY The device model is empty CONNECTION_DEVICE_MODEL_EMPTY The device model is empty
@ -103,11 +80,8 @@ CONNECTION_SYSTEM_EMPTY The connection to the system is empty
CONNECTION_SYSTEM_LANG_CODE_EMPTY The system language code is empty CONNECTION_SYSTEM_LANG_CODE_EMPTY The system language code is empty
CONTACT_ADD_MISSING Contact to add is missing CONTACT_ADD_MISSING Contact to add is missing
CONTACT_ID_INVALID The provided contact id is invalid CONTACT_ID_INVALID The provided contact id is invalid
CONTACT_MISSING The specified user is not a contact.
CONTACT_NAME_EMPTY The provided contact name is empty CONTACT_NAME_EMPTY The provided contact name is empty
CONTACT_REQ_MISSING Missing contact request CONTACT_REQ_MISSING Missing contact request
CREATE_CALL_FAILED An error occurred while creating the call
CURRENCY_TOTAL_AMOUNT_INVALID The total amount of all prices is invalid
DATA_INVALID The encrypted data is invalid DATA_INVALID The encrypted data is invalid
DATA_JSON_INVALID The provided JSON data is invalid DATA_JSON_INVALID The provided JSON data is invalid
DATA_TOO_LONG Data too long DATA_TOO_LONG Data too long
@ -117,14 +91,9 @@ DH_G_A_INVALID The g_a parameter invalid
DOCUMENT_INVALID The document is invalid DOCUMENT_INVALID The document is invalid
EMAIL_HASH_EXPIRED The email hash expired and cannot be used to verify it EMAIL_HASH_EXPIRED The email hash expired and cannot be used to verify it
EMAIL_INVALID The email provided is invalid EMAIL_INVALID The email provided is invalid
EMAIL_NOT_ALLOWED This email is not allowed
EMAIL_NOT_SETUP In order to change the login email with emailVerifyPurposeLoginChange, an existing login email must already be set using emailVerifyPurposeLoginSetup.
EMAIL_UNCONFIRMED Email unconfirmed EMAIL_UNCONFIRMED Email unconfirmed
EMAIL_UNCONFIRMED_X The provided email isn't confirmed, {value} is the length of the verification code that was just sent to the email EMAIL_UNCONFIRMED_X The provided email isn't confirmed, {value} is the length of the verification code that was just sent to the email
EMAIL_VERIFY_EXPIRED The verification email has expired EMAIL_VERIFY_EXPIRED The verification email has expired
EMOJI_INVALID The specified theme emoji is valid
EMOJI_MARKUP_INVALID The specified `video_emoji_markup` was invalid.
EMOJI_NOT_MODIFIED The theme wasn't changed
EMOTICON_EMPTY The emoticon parameter is empty EMOTICON_EMPTY The emoticon parameter is empty
EMOTICON_INVALID The emoticon parameter is invalid EMOTICON_INVALID The emoticon parameter is invalid
EMOTICON_STICKERPACK_MISSING The emoticon sticker pack you are trying to obtain is missing EMOTICON_STICKERPACK_MISSING The emoticon sticker pack you are trying to obtain is missing
@ -138,20 +107,13 @@ ENTITY_BOUNDS_INVALID The message entity bounds are invalid
ENTITY_MENTION_USER_INVALID The mentioned entity is not an user ENTITY_MENTION_USER_INVALID The mentioned entity is not an user
ERROR_TEXT_EMPTY The provided error message is empty ERROR_TEXT_EMPTY The provided error message is empty
EXPIRE_DATE_INVALID The expiration date is invalid EXPIRE_DATE_INVALID The expiration date is invalid
EXPIRE_FORBIDDEN Expire forbidden
EXPORT_CARD_INVALID The provided card is invalid EXPORT_CARD_INVALID The provided card is invalid
EXTENDED_MEDIA_AMOUNT_INVALID The maximum amount of `star_count` should be less than the `stars_paid_post_amount_max`
EXTENDED_MEDIA_PEER_INVALID The specified chat type is invalid.
EXTENDED_MEDIA_TYPE_INVALID The specified extended media type is unsupported.
EXTERNAL_URL_INVALID The external media URL is invalid EXTERNAL_URL_INVALID The external media URL is invalid
FIELD_NAME_EMPTY The field with the name FIELD_NAME is missing FIELD_NAME_EMPTY The field with the name FIELD_NAME is missing
FIELD_NAME_INVALID The field with the name FIELD_NAME is invalid FIELD_NAME_INVALID The field with the name FIELD_NAME is invalid
FILE_CONTENT_TYPE_INVALID File content-type is invalid
FILE_EMTPY An empty file was provided
FILE_ID_INVALID The file id is invalid FILE_ID_INVALID The file id is invalid
FILE_MIGRATE_X The file is in Data Center No. {value} FILE_MIGRATE_X The file is in Data Center No. {value}
FILE_PARTS_INVALID Invalid number of parts. FILE_PARTS_INVALID Invalid number of parts.
FILE_PART_0_MISSING File part 0 missing
FILE_PART_EMPTY The file part sent is empty FILE_PART_EMPTY The file part sent is empty
FILE_PART_INVALID The file part number is invalid. FILE_PART_INVALID The file part number is invalid.
FILE_PART_LENGTH_INVALID The length of a file part is invalid FILE_PART_LENGTH_INVALID The length of a file part is invalid
@ -162,38 +124,23 @@ FILE_PART_X_MISSING Part {value} of the file is missing from storage
FILE_REFERENCE_EMPTY The file id contains an empty file reference, you must obtain a valid one by fetching the message from the origin context FILE_REFERENCE_EMPTY The file id contains an empty file reference, you must obtain a valid one by fetching the message from the origin context
FILE_REFERENCE_EXPIRED The file id contains an expired file reference, you must obtain a valid one by fetching the message from the origin context FILE_REFERENCE_EXPIRED The file id contains an expired file reference, you must obtain a valid one by fetching the message from the origin context
FILE_REFERENCE_INVALID The file id contains an invalid file reference, you must obtain a valid one by fetching the message from the origin context FILE_REFERENCE_INVALID The file id contains an invalid file reference, you must obtain a valid one by fetching the message from the origin context
FILE_TITLE_EMPTY An empty file title was specified
FILTER_ID_INVALID The specified filter ID is invalid FILTER_ID_INVALID The specified filter ID is invalid
FILTER_INCLUDE_EMPTY The filter include is empty
FILTER_NOT_SUPPORTED The specified filter cannot be used in this context
FILTER_TITLE_EMPTY The title field of the filter is empty
FIRSTNAME_INVALID The first name is invalid FIRSTNAME_INVALID The first name is invalid
FOLDER_ID_EMPTY The folder you tried to delete was already empty FOLDER_ID_EMPTY The folder you tried to delete was already empty
FOLDER_ID_INVALID The folder id is invalid FOLDER_ID_INVALID The folder id is invalid
FORM_ID_EXPIRED The specified id has expired.
FORUM_ENABLED You can't execute the specified action because the group is a [forum](https://core.telegram.org/api/forum), disable forum functionality to continue.
FRESH_CHANGE_ADMINS_FORBIDDEN You can't change administrator settings in this chat because your session was logged-in recently FRESH_CHANGE_ADMINS_FORBIDDEN You can't change administrator settings in this chat because your session was logged-in recently
FROM_MESSAGE_BOT_DISABLED Bots can't use fromMessage min constructors FROM_MESSAGE_BOT_DISABLED Bots can't use fromMessage min constructors
FROM_PEER_INVALID The from peer value is invalid FROM_PEER_INVALID The from peer value is invalid
GAME_BOT_INVALID You cannot send that game with the current bot GAME_BOT_INVALID You cannot send that game with the current bot
GENERAL_MODIFY_ICON_FORBIDDEN You can't modify the icon of the General topic.
GEO_POINT_INVALID Invalid geo point provided GEO_POINT_INVALID Invalid geo point provided
GIF_CONTENT_TYPE_INVALID GIF content-type invalid GIF_CONTENT_TYPE_INVALID GIF content-type invalid
GIF_ID_INVALID The provided gif/animation id is invalid GIF_ID_INVALID The provided gif/animation id is invalid
GIFT_SLUG_INVALID The specified slug is invalid.
GIFT_SLUG_EXPIRED The gift slug is expired
GRAPH_EXPIRED_RELOAD This graph has expired, please obtain a new graph token
GRAPH_INVALID_RELOAD Invalid graph token provided, please reload the stats and provide the updated token GRAPH_INVALID_RELOAD Invalid graph token provided, please reload the stats and provide the updated token
GRAPH_OUTDATED_RELOAD The graph data is outdated GRAPH_OUTDATED_RELOAD The graph data is outdated
GROUPCALL_ALREADY_DISCARDED The group call was already discarded
GROUPCALL_INVALID The specified group call is invalid
GROUPCALL_JOIN_MISSING You haven't joined this group call
GROUPCALL_NOT_MODIFIED Group call settings weren't modified
GROUPCALL_SSRC_DUPLICATE_MUCH Too many group call synchronization source duplicates GROUPCALL_SSRC_DUPLICATE_MUCH Too many group call synchronization source duplicates
GROUPED_MEDIA_INVALID The album contains invalid media GROUPED_MEDIA_INVALID The album contains invalid media
GROUP_CALL_INVALID The group call is invalid GROUP_CALL_INVALID The group call is invalid
HASH_INVALID The provided hash is invalid HASH_INVALID The provided hash is invalid
HIDE_REQUESTER_MISSING The join request was missing or was already handled
IMAGE_PROCESS_FAILED The server failed to process your image IMAGE_PROCESS_FAILED The server failed to process your image
IMPORT_FILE_INVALID The imported file is invalid IMPORT_FILE_INVALID The imported file is invalid
IMPORT_FORMAT_UNRECOGNIZED The imported format is unrecognized IMPORT_FORMAT_UNRECOGNIZED The imported format is unrecognized
@ -206,35 +153,23 @@ INPUT_FILTER_INVALID The filter is invalid for this query
INPUT_LAYER_INVALID The provided layer is invalid INPUT_LAYER_INVALID The provided layer is invalid
INPUT_METHOD_INVALID The method invoked is invalid in the current schema INPUT_METHOD_INVALID The method invoked is invalid in the current schema
INPUT_REQUEST_TOO_LONG The input request is too long INPUT_REQUEST_TOO_LONG The input request is too long
INPUT_TEXT_EMPTY The specified text is empty
INPUT_TEXT_TOO_LONG The specified text is too long.
INPUT_USER_DEACTIVATED The target user has been deleted/deactivated INPUT_USER_DEACTIVATED The target user has been deleted/deactivated
INVITES_TOO_MUCH The maximum number of per-folder invites specified by the `chatlist_invites_limit_default`/`chatlist_invites_limit_premium` was reached.
INVITE_FORBIDDEN_WITH_JOINAS If the user has anonymously joined a group call as a channel, they can't invite other users to the group call because that would cause deanonymization, because the invite would be sent using the original user ID, not the anonymized channel ID
INVITE_HASH_EMPTY The invite hash is empty INVITE_HASH_EMPTY The invite hash is empty
INVITE_HASH_EXPIRED The chat invite link is no longer valid INVITE_HASH_EXPIRED The chat invite link is no longer valid
INVITE_HASH_INVALID The invite link hash is invalid INVITE_HASH_INVALID The invite link hash is invalid
INVITE_REQUEST_SENT The request to join this chat or channel has been successfully sent INVITE_REQUEST_SENT The request to join this chat or channel has been successfully sent
INVITE_REVOKED_MISSING The action required a chat invite link to be revoked first INVITE_REVOKED_MISSING The action required a chat invite link to be revoked first
INVITE_SLUG_EMPTY The invite slug is empty
INVITE_SLUG_EXPIRED The invite slug is expired
INVOICE_PAYLOAD_INVALID The specified invoice payload is invalid
JOIN_AS_PEER_INVALID The specified peer cannot be used to join a group call
LANG_CODE_INVALID The specified language code is invalid
LANG_CODE_NOT_SUPPORTED The specified language code is not supported
LANG_PACK_INVALID The provided language pack is invalid LANG_PACK_INVALID The provided language pack is invalid
LASTNAME_INVALID The last name is invalid LASTNAME_INVALID The last name is invalid
LIMIT_INVALID The limit parameter is invalid LIMIT_INVALID The limit parameter is invalid
LINK_NOT_MODIFIED The chat link was not modified because you tried to link to the same target LINK_NOT_MODIFIED The chat link was not modified because you tried to link to the same target
LOCATION_INVALID The file location is invalid LOCATION_INVALID The file location is invalid
MAX_DATE_INVALID The specified maximum date is invalid
MAX_ID_INVALID The max_id parameter is invalid MAX_ID_INVALID The max_id parameter is invalid
MAX_QTS_INVALID The provided QTS is invalid MAX_QTS_INVALID The provided QTS is invalid
MD5_CHECKSUM_INVALID The file's checksum did not match the md5_checksum parameter MD5_CHECKSUM_INVALID The file's checksum did not match the md5_checksum parameter
MEDIA_CAPTION_TOO_LONG The media caption is too long MEDIA_CAPTION_TOO_LONG The media caption is too long
MEDIA_EMPTY The media you tried to send is invalid MEDIA_EMPTY The media you tried to send is invalid
MEDIA_FILE_INVALID The provided media file is invalid MEDIA_FILE_INVALID The media file is invalid
MEDIA_GROUPED_INVALID You tried to send media of different types in an album
MEDIA_INVALID The media is invalid MEDIA_INVALID The media is invalid
MEDIA_NEW_INVALID The new media to edit the message with is invalid MEDIA_NEW_INVALID The new media to edit the message with is invalid
MEDIA_PREV_INVALID The previous media cannot be edited with anything else MEDIA_PREV_INVALID The previous media cannot be edited with anything else
@ -251,16 +186,12 @@ MESSAGE_NOT_MODIFIED The message was not modified because you tried to edit it u
MESSAGE_POLL_CLOSED You can't interact with a closed poll MESSAGE_POLL_CLOSED You can't interact with a closed poll
MESSAGE_TOO_LONG The message text is too long MESSAGE_TOO_LONG The message text is too long
METHOD_INVALID The API method is invalid and cannot be used METHOD_INVALID The API method is invalid and cannot be used
MIN_DATE_INVALID The specified minimum date is invalid
MSG_ID_INVALID The message ID used in the peer was invalid MSG_ID_INVALID The message ID used in the peer was invalid
MSG_TOO_OLD chat_read_mark_expire_period have passed since the message was sent, read receipts were deleted
MSG_VOICE_MISSING The message does not contain a voice message MSG_VOICE_MISSING The message does not contain a voice message
MSG_WAIT_FAILED A waiting call returned an error MSG_WAIT_FAILED A waiting call returned an error
MULTI_MEDIA_TOO_LONG The album/media group contains too many items MULTI_MEDIA_TOO_LONG The album/media group contains too many items
NEW_SALT_INVALID The new salt is invalid NEW_SALT_INVALID The new salt is invalid
NEW_SETTINGS_EMPTY No password is set on the current account, and no new password was specified in `new_settings`
NEW_SETTINGS_INVALID The new settings are invalid NEW_SETTINGS_INVALID The new settings are invalid
NOGENERAL_HIDE_FORBIDDEN The hidden parameter is only valid for the General topic message_thread_id=1
NEXT_OFFSET_INVALID The next offset value is invalid NEXT_OFFSET_INVALID The next offset value is invalid
OFFSET_INVALID The offset parameter is invalid OFFSET_INVALID The offset parameter is invalid
OFFSET_PEER_ID_INVALID The provided offset peer is invalid OFFSET_PEER_ID_INVALID The provided offset peer is invalid
@ -270,8 +201,6 @@ PACK_SHORT_NAME_INVALID Invalid sticker pack name. It must begin with a letter,
PACK_SHORT_NAME_OCCUPIED A sticker pack with this name already exists PACK_SHORT_NAME_OCCUPIED A sticker pack with this name already exists
PACK_TITLE_INVALID The sticker pack title is invalid PACK_TITLE_INVALID The sticker pack title is invalid
PARTICIPANTS_TOO_FEW The chat doesn't have enough participants PARTICIPANTS_TOO_FEW The chat doesn't have enough participants
PARTICIPANT_ID_INVALID The specified participant ID is invalid
PARTICIPANT_JOIN_MISSING Trying to enable a presentation, when the user hasn't joined the Video Chat with phone.joinGroupCall
PARTICIPANT_VERSION_OUTDATED The other participant is using an outdated Telegram app version PARTICIPANT_VERSION_OUTDATED The other participant is using an outdated Telegram app version
PASSWORD_EMPTY The password provided is empty PASSWORD_EMPTY The password provided is empty
PASSWORD_HASH_INVALID The two-step verification password is invalid PASSWORD_HASH_INVALID The two-step verification password is invalid
@ -281,7 +210,6 @@ PASSWORD_REQUIRED The two-step verification password is required for this method
PASSWORD_TOO_FRESH_X The two-step verification password was added recently and you are required to wait {value} seconds PASSWORD_TOO_FRESH_X The two-step verification password was added recently and you are required to wait {value} seconds
PAYMENT_PROVIDER_INVALID The payment provider was not recognised or its token was invalid PAYMENT_PROVIDER_INVALID The payment provider was not recognised or its token was invalid
PEER_FLOOD The method can't be used because your account is currently limited PEER_FLOOD The method can't be used because your account is currently limited
PEER_HISTORY_EMPTY Peer history empty
PEER_ID_INVALID The peer id being used is invalid or not known yet. Make sure you meet the peer before interacting with it PEER_ID_INVALID The peer id being used is invalid or not known yet. Make sure you meet the peer before interacting with it
PEER_ID_NOT_SUPPORTED The provided peer id is not supported PEER_ID_NOT_SUPPORTED The provided peer id is not supported
PERSISTENT_TIMESTAMP_EMPTY The pts argument is empty PERSISTENT_TIMESTAMP_EMPTY The pts argument is empty
@ -290,8 +218,6 @@ PHONE_CODE_EMPTY The phone code is missing
PHONE_CODE_EXPIRED The confirmation code has expired PHONE_CODE_EXPIRED The confirmation code has expired
PHONE_CODE_HASH_EMPTY The phone code hash is missing PHONE_CODE_HASH_EMPTY The phone code hash is missing
PHONE_CODE_INVALID The confirmation code is invalid PHONE_CODE_INVALID The confirmation code is invalid
PHONE_HASH_EXPIRED An invalid or expired phone_code_hash was provided
PHONE_NOT_OCCUPIED No user is associated to the specified phone number
PHONE_NUMBER_APP_SIGNUP_FORBIDDEN You can't sign up using this app PHONE_NUMBER_APP_SIGNUP_FORBIDDEN You can't sign up using this app
PHONE_NUMBER_BANNED The phone number is banned from Telegram and cannot be used PHONE_NUMBER_BANNED The phone number is banned from Telegram and cannot be used
PHONE_NUMBER_FLOOD This number has tried to login too many times PHONE_NUMBER_FLOOD This number has tried to login too many times
@ -312,26 +238,20 @@ PHOTO_SAVE_FILE_INVALID The photo you tried to send cannot be saved by Telegram
PHOTO_THUMB_URL_EMPTY The photo thumb URL is empty PHOTO_THUMB_URL_EMPTY The photo thumb URL is empty
PHOTO_THUMB_URL_INVALID The photo thumb URL is invalid PHOTO_THUMB_URL_INVALID The photo thumb URL is invalid
PINNED_DIALOGS_TOO_MUCH Too many pinned dialogs PINNED_DIALOGS_TOO_MUCH Too many pinned dialogs
PINNED_TOPIC_NOT_MODIFIED The pinned topic was not modified.
PIN_RESTRICTED You can't pin messages in private chats with other people PIN_RESTRICTED You can't pin messages in private chats with other people
POLL_ANSWERS_INVALID The poll answers are invalid POLL_ANSWERS_INVALID The poll answers are invalid
POLL_ANSWER_INVALID One of the poll answers is not acceptable
POLL_OPTION_DUPLICATE A duplicate option was sent in the same poll POLL_OPTION_DUPLICATE A duplicate option was sent in the same poll
POLL_OPTION_INVALID A poll option used invalid data (the data may be too long) POLL_OPTION_INVALID A poll option used invalid data (the data may be too long)
POLL_QUESTION_INVALID The poll question is invalid POLL_QUESTION_INVALID The poll question is invalid
POLL_UNSUPPORTED This layer does not support polls in the invoked method POLL_UNSUPPORTED This layer does not support polls in the invoked method
POLL_VOTE_REQUIRED Cast a vote in the poll before calling this method POLL_VOTE_REQUIRED Cast a vote in the poll before calling this method
PREMIUM_ACCOUNT_REQUIRED The method requires a premium user account PREMIUM_ACCOUNT_REQUIRED The method requires a premium user account
PREMIUM_GIFTCODE_WAS_REFUNDED This gift code can't be redeemed because the giveaway organizer requested a refund
PRICING_CHAT_INVALID This chat chat doesn't support subscription link.
PRIVACY_KEY_INVALID The privacy key is invalid PRIVACY_KEY_INVALID The privacy key is invalid
PRIVACY_TOO_LONG Your privacy exception list has exceeded the maximum capacity PRIVACY_TOO_LONG Your privacy exception list has exceeded the maximum capacity
PRIVACY_VALUE_INVALID The privacy value is invalid PRIVACY_VALUE_INVALID The privacy value is invalid
PUBLIC_KEY_REQUIRED A public key is required
QUERY_ID_EMPTY The query ID is empty QUERY_ID_EMPTY The query ID is empty
QUERY_ID_INVALID The callback query id is invalid QUERY_ID_INVALID The callback query id is invalid
QUERY_TOO_SHORT The query is too short QUERY_TOO_SHORT The query is too short
QUIZ_ANSWER_MISSING You can forward a quiz while hiding the original author only after choosing an option in the quiz
QUIZ_CORRECT_ANSWERS_EMPTY The correct answers of the quiz are empty QUIZ_CORRECT_ANSWERS_EMPTY The correct answers of the quiz are empty
QUIZ_CORRECT_ANSWERS_TOO_MUCH The quiz contains too many correct answers QUIZ_CORRECT_ANSWERS_TOO_MUCH The quiz contains too many correct answers
QUIZ_CORRECT_ANSWER_INVALID The correct answers of the quiz are invalid QUIZ_CORRECT_ANSWER_INVALID The correct answers of the quiz are invalid
@ -347,46 +267,33 @@ REPLY_MARKUP_BUY_EMPTY Reply markup for buy button empty
REPLY_MARKUP_GAME_EMPTY The provided reply markup for the game is empty REPLY_MARKUP_GAME_EMPTY The provided reply markup for the game is empty
REPLY_MARKUP_INVALID The provided reply markup is invalid REPLY_MARKUP_INVALID The provided reply markup is invalid
REPLY_MARKUP_TOO_LONG The reply markup is too long REPLY_MARKUP_TOO_LONG The reply markup is too long
REPLY_MESSAGE_ID_INVALID The reply message id is invalid
RESET_REQUEST_MISSING No password reset is in progress
RESULTS_TOO_MUCH The result contains too many items RESULTS_TOO_MUCH The result contains too many items
RESULT_ID_DUPLICATE The result contains items with duplicated identifiers RESULT_ID_DUPLICATE The result contains items with duplicated identifiers
RESULT_ID_EMPTY Result ID empty RESULT_ID_EMPTY Result ID empty
RESULT_ID_INVALID The given result cannot be used to send the selection to the bot RESULT_ID_INVALID The given result cannot be used to send the selection to the bot
REACTIONS_TOO_MANY Currently, non-premium users, can set up to one reaction per message
RESULT_TYPE_INVALID The result type is invalid RESULT_TYPE_INVALID The result type is invalid
REVOTE_NOT_ALLOWED You cannot change your vote REVOTE_NOT_ALLOWED You cannot change your vote
RIGHTS_NOT_MODIFIED The new admin rights are equal to the old rights, no change was made
RSA_DECRYPT_FAILED Internal RSA decryption failed RSA_DECRYPT_FAILED Internal RSA decryption failed
SCHEDULE_BOT_NOT_ALLOWED Bots are not allowed to schedule messages SCHEDULE_BOT_NOT_ALLOWED Bots are not allowed to schedule messages
SCHEDULE_DATE_INVALID Invalid schedule date provided SCHEDULE_DATE_INVALID Invalid schedule date provided
SCHEDULE_DATE_TOO_LATE The date you tried to schedule is too far in the future (more than one year) SCHEDULE_DATE_TOO_LATE The date you tried to schedule is too far in the future (more than one year)
SCHEDULE_STATUS_PRIVATE You cannot schedule a message until the person comes online if their privacy does not show this information SCHEDULE_STATUS_PRIVATE You cannot schedule a message until the person comes online if their privacy does not show this information
SCHEDULE_TOO_MUCH You tried to schedule too many messages in this chat SCHEDULE_TOO_MUCH You tried to schedule too many messages in this chat
SCORE_INVALID The specified game score is invalid
SEARCH_QUERY_EMPTY The search query is empty SEARCH_QUERY_EMPTY The search query is empty
SEARCH_WITH_LINK_NOT_SUPPORTED You cannot provide a search query and an invite link at the same time
SECONDS_INVALID The seconds interval is invalid SECONDS_INVALID The seconds interval is invalid
SEND_AS_PEER_INVALID You can't send messages as the specified peer
SEND_MESSAGE_MEDIA_INVALID The message media is invalid SEND_MESSAGE_MEDIA_INVALID The message media is invalid
SEND_MESSAGE_TYPE_INVALID The message type is invalid SEND_MESSAGE_TYPE_INVALID The message type is invalid
SESSION_TOO_FRESH_X You can't do this action because the current session was logged-in recently SESSION_TOO_FRESH_X You can't do this action because the current session was logged-in recently
SETTINGS_INVALID Invalid settings were provided SETTINGS_INVALID Invalid settings were provided
SHA256_HASH_INVALID The provided SHA256 hash is invalid SHA256_HASH_INVALID The provided SHA256 hash is invalid
SHORTNAME_OCCUPY_FAILED An error occurred when trying to register the short-name used for the sticker pack. Try a different name SHORTNAME_OCCUPY_FAILED An error occurred when trying to register the short-name used for the sticker pack. Try a different name
SHORT_NAME_INVALID The specified short name is invalid
SHORT_NAME_OCCUPIED The specified short name is already in use
SLOWMODE_MULTI_MSGS_DISABLED Slowmode is enabled, you cannot forward multiple messages to this group SLOWMODE_MULTI_MSGS_DISABLED Slowmode is enabled, you cannot forward multiple messages to this group
SMS_CODE_CREATE_FAILED An error occurred while creating the SMS code SMS_CODE_CREATE_FAILED An error occurred while creating the SMS code
SRP_ID_INVALID Invalid SRP ID provided SRP_ID_INVALID Invalid SRP ID provided
SRP_PASSWORD_CHANGED The password has changed SRP_PASSWORD_CHANGED The password has changed
STARGIFT_ALREADY_CONVERTED The provided star gift already converted to stars
STARGIFT_ALREADY_UPGRADED This star gift was already upgraded before
STARGIFT_USAGE_LIMITED The star gift usage is limited
START_PARAM_EMPTY The start parameter is empty START_PARAM_EMPTY The start parameter is empty
START_PARAM_INVALID The start parameter is invalid START_PARAM_INVALID The start parameter is invalid
START_PARAM_TOO_LONG The start parameter is too long START_PARAM_TOO_LONG The start parameter is too long
STICKERPACK_STICKERS_TOO_MUCH There are too many stickers in this stickerpack, you can't add any more
STICKERSET_INVALID The requested sticker set is invalid STICKERSET_INVALID The requested sticker set is invalid
STICKERSET_NOT_MODIFIED The sticker set is not modified STICKERSET_NOT_MODIFIED The sticker set is not modified
STICKERS_EMPTY The sticker provided is empty STICKERS_EMPTY The sticker provided is empty
@ -394,55 +301,32 @@ STICKERS_TOO_MUCH Too many stickers in the set
STICKER_DOCUMENT_INVALID The sticker document is invalid STICKER_DOCUMENT_INVALID The sticker document is invalid
STICKER_EMOJI_INVALID The sticker emoji is invalid STICKER_EMOJI_INVALID The sticker emoji is invalid
STICKER_FILE_INVALID The sticker file is invalid STICKER_FILE_INVALID The sticker file is invalid
STICKER_GIF_DIMENSIONS The specified video sticker has invalid dimensions
STICKER_ID_INVALID The provided sticker id is invalid STICKER_ID_INVALID The provided sticker id is invalid
STICKER_INVALID The provided sticker is invalid STICKER_INVALID The provided sticker is invalid
STICKER_MIME_INVALID Make sure to pass a valid image file for the right InputFile parameter
STICKER_PNG_DIMENSIONS The sticker png dimensions are invalid STICKER_PNG_DIMENSIONS The sticker png dimensions are invalid
STICKER_PNG_NOPNG Stickers must be png files but the provided image was not a png STICKER_PNG_NOPNG Stickers must be png files but the provided image was not a png
STICKER_TGS_NODOC You must send the animated sticker as a document
STICKER_TGS_NOTGS A tgs sticker file was expected, but something else was provided STICKER_TGS_NOTGS A tgs sticker file was expected, but something else was provided
STICKER_THUMB_PNG_NOPNG A png sticker thumbnail file was expected, but something else was provided STICKER_THUMB_PNG_NOPNG A png sticker thumbnail file was expected, but something else was provided
STICKER_VIDEO_BIG The specified video sticker is too big
STICKER_VIDEO_NODOC You must send the video sticker as a document
STICKER_VIDEO_NOWEBM A webm video file was expected, but something else was provided STICKER_VIDEO_NOWEBM A webm video file was expected, but something else was provided
STORY_ID_EMPTY You specified no story IDs.
STORY_ID_INVALID The specified story ID is invalid.
STORY_NOT_MODIFIED The new story information you passed is equal to the previous story information, thus it wasn't modified.
STORY_PERIOD_INVALID The specified story period is invalid for this account.
STORIES_TOO_MUCH Too many stories in the current account STORIES_TOO_MUCH Too many stories in the current account
STORY_SEND_FLOOD_WEEKLY_X You've hit the weekly story limit, wait for the specified number of seconds before posting a new story.
STORY_SEND_FLOOD_MONTHLY_X You've hit the monthly story limit, wait for the specified number of seconds before posting a new story.
STORY_PERIOD_INVALID The story period is invalid
SUBSCRIPTION_PERIOD_INVALID The subscription period is invalid.
SWITCH_PM_TEXT_EMPTY The switch_pm.text field was empty
TAKEOUT_INVALID The takeout id is invalid TAKEOUT_INVALID The takeout id is invalid
TAKEOUT_REQUIRED The method must be invoked inside a takeout session TAKEOUT_REQUIRED The method must be invoked inside a takeout session
TEMP_AUTH_KEY_ALREADY_BOUND The passed temporary key is already bound to another perm_auth_key_id
TEMP_AUTH_KEY_EMPTY The temporary auth key provided is empty TEMP_AUTH_KEY_EMPTY The temporary auth key provided is empty
THEME_FILE_INVALID Invalid theme file provided THEME_FILE_INVALID Invalid theme file provided
THEME_FORMAT_INVALID Invalid theme format provided THEME_FORMAT_INVALID Invalid theme format provided
THEME_INVALID Invalid theme provided THEME_INVALID Invalid theme provided
THEME_MIME_INVALID You cannot create this theme because the mime-type is invalid THEME_MIME_INVALID You cannot create this theme because the mime-type is invalid
THEME_TITLE_INVALID The specified theme title is invalid
TITLE_INVALID The specified stickerpack title is invalid
TMP_PASSWORD_DISABLED The temporary password is disabled TMP_PASSWORD_DISABLED The temporary password is disabled
TMP_PASSWORD_INVALID The temporary password is invalid TMP_PASSWORD_INVALID The temporary password is invalid
TOKEN_INVALID The provided token is invalid TOKEN_INVALID The provided token is invalid
TOPIC_CLOSED The topic was closed TOPIC_CLOSED The topic was closed
TOPIC_DELETED The topic was deleted TOPIC_DELETED The topic was deleted
TOPIC_CLOSE_SEPARATELY The close flag cannot be provided together with any of the other flags.
TOPIC_HIDE_SEPARATELY The hide flag cannot be provided together with any of the other flags.
TOPIC_ID_INVALID The provided topic ID is invalid
TOPIC_NOT_MODIFIED The topic was not modified TOPIC_NOT_MODIFIED The topic was not modified
TOPIC_TITLE_EMPTY The specified topic title is empty.
TO_LANG_INVALID The specified destination language is invalid
TRANSCRIPTION_FAILED Telegram is having internal problems. Please try again later to transcribe the audio. TRANSCRIPTION_FAILED Telegram is having internal problems. Please try again later to transcribe the audio.
TTL_DAYS_INVALID The provided TTL days is invalid TTL_DAYS_INVALID The provided TTL days is invalid
TTL_MEDIA_INVALID The media does not support self-destruction TTL_MEDIA_INVALID The media does not support self-destruction
TYPES_EMPTY The types parameter is empty TYPES_EMPTY The types parameter is empty
TYPE_CONSTRUCTOR_INVALID The type constructor is invalid TYPE_CONSTRUCTOR_INVALID The type constructor is invalid
UNKNOWN_ERROR Unknown error
UNTIL_DATE_INVALID That date parameter is invalid UNTIL_DATE_INVALID That date parameter is invalid
URL_INVALID The URL provided is invalid URL_INVALID The URL provided is invalid
USAGE_LIMIT_INVALID The usage limit is invalid USAGE_LIMIT_INVALID The usage limit is invalid
@ -455,7 +339,6 @@ USERPIC_UPLOAD_REQUIRED You are required to upload a profile picture for this ac
USERS_TOO_FEW Not enough users (to create a chat, for example) USERS_TOO_FEW Not enough users (to create a chat, for example)
USERS_TOO_MUCH The maximum number of users has been exceeded (to create a chat, for example) USERS_TOO_MUCH The maximum number of users has been exceeded (to create a chat, for example)
USER_ADMIN_INVALID The action requires admin privileges. Probably you tried to edit admin privileges on someone you don't have rights to USER_ADMIN_INVALID The action requires admin privileges. Probably you tried to edit admin privileges on someone you don't have rights to
USER_ALREADY_INVITED You have already invited this user
USER_ALREADY_PARTICIPANT The user is already a participant of this chat USER_ALREADY_PARTICIPANT The user is already a participant of this chat
USER_BANNED_IN_CHANNEL You are limited from sending messages in supergroups/channels, check @SpamBot for details USER_BANNED_IN_CHANNEL You are limited from sending messages in supergroups/channels, check @SpamBot for details
USER_BLOCKED The user is blocked USER_BLOCKED The user is blocked
@ -471,17 +354,13 @@ USER_IS_BOT A bot cannot send messages to other bots or to itself
USER_KICKED This user was kicked from this chat USER_KICKED This user was kicked from this chat
USER_NOT_MUTUAL_CONTACT The user is not a mutual contact USER_NOT_MUTUAL_CONTACT The user is not a mutual contact
USER_NOT_PARTICIPANT The user is not a member of this chat USER_NOT_PARTICIPANT The user is not a member of this chat
USER_PUBLIC_MISSING The accounts username is missing
USER_VOLUME_INVALID The specified user volume is invalid
VIDEO_CONTENT_TYPE_INVALID The video content type is invalid (i.e.: not streamable) VIDEO_CONTENT_TYPE_INVALID The video content type is invalid (i.e.: not streamable)
VIDEO_FILE_INVALID The video file is invalid VIDEO_FILE_INVALID The video file is invalid
VIDEO_TITLE_EMPTY The specified video title is empty VOICE_MESSAGES_FORBIDDEN Voice messages are restricted
VOICE_MESSAGES_FORBIDDEN This user's privacy settings forbid you from sending voice messages
VOLUME_LOC_NOT_FOUND The volume location can't be found VOLUME_LOC_NOT_FOUND The volume location can't be found
WALLPAPER_FILE_INVALID The provided file cannot be used as a wallpaper WALLPAPER_FILE_INVALID The provided file cannot be used as a wallpaper
WALLPAPER_INVALID The input wallpaper was not valid WALLPAPER_INVALID The input wallpaper was not valid
WALLPAPER_MIME_INVALID The wallpaper mime type is invalid WALLPAPER_MIME_INVALID The wallpaper mime type is invalid
WALLPAPER_NOT_FOUND The specified wallpaper could not be found.
WC_CONVERT_URL_INVALID WC convert URL invalid WC_CONVERT_URL_INVALID WC convert URL invalid
WEBDOCUMENT_INVALID The web document is invalid WEBDOCUMENT_INVALID The web document is invalid
WEBDOCUMENT_MIME_INVALID The web document mime type is invalid WEBDOCUMENT_MIME_INVALID The web document mime type is invalid
@ -490,19 +369,6 @@ WEBDOCUMENT_URL_EMPTY The web document URL is empty
WEBDOCUMENT_URL_INVALID The web document URL is invalid WEBDOCUMENT_URL_INVALID The web document URL is invalid
WEBPAGE_CURL_FAILED Telegram server could not fetch the provided URL WEBPAGE_CURL_FAILED Telegram server could not fetch the provided URL
WEBPAGE_MEDIA_EMPTY The URL doesn't contain any valid media WEBPAGE_MEDIA_EMPTY The URL doesn't contain any valid media
WEBPAGE_NOT_FOUND Webpage not found
WEBPAGE_URL_INVALID Webpage url invalid
WEBPUSH_AUTH_INVALID The specified web push authentication secret is invalid
WEBPUSH_KEY_INVALID The specified web push elliptic curve Diffie-Hellman public key is invalid
WEBPUSH_TOKEN_INVALID The specified web push token is invalid
YOU_BLOCKED_USER You blocked this user YOU_BLOCKED_USER You blocked this user
STORIES_NEVER_CREATED You have never created any stories STORIES_NEVER_CREATED You have never created any stories
MEDIA_FILE_INVALID The provided media file is invalid MEDIA_FILE_INVALID The provided media file is invalid
CHANNEL_FORUM_MISSING The channel forum is missing
TTL_PERIOD_INVALID The provided TTL period is invalid
BOOSTS_REQUIRED The specified channel must first be boosted by its users in order to perform this action
BOOSTS_EMPTY You can't modify the icon of the General topic.
BOOST_NOT_MODIFIED You're already boosting the specified channel.
PAYMENT_REQUIRED The payment is required
BOOST_PEER_INVALID The specified `boost_peer` is invalid.
STARS_AMOUNT_INVALID The specified `amount` is invalid.
1 id message
2 ABOUT_TOO_LONG The provided about/bio text is too long
3 ACCESS_TOKEN_EXPIRED The bot token has expired
4 ACCESS_TOKEN_INVALID The bot access token is invalid
ADDRESS_INVALID The specified geopoint address is invalid.
5 ADMINS_TOO_MUCH The chat has too many administrators
ADMIN_ID_INVALID The specified admin ID is invalid
6 ADMIN_RANK_EMOJI_NOT_ALLOWED Emoji are not allowed in custom administrator titles
7 ADMIN_RANK_INVALID The custom administrator title is invalid or too long
ADMIN_RIGHTS_EMPTY The chatAdminRights constructor passed in keyboardButtonRequestPeer.peer_type.user_admin_rights has no rights set (i.e. flags is 0).
8 ALBUM_PHOTOS_TOO_MANY Too many photos were included in the album
9 API_ID_INVALID The api_id/api_hash combination is invalid
10 API_ID_PUBLISHED_FLOOD You are using an API key that is limited on the server side because it was published somewhere
11 ARTICLE_TITLE_EMPTY The article title is empty
AUDIO_CONTENT_URL_EMPTY The remote URL specified in the content field is empty
12 AUDIO_TITLE_EMPTY The title attribute of the audio is empty
13 AUTH_BYTES_INVALID The authorization bytes are invalid
14 AUTH_TOKEN_ALREADY_ACCEPTED The authorization token was already used
AUTH_TOKEN_EXCEPTION An error occurred while importing the auth token
15 AUTH_TOKEN_EXPIRED The provided authorization token has expired and the updated QR-code must be re-scanned
16 AUTH_TOKEN_INVALID An invalid authorization token was provided
AUTH_TOKEN_INVALID2 An invalid authorization token was provided
AUTH_TOKEN_INVALIDX The specified auth token is invalid
17 AUTOARCHIVE_NOT_AVAILABLE This feature is not yet enabled for your account due to it not receiving too many private messages from strangers
18 BANK_CARD_NUMBER_INVALID The credit card number is invalid
19 BANNED_RIGHTS_INVALID You provided a set of restrictions that is invalid
20 BASE_PORT_LOC_INVALID The base port location is invalid
BIRTHDAY_INVALID The age should be less than 150 year old in Telegram
21 BOTS_TOO_MUCH The chat has too many bots
22 BOT_CHANNELS_NA Bots can't edit admin privileges
23 BOT_COMMAND_DESCRIPTION_INVALID The command description was empty, too long or had invalid characters
BOT_COMMAND_INVALID The specified command is invalid
24 BOT_DOMAIN_INVALID The domain used for the auth button does not match the one configured in @BotFather
25 BOT_GAMES_DISABLED Bot games cannot be used in this type of chat
26 BOT_GROUPS_BLOCKED This bot can't be added to groups
27 BOT_INLINE_DISABLED The inline feature of the bot is disabled
28 BOT_INVALID This is not a valid bot
BOT_INVOICE_INVALID The provided invoice is invalid
29 BOT_METHOD_INVALID The method can't be used by bots
30 BOT_MISSING This method can only be run by a bot
31 BOT_ONESIDE_NOT_AVAIL Bots can't pin messages for one side only in private chats
33 BOT_POLLS_DISABLED Sending polls by bots has been disabled
34 BOT_RESPONSE_TIMEOUT The bot did not answer to the callback query in time
35 BOT_SCORE_NOT_MODIFIED The bot score was not modified
BROADCAST_CALLS_DISABLED Broadcast calls disabled
36 BROADCAST_ID_INVALID The channel is invalid
37 BROADCAST_PUBLIC_VOTERS_FORBIDDEN Polls with public voters cannot be sent in channels
38 BROADCAST_REQUIRED The request can only be used with a channel
BUSINESS_BOT_MISSING Business bot missing
39 BUTTON_DATA_INVALID The button callback data is invalid or too large
BUTTON_ID_INVALID The button_id parameter is invalid
BUTTON_TEXT_INVALID The specified button text is invalid
40 BUTTON_TYPE_INVALID The type of one of the buttons you provided is invalid
41 BUTTON_URL_INVALID The button url is invalid
42 BUTTON_USER_PRIVACY_RESTRICTED The privacy settings of the user specified in a keyboard button do not allow creating such button
45 CALL_PEER_INVALID The provided call peer object is invalid
46 CALL_PROTOCOL_FLAGS_INVALID Call protocol flags invalid
47 CDN_METHOD_INVALID The method can't be used on CDN DCs
CHANNELS_ADMIN_LOCATED_TOO_MUCH The user has reached the limit of public geogroups
48 CHANNELS_ADMIN_PUBLIC_TOO_MUCH You are an administrator of too many public channels
49 CHANNELS_TOO_MUCH You have joined too many channels or supergroups, leave some and try again
50 CHANNEL_ADD_INVALID Internal error.
51 CHANNEL_BANNED The channel is banned
CHANNEL_ID_INVALID The specified supergroup ID is invalid.
52 CHANNEL_INVALID The channel parameter is invalid
CHANNEL_PARICIPANT_MISSING The current user is not in the channel
53 CHANNEL_PRIVATE The channel/supergroup is not accessible
54 CHANNEL_TOO_BIG CHANNEL_TOO_LARGE The channel too big The channel is too large
CHANNEL_TOO_LARGE Channel is too large to be deleted; this error is issued when trying to delete channels with more than 1000 members (subject to change).
CHARGE_ALREADY_REFUNDED The charge id was already used for a refund.
CHARGE_NOT_FOUND The charge id was not found.
CHATLIST_EXCLUDE_INVALID The specified `exclude_peers` are invalid.
55 CHAT_ABOUT_NOT_MODIFIED The chat about text was not modified because you tried to edit it using the same content
56 CHAT_ABOUT_TOO_LONG The chat about text is too long
57 CHAT_ADMIN_REQUIRED The method requires chat admin privileges
64 CHAT_LINK_EXISTS The action failed because the supergroup is linked to a channel
65 CHAT_NOT_MODIFIED The chat settings (title, permissions, photo, etc..) were not modified because you tried to edit them using the same content
66 CHAT_RESTRICTED The chat is restricted and cannot be used
CHAT_REVOKE_DATE_UNSUPPORTED `min_date` and `max_date` are not available for using with non-user peers
67 CHAT_SEND_INLINE_FORBIDDEN You cannot use inline bots to send messages in this chat
68 CHAT_TITLE_EMPTY The chat title is empty
69 CHAT_TOO_BIG The chat is too big for this action
70 CODE_EMPTY The provided code is empty
71 CODE_HASH_INVALID The provided code hash invalid
72 CODE_INVALID The provided code is invalid (i.e. from email)
COLOR_INVALID The provided color is invalid
73 CONNECTION_API_ID_INVALID The provided API id is invalid
74 CONNECTION_APP_VERSION_EMPTY App version is empty
75 CONNECTION_DEVICE_MODEL_EMPTY The device model is empty
80 CONNECTION_SYSTEM_LANG_CODE_EMPTY The system language code is empty
81 CONTACT_ADD_MISSING Contact to add is missing
82 CONTACT_ID_INVALID The provided contact id is invalid
CONTACT_MISSING The specified user is not a contact.
83 CONTACT_NAME_EMPTY The provided contact name is empty
84 CONTACT_REQ_MISSING Missing contact request
CREATE_CALL_FAILED An error occurred while creating the call
CURRENCY_TOTAL_AMOUNT_INVALID The total amount of all prices is invalid
85 DATA_INVALID The encrypted data is invalid
86 DATA_JSON_INVALID The provided JSON data is invalid
87 DATA_TOO_LONG Data too long
91 DOCUMENT_INVALID The document is invalid
92 EMAIL_HASH_EXPIRED The email hash expired and cannot be used to verify it
93 EMAIL_INVALID The email provided is invalid
EMAIL_NOT_ALLOWED This email is not allowed
EMAIL_NOT_SETUP In order to change the login email with emailVerifyPurposeLoginChange, an existing login email must already be set using emailVerifyPurposeLoginSetup.
94 EMAIL_UNCONFIRMED Email unconfirmed
95 EMAIL_UNCONFIRMED_X The provided email isn't confirmed, {value} is the length of the verification code that was just sent to the email
96 EMAIL_VERIFY_EXPIRED The verification email has expired
EMOJI_INVALID The specified theme emoji is valid
EMOJI_MARKUP_INVALID The specified `video_emoji_markup` was invalid.
EMOJI_NOT_MODIFIED The theme wasn't changed
97 EMOTICON_EMPTY The emoticon parameter is empty
98 EMOTICON_INVALID The emoticon parameter is invalid
99 EMOTICON_STICKERPACK_MISSING The emoticon sticker pack you are trying to obtain is missing
107 ENTITY_MENTION_USER_INVALID The mentioned entity is not an user
108 ERROR_TEXT_EMPTY The provided error message is empty
109 EXPIRE_DATE_INVALID The expiration date is invalid
EXPIRE_FORBIDDEN Expire forbidden
110 EXPORT_CARD_INVALID The provided card is invalid
EXTENDED_MEDIA_AMOUNT_INVALID The maximum amount of `star_count` should be less than the `stars_paid_post_amount_max`
EXTENDED_MEDIA_PEER_INVALID The specified chat type is invalid.
EXTENDED_MEDIA_TYPE_INVALID The specified extended media type is unsupported.
111 EXTERNAL_URL_INVALID The external media URL is invalid
112 FIELD_NAME_EMPTY The field with the name FIELD_NAME is missing
113 FIELD_NAME_INVALID The field with the name FIELD_NAME is invalid
FILE_CONTENT_TYPE_INVALID File content-type is invalid
FILE_EMTPY An empty file was provided
114 FILE_ID_INVALID The file id is invalid
115 FILE_MIGRATE_X The file is in Data Center No. {value}
116 FILE_PARTS_INVALID Invalid number of parts.
FILE_PART_0_MISSING File part 0 missing
117 FILE_PART_EMPTY The file part sent is empty
118 FILE_PART_INVALID The file part number is invalid.
119 FILE_PART_LENGTH_INVALID The length of a file part is invalid
124 FILE_REFERENCE_EMPTY The file id contains an empty file reference, you must obtain a valid one by fetching the message from the origin context
125 FILE_REFERENCE_EXPIRED The file id contains an expired file reference, you must obtain a valid one by fetching the message from the origin context
126 FILE_REFERENCE_INVALID The file id contains an invalid file reference, you must obtain a valid one by fetching the message from the origin context
FILE_TITLE_EMPTY An empty file title was specified
127 FILTER_ID_INVALID The specified filter ID is invalid
FILTER_INCLUDE_EMPTY The filter include is empty
FILTER_NOT_SUPPORTED The specified filter cannot be used in this context
FILTER_TITLE_EMPTY The title field of the filter is empty
128 FIRSTNAME_INVALID The first name is invalid
129 FOLDER_ID_EMPTY The folder you tried to delete was already empty
130 FOLDER_ID_INVALID The folder id is invalid
FORM_ID_EXPIRED The specified id has expired.
FORUM_ENABLED You can't execute the specified action because the group is a [forum](https://core.telegram.org/api/forum), disable forum functionality to continue.
131 FRESH_CHANGE_ADMINS_FORBIDDEN You can't change administrator settings in this chat because your session was logged-in recently
132 FROM_MESSAGE_BOT_DISABLED Bots can't use fromMessage min constructors
133 FROM_PEER_INVALID The from peer value is invalid
134 GAME_BOT_INVALID You cannot send that game with the current bot
GENERAL_MODIFY_ICON_FORBIDDEN You can't modify the icon of the General topic.
135 GEO_POINT_INVALID Invalid geo point provided
136 GIF_CONTENT_TYPE_INVALID GIF content-type invalid
137 GIF_ID_INVALID The provided gif/animation id is invalid
GIFT_SLUG_INVALID The specified slug is invalid.
GIFT_SLUG_EXPIRED The gift slug is expired
GRAPH_EXPIRED_RELOAD This graph has expired, please obtain a new graph token
138 GRAPH_INVALID_RELOAD Invalid graph token provided, please reload the stats and provide the updated token
139 GRAPH_OUTDATED_RELOAD The graph data is outdated
GROUPCALL_ALREADY_DISCARDED The group call was already discarded
GROUPCALL_INVALID The specified group call is invalid
GROUPCALL_JOIN_MISSING You haven't joined this group call
GROUPCALL_NOT_MODIFIED Group call settings weren't modified
140 GROUPCALL_SSRC_DUPLICATE_MUCH Too many group call synchronization source duplicates
141 GROUPED_MEDIA_INVALID The album contains invalid media
142 GROUP_CALL_INVALID The group call is invalid
143 HASH_INVALID The provided hash is invalid
HIDE_REQUESTER_MISSING The join request was missing or was already handled
144 IMAGE_PROCESS_FAILED The server failed to process your image
145 IMPORT_FILE_INVALID The imported file is invalid
146 IMPORT_FORMAT_UNRECOGNIZED The imported format is unrecognized
153 INPUT_LAYER_INVALID The provided layer is invalid
154 INPUT_METHOD_INVALID The method invoked is invalid in the current schema
155 INPUT_REQUEST_TOO_LONG The input request is too long
INPUT_TEXT_EMPTY The specified text is empty
INPUT_TEXT_TOO_LONG The specified text is too long.
156 INPUT_USER_DEACTIVATED The target user has been deleted/deactivated
INVITES_TOO_MUCH The maximum number of per-folder invites specified by the `chatlist_invites_limit_default`/`chatlist_invites_limit_premium` was reached.
INVITE_FORBIDDEN_WITH_JOINAS If the user has anonymously joined a group call as a channel, they can't invite other users to the group call because that would cause deanonymization, because the invite would be sent using the original user ID, not the anonymized channel ID
157 INVITE_HASH_EMPTY The invite hash is empty
158 INVITE_HASH_EXPIRED The chat invite link is no longer valid
159 INVITE_HASH_INVALID The invite link hash is invalid
160 INVITE_REQUEST_SENT The request to join this chat or channel has been successfully sent
161 INVITE_REVOKED_MISSING The action required a chat invite link to be revoked first
INVITE_SLUG_EMPTY The invite slug is empty
INVITE_SLUG_EXPIRED The invite slug is expired
INVOICE_PAYLOAD_INVALID The specified invoice payload is invalid
JOIN_AS_PEER_INVALID The specified peer cannot be used to join a group call
LANG_CODE_INVALID The specified language code is invalid
LANG_CODE_NOT_SUPPORTED The specified language code is not supported
162 LANG_PACK_INVALID The provided language pack is invalid
163 LASTNAME_INVALID The last name is invalid
164 LIMIT_INVALID The limit parameter is invalid
165 LINK_NOT_MODIFIED The chat link was not modified because you tried to link to the same target
166 LOCATION_INVALID The file location is invalid
MAX_DATE_INVALID The specified maximum date is invalid
167 MAX_ID_INVALID The max_id parameter is invalid
168 MAX_QTS_INVALID The provided QTS is invalid
169 MD5_CHECKSUM_INVALID The file's checksum did not match the md5_checksum parameter
170 MEDIA_CAPTION_TOO_LONG The media caption is too long
171 MEDIA_EMPTY The media you tried to send is invalid
172 MEDIA_FILE_INVALID The provided media file is invalid The media file is invalid
MEDIA_GROUPED_INVALID You tried to send media of different types in an album
173 MEDIA_INVALID The media is invalid
174 MEDIA_NEW_INVALID The new media to edit the message with is invalid
175 MEDIA_PREV_INVALID The previous media cannot be edited with anything else
186 MESSAGE_POLL_CLOSED You can't interact with a closed poll
187 MESSAGE_TOO_LONG The message text is too long
188 METHOD_INVALID The API method is invalid and cannot be used
MIN_DATE_INVALID The specified minimum date is invalid
189 MSG_ID_INVALID The message ID used in the peer was invalid
MSG_TOO_OLD chat_read_mark_expire_period have passed since the message was sent, read receipts were deleted
190 MSG_VOICE_MISSING The message does not contain a voice message
191 MSG_WAIT_FAILED A waiting call returned an error
192 MULTI_MEDIA_TOO_LONG The album/media group contains too many items
193 NEW_SALT_INVALID The new salt is invalid
NEW_SETTINGS_EMPTY No password is set on the current account, and no new password was specified in `new_settings`
194 NEW_SETTINGS_INVALID The new settings are invalid
NOGENERAL_HIDE_FORBIDDEN The hidden parameter is only valid for the General topic message_thread_id=1
195 NEXT_OFFSET_INVALID The next offset value is invalid
196 OFFSET_INVALID The offset parameter is invalid
197 OFFSET_PEER_ID_INVALID The provided offset peer is invalid
201 PACK_SHORT_NAME_OCCUPIED A sticker pack with this name already exists
202 PACK_TITLE_INVALID The sticker pack title is invalid
203 PARTICIPANTS_TOO_FEW The chat doesn't have enough participants
PARTICIPANT_ID_INVALID The specified participant ID is invalid
PARTICIPANT_JOIN_MISSING Trying to enable a presentation, when the user hasn't joined the Video Chat with phone.joinGroupCall
204 PARTICIPANT_VERSION_OUTDATED The other participant is using an outdated Telegram app version
205 PASSWORD_EMPTY The password provided is empty
206 PASSWORD_HASH_INVALID The two-step verification password is invalid
210 PASSWORD_TOO_FRESH_X The two-step verification password was added recently and you are required to wait {value} seconds
211 PAYMENT_PROVIDER_INVALID The payment provider was not recognised or its token was invalid
212 PEER_FLOOD The method can't be used because your account is currently limited
PEER_HISTORY_EMPTY Peer history empty
213 PEER_ID_INVALID The peer id being used is invalid or not known yet. Make sure you meet the peer before interacting with it
214 PEER_ID_NOT_SUPPORTED The provided peer id is not supported
215 PERSISTENT_TIMESTAMP_EMPTY The pts argument is empty
218 PHONE_CODE_EXPIRED The confirmation code has expired
219 PHONE_CODE_HASH_EMPTY The phone code hash is missing
220 PHONE_CODE_INVALID The confirmation code is invalid
PHONE_HASH_EXPIRED An invalid or expired phone_code_hash was provided
PHONE_NOT_OCCUPIED No user is associated to the specified phone number
221 PHONE_NUMBER_APP_SIGNUP_FORBIDDEN You can't sign up using this app
222 PHONE_NUMBER_BANNED The phone number is banned from Telegram and cannot be used
223 PHONE_NUMBER_FLOOD This number has tried to login too many times
238 PHOTO_THUMB_URL_EMPTY The photo thumb URL is empty
239 PHOTO_THUMB_URL_INVALID The photo thumb URL is invalid
240 PINNED_DIALOGS_TOO_MUCH Too many pinned dialogs
PINNED_TOPIC_NOT_MODIFIED The pinned topic was not modified.
241 PIN_RESTRICTED You can't pin messages in private chats with other people
242 POLL_ANSWERS_INVALID The poll answers are invalid
POLL_ANSWER_INVALID One of the poll answers is not acceptable
243 POLL_OPTION_DUPLICATE A duplicate option was sent in the same poll
244 POLL_OPTION_INVALID A poll option used invalid data (the data may be too long)
245 POLL_QUESTION_INVALID The poll question is invalid
246 POLL_UNSUPPORTED This layer does not support polls in the invoked method
247 POLL_VOTE_REQUIRED Cast a vote in the poll before calling this method
248 PREMIUM_ACCOUNT_REQUIRED The method requires a premium user account
PREMIUM_GIFTCODE_WAS_REFUNDED This gift code can't be redeemed because the giveaway organizer requested a refund
PRICING_CHAT_INVALID This chat chat doesn't support subscription link.
249 PRIVACY_KEY_INVALID The privacy key is invalid
250 PRIVACY_TOO_LONG Your privacy exception list has exceeded the maximum capacity
251 PRIVACY_VALUE_INVALID The privacy value is invalid
PUBLIC_KEY_REQUIRED A public key is required
252 QUERY_ID_EMPTY The query ID is empty
253 QUERY_ID_INVALID The callback query id is invalid
254 QUERY_TOO_SHORT The query is too short
QUIZ_ANSWER_MISSING You can forward a quiz while hiding the original author only after choosing an option in the quiz
255 QUIZ_CORRECT_ANSWERS_EMPTY The correct answers of the quiz are empty
256 QUIZ_CORRECT_ANSWERS_TOO_MUCH The quiz contains too many correct answers
257 QUIZ_CORRECT_ANSWER_INVALID The correct answers of the quiz are invalid
267 REPLY_MARKUP_GAME_EMPTY The provided reply markup for the game is empty
268 REPLY_MARKUP_INVALID The provided reply markup is invalid
269 REPLY_MARKUP_TOO_LONG The reply markup is too long
REPLY_MESSAGE_ID_INVALID The reply message id is invalid
RESET_REQUEST_MISSING No password reset is in progress
270 RESULTS_TOO_MUCH The result contains too many items
271 RESULT_ID_DUPLICATE The result contains items with duplicated identifiers
272 RESULT_ID_EMPTY Result ID empty
273 RESULT_ID_INVALID The given result cannot be used to send the selection to the bot
REACTIONS_TOO_MANY Currently, non-premium users, can set up to one reaction per message
274 RESULT_TYPE_INVALID The result type is invalid
275 REVOTE_NOT_ALLOWED You cannot change your vote
RIGHTS_NOT_MODIFIED The new admin rights are equal to the old rights, no change was made
276 RSA_DECRYPT_FAILED Internal RSA decryption failed
277 SCHEDULE_BOT_NOT_ALLOWED Bots are not allowed to schedule messages
278 SCHEDULE_DATE_INVALID Invalid schedule date provided
279 SCHEDULE_DATE_TOO_LATE The date you tried to schedule is too far in the future (more than one year)
280 SCHEDULE_STATUS_PRIVATE You cannot schedule a message until the person comes online if their privacy does not show this information
281 SCHEDULE_TOO_MUCH You tried to schedule too many messages in this chat
SCORE_INVALID The specified game score is invalid
282 SEARCH_QUERY_EMPTY The search query is empty
SEARCH_WITH_LINK_NOT_SUPPORTED You cannot provide a search query and an invite link at the same time
283 SECONDS_INVALID The seconds interval is invalid
SEND_AS_PEER_INVALID You can't send messages as the specified peer
284 SEND_MESSAGE_MEDIA_INVALID The message media is invalid
285 SEND_MESSAGE_TYPE_INVALID The message type is invalid
286 SESSION_TOO_FRESH_X You can't do this action because the current session was logged-in recently
287 SETTINGS_INVALID Invalid settings were provided
288 SHA256_HASH_INVALID The provided SHA256 hash is invalid
289 SHORTNAME_OCCUPY_FAILED An error occurred when trying to register the short-name used for the sticker pack. Try a different name
SHORT_NAME_INVALID The specified short name is invalid
SHORT_NAME_OCCUPIED The specified short name is already in use
290 SLOWMODE_MULTI_MSGS_DISABLED Slowmode is enabled, you cannot forward multiple messages to this group
291 SMS_CODE_CREATE_FAILED An error occurred while creating the SMS code
292 SRP_ID_INVALID Invalid SRP ID provided
293 SRP_PASSWORD_CHANGED The password has changed
STARGIFT_ALREADY_CONVERTED The provided star gift already converted to stars
STARGIFT_ALREADY_UPGRADED This star gift was already upgraded before
STARGIFT_USAGE_LIMITED The star gift usage is limited
294 START_PARAM_EMPTY The start parameter is empty
295 START_PARAM_INVALID The start parameter is invalid
296 START_PARAM_TOO_LONG The start parameter is too long
STICKERPACK_STICKERS_TOO_MUCH There are too many stickers in this stickerpack, you can't add any more
297 STICKERSET_INVALID The requested sticker set is invalid
298 STICKERSET_NOT_MODIFIED The sticker set is not modified
299 STICKERS_EMPTY The sticker provided is empty
301 STICKER_DOCUMENT_INVALID The sticker document is invalid
302 STICKER_EMOJI_INVALID The sticker emoji is invalid
303 STICKER_FILE_INVALID The sticker file is invalid
STICKER_GIF_DIMENSIONS The specified video sticker has invalid dimensions
304 STICKER_ID_INVALID The provided sticker id is invalid
305 STICKER_INVALID The provided sticker is invalid
STICKER_MIME_INVALID Make sure to pass a valid image file for the right InputFile parameter
306 STICKER_PNG_DIMENSIONS The sticker png dimensions are invalid
307 STICKER_PNG_NOPNG Stickers must be png files but the provided image was not a png
STICKER_TGS_NODOC You must send the animated sticker as a document
308 STICKER_TGS_NOTGS A tgs sticker file was expected, but something else was provided
309 STICKER_THUMB_PNG_NOPNG A png sticker thumbnail file was expected, but something else was provided
STICKER_VIDEO_BIG The specified video sticker is too big
STICKER_VIDEO_NODOC You must send the video sticker as a document
310 STICKER_VIDEO_NOWEBM A webm video file was expected, but something else was provided
STORY_ID_EMPTY You specified no story IDs.
STORY_ID_INVALID The specified story ID is invalid.
STORY_NOT_MODIFIED The new story information you passed is equal to the previous story information, thus it wasn't modified.
STORY_PERIOD_INVALID The specified story period is invalid for this account.
311 STORIES_TOO_MUCH Too many stories in the current account
STORY_SEND_FLOOD_WEEKLY_X You've hit the weekly story limit, wait for the specified number of seconds before posting a new story.
STORY_SEND_FLOOD_MONTHLY_X You've hit the monthly story limit, wait for the specified number of seconds before posting a new story.
STORY_PERIOD_INVALID The story period is invalid
SUBSCRIPTION_PERIOD_INVALID The subscription period is invalid.
SWITCH_PM_TEXT_EMPTY The switch_pm.text field was empty
312 TAKEOUT_INVALID The takeout id is invalid
313 TAKEOUT_REQUIRED The method must be invoked inside a takeout session
TEMP_AUTH_KEY_ALREADY_BOUND The passed temporary key is already bound to another perm_auth_key_id
314 TEMP_AUTH_KEY_EMPTY The temporary auth key provided is empty
315 THEME_FILE_INVALID Invalid theme file provided
316 THEME_FORMAT_INVALID Invalid theme format provided
317 THEME_INVALID Invalid theme provided
318 THEME_MIME_INVALID You cannot create this theme because the mime-type is invalid
THEME_TITLE_INVALID The specified theme title is invalid
TITLE_INVALID The specified stickerpack title is invalid
319 TMP_PASSWORD_DISABLED The temporary password is disabled
320 TMP_PASSWORD_INVALID The temporary password is invalid
321 TOKEN_INVALID The provided token is invalid
322 TOPIC_CLOSED The topic was closed
323 TOPIC_DELETED The topic was deleted
TOPIC_CLOSE_SEPARATELY The close flag cannot be provided together with any of the other flags.
TOPIC_HIDE_SEPARATELY The hide flag cannot be provided together with any of the other flags.
TOPIC_ID_INVALID The provided topic ID is invalid
324 TOPIC_NOT_MODIFIED The topic was not modified
TOPIC_TITLE_EMPTY The specified topic title is empty.
TO_LANG_INVALID The specified destination language is invalid
325 TRANSCRIPTION_FAILED Telegram is having internal problems. Please try again later to transcribe the audio.
326 TTL_DAYS_INVALID The provided TTL days is invalid
327 TTL_MEDIA_INVALID The media does not support self-destruction
328 TYPES_EMPTY The types parameter is empty
329 TYPE_CONSTRUCTOR_INVALID The type constructor is invalid
UNKNOWN_ERROR Unknown error
330 UNTIL_DATE_INVALID That date parameter is invalid
331 URL_INVALID The URL provided is invalid
332 USAGE_LIMIT_INVALID The usage limit is invalid
339 USERS_TOO_FEW Not enough users (to create a chat, for example)
340 USERS_TOO_MUCH The maximum number of users has been exceeded (to create a chat, for example)
341 USER_ADMIN_INVALID The action requires admin privileges. Probably you tried to edit admin privileges on someone you don't have rights to
USER_ALREADY_INVITED You have already invited this user
342 USER_ALREADY_PARTICIPANT The user is already a participant of this chat
343 USER_BANNED_IN_CHANNEL You are limited from sending messages in supergroups/channels, check @SpamBot for details
344 USER_BLOCKED The user is blocked
354 USER_KICKED This user was kicked from this chat
355 USER_NOT_MUTUAL_CONTACT The user is not a mutual contact
356 USER_NOT_PARTICIPANT The user is not a member of this chat
USER_PUBLIC_MISSING The accounts username is missing
USER_VOLUME_INVALID The specified user volume is invalid
357 VIDEO_CONTENT_TYPE_INVALID The video content type is invalid (i.e.: not streamable)
358 VIDEO_FILE_INVALID The video file is invalid
359 VIDEO_TITLE_EMPTY VOICE_MESSAGES_FORBIDDEN The specified video title is empty Voice messages are restricted
VOICE_MESSAGES_FORBIDDEN This user's privacy settings forbid you from sending voice messages
360 VOLUME_LOC_NOT_FOUND The volume location can't be found
361 WALLPAPER_FILE_INVALID The provided file cannot be used as a wallpaper
362 WALLPAPER_INVALID The input wallpaper was not valid
363 WALLPAPER_MIME_INVALID The wallpaper mime type is invalid
WALLPAPER_NOT_FOUND The specified wallpaper could not be found.
364 WC_CONVERT_URL_INVALID WC convert URL invalid
365 WEBDOCUMENT_INVALID The web document is invalid
366 WEBDOCUMENT_MIME_INVALID The web document mime type is invalid
369 WEBDOCUMENT_URL_INVALID The web document URL is invalid
370 WEBPAGE_CURL_FAILED Telegram server could not fetch the provided URL
371 WEBPAGE_MEDIA_EMPTY The URL doesn't contain any valid media
WEBPAGE_NOT_FOUND Webpage not found
WEBPAGE_URL_INVALID Webpage url invalid
WEBPUSH_AUTH_INVALID The specified web push authentication secret is invalid
WEBPUSH_KEY_INVALID The specified web push elliptic curve Diffie-Hellman public key is invalid
WEBPUSH_TOKEN_INVALID The specified web push token is invalid
372 YOU_BLOCKED_USER You blocked this user
373 STORIES_NEVER_CREATED You have never created any stories
374 MEDIA_FILE_INVALID The provided media file is invalid
CHANNEL_FORUM_MISSING The channel forum is missing
TTL_PERIOD_INVALID The provided TTL period is invalid
BOOSTS_REQUIRED The specified channel must first be boosted by its users in order to perform this action
BOOSTS_EMPTY You can't modify the icon of the General topic.
BOOST_NOT_MODIFIED You're already boosting the specified channel.
PAYMENT_REQUIRED The payment is required
BOOST_PEER_INVALID The specified `boost_peer` is invalid.
STARS_AMOUNT_INVALID The specified `amount` is invalid.

View file

@ -4,24 +4,17 @@ CHANNEL_PUBLIC_GROUP_NA The channel/supergroup is not available
CHAT_ADMIN_INVITE_REQUIRED You don't have rights to invite other users CHAT_ADMIN_INVITE_REQUIRED You don't have rights to invite other users
CHAT_ADMIN_REQUIRED The method requires chat admin privileges CHAT_ADMIN_REQUIRED The method requires chat admin privileges
CHAT_FORBIDDEN You cannot write in this chat CHAT_FORBIDDEN You cannot write in this chat
CHAT_GUEST_SEND_FORBIDDEN You need to join the discussion group before commentingr
EDIT_BOT_INVITE_FORBIDDEN Bots' chat invite links can't be edited EDIT_BOT_INVITE_FORBIDDEN Bots' chat invite links can't be edited
INLINE_BOT_REQUIRED The action must be performed through an inline bot callback INLINE_BOT_REQUIRED The action must be performed through an inline bot callback
MESSAGE_AUTHOR_REQUIRED You are not the author of this message MESSAGE_AUTHOR_REQUIRED You are not the author of this message
MESSAGE_DELETE_FORBIDDEN You don't have rights to delete messages in this chat, most likely because you are not the author of them MESSAGE_DELETE_FORBIDDEN You don't have rights to delete messages in this chat, most likely because you are not the author of them
NOT_ALLOWED Not allowed
NOT_ELIGIBLE You are not eligible for this action
PARTICIPANT_JOIN_MISSING Trying to enable a presentation, when the user hasn't joined the Video Chat with phone.joinGroupCall
POLL_VOTE_REQUIRED Cast a vote in the poll before calling this method POLL_VOTE_REQUIRED Cast a vote in the poll before calling this method
PREMIUM_ACCOUNT_REQUIRED This action requires a premium account PREMIUM_ACCOUNT_REQUIRED This action requires a premium account
PRIVACY_PREMIUM_REQUIRED The user has restricted from sending messages OR This action requires a premium account
PUBLIC_CHANNEL_MISSING You can only export group call invite links for public chats or channels
RIGHT_FORBIDDEN You don't have enough rights for this action, or you tried to set one or more admin rights that can't be applied to this kind of chat (channel or supergroup) RIGHT_FORBIDDEN You don't have enough rights for this action, or you tried to set one or more admin rights that can't be applied to this kind of chat (channel or supergroup)
SENSITIVE_CHANGE_FORBIDDEN Your sensitive content settings can't be changed at this time SENSITIVE_CHANGE_FORBIDDEN Your sensitive content settings can't be changed at this time
TAKEOUT_REQUIRED The method must be invoked inside a takeout session TAKEOUT_REQUIRED The method must be invoked inside a takeout session
USER_BOT_INVALID This method can only be called by a bot USER_BOT_INVALID This method can only be called by a bot
USER_CHANNELS_TOO_MUCH One of the users you tried to add is already in too many channels/supergroups USER_CHANNELS_TOO_MUCH One of the users you tried to add is already in too many channels/supergroups
USER_DELETED You can't send this secret message because the other participant deleted their account
USER_INVALID The provided user is invalid USER_INVALID The provided user is invalid
USER_IS_BLOCKED The user is blocked USER_IS_BLOCKED The user is blocked
USER_NOT_MUTUAL_CONTACT The provided user is not a mutual contact USER_NOT_MUTUAL_CONTACT The provided user is not a mutual contact
@ -40,8 +33,5 @@ CHAT_SEND_STICKERS_FORBIDDEN You can't send stickers in this chat
CHAT_SEND_VIDEOS_FORBIDDEN You can't send videos in this chat CHAT_SEND_VIDEOS_FORBIDDEN You can't send videos in this chat
CHAT_SEND_VOICES_FORBIDDEN You can't send voice recordings in this chat CHAT_SEND_VOICES_FORBIDDEN You can't send voice recordings in this chat
CHAT_WRITE_FORBIDDEN You can't write in this chat CHAT_WRITE_FORBIDDEN You can't write in this chat
GROUPCALL_ALREADY_STARTED The groupcall has already started, you can join directly using phone.joinGroupCall
GROUPCALL_FORBIDDEN The group call has already ended GROUPCALL_FORBIDDEN The group call has already ended
LIVE_DISABLED Story is disabled server-side LIVE_DISABLED Story is disabled server-side
CHAT_GUEST_SEND_FORBIDDEN You need to join the discussion group before commenting
ALLOW_PAYMENT_REQUIRED_X Payment of {value} stars is required to perform this action
1 id message
4 CHAT_ADMIN_INVITE_REQUIRED You don't have rights to invite other users
5 CHAT_ADMIN_REQUIRED The method requires chat admin privileges
6 CHAT_FORBIDDEN You cannot write in this chat
CHAT_GUEST_SEND_FORBIDDEN You need to join the discussion group before commentingr
7 EDIT_BOT_INVITE_FORBIDDEN Bots' chat invite links can't be edited
8 INLINE_BOT_REQUIRED The action must be performed through an inline bot callback
9 MESSAGE_AUTHOR_REQUIRED You are not the author of this message
10 MESSAGE_DELETE_FORBIDDEN You don't have rights to delete messages in this chat, most likely because you are not the author of them
NOT_ALLOWED Not allowed
NOT_ELIGIBLE You are not eligible for this action
PARTICIPANT_JOIN_MISSING Trying to enable a presentation, when the user hasn't joined the Video Chat with phone.joinGroupCall
11 POLL_VOTE_REQUIRED Cast a vote in the poll before calling this method
12 PREMIUM_ACCOUNT_REQUIRED This action requires a premium account
PRIVACY_PREMIUM_REQUIRED The user has restricted from sending messages OR This action requires a premium account
PUBLIC_CHANNEL_MISSING You can only export group call invite links for public chats or channels
13 RIGHT_FORBIDDEN You don't have enough rights for this action, or you tried to set one or more admin rights that can't be applied to this kind of chat (channel or supergroup)
14 SENSITIVE_CHANGE_FORBIDDEN Your sensitive content settings can't be changed at this time
15 TAKEOUT_REQUIRED The method must be invoked inside a takeout session
16 USER_BOT_INVALID This method can only be called by a bot
17 USER_CHANNELS_TOO_MUCH One of the users you tried to add is already in too many channels/supergroups
USER_DELETED You can't send this secret message because the other participant deleted their account
18 USER_INVALID The provided user is invalid
19 USER_IS_BLOCKED The user is blocked
20 USER_NOT_MUTUAL_CONTACT The provided user is not a mutual contact
33 CHAT_SEND_VIDEOS_FORBIDDEN You can't send videos in this chat
34 CHAT_SEND_VOICES_FORBIDDEN You can't send voice recordings in this chat
35 CHAT_WRITE_FORBIDDEN You can't write in this chat
GROUPCALL_ALREADY_STARTED The groupcall has already started, you can join directly using phone.joinGroupCall
36 GROUPCALL_FORBIDDEN The group call has already ended
37 LIVE_DISABLED Story is disabled server-side
CHAT_GUEST_SEND_FORBIDDEN You need to join the discussion group before commenting
ALLOW_PAYMENT_REQUIRED_X Payment of {value} stars is required to perform this action

View file

@ -1,23 +1,13 @@
id message id message
AUTH_KEY_DUPLICATED The same authorization key (session file) was used in more than one place simultaneously. You must delete your session file and log in again with your phone number or bot token AUTH_KEY_DUPLICATED The same authorization key (session file) was used in more than one place simultaneously. You must delete your session file and log in again with your phone number or bot token
CHANNEL_PRIVATE The channel/supergroup is not accessible CHANNEL_PRIVATE The channel/supergroup is not accessible
CHANNEL_TOO_LARGE Сhannel is too large to be deleted. Contact support for removal
CHAT_FORWARDS_RESTRICTED You can't forward messages from a protected chat
FILEREF_UPGRADE_NEEDED The file reference has expired and you must use a refreshed one by obtaining the original media message FILEREF_UPGRADE_NEEDED The file reference has expired and you must use a refreshed one by obtaining the original media message
FRESH_CHANGE_ADMINS_FORBIDDEN You were just elected admin, you can't add or modify other admins yet FRESH_CHANGE_ADMINS_FORBIDDEN You were just elected admin, you can't add or modify other admins yet
FRESH_CHANGE_PHONE_FORBIDDEN You can't change your phone number because your session was logged-in recently FRESH_CHANGE_PHONE_FORBIDDEN You can't change your phone number because your session was logged-in recently
FRESH_RESET_AUTHORISATION_FORBIDDEN You can't terminate other authorized sessions because the current was logged-in recently FRESH_RESET_AUTHORISATION_FORBIDDEN You can't terminate other authorized sessions because the current was logged-in recently
GIFTCODE_NOT_ALLOWED Giftcode not allowed
INVITE_HASH_EXPIRED The chat the user tried to join has expired and is not valid anymore
PHONE_NUMBER_INVALID The phone number is invalid PHONE_NUMBER_INVALID The phone number is invalid
PHONE_PASSWORD_FLOOD You have tried to log-in too many times PHONE_PASSWORD_FLOOD You have tried to log-in too many times
PREMIUM_CURRENTLY_UNAVAILABLE Premium currently unavailable
PREVIOUS_CHAT_IMPORT_ACTIVE_WAIT_XMIN Similar to a flood wait, must wait {value} minutes
SEND_CODE_UNAVAILABLE Returned when all available options for this type of number were already used (e.g. flash-call, then SMS, then this error might be returned to trigger a second resend)
PREMIUM_GIFTCODE_WAS_REFUNDED This gift code can't be redeemed because the giveaway organizer requested a refund
STICKERSET_INVALID The sticker set is invalid STICKERSET_INVALID The sticker set is invalid
STICKERSET_OWNER_ANONYMOUS This sticker set can't be used as the group's sticker set because it was created by one of its anonymous admins STICKERSET_OWNER_ANONYMOUS This sticker set can't be used as the group's sticker set because it was created by one of its anonymous admins
UPDATE_APP_TO_LOGIN Update app to login
USERPIC_PRIVACY_REQUIRED You need to disable privacy settings for your profile picture in order to make your geolocation public
USERPIC_UPLOAD_REQUIRED You must have a profile picture to publish your geolocation USERPIC_UPLOAD_REQUIRED You must have a profile picture to publish your geolocation
USER_RESTRICTED You are limited/restricted. You can't perform this action USER_RESTRICTED You are limited/restricted. You can't perform this action
1 id message
2 AUTH_KEY_DUPLICATED The same authorization key (session file) was used in more than one place simultaneously. You must delete your session file and log in again with your phone number or bot token
3 CHANNEL_PRIVATE The channel/supergroup is not accessible
CHANNEL_TOO_LARGE Сhannel is too large to be deleted. Contact support for removal
CHAT_FORWARDS_RESTRICTED You can't forward messages from a protected chat
4 FILEREF_UPGRADE_NEEDED The file reference has expired and you must use a refreshed one by obtaining the original media message
5 FRESH_CHANGE_ADMINS_FORBIDDEN You were just elected admin, you can't add or modify other admins yet
6 FRESH_CHANGE_PHONE_FORBIDDEN You can't change your phone number because your session was logged-in recently
7 FRESH_RESET_AUTHORISATION_FORBIDDEN You can't terminate other authorized sessions because the current was logged-in recently
GIFTCODE_NOT_ALLOWED Giftcode not allowed
INVITE_HASH_EXPIRED The chat the user tried to join has expired and is not valid anymore
8 PHONE_NUMBER_INVALID The phone number is invalid
9 PHONE_PASSWORD_FLOOD You have tried to log-in too many times
PREMIUM_CURRENTLY_UNAVAILABLE Premium currently unavailable
PREVIOUS_CHAT_IMPORT_ACTIVE_WAIT_XMIN Similar to a flood wait, must wait {value} minutes
SEND_CODE_UNAVAILABLE Returned when all available options for this type of number were already used (e.g. flash-call, then SMS, then this error might be returned to trigger a second resend)
PREMIUM_GIFTCODE_WAS_REFUNDED This gift code can't be redeemed because the giveaway organizer requested a refund
10 STICKERSET_INVALID The sticker set is invalid
11 STICKERSET_OWNER_ANONYMOUS This sticker set can't be used as the group's sticker set because it was created by one of its anonymous admins
UPDATE_APP_TO_LOGIN Update app to login
USERPIC_PRIVACY_REQUIRED You need to disable privacy settings for your profile picture in order to make your geolocation public
12 USERPIC_UPLOAD_REQUIRED You must have a profile picture to publish your geolocation
13 USER_RESTRICTED You are limited/restricted. You can't perform this action

View file

@ -2,8 +2,5 @@ id message
2FA_CONFIRM_WAIT_X A wait of {value} seconds is required because this account is active and protected by a 2FA password 2FA_CONFIRM_WAIT_X A wait of {value} seconds is required because this account is active and protected by a 2FA password
FLOOD_TEST_PHONE_WAIT_X A wait of {value} seconds is required in the test servers FLOOD_TEST_PHONE_WAIT_X A wait of {value} seconds is required in the test servers
FLOOD_WAIT_X A wait of {value} seconds is required FLOOD_WAIT_X A wait of {value} seconds is required
FLOOD_PREMIUM_WAIT_X A wait of {value} seconds is required SLOWMODE_WAIT_X A wait of {value} seconds is required to send messages in this chat.
PREMIUM_SUB_ACTIVE_UNTIL_X A wait of {value} seconds is required
SLOWMODE_WAIT_X A wait of {value} seconds is required to send messages in this chat
STORY_SEND_FLOOD_X A wait of {value} seconds is required to continue posting stories
TAKEOUT_INIT_DELAY_X You have to confirm the data export request using one of your mobile devices or wait {value} seconds TAKEOUT_INIT_DELAY_X You have to confirm the data export request using one of your mobile devices or wait {value} seconds
1 id message
2 2FA_CONFIRM_WAIT_X A wait of {value} seconds is required because this account is active and protected by a 2FA password
3 FLOOD_TEST_PHONE_WAIT_X A wait of {value} seconds is required in the test servers
4 FLOOD_WAIT_X A wait of {value} seconds is required
5 FLOOD_PREMIUM_WAIT_X SLOWMODE_WAIT_X A wait of {value} seconds is required A wait of {value} seconds is required to send messages in this chat.
PREMIUM_SUB_ACTIVE_UNTIL_X A wait of {value} seconds is required
SLOWMODE_WAIT_X A wait of {value} seconds is required to send messages in this chat
STORY_SEND_FLOOD_X A wait of {value} seconds is required to continue posting stories
6 TAKEOUT_INIT_DELAY_X You have to confirm the data export request using one of your mobile devices or wait {value} seconds

View file

@ -38,11 +38,9 @@ RPC_MCGET_FAIL Telegram is having internal problems. Please try again later
SIGN_IN_FAILED Failure while signing in due to Telegram having internal problems. Please try again later SIGN_IN_FAILED Failure while signing in due to Telegram having internal problems. Please try again later
STORAGE_CHECK_FAILED Server storage check failed due to Telegram having internal problems. Please try again later STORAGE_CHECK_FAILED Server storage check failed due to Telegram having internal problems. Please try again later
STORE_INVALID_SCALAR_TYPE Telegram is having internal problems. Please try again later STORE_INVALID_SCALAR_TYPE Telegram is having internal problems. Please try again later
TIMEOUT A timeout occurred while fetching data from the worker
UNKNOWN_METHOD The method you tried to call cannot be called on non-CDN DCs UNKNOWN_METHOD The method you tried to call cannot be called on non-CDN DCs
UPLOAD_NO_VOLUME Telegram is having internal problems. Please try again later UPLOAD_NO_VOLUME Telegram is having internal problems. Please try again later
VOLUME_LOC_NOT_FOUND Telegram is having internal problems. Please try again later VOLUME_LOC_NOT_FOUND Telegram is having internal problems. Please try again later
WORKER_BUSY_TOO_LONG_RETRY Server workers are too busy right now due to Telegram having internal problems. Please try again later WORKER_BUSY_TOO_LONG_RETRY Server workers are too busy right now due to Telegram having internal problems. Please try again later
WP_ID_GENERATE_FAILED Telegram is having internal problems. Please try again later WP_ID_GENERATE_FAILED Telegram is having internal problems. Please try again later
FILE_WRITE_FAILED Telegram is having internal problems. Please try again later FILE_WRITE_FAILED Telegram is having internal problems. Please try again later
CHAT_FROM_CALL_CHANGED
1 id message
38 SIGN_IN_FAILED Failure while signing in due to Telegram having internal problems. Please try again later
39 STORAGE_CHECK_FAILED Server storage check failed due to Telegram having internal problems. Please try again later
40 STORE_INVALID_SCALAR_TYPE Telegram is having internal problems. Please try again later
TIMEOUT A timeout occurred while fetching data from the worker
41 UNKNOWN_METHOD The method you tried to call cannot be called on non-CDN DCs
42 UPLOAD_NO_VOLUME Telegram is having internal problems. Please try again later
43 VOLUME_LOC_NOT_FOUND Telegram is having internal problems. Please try again later
44 WORKER_BUSY_TOO_LONG_RETRY Server workers are too busy right now due to Telegram having internal problems. Please try again later
45 WP_ID_GENERATE_FAILED Telegram is having internal problems. Please try again later
46 FILE_WRITE_FAILED Telegram is having internal problems. Please try again later
CHAT_FROM_CALL_CHANGED

6
dev-requirements.txt Normal file
View file

@ -0,0 +1,6 @@
-r requirements.txt
pytest
pytest-asyncio
pytest-cov
twine

7
docs/requirements.txt Normal file
View file

@ -0,0 +1,7 @@
sphinx
sphinx_rtd_theme==1.3.0
sphinx-rtd-dark-mode
sphinx_copybutton
sphinx-autobuild
tgcrypto
tornado>=6.3.3 # not directly required, pinned by Snyk to avoid a vulnerability

View file

@ -1,7 +1,5 @@
.. raw:: html .. raw:: html
<blockquote> <strong>Usable by</strong>
<strong>Usable by</strong> <span class="usable-by"><i class="fa-solid fa-xmark" style="color: var(--color-red)"></i> Users</span>
<span class="usable-by"><i class="fa-solid fa-xmark" style="color: var(--color-red)"></i> Users</span> <span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Bots</span>
<span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Bots</span>
</blockquote>

View file

@ -1,7 +1,5 @@
.. raw:: html .. raw:: html
<blockquote> <strong>Usable by</strong>
<strong>Usable by</strong> <span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Users</span>
<span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Users</span> <span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Bots</span>
<span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Bots</span>
</blockquote>

View file

@ -1,7 +1,5 @@
.. raw:: html .. raw:: html
<blockquote> <strong>Usable by</strong>
<strong>Usable by</strong> <span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Users</span>
<span class="usable-by"><i class="fa-solid fa-check" style="color: var(--color-green)"></i> Users</span> <span class="usable-by"><i class="fa-solid fa-xmark" style="color: var(--color-red)"></i> Bots</span>
<span class="usable-by"><i class="fa-solid fa-xmark" style="color: var(--color-red)"></i> Bots</span>
</blockquote>

View file

@ -1 +0,0 @@
@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css");

View file

@ -1,24 +0,0 @@
body{
--color-green: darkgreen;
--color-red: darkred;
}
.usable-by {
border: 1px ;
border-radius: .2em;
padding: 2px 5px;
background-color: #1a1c1e;
}
a .pre{
color:lightgrey;
}
.md-main a {
text-decoration: underline;
color:lightgrey;
}
.md-sidebar a {
text-decoration: none;
}

View file

@ -0,0 +1,3 @@
.pre{
color: #bfbfbf;
}

View file

@ -35,28 +35,19 @@ Index
.. hlist:: .. hlist::
:columns: 3 :columns: 3
- :meth:`~Client.on_bot_business_connect`
- :meth:`~Client.on_message` - :meth:`~Client.on_message`
- :meth:`~Client.on_bot_business_message`
- :meth:`~Client.on_edited_message` - :meth:`~Client.on_edited_message`
- :meth:`~Client.on_edited_bot_business_message`
- :meth:`~Client.on_callback_query` - :meth:`~Client.on_callback_query`
- :meth:`~Client.on_shipping_query`
- :meth:`~Client.on_pre_checkout_query`
- :meth:`~Client.on_message_reaction_updated`
- :meth:`~Client.on_message_reaction_count_updated`
- :meth:`~Client.on_inline_query` - :meth:`~Client.on_inline_query`
- :meth:`~Client.on_chosen_inline_result` - :meth:`~Client.on_chosen_inline_result`
- :meth:`~Client.on_chat_member_updated` - :meth:`~Client.on_chat_member_updated`
- :meth:`~Client.on_chat_join_request` - :meth:`~Client.on_chat_join_request`
- :meth:`~Client.on_deleted_messages` - :meth:`~Client.on_deleted_messages`
- :meth:`~Client.on_deleted_bot_business_message`
- :meth:`~Client.on_user_status` - :meth:`~Client.on_user_status`
- :meth:`~Client.on_story` - :meth:`~Client.on_story`
- :meth:`~Client.on_poll` - :meth:`~Client.on_poll`
- :meth:`~Client.on_disconnect` - :meth:`~Client.on_disconnect`
- :meth:`~Client.on_raw_update` - :meth:`~Client.on_raw_update`
- :meth:`~Client.on_error`
----- -----
@ -64,25 +55,16 @@ Details
------- -------
.. Decorators .. Decorators
.. autodecorator:: pyrogram.Client.on_bot_business_connect()
.. autodecorator:: pyrogram.Client.on_message() .. autodecorator:: pyrogram.Client.on_message()
.. autodecorator:: pyrogram.Client.on_bot_business_message()
.. autodecorator:: pyrogram.Client.on_edited_message() .. autodecorator:: pyrogram.Client.on_edited_message()
.. autodecorator:: pyrogram.Client.on_edited_bot_business_message()
.. autodecorator:: pyrogram.Client.on_callback_query() .. autodecorator:: pyrogram.Client.on_callback_query()
.. autodecorator:: pyrogram.Client.on_shipping_query()
.. autodecorator:: pyrogram.Client.on_pre_checkout_query()
.. autodecorator:: pyrogram.Client.on_message_reaction_updated()
.. autodecorator:: pyrogram.Client.on_message_reaction_count_updated()
.. autodecorator:: pyrogram.Client.on_inline_query() .. autodecorator:: pyrogram.Client.on_inline_query()
.. autodecorator:: pyrogram.Client.on_chosen_inline_result() .. autodecorator:: pyrogram.Client.on_chosen_inline_result()
.. autodecorator:: pyrogram.Client.on_chat_member_updated() .. autodecorator:: pyrogram.Client.on_chat_member_updated()
.. autodecorator:: pyrogram.Client.on_chat_join_request() .. autodecorator:: pyrogram.Client.on_chat_join_request()
.. autodecorator:: pyrogram.Client.on_deleted_messages() .. autodecorator:: pyrogram.Client.on_deleted_messages()
.. autodecorator:: pyrogram.Client.on_deleted_bot_business_message()
.. autodecorator:: pyrogram.Client.on_user_status() .. autodecorator:: pyrogram.Client.on_user_status()
.. autodecorator:: pyrogram.Client.on_story() .. autodecorator:: pyrogram.Client.on_story()
.. autodecorator:: pyrogram.Client.on_poll() .. autodecorator:: pyrogram.Client.on_poll()
.. autodecorator:: pyrogram.Client.on_disconnect() .. autodecorator:: pyrogram.Client.on_disconnect()
.. autodecorator:: pyrogram.Client.on_raw_update() .. autodecorator:: pyrogram.Client.on_raw_update()
.. autodecorator:: pyrogram.Client.on_error()

View file

@ -1,8 +0,0 @@
BusinessSchedule
==========
.. autoclass:: pyrogram.enums.BusinessSchedule()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -1,8 +0,0 @@
ChatJoinType
==========
.. autoclass:: pyrogram.enums.ChatJoinType()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -1,8 +0,0 @@
ClientPlatform
==========
.. autoclass:: pyrogram.enums.ClientPlatform()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -1,8 +0,0 @@
FolderColor
===========
.. autoclass:: pyrogram.enums.FolderColor()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -1,8 +0,0 @@
GiftAttributeType
==========
.. autoclass:: pyrogram.enums.GiftAttributeType()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -1,8 +0,0 @@
GiftAttributeType
=================
.. autoclass:: pyrogram.enums.GiftForResaleOrder()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -1,8 +0,0 @@
ListenerTypes
=============
.. autoclass:: pyrogram.enums.ListenerTypes()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -1,8 +0,0 @@
MessageOriginType
=================
.. autoclass:: pyrogram.enums.MessageOriginType()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -1,8 +0,0 @@
ProfileColor
==========
.. autoclass:: pyrogram.enums.ProfileColor()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -1,8 +0,0 @@
ReactionType
============
.. autoclass:: pyrogram.enums.ReactionType()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -1,8 +0,0 @@
ReplyColor
==========
.. autoclass:: pyrogram.enums.ReplyColor()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -1,8 +0,0 @@
StoriesPrivacyRules
===================
.. autoclass:: pyrogram.enums.StoriesPrivacyRules()
:members:
.. raw:: html
:file: ./cleanup.html

View file

@ -13,57 +13,39 @@ to apply only a valid value among the expected ones.
.. autosummary:: .. autosummary::
:nosignatures: :nosignatures:
BusinessSchedule
ChatAction ChatAction
ChatEventAction ChatEventAction
ChatJoinType
ChatMemberStatus ChatMemberStatus
ChatMembersFilter ChatMembersFilter
ChatType ChatType
ClientPlatform
FolderColor
GiftAttributeType
ListenerTypes
MessageEntityType MessageEntityType
MessageMediaType MessageMediaType
MessageServiceType MessageServiceType
MessagesFilter MessagesFilter
ParseMode ParseMode
PollType PollType
ProfileColor
SentCodeType SentCodeType
NextCodeType NextCodeType
UserStatus UserStatus
ReactionType
ReplyColor
StoriesPrivacyRules StoriesPrivacyRules
StoryPrivacy StoryPrivacy
.. toctree:: .. toctree::
:hidden: :hidden:
BusinessSchedule
ChatAction ChatAction
ChatEventAction ChatEventAction
ChatJoinType
ChatMemberStatus ChatMemberStatus
ChatMembersFilter ChatMembersFilter
ChatType ChatType
ClientPlatform
FolderColor
GiftAttributeType
ListenerTypes
MessageEntityType MessageEntityType
MessageMediaType MessageMediaType
MessageServiceType MessageServiceType
MessagesFilter MessagesFilter
ParseMode ParseMode
PollType PollType
ProfileColor
SentCodeType SentCodeType
NextCodeType NextCodeType
UserStatus UserStatus
ReactionType
ReplyColor
StoriesPrivacyRules StoriesPrivacyRules
StoryPrivacy StoryPrivacy

View file

@ -35,18 +35,10 @@ Index
.. hlist:: .. hlist::
:columns: 3 :columns: 3
- :class:`BotBusinessConnectHandler`
- :class:`MessageHandler` - :class:`MessageHandler`
- :class:`BotBusinessMessageHandler`
- :class:`EditedMessageHandler` - :class:`EditedMessageHandler`
- :class:`EditedBotBusinessMessageHandler`
- :class:`DeletedMessagesHandler` - :class:`DeletedMessagesHandler`
- :class:`DeletedBotBusinessMessagesHandler`
- :class:`CallbackQueryHandler` - :class:`CallbackQueryHandler`
- :class:`PreCheckoutQueryHandler`
- :class:`ShippingQueryHandler`
- :class:`MessageReactionUpdatedHandler`
- :class:`MessageReactionCountUpdatedHandler`
- :class:`InlineQueryHandler` - :class:`InlineQueryHandler`
- :class:`ChosenInlineResultHandler` - :class:`ChosenInlineResultHandler`
- :class:`ChatMemberUpdatedHandler` - :class:`ChatMemberUpdatedHandler`
@ -55,7 +47,6 @@ Index
- :class:`PollHandler` - :class:`PollHandler`
- :class:`DisconnectHandler` - :class:`DisconnectHandler`
- :class:`RawUpdateHandler` - :class:`RawUpdateHandler`
- :class:`ErrorHandler`
----- -----
@ -63,18 +54,10 @@ Details
------- -------
.. Handlers .. Handlers
.. autoclass:: BotBusinessConnectHandler()
.. autoclass:: MessageHandler() .. autoclass:: MessageHandler()
.. autoclass:: BotBusinessMessageHandler()
.. autoclass:: EditedMessageHandler() .. autoclass:: EditedMessageHandler()
.. autoclass:: EditedBotBusinessMessageHandler()
.. autoclass:: DeletedMessagesHandler() .. autoclass:: DeletedMessagesHandler()
.. autoclass:: DeletedBotBusinessMessagesHandler()
.. autoclass:: CallbackQueryHandler() .. autoclass:: CallbackQueryHandler()
.. autoclass:: ShippingQueryHandler()
.. autoclass:: PreCheckoutQueryHandler()
.. autoclass:: MessageReactionUpdatedHandler()
.. autoclass:: MessageReactionCountUpdatedHandler()
.. autoclass:: InlineQueryHandler() .. autoclass:: InlineQueryHandler()
.. autoclass:: ChosenInlineResultHandler() .. autoclass:: ChosenInlineResultHandler()
.. autoclass:: ChatMemberUpdatedHandler() .. autoclass:: ChatMemberUpdatedHandler()
@ -83,4 +66,3 @@ Details
.. autoclass:: PollHandler() .. autoclass:: PollHandler()
.. autoclass:: DisconnectHandler() .. autoclass:: DisconnectHandler()
.. autoclass:: RawUpdateHandler() .. autoclass:: RawUpdateHandler()
.. autoclass:: ErrorHandler()

View file

@ -29,7 +29,7 @@ from pygments.styles.friendly import FriendlyStyle
FriendlyStyle.background_color = "#f3f2f1" FriendlyStyle.background_color = "#f3f2f1"
project = "Pyrofork" project = "Pyrofork"
copyright = "2022-present, Mayuri-Chan" copyright = f"2022-present, Mayuri-Chan"
author = "Mayuri-Chan" author = "Mayuri-Chan"
version = ".".join(__version__.split(".")[:-1]) version = ".".join(__version__.split(".")[:-1])
@ -40,7 +40,7 @@ extensions = [
"sphinx.ext.autosummary", "sphinx.ext.autosummary",
"sphinx.ext.intersphinx", "sphinx.ext.intersphinx",
"sphinx_copybutton", "sphinx_copybutton",
"sphinx_immaterial" "sphinx_rtd_dark_mode"
] ]
intersphinx_mapping = { intersphinx_mapping = {
@ -64,42 +64,17 @@ copybutton_prompt_text = "$ "
suppress_warnings = ["image.not_readable"] suppress_warnings = ["image.not_readable"]
html_title = "Pyrofork Documentation" html_title = "Pyrofork Documentation"
html_theme = "sphinx_immaterial" html_theme = "sphinx_rtd_theme"
html_static_path = ["../resources/static","_static"] html_static_path = ["../resources/static","_static"]
html_show_sourcelink = True html_show_sourcelink = True
html_show_copyright = False html_show_copyright = False
html_theme_options = { html_theme_options = {
"icon": { "canonical_url": "https://pyrofork.mayuri.my.id/",
"repo": "fontawesome/brands/github", "collapse_navigation": True,
"edit": "material/file-edit-outline", "sticky_navigation": False,
}, "logo_only": True,
"site_url": "https://pyrofork.wulan17.dev/", "display_version": False,
"repo_url": "https://github.com/Mayuri-Chan/pyrofork/", "style_external_links": True
"repo_name": "pyrofork",
"globaltoc_collapse": True,
"features": [
"navigation.expand",
"navigation.tabs",
"navigation.sections",
"navigation.top",
"search.share",
"toc.follow",
"toc.sticky",
"content.tabs.link",
"announce.dismiss",
],
"palette": [
{
"media": "(prefers-color-scheme: dark)",
"scheme": "slate"
}
],
"toc_title_is_page_title": True,
"version_dropdown": True,
"version_info": [
{"version": "main", "title": "main", "aliases": ["latest"]},
{"version": "staging", "title": "staging", "aliases": []},
],
} }
html_logo = "../resources/static/img/pyrogram.png" html_logo = "../resources/static/img/pyrogram.png"
@ -118,6 +93,7 @@ latex_elements = {
} }
html_css_files = [ html_css_files = [
"css/custom.css", "css/my.css",
"css/all.min.css", "https://docs.pyrogram.org/_static/css/custom.css",
] "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css",
]

View file

@ -5,7 +5,8 @@ Welcome to Pyrofork
<div align="center"> <div align="center">
<a href="/"> <a href="/">
<h1 class="pyrogram-text pyrogram-text-index">PyroFork</h1> <div class="pyrogram-logo-index"><img src="_static/pyrogram.png" alt="Pyrofork"></div>
<div class="pyrogram-text pyrogram-text-index">Pyrofork</div>
</a> </a>
</div> </div>
@ -13,25 +14,9 @@ Welcome to Pyrofork
<b>Telegram MTProto API Framework for Python</b> <b>Telegram MTProto API Framework for Python</b>
<br> <br>
<a href="https://github.com/Mayuri-Chan">
Homepage
</a>
<a href="https://github.com/Mayuri-Chan/pyrofork"> <a href="https://github.com/Mayuri-Chan/pyrofork">
Development Development
</a> </a>
<a href="https://github.com/Mayuri-Chan/pyrofork/issues">
Issues
</a>
<a href="https://t.me/MayuriChan_Chat">
Support Chat
</a>
<a href="https://t.me/Pyrofork_CH">
News/Releases
</a>
</p> </p>
.. code-block:: python .. code-block:: python
@ -100,6 +85,7 @@ Meta
- :doc:`Pyrofork FAQ <faq/index>`: Answers to common Pyrofork questions. - :doc:`Pyrofork FAQ <faq/index>`: Answers to common Pyrofork questions.
- :doc:`Support Pyrofork <support>`: Ways to show your appreciation. - :doc:`Support Pyrofork <support>`: Ways to show your appreciation.
- :doc:`Release Notes <releases/index>`: Release notes for Pyrofork releases.
.. toctree:: .. toctree::
:hidden: :hidden:
@ -161,6 +147,7 @@ Meta
faq/index faq/index
support support
releases/index
.. toctree:: .. toctree::
:hidden: :hidden:
@ -168,4 +155,4 @@ Meta
telegram/functions/index telegram/functions/index
telegram/types/index telegram/types/index
telegram/base/index telegram/base/index

View file

@ -12,7 +12,7 @@ Get Pyrofork Real Fast
If you need a cloud server to host your applications, try Hetzner Cloud. You can sign up with If you need a cloud server to host your applications, try Hetzner Cloud. You can sign up with
`this link <https://hetzner.cloud/?ref=9CyT92gZEINU>`_ to get €20 in cloud credits. `this link <https://hetzner.cloud/?ref=9CyT92gZEINU>`_ to get €20 in cloud credits.
1. Install Pyrofork with ``pip3 install -U pyrofork``. 1. Install Pyrofork with ``pip3 install -U pyrogram``.
2. Get your own Telegram API key from https://my.telegram.org/apps. 2. Get your own Telegram API key from https://my.telegram.org/apps.
@ -53,4 +53,4 @@ we have just done above.
If you are feeling eager to continue you can take a shortcut to :doc:`../start/invoking` and come back If you are feeling eager to continue you can take a shortcut to :doc:`../start/invoking` and come back
later to learn some more details. later to learn some more details.
.. _community: https://t.me/MayuriChan-Chat .. _community: https://t.me/Pyrofork

View file

@ -47,7 +47,7 @@ like send_audio(), send_document(), send_location(), etc...
), ),
InlineKeyboardButton( # Opens a web URL InlineKeyboardButton( # Opens a web URL
"URL", "URL",
url="https://pyrofork.wulan17.dev" url="https://pyrofork.mayuri.my.id"
), ),
], ],
[ # Second row [ # Second row

View file

@ -24,13 +24,13 @@ It uses the @on_inline_query decorator to register an InlineQueryHandler.
input_message_content=InputTextMessageContent( input_message_content=InputTextMessageContent(
"Here's how to install **Pyrofork**" "Here's how to install **Pyrofork**"
), ),
url="https://pyrofork.wulan17.dev/intro/install", url="https://pyrofork.mayuri.my.id/intro/install",
description="How to install Pyrofork", description="How to install Pyrofork",
reply_markup=InlineKeyboardMarkup( reply_markup=InlineKeyboardMarkup(
[ [
[InlineKeyboardButton( [InlineKeyboardButton(
"Open website", "Open website",
url="https://pyrofork.wulan17.dev/intro/install" url="https://pyrofork.mayuri.my.id/intro/install"
)] )]
] ]
) )
@ -40,13 +40,13 @@ It uses the @on_inline_query decorator to register an InlineQueryHandler.
input_message_content=InputTextMessageContent( input_message_content=InputTextMessageContent(
"Here's how to use **Pyrofork**" "Here's how to use **Pyrofork**"
), ),
url="https://pyrofork.wulan17.dev/start/invoking", url="https://pyrofork.mayuri.my.id/start/invoking",
description="How to use Pyrofork", description="How to use Pyrofork",
reply_markup=InlineKeyboardMarkup( reply_markup=InlineKeyboardMarkup(
[ [
[InlineKeyboardButton( [InlineKeyboardButton(
"Open website", "Open website",
url="https://pyrofork.wulan17.dev/start/invoking" url="https://pyrofork.mayuri.my.id/start/invoking"
)] )]
] ]
) )

View file

@ -11,7 +11,7 @@ to make it only work for specific messages in a specific chat.
# Target chat. Can also be a list of multiple chat ids/usernames # Target chat. Can also be a list of multiple chat ids/usernames
TARGET = -100123456789 TARGET = -100123456789
# Welcome message template # Welcome message template
MESSAGE = "{} Welcome to [Pyrofork](https://pyrofork.wulan17.dev/)'s group chat {}!" MESSAGE = "{} Welcome to [Pyrofork](https://pyrofork.mayuri.my.id/)'s group chat {}!"
app = Client("my_account") app = Client("my_account")

View file

@ -121,4 +121,4 @@ For example, given the ID *123456789*, here's how Pyrofork can tell entities apa
So, every time you take a raw ID, make sure to translate it into the correct ID when you want to use it with an So, every time you take a raw ID, make sure to translate it into the correct ID when you want to use it with an
high-level method. high-level method.
.. _Community: https://t.me/MayuriChan-Chat .. _Community: https://t.me/Pyrofork

View file

@ -10,10 +10,10 @@ Pyrofork's speed can be boosted up by using TgCrypto and uvloop.
----- -----
TgCrypto-pyrofork TgCrypto
-------- --------
TgCrypto-pyrofork_ is a high-performance, easy-to-install cryptography library specifically written in C for Pyrofork as a Python TgCrypto_ is a high-performance, easy-to-install cryptography library specifically written in C for Pyrofork as a Python
extension. It is a replacement for a slower Python-only alternative and implements the cryptographic algorithms Telegram extension. It is a replacement for a slower Python-only alternative and implements the cryptographic algorithms Telegram
requires, namely: AES-256-IGE, AES-256-CTR and AES-256-CBC. requires, namely: AES-256-IGE, AES-256-CTR and AES-256-CBC.
@ -22,7 +22,7 @@ Installation
.. code-block:: bash .. code-block:: bash
$ pip3 install -U tgcrypto-pyrofork $ pip3 install -U tgcrypto
Usage Usage
^^^^^ ^^^^^

View file

@ -68,40 +68,21 @@ In case you want to have persistent session but you don't have persistent storag
mongodb config as ``dict`` to the ``mongodb`` parameter of the :obj:`~pyrogram.Client` constructor: mongodb config as ``dict`` to the ``mongodb`` parameter of the :obj:`~pyrogram.Client` constructor:
Using async_pymongo (Recommended for python3.9+): Using async_pymongo (Recommended for python3.9+):
.. code-block:: python .. code-block:: python
from async_pymongo import AsyncClient from async_pymongo import AsyncClient
from pyrogram import Client from pyrogram import Client
conn = AsyncClient("mongodb://...") conn = AsyncClient("mongodb://...")
async with Client("my_account", mongodb=dict(connection=conn, remove_peers=False)) as app: async with Client("my_account", mongodb=dict(connection=conn, remove_peers=False)) as app:
print(await app.get_me()) print(await app.get_me())
Using official mongodb driver: Using motor:
.. code-block:: python .. code-block:: python
from pymongo import AsyncMongoClient
from pyrogram import Client
conn = AsyncMongoClient("mongodb://...")
async with Client("my_account", mongodb=dict(connection=conn, remove_peers=False)) as app:
print(await app.get_me())
Using motor (Deprecated, but still works):
.. code-block:: python
from motor.motor_asyncio import AsyncIOMotorClient from motor.motor_asyncio import AsyncIOMotorClient
from pyrogram import Client from pyrogram import Client
conn = AsyncIOMotorClient("mongodb://...") conn = AsyncIOMotorClient("mongodb://...")
async with Client("my_account", mongodb=dict(connection=conn, remove_peers=False)) as app: async with Client("my_account", mongodb=dict(connection=conn, remove_peers=False)) as app:
print(await app.get_me()) print(await app.get_me())

View file

@ -37,106 +37,16 @@ list of the basic styles currently supported by Pyrofork.
- spoiler - spoiler
- `text URL <https://pyrogram.org>`_ - `text URL <https://pyrogram.org>`_
- `user text mention <tg://user?id=123456789>`_ - `user text mention <tg://user?id=123456789>`_
- :emoji:`🔥`
- ``inline fixed-width code`` - ``inline fixed-width code``
- .. code-block:: text - .. code-block:: text
pre-formatted pre-formatted
fixed-width fixed-width
code block code block
- > Quoted text
- > Quoted text with collapse/expand button
HTML Style
----------
To strictly use this mode, pass :obj:`~pyrogram.enums.HTML` to the *parse_mode* parameter when using
:meth:`~pyrogram.Client.send_message`. The following tags are currently supported:
.. code-block:: text
<b>bold</b>, <strong>bold</strong>
<i>italic</i>, <em>italic</em>
<u>underline</u>
<s>strike</s>, <del>strike</del>, <strike>strike</strike>
<spoiler>spoiler</spoiler>
<a href="https://pyrogram.org/">text URL</a>
<a href="tg://user?id=123456789">inline mention</a>
<emoji id="12345678901234567890">🔥</emoji>
<code>inline fixed-width code</code>
<pre>
pre-formatted
fixed-width
code block
</pre>
<blockquote>Quoted text</blockquote>
<blockquote expandable>Quoted text with collapse/expand button</blockquote>
**Example**:
.. code-block:: python
from pyrogram import enums
await app.send_message(
"me",
(
"<b>bold</b>, "
"<i>italic</i>, "
"<u>underline</u>, "
"<s>strike</s>, "
"<spoiler>spoiler</spoiler>, "
"<a href=\"https://pyrogram.org/\">URL</a>, "
"<code>code</code>\n\n"
"<pre>"
"for i in range(10):\n"
" print(i)"
"</pre>"
"<blockquote>quote</blockquote>"
),
parse_mode=enums.ParseMode.HTML
)
.. note::
All ``<``, ``>`` and ``&`` symbols that are not a part of a tag or an HTML entity must be replaced with the
corresponding HTML entities (``<`` with ``&lt;``, ``>`` with ``&gt;`` and ``&`` with ``&amp;``). You can use this
snippet to quickly escape those characters:
.. code-block:: python
import html
text = "<my text>"
text = html.escape(text)
print(text)
.. code-block:: text
&lt;my text&gt;
Markdown Style Markdown Style
-------------- --------------
.. warning::
The Markdown style is not recommended for complex text formatting.
If you want to use complex text formatting such as nested entities, overlapping entities use the HTML style instead.
To strictly use this mode, pass :obj:`~pyrogram.enums.ParseMode.MARKDOWN` to the *parse_mode* parameter when using To strictly use this mode, pass :obj:`~pyrogram.enums.ParseMode.MARKDOWN` to the *parse_mode* parameter when using
:meth:`~pyrogram.Client.send_message`. Use the following syntax in your message: :meth:`~pyrogram.Client.send_message`. Use the following syntax in your message:
@ -156,8 +66,6 @@ To strictly use this mode, pass :obj:`~pyrogram.enums.ParseMode.MARKDOWN` to the
[text user mention](tg://user?id=123456789) [text user mention](tg://user?id=123456789)
![🔥](tg://emoji?id=12345678901234567890)
`inline fixed-width code` `inline fixed-width code`
``` ```
@ -166,10 +74,6 @@ To strictly use this mode, pass :obj:`~pyrogram.enums.ParseMode.MARKDOWN` to the
code block code block
``` ```
> Quoted text
**> Quoted text with collapse/expand button
**Example**: **Example**:
.. code-block:: python .. code-block:: python
@ -194,6 +98,81 @@ To strictly use this mode, pass :obj:`~pyrogram.enums.ParseMode.MARKDOWN` to the
parse_mode=enums.ParseMode.MARKDOWN parse_mode=enums.ParseMode.MARKDOWN
) )
HTML Style
----------
To strictly use this mode, pass :obj:`~pyrogram.enums.HTML` to the *parse_mode* parameter when using
:meth:`~pyrogram.Client.send_message`. The following tags are currently supported:
.. code-block:: text
<b>bold</b>, <strong>bold</strong>
<i>italic</i>, <em>italic</em>
<u>underline</u>
<s>strike</s>, <del>strike</del>, <strike>strike</strike>
<spoiler>spoiler</spoiler>
<a href="https://pyrogram.org/">text URL</a>
<a href="tg://user?id=123456789">inline mention</a>
<code>inline fixed-width code</code>
<emoji id="12345678901234567890">🔥</emoji>
<pre>
pre-formatted
fixed-width
code block
</pre>
**Example**:
.. code-block:: python
from pyrogram import enums
await app.send_message(
"me",
(
"<b>bold</b>, "
"<i>italic</i>, "
"<u>underline</u>, "
"<s>strike</s>, "
"<spoiler>spoiler</spoiler>, "
"<a href=\"https://pyrogram.org/\">URL</a>, "
"<code>code</code>\n\n"
"<pre>"
"for i in range(10):\n"
" print(i)"
"</pre>"
),
parse_mode=enums.ParseMode.HTML
)
.. note::
All ``<``, ``>`` and ``&`` symbols that are not a part of a tag or an HTML entity must be replaced with the
corresponding HTML entities (``<`` with ``&lt;``, ``>`` with ``&gt;`` and ``&`` with ``&amp;``). You can use this
snippet to quickly escape those characters:
.. code-block:: python
import html
text = "<my text>"
text = html.escape(text)
print(text)
.. code-block:: text
&lt;my text&gt;
Different Styles Different Styles
---------------- ----------------
@ -246,18 +225,18 @@ strike` styles, and you can still combine both Markdown and HTML together.
Here there are some example texts you can try sending: Here there are some example texts you can try sending:
**Markdown**:
- ``**bold, --underline--**``
- ``**bold __italic --underline ~~strike~~--__**``
- ``**bold __and** italic__``
**HTML**: **HTML**:
- ``<b>bold, <u>underline</u></b>`` - ``<b>bold, <u>underline</u></b>``
- ``<b>bold <i>italic <u>underline <s>strike</s></u></i></b>`` - ``<b>bold <i>italic <u>underline <s>strike</s></u></i></b>``
- ``<b>bold <i>and</b> italic</i>`` - ``<b>bold <i>and</b> italic</i>``
**Markdown (Not Recommended)**:
- ``**bold, --underline--**``
- ``**bold __italic --underline ~~strike~~--__**``
- ``**bold __and** italic__``
**Combined**: **Combined**:
- ``--you can combine <i>HTML</i> with **Markdown**--`` - ``--you can combine <i>HTML</i> with **Markdown**--``

View file

@ -1,40 +0,0 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2023-present Hydrogram <https://hydrogram.org>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork 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 General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
import sys
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
# Add the current directory to the path, so we can import the compiler.
sys.path.insert(0, ".")
class CustomHook(BuildHookInterface):
"""A custom build hook for pyrofork."""
def initialize(self, version, build_data):
"""Initialize the hook."""
if self.target_name not in ["wheel", "install"]:
return
from compiler.api.compiler import start as compile_api
from compiler.errors.compiler import start as compile_errors
compile_api()
compile_errors()

View file

@ -1,93 +0,0 @@
[project]
name = "pyrofork"
dynamic = ["version"]
description = "Fork of pyrogram. Elegant, modern and asynchronous Telegram MTProto API framework in Python for users and bots"
authors = [{ name = "wulan17", email = "mayuri@mayuri.my.id" }]
dependencies = ["pyaes==1.6.1", "pysocks==1.7.1", "pymediainfo-pyrofork>=6.0.1,<7.0.0"]
readme = "README.md"
license = "LGPL-3.0-or-later"
requires-python = "~=3.10"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Natural Language :: English",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: Implementation",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Internet",
"Topic :: Communications",
"Topic :: Communications :: Chat",
"Topic :: Software Development :: Libraries",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Libraries :: Application Frameworks",
]
keywords = ["telegram chat messenger mtproto api client library python"]
[tool.hatch.version]
path = "pyrogram/__init__.py"
# Used to call hatch_build.py
[tool.hatch.build.hooks.custom]
[project.urls]
Homepage = "https://github.com/Mayuri-Chan"
Tracker = "https://github.com/Mayuri-Chan/pyrofork/issues"
Community = "https://t.me/MayuriChan_Chat"
Source = "https://github.com/Mayuri-Chan/pyrofork"
Documentation = "https://pyrofork.wulan17.dev"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project.optional-dependencies]
dev = [
"hatch>=1.7.0",
"pytest>=7.4.3",
"pytest-asyncio>=0.21.1",
"pytest-cov>=4.1.0",
"twine>=4.0.2"
]
docs = [
"sphinx",
"sphinx-immaterial==0.12.5",
"sphinx_copybutton",
"sphinx-autobuild",
"tornado>=6.3.3"
]
speedup = [
"tgcrypto-pyrofork>=1.2.6",
"uvloop>=0.19.0"
]
[tool.hatch.metadata]
allow-direct-references = true
[tool.hatch.build.targets.sdist]
exclude = [
".github/",
"docs/",
"tests/",
".editorconfig",
".gitignore",
".pre-commit-config.yaml",
"CODE_OF_CONDUCT.rst",
"CONTRIBUTING.rst",
"requirements.lock",
"requirements-dev.lock",
]
[tool.hatch.build.targets.wheel]
ignore-vcs = true
packages = ["pyrogram"]

View file

@ -18,7 +18,7 @@
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
__fork_name__ = "PyroFork" __fork_name__ = "PyroFork"
__version__ = "2.3.69" __version__ = "2.3.8"
__license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)" __license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)"
__copyright__ = "Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>" __copyright__ = "Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>"
@ -37,24 +37,8 @@ class ContinuePropagation(StopAsyncIteration):
pass pass
from . import raw, types, filters, handlers, emoji, enums # pylint: disable=wrong-import-position from . import raw, types, filters, handlers, emoji, enums
from .client import Client # pylint: disable=wrong-import-position from .client import Client
from .sync import idle, compose # pylint: disable=wrong-import-position from .sync import idle, compose
crypto_executor = ThreadPoolExecutor(1, thread_name_prefix="CryptoWorker") crypto_executor = ThreadPoolExecutor(1, thread_name_prefix="CryptoWorker")
__all__ = [
"Client",
"idle",
"compose",
"crypto_executor",
"StopTransmission",
"StopPropagation",
"ContinuePropagation",
"raw",
"types",
"filters",
"handlers",
"emoji",
"enums",
]

View file

@ -33,29 +33,26 @@ from importlib import import_module
from io import StringIO, BytesIO from io import StringIO, BytesIO
from mimetypes import MimeTypes from mimetypes import MimeTypes
from pathlib import Path from pathlib import Path
from typing import Union, List, Optional, Callable, AsyncGenerator, Tuple from typing import Union, List, Optional, Callable, AsyncGenerator
import pyrogram import pyrogram
from pyrogram import __version__, __license__ from pyrogram import __version__, __license__
from pyrogram import enums from pyrogram import enums
from pyrogram import raw from pyrogram import raw
from pyrogram import types
from pyrogram import utils from pyrogram import utils
from pyrogram.crypto import aes from pyrogram.crypto import aes
from pyrogram.errors import CDNFileHashMismatch from pyrogram.errors import CDNFileHashMismatch
from pyrogram.errors import ( from pyrogram.errors import (
SessionPasswordNeeded, SessionPasswordNeeded,
VolumeLocNotFound, ChannelPrivate, VolumeLocNotFound, ChannelPrivate,
BadRequest, ChannelInvalid, PersistentTimestampInvalid, PersistentTimestampOutdated BadRequest
) )
from pyrogram.handlers.handler import Handler from pyrogram.handlers.handler import Handler
from pyrogram.methods import Methods from pyrogram.methods import Methods
from pyrogram.session import Auth, Session from pyrogram.session import Auth, Session
from pyrogram.storage import FileStorage, MemoryStorage, Storage from pyrogram.storage import FileStorage, MemoryStorage, MongoStorage, Storage
from pyrogram.types import User from pyrogram.types import User, TermsOfService
from pyrogram.utils import ainput from pyrogram.utils import ainput
from .connection import Connection
from .connection.transport import TCPAbridged
from .dispatcher import Dispatcher from .dispatcher import Dispatcher
from .file_id import FileId, FileType, ThumbnailSource from .file_id import FileId, FileType, ThumbnailSource
from .mime_types import mime_types from .mime_types import mime_types
@ -63,15 +60,6 @@ from .parser import Parser
from .session.internals import MsgId from .session.internals import MsgId
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
MONGO_AVAIL = False
try:
import pymongo
except Exception:
pass
else:
from pyrogram.storage import MongoStorage
MONGO_AVAIL = True
class Client(Methods): class Client(Methods):
@ -131,9 +119,6 @@ class Client(Methods):
Pass a session string to load the session in-memory. Pass a session string to load the session in-memory.
Implies ``in_memory=True``. Implies ``in_memory=True``.
use_qrcode (``bool``, *optional*):
Pass True to login using a QR code.
in_memory (``bool``, *optional*): in_memory (``bool``, *optional*):
Pass True to start an in-memory session that will be discarded as soon as the client stops. Pass True to start an in-memory session that will be discarded as soon as the client stops.
In order to reconnect again using an in-memory session without having to login again, you can use In order to reconnect again using an in-memory session without having to login again, you can use
@ -144,7 +129,7 @@ class Client(Methods):
mongodb (``dict``, *optional*): mongodb (``dict``, *optional*):
Mongodb config as dict, e.g.: *dict(connection=async_pymongo.AsyncClient("mongodb://..."), remove_peers=False)*. Mongodb config as dict, e.g.: *dict(connection=async_pymongo.AsyncClient("mongodb://..."), remove_peers=False)*.
Only applicable for new sessions. Only applicable for new sessions.
storage (:obj:`~pyrogram.storage.Storage`, *optional*): storage (:obj:`~pyrogram.storage.Storage`, *optional*):
Custom session storage. Custom session storage.
@ -182,10 +167,6 @@ class Client(Methods):
Useful for batch programs that don't need to deal with updates. Useful for batch programs that don't need to deal with updates.
Defaults to False (updates enabled and received). Defaults to False (updates enabled and received).
skip_updates (``bool``, *optional*):
Pass True to skip pending updates that arrived while the client was offline.
Defaults to True.
takeout (``bool``, *optional*): takeout (``bool``, *optional*):
Pass True to let the client use a takeout session instead of a normal one, implies *no_updates=True*. Pass True to let the client use a takeout session instead of a normal one, implies *no_updates=True*.
Useful for exporting Telegram data. Methods invoked inside a takeout session (such as get_chat_history, Useful for exporting Telegram data. Methods invoked inside a takeout session (such as get_chat_history,
@ -208,18 +189,6 @@ class Client(Methods):
Set the maximum amount of concurrent transmissions (uploads & downloads). Set the maximum amount of concurrent transmissions (uploads & downloads).
A value that is too high may result in network related issues. A value that is too high may result in network related issues.
Defaults to 1. Defaults to 1.
max_message_cache_size (``int``, *optional*):
Set the maximum size of the message cache.
Defaults to 10000.
max_business_user_connection_cache_size (``int``, *optional*):
Set the maximum size of the message cache.
Defaults to 10000.
client_platform (:obj:`~pyrogram.enums.ClientPlatform`, *optional*):
The platform where this client is running.
Defaults to 'other'
""" """
APP_VERSION = f"Pyrogram {__version__}" APP_VERSION = f"Pyrogram {__version__}"
@ -227,21 +196,17 @@ class Client(Methods):
SYSTEM_VERSION = f"{platform.system()} {platform.release()}" SYSTEM_VERSION = f"{platform.system()} {platform.release()}"
LANG_CODE = "en" LANG_CODE = "en"
LANG_PACK = ""
SYSTEM_LANG_CODE = "en-US"
PARENT_DIR = Path(sys.argv[0]).parent PARENT_DIR = Path(sys.argv[0]).parent
INVITE_LINK_RE = re.compile(r"^(?:https?://)?(?:www\.)?(?:t(?:elegram)?\.(?:org|me|dog)/(?:joinchat/|\+))([\w-]+)$") INVITE_LINK_RE = re.compile(r"^(?:https?://)?(?:www\.)?(?:t(?:elegram)?\.(?:org|me|dog)/(?:joinchat/|\+))([\w-]+)$")
UPGRADED_GIFT_RE = re.compile(r"^(?:https?://)?(?:www\.)?(?:t(?:elegram)?\.(?:org|me|dog)/(?:nft/|\+))([\w-]+)$")
WORKERS = min(32, (os.cpu_count() or 0) + 4) # os.cpu_count() can be None WORKERS = min(32, (os.cpu_count() or 0) + 4) # os.cpu_count() can be None
WORKDIR = PARENT_DIR WORKDIR = PARENT_DIR
# Interval of seconds in which the updates watchdog will kick in # Interval of seconds in which the updates watchdog will kick in
UPDATES_WATCHDOG_INTERVAL = 15 * 60 UPDATES_WATCHDOG_INTERVAL = 5 * 60
MAX_CONCURRENT_TRANSMISSIONS = 1 MAX_CONCURRENT_TRANSMISSIONS = 1
MAX_CACHE_SIZE = 10000
mimetypes = MimeTypes() mimetypes = MimeTypes()
mimetypes.readfp(StringIO(mime_types)) mimetypes.readfp(StringIO(mime_types))
@ -249,40 +214,33 @@ class Client(Methods):
def __init__( def __init__(
self, self,
name: str, name: str,
api_id: Optional[Union[int, str]] = None, api_id: Union[int, str] = None,
api_hash: Optional[str] = None, api_hash: str = None,
app_version: str = APP_VERSION, app_version: str = APP_VERSION,
device_model: str = DEVICE_MODEL, device_model: str = DEVICE_MODEL,
system_version: str = SYSTEM_VERSION, system_version: str = SYSTEM_VERSION,
system_lang_code: str = SYSTEM_LANG_CODE,
lang_code: str = LANG_CODE, lang_code: str = LANG_CODE,
lang_pack: str = LANG_PACK, ipv6: bool = False,
ipv6: Optional[bool] = False, alt_port: bool = False,
alt_port: Optional[bool] = False, proxy: dict = None,
proxy: Optional[dict] = None, test_mode: bool = False,
test_mode: Optional[bool] = False, bot_token: str = None,
bot_token: Optional[str] = None, session_string: str = None,
session_string: Optional[str] = None, in_memory: bool = None,
use_qrcode: Optional[bool] = False, mongodb: dict = None,
in_memory: Optional[bool] = None, storage: Storage = None,
mongodb: Optional[dict] = None, phone_number: str = None,
storage: Optional[Storage] = None, phone_code: str = None,
phone_number: Optional[str] = None, password: str = None,
phone_code: Optional[str] = None,
password: Optional[str] = None,
workers: int = WORKERS, workers: int = WORKERS,
workdir: Union[str, Path] = WORKDIR, workdir: str = WORKDIR,
plugins: Optional[dict] = None, plugins: dict = None,
parse_mode: "enums.ParseMode" = enums.ParseMode.DEFAULT, parse_mode: "enums.ParseMode" = enums.ParseMode.DEFAULT,
no_updates: Optional[bool] = None, no_updates: bool = None,
skip_updates: bool = True,
takeout: bool = None, takeout: bool = None,
sleep_threshold: int = Session.SLEEP_THRESHOLD, sleep_threshold: int = Session.SLEEP_THRESHOLD,
hide_password: Optional[bool] = True, hide_password: bool = False,
max_concurrent_transmissions: int = MAX_CONCURRENT_TRANSMISSIONS, max_concurrent_transmissions: int = MAX_CONCURRENT_TRANSMISSIONS
client_platform: "enums.ClientPlatform" = enums.ClientPlatform.OTHER,
max_message_cache_size: int = MAX_CACHE_SIZE,
max_business_user_connection_cache_size: int = MAX_CACHE_SIZE
): ):
super().__init__() super().__init__()
@ -292,16 +250,13 @@ class Client(Methods):
self.app_version = app_version self.app_version = app_version
self.device_model = device_model self.device_model = device_model
self.system_version = system_version self.system_version = system_version
self.system_lang_code = system_lang_code.lower()
self.lang_code = lang_code.lower() self.lang_code = lang_code.lower()
self.lang_pack = lang_pack.lower()
self.ipv6 = ipv6 self.ipv6 = ipv6
self.alt_port = alt_port self.alt_port = alt_port
self.proxy = proxy self.proxy = proxy
self.test_mode = test_mode self.test_mode = test_mode
self.bot_token = bot_token self.bot_token = bot_token
self.session_string = session_string self.session_string = session_string
self.use_qrcode = use_qrcode
self.in_memory = in_memory self.in_memory = in_memory
self.mongodb = mongodb self.mongodb = mongodb
self.phone_number = phone_number self.phone_number = phone_number
@ -312,15 +267,10 @@ class Client(Methods):
self.plugins = plugins self.plugins = plugins
self.parse_mode = parse_mode self.parse_mode = parse_mode
self.no_updates = no_updates self.no_updates = no_updates
self.skip_updates = skip_updates
self.takeout = takeout self.takeout = takeout
self.sleep_threshold = sleep_threshold self.sleep_threshold = sleep_threshold
self.hide_password = hide_password self.hide_password = hide_password
self.max_concurrent_transmissions = max_concurrent_transmissions self.max_concurrent_transmissions = max_concurrent_transmissions
self.client_platform = client_platform
self.max_message_cache_size = max_message_cache_size
self.max_message_cache_size = max_message_cache_size
self.max_business_user_connection_cache_size = max_business_user_connection_cache_size
self.executor = ThreadPoolExecutor(self.workers, thread_name_prefix="Handler") self.executor = ThreadPoolExecutor(self.workers, thread_name_prefix="Handler")
@ -331,20 +281,10 @@ class Client(Methods):
elif self.in_memory: elif self.in_memory:
self.storage = MemoryStorage(self.name) self.storage = MemoryStorage(self.name)
elif self.mongodb: elif self.mongodb:
if not MONGO_AVAIL: self.storage = MongoStorage(self.name, **self.mongodb)
log.warning(
"pymongo is missing! "
"Using MemoryStorage as session storage"
)
self.storage = MemoryStorage(self.name)
else:
self.storage = MongoStorage(self.name, **self.mongodb)
else: else:
self.storage = FileStorage(self.name, self.workdir) self.storage = FileStorage(self.name, self.workdir)
self.connection_factory = Connection
self.protocol_factory = TCPAbridged
self.dispatcher = Dispatcher(self) self.dispatcher = Dispatcher(self)
self.rnd_id = MsgId self.rnd_id = MsgId
@ -368,8 +308,7 @@ class Client(Methods):
self.me: Optional[User] = None self.me: Optional[User] = None
self.message_cache = Cache(self.max_message_cache_size) self.message_cache = Cache(10000)
self.business_user_connection_cache = Cache(self.max_business_user_connection_cache_size)
# Sometimes, for some reason, the server will stop sending updates and will only respond to pings. # Sometimes, for some reason, the server will stop sending updates and will only respond to pings.
# This watchdog will invoke updates.GetState in order to wake up the server and enable it sending updates again # This watchdog will invoke updates.GetState in order to wake up the server and enable it sending updates again
@ -377,7 +316,7 @@ class Client(Methods):
self.updates_watchdog_task = None self.updates_watchdog_task = None
self.updates_watchdog_event = asyncio.Event() self.updates_watchdog_event = asyncio.Event()
self.last_update_time = datetime.now() self.last_update_time = datetime.now()
self.listeners = {listener_type: [] for listener_type in pyrogram.enums.ListenerTypes}
self.loop = asyncio.get_event_loop() self.loop = asyncio.get_event_loop()
def __enter__(self): def __enter__(self):
@ -410,15 +349,6 @@ class Client(Methods):
if datetime.now() - self.last_update_time > timedelta(seconds=self.UPDATES_WATCHDOG_INTERVAL): if datetime.now() - self.last_update_time > timedelta(seconds=self.UPDATES_WATCHDOG_INTERVAL):
await self.invoke(raw.functions.updates.GetState()) await self.invoke(raw.functions.updates.GetState())
async def _wait_for_update_login_token(self):
"""
Wait for an UpdateLoginToken update from Telegram.
"""
while True:
update, _, _ = await self.dispatcher.updates_queue.get()
if isinstance(update, raw.types.UpdateLoginToken):
break
async def authorize(self) -> User: async def authorize(self) -> User:
if self.bot_token: if self.bot_token:
return await self.sign_in_bot(self.bot_token) return await self.sign_in_bot(self.bot_token)
@ -426,60 +356,52 @@ class Client(Methods):
print(f"Welcome to Pyrogram (version {__version__})") print(f"Welcome to Pyrogram (version {__version__})")
print(f"Pyrogram is free software and comes with ABSOLUTELY NO WARRANTY. Licensed\n" print(f"Pyrogram is free software and comes with ABSOLUTELY NO WARRANTY. Licensed\n"
f"under the terms of the {__license__}.\n") f"under the terms of the {__license__}.\n")
if not self.use_qrcode:
while True:
try:
if not self.phone_number:
while True:
print("Enter 'qrcode' if you want to login with qrcode.")
value = await ainput("Enter phone number or bot token: ")
if not value:
continue
if value.lower() == "qrcode":
self.use_qrcode = True
break
confirm = (await ainput(f'Is "{value}" correct? (y/N): ')).lower()
if confirm == "y":
break
if ":" in value:
self.bot_token = value
return await self.sign_in_bot(value)
else:
self.phone_number = value
if not self.use_qrcode:
sent_code = await self.send_code(self.phone_number)
except BadRequest as e:
print(e.MESSAGE)
self.phone_number = None
self.bot_token = None
else:
break
if not self.use_qrcode:
sent_code_descriptions = {
enums.SentCodeType.APP: "Telegram app",
enums.SentCodeType.SMS: "SMS",
enums.SentCodeType.CALL: "phone call",
enums.SentCodeType.FLASH_CALL: "phone flash call",
enums.SentCodeType.FRAGMENT_SMS: "Fragment SMS",
enums.SentCodeType.EMAIL_CODE: "email code"
}
print(f"The confirmation code has been sent via {sent_code_descriptions[sent_code.type]}")
while True: while True:
if not self.use_qrcode and not self.phone_code: try:
if not self.phone_number:
while True:
value = await ainput("Enter phone number or bot token: ")
if not value:
continue
confirm = (await ainput(f'Is "{value}" correct? (y/N): ')).lower()
if confirm == "y":
break
if ":" in value:
self.bot_token = value
return await self.sign_in_bot(value)
else:
self.phone_number = value
sent_code = await self.send_code(self.phone_number)
except BadRequest as e:
print(e.MESSAGE)
self.phone_number = None
self.bot_token = None
else:
break
sent_code_descriptions = {
enums.SentCodeType.APP: "Telegram app",
enums.SentCodeType.SMS: "SMS",
enums.SentCodeType.CALL: "phone call",
enums.SentCodeType.FLASH_CALL: "phone flash call",
enums.SentCodeType.FRAGMENT_SMS: "Fragment SMS",
enums.SentCodeType.EMAIL_CODE: "email code"
}
print(f"The confirmation code has been sent via {sent_code_descriptions[sent_code.type]}")
while True:
if not self.phone_code:
self.phone_code = await ainput("Enter confirmation code: ") self.phone_code = await ainput("Enter confirmation code: ")
try: try:
if self.use_qrcode: signed_in = await self.sign_in(self.phone_number, sent_code.phone_code_hash, self.phone_code)
signed_in = await self.sign_in_qrcode()
else:
signed_in = await self.sign_in(self.phone_number, sent_code.phone_code_hash, self.phone_code)
except BadRequest as e: except BadRequest as e:
print(e.MESSAGE) print(e.MESSAGE)
self.phone_code = None self.phone_code = None
@ -518,18 +440,33 @@ class Client(Methods):
print(e.MESSAGE) print(e.MESSAGE)
self.password = None self.password = None
else: else:
if self.use_qrcode and isinstance(signed_in, types.LoginToken):
time_out = signed_in.expires - datetime.timestamp(datetime.now())
try:
await asyncio.wait_for(self._wait_for_update_login_token(), timeout=time_out)
except asyncio.TimeoutError:
print("QR code expired, Requesting new Qr code...")
continue
break break
if isinstance(signed_in, User): if isinstance(signed_in, User):
return signed_in return signed_in
while True:
first_name = await ainput("Enter first name: ")
last_name = await ainput("Enter last name (empty to skip): ")
try:
signed_up = await self.sign_up(
self.phone_number,
sent_code.phone_code_hash,
first_name,
last_name
)
except BadRequest as e:
print(e.MESSAGE)
else:
break
if isinstance(signed_in, TermsOfService):
print("\n" + signed_in.text + "\n")
await self.accept_terms_of_service(signed_in.id)
return signed_up
def set_parse_mode(self, parse_mode: Optional["enums.ParseMode"]): def set_parse_mode(self, parse_mode: Optional["enums.ParseMode"]):
"""Set the parse mode to be used globally by the client. """Set the parse mode to be used globally by the client.
@ -571,7 +508,6 @@ class Client(Methods):
async def fetch_peers(self, peers: List[Union[raw.types.User, raw.types.Chat, raw.types.Channel]]) -> bool: async def fetch_peers(self, peers: List[Union[raw.types.User, raw.types.Chat, raw.types.Channel]]) -> bool:
is_min = False is_min = False
parsed_peers = [] parsed_peers = []
usernames = []
for peer in peers: for peer in peers:
if getattr(peer, "min", False): if getattr(peer, "min", False):
@ -589,9 +525,6 @@ class Client(Methods):
else peer.usernames[0].username.lower() if peer.usernames else peer.usernames[0].username.lower() if peer.usernames
else None else None
) )
if peer.usernames is not None and len(peer.usernames) > 1:
for uname in peer.usernames:
usernames.append((peer_id, uname.username.lower()))
phone_number = peer.phone phone_number = peer.phone
peer_type = "bot" if peer.bot else "user" peer_type = "bot" if peer.bot else "user"
elif isinstance(peer, (raw.types.Chat, raw.types.ChatForbidden)): elif isinstance(peer, (raw.types.Chat, raw.types.ChatForbidden)):
@ -606,9 +539,6 @@ class Client(Methods):
else peer.usernames[0].username.lower() if peer.usernames else peer.usernames[0].username.lower() if peer.usernames
else None else None
) )
if peer.usernames is not None and len(peer.usernames) > 1:
for uname in peer.usernames:
usernames.append((peer_id, uname.username.lower()))
peer_type = "channel" if peer.broadcast else "supergroup" peer_type = "channel" if peer.broadcast else "supergroup"
elif isinstance(peer, raw.types.ChannelForbidden): elif isinstance(peer, raw.types.ChannelForbidden):
peer_id = utils.get_channel_id(peer.id) peer_id = utils.get_channel_id(peer.id)
@ -620,7 +550,6 @@ class Client(Methods):
parsed_peers.append((peer_id, access_hash, peer_type, username, phone_number)) parsed_peers.append((peer_id, access_hash, peer_type, username, phone_number))
await self.storage.update_peers(parsed_peers) await self.storage.update_peers(parsed_peers)
await self.storage.update_usernames(usernames)
return is_min return is_min
@ -648,17 +577,6 @@ class Client(Methods):
pts = getattr(update, "pts", None) pts = getattr(update, "pts", None)
pts_count = getattr(update, "pts_count", None) pts_count = getattr(update, "pts_count", None)
if pts:
await self.storage.update_state(
(
utils.get_channel_id(channel_id) if channel_id else 0,
pts,
None,
updates.date,
None
)
)
if isinstance(update, raw.types.UpdateChannelTooLong): if isinstance(update, raw.types.UpdateChannelTooLong):
log.info(update) log.info(update)
@ -677,11 +595,10 @@ class Client(Methods):
)] )]
), ),
pts=pts - pts_count, pts=pts - pts_count,
limit=pts, limit=pts
force=False
) )
) )
except (ChannelPrivate, PersistentTimestampOutdated, PersistentTimestampInvalid): except ChannelPrivate:
pass pass
else: else:
if not isinstance(diff, raw.types.updates.ChannelDifferenceEmpty): if not isinstance(diff, raw.types.updates.ChannelDifferenceEmpty):
@ -690,16 +607,6 @@ class Client(Methods):
self.dispatcher.updates_queue.put_nowait((update, users, chats)) self.dispatcher.updates_queue.put_nowait((update, users, chats))
elif isinstance(updates, (raw.types.UpdateShortMessage, raw.types.UpdateShortChatMessage)): elif isinstance(updates, (raw.types.UpdateShortMessage, raw.types.UpdateShortChatMessage)):
await self.storage.update_state(
(
0,
updates.pts,
None,
updates.date,
None
)
)
diff = await self.invoke( diff = await self.invoke(
raw.functions.updates.GetDifference( raw.functions.updates.GetDifference(
pts=updates.pts - updates.pts_count, pts=updates.pts - updates.pts_count,
@ -726,92 +633,6 @@ class Client(Methods):
elif isinstance(updates, raw.types.UpdatesTooLong): elif isinstance(updates, raw.types.UpdatesTooLong):
log.info(updates) log.info(updates)
async def recover_gaps(self) -> Tuple[int, int]:
states = await self.storage.update_state()
message_updates_counter = 0
other_updates_counter = 0
if not states:
log.info("No states found, skipping recovery.")
return (message_updates_counter, other_updates_counter)
for state in states:
id, local_pts, _, local_date, _ = state
prev_pts = 0
while True:
try:
diff = await self.invoke(
raw.functions.updates.GetChannelDifference(
channel=await self.resolve_peer(id),
filter=raw.types.ChannelMessagesFilterEmpty(),
pts=local_pts,
limit=10000,
force=False
) if id < 0 else
raw.functions.updates.GetDifference(
pts=local_pts,
date=local_date,
qts=0
)
)
except (ChannelPrivate, ChannelInvalid, PersistentTimestampOutdated, PersistentTimestampInvalid):
break
if isinstance(diff, raw.types.updates.DifferenceEmpty):
break
elif isinstance(diff, raw.types.updates.DifferenceTooLong):
break
elif isinstance(diff, raw.types.updates.Difference):
local_pts = diff.state.pts
elif isinstance(diff, raw.types.updates.DifferenceSlice):
local_pts = diff.intermediate_state.pts
local_date = diff.intermediate_state.date
if prev_pts == local_pts:
break
prev_pts = local_pts
elif isinstance(diff, raw.types.updates.ChannelDifferenceEmpty):
break
elif isinstance(diff, raw.types.updates.ChannelDifferenceTooLong):
break
elif isinstance(diff, raw.types.updates.ChannelDifference):
local_pts = diff.pts
users = {i.id: i for i in diff.users}
chats = {i.id: i for i in diff.chats}
for message in diff.new_messages:
message_updates_counter += 1
self.dispatcher.updates_queue.put_nowait(
(
raw.types.UpdateNewMessage(
message=message,
pts=local_pts,
pts_count=-1
),
users,
chats
)
)
for update in diff.other_updates:
other_updates_counter += 1
self.dispatcher.updates_queue.put_nowait(
(update, users, chats)
)
if isinstance(diff, (raw.types.updates.Difference, raw.types.updates.ChannelDifference)):
break
await self.storage.update_state(id)
log.info("Recovered %s messages and %s updates.", message_updates_counter, other_updates_counter)
return (message_updates_counter, other_updates_counter)
async def load_session(self): async def load_session(self):
await self.storage.open() await self.storage.open()
@ -825,7 +646,7 @@ class Client(Methods):
if session_empty: if session_empty:
if not self.api_id or not self.api_hash: if not self.api_id or not self.api_hash:
raise AttributeError("The API key is required for new authorizations. " raise AttributeError("The API key is required for new authorizations. "
"More info: https://pyrofork.wulan17.dev/main/start/auth") "More info: https://pyrofork.mayuri.my.id/start/auth")
await self.storage.api_id(self.api_id) await self.storage.api_id(self.api_id)
@ -863,12 +684,6 @@ class Client(Methods):
except Exception as e: except Exception as e:
print(e) print(e)
def is_excluded(self, exclude, module):
for e in exclude:
if module == e or module.startswith(e + '.'):
return True
return False
def load_plugins(self): def load_plugins(self):
if self.plugins: if self.plugins:
plugins = self.plugins.copy() plugins = self.plugins.copy()
@ -887,178 +702,40 @@ class Client(Methods):
include = plugins.get("include", []) include = plugins.get("include", [])
exclude = plugins.get("exclude", []) exclude = plugins.get("exclude", [])
exclude_plugins = []
exclude_handlers = {}
if exclude:
for path, handler in exclude:
module_path = os.path.join(
root.replace(".", "/"), path.replace(".", "/")
)
if handler is None:
exclude_plugins.append(module_path.replace("/", ".").replace("\\", "."))
else:
exclude_handlers[module_path.replace("/", ".").replace("\\", ".")] = handler
count = 0 count = 0
if not include: if not include:
for current_root, _, filenames in os.walk(root.replace(".", "/")): for path in sorted(Path(root.replace(".", "/")).rglob("*.py")):
namespace = current_root.replace("/", ".").replace("\\", ".") module_path = '.'.join(path.parent.parts + (path.stem,))
if "__pycache__" in namespace: module = import_module(module_path)
continue
if namespace in exclude_plugins:
log.warning(
'[%s] [LOAD] Ignoring namespace "%s"', self.name, namespace
)
continue
else:
for filename in filenames:
if filename.endswith(".py"):
module_path = namespace + "." + filename[:-3]
if module_path in exclude_plugins:
log.warning(
'[%s] [LOAD] Ignoring namespace "%s"',
self.name,
module_path,
)
continue
else:
module = import_module(module_path)
for name in vars(module).keys(): for name in vars(module).keys():
# noinspection PyBroadException
try:
for handler, group in getattr(module, name).handlers:
if isinstance(handler, Handler) and isinstance(group, int):
self.add_handler(handler, group)
# noinspection PyBroadException log.info('[{}] [LOAD] {}("{}") in group {} from "{}"'.format(
try: self.name, type(handler).__name__, name, group, module_path))
for handler, group in getattr(
module, name
).handlers:
if isinstance(
handler, Handler
) and isinstance(group, int):
if ( count += 1
module_path in exclude_handlers except Exception:
and name pass
in exclude_handlers[module_path]
):
exclude_handlers[
module_path
].remove(name)
log.warning(
'[{}] [LOAD] Ignoring function "{}" from group {} in "{}"'.format(
self.name,
name,
group,
module_path,
)
)
continue
self.add_handler(handler, group)
log.info(
'[{}] [LOAD] {}("{}") in group {} from "{}"'.format(
self.name,
type(handler).__name__,
name,
group,
module_path,
)
)
count += 1
except Exception:
pass
else: else:
for path, handlers in include: for path, handlers in include:
module_path = root.replace("/", ".").replace("\\", ".") + "." + path module_path = root + "." + path
if self.is_excluded(exclude_plugins, module_path):
log.warning(
'[%s] [LOAD] Ignoring namespace "%s"', self.name, module_path
)
continue
warn_non_existent_functions = True warn_non_existent_functions = True
try: try:
module = import_module(module_path) module = import_module(module_path)
except ImportError: except ImportError:
log.warning( log.warning('[%s] [LOAD] Ignoring non-existent module "%s"', self.name, module_path)
'[%s] [LOAD] Ignoring non-existent module "%s"',
self.name,
module_path,
)
continue continue
if "__path__" in dir(module): if "__path__" in dir(module):
for current_root, _, filenames in os.walk(module_path.replace(".", "/")): log.warning('[%s] [LOAD] Ignoring namespace "%s"', self.name, module_path)
namespace = current_root.replace("/", ".").replace("\\", ".") continue
if "__pycache__" in namespace:
continue
if namespace in exclude_plugins:
log.warning(
'[%s] [LOAD] Ignoring namespace "%s"', self.name, namespace
)
continue
else:
for filename in filenames:
if filename.endswith(".py"):
module_path = namespace + "." + filename[:-3]
if module_path in exclude_plugins:
log.warning(
'[%s] [LOAD] Ignoring namespace "%s"',
self.name,
module_path,
)
continue
else:
module = import_module(module_path)
for name in vars(module).keys():
# noinspection PyBroadException
try:
for handler, group in getattr(
module, name
).handlers:
if isinstance(
handler, Handler
) and isinstance(group, int):
if (
module_path in exclude_handlers
and name
in exclude_handlers[module_path]
):
exclude_handlers[
module_path
].remove(name)
log.warning(
'[{}] [LOAD] Ignoring function "{}" from group {} in "{}"'.format(
self.name,
name,
group,
module_path,
)
)
continue
self.add_handler(handler, group)
log.info(
'[{}] [LOAD] {}("{}") in group {} from "{}"'.format(
self.name,
type(handler).__name__,
name,
group,
module_path,
)
)
count += 1
except Exception:
pass
if handlers is None: if handlers is None:
handlers = vars(module).keys() handlers = vars(module).keys()
@ -1069,59 +746,62 @@ class Client(Methods):
try: try:
for handler, group in getattr(module, name).handlers: for handler, group in getattr(module, name).handlers:
if isinstance(handler, Handler) and isinstance(group, int): if isinstance(handler, Handler) and isinstance(group, int):
if (
module_path in exclude_handlers
and name in exclude_handlers[module_path]
):
exclude_handlers[module_path].remove(name)
log.warning(
'[{}] [LOAD] Ignoring function "{}" from group {} in "{}"'.format(
self.name, name, group, module_path
)
)
continue
self.add_handler(handler, group) self.add_handler(handler, group)
log.info( log.info('[{}] [LOAD] {}("{}") in group {} from "{}"'.format(
'[{}] [LOAD] {}("{}") in group {} from "{}"'.format( self.name, type(handler).__name__, name, group, module_path))
self.name,
type(handler).__name__,
name,
group,
module_path,
)
)
count += 1 count += 1
except Exception: except Exception:
if warn_non_existent_functions: if warn_non_existent_functions:
log.warning( log.warning('[{}] [LOAD] Ignoring non-existent function "{}" from "{}"'.format(
'[{}] [LOAD] Ignoring non-existent function "{}" from "{}"'.format( self.name, name, module_path))
self.name, name, module_path
)
)
for module in exclude_handlers: if exclude:
for handler in exclude_handlers[module]: for path, handlers in exclude:
log.warning( module_path = root + "." + path
'[{}] [LOAD] Ignoring non-existent function "{}" from "{}"'.format( warn_non_existent_functions = True
self.name, handler, module
) try:
) module = import_module(module_path)
except ImportError:
log.warning('[%s] [UNLOAD] Ignoring non-existent module "%s"', self.name, module_path)
continue
if "__path__" in dir(module):
log.warning('[%s] [UNLOAD] Ignoring namespace "%s"', self.name, module_path)
continue
if handlers is None:
handlers = vars(module).keys()
warn_non_existent_functions = False
for name in handlers:
# noinspection PyBroadException
try:
for handler, group in getattr(module, name).handlers:
if isinstance(handler, Handler) and isinstance(group, int):
self.remove_handler(handler, group)
log.info('[{}] [UNLOAD] {}("{}") from group {} in "{}"'.format(
self.name, type(handler).__name__, name, group, module_path))
count -= 1
except Exception:
if warn_non_existent_functions:
log.warning('[{}] [UNLOAD] Ignoring non-existent function "{}" from "{}"'.format(
self.name, name, module_path))
if count > 0: if count > 0:
log.info( log.info('[{}] Successfully loaded {} plugin{} from "{}"'.format(
'[{}] Successfully loaded {} plugin{} from "{}"'.format( self.name, count, "s" if count > 1 else "", root))
self.name, count, "s" if count > 1 else "", root
)
)
else: else:
log.warning('[%s] No plugin loaded from "%s"', self.name, root) log.warning('[%s] No plugin loaded from "%s"', self.name, root)
async def handle_download(self, packet): async def handle_download(self, packet):
file_id, directory, file_name, in_memory, file_size, progress, progress_args = packet file_id, directory, file_name, in_memory, file_size, progress, progress_args = packet
_ = os.makedirs(directory, exist_ok=True) if not in_memory else None os.makedirs(directory, exist_ok=True) if not in_memory else None
temp_file_path = os.path.abspath(re.sub("\\\\", "/", os.path.join(directory, file_name))) + ".temp" temp_file_path = os.path.abspath(re.sub("\\\\", "/", os.path.join(directory, file_name))) + ".temp"
file = BytesIO() if in_memory else open(temp_file_path, "wb") file = BytesIO() if in_memory else open(temp_file_path, "wb")
@ -1136,9 +816,6 @@ class Client(Methods):
if isinstance(e, asyncio.CancelledError): if isinstance(e, asyncio.CancelledError):
raise e raise e
if isinstance(e, pyrogram.errors.FloodWait):
raise e
return None return None
else: else:
if in_memory: if in_memory:
@ -1361,8 +1038,6 @@ class Client(Methods):
await cdn_session.stop() await cdn_session.stop()
except pyrogram.StopTransmission: except pyrogram.StopTransmission:
raise raise
except pyrogram.errors.FloodWait:
raise
except Exception as e: except Exception as e:
log.exception(e) log.exception(e)
finally: finally:

View file

@ -1,24 +1,19 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from .connection import Connection from .connection import Connection
__all__ = [
"Connection"
]

View file

@ -19,7 +19,7 @@
import asyncio import asyncio
import logging import logging
from typing import Optional, Type from typing import Optional
from .transport import TCP, TCPAbridged from .transport import TCP, TCPAbridged
from ..session.internals import DataCenter from ..session.internals import DataCenter
@ -30,30 +30,20 @@ log = logging.getLogger(__name__)
class Connection: class Connection:
MAX_CONNECTION_ATTEMPTS = 3 MAX_CONNECTION_ATTEMPTS = 3
def __init__( def __init__(self, dc_id: int, test_mode: bool, ipv6: bool, alt_port: bool, proxy: dict, media: bool = False):
self,
dc_id: int,
test_mode: bool,
ipv6: bool,
alt_port: bool,
proxy: dict,
media: bool = False,
protocol_factory: Type[TCP] = TCPAbridged
) -> None:
self.dc_id = dc_id self.dc_id = dc_id
self.test_mode = test_mode self.test_mode = test_mode
self.ipv6 = ipv6 self.ipv6 = ipv6
self.alt_port = alt_port self.alt_port = alt_port
self.proxy = proxy self.proxy = proxy
self.media = media self.media = media
self.protocol_factory = protocol_factory
self.address = DataCenter(dc_id, test_mode, ipv6, alt_port, media) self.address = DataCenter(dc_id, test_mode, ipv6, alt_port, media)
self.protocol: Optional[TCP] = None self.protocol: TCP = None
async def connect(self) -> None: async def connect(self):
for _ in range(Connection.MAX_CONNECTION_ATTEMPTS): for i in range(Connection.MAX_CONNECTION_ATTEMPTS):
self.protocol = self.protocol_factory(ipv6=self.ipv6, proxy=self.proxy) self.protocol = TCPAbridged(self.ipv6, self.proxy)
try: try:
log.info("Connecting...") log.info("Connecting...")
@ -73,11 +63,11 @@ class Connection:
log.warning("Connection failed! Trying again...") log.warning("Connection failed! Trying again...")
raise ConnectionError raise ConnectionError
async def close(self) -> None: async def close(self):
await self.protocol.close() await self.protocol.close()
log.info("Disconnected") log.info("Disconnected")
async def send(self, data: bytes) -> None: async def send(self, data: bytes):
await self.protocol.send(data) await self.protocol.send(data)
async def recv(self) -> Optional[bytes]: async def recv(self) -> Optional[bytes]:

View file

@ -1,23 +1,19 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from .tcp import * from .tcp import *
__all__ = []
__all__.extend(tcp.__all__)

View file

@ -1,35 +1,24 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from .tcp import TCP, Proxy from .tcp import TCP
from .tcp_abridged import TCPAbridged from .tcp_abridged import TCPAbridged
from .tcp_abridged_o import TCPAbridgedO from .tcp_abridged_o import TCPAbridgedO
from .tcp_full import TCPFull from .tcp_full import TCPFull
from .tcp_intermediate import TCPIntermediate from .tcp_intermediate import TCPIntermediate
from .tcp_intermediate_o import TCPIntermediateO from .tcp_intermediate_o import TCPIntermediateO
__all__ = [
"TCP",
"Proxy",
"TCPAbridged",
"TCPAbridgedO",
"TCPFull",
"TCPIntermediate",
"TCPIntermediateO"
]

View file

@ -1,154 +1,109 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import asyncio import asyncio
import ipaddress import ipaddress
import logging import logging
import socket import socket
from typing import Tuple, Dict, TypedDict, Optional from concurrent.futures import ThreadPoolExecutor
import socks import socks
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
proxy_type_by_scheme: Dict[str, int] = {
"SOCKS4": socks.SOCKS4,
"SOCKS5": socks.SOCKS5,
"HTTP": socks.HTTP,
}
class Proxy(TypedDict):
scheme: str
hostname: str
port: int
username: Optional[str]
password: Optional[str]
class TCP: class TCP:
TIMEOUT = 10 TIMEOUT = 10
def __init__(self, ipv6: bool, proxy: Proxy) -> None: def __init__(self, ipv6: bool, proxy: dict):
self.ipv6 = ipv6 self.socket = None
self.proxy = proxy
self.reader: Optional[asyncio.StreamReader] = None self.reader = None
self.writer: Optional[asyncio.StreamWriter] = None self.writer = None
self.lock = asyncio.Lock() self.lock = asyncio.Lock()
self.loop = asyncio.get_event_loop() self.loop = asyncio.get_event_loop()
async def _connect_via_proxy( self.proxy = proxy
self,
destination: Tuple[str, int]
) -> None:
scheme = self.proxy.get("scheme")
if scheme is None:
raise ValueError("No scheme specified")
proxy_type = proxy_type_by_scheme.get(scheme.upper()) if proxy:
if proxy_type is None: hostname = proxy.get("hostname")
raise ValueError(f"Unknown proxy type {scheme}")
hostname = self.proxy.get("hostname") try:
port = self.proxy.get("port") ip_address = ipaddress.ip_address(hostname)
username = self.proxy.get("username") except ValueError:
password = self.proxy.get("password") self.socket = socks.socksocket(socket.AF_INET)
else:
if isinstance(ip_address, ipaddress.IPv6Address):
self.socket = socks.socksocket(socket.AF_INET6)
else:
self.socket = socks.socksocket(socket.AF_INET)
try: self.socket.set_proxy(
ip_address = ipaddress.ip_address(hostname) proxy_type=getattr(socks, proxy.get("scheme").upper()),
except ValueError: addr=hostname,
is_proxy_ipv6 = False port=proxy.get("port", None),
username=proxy.get("username", None),
password=proxy.get("password", None)
)
self.socket.settimeout(TCP.TIMEOUT)
log.info("Using proxy %s", hostname)
else: else:
is_proxy_ipv6 = isinstance(ip_address, ipaddress.IPv6Address) self.socket = socket.socket(
socket.AF_INET6 if ipv6
else socket.AF_INET
)
proxy_family = socket.AF_INET6 if is_proxy_ipv6 else socket.AF_INET self.socket.setblocking(False)
sock = socks.socksocket(proxy_family)
sock.set_proxy( async def connect(self, address: tuple):
proxy_type=proxy_type,
addr=hostname,
port=port,
username=username,
password=password
)
sock.settimeout(TCP.TIMEOUT)
await self.loop.sock_connect(
sock=sock,
address=destination
)
sock.setblocking(False)
self.reader, self.writer = await asyncio.open_connection(
sock=sock
)
async def _connect_via_direct(
self,
destination: Tuple[str, int]
) -> None:
host, port = destination
family = socket.AF_INET6 if self.ipv6 else socket.AF_INET
self.reader, self.writer = await asyncio.open_connection(
host=host,
port=port,
family=family
)
async def _connect(self, destination: Tuple[str, int]) -> None:
if self.proxy: if self.proxy:
await self._connect_via_proxy(destination) with ThreadPoolExecutor(1) as executor:
await self.loop.run_in_executor(executor, self.socket.connect, address)
else: else:
await self._connect_via_direct(destination) try:
await asyncio.wait_for(asyncio.get_event_loop().sock_connect(self.socket, address), TCP.TIMEOUT)
except asyncio.TimeoutError: # Re-raise as TimeoutError. asyncio.TimeoutError is deprecated in 3.11
raise TimeoutError("Connection timed out")
async def connect(self, address: Tuple[str, int]) -> None: self.reader, self.writer = await asyncio.open_connection(sock=self.socket)
async def close(self):
try: try:
await asyncio.wait_for(self._connect(address), TCP.TIMEOUT) if self.writer is not None:
except asyncio.TimeoutError: # Re-raise as TimeoutError. asyncio.TimeoutError is deprecated in 3.11 self.writer.close()
raise TimeoutError("Connection timed out") await asyncio.wait_for(self.writer.wait_closed(), TCP.TIMEOUT)
async def close(self) -> None:
if self.writer is None:
return None
try:
self.writer.close()
await asyncio.wait_for(self.writer.wait_closed(), TCP.TIMEOUT)
except Exception as e: except Exception as e:
log.info("Close exception: %s %s", type(e).__name__, e) log.info("Close exception: %s %s", type(e).__name__, e)
async def send(self, data: bytes) -> None: async def send(self, data: bytes):
if self.writer is None:
return None
async with self.lock: async with self.lock:
try: try:
self.writer.write(data) if self.writer is not None:
await self.writer.drain() self.writer.write(data)
await self.writer.drain()
except Exception as e: except Exception as e:
log.info("Send exception: %s %s", type(e).__name__, e) log.info("Send exception: %s %s", type(e).__name__, e)
raise OSError(e) raise OSError(e)
async def recv(self, length: int = 0) -> Optional[bytes]: async def recv(self, length: int = 0):
data = b"" data = b""
while len(data) < length: while len(data) < length:

View file

@ -1,39 +1,38 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import logging import logging
from typing import Optional, Tuple from typing import Optional
from .tcp import TCP, Proxy from .tcp import TCP
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class TCPAbridged(TCP): class TCPAbridged(TCP):
def __init__(self, ipv6: bool, proxy: Proxy) -> None: def __init__(self, ipv6: bool, proxy: dict):
super().__init__(ipv6, proxy) super().__init__(ipv6, proxy)
async def connect(self, address: Tuple[str, int]) -> None: async def connect(self, address: tuple):
await super().connect(address) await super().connect(address)
await super().send(b"\xef") await super().send(b"\xef")
async def send(self, data: bytes, *args) -> None: async def send(self, data: bytes, *args):
length = len(data) // 4 length = len(data) // 4
await super().send( await super().send(

View file

@ -1,29 +1,28 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import logging import logging
import os import os
from typing import Optional, Tuple from typing import Optional
import pyrogram import pyrogram
from pyrogram.crypto import aes from pyrogram.crypto import aes
from .tcp import TCP, Proxy from .tcp import TCP
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -31,13 +30,13 @@ log = logging.getLogger(__name__)
class TCPAbridgedO(TCP): class TCPAbridgedO(TCP):
RESERVED = (b"HEAD", b"POST", b"GET ", b"OPTI", b"\xee" * 4) RESERVED = (b"HEAD", b"POST", b"GET ", b"OPTI", b"\xee" * 4)
def __init__(self, ipv6: bool, proxy: Proxy) -> None: def __init__(self, ipv6: bool, proxy: dict):
super().__init__(ipv6, proxy) super().__init__(ipv6, proxy)
self.encrypt = None self.encrypt = None
self.decrypt = None self.decrypt = None
async def connect(self, address: Tuple[str, int]) -> None: async def connect(self, address: tuple):
await super().connect(address) await super().connect(address)
while True: while True:
@ -56,7 +55,7 @@ class TCPAbridgedO(TCP):
await super().send(nonce) await super().send(nonce)
async def send(self, data: bytes, *args) -> None: async def send(self, data: bytes, *args):
length = len(data) // 4 length = len(data) // 4
data = (bytes([length]) if length <= 126 else b"\x7f" + length.to_bytes(3, "little")) + data data = (bytes([length]) if length <= 126 else b"\x7f" + length.to_bytes(3, "little")) + data
payload = await self.loop.run_in_executor(pyrogram.crypto_executor, aes.ctr256_encrypt, data, *self.encrypt) payload = await self.loop.run_in_executor(pyrogram.crypto_executor, aes.ctr256_encrypt, data, *self.encrypt)

View file

@ -1,43 +1,42 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import logging import logging
from binascii import crc32 from binascii import crc32
from struct import pack, unpack from struct import pack, unpack
from typing import Optional, Tuple from typing import Optional
from .tcp import TCP, Proxy from .tcp import TCP
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class TCPFull(TCP): class TCPFull(TCP):
def __init__(self, ipv6: bool, proxy: Proxy) -> None: def __init__(self, ipv6: bool, proxy: dict):
super().__init__(ipv6, proxy) super().__init__(ipv6, proxy)
self.seq_no: Optional[int] = None self.seq_no = None
async def connect(self, address: Tuple[str, int]) -> None: async def connect(self, address: tuple):
await super().connect(address) await super().connect(address)
self.seq_no = 0 self.seq_no = 0
async def send(self, data: bytes, *args) -> None: async def send(self, data: bytes, *args):
data = pack("<II", len(data) + 12, self.seq_no) + data data = pack("<II", len(data) + 12, self.seq_no) + data
data += pack("<I", crc32(data)) data += pack("<I", crc32(data))
self.seq_no += 1 self.seq_no += 1

View file

@ -1,40 +1,39 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import logging import logging
from struct import pack, unpack from struct import pack, unpack
from typing import Optional, Tuple from typing import Optional
from .tcp import TCP, Proxy from .tcp import TCP
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class TCPIntermediate(TCP): class TCPIntermediate(TCP):
def __init__(self, ipv6: bool, proxy: Proxy) -> None: def __init__(self, ipv6: bool, proxy: dict):
super().__init__(ipv6, proxy) super().__init__(ipv6, proxy)
async def connect(self, address: Tuple[str, int]) -> None: async def connect(self, address: tuple):
await super().connect(address) await super().connect(address)
await super().send(b"\xee" * 4) await super().send(b"\xee" * 4)
async def send(self, data: bytes, *args) -> None: async def send(self, data: bytes, *args):
await super().send(pack("<i", len(data)) + data) await super().send(pack("<i", len(data)) + data)
async def recv(self, length: int = 0) -> Optional[bytes]: async def recv(self, length: int = 0) -> Optional[bytes]:

View file

@ -1,29 +1,28 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import logging import logging
import os import os
from struct import pack, unpack from struct import pack, unpack
from typing import Optional, Tuple from typing import Optional
from pyrogram.crypto import aes from pyrogram.crypto import aes
from .tcp import TCP, Proxy from .tcp import TCP
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -31,13 +30,13 @@ log = logging.getLogger(__name__)
class TCPIntermediateO(TCP): class TCPIntermediateO(TCP):
RESERVED = (b"HEAD", b"POST", b"GET ", b"OPTI", b"\xee" * 4) RESERVED = (b"HEAD", b"POST", b"GET ", b"OPTI", b"\xee" * 4)
def __init__(self, ipv6: bool, proxy: Proxy) -> None: def __init__(self, ipv6: bool, proxy: dict):
super().__init__(ipv6, proxy) super().__init__(ipv6, proxy)
self.encrypt = None self.encrypt = None
self.decrypt = None self.decrypt = None
async def connect(self, address: Tuple[str, int]) -> None: async def connect(self, address: tuple):
await super().connect(address) await super().connect(address)
while True: while True:
@ -56,7 +55,7 @@ class TCPIntermediateO(TCP):
await super().send(nonce) await super().send(nonce)
async def send(self, data: bytes, *args) -> None: async def send(self, data: bytes, *args):
await super().send( await super().send(
aes.ctr256_encrypt( aes.ctr256_encrypt(
pack("<i", len(data)) + data, pack("<i", len(data)) + data,

View file

@ -1,18 +1,17 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import logging import logging
@ -55,7 +54,7 @@ except ImportError:
log.warning( log.warning(
"TgCrypto is missing! " "TgCrypto is missing! "
"Pyrogram will work the same, but at a much slower speed. " "Pyrogram will work the same, but at a much slower speed. "
"More info: https://pyrofork.wulan17.dev/main/topics/speedups" "More info: https://pyrofork.mayuri.my.id/topics/speedups"
) )

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from hashlib import sha256 from hashlib import sha256
from io import BytesIO from io import BytesIO
@ -71,7 +70,7 @@ def unpack(
message = Message.read(data) message = Message.read(data)
except KeyError as e: except KeyError as e:
if e.args[0] == 0: if e.args[0] == 0:
raise ConnectionError("Received empty data. Check your internet connection.") raise ConnectionError(f"Received empty data. Check your internet connection.")
left = data.read().hex() left = data.read().hex()

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from random import randint from random import randint
@ -55,7 +54,7 @@ def decompose(pq: int) -> int:
while g == 1: while g == 1:
x = y x = y
for _ in range(r): for i in range(r):
y = (pow(y, 2, pq) + c) % pq y = (pow(y, 2, pq) + c) % pq
k = 0 k = 0
@ -63,7 +62,7 @@ def decompose(pq: int) -> int:
while k < r and g == 1: while k < r and g == 1:
ys = y ys = y
for _ in range(min(m, r - k)): for i in range(min(m, r - k)):
y = (pow(y, 2, pq) + c) % pq y = (pow(y, 2, pq) + c) % pq
q = q * (abs(x - y)) % pq q = q * (abs(x - y)) % pq

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from collections import namedtuple from collections import namedtuple

View file

@ -21,51 +21,22 @@ import asyncio
import inspect import inspect
import logging import logging
from collections import OrderedDict from collections import OrderedDict
from typing import Any
import pyrogram import pyrogram
from pyrogram import raw, types, utils from pyrogram import utils
from pyrogram.handlers.handler import Handler
from pyrogram.handlers import ( from pyrogram.handlers import (
BotBusinessConnectHandler, CallbackQueryHandler, MessageHandler, EditedMessageHandler, DeletedMessagesHandler,
BotBusinessMessageHandler, UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler,
CallbackQueryHandler, ChosenInlineResultHandler, ChatMemberUpdatedHandler, ChatJoinRequestHandler, StoryHandler
MessageHandler,
EditedMessageHandler,
EditedBotBusinessMessageHandler,
ErrorHandler,
DeletedMessagesHandler,
DeletedBotBusinessMessagesHandler,
MessageReactionUpdatedHandler,
MessageReactionCountUpdatedHandler,
UserStatusHandler,
RawUpdateHandler,
InlineQueryHandler,
PollHandler,
ShippingQueryHandler,
PreCheckoutQueryHandler,
ConversationHandler,
ChosenInlineResultHandler,
ChatMemberUpdatedHandler,
ChatJoinRequestHandler,
StoryHandler,
PurchasedPaidMediaHandler
) )
from pyrogram.raw.types import ( from pyrogram.raw.types import (
UpdateNewMessage, UpdateNewChannelMessage, UpdateNewScheduledMessage, UpdateNewMessage, UpdateNewChannelMessage, UpdateNewScheduledMessage,
UpdateBotBusinessConnect,
UpdateBotNewBusinessMessage, UpdateBotDeleteBusinessMessage, UpdateBotEditBusinessMessage,
UpdateEditMessage, UpdateEditChannelMessage, UpdateEditMessage, UpdateEditChannelMessage,
UpdateDeleteMessages, UpdateDeleteChannelMessages, UpdateDeleteMessages, UpdateDeleteChannelMessages,
UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery, UpdateBotPrecheckoutQuery, UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery,
UpdateUserStatus, UpdateBotInlineQuery, UpdateMessagePoll, UpdateUserStatus, UpdateBotInlineQuery, UpdateMessagePoll,
UpdateBotInlineSend, UpdateChatParticipant, UpdateChannelParticipant, UpdateBotStopped, UpdateBotInlineSend, UpdateChatParticipant, UpdateChannelParticipant,
UpdateBotChatInviteRequester, UpdateStory, UpdateBotChatInviteRequester, UpdateStory
UpdateBotMessageReaction,
UpdateBotMessageReactions,
UpdateBotShippingQuery,
UpdateBusinessBotCallbackQuery,
UpdateBotPurchasedPaidMedia
) )
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -73,64 +44,34 @@ log = logging.getLogger(__name__)
class Dispatcher: class Dispatcher:
NEW_MESSAGE_UPDATES = (UpdateNewMessage, UpdateNewChannelMessage, UpdateNewScheduledMessage) NEW_MESSAGE_UPDATES = (UpdateNewMessage, UpdateNewChannelMessage, UpdateNewScheduledMessage)
NEW_BOT_BUSINESS_MESSAGE_UPDATES = (UpdateBotNewBusinessMessage,)
EDIT_MESSAGE_UPDATES = (UpdateEditMessage, UpdateEditChannelMessage) EDIT_MESSAGE_UPDATES = (UpdateEditMessage, UpdateEditChannelMessage)
EDIT_BOT_BUSINESS_MESSAGE_UPDATES = (UpdateBotEditBusinessMessage,)
DELETE_MESSAGES_UPDATES = (UpdateDeleteMessages, UpdateDeleteChannelMessages) DELETE_MESSAGES_UPDATES = (UpdateDeleteMessages, UpdateDeleteChannelMessages)
DELETE_BOT_BUSINESS_MESSAGES_UPDATES = (UpdateBotDeleteBusinessMessage,) CALLBACK_QUERY_UPDATES = (UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery)
CALLBACK_QUERY_UPDATES = (UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery, UpdateBusinessBotCallbackQuery) CHAT_MEMBER_UPDATES = (UpdateChatParticipant, UpdateChannelParticipant)
CHAT_MEMBER_UPDATES = (UpdateChatParticipant, UpdateChannelParticipant, UpdateBotStopped,)
USER_STATUS_UPDATES = (UpdateUserStatus,) USER_STATUS_UPDATES = (UpdateUserStatus,)
BOT_INLINE_QUERY_UPDATES = (UpdateBotInlineQuery,) BOT_INLINE_QUERY_UPDATES = (UpdateBotInlineQuery,)
POLL_UPDATES = (UpdateMessagePoll,) POLL_UPDATES = (UpdateMessagePoll,)
CHOSEN_INLINE_RESULT_UPDATES = (UpdateBotInlineSend,) CHOSEN_INLINE_RESULT_UPDATES = (UpdateBotInlineSend,)
CHAT_JOIN_REQUEST_UPDATES = (UpdateBotChatInviteRequester,) CHAT_JOIN_REQUEST_UPDATES = (UpdateBotChatInviteRequester,)
NEW_STORY_UPDATES = (UpdateStory,) NEW_STORY_UPDATES = (UpdateStory,)
MESSAGE_BOT_NA_REACTION_UPDATES = (UpdateBotMessageReaction,)
MESSAGE_BOT_A_REACTION_UPDATES = (UpdateBotMessageReactions,)
BOT_BUSSINESS_CONNECT_UPDATES = (UpdateBotBusinessConnect,)
PRE_CHECKOUT_QUERY_UPDATES = (UpdateBotPrecheckoutQuery,)
SHIPPING_QUERY_UPDATES = (UpdateBotShippingQuery,)
PURCHASED_PAID_MEDIA_UPDATES = (UpdateBotPurchasedPaidMedia,)
def __init__(self, client: "pyrogram.Client"): def __init__(self, client: "pyrogram.Client"):
self.client = client self.client = client
try: self.loop = asyncio.get_event_loop()
loop = asyncio.get_event_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
self.loop = loop
self.handler_worker_tasks = [] self.handler_worker_tasks = []
self.locks_list = [] self.locks_list = []
self.error_handlers = []
self.updates_queue = asyncio.Queue() self.updates_queue = asyncio.Queue()
self.groups = OrderedDict() self.groups = OrderedDict()
self.conversation_handler = ConversationHandler()
self.groups[0] = [self.conversation_handler]
async def message_parser(update, users, chats): async def message_parser(update, users, chats):
return ( return (
await pyrogram.types.Message._parse(self.client, update.message, users, chats, await pyrogram.types.Message._parse(self.client, update.message, users, chats,
is_scheduled=isinstance(update, UpdateNewScheduledMessage)), isinstance(update, UpdateNewScheduledMessage)),
MessageHandler MessageHandler
) )
async def bot_business_message_parser(update, users, chats):
return (
await pyrogram.types.Message._parse(
self.client,
update.message,
users,
chats,
business_connection_id=update.connection_id
),
BotBusinessMessageHandler
)
async def edited_message_parser(update, users, chats): async def edited_message_parser(update, users, chats):
# Edited messages are parsed the same way as new messages, but the handler is different # Edited messages are parsed the same way as new messages, but the handler is different
parsed, _ = await message_parser(update, users, chats) parsed, _ = await message_parser(update, users, chats)
@ -140,27 +81,12 @@ class Dispatcher:
EditedMessageHandler EditedMessageHandler
) )
async def edited_bot_business_message_parser(update, users, chats):
# Edited messages are parsed the same way as new messages, but the handler is different
parsed, _ = await bot_business_message_parser(update, users, chats)
return (
parsed,
EditedBotBusinessMessageHandler
)
async def deleted_messages_parser(update, users, chats): async def deleted_messages_parser(update, users, chats):
return ( return (
utils.parse_deleted_messages(self.client, update), utils.parse_deleted_messages(self.client, update),
DeletedMessagesHandler DeletedMessagesHandler
) )
async def deleted_bot_business_messages_parser(update, users, chats):
return (
utils.parse_deleted_messages(self.client, update, business_connection_id=update.connection_id),
DeletedBotBusinessMessagesHandler
)
async def callback_query_parser(update, users, chats): async def callback_query_parser(update, users, chats):
return ( return (
await pyrogram.types.CallbackQuery._parse(self.client, update, users), await pyrogram.types.CallbackQuery._parse(self.client, update, users),
@ -181,7 +107,7 @@ class Dispatcher:
async def poll_parser(update, users, chats): async def poll_parser(update, users, chats):
return ( return (
await pyrogram.types.Poll._parse_update(self.client, update, users), pyrogram.types.Poll._parse_update(self.client, update),
PollHandler PollHandler
) )
@ -209,49 +135,10 @@ class Dispatcher:
StoryHandler StoryHandler
) )
async def shipping_query_parser(update, users, chats):
return (
await pyrogram.types.ShippingQuery._parse(self.client, update, users),
ShippingQueryHandler
)
async def pre_checkout_query_parser(update, users, chats):
return (
await pyrogram.types.PreCheckoutQuery._parse(self.client, update, users),
PreCheckoutQueryHandler
)
async def message_bot_na_reaction_parser(update, users, chats):
return (
pyrogram.types.MessageReactionUpdated._parse(self.client, update, users, chats),
MessageReactionUpdatedHandler
)
async def message_bot_a_reaction_parser(update, users, chats):
return (
pyrogram.types.MessageReactionCountUpdated._parse(self.client, update, users, chats),
MessageReactionCountUpdatedHandler
)
async def bot_business_connect_parser(update, users, chats):
return (
await pyrogram.types.BotBusinessConnection._parse(self.client, update.connection),
BotBusinessConnectHandler
)
async def purchased_paid_media_parser(update, users, chats):
return (
pyrogram.types.PurchasedPaidMedia._parse(self.client, update, users),
PurchasedPaidMediaHandler
)
self.update_parsers = { self.update_parsers = {
Dispatcher.NEW_MESSAGE_UPDATES: message_parser, Dispatcher.NEW_MESSAGE_UPDATES: message_parser,
Dispatcher.NEW_BOT_BUSINESS_MESSAGE_UPDATES: bot_business_message_parser,
Dispatcher.EDIT_MESSAGE_UPDATES: edited_message_parser, Dispatcher.EDIT_MESSAGE_UPDATES: edited_message_parser,
Dispatcher.EDIT_BOT_BUSINESS_MESSAGE_UPDATES: edited_bot_business_message_parser,
Dispatcher.DELETE_MESSAGES_UPDATES: deleted_messages_parser, Dispatcher.DELETE_MESSAGES_UPDATES: deleted_messages_parser,
Dispatcher.DELETE_BOT_BUSINESS_MESSAGES_UPDATES: deleted_bot_business_messages_parser,
Dispatcher.CALLBACK_QUERY_UPDATES: callback_query_parser, Dispatcher.CALLBACK_QUERY_UPDATES: callback_query_parser,
Dispatcher.USER_STATUS_UPDATES: user_status_parser, Dispatcher.USER_STATUS_UPDATES: user_status_parser,
Dispatcher.BOT_INLINE_QUERY_UPDATES: inline_query_parser, Dispatcher.BOT_INLINE_QUERY_UPDATES: inline_query_parser,
@ -259,20 +146,14 @@ class Dispatcher:
Dispatcher.CHOSEN_INLINE_RESULT_UPDATES: chosen_inline_result_parser, Dispatcher.CHOSEN_INLINE_RESULT_UPDATES: chosen_inline_result_parser,
Dispatcher.CHAT_MEMBER_UPDATES: chat_member_updated_parser, Dispatcher.CHAT_MEMBER_UPDATES: chat_member_updated_parser,
Dispatcher.CHAT_JOIN_REQUEST_UPDATES: chat_join_request_parser, Dispatcher.CHAT_JOIN_REQUEST_UPDATES: chat_join_request_parser,
Dispatcher.NEW_STORY_UPDATES: story_parser, Dispatcher.NEW_STORY_UPDATES: story_parser
Dispatcher.SHIPPING_QUERY_UPDATES: shipping_query_parser,
Dispatcher.PRE_CHECKOUT_QUERY_UPDATES: pre_checkout_query_parser,
Dispatcher.MESSAGE_BOT_NA_REACTION_UPDATES: message_bot_na_reaction_parser,
Dispatcher.MESSAGE_BOT_A_REACTION_UPDATES: message_bot_a_reaction_parser,
Dispatcher.BOT_BUSSINESS_CONNECT_UPDATES: bot_business_connect_parser,
Dispatcher.PURCHASED_PAID_MEDIA_UPDATES: purchased_paid_media_parser
} }
self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple} self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple}
async def start(self): async def start(self):
if not self.client.no_updates: if not self.client.no_updates:
for _ in range(self.client.workers): for i in range(self.client.workers):
self.locks_list.append(asyncio.Lock()) self.locks_list.append(asyncio.Lock())
self.handler_worker_tasks.append( self.handler_worker_tasks.append(
@ -281,9 +162,6 @@ class Dispatcher:
log.info("Started %s HandlerTasks", self.client.workers) log.info("Started %s HandlerTasks", self.client.workers)
if not self.client.skip_updates:
await self.client.recover_gaps()
async def stop(self): async def stop(self):
if not self.client.no_updates: if not self.client.no_updates:
for i in range(self.client.workers): for i in range(self.client.workers):
@ -294,7 +172,6 @@ class Dispatcher:
self.handler_worker_tasks.clear() self.handler_worker_tasks.clear()
self.groups.clear() self.groups.clear()
self.error_handlers.clear()
log.info("Stopped %s HandlerTasks", self.client.workers) log.info("Stopped %s HandlerTasks", self.client.workers)
@ -304,14 +181,11 @@ class Dispatcher:
await lock.acquire() await lock.acquire()
try: try:
if isinstance(handler, ErrorHandler): if group not in self.groups:
if handler not in self.error_handlers: self.groups[group] = []
self.error_handlers.append(handler) self.groups = OrderedDict(sorted(self.groups.items()))
else:
if group not in self.groups: self.groups[group].append(handler)
self.groups[group] = []
self.groups = OrderedDict(sorted(self.groups.items()))
self.groups[group].append(handler)
finally: finally:
for lock in self.locks_list: for lock in self.locks_list:
lock.release() lock.release()
@ -324,23 +198,17 @@ class Dispatcher:
await lock.acquire() await lock.acquire()
try: try:
if isinstance(handler, ErrorHandler): if group not in self.groups:
if handler not in self.error_handlers: raise ValueError(f"Group {group} does not exist. Handler was not removed.")
raise ValueError(
f"Error handler {handler} does not exist. Handler was not removed." self.groups[group].remove(handler)
)
self.error_handlers.remove(handler)
else:
if group not in self.groups:
raise ValueError(f"Group {group} does not exist. Handler was not removed.")
self.groups[group].remove(handler)
finally: finally:
for lock in self.locks_list: for lock in self.locks_list:
lock.release() lock.release()
self.loop.create_task(fn()) self.loop.create_task(fn())
async def handler_worker(self, lock: asyncio.Lock): async def handler_worker(self, lock):
while True: while True:
packet = await self.updates_queue.get() packet = await self.updates_queue.get()
@ -348,91 +216,53 @@ class Dispatcher:
break break
try: try:
await self._handle_packet(packet, lock) update, users, chats = packet
parser = self.update_parsers.get(type(update), None)
parsed_update, handler_type = (
await parser(update, users, chats)
if parser is not None
else (None, type(None))
)
async with lock:
for group in self.groups.values():
for handler in group:
args = None
if isinstance(handler, handler_type):
try:
if await handler.check(self.client, parsed_update):
args = (parsed_update,)
except Exception as e:
log.exception(e)
continue
elif isinstance(handler, RawUpdateHandler):
args = (update, users, chats)
if args is None:
continue
try:
if inspect.iscoroutinefunction(handler.callback):
await handler.callback(self.client, *args)
else:
await self.loop.run_in_executor(
self.client.executor,
handler.callback,
self.client,
*args
)
except pyrogram.StopPropagation:
raise
except pyrogram.ContinuePropagation:
continue
except Exception as e:
log.exception(e)
break
except pyrogram.StopPropagation: except pyrogram.StopPropagation:
pass pass
except Exception as e: except Exception as e:
log.exception(e) log.exception(e)
finally:
self.updates_queue.task_done()
async def _handle_packet(self, packet, lock: asyncio.Lock):
update, users, chats = packet
parser = self.update_parsers.get(type(update))
parsed_update, handler_type = (
await parser(update, users, chats)
if parser is not None else (None, type(None))
)
async with lock:
await self._dispatch_to_handlers(update, users, chats, parsed_update, handler_type)
async def _dispatch_to_handlers(
self, update, users, chats, parsed_update, handler_type,
):
for group in self.groups.values():
for handler in group:
args = await self._match_handler(
handler, update, users, chats, parsed_update, handler_type,
)
if args is None:
continue
try:
await self._execute_handler(handler, *args)
except pyrogram.StopPropagation:
raise
except pyrogram.ContinuePropagation:
continue
except Exception as error:
if parsed_update is not None:
await self._handle_exception(parsed_update, error)
break
async def _match_handler(
self, handler, update, users, chats, parsed_update, handler_type,
):
try:
if isinstance(handler, handler_type):
if await handler.check(self.client, parsed_update):
return (parsed_update,)
elif isinstance(handler, RawUpdateHandler):
if await handler.check(self.client, update):
return (update, users, chats)
except Exception as e:
log.exception(e)
return None
async def _execute_handler(self, handler, *args: Any):
if inspect.iscoroutinefunction(handler.callback):
await handler.callback(self.client, *args)
else:
await self.loop.run_in_executor(
self.client.executor,
handler.callback,
self.client,
*args
)
async def _handle_exception(
self, parsed_update: types.Update, exception: Exception,
):
handled_error = False
for error_handler in self.error_handlers:
try:
if await error_handler.check(
self.client, parsed_update, exception,
):
handled_error = True
break
except pyrogram.StopPropagation:
raise
except pyrogram.ContinuePropagation:
continue
except Exception as inner_exception:
log.exception("Error in error handler: %s", inner_exception)
if not handled_error:
log.exception("Unhandled exception: %s", exception)

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
GRINNING_FACE = "\U0001f600" GRINNING_FACE = "\U0001f600"
GRINNING_FACE_WITH_BIG_EYES = "\U0001f603" GRINNING_FACE_WITH_BIG_EYES = "\U0001f603"

View file

@ -1,74 +1,51 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from .business_schedule import BusinessSchedule
from .chat_action import ChatAction from .chat_action import ChatAction
from .chat_event_action import ChatEventAction from .chat_event_action import ChatEventAction
from .chat_join_type import ChatJoinType
from .chat_member_status import ChatMemberStatus from .chat_member_status import ChatMemberStatus
from .chat_members_filter import ChatMembersFilter from .chat_members_filter import ChatMembersFilter
from .chat_type import ChatType from .chat_type import ChatType
from .client_platform import ClientPlatform
from .folder_color import FolderColor
from .gift_attribute_type import GiftAttributeType
from .gift_for_resale_order import GiftForResaleOrder
from .listerner_types import ListenerTypes
from .message_entity_type import MessageEntityType from .message_entity_type import MessageEntityType
from .message_media_type import MessageMediaType from .message_media_type import MessageMediaType
from .message_origin_type import MessageOriginType
from .message_service_type import MessageServiceType from .message_service_type import MessageServiceType
from .messages_filter import MessagesFilter from .messages_filter import MessagesFilter
from .next_code_type import NextCodeType from .next_code_type import NextCodeType
from .parse_mode import ParseMode from .parse_mode import ParseMode
from .poll_type import PollType from .poll_type import PollType
from .profile_color import ProfileColor
from .reaction_type import ReactionType
from .reply_color import ReplyColor
from .sent_code_type import SentCodeType from .sent_code_type import SentCodeType
from .stories_privacy_rules import StoriesPrivacyRules from .stories_privacy_rules import StoriesPrivacyRules
from .story_privacy import StoryPrivacy from .story_privacy import StoryPrivacy
from .user_status import UserStatus from .user_status import UserStatus
__all__ = [ __all__ = [
'BusinessSchedule',
'ChatAction', 'ChatAction',
'ChatEventAction', 'ChatEventAction',
'ChatJoinType',
'ChatMemberStatus', 'ChatMemberStatus',
'ChatMembersFilter', 'ChatMembersFilter',
'ChatType', 'ChatType',
'ClientPlatform',
'FolderColor',
'GiftAttributeType',
'GiftForResaleOrder',
'ListenerTypes',
'MessageEntityType', 'MessageEntityType',
'MessageMediaType', 'MessageMediaType',
'MessageOriginType',
'MessageServiceType', 'MessageServiceType',
'MessagesFilter', 'MessagesFilter',
'NextCodeType', 'NextCodeType',
'ParseMode', 'ParseMode',
'PollType', 'PollType',
'ProfileColor',
'ReactionType',
'ReplyColor',
'SentCodeType', 'SentCodeType',
"StoriesPrivacyRules", "StoriesPrivacyRules",
"StoryPrivacy", "StoryPrivacy",

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from enum import Enum from enum import Enum

View file

@ -1,33 +0,0 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram 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 General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw
from .auto_name import AutoName
class BusinessSchedule(AutoName):
"""Business away enumeration used in :obj:`~pyrogram.types.BusinessInfo`."""
ALWAYS = raw.types.BusinessAwayMessageScheduleAlways
"Send always"
OUTSIDE_WORK_HOURS = raw.types.BusinessAwayMessageScheduleOutsideWorkHours
"Outside of Business Hours"
CUSTOM = raw.types.BusinessAwayMessageScheduleCustom
"Custom Schedule"

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw from pyrogram import raw
from .auto_name import AutoName from .auto_name import AutoName
@ -71,9 +70,3 @@ class ChatAction(AutoName):
CANCEL = raw.types.SendMessageCancelAction CANCEL = raw.types.SendMessageCancelAction
"Cancel ongoing chat action" "Cancel ongoing chat action"
TRIGGER_EMOJI_ANIMATION = raw.types.SendMessageEmojiInteraction
"User has clicked on an animated emoji triggering a `reaction <https://core.telegram.org/api/animated-emojis#emoji-reactions>`_"
WATCH_EMOJI_ANIMATION = raw.types.SendMessageEmojiInteractionSeen
"The user is watching animations sent by the other party by clicking on an animated emoji"

View file

@ -35,13 +35,13 @@ class ChatEventAction(AutoName):
"The linked chat has been changed (see ``old_linked_chat`` and ``new_linked_chat``)" "The linked chat has been changed (see ``old_linked_chat`` and ``new_linked_chat``)"
# LOCATION_CHANGED = auto() # LOCATION_CHANGED = auto()
# "" ""
PHOTO_CHANGED = auto() PHOTO_CHANGED = auto()
"The chat photo has been changed (see ``old_photo`` and ``new_photo``)" "The chat photo has been changed (see ``old_photo`` and ``new_photo``)"
# STICKER_SET_CHANGED = auto() # STICKER_SET_CHANGED = auto()
# "" ""
TITLE_CHANGED = auto() TITLE_CHANGED = auto()
"the chat title has been changed (see ``old_title`` and ``new_title``)" "the chat title has been changed (see ``old_title`` and ``new_title``)"
@ -56,7 +56,7 @@ class ChatEventAction(AutoName):
"a message has been deleted (see ``deleted_message``)" "a message has been deleted (see ``deleted_message``)"
# VOICE_CHAT_DISCARDED = auto() # VOICE_CHAT_DISCARDED = auto()
# "" ""
MESSAGE_EDITED = auto() MESSAGE_EDITED = auto()
"a message has been edited (see ``old_message`` and ``new_message``)" "a message has been edited (see ``old_message`` and ``new_message``)"
@ -77,13 +77,13 @@ class ChatEventAction(AutoName):
"a member joined by themselves. (see ``user``)" "a member joined by themselves. (see ``user``)"
# MEMBER_JOINED_BY_LINK = auto() # MEMBER_JOINED_BY_LINK = auto()
# "" ""
MEMBER_LEFT = auto() MEMBER_LEFT = auto()
"a member left by themselves. (see ``user``)" "a member left by themselves. (see ``user``)"
# MEMBER_MUTED = auto() # MEMBER_MUTED = auto()
# "" ""
ADMINISTRATOR_PRIVILEGES_CHANGED = auto() ADMINISTRATOR_PRIVILEGES_CHANGED = auto()
"a chat member has been promoted/demoted or their administrator privileges has changed (see ``old_administrator_privileges`` and ``new_administrator_privileges``)" "a chat member has been promoted/demoted or their administrator privileges has changed (see ``old_administrator_privileges`` and ``new_administrator_privileges``)"
@ -92,19 +92,19 @@ class ChatEventAction(AutoName):
"a chat member has been restricted/unrestricted or banned/unbanned, or their permissions has changed (see ``old_member_permissions`` and ``new_member_permissions``)" "a chat member has been restricted/unrestricted or banned/unbanned, or their permissions has changed (see ``old_member_permissions`` and ``new_member_permissions``)"
# MEMBER_UNMUTED = auto() # MEMBER_UNMUTED = auto()
# "" ""
# MEMBER_VOLUME_CHANGED = auto() # MEMBER_VOLUME_CHANGED = auto()
# "" ""
# VIDEO_CHAT_STARTED = auto() # VIDEO_CHAT_STARTED = auto()
# "" ""
POLL_STOPPED = auto() POLL_STOPPED = auto()
"a poll has been stopped (see ``stopped_poll``)" "a poll has been stopped (see ``stopped_poll``)"
# VOICE_CHAT_SETTINGS_CHANGED = auto() # VOICE_CHAT_SETTINGS_CHANGED = auto()
# "" ""
INVITES_ENABLED = auto() INVITES_ENABLED = auto()
"the chat invitation has been enabled or disabled (see ``invites_enabled``)" "the chat invitation has been enabled or disabled (see ``invites_enabled``)"

View file

@ -1,34 +0,0 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram 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 General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from enum import auto
from .auto_name import AutoName
class ChatJoinType(AutoName):
"""How the service message :obj:`~pyrogram.enums.MessageServiceType.NEW_CHAT_MEMBERS` was used for the member to join the chat."""
BY_ADD = auto()
"A new member joined the chat via an invite link"
BY_LINK = auto()
"A new member joined the chat via an invite link"
BY_REQUEST = auto()
"A new member was accepted to the chat by an administrator"

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from enum import auto from enum import auto
@ -25,7 +24,7 @@ from .auto_name import AutoName
class ChatMemberStatus(AutoName): class ChatMemberStatus(AutoName):
"""Chat member status enumeration used in :obj:`~pyrogram.types.ChatMember`.""" """Chat member status enumeration used in :obj:`~pyrogram.types.ChatMember`."""
OWNER = auto() # TODO: rename to 'creator' OWNER = auto()
"Chat owner" "Chat owner"
ADMINISTRATOR = auto() ADMINISTRATOR = auto()
@ -40,5 +39,5 @@ class ChatMemberStatus(AutoName):
LEFT = auto() LEFT = auto()
"Left chat member" "Left chat member"
BANNED = auto() # TODO: rename to 'kicked' BANNED = auto()
"Banned chat member" "Banned chat member"

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw from pyrogram import raw
from .auto_name import AutoName from .auto_name import AutoName

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from enum import auto from enum import auto
@ -39,9 +38,3 @@ class ChatType(AutoName):
CHANNEL = auto() CHANNEL = auto()
"Chat is a channel" "Chat is a channel"
FORUM = auto()
"Chat is a forum"
MONOFORUM = auto()
"Chat is a monoforum"

View file

@ -1,49 +0,0 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram 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 General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from enum import auto
from .auto_name import AutoName
class ClientPlatform(AutoName):
"""Valid platforms for a :obj:`~pyrogram.Client`."""
ANDROID = auto()
"Android"
IOS = auto()
"iOS"
WP = auto()
"Windows Phone"
BB = auto()
"Blackberry"
DESKTOP = auto()
"Desktop"
WEB = auto()
"Web"
UBP = auto()
"Ubuntu Phone"
OTHER = auto()
"Other"

View file

@ -1,47 +0,0 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram 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 General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from .auto_name import AutoName
class FolderColor(AutoName):
"""Folder color enumeration used in :obj:`~pyrogram.types.Folder`."""
NO_COLOR = None
"No color."
RED = 0
"Red color."
ORANGE = 1
"Orange color."
VIOLET = 2
"Violet color."
GREEN = 3
"Green color."
CYAN = 4
"Cyan color."
BLUE = 5
"Blue color."
PINK = 6
"Pink color."

View file

@ -1,36 +0,0 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram 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 General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw
from .auto_name import AutoName
class GiftAttributeType(AutoName):
"""Star gift attribute type enumeration used in :obj:`~pyrogram.types.GiftAttribute`."""
MODEL = raw.types.StarGiftAttributeModel
"Model attribute"
SYMBOL = raw.types.StarGiftAttributePattern
"Symbol attribute"
BACKDROP = raw.types.StarGiftAttributeBackdrop
"Backdrop attribute"
ORIGINAL_DETAILS = raw.types.StarGiftAttributeOriginalDetails
"Original details attribute"

View file

@ -1,35 +0,0 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork 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 General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from enum import auto
from .auto_name import AutoName
class GiftForResaleOrder(AutoName):
"""Describes order in which upgraded gifts for resale will be sorted. Used in :meth:`~pyrogram.Client.search_gifts_for_resale`."""
PRICE = auto()
"The gifts will be sorted by their price from the lowest to the highest"
CHANGE_DATE = auto()
"The gifts will be sorted by the last date when their price was changed from the newest to the oldest"
NUMBER = auto()
"The gifts will be sorted by their number from the smallest to the largest"

View file

@ -1,32 +0,0 @@
# Pyrofork - Telegram MTProto API Client Library for Python
# Copyright (C) 2020 Cezar H. <https://github.com/usernein>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrofork.
#
# Pyrofork is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrofork 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 General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>.
from enum import auto
from .auto_name import AutoName
class ListenerTypes(AutoName):
"""Listener type enumeration used in :obj:`~pyrogram.types.Client`."""
MESSAGE = auto()
"A Message"
CALLBACK_QUERY = auto()
"A CallbackQuery"

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw from pyrogram import raw
from .auto_name import AutoName from .auto_name import AutoName
@ -69,9 +68,6 @@ class MessageEntityType(AutoName):
BLOCKQUOTE = raw.types.MessageEntityBlockquote BLOCKQUOTE = raw.types.MessageEntityBlockquote
"Blockquote text" "Blockquote text"
EXPANDABLE_BLOCKQUOTE = raw.types.MessageEntityBlockquote
"collapsed-by-default block quotation"
TEXT_LINK = raw.types.MessageEntityTextUrl TEXT_LINK = raw.types.MessageEntityTextUrl
"For clickable text URLs" "For clickable text URLs"

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from enum import auto from enum import auto
@ -61,8 +60,8 @@ class MessageMediaType(AutoName):
POLL = auto() POLL = auto()
"Poll media" "Poll media"
WEB_PAGE_PREVIEW = auto() WEB_PAGE = auto()
"Web page preview media" "Web page media"
DICE = auto() DICE = auto()
"Dice media" "Dice media"
@ -70,20 +69,5 @@ class MessageMediaType(AutoName):
GAME = auto() GAME = auto()
"Game media" "Game media"
GIVEAWAY = auto()
"Giveaway media"
GIVEAWAY_RESULT = auto()
"Giveaway result media"
STORY = auto() STORY = auto()
"Forwarded story media" "Forwarded story media"
INVOICE = auto()
"Invoice media"
PAID_MEDIA = auto()
"Paid media"
TODO = auto()
"To-Do list media"

View file

@ -1,42 +0,0 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram 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 General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from enum import auto
from .auto_name import AutoName
class MessageOriginType(AutoName):
"""Message origin type enumeration used in :obj:`~pyrogram.types.MessageOrigin`."""
CHANNEL = auto()
"The message was originally a post in a channel"
CHAT = auto()
"The message was originally sent on behalf of a chat"
HIDDEN_USER = auto()
"The message was originally sent by a user, which is hidden by their privacy settings"
IMPORT = auto()
"The message was imported from a foreign chat service"
USER = auto()
"The message was originally sent by a known user"

View file

@ -28,6 +28,9 @@ class MessageServiceType(AutoName):
NEW_CHAT_MEMBERS = auto() NEW_CHAT_MEMBERS = auto()
"New members join" "New members join"
CHAT_JOINED_BY_REQUEST = auto()
"a member chat join request approved by admin."
LEFT_CHAT_MEMBERS = auto() LEFT_CHAT_MEMBERS = auto()
"Left chat members" "Left chat members"
@ -58,8 +61,11 @@ class MessageServiceType(AutoName):
GAME_HIGH_SCORE = auto() GAME_HIGH_SCORE = auto()
"Game high score" "Game high score"
CHAT_SHARED = auto() ChannelShared = auto()
"a shared chat/channel/user" "a shared chat/channel"
UserShared = auto()
"a shared user"
FORUM_TOPIC_CREATED = auto() FORUM_TOPIC_CREATED = auto()
"a new forum topic created in the chat" "a new forum topic created in the chat"
@ -93,51 +99,3 @@ class MessageServiceType(AutoName):
WEB_APP_DATA = auto() WEB_APP_DATA = auto()
"Web app data" "Web app data"
GIFTED_PREMIUM = auto()
"Gifted Premium"
GIVEAWAY_LAUNCHED = auto()
"Giveaway Launch"
GIVEAWAY_RESULT = auto()
"Giveaway Result"
BOOST_APPLY = auto()
"Boost apply"
SUCCESSFUL_PAYMENT = auto()
"Successful payment"
PAYMENT_REFUNDED = auto()
"Payment refunded"
BOT_ALLOWED = auto()
"Bot allowed"
CHAT_THEME_UPDATED = auto()
"Chat theme updated"
CHAT_WALLPAPER_UPDATED = auto()
"Chat wallpaper updated"
CONTACT_REGISTERED = auto()
"Contact registered"
GIFT_CODE = auto()
"Gift code"
GIFT = auto()
"Star gift"
SCREENSHOT_TAKEN = auto()
"Screenshot taken"
PAID_MESSAGE_PRICE_CHANGED = auto()
"Paid message price changed"
TODO_TASKS_ADDED = auto()
"To-Do tasks added"
TODO_TASKS_COMPLETION = auto()
"To-Do tasks completion/incompletion"

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw from pyrogram import raw
from .auto_name import AutoName from .auto_name import AutoName

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw from pyrogram import raw
from .auto_name import AutoName from .auto_name import AutoName

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from enum import auto from enum import auto

View file

@ -1,21 +1,20 @@
# Pyrofork - Telegram MTProto API Client Library for Python # Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance> # Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2022-present Mayuri-Chan <https://github.com/Mayuri-Chan>
# #
# This file is part of Pyrofork. # This file is part of Pyrogram.
# #
# Pyrofork is free software: you can redistribute it and/or modify # Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published # it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or # by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Pyrofork is distributed in the hope that it will be useful, # Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrofork. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from enum import auto from enum import auto

Some files were not shown because too many files have changed in this diff Show more