RubigramClient 1.3.3__py3-none-any.whl → 1.3.4__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 CHANGED
@@ -1,2 +1,4 @@
1
1
  from .client import Client
2
- from .filters import filter
2
+ from .method import Method
3
+ from .network import NetWork
4
+ from . import filters
rubigram/client.py CHANGED
@@ -1,21 +1,12 @@
1
- from rubigram.types import Update, MessageId, InlineMessage, Keypad, Chat, Bot
2
- from aiohttp import ClientSession, FormData, web
3
- from typing import Literal, Optional
4
- import aiofiles
1
+ from rubigram.types import Update, InlineMessage
2
+ from rubigram.method import Method
3
+ from aiohttp import web
5
4
 
6
-
7
- class Client:
5
+ class Client(Method):
8
6
  def __init__(self, token: str):
9
- self.token = token
10
7
  self.messages_handler = []
11
- self.api = f"https://botapi.rubika.ir/v3/{self.token}"
12
-
13
- async def request(self, method: str, data: dict):
14
- async with ClientSession() as session:
15
- async with session.post(f"{self.api}/{method}", json=data) as response:
16
- response.raise_for_status()
17
- return await response.json()
18
-
8
+ super().__init__(token)
9
+
19
10
  def on_message(self, *filters):
20
11
  def decorator(func):
21
12
  async def wrapped(client, update):
@@ -26,283 +17,9 @@ class Client:
26
17
  return decorator
27
18
 
28
19
  async def update(self, data: dict):
29
- event = Update.read(data["update"], self) if data.get("update") else InlineMessage.read(data["inline_message"])
20
+ event = Update.read(data["update"]) if data.get("update") else InlineMessage.read(data["inline_message"])
30
21
  for handler in self.messages_handler:
31
22
  await handler(self, event)
