RubigramClient 1.1.1__tar.gz → 1.2.0__tar.gz

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.

@@ -0,0 +1,33 @@
1
+ Metadata-Version: 2.4
2
+ Name: RubigramClient
3
+ Version: 1.2.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
+
16
+ A lightweight Python library to build Rubika bots easily.
17
+
18
+ ## Installation
19
+ ```bash
20
+ pip install RubigramClient
21
+
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,20 @@
1
+ # Rubigram
2
+
3
+ A lightweight Python library to build Rubika bots easily.
4
+
5
+ ## Installation
6
+ ```bash
7
+ pip install RubigramClient
8
+
9
+ ```python
10
+ from rubigram import Client, filters
11
+ from rubigram.types import Update
12
+
13
+ bot = Client("your_bot_token")
14
+
15
+ @bot.on_message(filters.command("start"))
16
+ async def start_handler(client, message: Update):
17
+ await message.reply("Hi, WELCOME TO RUBIGRAM")
18
+
19
+ bot.run()
20
+ ```
@@ -0,0 +1,33 @@
1
+ Metadata-Version: 2.4
2
+ Name: RubigramClient
3
+ Version: 1.2.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
+
16
+ A lightweight Python library to build Rubika bots easily.
17
+
18
+ ## Installation
19
+ ```bash
20
+ pip install RubigramClient
21
+
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,15 @@
1
+ [project]
2
+ name = "RubigramClient"
3
+ version = "1.2.0"
4
+ description = "A simple and flexible Python library for building advanced Rubika bots with powerful message handling, inline buttons, and custom filters."
5
+ readme = "README.md"
6
+ requires-python = ">=3.7"
7
+ license = {file = "LICENSE"}
8
+ authors = [
9
+ { name="Javad RZ", email="Javad.Py1385@gmail.com" }
10
+ ]
11
+ classifiers = [
12
+ "Programming Language :: Python :: 3",
13
+ "License :: OSI Approved :: MIT License",
14
+ "Operating System :: OS Independent",
15
+ ]
@@ -0,0 +1,2 @@
1
+ from .client import Client
2
+ from .filters import filter
@@ -1,6 +1,6 @@
1
- from rubigram.types import Message, InlineMessage, MessageId, Chat, Bot
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
- update_object = Message(self, data["update"]) if data.get("update") else InlineMessage(data["inline_message"])
30
+ event = Update.read(data["update"], self)
31
31
  for handler in self.messages_handler:
32
- await handler(self, update_object)
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
- return response
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):
@@ -1,23 +1,23 @@
1
- from rubigram.types import Message
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: Message):
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: Message):
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: Message):
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: Message):
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: Message):
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: Message):
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: Message):
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
@@ -0,0 +1,470 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any, Dict, List, Literal, Optional
3
+ import rubigram
4
+
5
+
6
+
7
+ @dataclass
8
+ class Location:
9
+ longitude: Optional[str] = None
10
+ latitude: Optional[str] = None
11
+
12
+ def _dict(self) -> Dict:
13
+ return {
14
+ "longitude": self.longitude,
15
+ "latitude": self.latitude
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
+ )
24
+
25
+ @dataclass
26
+ class ButtonSelectionItem:
27
+ text: Optional[str] = None
28
+ image_url: Optional[str] = None
29
+ type: Optional[Literal["TextOnly", "TextImgThu", "TextImgBig"]] = None
30
+
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
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
62
+
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
+ }
71
+
72
+ @dataclass
73
+ class ButtonStringPicker:
74
+ items: Optional[List[str]] = None
75
+ default_value: Optional[str] = None
76
+ title: Optional[str] = None
77
+
78
+ def _dict(self) -> Dict:
79
+ return {
80
+ "items": self.items,
81
+ "default_value": self.default_value,
82
+ "title": self.title,
83
+ }
84
+
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
91
+
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
+ }
99
+
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
107
+
108
+ def _dict(self) -> Dict:
109
+ return {
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
115
+ }
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:
128
+ return {
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
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:
157
+ return {
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
167
+ }
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
+ }
177
+
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:
185
+ return {
186
+ "rows": [row._dict() for row in self.rows],
187
+ "resize_keyboard": self.resize_keyboard,
188
+ "one_time_keyboard": self.on_time_keyboard
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
196
+
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
+ )
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
+ )
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
339
+ class Chat:
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
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
+ )
359
+
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
+ )
381
+
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
391
+
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
+ )
403
+
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)
@@ -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,14 +0,0 @@
1
- Rubigram
2
-
3
- ```python
4
- from rubigram import Client, filter
5
- from rubigram.types import Message
6
-
7
- client = Client("Your_Bot_Token")
8
-
9
- @bot.on_message(filter.command("start"))
10
- async def start(client: Client, message: Message):
11
- chat_id = message.chat_id
12
- await message.reply("Hi, {}".format(chat_id))
13
-
14
- client.run()
@@ -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,17 +0,0 @@
1
- [build-system]
2
- requires = ["setuptools", "wheel"]
3
- build-backend = "setuptools.build_meta"
4
-
5
- [project]
6
- name = "RubigramClient"
7
- version = "1.1.1"
8
- description = "A Python library for connect to Rubika API"
9
- readme = "README.md"
10
- authors = [
11
- { name = "Javad RJ", email = "Javad.Py1385@gmail.com" }
12
- ]
13
- license = { file = "LICENSE" }
14
- requires-python = ">=3.7"
15
-
16
- [tool.setuptools.packages.find]
17
- where = ["."]
@@ -1,3 +0,0 @@
1
- from .client import Client
2
- from .filters import filter
3
- from . import types
@@ -1,235 +0,0 @@
1
- import rubigram
2
- from typing import Literal
3
- from json import dumps
4
-
5
-
6
-
7
- class ForwardFrom:
8
- def __init__(self, data: dict):
9
- self.type_from: str = data["type_from"]
10
- self.message_id: str = data["message_id"]
11
- self.from_sender_id: str = data.get("from_sender_id")
12
- self.from_chat_id: str = data.get("from_chat_id")
13
-
14
- def _dict(self):
15
- return {
16
- "type_from": self.type_from,
17
- "message_id": self.message_id,
18
- "from_sender_id": self.from_sender_id,
19
- "from_chat_id": self.from_chat_id
20
- }
21
-
22
- def __str__(self):
23
- return dumps(self._dict(), indent=4, ensure_ascii=False)
24
-
25
-
26
- class File:
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")
31
-
32
- def _dict(self):
33
- return {"file_id": self.file_id, "file_name": self.file_name, "size": self.size}
34
-
35
- def __str__(self):
36
- return dumps(self._dict(), indent=4, ensure_ascii=False)
37
-
38
-
39
- class Location:
40
- def __init__(self, data: dict):
41
- self.longitude: int = data["longitude"]
42
- self.latitude: int = data["latitude"]
43
-
44
- def _dict(self):
45
- return {"longitude": self.longitude, "latitude": self.latitude}
46
-
47
- def __str__(self):
48
- return dumps(self._dict(), indent=4, ensure_ascii=False)
49
-
50
-
51
- class AuxData:
52
- def __init__(self, data: dict):
53
- self.start_id = data.get("start_id")
54
- self.button_id: str = data.get("button_id")
55
-
56
- def _dict(self):
57
- return {"start_id": self.start_id, "button_id": self.button_id}
58
-
59
- def __str__(self):
60
- return dumps(self._dict(), indent=4, ensure_ascii=False)
61
-
62
-
63
- class MessageId:
64
- def __init__(self, data: dict):
65
- self.message_id = data["message_id"]
66
-
67
- def _dict(self):
68
- return {"message_id": self.message_id}
69
-
70
- def __str__(self):
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):
84
- return {
85
- "message_id": self.message_id,
86
- "text": self.text,
87
- "time": self.time,
88
- "is_edited": self.is_edited,
89
- "sender_type": self.sender_type,
90
- "sender_id": self.sender_id
91
- }
92
-
93
- def __str__(self):
94
- return dumps(self._dict(), indent=4, ensure_ascii=False)
95
-
96
-
97
- class NewMessage:
98
- def __init__(self, data: dict):
99
- self.message_id: str = data["message_id"]
100
- self.time: str = data["time"]
101
- self.is_edited: bool = data["is_edited"]
102
- self.sender_type: str = data["sender_type"]
103
- self.sender_id: str = data["sender_id"]
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):
111
- return {
112
- "message_id": self.message_id,
113
- "time": self.time,
114
- "is_edited": self.is_edited,
115
- "sender_type": self.sender_type,
116
- "sender_id": self.sender_id,
117
- "text": self.text,
118
- "forwarded_from": self.forwarded_from._dict() if self.forwarded_from else None,
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
122
- }
123
-
124
- def __str__(self):
125
- return dumps(self._dict(), indent=4, ensure_ascii=False)
126
-
127
-
128
- class InlineMessage:
129
- def __init__(self, data: dict):
130
- self.message_id: str = data["message_id"]
131
- self.chat_id: str = data["chat_id"]
132
- self.sender_id: str = data["sender_id"]
133
- self.text: str = data["text"]
134
- self.aux_data: AuxData = AuxData(data["aux_data"])
135
- self.location: Location = Location(data["location"]) if data.get("location") else None
136
-
137
- def _dict(self):
138
- return {
139
- "message_id": self.message_id,
140
- "chat_id": self.chat_id,
141
- "sender_id": self.sender_id,
142
- "text": self.text,
143
- "aux_data": self.aux_data._dict() if self.aux_data else None,
144
- "location":self.location._dict() if self.location else None
145
- }
146
-
147
- def __str__(self):
148
- return dumps(self._dict(), indent=4, ensure_ascii=False)
149
-
150
-
151
- class Bot:
152
- def __init__(self, data: dict):
153
- self.bot_id: str = data["bot_id"]
154
- self.bot_title: str = data["bot_title"]
155
- self.username: str = data["username"]
156
- self.start_message: str = data["start_message"]
157
- self.share_url: str = data["share_url"]
158
- self.description: str = data["description"]
159
- self.avatar: File = File(data["avatar"]) if data.get("avatar") else None
160
-
161
- def _dict(self):
162
- return {
163
- "bot_id": self.bot_id,
164
- "bot_title": self.bot_title,
165
- "username": self.username,
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
170
- }
171
-
172
- def __str__(self):
173
- return dumps(self._dict(), indent=4, ensure_ascii=False)
174
-
175
-
176
- class Chat:
177
- def __init__(self, data: dict):
178
- self.chat_id: str = data["chat_id"]
179
- self.chat_type: str = data["chat_type"]
180
- self.user_id: str = data.get("user_id")
181
- self.first_name: str = data.get("first_name")
182
- self.last_name: str = data.get("last_name")
183
- self.title: str = data.get("title")
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)
199
-
200
-
201
- class Message:
202
- def __init__(self, client: "rubigram.Client", data: dict):
203
- # Message Update Type : ["NewMessage", "UpdatedMessage", "RemovedMessage", "StartedBot", "StoppedBot"و "UpdatedPayment"]
204
- self.client = client
205
- self.type: str = data["type"]
206
- self.chat_id: str = data["chat_id"]
207
- self.new_message: NewMessage = NewMessage(data.get("new_message")) if data.get("new_message") else None
208
- self.removed_message_id: int = data.get("removed_message_id")
209
- self.updated_message: UpdateMessage = UpdateMessage(data.get("updated_message")) if data.get("updated_message") else None
210
-
211
- def _dict(self):
212
- return {
213
- "type": self.type,
214
- "chat_id": self.chat_id,
215
- "new_message": self.new_message._dict() if self.new_message else None,
216
- "removed_message_id" : self.removed_message_id,
217
- "updated_message": self.updated_message._dict() if self.updated_message else None
218
- }
219
-
220
- def __str__(self):
221
- return dumps(self._dict(), indent=4, ensure_ascii=False)
222
-
223
- async def reply_text(self, text: str):
224
- return await self.client.send_message(self.chat_id, text, reply_to_message_id=self.new_message.message_id)
225
-
226
- async def reply_file(
227
- self,
228
- path: str,
229
- file_name: str,
230
- type: Literal["File", "Image", "Voice", "Music", "Gif", "Video"] = "File"
231
- ):
232
- return await self.client.send_file(self.chat_id, path, file_name, type)
233
-
234
- async def download(self, file_name: str):
235
- return await self.client.download_file(self.new_message.file.file_id, file_name)
File without changes
File without changes