RubigramClient 1.7.0__py3-none-any.whl → 1.7.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.

Potentially problematic release.


This version of RubigramClient might be problematic. Click here for more details.

Files changed (74) hide show
  1. rubigram/__init__.py +1 -5
  2. rubigram/client.py +102 -154
  3. rubigram/enums.py +4 -3
  4. rubigram/filters.py +600 -139
  5. rubigram/handler.py +24 -0
  6. rubigram/http.py +32 -0
  7. rubigram/logger.py +20 -0
  8. rubigram/method/__init__.py +18 -0
  9. rubigram/method/chat/__init__.py +10 -0
  10. rubigram/method/chat/get_chat.py +26 -0
  11. rubigram/method/chat/get_me.py +22 -0
  12. rubigram/method/chat/get_update.py +32 -0
  13. rubigram/method/decorator/__init__.py +8 -0
  14. rubigram/method/decorator/on_delete_message.py +37 -0
  15. rubigram/method/decorator/on_edit_message.py +37 -0
  16. rubigram/method/decorator/on_inline_message.py +40 -0
  17. rubigram/method/decorator/on_message.py +38 -0
  18. rubigram/method/decorator/on_start.py +30 -0
  19. rubigram/method/decorator/on_stop.py +29 -0
  20. rubigram/method/decorator/register.py +43 -0
  21. rubigram/method/file/__init__.py +32 -0
  22. rubigram/method/file/download_file.py +34 -0
  23. rubigram/method/file/get_bytes.py +25 -0
  24. rubigram/method/file/get_file.py +27 -0
  25. rubigram/method/file/get_file_name.py +29 -0
  26. rubigram/method/file/request_download_file.py +35 -0
  27. rubigram/method/file/request_send_file.py +28 -0
  28. rubigram/method/file/request_upload_file.py +62 -0
  29. rubigram/method/file/send_document.py +58 -0
  30. rubigram/method/file/send_file.py +78 -0
  31. rubigram/method/file/send_gif.py +58 -0
  32. rubigram/method/file/send_music.py +58 -0
  33. rubigram/method/file/send_photo.py +58 -0
  34. rubigram/method/file/send_video.py +58 -0
  35. rubigram/method/file/send_voice.py +55 -0
  36. rubigram/method/messages/__init__.py +29 -0
  37. rubigram/method/messages/delete_message.py +50 -0
  38. rubigram/method/messages/edit_chat_keypad.py +34 -0
  39. rubigram/method/messages/edit_message.py +41 -0
  40. rubigram/method/messages/edit_message_keypad.py +38 -0
  41. rubigram/method/messages/edit_message_text.py +34 -0
  42. rubigram/method/messages/forward_message.py +43 -0
  43. rubigram/method/messages/remove_chat_keypad.py +28 -0
  44. rubigram/method/messages/send_contact.py +74 -0
  45. rubigram/method/messages/send_location.py +70 -0
  46. rubigram/method/messages/send_message.py +67 -0
  47. rubigram/method/messages/send_poll.py +71 -0
  48. rubigram/method/messages/send_sticker.py +66 -0
  49. rubigram/method/network/__init__.py +7 -0
  50. rubigram/method/network/request.py +20 -0
  51. rubigram/method/setting/__init__.py +9 -0
  52. rubigram/method/setting/set_command.py +32 -0
  53. rubigram/method/setting/update_bot_endpoint.py +31 -0
  54. rubigram/method/utilities/__init__.py +11 -0
  55. rubigram/method/utilities/dispatch.py +25 -0
  56. rubigram/method/utilities/setup_endpoint.py +16 -0
  57. rubigram/method/utilities/updater.py +17 -0
  58. rubigram/state.py +14 -19
  59. rubigram/types/__init__.py +3 -0
  60. rubigram/types/messages.py +175 -0
  61. rubigram/types/object.py +112 -0
  62. rubigram/types/types.py +211 -0
  63. rubigram/types/updates.py +572 -0
  64. {rubigramclient-1.7.0.dist-info → rubigramclient-1.7.2.dist-info}/METADATA +12 -8
  65. rubigramclient-1.7.2.dist-info/RECORD +68 -0
  66. rubigram/method.py +0 -354
  67. rubigram/network.py +0 -80
  68. rubigram/rubino/__init__.py +0 -1
  69. rubigram/rubino/client.py +0 -480
  70. rubigram/types.py +0 -538
  71. rubigramclient-1.7.0.dist-info/RECORD +0 -15
  72. {rubigramclient-1.7.0.dist-info → rubigramclient-1.7.2.dist-info}/WHEEL +0 -0
  73. {rubigramclient-1.7.0.dist-info → rubigramclient-1.7.2.dist-info}/licenses/LICENSE +0 -0
  74. {rubigramclient-1.7.0.dist-info → rubigramclient-1.7.2.dist-info}/top_level.txt +0 -0