32
-
33
-
34
- async def get_me(self) -> "Bot":
35
- response = await self.request("getMe", {})
36
- return Bot.read(response["data"]["bot"])
37
-
38
-
39
- async def get_chat(self, chat_id: str) -> "Chat":
40
- response = await self.request("getChat", {"chat_id": chat_id})
41
- return Chat.read(response["data"]["chat"])
42
-
43
-
44
- async def get_updates(self, limit: int = 1, offset_id: str = None) -> list["Update"]:
45
- response = await self.request("getUpdates", {"limit": limit, "offset_id": offset_id})
46
- updates = [update for update in response["data"]["updates"]]
47
- return [Update.read(update) for update in updates]
48
-
49
-
50
- async def set_command(self, commands: list):
51
- response = await self.request("setCommands", {"bot_commands": commands})
52
- return response
53
-
54
-
55
- async def update_bot_endpoint(
56
- self,
57
- url: str,
58
- type: Literal["ReceiveUpdate", "ReceiveInlineMessage", "ReceiveQuery", "GetSelectionItem", "SearchSelectionItems"]
59
- ):
60
- response = await self.request("updateBotEndpoints", {"url": url, "type": type})
61
- return response
62
-
63
-
64
- async def send_message(
65
- self,
66
- chat_id: str,
67
- text: str,
68
- chat_keypad : Optional[Keypad] = None,
69
- inline_keypad: Optional[Keypad] = None,
70
- chat_keypad_type: Literal["New", "Remove"] = None,
71
- disable_notification: bool = None,
72
- reply_to_message_id = None
73
- ) -> "MessageId":
74
- data = {
75
- "chat_id": chat_id,
76
- "text": text,
77
- "chat_keypad": chat_keypad._dict() if chat_keypad else None,
78
- "inline_keypad": inline_keypad._dict() if inline_keypad else None,
79
- "chat_keypad_type": chat_keypad_type,
80
- "disable_notification": disable_notification,
81
- "reply_to_message_id": reply_to_message_id
82
- }
83
- response = await self.request("sendMessage", data)
84
- return MessageId.read(response["data"])
85
-
86
-
87
- async def send_poll(
88
- self,
89
- chat_id: str,
90
- question: str,
91
- options: list[str],
92
- chat_keypad: Keypad = None,
93
- inline_keypad: Keypad = None,
94
- disable_notification: bool = False,
95
- reply_to_message_id: str = None,
96
- chat_keypad_type: Literal[None, "New", "Remove"] = None
97
- ) -> "MessageId":
98
- data = {
99
- "chat_id": chat_id,
100
- "question": question,
101
- "options": options,
102
- "chat_keypad": chat_keypad,
103
- "inline_keypad": inline_keypad,
104
- "disable_notification": disable_notification,
105
- "reply_to_message_id": reply_to_message_id,
106
- "chat_keypad_type": chat_keypad_type
107
- }
108
- response = await self.request("sendPoll", data)
109
- return MessageId.read(response["data"])
110
-
111
-
112
- async def send_location(
113
- self,
114
- chat_id: str,
115
- latitude: str,
116
- longitude: str,
117
- chat_keypad: Keypad = None,
118
- inline_keypad: Keypad = None,
119
- disable_notification: bool = False,
120
- reply_to_message_id: str = None,
121
- chat_keypad_type: Literal[None, "New", "Remove"] = None
122
- ) -> "MessageId":
123
- data = {
124
- "chat_id": chat_id,
125
- "latitude": latitude,
126
- "longitude": longitude,
127
- "chat_keypad": chat_keypad,
128
- "inline_keypad": inline_keypad,
129
- "disable_notification": disable_notification,
130
- "reply_to_message_id": reply_to_message_id,
131
- "chat_keypad_type": chat_keypad_type
132
- }
133
- response = await self.request("sendLocation", data)
134
- return MessageId.read(response["data"])
135
-
136
-
137
- async def send_contact(
138
- self,
139
- chat_id: str,
140
- first_name: str,
141
- last_name: str,
142
- phone_number: str,
143
- chat_keypad: Keypad = None,
144
- inline_keypad: Keypad = None,
145
- disable_notification: bool = False,
146
- reply_to_message_id: str = None,
147
- chat_keypad_type: Literal[None, "New", "Remove"] = None
148
- ) -> "MessageId":
149
- data = {
150
- "chat_id": chat_id,
151
- "first_name": first_name,
152
- "last_name": last_name,
153
- "phone_number": phone_number,
154
- "chat_keypad": chat_keypad,
155
- "inline_keypad": inline_keypad,
156
- "disable_notification": disable_notification,
157
- "reply_to_message_id": reply_to_message_id,
158
- "chat_keypad_type": chat_keypad_type
159
- }
160
- response = await self.request("sendContact", data)
161
- return MessageId.read(response["data"])
162
-
163
-
164
- async def send_sticker(
165
- self,
166
- chat_id: str,
167
- sticker_id: str,
168
- chat_keypad: Keypad = None,
169
- inline_keypad: Keypad = None,
170
- disable_notification: bool = False,
171
- reply_to_message_id: str = None,
172
- chat_keypad_type: Literal[None, "New", "Remove"] = None,
173
- ) -> "MessageId":
174
- data = {
175
- "chat_id": chat_id,
176
- "sticker_id": sticker_id,
177
- "chat_keypad": chat_keypad,
178
- "disable_notification": disable_notification,
179
- "inline_keypad": inline_keypad,
180
- "reply_to_message_id": reply_to_message_id,
181
- "chat_keypad_type": chat_keypad_type
182
- }
183
- response = await self.request("sendSticker", data)
184
- return MessageId.read(response["data"])
185
-
186
-
187
- async def forward_message(
188
- self,
189
- from_chat_id: str,
190
- message_id: str,
191
- to_chat_id: str,
192
- disable_notification: bool = False
193
- ) -> "MessageId":
194
- data = {
195
- "from_chat_id": from_chat_id,
196
- "message_id": message_id,
197
- "to_chat_id": to_chat_id,
198
- "disable_notification": disable_notification
199
- }
200
- response = await self.request("forwardMessage", data)
201
- return MessageId.read(response["data"])
202
-
203
-
204
- async def edit_message_text(
205
- self,
206
- chat_id: str,
207
- message_id: str,
208
- text: str
209
- ) -> None:
210
- data = {"chat_id": chat_id, "message_id": message_id, "text": text}
211
- await self.request("editMessageText", data)
212
-
213
-
214
- async def edit_message_keypad(
215
- self,
216
- chat_id: str,
217
- message_id: str,
218
- inline_keypad: Keypad
219
- ) -> None:
220
- data = {"chat_id": chat_id, "message_id": message_id, "inline_keypad": inline_keypad}
221
- await self.request("editMessageKeypad", data)
222
-
223
-
224
- async def edit_chat_keypad(
225
- self,
226
- chat_id: str,
227
- chat_keypad: Keypad
228
- ) -> None:
229
- data = {"chat_id": chat_id, "chat_keypad_type": "New", "chat_keypad": chat_keypad}
230
- await self.request("editChatKeypad", data)
231
-
232
-
233
- async def remove_chat_keypad(
234
- self,
235
- chat_id: str
236
- ) -> None:
237
- data = {"chat_id": chat_id, "chat_keypad_type": "Remove"}
238
- await self.request("editChatKeypad", data)
239
-
240
-
241
- async def delete_message(
242
- self,
243
- chat_id: str,
244
- message_id: str
245
- ) -> None:
246
- data = {"chat_id": chat_id, "message_id": message_id}
247
- await self.request("deleteMessage", data)
248
-
249
-
250
- async def get_file(self, file_id: str) -> str:
251
- response = await self.request("getFile", {"file_id": file_id})
252
- return response["data"]["download_url"]
253
-
254
-
255
- async def request_send_file(self, type: Literal["File", "Image", "Voice", "Music", "Gif", "Video"]) -> str:
256
- response = await self.request("requestSendFile", {"type": type})
257
- return response["data"]["upload_url"]
258
-
259
-
260
- async def upload_file(self, path: str, file_name: str, type: Literal["File", "Image", "Voice", "Music", "Gif", "Video"]) -> str:
261
- upload_url = await self.request_send_file(type)
262
- form = FormData()
263
- form.add_field("file", open(path, "rb"), filename=file_name, content_type="application/octet-stream")
264
- async with ClientSession() as session:
265
- async with session.post(upload_url, data=form) as response:
266
- result = await response.json()
267
- return result["data"]["file_id"]
268
-
269
-
270
- async def send_file(
271
- self,
272
- chat_id: str,
273
- path: str,
274
- file_name: str,
275
- type: Literal["File", "Image", "Voice", "Music", "Gif", "Video"] = "File",
276
- chat_keypad = None,
277
- inline_keypad = None,
278
- disable_notification: bool = False,
279
- reply_to_message_id: str = None,
280
- chat_keypad_type: Literal["New", "Remove"] = None,
281
- ) -> str:
282
- file_id = await self.upload_file(path, file_name, type)
283
- data = {
284
- "chat_id": chat_id,
285
- "file_id": file_id,
286
- "chat_keypad": chat_keypad,
287
- "disable_notification": disable_notification,
288
- "inline_keypad": inline_keypad,
289
- "reply_to_message_id": reply_to_message_id,
290
- "chat_keypad_type": chat_keypad_type,
291
- }
292
- response = await self.request("sendFile", data)
293
- return MessageId.read(response["data"])
294
-
295
-
296
- async def download_file(self, file_id: str, file_name: str):
297
- download_url = await self.get_file(file_id)
298
- async with ClientSession() as session:
299
- async with session.get(download_url) as response:
300
- if response.status == 200:
301
- async with aiofiles.open(file_name, "wb") as file:
302
- await file.write(await response.read())
303
- return {"status": "OK", "file": file_name}
304
- raise Exception(f"Download Error | status_code : {response.status}")
305
-
306
23
 
