RubigramClient 1.4.1__py3-none-any.whl → 1.4.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of RubigramClient might be problematic. Click here for more details.
- rubigram/__init__.py +1 -2
- rubigram/client.py +97 -43
- rubigram/filters.py +143 -123
- rubigram/method.py +52 -177
- rubigram/types.py +46 -150
- {rubigramclient-1.4.1.dist-info → rubigramclient-1.4.2.dist-info}/METADATA +1 -1
- rubigramclient-1.4.2.dist-info/RECORD +11 -0
- rubigram/state.py +0 -30
- rubigramclient-1.4.1.dist-info/RECORD +0 -12
- {rubigramclient-1.4.1.dist-info → rubigramclient-1.4.2.dist-info}/WHEEL +0 -0
- {rubigramclient-1.4.1.dist-info → rubigramclient-1.4.2.dist-info}/licenses/LICENSE +0 -0
- {rubigramclient-1.4.1.dist-info → rubigramclient-1.4.2.dist-info}/top_level.txt +0 -0
rubigram/__init__.py
CHANGED
rubigram/client.py
CHANGED
|
@@ -1,92 +1,146 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from typing import Callable, Awaitable
|
|
2
|
+
from typing import Optional, Callable, Awaitable
|
|
3
3
|
from aiohttp import web
|
|
4
4
|
from functools import wraps
|
|
5
5
|
from rubigram.types import Update, InlineMessage
|
|
6
6
|
from rubigram.method import Method
|
|
7
|
+
from rubigram.filters import Filter
|
|
8
|
+
from datetime import datetime
|
|
7
9
|
import asyncio
|
|
8
10
|
import logging
|
|
9
11
|
|
|
10
12
|
logger = logging.getLogger(__name__)
|
|
11
13
|
|
|
12
|
-
|
|
13
14
|
class Client(Method):
|
|
14
|
-
def __init__(
|
|
15
|
-
self,
|
|
16
|
-
token: str,
|
|
17
|
-
endpoint: Optional[str] = None,
|
|
18
|
-
host: str = "0.0.0.0",
|
|
19
|
-
port: int = 8000
|
|
20
|
-
):
|
|
15
|
+
def __init__(self, token: str, endpoint: Optional[str] = None, host: str = "0.0.0.0", port: int = 8000):
|
|
21
16
|
self.token = token
|
|
22
|
-
self.port = port
|
|
23
|
-
self.host = host
|
|
24
17
|
self.endpoint = endpoint
|
|
25
|
-
self.
|
|
26
|
-
self.
|
|
18
|
+
self.host = host
|
|
19
|
+
self.port = port
|
|
20
|
+
self.offset_id = None
|
|
27
21
|
self.routes = web.RouteTableDef()
|
|
22
|
+
self.message_handlers = []
|
|
23
|
+
self.inline_handlers = []
|
|
28
24
|
super().__init__(token)
|
|
29
25
|
|
|
30
|
-
def on_message(self, *filters:
|
|
26
|
+
def on_message(self, *filters: Filter):
|
|
31
27
|
def decorator(func: Callable[[Client, Update], Awaitable]):
|
|
32
28
|
@wraps(func)
|
|
33
29
|
async def wrapper(client: Client, update: Update):
|
|
34
30
|
try:
|
|
35
|
-
|
|
31
|
+
combined_filter = filters[0] if filters else None
|
|
32
|
+
for filter in filters[1:]:
|
|
33
|
+
combined_filter = combined_filter & filter
|
|
34
|
+
|
|
35
|
+
if combined_filter is None or await combined_filter(update):
|
|
36
36
|
await func(client, update)
|
|
37
|
+
return True
|
|
38
|
+
return False
|
|
37
39
|
except Exception as e:
|
|
38
40
|
logger.exception(f"Error in message handler {func.__name__}: {e}")
|
|
39
|
-
|
|
41
|
+
return False
|
|
42
|
+
self.message_handlers.append(wrapper)
|
|
40
43
|
return func
|
|
41
44
|
return decorator
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
|
|
47
|
+
def on_inline_message(self, *filters: Filter):
|
|
44
48
|
def decorator(func: Callable[[Client, InlineMessage], Awaitable]):
|
|
45
49
|
@wraps(func)
|
|
46
50
|
async def wrapper(client: Client, update: InlineMessage):
|
|
47
51
|
try:
|
|
48
|
-
|
|
52
|
+
combined_filter = filters[0] if filters else None
|
|
53
|
+
for filter in filters[1:]:
|
|
54
|
+
combined_filter = combined_filter & filter
|
|
55
|
+
|
|
56
|
+
if combined_filter is None or await combined_filter(update):
|
|
49
57
|
await func(client, update)
|
|
58
|
+
return True
|
|
59
|
+
return False
|
|
50
60
|
except Exception as e:
|
|
51
61
|
logger.exception(f"Error in inline handler {func.__name__}: {e}")
|
|
52
|
-
|
|
62
|
+
return False
|
|
63
|
+
self.inline_handlers.append(wrapper)
|
|
53
64
|
return func
|
|
54
65
|
return decorator
|
|
55
66
|
|
|
56
|
-
|
|
67
|
+
|
|
68
|
+
async def dispatch_update(self, update: Update):
|
|
69
|
+
for handler in self.message_handlers:
|
|
70
|
+
try:
|
|
71
|
+
matched = await handler(self, update)
|
|
72
|
+
if matched:
|
|
73
|
+
return
|
|
74
|
+
except Exception as error:
|
|
75
|
+
logger.exception(f"Error in handler dispatch: {error}")
|
|
76
|
+
|
|
77
|
+
async def dispatch_inline(self, update: InlineMessage):
|
|
78
|
+
for handler in self.inline_handlers:
|
|
79
|
+
try:
|
|
80
|
+
matched = await handler(self, update)
|
|
81
|
+
if matched:
|
|
82
|
+
return
|
|
83
|
+
except Exception as error:
|
|
84
|
+
logger.exception(f"Error in inline handler dispatch: {error}")
|
|
85
|
+
|
|
86
|
+
async def updater(self, data: dict):
|
|
57
87
|
if "inline_message" in data:
|
|
58
88
|
event = InlineMessage.from_dict(data["inline_message"])
|
|
59
|
-
await
|
|
89
|
+
await self.dispatch_inline(event)
|
|
60
90
|
elif "update" in data:
|
|
61
91
|
event = Update.from_dict(data["update"])
|
|
62
92
|
event.client = self
|
|
63
|
-
await
|
|
93
|
+
await self.dispatch_update(event)
|
|
64
94
|
|
|
65
|
-
|
|
66
95
|
async def set_endpoints(self):
|
|
67
|
-
if
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
await self.update_bot_endpoint(f"{self.endpoint}/ReceiveInlineMessage", "ReceiveInlineMessage")
|
|
96
|
+
if self.endpoint:
|
|
97
|
+
await self.update_bot_endpoint(f"{self.endpoint}/ReceiveUpdate", "ReceiveUpdate")
|
|
98
|
+
await self.update_bot_endpoint(f"{self.endpoint}/ReceiveInlineMessage", "ReceiveInlineMessage")
|
|
71
99
|
|
|
72
100
|
def run(self):
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
101
|
+
if self.endpoint:
|
|
102
|
+
@self.routes.post("/ReceiveUpdate")
|
|
103
|
+
async def receive_update(request: web.Request):
|
|
104
|
+
data = await request.json()
|
|
105
|
+
await self.updater(data)
|
|
106
|
+
return web.json_response({"status": "OK"})
|
|
78
107
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
108
|
+
@self.routes.post("/ReceiveInlineMessage")
|
|
109
|
+
async def receive_inline_message(request: web.Request):
|
|
110
|
+
data = await request.json()
|
|
111
|
+
await self.updater(data)
|
|
112
|
+
return web.json_response({"status": "OK"})
|
|
113
|
+
|
|
114
|
+
app = web.Application()
|
|
115
|
+
app.add_routes(self.routes)
|
|
116
|
+
|
|
117
|
+
async def on_startup(_):
|
|
118
|
+
await self.set_endpoints()
|
|
119
|
+
app.on_startup.append(on_startup)
|
|
120
|
+
web.run_app(app, host=self.host, port=self.port)
|
|
121
|
+
|
|
122
|
+
else:
|
|
123
|
+
async def polling():
|
|
124
|
+
while True:
|
|
125
|
+
try:
|
|
126
|
+
get_update = await self.get_update(100, self.offset_id)
|
|
127
|
+
if get_update.updates:
|
|
128
|
+
updates = get_update.updates
|
|
129
|
+
for update in updates:
|
|
130
|
+
if update.type == "NewMessage":
|
|
131
|
+
message_time = int(update.new_message.time)
|
|
132
|
+
elif update.type == "UpdatedMessage":
|
|
133
|
+
message_time = int(update.updated_message.time)
|
|
134
|
+
else:
|
|
135
|
+
continue
|
|
84
136
|
|
|
85
|
-
|
|
86
|
-
|
|
137
|
+
now = int(datetime.now().timestamp())
|
|
138
|
+
if message_time >= now or message_time + 2 >= now:
|
|
139
|
+
await self.dispatch_update(update)
|
|
87
140
|
|
|
88
|
-
|
|
89
|
-
|
|
141
|
+
self.offset_id = get_update.next_offset_id
|
|
142
|
+
except Exception as e:
|
|
143
|
+
logger.exception(f"Polling error: {e}")
|
|
144
|
+
await asyncio.sleep(1)
|
|
90
145
|
|
|
91
|
-
|
|
92
|
-
web.run_app(app, host=self.host, port=self.port)
|
|
146
|
+
asyncio.run(polling())
|
rubigram/filters.py
CHANGED
|
@@ -1,145 +1,165 @@
|
|
|
1
1
|
from rubigram.types import Update, InlineMessage
|
|
2
|
-
from
|
|
3
|
-
from typing import Union
|
|
2
|
+
from typing import Union, Callable, Awaitable
|
|
4
3
|
import re
|
|
5
4
|
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
def
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
6
|
+
class Filter:
|
|
7
|
+
def __init__(self, func: Callable[[Union[Update, InlineMessage]], bool | Awaitable[bool]]):
|
|
8
|
+
self.func = func
|
|
9
|
+
|
|
10
|
+
async def __call__(self, update: Union[Update, InlineMessage]) -> bool:
|
|
11
|
+
result = self.func(update)
|
|
12
|
+
if isinstance(result, Awaitable):
|
|
13
|
+
return await result
|
|
14
|
+
return result
|
|
15
|
+
|
|
16
|
+
def __and__(self, other: "Filter"):
|
|
17
|
+
async def combined(update):
|
|
18
|
+
return await self(update) and await other(update)
|
|
19
|
+
return Filter(combined)
|
|
20
|
+
|
|
21
|
+
def __or__(self, other: "Filter"):
|
|
22
|
+
async def combined(update):
|
|
23
|
+
return await self(update) or await other(update)
|
|
24
|
+
return Filter(combined)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class command(Filter):
|
|
28
|
+
def __init__(self, cmd: Union[str, list[str]], prefix: str = "/"):
|
|
29
|
+
self.cmd = cmd
|
|
30
|
+
self.prefix = prefix
|
|
31
|
+
super().__init__(self.filter)
|
|
32
|
+
|
|
33
|
+
def filter(self, update: Update):
|
|
34
|
+
commands = [self.cmd] if isinstance(self.cmd, str) else self.cmd
|
|
35
|
+
text = ""
|
|
36
|
+
if isinstance(update, Update):
|
|
37
|
+
if update.type == "NewMessage":
|
|
38
|
+
text = update.new_message.text
|
|
39
|
+
elif update.type == "UpdatedMessage":
|
|
40
|
+
text = update.updated_message.text
|
|
41
|
+
|
|
42
|
+
for cmd in commands:
|
|
43
|
+
if text.lower().startswith(self.prefix + cmd.lower()):
|
|
38
44
|
return True
|
|
39
|
-
|
|
40
|
-
return filter
|
|
45
|
+
return False
|
|
41
46
|
|
|
42
|
-
def chat(chat_id: Union[str, list[str]]):
|
|
43
|
-
def filter(message: Union[Update, InlineMessage]):
|
|
44
|
-
chat_ids = chat_id if isinstance(chat_id, list) else [chat_id]
|
|
45
|
-
if isinstance(message, Update) or isinstance(message, InlineMessage):
|
|
46
|
-
return message.chat_id in chat_ids
|
|
47
|
-
return False
|
|
48
|
-
return filter
|
|
49
|
-
|
|
50
|
-
def regex(pattern: str):
|
|
51
|
-
def filter(message: Union[Update, InlineMessage]):
|
|
52
|
-
if isinstance(message, Update) and message.type == "NewMessage" and message.new_message.text:
|
|
53
|
-
return bool(re.search(pattern, message.new_message.text))
|
|
54
|
-
elif isinstance(message, InlineMessage) and message.text:
|
|
55
|
-
return bool(re.search(pattern, message.text))
|
|
56
|
-
return False
|
|
57
|
-
return filter
|
|
58
|
-
|
|
59
|
-
def text():
|
|
60
|
-
def filter(message: Update):
|
|
61
|
-
if isinstance(message, Update) and message.type == "NewMessage":
|
|
62
|
-
return message.new_message.text is None
|
|
63
|
-
return False
|
|
64
|
-
return filter
|
|
65
47
|
|
|
66
|
-
|
|
67
|
-
def
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return False
|
|
71
|
-
return filter
|
|
48
|
+
class regex(Filter):
|
|
49
|
+
def __init__(self, pattern: str):
|
|
50
|
+
self.pattern = pattern
|
|
51
|
+
super().__init__(self.filter)
|
|
72
52
|
|
|
73
|
-
def
|
|
74
|
-
|
|
75
|
-
if isinstance(
|
|
76
|
-
|
|
53
|
+
def filter(self, update: Union[Update, InlineMessage]):
|
|
54
|
+
text = ""
|
|
55
|
+
if isinstance(update, Update):
|
|
56
|
+
if update.type == "NewMessage":
|
|
57
|
+
text = getattr(update.new_message, "text", "")
|
|
58
|
+
elif update.type == "UpdatedMessage":
|
|
59
|
+
text = getattr(update.updated_message, "text", "")
|
|
60
|
+
elif isinstance(update, InlineMessage):
|
|
61
|
+
text = getattr(update, "text", "")
|
|
62
|
+
|
|
63
|
+
if text:
|
|
64
|
+
return bool(re.search(self.pattern, text))
|
|
77
65
|
return False
|
|
78
|
-
return filter
|
|
79
66
|
|
|
80
67
|
|
|
81
|
-
|
|
82
|
-
def
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return False
|
|
86
|
-
return filter
|
|
68
|
+
class chat(Filter):
|
|
69
|
+
def __init__(self, chat_id: Union[str, list[str]]):
|
|
70
|
+
self.chat_id = chat_id
|
|
71
|
+
super().__init__(self.filter)
|
|
87
72
|
|
|
88
|
-
def
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return False
|
|
93
|
-
return filter
|
|
73
|
+
def filter(self, update: Union[Update, InlineMessage]):
|
|
74
|
+
chat_ids = [self.chat_id] if isinstance(
|
|
75
|
+
self.chat_id, str) else self.chat_id
|
|
76
|
+
return update.chat_id in chat_ids
|
|
94
77
|
|
|
95
78
|
|
|
96
|
-
|
|
97
|
-
def
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return False
|
|
101
|
-
return filter
|
|
79
|
+
class button(Filter):
|
|
80
|
+
def __init__(self, button_id: Union[str, list[str]]):
|
|
81
|
+
self.button_id = button_id
|
|
82
|
+
super().__init__(self.filter)
|
|
102
83
|
|
|
84
|
+
def filter(self, update: InlineMessage):
|
|
85
|
+
if isinstance(update, InlineMessage):
|
|
86
|
+
button_ids = [self.button_id] if isinstance(
|
|
87
|
+
self.button_id, str) else self.button_id
|
|
88
|
+
return update.aux_data.button_id in button_ids
|
|
103
89
|
|
|
104
|
-
def forward_bot():
|
|
105
|
-
def filter(message: Update):
|
|
106
|
-
if isinstance(message, Update) and message.type == "NewMessage" and message.new_message.forwarded_from:
|
|
107
|
-
return message.new_message.forwarded_from.from_sender_id == "Bot"
|
|
108
|
-
return False
|
|
109
|
-
return filter
|
|
110
90
|
|
|
111
91
|
|
|
112
|
-
def
|
|
113
|
-
|
|
114
|
-
if isinstance(message, Update) and message.type == "NewMessage":
|
|
115
|
-
return message.new_message.location is None
|
|
116
|
-
return False
|
|
117
|
-
return filter
|
|
92
|
+
def TEXT(update: Update):
|
|
93
|
+
return bool(update.new_message and getattr(update.new_message, "text", None))
|
|
118
94
|
|
|
119
|
-
def sticker():
|
|
120
|
-
def filter(message: Update):
|
|
121
|
-
if isinstance(message, Update) and message.type == "NewMessage":
|
|
122
|
-
return message.new_message.sticker is None
|
|
123
|
-
return False
|
|
124
|
-
return filter
|
|
125
95
|
|
|
126
|
-
def
|
|
127
|
-
|
|
128
|
-
if isinstance(message, Update) and message.type == "NewMessage":
|
|
129
|
-
return message.new_message.contact_message is None
|
|
130
|
-
return False
|
|
131
|
-
return filter
|
|
96
|
+
def FILE(update: Update):
|
|
97
|
+
return bool(update.new_message and getattr(update.new_message, "file", None))
|
|
132
98
|
|
|
133
|
-
def poll():
|
|
134
|
-
def filter(message: Update):
|
|
135
|
-
if isinstance(message, Update) and message.type == "NewMessage":
|
|
136
|
-
return message.new_message.poll is None
|
|
137
|
-
return False
|
|
138
|
-
return filter
|
|
139
99
|
|
|
140
|
-
def
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
return
|
|
100
|
+
def LIVE(update: Update):
|
|
101
|
+
return bool(update.new_message and getattr(update.new_message, "live_location", None))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def POLL(update: Update):
|
|
105
|
+
return bool(update.new_message and getattr(update.new_message, "poll", None))
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def CONTACT(update: Update):
|
|
109
|
+
return bool(update.new_message and getattr(update.new_message, "contact_message", None))
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def STICKER(update: Update):
|
|
113
|
+
return bool(update.new_message and getattr(update.new_message, "sticker", None))
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def LOCATION(update: Update):
|
|
117
|
+
return bool(update.new_message and getattr(update.new_message, "location", None))
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def FORWARD(update: Update):
|
|
121
|
+
return bool(update.new_message and getattr(update.new_message, "forwarded_from", None))
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def EDITED(update: Update):
|
|
125
|
+
if isinstance(update, Update) and update.type == "UpdatedMessage":
|
|
126
|
+
return update.updated_message.is_edited
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def PRIVATE(update: Update):
|
|
130
|
+
if isinstance(update, Update) and update.type == "NewMessage":
|
|
131
|
+
return update.new_message.sender_type in ["User", "Bot"]
|
|
132
|
+
return False
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def FORWARD_BOT(update: Update):
|
|
136
|
+
if isinstance(update, Update) and update.type == "NewMessage" and update.new_message.forwarded_from:
|
|
137
|
+
return update.new_message.forwarded_from.type_from == "Bot"
|
|
138
|
+
return False
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def FORWARD_USER(update: Update):
|
|
142
|
+
if isinstance(update, Update) and update.type == "NewMessage" and update.new_message.forwarded_from:
|
|
143
|
+
return update.new_message.forwarded_from.type_from == "User"
|
|
144
|
+
return False
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def FORWARD_CHANNEL(update: Update):
|
|
148
|
+
if isinstance(update, Update) and update.type == "NewMessage" and update.new_message.forwarded_from:
|
|
149
|
+
return update.new_message.forwarded_from.type_from == "Channel"
|
|
150
|
+
return False
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
text = Filter(TEXT)
|
|
154
|
+
file = Filter(FILE)
|
|
155
|
+
live = Filter(LIVE)
|
|
156
|
+
poll = Filter(POLL)
|
|
157
|
+
edited = Filter(EDITED)
|
|
158
|
+
contact = Filter(CONTACT)
|
|
159
|
+
sticker = Filter(STICKER)
|
|
160
|
+
location = Filter(LOCATION)
|
|
161
|
+
forward = Filter(FORWARD)
|
|
162
|
+
private = Filter(PRIVATE)
|
|
163
|
+
forward_bot = Filter(FORWARD_BOT)
|
|
164
|
+
forward_user = Filter(FORWARD_USER)
|
|
165
|
+
forward_channel = Filter(FORWARD_CHANNEL)
|
rubigram/method.py
CHANGED
|
@@ -1,65 +1,66 @@
|
|
|
1
|
-
from
|
|
1
|
+
from .network import Network
|
|
2
2
|
from typing import Literal, Optional
|
|
3
|
-
from
|
|
3
|
+
from .types import Bot, Chat, Keypad, MessageId, Updates
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class Method(Network):
|
|
7
7
|
def __init__(self, token: str):
|
|
8
8
|
super().__init__(token)
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
async def get_me(self) -> "Bot":
|
|
11
11
|
response = await self.request("getMe", {})
|
|
12
12
|
return Bot.from_dict(response["bot"])
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
async def get_chat(self, chat_id: str) -> "Chat":
|
|
15
15
|
response = await self.request("getChat", {"chat_id": chat_id})
|
|
16
16
|
return Chat.from_dict(response["chat"])
|
|
17
|
-
|
|
18
|
-
async def get_update(self, limit: int = 1, offset_id: Optional[int] = None) ->
|
|
17
|
+
|
|
18
|
+
async def get_update(self, limit: int = 1, offset_id: Optional[int] = None) -> "Updates":
|
|
19
19
|
response = await self.request("getUpdates", {"limit": limit, "offset_id": offset_id})
|
|
20
|
-
return
|
|
21
|
-
|
|
20
|
+
return Updates.from_dict(response)
|
|
21
|
+
|
|
22
22
|
async def get_file(self, file_id: str) -> str:
|
|
23
23
|
response = await self.request("getFile", {"file_id": file_id})
|
|
24
24
|
return response["download_url"]
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
async def set_command(self, command: list):
|
|
27
27
|
response = await self.request("setCommands", {"bot_commands": command})
|
|
28
28
|
return response
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
async def update_bot_endpoint(self, url: str, type: Literal["ReceiveUpdate", "ReceiveInlineMessage", "ReceiveQuery", "GetSelectionItem", "SearchSelectionItems"]):
|
|
31
31
|
response = await self.request("updateBotEndpoints", {"url": url, "type": type})
|
|
32
32
|
return response
|
|
33
|
-
|
|
34
|
-
async def forward_message(self, from_chat_id: str, message_id: str, to_chat_id: str, disable_notification: bool = False) -> "MessageId":
|
|
35
|
-
data = {"from_chat_id": from_chat_id, "message_id": message_id, "to_chat_id": to_chat_id, "disable_notification": disable_notification}
|
|
36
|
-
response = await self.request("forwardMessage", data)
|
|
37
|
-
return MessageId.from_dict(response)
|
|
38
|
-
|
|
33
|
+
|
|
39
34
|
async def delete_message(self, chat_id: str, message_id: str):
|
|
40
35
|
await self.request("deleteMessage", {"chat_id": chat_id, "message_id": message_id})
|
|
41
|
-
|
|
36
|
+
|
|
42
37
|
async def remove_chat_keypad(self, chat_id: str):
|
|
43
38
|
await self.request("editChatKeypad", {"chat_id": chat_id, "chat_keypad_type": "Remove"})
|
|
44
|
-
|
|
39
|
+
|
|
45
40
|
async def edit_chat_keypad(self, chat_id: str, chat_keypad):
|
|
46
41
|
await self.request("editChatKeypad", {"chat_id": chat_id, "chat_keypad_type": "New", "chat_keypad": chat_keypad})
|
|
47
42
|
|
|
48
43
|
async def edit_message_keypad(self, chat_id: str, message_id: str, inline_keypad):
|
|
49
44
|
await self.request("editMessageKeypad", {"chat_id": chat_id, "message_id": message_id, "inline_keypad": inline_keypad})
|
|
50
|
-
|
|
45
|
+
|
|
51
46
|
async def edit_message_text(self, chat_id: str, message_id: str, text: str):
|
|
52
47
|
await self.request("editMessageText", {"chat_id": chat_id, "message_id": message_id, "text": text})
|
|
53
|
-
|
|
48
|
+
|
|
49
|
+
async def forward_message(self, from_chat_id: str, message_id: str, to_chat_id: str, disable_notification: bool = False) -> "MessageId":
|
|
50
|
+
data = {"from_chat_id": from_chat_id, "message_id": message_id,
|
|
51
|
+
"to_chat_id": to_chat_id, "disable_notification": disable_notification}
|
|
52
|
+
response = await self.request("forwardMessage", data)
|
|
53
|
+
return MessageId.from_dict(response)
|
|
54
|
+
|
|
54
55
|
async def send_message(
|
|
55
56
|
self,
|
|
56
57
|
chat_id: str,
|
|
57
58
|
text: str,
|
|
58
59
|
chat_keypad: Keypad = None,
|
|
59
|
-
inline_keypad: Keypad= None,
|
|
60
|
+
inline_keypad: Keypad = None,
|
|
60
61
|
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
61
62
|
disable_notification: bool = None,
|
|
62
|
-
reply_to_message_id
|
|
63
|
+
reply_to_message_id=None
|
|
63
64
|
) -> "MessageId":
|
|
64
65
|
data = {
|
|
65
66
|
"chat_id": chat_id,
|
|
@@ -72,7 +73,7 @@ class Method(Network):
|
|
|
72
73
|
}
|
|
73
74
|
response = await self.request("sendMessage", data)
|
|
74
75
|
return MessageId.from_dict(response)
|
|
75
|
-
|
|
76
|
+
|
|
76
77
|
async def send_poll(
|
|
77
78
|
self,
|
|
78
79
|
chat_id: str,
|
|
@@ -96,7 +97,7 @@ class Method(Network):
|
|
|
96
97
|
}
|
|
97
98
|
response = await self.request("sendPoll", data)
|
|
98
99
|
return MessageId.from_dict(response)
|
|
99
|
-
|
|
100
|
+
|
|
100
101
|
async def send_location(
|
|
101
102
|
self,
|
|
102
103
|
chat_id: str,
|
|
@@ -120,7 +121,7 @@ class Method(Network):
|
|
|
120
121
|
}
|
|
121
122
|
response = await self.request("sendLocation", data)
|
|
122
123
|
return MessageId.from_dict(response)
|
|
123
|
-
|
|
124
|
+
|
|
124
125
|
async def send_contact(
|
|
125
126
|
self,
|
|
126
127
|
chat_id: str,
|
|
@@ -146,7 +147,7 @@ class Method(Network):
|
|
|
146
147
|
}
|
|
147
148
|
response = await self.request("sendContact", data)
|
|
148
149
|
return MessageId.from_dict(response)
|
|
149
|
-
|
|
150
|
+
|
|
150
151
|
async def send_sticker(
|
|
151
152
|
self,
|
|
152
153
|
chat_id: str,
|
|
@@ -166,30 +167,31 @@ class Method(Network):
|
|
|
166
167
|
"reply_to_message_id": reply_to_message_id,
|
|
167
168
|
"chat_keypad_type": chat_keypad_type
|
|
168
169
|
}
|
|
170
|
+
|
|
169
171
|
response = await self.request("sendSticker", data)
|
|
170
172
|
return MessageId.from_dict(response)
|
|
171
|
-
|
|
173
|
+
|
|
172
174
|
async def request_send_file(self, type: str):
|
|
173
175
|
response = await self.request("requestSendFile", {"type": type})
|
|
174
176
|
return response["upload_url"]
|
|
175
|
-
|
|
177
|
+
|
|
176
178
|
async def upload_file(self, file: str, name: str, type: str):
|
|
177
179
|
upload_url = await self.request_send_file(type)
|
|
178
180
|
response = await self.request_upload_file(upload_url, file, name)
|
|
179
181
|
return response
|
|
180
|
-
|
|
181
|
-
|
|
182
|
+
|
|
182
183
|
async def download_file(self, file_id: str, file_name: str):
|
|
183
184
|
download_url = await self.get_file(file_id)
|
|
184
185
|
response = await self.request_download_file(download_url, file_name)
|
|
185
186
|
return response
|
|
186
|
-
|
|
187
|
+
|
|
187
188
|
async def send_file(
|
|
188
189
|
self,
|
|
189
190
|
chat_id: str,
|
|
190
191
|
file: str,
|
|
191
192
|
file_name: str,
|
|
192
|
-
type: Literal["File", "Image", "Voice",
|
|
193
|
+
type: Literal["File", "Image", "Voice",
|
|
194
|
+
"Music", "Gif", "Video"] = "File",
|
|
193
195
|
chat_keypad: Keypad = None,
|
|
194
196
|
inline_keypad: Keypad = None,
|
|
195
197
|
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
@@ -208,148 +210,21 @@ class Method(Network):
|
|
|
208
210
|
}
|
|
209
211
|
response = await self.request("sendFile", data)
|
|
210
212
|
return MessageId.from_dict(response)
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
"inline_keypad": inline_keypad.to_dict() if inline_keypad else None,
|
|
230
|
-
"disable_notification": disable_notification,
|
|
231
|
-
"reply_to_message_id": reply_to_message_id,
|
|
232
|
-
"chat_keypad_type": chat_keypad_type,
|
|
233
|
-
}
|
|
234
|
-
response = await self.request("sendFile", data)
|
|
235
|
-
return MessageId.from_dict(response)
|
|
236
|
-
|
|
237
|
-
async def send_photo(
|
|
238
|
-
self,
|
|
239
|
-
chat_id: str,
|
|
240
|
-
photo: str,
|
|
241
|
-
name: str,
|
|
242
|
-
chat_keypad: Keypad = None,
|
|
243
|
-
inline_keypad: Keypad = None,
|
|
244
|
-
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
245
|
-
disable_notification: bool = False,
|
|
246
|
-
reply_to_message_id: str = None,
|
|
247
|
-
) -> "MessageId":
|
|
248
|
-
file_id = await self.upload_file(photo, name, "Image")
|
|
249
|
-
data = {
|
|
250
|
-
"chat_id": chat_id,
|
|
251
|
-
"file_id": file_id,
|
|
252
|
-
"chat_keypad": chat_keypad.to_dict() if chat_keypad else None,
|
|
253
|
-
"inline_keypad": inline_keypad.to_dict() if inline_keypad else None,
|
|
254
|
-
"disable_notification": disable_notification,
|
|
255
|
-
"reply_to_message_id": reply_to_message_id,
|
|
256
|
-
"chat_keypad_type": chat_keypad_type,
|
|
257
|
-
}
|
|
258
|
-
response = await self.request("sendFile", data)
|
|
259
|
-
return MessageId.from_dict(response)
|
|
260
|
-
|
|
261
|
-
async def send_video(
|
|
262
|
-
self,
|
|
263
|
-
chat_id: str,
|
|
264
|
-
video: str,
|
|
265
|
-
name: str,
|
|
266
|
-
chat_keypad: Keypad = None,
|
|
267
|
-
inline_keypad: Keypad = None,
|
|
268
|
-
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
269
|
-
disable_notification: bool = False,
|
|
270
|
-
reply_to_message_id: str = None,
|
|
271
|
-
) -> "MessageId":
|
|
272
|
-
file_id = await self.upload_file(video, name, "Video")
|
|
273
|
-
data = {
|
|
274
|
-
"chat_id": chat_id,
|
|
275
|
-
"file_id": file_id,
|
|
276
|
-
"chat_keypad": chat_keypad.to_dict() if chat_keypad else None,
|
|
277
|
-
"inline_keypad": inline_keypad.to_dict() if inline_keypad else None,
|
|
278
|
-
"disable_notification": disable_notification,
|
|
279
|
-
"reply_to_message_id": reply_to_message_id,
|
|
280
|
-
"chat_keypad_type": chat_keypad_type,
|
|
281
|
-
}
|
|
282
|
-
response = await self.request("sendFile", data)
|
|
283
|
-
return MessageId.from_dict(response)
|
|
284
|
-
|
|
285
|
-
async def send_gif(
|
|
286
|
-
self,
|
|
287
|
-
chat_id: str,
|
|
288
|
-
gif: str,
|
|
289
|
-
name: str,
|
|
290
|
-
chat_keypad: Keypad = None,
|
|
291
|
-
inline_keypad: Keypad = None,
|
|
292
|
-
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
293
|
-
disable_notification: bool = False,
|
|
294
|
-
reply_to_message_id: str = None,
|
|
295
|
-
) -> "MessageId":
|
|
296
|
-
file_id = await self.upload_file(gif, name, "Gif")
|
|
297
|
-
data = {
|
|
298
|
-
"chat_id": chat_id,
|
|
299
|
-
"file_id": file_id,
|
|
300
|
-
"chat_keypad": chat_keypad.to_dict() if chat_keypad else None,
|
|
301
|
-
"inline_keypad": inline_keypad.to_dict() if inline_keypad else None,
|
|
302
|
-
"disable_notification": disable_notification,
|
|
303
|
-
"reply_to_message_id": reply_to_message_id,
|
|
304
|
-
"chat_keypad_type": chat_keypad_type,
|
|
305
|
-
}
|
|
306
|
-
response = await self.request("sendFile", data)
|
|
307
|
-
return MessageId.from_dict(response)
|
|
308
|
-
|
|
309
|
-
async def send_music(
|
|
310
|
-
self,
|
|
311
|
-
chat_id: str,
|
|
312
|
-
music: str,
|
|
313
|
-
name: str,
|
|
314
|
-
chat_keypad: Keypad = None,
|
|
315
|
-
inline_keypad: Keypad = None,
|
|
316
|
-
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
317
|
-
disable_notification: bool = False,
|
|
318
|
-
reply_to_message_id: str = None,
|
|
319
|
-
) -> "MessageId":
|
|
320
|
-
file_id = await self.upload_file(music, name, "Music")
|
|
321
|
-
data = {
|
|
322
|
-
"chat_id": chat_id,
|
|
323
|
-
"file_id": file_id,
|
|
324
|
-
"chat_keypad": chat_keypad.to_dict() if chat_keypad else None,
|
|
325
|
-
"inline_keypad": inline_keypad.to_dict() if inline_keypad else None,
|
|
326
|
-
"disable_notification": disable_notification,
|
|
327
|
-
"reply_to_message_id": reply_to_message_id,
|
|
328
|
-
"chat_keypad_type": chat_keypad_type,
|
|
329
|
-
}
|
|
330
|
-
response = await self.request("sendFile", data)
|
|
331
|
-
return MessageId.from_dict(response)
|
|
332
|
-
|
|
333
|
-
async def send_voice(
|
|
334
|
-
self,
|
|
335
|
-
chat_id: str,
|
|
336
|
-
voice: str,
|
|
337
|
-
name: str,
|
|
338
|
-
chat_keypad: Keypad = None,
|
|
339
|
-
inline_keypad: Keypad = None,
|
|
340
|
-
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
341
|
-
disable_notification: bool = False,
|
|
342
|
-
reply_to_message_id: str = None,
|
|
343
|
-
) -> "MessageId":
|
|
344
|
-
file_id = await self.upload_file(voice, name, "Voice")
|
|
345
|
-
data = {
|
|
346
|
-
"chat_id": chat_id,
|
|
347
|
-
"file_id": file_id,
|
|
348
|
-
"chat_keypad": chat_keypad.to_dict() if chat_keypad else None,
|
|
349
|
-
"inline_keypad": inline_keypad.to_dict() if inline_keypad else None,
|
|
350
|
-
"disable_notification": disable_notification,
|
|
351
|
-
"reply_to_message_id": reply_to_message_id,
|
|
352
|
-
"chat_keypad_type": chat_keypad_type,
|
|
353
|
-
}
|
|
354
|
-
response = await self.request("sendFile", data)
|
|
355
|
-
return MessageId.from_dict(response)
|
|
213
|
+
|
|
214
|
+
async def send_document(self, chat_id: str, document: str, name: str, **kwargs):
|
|
215
|
+
return await self.send_file(chat_id, document, name, "File", **kwargs)
|
|
216
|
+
|
|
217
|
+
async def send_photo(self, chat_id: str, photo: str, name: str, **kwargs):
|
|
218
|
+
return await self.send_file(chat_id, photo, name, "Image", **kwargs)
|
|
219
|
+
|
|
220
|
+
async def send_video(self, chat_id: str, video: str, name: str, **kwargs):
|
|
221
|
+
return await self.send_file(chat_id, video, name, "Video", **kwargs)
|
|
222
|
+
|
|
223
|
+
async def send_gif(self, chat_id: str, gif: str, name: str, **kwargs):
|
|
224
|
+
return await self.send_file(chat_id, gif, name, "Gif", **kwargs)
|
|
225
|
+
|
|
226
|
+
async def send_music(self, chat_id: str, music: str, name: str, **kwargs):
|
|
227
|
+
return await self.send_file(chat_id, music, name, "Music", **kwargs)
|
|
228
|
+
|
|
229
|
+
async def send_voice(self, chat_id: str, voice: str, name: str, **kwargs):
|
|
230
|
+
return await self.send_file(chat_id, voice, name, "Voice", **kwargs)
|
rubigram/types.py
CHANGED
|
@@ -5,6 +5,7 @@ import rubigram
|
|
|
5
5
|
|
|
6
6
|
T = TypeVar("T", bound="Dict")
|
|
7
7
|
|
|
8
|
+
|
|
8
9
|
@dataclass
|
|
9
10
|
class Dict:
|
|
10
11
|
def to_dict(self) -> dict[str, Any]:
|
|
@@ -14,7 +15,8 @@ class Dict:
|
|
|
14
15
|
if is_dataclass(value):
|
|
15
16
|
data[field.name] = value.to_dict()
|
|
16
17
|
elif isinstance(value, list):
|
|
17
|
-
data[field.name] = [i.to_dict() if is_dataclass(i)
|
|
18
|
+
data[field.name] = [i.to_dict() if is_dataclass(i)
|
|
19
|
+
else i for i in value]
|
|
18
20
|
else:
|
|
19
21
|
data[field.name] = value
|
|
20
22
|
return data
|
|
@@ -22,7 +24,7 @@ class Dict:
|
|
|
22
24
|
@classmethod
|
|
23
25
|
def from_dict(cls: Type[T], data: dict[str, Any]) -> Optional[T]:
|
|
24
26
|
if data is None:
|
|
25
|
-
|
|
27
|
+
data = {}
|
|
26
28
|
init_data = {}
|
|
27
29
|
for field in fields(cls):
|
|
28
30
|
value = data.get(field.name)
|
|
@@ -33,12 +35,14 @@ class Dict:
|
|
|
33
35
|
elif origin == list:
|
|
34
36
|
inner_type = get_args(field_type)[0]
|
|
35
37
|
if isinstance(inner_type, type) and issubclass(inner_type, Dict):
|
|
36
|
-
init_data[field.name] = [inner_type.from_dict(
|
|
38
|
+
init_data[field.name] = [inner_type.from_dict(
|
|
39
|
+
v) if isinstance(v, dict) else v for v in (value or [])]
|
|
37
40
|
else:
|
|
38
41
|
init_data[field.name] = value or []
|
|
39
42
|
elif get_origin(field_type) is Union:
|
|
40
43
|
args = get_args(field_type)
|
|
41
|
-
dict_type = next((a for a in args if isinstance(
|
|
44
|
+
dict_type = next((a for a in args if isinstance(
|
|
45
|
+
a, type) and issubclass(a, Dict)), None)
|
|
42
46
|
if dict_type and isinstance(value, dict):
|
|
43
47
|
init_data[field.name] = dict_type.from_dict(value)
|
|
44
48
|
else:
|
|
@@ -65,6 +69,7 @@ class JoinChannelData(Dict):
|
|
|
65
69
|
username: Optional[str] = None
|
|
66
70
|
ask_join: Optional[bool] = False
|
|
67
71
|
|
|
72
|
+
|
|
68
73
|
@dataclass
|
|
69
74
|
class ButtonLink(Dict):
|
|
70
75
|
type: Optional[Literal["joinchannel", "url"]] = None
|
|
@@ -292,172 +297,63 @@ class MessageId(Dict):
|
|
|
292
297
|
@dataclass
|
|
293
298
|
class Update(Dict):
|
|
294
299
|
client: Optional["rubigram.Client"] = None
|
|
295
|
-
type: Optional[Literal["NewMessage", "UpdatedMessage", "RemovedMessage",
|
|
300
|
+
type: Optional[Literal["NewMessage", "UpdatedMessage", "RemovedMessage",
|
|
301
|
+
"StartedBot", "StoppedBot", "UpdatedPayment"]] = None
|
|
296
302
|
chat_id: Optional[str] = None
|
|
297
303
|
removed_message_id: Optional[str] = None
|
|
298
304
|
new_message: Optional[Message] = None
|
|
299
305
|
updated_message: Optional[Message] = None
|
|
300
306
|
updated_payment: Optional[PaymentStatus] = None
|
|
307
|
+
|
|
308
|
+
async def send_text(self, text: str,) -> "MessageId":
|
|
309
|
+
return await self.client.send_message(self.chat_id, text)
|
|
301
310
|
|
|
302
|
-
async def
|
|
303
|
-
self,
|
|
304
|
-
|
|
305
|
-
chat_keypad: Keypad = None,
|
|
306
|
-
inline_keypad: Keypad= None,
|
|
307
|
-
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
308
|
-
disable_notification: bool = None,
|
|
309
|
-
reply_to_message_id = None
|
|
310
|
-
) -> "MessageId":
|
|
311
|
-
return await self.client.send_message(self.chat_id, text, chat_keypad, inline_keypad, chat_keypad_type, disable_notification, reply_to_message_id)
|
|
312
|
-
|
|
311
|
+
async def download(self, name: str):
|
|
312
|
+
return await self.client.download_file(self.new_message.file.file_id, name)
|
|
313
|
+
|
|
313
314
|
async def reply(
|
|
314
315
|
self,
|
|
315
316
|
text: str,
|
|
316
317
|
chat_keypad: Keypad = None,
|
|
317
|
-
inline_keypad: Keypad= None,
|
|
318
|
+
inline_keypad: Keypad = None,
|
|
318
319
|
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
319
320
|
disable_notification: bool = None,
|
|
320
321
|
) -> "MessageId":
|
|
321
322
|
return await self.client.send_message(self.chat_id, text, chat_keypad, inline_keypad, chat_keypad_type, disable_notification, self.new_message.message_id)
|
|
322
|
-
|
|
323
|
+
|
|
323
324
|
async def reply_file(
|
|
324
325
|
self,
|
|
325
326
|
file: str,
|
|
326
327
|
file_name: str,
|
|
327
|
-
type: Literal["File", "Image", "Voice",
|
|
328
|
-
|
|
329
|
-
inline_keypad: Keypad = None,
|
|
330
|
-
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
331
|
-
disable_notification: bool = False,
|
|
332
|
-
) -> "MessageId":
|
|
333
|
-
return await self.client.send_file(
|
|
334
|
-
self.chat_id,
|
|
335
|
-
file,
|
|
336
|
-
file_name,
|
|
337
|
-
type,
|
|
338
|
-
chat_keypad,
|
|
339
|
-
inline_keypad,
|
|
340
|
-
chat_keypad_type,
|
|
341
|
-
disable_notification,
|
|
342
|
-
self.new_message.message_id
|
|
343
|
-
)
|
|
344
|
-
|
|
345
|
-
async def reply_document(
|
|
346
|
-
self,
|
|
347
|
-
document: str,
|
|
348
|
-
name: str,
|
|
328
|
+
type: Literal["File", "Image", "Voice",
|
|
329
|
+
"Music", "Gif", "Video"] = "File",
|
|
349
330
|
chat_keypad: Keypad = None,
|
|
350
331
|
inline_keypad: Keypad = None,
|
|
351
332
|
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
352
333
|
disable_notification: bool = False,
|
|
353
334
|
) -> "MessageId":
|
|
354
|
-
return await self.client.
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
)
|
|
364
|
-
|
|
365
|
-
async def
|
|
366
|
-
self,
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
inline_keypad,
|
|
380
|
-
chat_keypad_type,
|
|
381
|
-
disable_notification,
|
|
382
|
-
self.new_message.message_id
|
|
383
|
-
)
|
|
384
|
-
|
|
385
|
-
async def reply_video(
|
|
386
|
-
self,
|
|
387
|
-
video: str,
|
|
388
|
-
name: str,
|
|
389
|
-
chat_keypad: Keypad = None,
|
|
390
|
-
inline_keypad: Keypad = None,
|
|
391
|
-
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
392
|
-
disable_notification: bool = False,
|
|
393
|
-
) -> "MessageId":
|
|
394
|
-
return await self.client.send_video(
|
|
395
|
-
self.chat_id,
|
|
396
|
-
video,
|
|
397
|
-
name,
|
|
398
|
-
chat_keypad,
|
|
399
|
-
inline_keypad,
|
|
400
|
-
chat_keypad_type,
|
|
401
|
-
disable_notification,
|
|
402
|
-
self.new_message.message_id
|
|
403
|
-
)
|
|
404
|
-
|
|
405
|
-
async def reply_gif(
|
|
406
|
-
self,
|
|
407
|
-
gif: str,
|
|
408
|
-
name: str,
|
|
409
|
-
chat_keypad: Keypad = None,
|
|
410
|
-
inline_keypad: Keypad = None,
|
|
411
|
-
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
412
|
-
disable_notification: bool = False,
|
|
413
|
-
) -> "MessageId":
|
|
414
|
-
return await self.client.send_gif(
|
|
415
|
-
self.chat_id,
|
|
416
|
-
gif,
|
|
417
|
-
name,
|
|
418
|
-
chat_keypad,
|
|
419
|
-
inline_keypad,
|
|
420
|
-
chat_keypad_type,
|
|
421
|
-
disable_notification,
|
|
422
|
-
self.new_message.message_id
|
|
423
|
-
)
|
|
424
|
-
|
|
425
|
-
async def reply_music(
|
|
426
|
-
self,
|
|
427
|
-
music: str,
|
|
428
|
-
name: str,
|
|
429
|
-
chat_keypad: Keypad = None,
|
|
430
|
-
inline_keypad: Keypad = None,
|
|
431
|
-
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
432
|
-
disable_notification: bool = False,
|
|
433
|
-
) -> "MessageId":
|
|
434
|
-
return await self.client.send_music(
|
|
435
|
-
self.chat_id,
|
|
436
|
-
music,
|
|
437
|
-
name,
|
|
438
|
-
chat_keypad,
|
|
439
|
-
inline_keypad,
|
|
440
|
-
chat_keypad_type,
|
|
441
|
-
disable_notification,
|
|
442
|
-
self.new_message.message_id
|
|
443
|
-
)
|
|
444
|
-
|
|
445
|
-
async def replyvoice(
|
|
446
|
-
self,
|
|
447
|
-
voice: str,
|
|
448
|
-
name: str,
|
|
449
|
-
chat_keypad: Keypad = None,
|
|
450
|
-
inline_keypad: Keypad = None,
|
|
451
|
-
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
452
|
-
disable_notification: bool = False,
|
|
453
|
-
) -> "MessageId":
|
|
454
|
-
return await self.client.send_voice(
|
|
455
|
-
self.chat_id,
|
|
456
|
-
voice,
|
|
457
|
-
name,
|
|
458
|
-
chat_keypad,
|
|
459
|
-
inline_keypad,
|
|
460
|
-
chat_keypad_type,
|
|
461
|
-
disable_notification,
|
|
462
|
-
self.new_message.message_id
|
|
463
|
-
)
|
|
335
|
+
return await self.client.send_file(self.chat_id, file, file_name, type, chat_keypad, inline_keypad, chat_keypad_type, disable_notification, self.new_message.message_id)
|
|
336
|
+
|
|
337
|
+
async def reply_document(self, document: str, name: str, **kwargs) -> "MessageId":
|
|
338
|
+
return await self.reply_file(document, name, "File", **kwargs)
|
|
339
|
+
|
|
340
|
+
async def reply_photo(self, photo: str, name: str, **kwargs) -> "MessageId":
|
|
341
|
+
return await self.reply_file(photo, name, "Image", **kwargs)
|
|
342
|
+
|
|
343
|
+
async def reply_video(self, video: str, name: str, **kwargs) -> "MessageId":
|
|
344
|
+
return await self.reply_file(video, name, "Video", **kwargs)
|
|
345
|
+
|
|
346
|
+
async def reply_gif(self, gif: str, name: str, **kwargs) -> "MessageId":
|
|
347
|
+
return await self.reply_file(gif, name, "Gif", **kwargs)
|
|
348
|
+
|
|
349
|
+
async def reply_music(self, music: str, name: str, **kwargs) -> "MessageId":
|
|
350
|
+
return await self.reply_file(music, name, "Music", **kwargs)
|
|
351
|
+
|
|
352
|
+
async def reply_voice(self, voice: str, name: str, **kwargs) -> "MessageId":
|
|
353
|
+
return await self.reply_file(voice, name, "Voice", **kwargs)
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
@dataclass
|
|
357
|
+
class Updates(Dict):
|
|
358
|
+
updates: list[Update] = None
|
|
359
|
+
next_offset_id: Optional[str] = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: RubigramClient
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.2
|
|
4
4
|
Summary: A simple and flexible Python library for building advanced Rubika bots with powerful message handling, inline buttons, and custom filters.
|
|
5
5
|
Author-email: Javad RZ <Javad.Py1385@gmail.com>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
rubigram/__init__.py,sha256=Z0foTm6Hpy4CDEH5am-IFWifi0bo4jLvpkfj3JQQHPc,107
|
|
2
|
+
rubigram/client.py,sha256=GqTECi0_rVHV5ZPF-GSL577bT5EEG6RWJqYg8BC1chY,6083
|
|
3
|
+
rubigram/filters.py,sha256=Zp9V81cHp41Qg4NcupZeZCaGfg3e8UUlHx2B8Xbdv7s,5386
|
|
4
|
+
rubigram/method.py,sha256=OnV4O3jLvA453qFxv8dLjX7Vd-XL5goZFnuM-BrjWZM,9920
|
|
5
|
+
rubigram/network.py,sha256=B5y_n7CC7wdMkzNqKpUG9cC7Cq86R0QJCwcScExluvM,2299
|
|
6
|
+
rubigram/types.py,sha256=_D1raWerXaMhHo0M7i6oFoZOc_RsnlQUXLWlfhnoSDY,11719
|
|
7
|
+
rubigramclient-1.4.2.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
rubigramclient-1.4.2.dist-info/METADATA,sha256=lFRnrGhVnO43XBnHi4Za7AQWzipj71yQVR43U_4JzCg,2035
|
|
9
|
+
rubigramclient-1.4.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
10
|
+
rubigramclient-1.4.2.dist-info/top_level.txt,sha256=Mhg5HfkL6rLec5sI4ClGmwoqYUANAZUz8sVa1sT_cas,9
|
|
11
|
+
rubigramclient-1.4.2.dist-info/RECORD,,
|
rubigram/state.py
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
from typing import Any, Union, Optional
|
|
2
|
-
|
|
3
|
-
class StateManager:
|
|
4
|
-
def __init__(self):
|
|
5
|
-
self.states: dict[str, Any] = {}
|
|
6
|
-
self.datas: dict[str, dict[str, Any]] = {}
|
|
7
|
-
|
|
8
|
-
def set_state(self, user_id: str, state: Any):
|
|
9
|
-
self.states[user_id] = state
|
|
10
|
-
|
|
11
|
-
def get_state(self, user_id: str):
|
|
12
|
-
return self.states.get(user_id)
|
|
13
|
-
|
|
14
|
-
def clear_state(self, user_id: str):
|
|
15
|
-
self.states.pop(user_id, None)
|
|
16
|
-
|
|
17
|
-
def set_data(self, user_id: str, **data):
|
|
18
|
-
if user_id not in self.datas:
|
|
19
|
-
self.datas[user_id] = {}
|
|
20
|
-
self.datas[user_id].update(data)
|
|
21
|
-
|
|
22
|
-
def get_data(self, user_id: str, key: Optional[Union[str, int]] = None):
|
|
23
|
-
if key is not None:
|
|
24
|
-
return self.datas.get(user_id, {}).get(key)
|
|
25
|
-
return self.datas.get(user_id)
|
|
26
|
-
|
|
27
|
-
def clear_data(self, user_id: str):
|
|
28
|
-
self.datas.pop(user_id, None)
|
|
29
|
-
|
|
30
|
-
state_manager = StateManager()
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
rubigram/__init__.py,sha256=WotLkwsGnUkQC6XhJRtI_QNtUfOboG5k4VVcqwp_zFI,128
|
|
2
|
-
rubigram/client.py,sha256=3bug_ezjMmhrPt3CmjOwEELbpFzNsRvXZZPQE7SJf0w,3557
|
|
3
|
-
rubigram/filters.py,sha256=lB75_08wCz3iQqiV4QXm-dUomf2QqRG7q3b1PL5JDUQ,5174
|
|
4
|
-
rubigram/method.py,sha256=AcvVyx1H0ADHHu6mfb4UW2auSVkeq9VWLE584RIXn1w,14748
|
|
5
|
-
rubigram/network.py,sha256=B5y_n7CC7wdMkzNqKpUG9cC7Cq86R0QJCwcScExluvM,2299
|
|
6
|
-
rubigram/state.py,sha256=jz9vNZyoxnMJM4juHeFZGc-AEa5npPWLSmp6_wBFfOY,954
|
|
7
|
-
rubigram/types.py,sha256=KOoexWaeaElShNM4Pov6JJD9It704YJ_7-ZiSYNcIrE,14373
|
|
8
|
-
rubigramclient-1.4.1.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
rubigramclient-1.4.1.dist-info/METADATA,sha256=OsGqyYJg6pExZ9U9eGAntYMFmociYN25LFqF8qORD3Q,2035
|
|
10
|
-
rubigramclient-1.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
-
rubigramclient-1.4.1.dist-info/top_level.txt,sha256=Mhg5HfkL6rLec5sI4ClGmwoqYUANAZUz8sVa1sT_cas,9
|
|
12
|
-
rubigramclient-1.4.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|