mirror of
https://github.com/pyrogram/pyrogram
synced 2025-08-31 22:35:36 +00:00
Merge branch 'develop' into asyncio
# Conflicts: # pyrogram/client/methods/chats/set_chat_description.py
This commit is contained in:
@@ -95,4 +95,5 @@ PHOTO_EXT_INVALID The photo extension is invalid
|
||||
EXTERNAL_URL_INVALID The external media URL is invalid
|
||||
CHAT_NOT_MODIFIED The chat settings were not modified
|
||||
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
|
||||
ACCESS_TOKEN_INVALID The bot access token is invalid
|
|
@@ -10,13 +10,14 @@ can be freely used as basic building blocks for your own applications without wo
|
||||
|
||||
Example | Description
|
||||
---: | :---
|
||||
[**hello**](hello.py) | Demonstration of basic API usage
|
||||
[**echo**](echo.py) | Reply to every private text message
|
||||
[**hello_world**](hello_world.py) | Demonstration of basic API usage
|
||||
[**echobot**](echobot.py) | Echo every private text message
|
||||
[**welcome**](welcome.py) | The Welcome Bot in [@PyrogramChat](https://t.me/pyrogramchat)
|
||||
[**history**](history.py) | Get the full message history of a chat
|
||||
[**chat_members**](chat_members.py) | Get all the members of a chat
|
||||
[**dialogs**](dialogs.py) | Get all of your dialog chats
|
||||
[**inline_bots**](inline_bots.py) | Query an inline bot and send a result to a chat
|
||||
[**using_inline_bots**](using_inline_bots.py) | Query an inline bot (as user) and send a result to a chat
|
||||
[**keyboards**](keyboards.py) | Send normal and inline keyboards using regular bots
|
||||
[**callback_queries**](callback_queries.py) | Handle queries coming from inline button presses
|
||||
[**inline_queries**](inline_queries.py) | Handle inline queries
|
||||
[**raw_updates**](raw_updates.py) | Handle raw updates (old, should be avoided)
|
||||
|
@@ -5,12 +5,12 @@ It uses the @on_callback_query decorator to register a CallbackQueryHandler.
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
app = Client("123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
|
||||
app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
|
||||
|
||||
|
||||
@app.on_callback_query()
|
||||
def answer(client, callback_query):
|
||||
callback_query.answer('Button contains: "{}"'.format(callback_query.data), show_alert=True)
|
||||
callback_query.answer("Button contains: '{}'".format(callback_query.data), show_alert=True)
|
||||
|
||||
|
||||
app.run() # Automatically start() and idle()
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
app = Client("my_count")
|
||||
app = Client("my_account")
|
||||
target = "pyrogramchat" # Target channel/supergroup
|
||||
|
||||
with app:
|
||||
|
54
examples/inline_queries.py
Normal file
54
examples/inline_queries.py
Normal file
@@ -0,0 +1,54 @@
|
||||
"""This example shows how to handle inline queries.
|
||||
Two results are generated when users invoke the bot inline mode, e.g.: @pyrogrambot hi.
|
||||
It uses the @on_inline_query decorator to register an InlineQueryHandler.
|
||||
"""
|
||||
|
||||
from uuid import uuid4
|
||||
|
||||
from pyrogram import (
|
||||
Client, InlineQueryResultArticle, InputTextMessageContent, InlineKeyboardMarkup, InlineKeyboardButton
|
||||
)
|
||||
|
||||
app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
|
||||
|
||||
|
||||
@app.on_inline_query()
|
||||
def answer(client, inline_query):
|
||||
inline_query.answer(
|
||||
results=[
|
||||
InlineQueryResultArticle(
|
||||
id=uuid4(),
|
||||
title="Installation",
|
||||
input_message_content=InputTextMessageContent(
|
||||
"Here's how to install **Pyrogram**"
|
||||
),
|
||||
url="https://docs.pyrogram.ml/start/Installation",
|
||||
description="How to install Pyrogram",
|
||||
thumb_url="https://i.imgur.com/JyxrStE.png",
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[
|
||||
[InlineKeyboardButton("Open website", url="https://docs.pyrogram.ml/start/Installation")]
|
||||
]
|
||||
)
|
||||
),
|
||||
InlineQueryResultArticle(
|
||||
id=uuid4(),
|
||||
title="Usage",
|
||||
input_message_content=InputTextMessageContent(
|
||||
"Here's how to use **Pyrogram**"
|
||||
),
|
||||
url="https://docs.pyrogram.ml/start/Usage",
|
||||
description="How to use Pyrogram",
|
||||
thumb_url="https://i.imgur.com/JyxrStE.png",
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[
|
||||
[InlineKeyboardButton("Open website", url="https://docs.pyrogram.ml/start/Usage")]
|
||||
]
|
||||
)
|
||||
)
|
||||
],
|
||||
cache_time=1
|
||||
)
|
||||
|
||||
|
||||
app.run() # Automatically start() and idle()
|
@@ -10,7 +10,7 @@ like send_audio(), send_document(), send_location(), etc...
|
||||
from pyrogram import Client, ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
|
||||
|
||||
# Create a client using your bot token
|
||||
app = Client("123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
|
||||
app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
|
||||
|
||||
with app:
|
||||
app.send_message(
|
||||
@@ -33,19 +33,17 @@ with app:
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[
|
||||
[ # First row
|
||||
|
||||
InlineKeyboardButton( # Generates a callback query when pressed
|
||||
"Button",
|
||||
callback_data=b"data"
|
||||
), # Note how callback_data must be bytes
|
||||
callback_data=b"data" # Note how callback_data must be bytes
|
||||
),
|
||||
InlineKeyboardButton( # Opens a web URL
|
||||
"URL",
|
||||
url="https://docs.pyrogram.ml"
|
||||
),
|
||||
],
|
||||
[ # Second row
|
||||
# Opens the inline interface
|
||||
InlineKeyboardButton(
|
||||
InlineKeyboardButton( # Opens the inline interface
|
||||
"Choose chat",
|
||||
switch_inline_query="pyrogram"
|
||||
),
|
||||
|
@@ -30,7 +30,6 @@ import shutil
|
||||
import struct
|
||||
import tempfile
|
||||
import time
|
||||
import warnings
|
||||
from configparser import ConfigParser
|
||||
from datetime import datetime
|
||||
from hashlib import sha256, md5
|
||||
@@ -41,6 +40,10 @@ from typing import Union, List
|
||||
|
||||
from pyrogram.api import functions, types
|
||||
from pyrogram.api.core import Object
|
||||
from pyrogram.client.handlers import DisconnectHandler
|
||||
from pyrogram.client.handlers.handler import Handler
|
||||
from pyrogram.client.methods.password.utils import compute_check
|
||||
from pyrogram.crypto import AES
|
||||
from pyrogram.errors import (
|
||||
PhoneMigrate, NetworkMigrate, PhoneNumberInvalid,
|
||||
PhoneNumberUnoccupied, PhoneCodeInvalid, PhoneCodeHashEmpty,
|
||||
@@ -49,10 +52,6 @@ from pyrogram.errors import (
|
||||
VolumeLocNotFound, UserMigrate, FileIdInvalid, ChannelPrivate, PhoneNumberOccupied,
|
||||
PasswordRecoveryNa, PasswordEmpty
|
||||
)
|
||||
from pyrogram.client.handlers import DisconnectHandler
|
||||
from pyrogram.client.handlers.handler import Handler
|
||||
from pyrogram.client.methods.password.utils import compute_check
|
||||
from pyrogram.crypto import AES
|
||||
from pyrogram.session import Auth, Session
|
||||
from .ext.utils import ainput
|
||||
from .ext import utils, Syncer, BaseClient, Dispatcher
|
||||
@@ -283,10 +282,10 @@ class Client(Methods, BaseClient):
|
||||
self.is_bot = True
|
||||
self.bot_token = self.session_name
|
||||
self.session_name = self.session_name.split(":")[0]
|
||||
warnings.warn('\nYou are using a bot token as session name.\n'
|
||||
'It will be deprecated in next update, please use session file name to load '
|
||||
'existing sessions and bot_token argument to create new sessions.',
|
||||
DeprecationWarning, stacklevel=2)
|
||||
log.warning('\nWARNING: You are using a bot token as session name!\n'
|
||||
'This usage will be deprecated soon. Please use a session file name to load '
|
||||
'an existing session and the bot_token argument to create new sessions.\n'
|
||||
'More info: https://docs.pyrogram.ml/start/Setup#bot-authorization\n')
|
||||
|
||||
self.load_config()
|
||||
await self.load_session()
|
||||
|
@@ -222,14 +222,16 @@ class Filters:
|
||||
- poll"""
|
||||
|
||||
@staticmethod
|
||||
def command(command: str or list,
|
||||
prefix: str or list = "/",
|
||||
separator: str = " ",
|
||||
case_sensitive: bool = False):
|
||||
def command(
|
||||
commands: str or list,
|
||||
prefix: str or list = "/",
|
||||
separator: str = " ",
|
||||
case_sensitive: bool = False
|
||||
):
|
||||
"""Filter commands, i.e.: text messages starting with "/" or any other custom prefix.
|
||||
|
||||
Args:
|
||||
command (``str`` | ``list``):
|
||||
commands (``str`` | ``list``):
|
||||
The command or list of commands as string the filter should look for.
|
||||
Examples: "start", ["start", "help", "settings"]. When a message text containing
|
||||
a command arrives, the command itself and its arguments will be stored in the *command*
|
||||
@@ -249,31 +251,25 @@ class Filters:
|
||||
Examples: when True, command="Start" would trigger /Start but not /start.
|
||||
"""
|
||||
|
||||
def f(_, m):
|
||||
if m.text:
|
||||
for i in _.p:
|
||||
if m.text.startswith(i):
|
||||
t = m.text.split(_.s)
|
||||
c, a = t[0][len(i):], t[1:]
|
||||
c = c if _.cs else c.lower()
|
||||
m.command = ([c] + a) if c in _.c else None
|
||||
def func(flt, message):
|
||||
text = message.text or message.caption
|
||||
|
||||
if text:
|
||||
for p in flt.p:
|
||||
if text.startswith(p):
|
||||
s = text.split(flt.s)
|
||||
c, a = s[0][len(p):], s[1:]
|
||||
c = c if flt.cs else c.lower()
|
||||
message.command = ([c] + a) if c in flt.c else None
|
||||
break
|
||||
|
||||
return bool(m.command)
|
||||
return bool(message.command)
|
||||
|
||||
return create(
|
||||
"Command",
|
||||
f,
|
||||
c={command if case_sensitive
|
||||
else command.lower()}
|
||||
if not isinstance(command, list)
|
||||
else {c if case_sensitive
|
||||
else c.lower()
|
||||
for c in command},
|
||||
p=set(prefix) if prefix else {""},
|
||||
s=separator,
|
||||
cs=case_sensitive
|
||||
)
|
||||
commands = commands if type(commands) is list else [commands]
|
||||
commands = {c if case_sensitive else c.lower() for c in commands}
|
||||
prefixes = set(prefix) if prefix else {""}
|
||||
|
||||
return create("Command", func=func, c=commands, p=prefixes, s=separator, cs=case_sensitive)
|
||||
|
||||
@staticmethod
|
||||
def regex(pattern, flags: int = 0):
|
||||
@@ -311,21 +307,20 @@ class Filters:
|
||||
|
||||
def __init__(self, users: int or str or list = None):
|
||||
users = [] if users is None else users if type(users) is list else [users]
|
||||
|
||||
super().__init__(
|
||||
{"me" if i in ["me", "self"] else i.lower().strip("@") if type(i) is str else i for i in users}
|
||||
if type(users) is list else
|
||||
{"me" if users in ["me", "self"] else users.lower().strip("@") if type(users) is str else users}
|
||||
"me" if u in ["me", "self"]
|
||||
else u.lower().strip("@") if type(u) is str
|
||||
else u for u in users
|
||||
)
|
||||
|
||||
def __call__(self, message):
|
||||
return bool(
|
||||
message.from_user
|
||||
and (message.from_user.id in self
|
||||
or (message.from_user.username
|
||||
and message.from_user.username.lower() in self)
|
||||
or ("me" in self
|
||||
and message.from_user.is_self))
|
||||
)
|
||||
return (message.from_user
|
||||
and (message.from_user.id in self
|
||||
or (message.from_user.username
|
||||
and message.from_user.username.lower() in self)
|
||||
or ("me" in self
|
||||
and message.from_user.is_self)))
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
class chat(Filter, set):
|
||||
@@ -343,21 +338,21 @@ class Filters:
|
||||
|
||||
def __init__(self, chats: int or str or list = None):
|
||||
chats = [] if chats is None else chats if type(chats) is list else [chats]
|
||||
|
||||
super().__init__(
|
||||
{"me" if i in ["me", "self"] else i.lower().strip("@") if type(i) is str else i for i in chats}
|
||||
if type(chats) is list else
|
||||
{"me" if chats in ["me", "self"] else chats.lower().strip("@") if type(chats) is str else chats}
|
||||
"me" if c in ["me", "self"]
|
||||
else c.lower().strip("@") if type(c) is str
|
||||
else c for c in chats
|
||||
)
|
||||
|
||||
def __call__(self, message):
|
||||
return bool(
|
||||
message.chat
|
||||
and (message.chat.id in self
|
||||
or (message.chat.username
|
||||
and message.chat.username.lower() in self)
|
||||
or ("me" in self and message.from_user
|
||||
and message.from_user.is_self
|
||||
and not message.outgoing))
|
||||
)
|
||||
return (message.chat
|
||||
and (message.chat.id in self
|
||||
or (message.chat.username
|
||||
and message.chat.username.lower() in self)
|
||||
or ("me" in self
|
||||
and message.from_user
|
||||
and message.from_user.is_self
|
||||
and not message.outgoing)))
|
||||
|
||||
dan = create("Dan", lambda _, m: bool(m.from_user and m.from_user.id == 23122162))
|
||||
|
@@ -47,15 +47,13 @@ class SetChatDescription(BaseClient):
|
||||
"""
|
||||
peer = await self.resolve_peer(chat_id)
|
||||
|
||||
if isinstance(peer, types.InputPeerChannel):
|
||||
if isinstance(peer, (types.InputPeerChannel, types.InputPeerChat)):
|
||||
await self.send(
|
||||
functions.channels.EditAbout(
|
||||
channel=peer,
|
||||
functions.messages.EditChatAbout(
|
||||
peer=peer,
|
||||
about=description
|
||||
)
|
||||
)
|
||||
elif isinstance(peer, types.InputPeerChat):
|
||||
raise ValueError("The chat_id \"{}\" belongs to a basic group".format(chat_id))
|
||||
else:
|
||||
raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
|
||||
|
||||
|
@@ -16,6 +16,8 @@
|
||||
# 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 typing import Any
|
||||
|
||||
from pyrogram.api import types
|
||||
from .inline_query_result import InlineQueryResult
|
||||
|
||||
@@ -61,7 +63,7 @@ class InlineQueryResultArticle(InlineQueryResult):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str,
|
||||
id: Any,
|
||||
title: str,
|
||||
input_message_content,
|
||||
reply_markup=None,
|
||||
@@ -84,7 +86,7 @@ class InlineQueryResultArticle(InlineQueryResult):
|
||||
|
||||
def write(self):
|
||||
return types.InputBotInlineResult(
|
||||
id=self.id,
|
||||
id=str(self.id),
|
||||
type=self.type,
|
||||
send_message=self.input_message_content.write(self.reply_markup),
|
||||
title=self.title,
|
||||
|
Reference in New Issue
Block a user