307
24
  def run(self):
308
25
  routes = web.RouteTableDef()
@@ -314,4 +31,4 @@ class Client:
314
31
  return web.json_response({"status": "ok"})
315
32
  app = web.Application()
316
33
  app.add_routes(routes)
317
- web.run_app(app, host="0.0.0.0", port=8000)
34
+ web.run_app(app, host="0.0.0.0", port=5000)
rubigram/filters.py CHANGED
@@ -1,58 +1,53 @@
1
1
  from rubigram.types import Update, InlineMessage
2
2
  from typing import Union
3
3
 
4
+ def command(commands: Union[str, list[str]], prefixe: str = "/"):
5
+ def filter(message: Update):
6
+ if isinstance(message, Update) and message.type == "NewMessage" and message.new_message.text:
7
+ text = message.new_message.text
8
+ COMMANDS = commands if isinstance(commands, list) else [commands]
9
+ for cmd in COMMANDS:
10
+ if text.lower().startswith(prefixe + cmd):
11
+ return True
12
+ return False
13
+ return filter
4
14
 
5
- class filter:
6
- @staticmethod
7
- def command(command: Union[str, list[str]], prefixes: Union[str, list[str]] = "/"):
8
- def inner(update: Update):
9
- if isinstance(update, Update) and update.new_message and update.new_message.text:
10
- message = update.new_message
11
- commands = command if isinstance(command, list) else [command]
12
- commands = [c.lower() for c in commands]
13
- prefix_list = [] if prefixes is None else prefixes
14
- prefix_list = prefix_list if isinstance(prefix_list, list) else [prefix_list]
15
- for prefix in prefix_list:
16
- if message.text.startswith(prefix) and commands:
17
- return message.text[len(prefix):].split()[0].lower() in commands
18
- return False
19
- return False
20
- return inner
21
-
22
- @staticmethod
23
- def text():
24
- def inner(update: Update):
25
- if isinstance(update, Update) and update.new_message:
26
- return update.new_message.text is not None
27
- return False
28
- return inner
15
+ def button(id: Union[str, list[str]]):
16
+ def filter(message: InlineMessage):
17
+ if isinstance(message, InlineMessage):
18
+ button_id = message.aux_data.button_id
19
+ ID = id if isinstance(id, list) else [id]
20
+ for i in ID:
21
+ if button_id == i:
22
+ return True
23
+ return False
24
+ return filter
29
25
 
