Rubka 4.5.0__py3-none-any.whl → 4.5.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
rubka/api.py CHANGED
@@ -115,6 +115,7 @@ class Robot:
115
115
  self._callback_handler = None
116
116
  self._message_handler = None
117
117
  self._inline_query_handler = None
118
+ self._message_handlers: List[dict] = []
118
119
  self._callback_handlers = None
119
120
  self._callback_handlers = [] # ✅ این خط مهمه
120
121
  if web_hook:
@@ -161,11 +162,11 @@ class Robot:
161
162
  return self._post("getMe", {})
162
163
  def on_message(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
163
164
  def decorator(func: Callable[[Any, Message], None]):
164
- self._message_handler = {
165
+ self._message_handlers.append({
165
166
  "func": func,
166
167
  "filters": filters,
167
168
  "commands": commands
168
- }
169
+ })
169
170
  return func
170
171
  return decorator
171
172
 
@@ -200,64 +201,58 @@ class Robot:
200
201
 
201
202
 
202
203
  def _process_update(self, update: dict):
203
- import threading, time
204
-
205
- # هندل پیام inline (معمولاً type = ReceiveQuery)
204
+ import threading
205
+ # هندل پیام inline (بدون تغییر)
206
206
  if update.get("type") == "ReceiveQuery":
207
207
  msg = update.get("inline_message", {})
208
- if update.get("type") == "ReceiveQuery":
209
- msg = update.get("inline_message", {})
210
- context = InlineMessage(bot=self, raw_data=msg)
211
- threading.Thread(target=self._handle_inline_query, args=(context,), daemon=True).start()
212
- return
208
+ context = InlineMessage(bot=self, raw_data=msg)
209
+ threading.Thread(target=self._handle_inline_query, args=(context,), daemon=True).start()
210
+ return
213
211
 
214
212
  # هندل پیام جدید متنی
215
213
  if update.get("type") == "NewMessage":
216
214
  msg = update.get("new_message", {})
217
- chat_id = update.get("chat_id")
218
- message_id = msg.get("message_id")
219
- sender_id = msg.get("sender_id")
220
- text = msg.get("text")
221
-
222
- # فیلتر زمان پیام (مثلاً پیام‌های خیلی قدیمی)
223
215
  try:
224
216
  if msg.get("time") and (time.time() - float(msg["time"])) > 20:
225
217
  return
226
218
  except Exception:
227
219
  return
228
220
 
229
- # ساخت context پیام
230
- context = Message(bot=self, chat_id=chat_id, message_id=message_id, sender_id=sender_id, text=text, raw_data=msg)
221
+ context = Message(bot=self,
222
+ chat_id=update.get("chat_id"),
223
+ message_id=msg.get("message_id"),
224
+ sender_id=msg.get("sender_id"),
225
+ text=msg.get("text"),
226
+ raw_data=msg)
231
227
 
232
- # هندل callback ها (دکمه‌ها)
233
- if context.aux_data and hasattr(self, "_callback_handlers"):
228
+ # هندل callback ها (دکمه‌ها) - بدون تغییر
229
+ if context.aux_data and self._callback_handlers:
234
230
  for handler in self._callback_handlers:
235
231
  if not handler["button_id"] or context.aux_data.button_id == handler["button_id"]:
236
232
  threading.Thread(target=handler["func"], args=(self, context), daemon=True).start()
237
- return # فقط یک callback اجرا شود
238
-
239
- # هندل پیام‌های متنی معمولی
240
- if hasattr(self, "_message_handler") and self._message_handler:
241
- handler = self._message_handler
242
-
243
- if handler["commands"]:
244
- if not context.text or not context.text.startswith("/"):
245
233
  return
246
- parts = context.text.split()
247
- cmd = parts[0][1:]
248
- if cmd not in handler["commands"]:
249
- return
250
- context.args = parts[1:]
251
234
 
252
- if handler["filters"] and not handler["filters"](context):
235
+ # هندل پیام‌های متنی با حلقه روی تمام هندلرها
236
+ if self._message_handlers:
237
+ for handler in self._message_handlers:
238
+ # بررسی شرط دستورات (commands)
239
+ if handler["commands"]:
240
+ if not context.text or not context.text.startswith("/"):
241
+ continue
242
+ parts = context.text.split()
243
+ cmd = parts[0][1:]
244
+ if cmd not in handler["commands"]:
245
+ continue
246
+ context.args = parts[1:]
247
+
248
+ # بررسی شرط فیلترها (filters)
249
+ if handler["filters"] and not handler["filters"](context):
250
+ continue
251
+
252
+ # اگر شرایط بالا برقرار بود یا هندلر عمومی بود، اجرا کن و خارج شو
253
+ threading.Thread(target=handler["func"], args=(self, context), daemon=True).start()
253
254
  return
254
255
 
255
- threading.Thread(target=handler["func"], args=(self, context), daemon=True).start()
256
-
257
-
258
-
259
-
260
-
261
256
  def get_updates(
262
257
  self,
263
258
  offset_id: Optional[str] = None,
rubka/asynco.py CHANGED
@@ -119,6 +119,7 @@ class Robot:
119
119
  self._inline_query_handler = None
120
120
  self._callback_handlers: List[dict] = []
121
121
  self._processed_message_ids: Dict[str, float] = {}
122
+ self._message_handlers: List[dict] = []
122
123
 
123
124
  logger.info(f"Initialized RubikaBot with token: {token[:8]}***")
124
125
 
@@ -184,11 +185,11 @@ class Robot:
184
185
 
185
186
  def on_message(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
186
187
  def decorator(func: Callable[[Any, Message], None]):
187
- self._message_handler = {
188
+ self._message_handlers.append({
188
189
  "func": func,
189
190
  "filters": filters,
190
191
  "commands": commands
191
- }
192
+ })
192
193
  return func
193
194
  return decorator
194
195
 
@@ -244,27 +245,40 @@ class Robot:
244
245
  text=msg.get("text"),
245
246
  raw_data=msg)
246
247
 
248
+ # پردازش دکمه‌های شیشه‌ای (بدون تغییر)
247
249
  if context.aux_data and self._callback_handlers:
248
250
  for handler in self._callback_handlers:
249
251
  if not handler["button_id"] or context.aux_data.button_id == handler["button_id"]:
250
252
  asyncio.create_task(handler["func"](self, context))
251
253
  return
252
254
 
253
- if self._message_handler:
254
- handler_info = self._message_handler
255
- if handler_info["commands"]:
256
- if not context.text or not context.text.startswith("/"):
257
- return
258
- parts = context.text.split()
259
- cmd = parts[0][1:]
260
- if cmd not in handler_info["commands"]:
261
- return
262
- context.args = parts[1:]
263
-
264
- if handler_info["filters"] and not handler_info["filters"](context):
265
- return
266
-
267
- asyncio.create_task(handler_info["func"](self, context))
255
+ # پردازش پیام‌های متنی با حلقه روی تمام هندلرها
256
+ if self._message_handlers:
257
+ for handler_info in self._message_handlers:
258
+ # بررسی شرط دستورات (commands)
259
+ if handler_info["commands"]:
260
+ if not context.text or not context.text.startswith("/"):
261
+ continue # اگر پیام کامند نبود، این هندلر را رد کن
262
+ parts = context.text.split()
263
+ cmd = parts[0][1:]
264
+ if cmd not in handler_info["commands"]:
265
+ continue # اگر کامند مطابقت نداشت، این هندلر را رد کن
266
+ context.args = parts[1:]
267
+
268
+ # بررسی شرط فیلترها (filters)
269
+ if handler_info["filters"]:
270
+ if not handler_info["filters"](context):
271
+ continue # اگر فیلتر برقرار نبود، این هندلر را رد کن
272
+
273
+ # اگر هندلری برای همه پیام‌ها باشد (بدون کامند و فیلتر)
274
+ if not handler_info["commands"] and not handler_info["filters"]:
275
+ asyncio.create_task(handler_info["func"](self, context))
276
+ return # بعد از یافتن هندلر مناسب، از حلقه خارج شو
277
+
278
+ # اگر شرایط کامند یا فیلتر برقرار بود
279
+ if handler_info["commands"] or handler_info["filters"]:
280
+ asyncio.create_task(handler_info["func"](self, context))
281
+ return # بعد از یافتن هندلر مناسب، از حلقه خارج شو
268
282
 
269
283
  async def get_updates(self, offset_id: Optional[str] = None, limit: Optional[int] = None) -> Dict[str, Any]:
270
284
  data = {}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Rubka
3
- Version: 4.5.0
3
+ Version: 4.5.2
4
4
  Summary: A Python library for interacting with Rubika Bot API.
5
5
  Home-page: https://github.com/Mahdy-Ahmadi/Rubka
6
6
  Download-URL: https://github.com/Mahdy-Ahmadi/rubka/blob/main/project_library.zip
@@ -1,6 +1,6 @@
1
1
  rubka/__init__.py,sha256=TR1DABU5Maz2eO62ZEFiwOqNU0dH6l6HZfqRUxeo4eY,194
2
- rubka/api.py,sha256=KGcbBPJh7RaoYPuJTcpzAfhbgZ1PerSA5wn_tzelDq0,35045
3
- rubka/asynco.py,sha256=osfR2hKKEOT1Pqp0Meq3Iu-_Oox_SjwEesKJzv_Jqgo,30581
2
+ rubka/api.py,sha256=gzaH2nfZjpxlMwzNsgA4FFBR38bAfQK2-2oTPs555Xw,35160
3
+ rubka/asynco.py,sha256=m3WztgmkzK6Jvrko8HxqLlIigWTbtJkdbDdQq3NtbMo,31994
4
4
  rubka/button.py,sha256=4fMSZR7vUADxSmw1R3_pZ4dw5uMLZX5sOkwPPyNTBDE,8437
5
5
  rubka/config.py,sha256=Bck59xkOiqioLv0GkQ1qPGnBXVctz1hKk6LT4h2EPx0,78
6
6
  rubka/context.py,sha256=j1scXTy_wBY52MmMixfZyIQnB0sdYjRwx17-8ZZmyB4,17017
@@ -33,7 +33,7 @@ rubka/adaptorrubka/types/socket/message.py,sha256=0WgLMZh4eow8Zn7AiSX4C3GZjQTkIg
33
33
  rubka/adaptorrubka/utils/__init__.py,sha256=OgCFkXdNFh379quNwIVOAWY2NP5cIOxU5gDRRALTk4o,54
34
34
  rubka/adaptorrubka/utils/configs.py,sha256=nMUEOJh1NqDJsf9W9PurkN_DLYjO6kKPMm923i4Jj_A,492
35
35
  rubka/adaptorrubka/utils/utils.py,sha256=5-LioLNYX_TIbQGDeT50j7Sg9nAWH2LJUUs-iEXpsUY,8816
36
- rubka-4.5.0.dist-info/METADATA,sha256=3xURNUuDQNQR2PrKrMgqOn11urYLW82eYtHEmGyMoOw,33216
37
- rubka-4.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
- rubka-4.5.0.dist-info/top_level.txt,sha256=vy2A4lot11cRMdQS-F4HDCIXL3JK8RKfu7HMDkezJW4,6
39
- rubka-4.5.0.dist-info/RECORD,,
36
+ rubka-4.5.2.dist-info/METADATA,sha256=xgwDJfrcrmaI2Hr9YEugIt8_3OzJiAXBHx2sldoW7ZU,33216
37
+ rubka-4.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
+ rubka-4.5.2.dist-info/top_level.txt,sha256=vy2A4lot11cRMdQS-F4HDCIXL3JK8RKfu7HMDkezJW4,6
39
+ rubka-4.5.2.dist-info/RECORD,,
File without changes