RubigramClient 1.7.1__py3-none-any.whl → 1.7.3__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 +1 -5
- rubigram/client.py +102 -154
- rubigram/enums.py +4 -3
- rubigram/filters.py +600 -139
- rubigram/handler.py +24 -0
- rubigram/http.py +32 -0
- rubigram/logger.py +20 -0
- rubigram/method/__init__.py +18 -0
- rubigram/method/chat/__init__.py +10 -0
- rubigram/method/chat/get_chat.py +26 -0
- rubigram/method/chat/get_me.py +22 -0
- rubigram/method/chat/get_update.py +32 -0
- rubigram/method/decorator/__init__.py +19 -0
- rubigram/method/decorator/on_delete_message.py +37 -0
- rubigram/method/decorator/on_edit_message.py +37 -0
- rubigram/method/decorator/on_inline_message.py +40 -0
- rubigram/method/decorator/on_message.py +38 -0
- rubigram/method/decorator/on_start.py +30 -0
- rubigram/method/decorator/on_stop.py +29 -0
- rubigram/method/decorator/register.py +43 -0
- rubigram/method/file/__init__.py +32 -0
- rubigram/method/file/download_file.py +34 -0
- rubigram/method/file/get_bytes.py +25 -0
- rubigram/method/file/get_file.py +27 -0
- rubigram/method/file/get_file_name.py +29 -0
- rubigram/method/file/request_download_file.py +35 -0
- rubigram/method/file/request_send_file.py +28 -0
- rubigram/method/file/request_upload_file.py +62 -0
- rubigram/method/file/send_document.py +58 -0
- rubigram/method/file/send_file.py +78 -0
- rubigram/method/file/send_gif.py +58 -0
- rubigram/method/file/send_music.py +58 -0
- rubigram/method/file/send_photo.py +58 -0
- rubigram/method/file/send_video.py +58 -0
- rubigram/method/file/send_voice.py +55 -0
- rubigram/method/messages/__init__.py +29 -0
- rubigram/method/messages/delete_message.py +50 -0
- rubigram/method/messages/edit_chat_keypad.py +34 -0
- rubigram/method/messages/edit_message.py +41 -0
- rubigram/method/messages/edit_message_keypad.py +38 -0
- rubigram/method/messages/edit_message_text.py +34 -0
- rubigram/method/messages/forward_message.py +43 -0
- rubigram/method/messages/remove_chat_keypad.py +28 -0
- rubigram/method/messages/send_contact.py +74 -0
- rubigram/method/messages/send_location.py +70 -0
- rubigram/method/messages/send_message.py +67 -0
- rubigram/method/messages/send_poll.py +71 -0
- rubigram/method/messages/send_sticker.py +66 -0
- rubigram/method/network/__init__.py +7 -0
- rubigram/method/network/request.py +20 -0
- rubigram/method/setting/__init__.py +9 -0
- rubigram/method/setting/set_command.py +32 -0
- rubigram/method/setting/update_bot_endpoint.py +31 -0
- rubigram/method/utilities/__init__.py +11 -0
- rubigram/method/utilities/dispatch.py +25 -0
- rubigram/method/utilities/setup_endpoint.py +16 -0
- rubigram/method/utilities/updater.py +17 -0
- rubigram/rubino/client.py +16 -130
- rubigram/rubino/network.py +121 -0
- rubigram/state.py +14 -19
- rubigram/types/__init__.py +3 -0
- rubigram/types/messages.py +175 -0
- rubigram/types/object.py +112 -0
- rubigram/types/types.py +211 -0
- rubigram/types/updates.py +572 -0
- {rubigramclient-1.7.1.dist-info → rubigramclient-1.7.3.dist-info}/METADATA +4 -3
- rubigramclient-1.7.3.dist-info/RECORD +71 -0
- rubigram/method.py +0 -354
- rubigram/network.py +0 -80
- rubigram/types.py +0 -538
- rubigramclient-1.7.1.dist-info/RECORD +0 -15
- {rubigramclient-1.7.1.dist-info → rubigramclient-1.7.3.dist-info}/WHEEL +0 -0
- {rubigramclient-1.7.1.dist-info → rubigramclient-1.7.3.dist-info}/licenses/LICENSE +0 -0
- {rubigramclient-1.7.1.dist-info → rubigramclient-1.7.3.dist-info}/top_level.txt +0 -0
rubigram/__init__.py
CHANGED
rubigram/client.py
CHANGED
|
@@ -1,22 +1,11 @@
|
|
|
1
|
-
from
|
|
2
|
-
from
|
|
3
|
-
from
|
|
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.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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.
|
|
69
|
+
await self.setup_endpoints()
|
|
132
70
|
await self.start()
|
|
133
71
|
|
|
134
|
-
async def
|
|
72
|
+
async def cleanup(self, app):
|
|
73
|
+
await self.run_stop_app()
|
|
135
74
|
await self.stop()
|
|
136
|
-
|
|
137
|
-
def
|
|
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
|
-
|
|
149
|
-
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
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
update.
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
|
|
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(
|
|
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.
|
|
169
|
-
app.on_cleanup(self.
|
|
170
|
-
|
|
171
|
-
app.router.add_post("/ReceiveUpdate", self.
|
|
172
|
-
app.router.add_post("/ReceiveInlineMessage", self.
|
|
173
|
-
|
|
174
|
-
for path, func, method in self.
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
|
|
192
|
-
asyncio.run(self.
|
|
137
|
+
logger.info("[<] Start bot ...")
|
|
138
|
+
asyncio.run(self.run_polling())
|
|
139
|
+
|
|
193
140
|
except KeyboardInterrupt:
|
|
194
|
-
|
|
141
|
+
logger.info("[<] Stop bot")
|
|
142
|
+
|
|
195
143
|
except Exception as error:
|
|
196
|
-
|
|
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"
|