30
- @staticmethod
31
- def private():
32
- def inner(update: Update):
33
- if isinstance(update, Update) and update.new_message:
34
- return update.new_message.sender_type == "User"
35
- return False
36
- return inner
37
-
38
- @staticmethod
39
- def chat(chat_id: str):
40
- def inner(update: Update):
41
- return getattr(update, "chat_id", None) == chat_id
42
- return inner
43
-
44
- @staticmethod
45
- def file():
46
- def inner(update: Update):
47
- if isinstance(update, Update) and update.new_message:
48
- return update.new_message.file is not None
49
- return False
50
- return inner
51
-
52
- @staticmethod
53
- def button(id: str):
54
- def inner(update: InlineMessage):
55
- if isinstance(update, InlineMessage):
56
- return update.aux_data.button_id == id
57
- return False
58
- return inner
26
+ def chat(chat_id: Union[str, list[str]]):
27
+ def filter(message: Union[Update, InlineMessage]):
28
+ chat_ids = chat_id if isinstance(chat_id, list) else [chat_id]
29
+ if isinstance(message, Update) or isinstance(message, InlineMessage):
30
+ return message.chat_id in chat_ids
31
+ return False
32
+ return filter
33
+
34
+ def text():
35
+ def filter(message: Update):
36
+ if isinstance(message, Update) and message.type == "NewMessage":
37
+ return bool(message.new_message.text)
38
+ return False
39
+ return filter
40
+
41
+ def file():
42
+ def filter(message: Update):
43
+ if isinstance(message, Update) and message.type == "NewMessage":
44
+ return bool(message.new_message.file)
45
+ return False
46
+ return filter
47
+
48
+ def private():
49
+ def filter(message: Update):
50
+ if isinstance(message, Update) and message.type == "NewMessage":
51
+ return message.new_message.sender_type in ["User", "Bot"]
52
+ return False
53
+ return filter
rubigram/method.py ADDED
@@ -0,0 +1,208 @@
1
+ from rubigram.network import NetWork
2
+ from typing import Literal, Optional
3
+ from rubigram.types import Bot, Chat, Update, Keypad, MessageId
4
+
5
+ class Method(NetWork):
6
+ def __init__(self, token: str):
7
+ super().__init__(token)
8
+
9
+ async def get_me(self) -> "Bot":
10
+ response = await self.request("getMe", {})
11
+ return Bot.read(response["data"]["bot"])
12
+
13
+ async def get_chat(self, chat_id: str) -> "Chat":
14
+ response = await self.request("getChat", {"chat_id": chat_id})
15
+ return Chat.read(response["data"]["chat"])
16
+
17
+ async def get_update(self, limit: int = 1, offset_id: Optional[int] = None) -> list[Update]:
18
+ response = await self.request("getUpdates", {"limit": limit, "offset_id": offset_id})
19
+ return [Update.read(update) for update in response["data"]["updates"]]
20
+
21
+ async def get_file(self, file_id: str) -> str:
22
+ response = await self.request("getFile", {"file_id": file_id})
23
+ return response["data"]["download_url"]
24
+
25
+ async def set_command(self, command: list):
26
+ response = await self.request("setCommands", {"bot_commands": command})
27
+ return response
28
+
29
+ async def update_bot_endpoint(self, url: str, type: Literal["ReceiveUpdate", "ReceiveInlineMessage", "ReceiveQuery", "GetSelectionItem", "SearchSelectionItems"]):
30
+ response = await self.request("updateBotEndpoints", {"url": url, "type": type})
31
+ return response
32
+
33
+ async def request_send_file(self, type: str):
34
+ response = await self.request("requestSendFile", {"type": type})
35
+ return response["data"]["upload_url"]
36
+
37
+ async def upload_file(self, path: str, name: str, type: str):
38
+ upload_url = await self.request_send_file(type)
39
+ response = await self.request_upload_file(upload_url, path, name)
40
+ return response
41
+
42
+ async def forward_message(self, from_chat_id: str, message_id: str, to_chat_id: str, disable_notification: bool = False) -> "MessageId":
43
+ data = {"from_chat_id": from_chat_id, "message_id": message_id, "to_chat_id": to_chat_id, "disable_notification": disable_notification}
44
+ response = await self.request("forwardMessage", data)
45
+ return MessageId.read(response["data"])
46
+
47
+ async def delete_message(self, chat_id: str, message_id: str):
48
+ await self.request("deleteMessage", {"chat_id": chat_id, "message_id": message_id})
49
+
50
+ async def remove_chat_keypad(self, chat_id: str):
51
+ await self.request("editChatKeypad", {"chat_id": chat_id, "chat_keypad_type": "Remove"})
52
+
53
+ async def edit_chat_keypad(self, chat_id: str, chat_keypad):
54
+ await self.request("editChatKeypad", {"chat_id": chat_id, "chat_keypad_type": "New", "chat_keypad": chat_keypad})
55
+
56
+ async def edit_message_keypad(self, chat_id: str, message_id: str, inline_keypad):
57
+ await self.request("editMessageKeypad", {"chat_id": chat_id, "message_id": message_id, "inline_keypad": inline_keypad})
58
+
59
+ async def edit_message_text(self, chat_id: str, message_id: str, text: str):
60
+ await self.request("editMessageText", {"chat_id": chat_id, "message_id": message_id, "text": text})
61
+
62
+ async def send_message(
63
+ self,
64
+ chat_id: str,
65
+ text: str,
66
+ chat_keypad: Keypad = None,
67
+ inline_keypad: Keypad= None,
68
+ chat_keypad_type: Literal["New", "Remove"] = None,
69
+ disable_notification: bool = None,
70
+ reply_to_message_id = None
71
+ ) -> "MessageId":
72
+ data = {
73
+ "chat_id": chat_id,
74
+ "text": text,
75
+ "chat_keypad": chat_keypad._dict() if chat_keypad else None,
76
+ "inline_keypad": inline_keypad._dict() if inline_keypad else None,
77
+ "chat_keypad_type": chat_keypad_type,
78
+ "disable_notification": disable_notification,
79
+ "reply_to_message_id": reply_to_message_id
80
+ }
81
+ response = await self.request("sendMessage", data)
82
+ return MessageId.read(response["data"])
83
+
84
+ async def send_poll(
85
+ self,
86
+ chat_id: str,
87
+ question: str,
88
+ options: list[str],
89
+ chat_keypad: Keypad = None,
90
+ inline_keypad: Keypad = None,
91
+ disable_notification: bool = False,
92
+ reply_to_message_id: str = None,
93
+ chat_keypad_type: Literal["New", "Remove"] = None
94
+ ) -> "MessageId":
95
+ data = {
96
+ "chat_id": chat_id,
97
+ "question": question,
98
+ "options": options,
99
+ "chat_keypad": chat_keypad._dict() if chat_keypad else None,
100
+ "inline_keypad": inline_keypad._dict() if inline_keypad else None,
101
+ "disable_notification": disable_notification,
102
+ "reply_to_message_id": reply_to_message_id,
103
+ "chat_keypad_type": chat_keypad_type
104
+ }
105
+ response = await self.request("sendPoll", data)
106
+ return MessageId.read(response["data"])
107
+
108
+ async def send_location(
109
+ self,
110
+ chat_id: str,
111
+ latitude: str,
112
+ longitude: str,
113
+ chat_keypad: Keypad = None,
114
+ inline_keypad: Keypad = None,
115
+ disable_notification: bool = False,
116
+ reply_to_message_id: str = None,
117
+ chat_keypad_type: Literal["New", "Remove"] = None
118
+ ) -> "MessageId":
119
+ data = {
120
+ "chat_id": chat_id,
121
+ "latitude": latitude,
122
+ "longitude": longitude,
123
+ "chat_keypad": chat_keypad._dict() if chat_keypad else None,
124
+ "inline_keypad": inline_keypad._dict() if inline_keypad else None,
125
+ "disable_notification": disable_notification,
126
+ "reply_to_message_id": reply_to_message_id,
127
+ "chat_keypad_type": chat_keypad_type
128
+ }
129
+ response = await self.request("sendLocation", data)
130
+ return MessageId.read(response["data"])
131
+
132
+ async def send_contact(
133
+ self,
134
+ chat_id: str,
135
+ first_name: str,
136
+ last_name: str,
137
+ phone_number: str,
138
+ chat_keypad: Keypad = None,
139
+ inline_keypad: Keypad = None,
140
+ disable_notification: bool = False,
141
+ reply_to_message_id: str = None,
142
+ chat_keypad_type: Literal["New", "Remove"] = None
143
+ ) -> "MessageId":
144
+ data = {
145
+ "chat_id": chat_id,
146
+ "first_name": first_name,
147
+ "last_name": last_name,
148
+ "phone_number": phone_number,
149
+ "chat_keypad": chat_keypad._dict() if chat_keypad else None,
150
+ "inline_keypad": inline_keypad._dict() if inline_keypad else None,
151
+ "disable_notification": disable_notification,
152
+ "reply_to_message_id": reply_to_message_id,
153
+ "chat_keypad_type": chat_keypad_type
154
+ }
155
+ response = await self.request("sendContact", data)
156
+ return MessageId.read(response["data"])
157
+
158
+ async def send_sticker(
159
+ self,
160
+ chat_id: str,
161
+ sticker_id: str,
162
+ chat_keypad: Keypad = None,
163
+ inline_keypad: Keypad = None,
164
+ disable_notification: bool = False,
165
+ reply_to_message_id: str = None,
166
+ chat_keypad_type: Literal["New", "Remove"] = None,
167
+ ) -> "MessageId":
168
+ data = {
169
+ "chat_id": chat_id,
170
+ "sticker_id": sticker_id,
171
+ "chat_keypad": chat_keypad._dict() if chat_keypad else None,
172
+ "inline_keypad": inline_keypad._dict() if inline_keypad else None,
173
+ "disable_notification": disable_notification,
174
+ "reply_to_message_id": reply_to_message_id,
175
+ "chat_keypad_type": chat_keypad_type
176
+ }
177
+ response = await self.request("sendSticker", data)
178
+ return MessageId.read(response["data"])
179
+
180
+ async def send_file(
181
+ self,
182
+ chat_id: str,
183
+ path: str,
184
+ file_name: str,
185
+ type: Literal["File", "Image", "Voice", "Music", "Gif", "Video"] = "File",
186
+ chat_keypad: Keypad = None,
187
+ inline_keypad: Keypad = None,
188
+ disable_notification: bool = False,
189
+ reply_to_message_id: str = None,
190
+ chat_keypad_type: Literal["New", "Remove"] = None,
191
+ ) -> "MessageId":
192
+ file_id = await self.upload_file(path, file_name, type)
193
+ data = {
194
+ "chat_id": chat_id,
195
+ "file_id": file_id,
196
+ "chat_keypad": chat_keypad._dict() if chat_keypad else None,
197
+ "inline_keypad": inline_keypad._dict() if inline_keypad else None,
198
+ "disable_notification": disable_notification,
199
+ "reply_to_message_id": reply_to_message_id,
200
+ "chat_keypad_type": chat_keypad_type,
201
+ }
202
+ response = await self.request("sendFile", data)
203
+ return MessageId.read(response["data"])
204
+
205
+ async def download_file(self, file_id: str, file_name: str):
206
+ download_url = await self.get_file(file_id)
207
+ response = await self.request_download_file(download_url, file_name)
208
+ return response
rubigram/network.py ADDED
@@ -0,0 +1,30 @@
1
+ from aiohttp import ClientSession, FormData
2
+ import aiofiles
3
+
4
+ class NetWork:
5
+ def __init__(self, token: str):
6
+ self.token = token
7
+ self.api = f"https://botapi.rubika.ir/v3/{self.token}/"
8
+
9
+ async def request(self, method: str, json: dict) -> dict:
10
+ async with ClientSession() as session:
11
+ async with session.post(self.api + method, json=json) as response:
12
+ response.raise_for_status()
13
+ return await response.json()
14
+
15
+ async def request_upload_file(self, url: str, path: str, name: str) -> str:
16
+ form = FormData()
17
+ form.add_field("file", open(path, "rb"), filename=name, content_type="application/octet-stream")
18
+ async with ClientSession() as session:
19
+ async with session.post(url, data=form) as response:
20
+ response.raise_for_status()
21
+ result = await response.json()
22
+ return result["data"]["file_id"]
23
+
24
+ async def request_download_file(self, url: str, name: str):
25
+ async with ClientSession() as session:
26
+ async with session.get(url) as response:
27
+ response.raise_for_status()
28
+ async with aiofiles.open(name, mode="wb") as file:
29
+ await file.write(await response.read())
30
+ return {"status": True, "file": name}
rubigram/types.py CHANGED
@@ -200,6 +200,7 @@ class MessageId:
200
200
  message_id = data.get("message_id"),