rubigram/__init__.py CHANGED
@@ -1,6 +1,2 @@
1
1
  from .client import Client
2
- from .rubino import Rubino
3
- from .state import StateManager
4
- from . import enums
5
- from . import filters
6
- from . import types
2
+ from . import enums, types, filters
rubigram/client.py CHANGED
@@ -1,22 +1,11 @@
1
- from typing import Optional, Callable, Union
2
- from rubigram.types 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
1
+ from .method import Method
2
+ from .http import Http
3
+ from .handler import Handler
7
4
  from aiohttp.web import Application, Request, json_response, run_app
5
+ from datetime import datetime
6
+ from typing import Optional, Callable
7
+ from .logger import logger
8
8
  import asyncio
9
- import logging
10
-
11
-
12
- logging.basicConfig(
13
- format="%(asctime)s | %(levelname)s : %(message)s",
14
- datefmt="%Y-%m-%d %H:%M:%S",
15
- level=logging.DEBUG
16
- )
17
-
18
- logging.getLogger("asyncio").setLevel(logging.WARNING)
19
- logging.getLogger("aiohttp").setLevel(logging.WARNING)
20
9
 
21
10
 
22
11
  class Client(Method):
@@ -24,173 +13,132 @@ class Client(Method):
24
13
  self,
25
14
  token: str,
26
15
  endpoint: Optional[str] = None,
27
- host: str = "0.0.0.0",
28
- port: int = 8000
16
+ host: Optional[str] = "0.0.0.0",
17
+ port: Optional[int] = 8000,
18
+ timeout: Optional[float] = 30
29
19
  ):
30
20
  self.token = token
31
21
  self.endpoint = endpoint
32
22
  self.host = host
33
23
  self.port = port
24
+ self.timeout = timeout
34
25
  self.offset_id = None
26
+ self.http: Http = Http(timeout)
35
27
  self.set_endpoint = True
