RubigramClient 1.5.5__tar.gz → 1.5.6__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RubigramClient
3
- Version: 1.5.5
3
+ Version: 1.5.6
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
@@ -51,8 +51,8 @@ async def start(_, message: Update):
51
51
  rows=[
52
52
  KeypadRow(
53
53
  buttons=[
54
- Button("1", "Simple", "Button 1"),
55
- Button("2", "Simple", "Button 2")
54
+ Button("1", "Button 1"),
55
+ Button("2", "Button 2")
56
56
  ]
57
57
  )
58
58
  ]
@@ -35,8 +35,8 @@ async def start(_, message: Update):
35
35
  rows=[
36
36
  KeypadRow(
37
37
  buttons=[
38
- Button("1", "Simple", "Button 1"),
39
- Button("2", "Simple", "Button 2")
38
+ Button("1", "Button 1"),
39
+ Button("2", "Button 2")
40
40
  ]
41
41
  )
42
42
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RubigramClient
3
- Version: 1.5.5
3
+ Version: 1.5.6
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
@@ -51,8 +51,8 @@ async def start(_, message: Update):
51
51
  rows=[
52
52
  KeypadRow(
53
53
  buttons=[
54
- Button("1", "Simple", "Button 1"),
55
- Button("2", "Simple", "Button 2")
54
+ Button("1", "Button 1"),
55
+ Button("2", "Button 2")
56
56
  ]
57
57
  )
58
58
  ]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "RubigramClient"
3
- version = "1.5.5"
3
+ version = "1.5.6"
4
4
  description = "A simple and flexible Python library for building advanced Rubika bots with powerful message handling, inline buttons, and custom filters."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.7"
@@ -0,0 +1,115 @@
1
+ from typing import Optional, Callable, Literal, Union
2
+ from rubigram.models import Update, InlineMessage
3
+ from rubigram.method import Method
4
+ from rubigram.filters import Filter
5
+ from rubigram.state import StateManager
6
+ from datetime import datetime
7
+ from aiohttp import web
8
+ import asyncio
9
+
10
+ class Client(Method):
11
+ def __init__(
12
+ self,
13
+ token: str,
14
+ endpoint: Optional[str] = None,
15
+ host: str = "0.0.0.0",
16
+ port: int = 8000
17
+ ):
18
+ self.token = token
19
+ self.endpoint = endpoint
20
+ self.host = host
21
+ self.port = port
22
+ self.offset_id = None
23
+ self.MESSAGE_HANDLER = []
24
+ self.INLINE_HANDLER = []
25
+ self.state = StateManager()
26
+ super().__init__(token)
27
+
28
+
29
+ def create_handler(self, type: Literal["message", "inline"], filters: Optional[Filter] = None):
30
+ def decorator(func: Callable) -> Callable:
31
+ async def wrapper(client: Client, update: Update):
32
+ if filters is None or await filters(update):
33
+ await func(client, update)
34
+ return True
35
+ return False
36
+ self.MESSAGE_HANDLER.append(wrapper) if type == "message" else self.INLINE_HANDLER.append(wrapper)
37
+ return func
38
+ return decorator
39
+
40
+ def on_message(self, filters: Optional[Filter] = None):
41
+ return self.create_handler("message", filters)
42
+
43
+ def on_inline_message(self, filters: Optional[Filter] = None):
44
+ return self.create_handler("inline", filters)
45
+
46
+ async def dispatch(self, update: Union[Update, InlineMessage], type: Literal["message", "inline"]):
47
+ handlers = self.MESSAGE_HANDLER if type == "message" else self.INLINE_HANDLER
48
+ for handler in handlers:
49
+ matched = await handler(self, update)
50
+ if matched:
51
+ return
52
+
53
+ async def updater(self, data: dict):
54
+ if "inline_message" in data:
55
+ event = InlineMessage.from_dict(data["inline_message"])
56
+ type = "inline"
57
+ elif "update" in data:
58
+ event = Update.from_dict(data["update"])
59
+ type = "message"
60
+ else: return
61
+ event.client = self
62
+ await self.dispatch(event, type)
63
+
64
+ async def set_endpoints(self):
65
+ endpoint_type = ["ReceiveUpdate", "ReceiveInlineMessage"]
66
+ if self.endpoint:
67
+ for i in endpoint_type:
68
+ await self.update_bot_endpoint(f"{self.endpoint}/{i}", i)
69
+
70
+ async def on_startup(self, app):
71
+ await self.set_endpoints()
72
+ await self.state.start()
73
+ await self.start()
74
+
75
+ async def on_cleanup(self, app):
76
+ await self.state.stop()
77
+ await self.stop()
78
+
79
+ def create_request_handler(self):
80
+ async def wrapper(request: web.Request):
81
+ data = await request.json()
82
+ await self.updater(data)
83
+ return web.json_response({"status": "OK"})
84
+ return wrapper
85
+
86
+ async def runner(self):
87
+ try:
88
+ await self.state.start()
89
+ while True:
90
+ get_updates = await self.get_update(100, self.offset_id)
91
+ if get_updates.updates:
92
+ updates = get_updates.updates
93
+ for update in updates:
94
+ time = int(update.new_message.time) if update.type == "NewMessage" else int(update.updated_message.time) if update.type == "UpdatedMessage" else None
95
+ now = int(datetime.now().timestamp())
96
+ if time and time >= now or time + 2 >= now:
97
+ update.client = self
98
+ await self.dispatch(update, "message")
99
+ self.offset_id = get_updates.next_offset_id
100
+ except Exception as error:
101
+ print(f"ERROR : {error}")
102
+ finally:
103
+ await self.state.stop()
104
+ await self.stop()
105
+
106
+ def run(self):
107
+ if self.endpoint:
108
+ app = web.Application()
109
+ app.router.add_post("/ReceiveUpdate", self.create_request_handler())
110
+ app.router.add_post("/ReceiveInlineMessage", self.create_request_handler())
111
+ web.run_app(app, host=self.host, port=self.port)
112
+ else:
113
+ try:
114
+ asyncio.run(self.runner())
115
+ except:pass
@@ -3,6 +3,9 @@ from typing import Union, Callable, Awaitable
3
3
  import re
4
4
 
5
5
 
6
+
7
+
8
+
6
9
  class Filter:
7
10
  def __init__(self, func: Callable[[Union[Update, InlineMessage]], Union[bool, Awaitable[bool]]]):
8
11
  self.func = func
@@ -1,159 +0,0 @@
1
- from __future__ import annotations
2
- from typing import Optional, Callable, Literal
3
- from aiohttp import web
4
- from functools import wraps
5
- from rubigram.models import Update, InlineMessage
6
- from rubigram.method import Method
7
- from rubigram.filters import Filter
8
- from rubigram.state import StateManager
9
- from datetime import datetime
10
- import asyncio
11
- import logging
12
-
13
-
14
- logger = logging.getLogger(__name__)
15
-
16
-
17
- class Client(Method):
18
- def __init__(self, token: str, endpoint: Optional[str] = None, host: str = "0.0.0.0", port: int = 8000):
19
- self.token = token
20
- self.endpoint = endpoint
21
- self.host = host
22
- self.port = port
23
- self.offset_id = None
24
- self.state = StateManager()
25
- self.routes = web.RouteTableDef()
26
- self.message_handlers = []
27
- self.inline_handlers = []
28
- super().__init__(token)
29
-
30
- def on_message(self, *filters: Filter):
31
- def decorator(func: Callable) -> Callable:
32
- @wraps(func)
33
- async def wrapper(client: Client, update: Update):
34
- try:
35
- combined_filter = filters[0] if filters else None
36
- for filter in filters[1:]:
37
- combined_filter = combined_filter & filter
38
-
39
- if combined_filter is None or await combined_filter(update):
40
- await func(client, update)
41
- return True
42
- return False
43
- except Exception as error:
44
- logger.exception("Error {}: {}".format(func.__name__, error))
45
-
46
- self.message_handlers.append(wrapper)
47
- return func
48
- return decorator
49
-
50
- def on_inline_message(self, *filters: Filter):
51
- def decorator(func: Callable) -> Callable:
52
- @wraps(func)
53
- async def wrapper(client: Client, update: InlineMessage):
54
- try:
55
- combined_filter = filters[0] if filters else None
56
- for filter in filters[1:]:
57
- combined_filter = combined_filter & filter
58
-
59
- if combined_filter is None or await combined_filter(update):
60
- await func(client, update)
61
- return True
62
- return False
63
- except Exception as error:
64
- logger.exception("Error {}: {}".format(func.__name__, error))
65
-
66
- self.inline_handlers.append(wrapper)
67
- return func
68
- return decorator
69
-
70
- async def dispatch(self, update: Update, type: Literal["update", "inline_message"] = "update"):
71
- handlers = self.message_handlers if type == "update" else self.inline_handlers
72
- for handler in handlers:
73
- try:
74
- matched = await handler(self, update)
75
- if matched:
76
- return
77
- except Exception as error:
78
- logger.exception(f"Dispatch Error in handler [ {handler.__name__} ] : {error}")
79
-
80
- async def updater(self, data: dict):
81
- if "inline_message" in data:
82
- event = InlineMessage.from_dict(data.get("inline_message", {}))
83
- event.client = self
84
- await self.dispatch(event, "inline_message")
85
- elif "update" in data:
86
- event = Update.from_dict(data.get("update", {}))
87
- event.client = self
88
- await self.dispatch(event)
89
- else:
90
- return
91
-
92
- async def set_endpoints(self):
93
- if self.endpoint:
94
- await self.update_bot_endpoint(f"{self.endpoint}/ReceiveUpdate", "ReceiveUpdate")
95
- await self.update_bot_endpoint(f"{self.endpoint}/ReceiveInlineMessage", "ReceiveInlineMessage")
96
-
97
- def run(self):
98
- if self.endpoint:
99
- @self.routes.post("/ReceiveUpdate")
100
- async def receive_update(request: web.Request):
101
- data = await request.json()
102
- await self.updater(data)
103
- return web.json_response({"status": "OK"})
104
-
105
- @self.routes.post("/ReceiveInlineMessage")
106
- async def receive_inline_message(request: web.Request):
107
- data = await request.json()
108
- await self.updater(data)
109
- return web.json_response({"status": "OK"})
110
-
111
- app = web.Application()
112
- app.add_routes(self.routes)
113
-
114
- async def on_startup(app):
115
- await self.set_endpoints()
116
- await self.state.start()
117
- await self.start()
118
-
119
- async def on_cleanup(app):
120
- await self.state.stop()
121
- await self.stop()
122
-
123
- app.on_startup.append(on_startup)
124
- app.on_cleanup.append(on_cleanup)
125
- web.run_app(app, host=self.host, port=self.port)
126
-
127
- else:
128
- async def polling():
129
- try:
130
- await self.state.start()
131
- while True:
132
- try:
133
- get_update = await self.get_update(100, self.offset_id)
134
- if get_update.updates:
135
- updates = get_update.updates
136
- for update in updates:
137
- if update.type == "NewMessage":
138
- message_time = int(update.new_message.time)
139
- elif update.type == "UpdatedMessage":
140
- message_time = int(update.updated_message.time)
141
- else:continue
142
-
143
- now = int(datetime.now().timestamp())
144
- if message_time >= now or message_time + 2 >= now:
145
- if isinstance(update, Update):
146
- update.client = self
147
- await self.dispatch(update)
148
-
149
- self.offset_id = get_update.next_offset_id
150
- except Exception as error:
151
- logger.exception("Polling Error : {}".format(error))
152
- await asyncio.sleep(1)
153
-
154
- except:
155
- pass
156
- finally:
157
- await self.state.stop()
158
- await self.stop()
159
- asyncio.run(polling())
File without changes
File without changes