201
201
  file_id = data.get("file_id")
202
202
  )
203
+
203
204
 
204
205
  @dataclass
205
206
  class PollStatus:
@@ -270,14 +271,14 @@ class Poll:
270
271
  @dataclass
271
272
  class ContactMessage:
272
273
  phone_number: Optional[str] = None
273
- first_name: Optional[File] = None
274
+ first_name: Optional[str] = None
274
275
  last_name: Optional[str] = None
275
276
 
276
277
  @classmethod
277
278
  def read(cls, data: dict[str, Any]) -> "ContactMessage":
278
279
  return cls(
279
280
  phone_number = data.get("phone_number"),
280
- first_name = File.read(data.get("first_name")) if "first_name" in data else None,
281
+ first_name = data.get("first_name"),
281
282
  last_name = data.get("last_name")
282
283
  )
283
284
 
@@ -458,7 +459,7 @@ class Update:
458
459
  type = data["type"],
459
460
  chat_id = data["chat_id"],
460
461
  removed_message_id = data.get("removed_message_id"),
461
- new_message = Message.read(data["new_message"]),
462
+ new_message = Message.read(data["new_message"]) if "new_message" in data else None,
462
463
  updated_message = Message.read(data["updated_message"]) if "updated_message" in data else None,
463
464
  updated_payment = PaymentStatus.read(data["updated_payment"]) if "updated_payment" in data else None