36
- self.ROUTES = []
37
- self.MESSAGE_HANDLER = []
38
- self.INLINE_HANDLER = []
39
- self.EDIT_HANDLER = []
40
- self.DELETE_HANDLER = []
41
- self.state = StateManager()
42
- super().__init__(token)
43
-
44
-
45
- def on_message(self, filters: Optional[Filter] = None):
46
- def decorator(func: Callable) -> Callable:
47
- async def wrapper(client: Client, update: Update):
48
- if filters is None or await filters(update):
49
- await func(client, update)
50
- return True
51
- return False
52
- self.MESSAGE_HANDLER.append(wrapper)
53
- return func
54
- return decorator
55
-
56
- def on_inline_message(self, filters: Optional[Filter] = None):
57
- def decorator(func: Callable) -> Callable:
58
- async def wrapper(client: Client, update: Update):
59
- if filters is None or await filters(update):
60
- await func(client, update)
61
- return True
62
- return False
63
- self.INLINE_HANDLER.append(wrapper)
64
- return func
65
- return decorator
66
-
67
- def on_edit_message(self, filters: Optional[Filter] = None):
68
- def decorator(func: Callable) -> Callable:
69
- async def wrapper(client: Client, update: Update):
70
- if filters is None or await filters(update):
71
- await func(client, update)
72
- return True
73
- return False
74
- self.EDIT_HANDLER.append(wrapper)
75
- return func
76
- return decorator
77
-
78
- def on_delete_message(self, filters: Optional[Filter] = None):
79
- def decorator(func: Callable) -> Callable:
80
- async def wrapper(client: Client, update: Update):
81
- if filters is None or await filters(update):
82
- await func(client, update)
83
- return True
84
- return False
85
- self.DELETE_HANDLER.append(wrapper)
86
- return func
87
- return decorator
88
-
89
- def on_create_app(self, path: str, method: str = "GET"):
90
- def decorator(func):
91
- self.ROUTES.append((path, func, method.upper()))
92
- return func
93
- return decorator
94
-
95
- async def dispatch(self, update: Union[Update, InlineMessage]):
96
- if isinstance(update, InlineMessage):
97
- handlers = self.INLINE_HANDLER
98
- else:
99
- type = update.type
100
- if type == "NewMessage":
101
- handlers = self.MESSAGE_HANDLER
102
- elif type == "UpdatedMessage":
103
- handlers = self.EDIT_HANDLER
104
- elif type == "RemovedMessage":
105
- handlers = self.DELETE_HANDLER
106
- else:
107
- logging.warning("Update type invalid : {}".format(type))
108
-
109
- for handler in handlers:
110
- matched = await handler(self, update)
111
- if matched:
112
- return
113
-
114
- async def updater(self, data: dict):
115
- if "inline_message" in data:
116
- event = InlineMessage.from_dict(data["inline_message"])
117
- elif "update" in data:
118
- event = Update.from_dict(data["update"])
119
- else: return
120
- event.client = self
121
- await self.dispatch(event)
122
-
123
- async def set_endpoints(self):
124
- endpoint_type = ["ReceiveUpdate", "ReceiveInlineMessage"]
125
- for i in endpoint_type:
126
- set_endpoint = await self.update_bot_endpoint(f"{self.endpoint}/{i}", i)
127
- logging.info(f"status set endpoint for {i} : {set_endpoint["status"]}")
128
-
129
- async def on_startup(self, app):
28
+ self.handlers: dict[str, list[Handler]] = {
29
+ "message": [],
30
+ "inline": [],
31
+ "delete": [],
32
+ "edit": [],
33
+ }
34
+ self.on_start_app: list[Callable] = []
35
+ self.on_stop_app: list[Callable] = []
36
+ self.routes = []
37
+ super().__init__(self)
38
+
39
+ async def start(self):
40
+ await self.http.connect()
41
+
42
+ async def stop(self):
43
+ await self.http.disconnect()
44
+
45
+ async def __aenter__(self):
46
+ await self.start()
47
+ return self
48
+
49
+ async def __aexit__(self, *args):
50
+ await self.stop()
51
+
52
+ async def run_start_app(self):
53
+ for func in self.on_start_app:
54
+ try:
55
+ await func(self)
56
+ except Exception as error:
57
+ logger.error("[!] On Start App Error : {}".format(error))
58
+
59
+ async def run_stop_app(self):
60
+ for func in self.on_stop_app:
61
+ try:
62
+ await func(self)
63
+ except Exception as error:
64
+ logger.error("[!] On Stop App Error : {}".format(error))
65
+
66
+ async def startup(self, app):
67
+ await self.run_start_app()
130
68
  if self.set_endpoint:
131
- await self.set_endpoints()
69
+ await self.setup_endpoints()
132
70
  await self.start()
133
71
 
134
- async def on_cleanup(self, app):
72
+ async def cleanup(self, app):
73
+ await self.run_stop_app()
135
74
  await self.stop()
136
-
137
- def create_request_handler(self):
75
+
76
+ def request_handler(self):
138
77
  async def wrapper(request: Request):
139
78
  data = await request.json()
140
79
  await self.updater(data)
141
80
  return json_response({"status": "OK"})
142
81
  return wrapper
143
82
 
144
-
145
- async def update_runner(self):
83
+ async def run_polling(self):
146
84
  try:
85
+ await self.run_start_app()
86
+ await self.start()
147
87
  while True:
148
- get_update = await self.get_update(100, self.offset_id)
149
- updates = get_update.updates
88
+ response = await self.get_updates(100, self.offset_id)
89
+ updates = response.updates
90
+
150
91
  if updates:
151
92
  for update in updates:
152
- time = update.new_message.time if update.type == "NewMessage" else update.updated_message.time if update.type == "UpdatedMessage" else None
153
- time = int(time)
154
- now = int(datetime.now().timestamp())
155
- if time and (time >= now or time + 2 >= now):
156
- update.client = self
157
- await self.dispatch(update)
158
- self.offset_id = get_update.next_offset_id
93
+ message_time = (
94
+ update.new_message.time
95
+ if update.type == "NewMessage"
96
+ else update.updated_message.time
97
+ if update.type == "UpdatedMessage"
98
+ else None
99
+ )
100
+
101
+ if message_time:
102
+ now = int(datetime.now().timestamp())
103
+ if int(message_time) + 2 >= now:
104
+ update.client = self
105
+ await self.dispatch(update)
106
+
107
+ self.offset_id = response.next_offset_id
108
+
159
109
  except Exception as error:
160
- logging.error(error)
110
+ logger.error("[!] {} : {}".format(__class__.__name__, error))
111
+
161
112
  finally:
113
+ await self.run_stop_app()
162
114
  await self.stop()
163
-
164
- def run(self, set_endpoint = True):
115
+
116
+ def run(
117
+ self,
118
+ set_endpoint: Optional[bool] = True
119
+ ):
165
120
  self.set_endpoint = set_endpoint
166
121
  if self.endpoint:
167
122
  app = Application()
168
- app.on_startup(self.on_startup)
169
- app.on_cleanup(self.on_cleanup)
170
-
171
- app.router.add_post("/ReceiveUpdate", self.create_request_handler())
172
- app.router.add_post("/ReceiveInlineMessage", self.create_request_handler())
173
-
174
- for path, func, method in self.ROUTES:
175
- match method:
176
- case "GET":
177
- app.router.add_get(path, func)
178
- case "POST":
179
- app.router.add_post(path, func)
180
- case "DELETE":
181
- app.router.add_delete(path, func)
182
- case "PUT":
183
- app.router.add_put(path, func)
184
- case "PATCH":
185
- app.router.add_patch(path, func)
186
-
123
+ app.on_startup.append(self.startup)
124
+ app.on_cleanup.append(self.cleanup)
125
+
126
+ app.router.add_post("/ReceiveUpdate", self.request_handler())
127
+ app.router.add_post("/ReceiveInlineMessage", self.request_handler())
128
+
129
+ for path, func, method in self.routes:
130
+ app.router.add_route(method, path, func)
131
+
132
+ logger.info("[<] Start bot on {}:{}".format(self.host, self.port))
187
133
  run_app(app, host=self.host, port=self.port)
188
134
 
189
135
  else:
190
136
  try:
191
- logging.info("Start Bot")
192
- asyncio.run(self.update_runner())
137
+ logger.info("[<] Start bot ...")
138
+ asyncio.run(self.run_polling())
139
+
193
140
  except KeyboardInterrupt:
194
- logging.info("Stop Bot")
141
+ logger.info("[<] Stop bot")
142
+
195
143
  except Exception as error:
196
- logging.error(error)
144
+ logger.error("[!] Unexpected error : {}".format(error))
rubigram/enums.py CHANGED
@@ -69,6 +69,7 @@ class ButtonLinkType(str, Enum):
69
69
  joinchannel = "joinchannel"
70
70
  url = "url"
71
71
 
72
+
72
73
  class MessageSender(str, Enum):
73
74
  User = "User"
74
75
  Bot = "Bot"
@@ -94,7 +95,7 @@ class UpdateEndpointType(str, Enum):
94
95
  ReceiveQuery = "ReceiveQuery"
95
96
  GetSelectionItem = "GetSelectionItem"
96
97
  SearchSelectionItems = "SearchSelectionItems"
97
-
98
+
98
99
 
99
100
  class ButtonType(str, Enum):
100
101
  Simple = "Simple"
@@ -118,7 +119,7 @@ class ButtonType(str, Enum):
118
119
  AskMyPhoneNumber = "AskMyPhoneNumber"
119
120
  AskLocation = "AskLocation"
120
121
  Barcode = "Barcode"
121
-
122
+
122
123
 
123
124
  class FileType(str, Enum):
124
125
  File = "File"
@@ -127,7 +128,7 @@ class FileType(str, Enum):
127
128
  Gif = "Gif"
128
129
  Music = "Music"
129
130
  Voice = "Voice"
130
-
131
+
131
132
 
132
133
  class ChatAction(str, Enum):
133
134
  Typing = "Typing"