RubigramClient 1.1.1__py3-none-any.whl → 1.3.0__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 +31 -30
- rubigram/filters.py +8 -8
- rubigram/types.py +433 -198
- rubigramclient-1.3.0.dist-info/METADATA +33 -0
- rubigramclient-1.3.0.dist-info/RECORD +9 -0
- rubigramclient-1.1.1.dist-info/METADATA +0 -24
- rubigramclient-1.1.1.dist-info/RECORD +0 -9
- {rubigramclient-1.1.1.dist-info → rubigramclient-1.3.0.dist-info}/WHEEL +0 -0
- {rubigramclient-1.1.1.dist-info → rubigramclient-1.3.0.dist-info}/licenses/LICENSE +0 -0
- {rubigramclient-1.1.1.dist-info → rubigramclient-1.3.0.dist-info}/top_level.txt +0 -0
rubigram/__init__.py
CHANGED
rubigram/client.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
from rubigram.types import
|
|
1
|
+
from rubigram.types import Update, MessageId, Keypad, Chat, Bot
|
|
2
2
|
from aiohttp import ClientSession, FormData, web
|
|
3
|
-
from typing import Literal
|
|
3
|
+
from typing import Literal, Optional
|
|
4
4
|
import aiofiles
|
|
5
5
|
|
|
6
6
|
|
|
@@ -27,24 +27,25 @@ class Client:
|
|
|
27
27
|
return decorator
|
|
28
28
|
|
|
29
29
|
async def update(self, data: dict):
|
|
30
|
-
|
|
30
|
+
event = Update.read(data["update"], self)
|
|
31
31
|
for handler in self.messages_handler:
|
|
32
|
-
await handler(self,
|
|
33
|
-
|
|
32
|
+
await handler(self, event)
|
|
33
|
+
|
|
34
34
|
|
|
35
35
|
async def get_me(self) -> "Bot":
|
|
36
36
|
response = await self.request("getMe", {})
|
|
37
|
-
return Bot(response["data"]["bot"])
|
|
37
|
+
return Bot.read(response["data"]["bot"])
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
async def get_chat(self, chat_id: str) -> "Chat":
|
|
41
41
|
response = await self.request("getChat", {"chat_id": chat_id})
|
|
42
|
-
return Chat(response["data"])
|
|
42
|
+
return Chat.read(response["data"]["chat"])
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
async def get_updates(self, limit: int = 1, offset_id: str = None):
|
|
45
|
+
async def get_updates(self, limit: int = 1, offset_id: str = None) -> list["Update"]:
|
|
46
46
|
response = await self.request("getUpdates", {"limit": limit, "offset_id": offset_id})
|
|
47
|
-
|
|
47
|
+
updates = [update for update in response["data"]["updates"]]
|
|
48
|
+
return [Update.read(update) for update in updates]
|
|
48
49
|
|
|
49
50
|
|
|
50
51
|
async def set_command(self, commands: list):
|
|
@@ -65,8 +66,8 @@ class Client:
|
|
|
65
66
|
self,
|
|
66
67
|
chat_id: str,
|
|
67
68
|
text: str,
|
|
68
|
-
chat_keypad = None,
|
|
69
|
-
inline_keypad = None,
|
|
69
|
+
chat_keypad : Optional[Keypad] = None,
|
|
70
|
+
inline_keypad: Optional[Keypad] = None,
|
|
70
71
|
chat_keypad_type: Literal["New", "Remove"] = None,
|
|
71
72
|
disable_notification: bool = None,
|
|
72
73
|
reply_to_message_id = None
|
|
@@ -74,14 +75,14 @@ class Client:
|
|
|
74
75
|
data = {
|
|
75
76
|
"chat_id": chat_id,
|
|
76
77
|
"text": text,
|
|
77
|
-
"chat_keypad": chat_keypad,
|
|
78
|
-
"inline_keypad": inline_keypad,
|
|
78
|
+
"chat_keypad": chat_keypad._dict() if chat_keypad else None,
|
|
79
|
+
"inline_keypad": inline_keypad._dict() if inline_keypad else None,
|
|
79
80
|
"chat_keypad_type": chat_keypad_type,
|
|
80
81
|
"disable_notification": disable_notification,
|
|
81
82
|
"reply_to_message_id": reply_to_message_id
|
|
82
83
|
}
|
|
83
84
|
response = await self.request("sendMessage", data)
|
|
84
|
-
return MessageId(response["data"])
|
|
85
|
+
return MessageId.read(response["data"])
|
|
85
86
|
|
|
86
87
|
|
|
87
88
|
async def send_poll(
|
|
@@ -89,8 +90,8 @@ class Client:
|
|
|
89
90
|
chat_id: str,
|
|
90
91
|
question: str,
|
|
91
92
|
options: list[str],
|
|
92
|
-
chat_keypad = None,
|
|
93
|
-
inline_keypad = None,
|
|
93
|
+
chat_keypad: Keypad = None,
|
|
94
|
+
inline_keypad: Keypad = None,
|
|
94
95
|
disable_notification: bool = False,
|
|
95
96
|
reply_to_message_id: str = None,
|
|
96
97
|
chat_keypad_type: Literal[None, "New", "Remove"] = None
|
|
@@ -106,7 +107,7 @@ class Client:
|
|
|
106
107
|
"chat_keypad_type": chat_keypad_type
|
|
107
108
|
}
|
|
108
109
|
response = await self.request("sendPoll", data)
|
|
109
|
-
return MessageId(response["data"])
|
|
110
|
+
return MessageId.read(response["data"])
|
|
110
111
|
|
|
111
112
|
|
|
112
113
|
async def send_location(
|
|
@@ -114,8 +115,8 @@ class Client:
|
|
|
114
115
|
chat_id: str,
|
|
115
116
|
latitude: str,
|
|
116
117
|
longitude: str,
|
|
117
|
-
chat_keypad = None,
|
|
118
|
-
inline_keypad = None,
|
|
118
|
+
chat_keypad: Keypad = None,
|
|
119
|
+
inline_keypad: Keypad = None,
|
|
119
120
|
disable_notification: bool = False,
|
|
120
121
|
reply_to_message_id: str = None,
|
|
121
122
|
chat_keypad_type: Literal[None, "New", "Remove"] = None
|
|
@@ -131,7 +132,7 @@ class Client:
|
|
|
131
132
|
"chat_keypad_type": chat_keypad_type
|
|
132
133
|
}
|
|
133
134
|
response = await self.request("sendLocation", data)
|
|
134
|
-
return MessageId(response["data"])
|
|
135
|
+
return MessageId.read(response["data"])
|
|
135
136
|
|
|
136
137
|
|
|
137
138
|
async def send_contact(
|
|
@@ -140,8 +141,8 @@ class Client:
|
|
|
140
141
|
first_name: str,
|
|
141
142
|
last_name: str,
|
|
142
143
|
phone_number: str,
|
|
143
|
-
chat_keypad = None,
|
|
144
|
-
inline_keypad = None,
|
|
144
|
+
chat_keypad: Keypad = None,
|
|
145
|
+
inline_keypad: Keypad = None,
|
|
145
146
|
disable_notification: bool = False,
|
|
146
147
|
reply_to_message_id: str = None,
|
|
147
148
|
chat_keypad_type: Literal[None, "New", "Remove"] = None
|
|
@@ -158,15 +159,15 @@ class Client:
|
|
|
158
159
|
"chat_keypad_type": chat_keypad_type
|
|
159
160
|
}
|
|
160
161
|
response = await self.request("sendContact", data)
|
|
161
|
-
return MessageId(response["data"])
|
|
162
|
+
return MessageId.read(response["data"])
|
|
162
163
|
|
|
163
164
|
|
|
164
165
|
async def send_sticker(
|
|
165
166
|
self,
|
|
166
167
|
chat_id: str,
|
|
167
168
|
sticker_id: str,
|
|
168
|
-
chat_keypad = None,
|
|
169
|
-
inline_keypad = None,
|
|
169
|
+
chat_keypad: Keypad = None,
|
|
170
|
+
inline_keypad: Keypad = None,
|
|
170
171
|
disable_notification: bool = False,
|
|
171
172
|
reply_to_message_id: str = None,
|
|
172
173
|
chat_keypad_type: Literal[None, "New", "Remove"] = None,
|
|
@@ -181,7 +182,7 @@ class Client:
|
|
|
181
182
|
"chat_keypad_type": chat_keypad_type
|
|
182
183
|
}
|
|
183
184
|
response = await self.request("sendSticker", data)
|
|
184
|
-
return MessageId(response["data"])
|
|
185
|
+
return MessageId.read(response["data"])
|
|
185
186
|
|
|
186
187
|
|
|
187
188
|
async def forward_message(
|
|
@@ -198,7 +199,7 @@ class Client:
|
|
|
198
199
|
"disable_notification": disable_notification
|
|
199
200
|
}
|
|
200
201
|
response = await self.request("forwardMessage", data)
|
|
201
|
-
return MessageId(response["data"])
|
|
202
|
+
return MessageId.read(response["data"])
|
|
202
203
|
|
|
203
204
|
|
|
204
205
|
async def edit_message_text(
|
|
@@ -215,7 +216,7 @@ class Client:
|
|
|
215
216
|
self,
|
|
216
217
|
chat_id: str,
|
|
217
218
|
message_id: str,
|
|
218
|
-
inline_keypad
|
|
219
|
+
inline_keypad: Keypad
|
|
219
220
|
) -> None:
|
|
220
221
|
data = {"chat_id": chat_id, "message_id": message_id, "inline_keypad": inline_keypad}
|
|
221
222
|
await self.request("editMessageKeypad", data)
|
|
@@ -224,7 +225,7 @@ class Client:
|
|
|
224
225
|
async def edit_chat_keypad(
|
|
225
226
|
self,
|
|
226
227
|
chat_id: str,
|
|
227
|
-
chat_keypad
|
|
228
|
+
chat_keypad: Keypad
|
|
228
229
|
) -> None:
|
|
229
230
|
data = {"chat_id": chat_id, "chat_keypad_type": "New", "chat_keypad": chat_keypad}
|
|
230
231
|
await self.request("editChatKeypad", data)
|
|
@@ -290,7 +291,7 @@ class Client:
|
|
|
290
291
|
"chat_keypad_type": chat_keypad_type,
|
|
291
292
|
}
|
|
292
293
|
response = await self.request("sendFile", data)
|
|
293
|
-
return MessageId(response["data"])
|
|
294
|
+
return MessageId.read(response["data"])
|
|
294
295
|
|
|
295
296
|
|
|
296
297
|
async def download_file(self, file_id: str, file_name: str):
|
rubigram/filters.py
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
from rubigram.types import
|
|
1
|
+
from rubigram.types import Update
|
|
2
2
|
from typing import Union
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class filter:
|
|
6
6
|
@staticmethod
|
|
7
7
|
def text():
|
|
8
|
-
def inner(update:
|
|
8
|
+
def inner(update: Update):
|
|
9
9
|
return update.new_message.text
|
|
10
10
|
return inner
|
|
11
11
|
|
|
12
12
|
@staticmethod
|
|
13
13
|
def private():
|
|
14
|
-
def inner(update:
|
|
14
|
+
def inner(update: Update):
|
|
15
15
|
return update.new_message.sender_type == "User"
|
|
16
16
|
return inner
|
|
17
17
|
|
|
18
18
|
@staticmethod
|
|
19
19
|
def command(cmd: Union[str, list[str]]):
|
|
20
|
-
def inner(update:
|
|
20
|
+
def inner(update: Update):
|
|
21
21
|
if not update.new_message.text:
|
|
22
22
|
return False
|
|
23
23
|
if not update.new_message.text.startswith("/"):
|
|
@@ -27,24 +27,24 @@ class filter:
|
|
|
27
27
|
|
|
28
28
|
@staticmethod
|
|
29
29
|
def text_filter(text: str):
|
|
30
|
-
def inner(update:
|
|
30
|
+
def inner(update: Update):
|
|
31
31
|
return update.new_message.text == text if update.new_message.text else False
|
|
32
32
|
return inner
|
|
33
33
|
|
|
34
34
|
@staticmethod
|
|
35
35
|
def chat(chat_id: str):
|
|
36
|
-
def inner(update:
|
|
36
|
+
def inner(update: Update):
|
|
37
37
|
return update.chat_id == chat_id
|
|
38
38
|
return inner
|
|
39
39
|
|
|
40
40
|
@staticmethod
|
|
41
41
|
def file():
|
|
42
|
-
def inner(update:
|
|
42
|
+
def inner(update: Update):
|
|
43
43
|
return update.new_message.file
|
|
44
44
|
return inner
|
|
45
45
|
|
|
46
46
|
@staticmethod
|
|
47
47
|
def button(id: str):
|
|
48
|
-
def inner(update:
|
|
48
|
+
def inner(update: Update):
|
|
49
49
|
return update.new_message.aux_data.button_id == id if update.new_message.aux_data else False
|
|
50
50
|
return inner
|
rubigram/types.py
CHANGED
|
@@ -1,235 +1,470 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Any, Dict, List, Literal, Optional
|
|
1
3
|
import rubigram
|
|
2
|
-
from typing import Literal
|
|
3
|
-
from json import dumps
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
self.from_sender_id: str = data.get("from_sender_id")
|
|
12
|
-
self.from_chat_id: str = data.get("from_chat_id")
|
|
7
|
+
@dataclass
|
|
8
|
+
class Location:
|
|
9
|
+
longitude: Optional[str] = None
|
|
10
|
+
latitude: Optional[str] = None
|
|
13
11
|
|
|
14
|
-
def _dict(self):
|
|
12
|
+
def _dict(self) -> Dict:
|
|
15
13
|
return {
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"from_sender_id": self.from_sender_id,
|
|
19
|
-
"from_chat_id": self.from_chat_id
|
|
14
|
+
"longitude": self.longitude,
|
|
15
|
+
"latitude": self.latitude
|
|
20
16
|
}
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def read(cls, data: dict[str, Any]) -> "Location":
|
|
20
|
+
return cls(
|
|
21
|
+
longitude = data.get("longitude"),
|
|
22
|
+
latitude = data.get("latitude"),
|
|
23
|
+
)
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def __init__(self, data: dict):
|
|
28
|
-
self.file_id: str = data["file_id"]
|
|
29
|
-
self.file_name: str = data.get("file_name")
|
|
30
|
-
self.size: int = data.get("size")
|
|
25
|
+
@dataclass
|
|
26
|
+
class ButtonSelectionItem:
|
|
27
|
+
text: Optional[str] = None
|
|
28
|
+
image_url: Optional[str] = None
|
|
29
|
+
type: Optional[Literal["TextOnly", "TextImgThu", "TextImgBig"]] = None
|
|
31
30
|
|
|
32
|
-
def _dict(self):
|
|
33
|
-
return {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
def _dict(self) -> Dict:
|
|
32
|
+
return {
|
|
33
|
+
"text": self.text,
|
|
34
|
+
"image_url": self.image_url,
|
|
35
|
+
"type": self.type
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class ButtonTextbox:
|
|
40
|
+
type_line: Optional[Literal["SingleLine", "MultiLine"]] = None
|
|
41
|
+
type_keypad: Optional[Literal["String", "Number"]] = None
|
|
42
|
+
place_holder: Optional[str] = None
|
|
43
|
+
title: Optional[str] = None
|
|
44
|
+
default_value: Optional[str] = None
|
|
37
45
|
|
|
46
|
+
def _dict(self) -> Dict:
|
|
47
|
+
return {
|
|
48
|
+
"type_line": self.type_line,
|
|
49
|
+
"type_keypad": self.type_keypad,
|
|
50
|
+
"place_holder": self.place_holder,
|
|
51
|
+
"title": self.title,
|
|
52
|
+
"default_value": self.default_value
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@dataclass
|
|
56
|
+
class ButtonLocation:
|
|
57
|
+
default_pointer_location: Optional[Location] = None
|
|
58
|
+
default_map_location: Optional[Location] = None
|
|
59
|
+
type: Optional[Literal["Picker", "View"]] = None
|
|
60
|
+
title: Optional[str] = None
|
|
61
|
+
location_image_url: Optional[str] = None
|
|
38
62
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
63
|
+
def _dict(self) -> Dict:
|
|
64
|
+
return {
|
|
65
|
+
"default_pointer_location": self.default_pointer_location._dict(),
|
|
66
|
+
"default_map_location": self.default_map_location._dict(),
|
|
67
|
+
"type": self.type,
|
|
68
|
+
"title": self.title,
|
|
69
|
+
"location_image_url": self.location_image_url
|
|
70
|
+
}
|
|
43
71
|
|
|
44
|
-
|
|
45
|
-
|
|
72
|
+
@dataclass
|
|
73
|
+
class ButtonStringPicker:
|
|
74
|
+
items: Optional[List[str]] = None
|
|
75
|
+
default_value: Optional[str] = None
|
|
76
|
+
title: Optional[str] = None
|
|
46
77
|
|
|
47
|
-
def
|
|
48
|
-
return
|
|
49
|
-
|
|
78
|
+
def _dict(self) -> Dict:
|
|
79
|
+
return {
|
|
80
|
+
"items": self.items,
|
|
81
|
+
"default_value": self.default_value,
|
|
82
|
+
"title": self.title,
|
|
83
|
+
}
|
|
50
84
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
85
|
+
@dataclass
|
|
86
|
+
class ButtonNumberPicker:
|
|
87
|
+
min_value: Optional[str] = None
|
|
88
|
+
max_value: Optional[str] = None
|
|
89
|
+
default_value: Optional[str] = None
|
|
90
|
+
title: Optional[str] = None
|
|
55
91
|
|
|
56
|
-
def _dict(self):
|
|
57
|
-
return {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class MessageId:
|
|
64
|
-
def __init__(self, data: dict):
|
|
65
|
-
self.message_id = data["message_id"]
|
|
92
|
+
def _dict(self) -> Dict:
|
|
93
|
+
return {
|
|
94
|
+
"min_value": self.min_value,
|
|
95
|
+
"max_value": self.max_value,
|
|
96
|
+
"default_value": self.default_value,
|
|
97
|
+
"title": self.title
|
|
98
|
+
}
|
|
66
99
|
|
|
67
|
-
|
|
68
|
-
|
|
100
|
+
@dataclass
|
|
101
|
+
class ButtonCalendar:
|
|
102
|
+
default_value: Optional[str] = None
|
|
103
|
+
type: Optional[Literal["DatePersian", "DateGregorian"]] = None
|
|
104
|
+
min_year: Optional[str] = None
|
|
105
|
+
max_year: Optional[str] = None
|
|
106
|
+
title: Optional[str] = None
|
|
69
107
|
|
|
70
|
-
def
|
|
71
|
-
return dumps(self._dict(), indent=4, ensure_ascii=False)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
class UpdateMessage:
|
|
75
|
-
def __init__(self, data: dict):
|
|
76
|
-
self.message_id: str = data["message_id"]
|
|
77
|
-
self.text: str = data["text"]
|
|
78
|
-
self.time: str = data["time"]
|
|
79
|
-
self.is_edited: bool = data["is_edited"]
|
|
80
|
-
self.sender_type: str = data["sender_type"]
|
|
81
|
-
self.sender_id: str = data["sender_id"]
|
|
82
|
-
|
|
83
|
-
def _dict(self):
|
|
108
|
+
def _dict(self) -> Dict:
|
|
84
109
|
return {
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"sender_id": self.sender_id
|
|
110
|
+
"default_value": self.default_value,
|
|
111
|
+
"type": self.type,
|
|
112
|
+
"min_year": self.min_year,
|
|
113
|
+
"max_year": self.max_year,
|
|
114
|
+
"title": self.title
|
|
91
115
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
self.text: str = data.get("text")
|
|
105
|
-
self.forwarded_from: ForwardFrom = ForwardFrom(data["forwarded_from"]) if data.get("forwarded_from") else None
|
|
106
|
-
self.file: File = File(data["file"]) if data.get("file") else None
|
|
107
|
-
self.location: Location = Location(data["location"]) if data.get("location") else None
|
|
108
|
-
self.aux_data: AuxData = AuxData(data["aux_data"]) if data.get("aux_data") else None
|
|
109
|
-
|
|
110
|
-
def _dict(self):
|
|
116
|
+
|
|
117
|
+
@dataclass
|
|
118
|
+
class ButtonSelection:
|
|
119
|
+
selection_id: Optional[str] = None
|
|
120
|
+
search_type: Optional[str] = None
|
|
121
|
+
get_type: Optional[str] = None
|
|
122
|
+
items: Optional[ButtonSelectionItem] = None
|
|
123
|
+
is_multi_selection: Optional[bool] = None
|
|
124
|
+
columns_count: Optional[str] = None
|
|
125
|
+
title: Optional[str] = None
|
|
126
|
+
|
|
127
|
+
def _dict(self) -> Dict:
|
|
111
128
|
return {
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
"file": self.file._dict() if self.file else None,
|
|
120
|
-
"location": self.location._dict() if self.location else None,
|
|
121
|
-
"aux_data": self.aux_data._dict() if self.aux_data else None
|
|
129
|
+
"selection_id": self.selection_id,
|
|
130
|
+
"search_type": self.search_type,
|
|
131
|
+
"get_type": self.get_type,
|
|
132
|
+
"items": self.items._dict() if self.items else None,
|
|
133
|
+
"is_multi_selection": self.is_multi_selection,
|
|
134
|
+
"columns_count": self.columns_count,
|
|
135
|
+
"title": self.title
|
|
122
136
|
}
|
|
123
|
-
|
|
124
|
-
def __str__(self):
|
|
125
|
-
return dumps(self._dict(), indent=4, ensure_ascii=False)
|
|
126
137
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@dataclass
|
|
141
|
+
class Button:
|
|
142
|
+
id: Optional[str] = None
|
|
143
|
+
type: Literal[
|
|
144
|
+
"Simple", "Selection", "Calendar", "NumberPicker", "StringPicker", "Location", "Payment",
|
|
145
|
+
"CameraImage", "CameraVideo", "GalleryImage", "GalleryVideo", "File", "Audio", "RecordAudio",
|
|
146
|
+
"MyPhoneNumber", "MyLocation", "Textbox", "Link", "AskMyPhoneNumber", "AskLocation", "Barcode"
|
|
147
|
+
] = "Simple"
|
|
148
|
+
button_text: Optional[str] = None
|
|
149
|
+
button_selection: Optional[ButtonSelection] = None
|
|
150
|
+
button_calendar: Optional[ButtonCalendar] = None
|
|
151
|
+
button_number_picker: Optional[ButtonNumberPicker] = None
|
|
152
|
+
button_string_picker: Optional[ButtonStringPicker] = None
|
|
153
|
+
button_location: Optional[ButtonLocation] = None
|
|
154
|
+
button_textbox: Optional[ButtonTextbox] = None
|
|
155
|
+
|
|
156
|
+
def _dict(self) -> Dict:
|
|
138
157
|
return {
|
|
139
|
-
"
|
|
140
|
-
"
|
|
141
|
-
"
|
|
142
|
-
"
|
|
143
|
-
"
|
|
144
|
-
"
|
|
158
|
+
"id": self.id,
|
|
159
|
+
"type": self.type,
|
|
160
|
+
"button_text": self.button_text,
|
|
161
|
+
"button_selection": self.button_selection._dict() if self.button_selection else None,
|
|
162
|
+
"button_calendar": self.button_calendar._dict() if self.button_calendar else None,
|
|
163
|
+
"button_number_picker": self.button_number_picker._dict() if self.button_number_picker else None,
|
|
164
|
+
"button_string_picker": self.button_string_picker._dict() if self.button_string_picker else None,
|
|
165
|
+
"button_location": self.button_location._dict() if self.button_location else None,
|
|
166
|
+
"button_textbox": self.button_textbox._dict() if self.button_textbox else None
|
|
145
167
|
}
|
|
146
|
-
|
|
147
|
-
def __str__(self):
|
|
148
|
-
return dumps(self._dict(), indent=4, ensure_ascii=False)
|
|
149
168
|
|
|
169
|
+
@dataclass
|
|
170
|
+
class KeypadRow:
|
|
171
|
+
buttons: List[Button]
|
|
172
|
+
|
|
173
|
+
def _dict(self) -> Dict:
|
|
174
|
+
return {
|
|
175
|
+
"buttons": [button._dict() for button in self.buttons]
|
|
176
|
+
}
|
|
150
177
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
self.description: str = data["description"]
|
|
159
|
-
self.avatar: File = File(data["avatar"]) if data.get("avatar") else None
|
|
160
|
-
|
|
161
|
-
def _dict(self):
|
|
178
|
+
@dataclass
|
|
179
|
+
class Keypad:
|
|
180
|
+
rows: List[KeypadRow]
|
|
181
|
+
resize_keyboard: bool = True
|
|
182
|
+
on_time_keyboard: bool = False
|
|
183
|
+
|
|
184
|
+
def _dict(self) -> Dict:
|
|
162
185
|
return {
|
|
163
|
-
"
|
|
164
|
-
"
|
|
165
|
-
"
|
|
166
|
-
"start_message": self.start_message,
|
|
167
|
-
"share_url": self.share_url,
|
|
168
|
-
"description": self.description,
|
|
169
|
-
"avatar": self.avatar._dict() if self.avatar else None
|
|
186
|
+
"rows": [row._dict() for row in self.rows],
|
|
187
|
+
"resize_keyboard": self.resize_keyboard,
|
|
188
|
+
"one_time_keyboard": self.on_time_keyboard
|
|
170
189
|
}
|
|
190
|
+
|
|
191
|
+
@dataclass
|
|
192
|
+
class MessageId:
|
|
193
|
+
client: Optional["rubigram.Client"] = None
|
|
194
|
+
message_id: Optional[str] = None
|
|
195
|
+
file_id: Optional[str] = None
|
|
171
196
|
|
|
172
|
-
|
|
173
|
-
|
|
197
|
+
@classmethod
|
|
198
|
+
def read(cls, data: Dict[str, Any]) -> "MessageId":
|
|
199
|
+
return cls(
|
|
200
|
+
message_id = data.get("message_id"),
|
|
201
|
+
file_id = data.get("file_id")
|
|
202
|
+
)
|
|
174
203
|
|
|
204
|
+
@dataclass
|
|
205
|
+
class PollStatus:
|
|
206
|
+
state: Optional[Literal["Open", "Closed"]] = None
|
|
207
|
+
selection_index: Optional[int] = None
|
|
208
|
+
percent_vote_options: Optional[List[int]] = None
|
|
209
|
+
total_vote: Optional[int] = None
|
|
210
|
+
show_total_votes: Optional[bool] = None
|
|
211
|
+
|
|
212
|
+
@classmethod
|
|
213
|
+
def read(cls, data: Dict[str, Any]) -> "PollStatus":
|
|
214
|
+
return cls(
|
|
215
|
+
state = data.get("state"),
|
|
216
|
+
selection_index = data.get("selection_index"),
|
|
217
|
+
percent_vote_options = data.get("percent_vote_options"),
|
|
218
|
+
total_vote = data.get("total_vote"),
|
|
219
|
+
show_total_votes = data.get("show_total_votes"),
|
|
220
|
+
)
|
|
175
221
|
|
|
222
|
+
@dataclass
|
|
223
|
+
class File:
|
|
224
|
+
file_id: Optional[str] = None
|
|
225
|
+
file_name: Optional[str] = None
|
|
226
|
+
size: Optional[str] = None
|
|
227
|
+
|
|
228
|
+
@classmethod
|
|
229
|
+
def read(cls, data: dict[str, Any]) -> "File":
|
|
230
|
+
return cls(
|
|
231
|
+
file_id = data.get("file_id"),
|
|
232
|
+
file_name = data.get("file_name"),
|
|
233
|
+
size = data.get("size"),
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
@dataclass
|
|
237
|
+
class LiveLocation:
|
|
238
|
+
start_time: Optional[str] = None
|
|
239
|
+
live_period: Optional[int] = None
|
|
240
|
+
current_location: Optional[Location] = None
|
|
241
|
+
user_id: Optional[str] = None
|
|
242
|
+
status: Optional[Literal["Stopped", "Live"]] = None
|
|
243
|
+
last_update_time: Optional[str] = None
|
|
244
|
+
|
|
245
|
+
@classmethod
|
|
246
|
+
def read(cls, data: dict[str, Any]) -> "LiveLocation":
|
|
247
|
+
return cls(
|
|
248
|
+
start_time = data.get("start_time"),
|
|
249
|
+
live_period = data.get("live_period"),
|
|
250
|
+
current_location = Location.read(data.get("current_location")) if "current_location" in data else None,
|
|
251
|
+
user_id = data.get("user_id"),
|
|
252
|
+
status = data.get("status"),
|
|
253
|
+
last_update_time = data.get("last_update_time")
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
@dataclass
|
|
257
|
+
class Poll:
|
|
258
|
+
question: Optional[str] = None
|
|
259
|
+
options: Optional[List[str]] = None
|
|
260
|
+
poll_status: Optional[PollStatus] = None
|
|
261
|
+
|
|
262
|
+
@classmethod
|
|
263
|
+
def read(cls, data: dict[str, Any]) -> "Poll":
|
|
264
|
+
return cls(
|
|
265
|
+
question = data.get("question"),
|
|
266
|
+
options = data.get("options"),
|
|
267
|
+
poll_status = PollStatus.read(data.get("poll_status")) if "poll_status" in data else None
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
@dataclass
|
|
271
|
+
class ContactMessage:
|
|
272
|
+
phone_number: Optional[str] = None
|
|
273
|
+
first_name: Optional[File] = None
|
|
274
|
+
last_name: Optional[str] = None
|
|
275
|
+
|
|
276
|
+
@classmethod
|
|
277
|
+
def read(cls, data: dict[str, Any]) -> "ContactMessage":
|
|
278
|
+
return cls(
|
|
279
|
+
phone_number = data.get("phone_number"),
|
|
280
|
+
first_name = File.read(data.get("first_name")) if "first_name" in data else None,
|
|
281
|
+
last_name = data.get("last_name")
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
@dataclass
|
|
285
|
+
class Sticker:
|
|
286
|
+
sticker_id: Optional[str] = None
|
|
287
|
+
file: Optional[File] = None
|
|
288
|
+
emoji_character: Optional[str] = None
|
|
289
|
+
|
|
290
|
+
@classmethod
|
|
291
|
+
def read(cls, data: dict[str, Any]) -> "Sticker":
|
|
292
|
+
return cls(
|
|
293
|
+
sticker_id = data.get("sticker_id"),
|
|
294
|
+
file = File.read(data.get("file")) if "file" in data else None,
|
|
295
|
+
emoji_character = data.get("emoji_character")
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
@dataclass
|
|
299
|
+
class ForwardedFrom:
|
|
300
|
+
type_from: Optional[Literal["User", "Channel", "Bot"]] = None
|
|
301
|
+
message_id: Optional[str] = None
|
|
302
|
+
from_chat_id: Optional[str] = None
|
|
303
|
+
from_sender_id: Optional[str] = None
|
|
304
|
+
|
|
305
|
+
@classmethod
|
|
306
|
+
def read(cls, data: dict[str, Any]) -> "ForwardedFrom":
|
|
307
|
+
return cls(
|
|
308
|
+
type_from = data.get("type_from"),
|
|
309
|
+
message_id = data.get("message_id"),
|
|
310
|
+
from_chat_id = data.get("from_chat_id"),
|
|
311
|
+
from_sender_id = data.get("from_sender_id")
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
@dataclass
|
|
315
|
+
class AuxData:
|
|
316
|
+
start_id: Optional[str] = None
|
|
317
|
+
button_id: Optional[str] = None
|
|
318
|
+
|
|
319
|
+
@classmethod
|
|
320
|
+
def read(cls, data: Dict[str, Any]) -> "AuxData":
|
|
321
|
+
return cls(
|
|
322
|
+
start_id = data.get("start_id"),
|
|
323
|
+
button_id = data.get("button_id")
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
@dataclass
|
|
327
|
+
class PaymentStatus:
|
|
328
|
+
payment_id: Optional[str] = None
|
|
329
|
+
status: Optional[Literal["Paid", "NotPaid"]] = None
|
|
330
|
+
|
|
331
|
+
@classmethod
|
|
332
|
+
def read(cls, data: Dict[str, Any]) -> "PaymentStatus":
|
|
333
|
+
return cls(
|
|
334
|
+
payment_id = data.get("payment_id"),
|
|
335
|
+
status = data.get("status")
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
@dataclass
|
|
176
339
|
class Chat:
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
self.username: str = data.get("username")
|
|
185
|
-
|
|
186
|
-
def _dict(self):
|
|
187
|
-
return {
|
|
188
|
-
"chat_id": self.chat_id,
|
|
189
|
-
"chat_type": self.chat_type,
|
|
190
|
-
"user_id": self.user_id,
|
|
191
|
-
"first_name": self.first_name,
|
|
192
|
-
"last_name": self.last_name,
|
|
193
|
-
"title" : self.title,
|
|
194
|
-
"username": self.username
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
def __str__(self):
|
|
198
|
-
return dumps(self._dict(), indent=4, ensure_ascii=False)
|
|
340
|
+
chat_id: Optional[str] = None
|
|
341
|
+
chat_type: Optional[Literal["User", "Bot", "Group", "Channel"]] = None
|
|
342
|
+
user_id: Optional[str] = None
|
|
343
|
+
first_name: Optional[str] = None
|
|
344
|
+
last_name: Optional[str] = None
|
|
345
|
+
title: Optional[str] = None
|
|
346
|
+
username: Optional[str] = None
|
|
199
347
|
|
|
348
|
+
@classmethod
|
|
349
|
+
def read(cls, data: Dict[str, Any]) -> "Chat":
|
|
350
|
+
return cls(
|
|
351
|
+
chat_id = data.get("chat_id"),
|
|
352
|
+
chat_type = data.get("chat_type"),
|
|
353
|
+
user_id = data.get("user_id"),
|
|
354
|
+
first_name = data.get("first_name"),
|
|
355
|
+
last_name = data.get("last_name"),
|
|
356
|
+
title = data.get("title"),
|
|
357
|
+
username = data.get("username")
|
|
358
|
+
)
|
|
200
359
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
"
|
|
215
|
-
|
|
216
|
-
"
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
360
|
+
@dataclass
|
|
361
|
+
class Bot:
|
|
362
|
+
bot_id: Optional[str] = None
|
|
363
|
+
bot_title: Optional[str] = None
|
|
364
|
+
avatar: Optional[File] = None
|
|
365
|
+
description: Optional[str] = None
|
|
366
|
+
username: Optional[str] = None
|
|
367
|
+
start_message: Optional[str] = None
|
|
368
|
+
share_url: Optional[str] = None
|
|
369
|
+
|
|
370
|
+
@classmethod
|
|
371
|
+
def read(cls, data: Dict[str, Any]) -> "Bot":
|
|
372
|
+
return cls(
|
|
373
|
+
bot_id = data.get("bot_id"),
|
|
374
|
+
bot_title = data.get("bot_title"),
|
|
375
|
+
avatar = File.read(data.get("avatar")) if data.get("avatar") else None,
|
|
376
|
+
description = data.get("description"),
|
|
377
|
+
username = data.get("username"),
|
|
378
|
+
start_message = data.get("start_message"),
|
|
379
|
+
share_url = data.get("share_url")
|
|
380
|
+
)
|
|
222
381
|
|
|
223
|
-
|
|
224
|
-
|
|
382
|
+
@dataclass
|
|
383
|
+
class InlineMessage:
|
|
384
|
+
sender_id: Optional[str] = None
|
|
385
|
+
text: Optional[str] = None
|
|
386
|
+
message_id: Optional[str] = None
|
|
387
|
+
chat_id: Optional[str] = None
|
|
388
|
+
file: Optional[File] = None
|
|
389
|
+
location: Optional[Location] = None
|
|
390
|
+
aux_data: Optional[AuxData] = None
|
|
225
391
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
392
|
+
@classmethod
|
|
393
|
+
def read(cls, data: Dict[str, Any]) -> "InlineMessage":
|
|
394
|
+
return cls(
|
|
395
|
+
sender_id = data.get("sender_id"),
|
|
396
|
+
text = data.get("text"),
|
|
397
|
+
message_id = data.get("message_id"),
|
|
398
|
+
chat_id = data.get("chat_id"),
|
|
399
|
+
file = File.read(data.get("file")) if data.get("file") else None,
|
|
400
|
+
location = Location.read(data.get("location")) if data.get("location") else None,
|
|
401
|
+
aux_data = AuxData.read(data.get("aux_data")) if data.get("aux_data") else None
|
|
402
|
+
)
|
|
233
403
|
|
|
234
|
-
|
|
235
|
-
|
|
404
|
+
@dataclass
|
|
405
|
+
class Message:
|
|
406
|
+
message_id: Optional[str] = None
|
|
407
|
+
text: Optional[str] = None
|
|
408
|
+
time: Optional[str] = None
|
|
409
|
+
is_edited: Optional[bool] = None
|
|
410
|
+
sender_type: Optional[Literal["User", "Bot"]] = None
|
|
411
|
+
sender_id: Optional[str] = None
|
|
412
|
+
aux_data: Optional[AuxData] = None
|
|
413
|
+
file: Optional[File] = None
|
|
414
|
+
reply_to_message_id: Optional[str] = None
|
|
415
|
+
forwarded_from: Optional[ForwardedFrom] = None
|
|
416
|
+
forwarded_no_link: Optional[str] = None
|
|
417
|
+
location: Optional[Location] = None
|
|
418
|
+
sticker: Optional[Sticker] = None
|
|
419
|
+
contact_message: Optional[ContactMessage] = None
|
|
420
|
+
poll: Optional[Poll] = None
|
|
421
|
+
live_location: Optional[LiveLocation] = None
|
|
422
|
+
|
|
423
|
+
@classmethod
|
|
424
|
+
def read(cls, data: Dict[str, Any]) -> "Message":
|
|
425
|
+
return cls(
|
|
426
|
+
message_id = data["message_id"],
|
|
427
|
+
text = data.get("text"),
|
|
428
|
+
time = data["time"],
|
|
429
|
+
is_edited = data["is_edited"],
|
|
430
|
+
sender_type = data["sender_type"],
|
|
431
|
+
sender_id = data["sender_id"],
|
|
432
|
+
aux_data = AuxData.read(data["aux_data"]) if "aux_data" in data else None,
|
|
433
|
+
file = File.read(data["file"]) if "file" in data else None,
|
|
434
|
+
reply_to_message_id = data.get("reply_to_message_id"),
|
|
435
|
+
forwarded_from = ForwardedFrom.read(data["forwarded_from"]) if "forwarded_from" in data else None,
|
|
436
|
+
forwarded_no_link = data.get("forwarded_no_link"),
|
|
437
|
+
location = Location.read(data["location"]) if "location" in data else None,
|
|
438
|
+
sticker = Sticker.read(data["sticker"]) if "sticker" in data else None,
|
|
439
|
+
contact_message = ContactMessage.read(data["contact_message"]) if "contact_message" in data else None,
|
|
440
|
+
poll = Poll.read(data["poll"]) if "poll" in data else None,
|
|
441
|
+
live_location = LiveLocation.read(data["live_location"]) if "live_location" in data else None
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
@dataclass
|
|
445
|
+
class Update:
|
|
446
|
+
client: Optional["rubigram.Client"] = None
|
|
447
|
+
type: Optional[Literal["NewMessage", "UpdatedMessage", "RemovedMessage", "StartedBot", "StoppedBot", "UpdatedPayment"]] = None
|
|
448
|
+
chat_id: Optional[str] = None
|
|
449
|
+
removed_message_id: Optional[str] = None
|
|
450
|
+
new_message: Optional[Message] = None
|
|
451
|
+
updated_message: Optional[Message] = None
|
|
452
|
+
updated_payment: Optional[PaymentStatus] = None
|
|
453
|
+
|
|
454
|
+
@classmethod
|
|
455
|
+
def read(cls, data: Dict[str, Any], client: Optional["rubigram.Client"] = None) -> "Update":
|
|
456
|
+
return cls(
|
|
457
|
+
client = client,
|
|
458
|
+
type = data["type"],
|
|
459
|
+
chat_id = data["chat_id"],
|
|
460
|
+
removed_message_id = data.get("removed_message_id"),
|
|
461
|
+
new_message = Message.read(data["new_message"]),
|
|
462
|
+
updated_message = Message.read(data["updated_message"]) if "updated_message" in data else None,
|
|
463
|
+
updated_payment = PaymentStatus.read(data["updated_payment"]) if "updated_payment" in data else None
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
async def reply_text(self, text: str) -> "MessageId":
|
|
467
|
+
return await self.client.send_message(self.chat_id, text, reply_to_message_id=self.new_message.message_id)
|
|
468
|
+
|
|
469
|
+
async def reply_file(self, path: str, file_name: str, type: Literal["File", "Image", "Voice", "Music", "Gif", "Video"] = "File") -> "MessageId":
|
|
470
|
+
return await self.client.send_file(self.chat_id, path, file_name, type, reply_to_message_id=self.new_message.message_id)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: RubigramClient
|
|
3
|
+
Version: 1.3.0
|
|
4
|
+
Summary: A simple and flexible Python library for building advanced Rubika bots with powerful message handling, inline buttons, and custom filters.
|
|
5
|
+
Author-email: Javad RZ <Javad.Py1385@gmail.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.7
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
# Rubigram
|
|
15
|
+
A lightweight Python library to build Rubika bots easily.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
```bash
|
|
19
|
+
pip install RubigramClient
|
|
20
|
+
```
|
|
21
|
+
## Example
|
|
22
|
+
```python
|
|
23
|
+
from rubigram import Client, filters
|
|
24
|
+
from rubigram.types import Update
|
|
25
|
+
|
|
26
|
+
bot = Client("your_bot_token")
|
|
27
|
+
|
|
28
|
+
@bot.on_message(filters.command("start"))
|
|
29
|
+
async def start_handler(client, message: Update):
|
|
30
|
+
await message.reply("Hi, WELCOME TO RUBIGRAM")
|
|
31
|
+
|
|
32
|
+
bot.run()
|
|
33
|
+
```
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
rubigram/__init__.py,sha256=K1WXGcBx9-1cLmImtnruqFk91nb_6XuhY_Ud0KS_IUk,55
|
|
2
|
+
rubigram/client.py,sha256=pvg-lokbQk6HAWlId578A9PugwgzEcAEsOGfHle-SiI,11578
|
|
3
|
+
rubigram/filters.py,sha256=HuW_Rscb02TK3Qm7jKVyvy-83FP-plIjTLTccypVniw,1468
|
|
4
|
+
rubigram/types.py,sha256=GIGvTGdDURuwJ3oHPvRR7B8oJ3V1f8MDaMAqjvOOO-0,16813
|
|
5
|
+
rubigramclient-1.3.0.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
rubigramclient-1.3.0.dist-info/METADATA,sha256=CqCq-HsdvgeOZf2YzpHWRArfmYAgzV8JRAQXblVOfTY,953
|
|
7
|
+
rubigramclient-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
+
rubigramclient-1.3.0.dist-info/top_level.txt,sha256=Mhg5HfkL6rLec5sI4ClGmwoqYUANAZUz8sVa1sT_cas,9
|
|
9
|
+
rubigramclient-1.3.0.dist-info/RECORD,,
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: RubigramClient
|
|
3
|
-
Version: 1.1.1
|
|
4
|
-
Summary: A Python library for connect to Rubika API
|
|
5
|
-
Author-email: Javad RJ <Javad.Py1385@gmail.com>
|
|
6
|
-
Requires-Python: >=3.7
|
|
7
|
-
Description-Content-Type: text/markdown
|
|
8
|
-
License-File: LICENSE
|
|
9
|
-
Dynamic: license-file
|
|
10
|
-
|
|
11
|
-
Rubigram
|
|
12
|
-
|
|
13
|
-
```python
|
|
14
|
-
from rubigram import Client, filter
|
|
15
|
-
from rubigram.types import Message
|
|
16
|
-
|
|
17
|
-
client = Client("Your_Bot_Token")
|
|
18
|
-
|
|
19
|
-
@bot.on_message(filter.command("start"))
|
|
20
|
-
async def start(client: Client, message: Message):
|
|
21
|
-
chat_id = message.chat_id
|
|
22
|
-
await message.reply("Hi, {}".format(chat_id))
|
|
23
|
-
|
|
24
|
-
client.run()
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
rubigram/__init__.py,sha256=LEWQ0sqQw_IrVicsh_GtKVTG2LRQoNCSfAJw0p4JVaM,76
|
|
2
|
-
rubigram/client.py,sha256=FkDzv3FdRb459gGCqn18VZzydzikNacvyBBP2P29BKg,11641
|
|
3
|
-
rubigram/filters.py,sha256=qY_jOUC_JSAnJ8GbPZ7h1ZRPt3t9DwokEUVA2-M20UA,1476
|
|
4
|
-
rubigram/types.py,sha256=JbNwZLtoY4iUapsfw7XexL8RrifxzfwrajI1ut5O2wc,8580
|
|
5
|
-
rubigramclient-1.1.1.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
rubigramclient-1.1.1.dist-info/METADATA,sha256=aD2B0Hb8GFpFZioS_0XpDnIQZCh-OGK6MeSVfHLJoJw,603
|
|
7
|
-
rubigramclient-1.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
-
rubigramclient-1.1.1.dist-info/top_level.txt,sha256=Mhg5HfkL6rLec5sI4ClGmwoqYUANAZUz8sVa1sT_cas,9
|
|
9
|
-
rubigramclient-1.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|