464
465
  )
@@ -467,4 +468,7 @@ class Update:
467
468
  return await self.client.send_message(self.chat_id, text, reply_to_message_id=self.new_message.message_id)
468
469
 
469
470
  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)
471
+ return await self.client.send_file(self.chat_id, path, file_name, type, reply_to_message_id=self.new_message.message_id)
472
+
473
+ async def download(self, file_name: str):
474
+ return await self.client.download_file(self.new_message.file.file_id, file_name)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RubigramClient
3
- Version: 1.3.3
3
+ Version: 1.3.4
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=4JZ6q8ukflz_izRmJNYcndcKZFCsyJdYoYVoAPwN5V0,107
2
+ rubigram/client.py,sha256=wjSFIoE5s2vniZuNUPpa80TvyYC6dvxbwCfKpJDcLnI,1257
3
+ rubigram/filters.py,sha256=VU9Nd5ALWQAXafH1mXi19hm-E5H20JgTswTS4usK3ro,1955
4
+ rubigram/method.py,sha256=nm2qfzkanpzDo3yusIXmjYgCYmLzV6nVOyaxPDDqqz4,9074
5
+ rubigram/network.py,sha256=K7vvGikXStvUBqHX2gogy3hJ1eQjLAJ7kdwLbfFuZIg,1399
6
+ rubigram/types.py,sha256=TidelegJkJ-UT8b9JTmhL_qKBmm-A-nu04pyPYk-ApI,16955
7
+ rubigramclient-1.3.4.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ rubigramclient-1.3.4.dist-info/METADATA,sha256=uKmdhwhbiJcdPSGpq3LEUjFUV1U-bRjwZ41kFZs37fo,984
9
+ rubigramclient-1.3.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
10
+ rubigramclient-1.3.4.dist-info/top_level.txt,sha256=Mhg5HfkL6rLec5sI4ClGmwoqYUANAZUz8sVa1sT_cas,9
11
+ rubigramclient-1.3.4.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- rubigram/__init__.py,sha256=K1WXGcBx9-1cLmImtnruqFk91nb_6XuhY_Ud0KS_IUk,55
2
- rubigram/client.py,sha256=bwt5209q4wcT9nUP67KLWryWF4TWmz1r1PR1lNuM1S8,11591
3
- rubigram/filters.py,sha256=nvROwHxBdjokWezfAZBjRgBdJdcOcjz0IuR3BShyiJw,2153
4
- rubigram/types.py,sha256=GIGvTGdDURuwJ3oHPvRR7B8oJ3V1f8MDaMAqjvOOO-0,16813
5
- rubigramclient-1.3.3.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- rubigramclient-1.3.3.dist-info/METADATA,sha256=JAm-gGFFLj-ea9Br1sx8GhREUYLGx-JO7dBTSbsLxKA,984
7
- rubigramclient-1.3.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
- rubigramclient-1.3.3.dist-info/top_level.txt,sha256=Mhg5HfkL6rLec5sI4ClGmwoqYUANAZUz8sVa1sT_cas,9
9
- rubigramclient-1.3.3.dist-info/RECORD,,