RubigramClient 1.6.6__tar.gz → 1.6.8__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.
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/PKG-INFO +22 -2
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/README.md +21 -1
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/RubigramClient.egg-info/PKG-INFO +22 -2
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/RubigramClient.egg-info/SOURCES.txt +3 -1
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/pyproject.toml +1 -1
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/rubigram/__init__.py +1 -0
- rubigramclient-1.6.8/rubigram/client.py +160 -0
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/rubigram/enums.py +9 -1
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/rubigram/method.py +75 -21
- rubigramclient-1.6.8/rubigram/network.py +81 -0
- rubigramclient-1.6.8/rubigram/rubino/__init__.py +1 -0
- rubigramclient-1.6.8/rubigram/rubino/client.py +82 -0
- rubigramclient-1.6.8/rubigram/types.py +979 -0
- rubigramclient-1.6.6/rubigram/client.py +0 -130
- rubigramclient-1.6.6/rubigram/network.py +0 -65
- rubigramclient-1.6.6/rubigram/types.py +0 -420
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/LICENSE +0 -0
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/RubigramClient.egg-info/dependency_links.txt +0 -0
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/RubigramClient.egg-info/requires.txt +0 -0
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/RubigramClient.egg-info/top_level.txt +0 -0
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/rubigram/filters.py +0 -0
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/rubigram/state.py +0 -0
- {rubigramclient-1.6.6 → rubigramclient-1.6.8}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: RubigramClient
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.8
|
|
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 <MrJavad.Email@gmail.com>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -31,7 +31,8 @@ bot = Client(token="YOUR_TOKEN_BOT")
|
|
|
31
31
|
|
|
32
32
|
@bot.on_message(filters.private)
|
|
33
33
|
async def welcome_message(client, message: Update):
|
|
34
|
-
await message.reply("Hi, WELCOME TO RUBIGRAM")
|
|
34
|
+
send = await message.reply("Hi, WELCOME TO RUBIGRAM")
|
|
35
|
+
await send.edit_text("message was edited")
|
|
35
36
|
|
|
36
37
|
bot.run()
|
|
37
38
|
```
|
|
@@ -84,3 +85,22 @@ async def main():
|
|
|
84
85
|
|
|
85
86
|
asyncio.run(main())
|
|
86
87
|
```
|
|
88
|
+
|
|
89
|
+
## Implementation of multiple programs
|
|
90
|
+
```python
|
|
91
|
+
from rubigram import Client
|
|
92
|
+
import asyncio
|
|
93
|
+
|
|
94
|
+
tokens = [
|
|
95
|
+
"TOKEN_1",
|
|
96
|
+
"TOKEN_2"
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
async def main():
|
|
100
|
+
for token in tokens:
|
|
101
|
+
async with Client(token) as bot:
|
|
102
|
+
get_me = await bot.get_me()
|
|
103
|
+
print(get_me.asjson())
|
|
104
|
+
|
|
105
|
+
asyncio.run(main())
|
|
106
|
+
```
|
|
@@ -15,7 +15,8 @@ bot = Client(token="YOUR_TOKEN_BOT")
|
|
|
15
15
|
|
|
16
16
|
@bot.on_message(filters.private)
|
|
17
17
|
async def welcome_message(client, message: Update):
|
|
18
|
-
await message.reply("Hi, WELCOME TO RUBIGRAM")
|
|
18
|
+
send = await message.reply("Hi, WELCOME TO RUBIGRAM")
|
|
19
|
+
await send.edit_text("message was edited")
|
|
19
20
|
|
|
20
21
|
bot.run()
|
|
21
22
|
```
|
|
@@ -66,5 +67,24 @@ async def main():
|
|
|
66
67
|
data = await bot.get_me()
|
|
67
68
|
print(data.bot_id)
|
|
68
69
|
|
|
70
|
+
asyncio.run(main())
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Implementation of multiple programs
|
|
74
|
+
```python
|
|
75
|
+
from rubigram import Client
|
|
76
|
+
import asyncio
|
|
77
|
+
|
|
78
|
+
tokens = [
|
|
79
|
+
"TOKEN_1",
|
|
80
|
+
"TOKEN_2"
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
async def main():
|
|
84
|
+
for token in tokens:
|
|
85
|
+
async with Client(token) as bot:
|
|
86
|
+
get_me = await bot.get_me()
|
|
87
|
+
print(get_me.asjson())
|
|
88
|
+
|
|
69
89
|
asyncio.run(main())
|
|
70
90
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: RubigramClient
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.8
|
|
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 <MrJavad.Email@gmail.com>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -31,7 +31,8 @@ bot = Client(token="YOUR_TOKEN_BOT")
|
|
|
31
31
|
|
|
32
32
|
@bot.on_message(filters.private)
|
|
33
33
|
async def welcome_message(client, message: Update):
|
|
34
|
-
await message.reply("Hi, WELCOME TO RUBIGRAM")
|
|
34
|
+
send = await message.reply("Hi, WELCOME TO RUBIGRAM")
|
|
35
|
+
await send.edit_text("message was edited")
|
|
35
36
|
|
|
36
37
|
bot.run()
|
|
37
38
|
```
|
|
@@ -84,3 +85,22 @@ async def main():
|
|
|
84
85
|
|
|
85
86
|
asyncio.run(main())
|
|
86
87
|
```
|
|
88
|
+
|
|
89
|
+
## Implementation of multiple programs
|
|
90
|
+
```python
|
|
91
|
+
from rubigram import Client
|
|
92
|
+
import asyncio
|
|
93
|
+
|
|
94
|
+
tokens = [
|
|
95
|
+
"TOKEN_1",
|
|
96
|
+
"TOKEN_2"
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
async def main():
|
|
100
|
+
for token in tokens:
|
|
101
|
+
async with Client(token) as bot:
|
|
102
|
+
get_me = await bot.get_me()
|
|
103
|
+
print(get_me.asjson())
|
|
104
|
+
|
|
105
|
+
asyncio.run(main())
|
|
106
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "RubigramClient"
|
|
3
|
-
version = "1.6.
|
|
3
|
+
version = "1.6.8"
|
|
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,160 @@
|
|
|
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
|
|
7
|
+
from aiohttp.web import Application, Request, json_response, run_app
|
|
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
|
+
|
|
21
|
+
|
|
22
|
+
class Client(Method):
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
token: str,
|
|
26
|
+
endpoint: Optional[str] = None,
|
|
27
|
+
host: str = "0.0.0.0",
|
|
28
|
+
port: int = 8000
|
|
29
|
+
):
|
|
30
|
+
self.token = token
|
|
31
|
+
self.endpoint = endpoint
|
|
32
|
+
self.host = host
|
|
33
|
+
self.port = port
|
|
34
|
+
self.offset_id = None
|
|
35
|
+
self.set_endpoint = True
|
|
36
|
+
self.ROUTES = []
|
|
37
|
+
self.MESSAGE_HANDLER = []
|
|
38
|
+
self.INLINE_HANDLER = []
|
|
39
|
+
self.state = StateManager()
|
|
40
|
+
super().__init__(token)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def on_message(self, filters: Optional[Filter] = None):
|
|
44
|
+
def decorator(func: Callable) -> Callable:
|
|
45
|
+
async def wrapper(client: Client, update: Update):
|
|
46
|
+
if filters is None or await filters(update):
|
|
47
|
+
await func(client, update)
|
|
48
|
+
return True
|
|
49
|
+
return False
|
|
50
|
+
self.MESSAGE_HANDLER.append(wrapper)
|
|
51
|
+
return func
|
|
52
|
+
return decorator
|
|
53
|
+
|
|
54
|
+
def on_inline_message(self, filters: Optional[Filter] = None):
|
|
55
|
+
def decorator(func: Callable) -> Callable:
|
|
56
|
+
async def wrapper(client: Client, update: Update):
|
|
57
|
+
if filters is None or await filters(update):
|
|
58
|
+
await func(client, update)
|
|
59
|
+
return True
|
|
60
|
+
return False
|
|
61
|
+
self.INLINE_HANDLER.append(wrapper)
|
|
62
|
+
return func
|
|
63
|
+
return decorator
|
|
64
|
+
|
|
65
|
+
def on_create_app(self, path: str, method: str = "GET"):
|
|
66
|
+
def decorator(func):
|
|
67
|
+
self.ROUTES.append((path, func, method.upper()))
|
|
68
|
+
return func
|
|
69
|
+
return decorator
|
|
70
|
+
|
|
71
|
+
async def dispatch(self, update: Union[Update, InlineMessage]):
|
|
72
|
+
handlers = self.MESSAGE_HANDLER if isinstance(update, Update) else self.INLINE_HANDLER
|
|
73
|
+
for handler in handlers:
|
|
74
|
+
matched = await handler(self, update)
|
|
75
|
+
if matched:
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
async def updater(self, data: dict):
|
|
79
|
+
if "inline_message" in data:
|
|
80
|
+
event = InlineMessage.from_dict(data["inline_message"])
|
|
81
|
+
elif "update" in data:
|
|
82
|
+
event = Update.from_dict(data["update"])
|
|
83
|
+
else: return
|
|
84
|
+
event.client = self
|
|
85
|
+
await self.dispatch(event)
|
|
86
|
+
|
|
87
|
+
async def set_endpoints(self):
|
|
88
|
+
endpoint_type = ["ReceiveUpdate", "ReceiveInlineMessage"]
|
|
89
|
+
for i in endpoint_type:
|
|
90
|
+
set_endpoint = await self.update_bot_endpoint(f"{self.endpoint}/{i}", i)
|
|
91
|
+
logging.info(f"status set endpoint for {i} : {set_endpoint["status"]}")
|
|
92
|
+
|
|
93
|
+
async def on_startup(self, app):
|
|
94
|
+
if self.set_endpoint:
|
|
95
|
+
await self.set_endpoints()
|
|
96
|
+
await self.start()
|
|
97
|
+
|
|
98
|
+
async def on_cleanup(self, app):
|
|
99
|
+
await self.stop()
|
|
100
|
+
|
|
101
|
+
def create_request_handler(self):
|
|
102
|
+
async def wrapper(request: Request):
|
|
103
|
+
data = await request.json()
|
|
104
|
+
await self.updater(data)
|
|
105
|
+
return json_response({"status": "OK"})
|
|
106
|
+
return wrapper
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
async def update_runner(self):
|
|
110
|
+
try:
|
|
111
|
+
while True:
|
|
112
|
+
get_update = await self.get_update(100, self.offset_id)
|
|
113
|
+
updates = get_update.updates
|
|
114
|
+
if updates:
|
|
115
|
+
for update in updates:
|
|
116
|
+
time = update.new_message.time if update.type == "NewMessage" else update.updated_message.time if update.type == "UpdatedMessage" else None
|
|
117
|
+
time = int(time)
|
|
118
|
+
now = int(datetime.now().timestamp())
|
|
119
|
+
if time and (time >= now or time + 2 >= now):
|
|
120
|
+
update.client = self
|
|
121
|
+
await self.dispatch(update)
|
|
122
|
+
self.offset_id = get_update.next_offset_id
|
|
123
|
+
except Exception as error:
|
|
124
|
+
logging.error(error)
|
|
125
|
+
finally:
|
|
126
|
+
await self.stop()
|
|
127
|
+
|
|
128
|
+
def run(self, set_endpoint = True):
|
|
129
|
+
self.set_endpoint = set_endpoint
|
|
130
|
+
if self.endpoint:
|
|
131
|
+
app = Application()
|
|
132
|
+
app.on_startup(self.on_startup)
|
|
133
|
+
app.on_cleanup(self.on_cleanup)
|
|
134
|
+
|
|
135
|
+
app.router.add_post("/ReceiveUpdate", self.create_request_handler())
|
|
136
|
+
app.router.add_post("/ReceiveInlineMessage", self.create_request_handler())
|
|
137
|
+
|
|
138
|
+
for path, func, method in self.ROUTES:
|
|
139
|
+
match method:
|
|
140
|
+
case "GET":
|
|
141
|
+
app.router.add_get(path, func)
|
|
142
|
+
case "POST":
|
|
143
|
+
app.router.add_post(path, func)
|
|
144
|
+
case "DELETE":
|
|
145
|
+
app.router.add_delete(path, func)
|
|
146
|
+
case "PUT":
|
|
147
|
+
app.router.add_put(path, func)
|
|
148
|
+
case "PATCH":
|
|
149
|
+
app.router.add_patch(path, func)
|
|
150
|
+
|
|
151
|
+
run_app(app, host=self.host, port=self.port)
|
|
152
|
+
|
|
153
|
+
else:
|
|
154
|
+
try:
|
|
155
|
+
logging.info("Start Bot")
|
|
156
|
+
asyncio.run(self.update_runner())
|
|
157
|
+
except KeyboardInterrupt:
|
|
158
|
+
logging.info("Stop Bot")
|
|
159
|
+
except Exception as error:
|
|
160
|
+
logging.error(error)
|
|
@@ -126,4 +126,12 @@ class FileType(str, Enum):
|
|
|
126
126
|
Video = "Video"
|
|
127
127
|
Gif = "Gif"
|
|
128
128
|
Music = "Music"
|
|
129
|
-
Voice = "Voice"
|
|
129
|
+
Voice = "Voice"
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class ChatAction(str, Enum):
|
|
133
|
+
Typing = "Typing"
|
|
134
|
+
Uploading = "Uploading"
|
|
135
|
+
Recording = "Recording"
|
|
136
|
+
|
|
137
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from .network import Network
|
|
2
2
|
from rubigram import enums
|
|
3
|
-
from typing import Optional
|
|
3
|
+
from typing import Optional, Union
|
|
4
4
|
from rubigram.types import Bot, Chat, Keypad, MessageId, Updates, BotCommand
|
|
5
5
|
|
|
6
6
|
|
|
@@ -49,6 +49,21 @@ class Method(Network):
|
|
|
49
49
|
|
|
50
50
|
async def edit_message_text(self, chat_id: str, message_id: str, text: str):
|
|
51
51
|
await self.request("editMessageText", {"chat_id": chat_id, "message_id": message_id, "text": text})
|
|
52
|
+
|
|
53
|
+
async def edit_message(
|
|
54
|
+
self,
|
|
55
|
+
chat_id: str,
|
|
56
|
+
message_id: str,
|
|
57
|
+
text: Optional[str] = None,
|
|
58
|
+
chat_keypad: Optional[Keypad] = None,
|
|
59
|
+
inline_keypad: Optional[Keypad] = None
|
|
60
|
+
):
|
|
61
|
+
if text:
|
|
62
|
+
await self.edit_message_text(chat_id, message_id, text)
|
|
63
|
+
if chat_keypad:
|
|
64
|
+
await self.edit_chat_keypad(chat_id, chat_keypad)
|
|
65
|
+
if inline_keypad:
|
|
66
|
+
await self.edit_message_keypad(chat_id, message_id, inline_keypad)
|
|
52
67
|
|
|
53
68
|
async def forward_message(self, from_chat_id: str, message_id: str, to_chat_id: str, disable_notification: bool = False) -> "MessageId":
|
|
54
69
|
data = {"from_chat_id": from_chat_id, "message_id": message_id, "to_chat_id": to_chat_id, "disable_notification": disable_notification}
|
|
@@ -195,30 +210,31 @@ class Method(Network):
|
|
|
195
210
|
response = await self.request("requestSendFile", {"type": type})
|
|
196
211
|
return response["upload_url"]
|
|
197
212
|
|
|
198
|
-
async def upload_file(self, file: str, name: str, type: str):
|
|
213
|
+
async def upload_file(self, file: Union[str, bytes], name: Optional[str] = None, type: str = "File"):
|
|
199
214
|
upload_url = await self.request_send_file(type)
|
|
200
|
-
response = await self.
|
|
215
|
+
response = await self.requestUpload(upload_url, file, name)
|
|
201
216
|
return response
|
|
202
217
|
|
|
203
|
-
async def download_file(self, file_id: str,
|
|
218
|
+
async def download_file(self, file_id: str, filename: Optional[str] = None):
|
|
204
219
|
download_url = await self.get_file(file_id)
|
|
205
|
-
response = await self.
|
|
220
|
+
response = await self.requestDownload(download_url, filename)
|
|
206
221
|
return response
|
|
207
222
|
|
|
208
223
|
async def send_file(
|
|
209
224
|
self,
|
|
210
225
|
chat_id: str,
|
|
211
|
-
file: str,
|
|
212
|
-
|
|
213
|
-
|
|
226
|
+
file: Union[str, bytes],
|
|
227
|
+
caption: Optional[str] = None,
|
|
228
|
+
file_name: Optional[str] = None,
|
|
214
229
|
type: enums.FileType = enums.FileType.File,
|
|
215
230
|
chat_keypad: Keypad = None,
|
|
216
231
|
inline_keypad: Keypad = None,
|
|
217
232
|
chat_keypad_type: Optional[enums.ChatKeypadType] = None,
|
|
218
233
|
disable_notification: bool = False,
|
|
219
|
-
reply_to_message_id: str = None,
|
|
234
|
+
reply_to_message_id: Optional[str] = None,
|
|
220
235
|
) -> "MessageId":
|
|
221
236
|
file_id = await self.upload_file(file, file_name, type)
|
|
237
|
+
|
|
222
238
|
data = {
|
|
223
239
|
"chat_id": chat_id,
|
|
224
240
|
"file_id": file_id,
|
|
@@ -236,20 +252,58 @@ class Method(Network):
|
|
|
236
252
|
message.client = self
|
|
237
253
|
return message
|
|
238
254
|
|
|
239
|
-
async def send_document(self, chat_id: str, document: str, name: str, caption: str = None, **kwargs):
|
|
240
|
-
return await self.send_file(chat_id, document, name, caption, "File", **kwargs)
|
|
241
255
|
|
|
242
|
-
async def send_photo(self, chat_id: str, photo: str, name: str, caption: str = None, **kwargs):
|
|
243
|
-
return await self.send_file(chat_id, photo, name, caption, "Image", **kwargs)
|
|
244
256
|
|
|
245
|
-
async def
|
|
246
|
-
return await self.send_file(chat_id,
|
|
257
|
+
async def send_document(self, chat_id: str, document: Union[str, bytes], caption: Optional[str] = None, file_name: Optional[str] = None, **kwargs):
|
|
258
|
+
return await self.send_file(chat_id, document, caption, file_name, "File", **kwargs)
|
|
247
259
|
|
|
248
|
-
async def
|
|
249
|
-
return await self.send_file(chat_id,
|
|
260
|
+
async def send_photo(self, chat_id: str, photo: Union[str, bytes], caption: Optional[str] = None, file_name: Optional[str] = None, **kwargs):
|
|
261
|
+
return await self.send_file(chat_id, photo, caption, file_name, "Image", **kwargs)
|
|
250
262
|
|
|
251
|
-
async def
|
|
252
|
-
return await self.send_file(chat_id,
|
|
263
|
+
async def send_video(self, chat_id: str, video: Union[str, bytes], caption: Optional[str] = None, file_name: Optional[str] = None, **kwargs):
|
|
264
|
+
return await self.send_file(chat_id, video, caption, file_name, "Video", **kwargs)
|
|
265
|
+
|
|
266
|
+
async def send_gif(self, chat_id: str, gif: Union[str, bytes], caption: Optional[str] = None, file_name: Optional[str] = None, **kwargs):
|
|
267
|
+
return await self.send_file(chat_id, gif, caption, file_name, "Gif", **kwargs)
|
|
268
|
+
|
|
269
|
+
async def send_music(self, chat_id: str, music: Union[str, bytes], caption: Optional[str] = None, file_name: Optional[str] = None, **kwargs):
|
|
270
|
+
return await self.send_file(chat_id, music, caption, file_name, "Music", **kwargs)
|
|
271
|
+
|
|
272
|
+
async def send_voice(self, chat_id: str, voice: Union[str, bytes], caption: Optional[str] = None, file_name: Optional[str] = None, **kwargs):
|
|
273
|
+
return await self.send_file(chat_id, voice, caption, file_name, "Voice", **kwargs)
|
|
274
|
+
|
|
275
|
+
# async def get_messages(self, chat_id: str, message_ids: Optional[list[str]] = None):
|
|
276
|
+
# return await self.request("getMessages", {"chat_id": chat_id, "message_ids": message_ids})
|
|
277
|
+
|
|
278
|
+
# async def get_bot_command(self):
|
|
279
|
+
# return await self.request("getBotCommands", {})
|
|
280
|
+
|
|
281
|
+
# async def send_chat_action(self, chat_id: str, action: enums.ChatAction):
|
|
282
|
+
# return await self.request("sendChatAction", {"chat_id": chat_id, "action": action})
|
|
283
|
+
|
|
284
|
+
# async def set_username(self, username: str):
|
|
285
|
+
# return await self.request("setUsername", {"username": username})
|
|
286
|
+
|
|
287
|
+
async def get_bot_name(self):
|
|
288
|
+
bot = await self.get_me()
|
|
289
|
+
return bot.bot_title
|
|
253
290
|
|
|
254
|
-
async def
|
|
255
|
-
|
|
291
|
+
async def get_bot_id(self):
|
|
292
|
+
bot = await self.get_me()
|
|
293
|
+
return bot.bot_id
|
|
294
|
+
|
|
295
|
+
async def get_bot_username(self):
|
|
296
|
+
bot = await self.get_me()
|
|
297
|
+
return bot.username
|
|
298
|
+
|
|
299
|
+
async def get_bot_share_url(self):
|
|
300
|
+
bot = await self.get_me()
|
|
301
|
+
return bot.share_url
|
|
302
|
+
|
|
303
|
+
async def get_bot_descriptionl(self):
|
|
304
|
+
bot = await self.get_me()
|
|
305
|
+
return bot.description
|
|
306
|
+
|
|
307
|
+
async def get_bot_start_messagel(self):
|
|
308
|
+
bot = await self.get_me()
|
|
309
|
+
return bot.start_message
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from aiohttp import ClientSession, FormData
|
|
2
|
+
from typing import Any, Optional, Union
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from urllib.parse import urlparse
|
|
5
|
+
from random import randint
|
|
6
|
+
import aiofiles
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Network:
|
|
11
|
+
def __init__(self, token: str) -> None:
|
|
12
|
+
self.token: str = token
|
|
13
|
+
self.session: Optional[ClientSession] = None
|
|
14
|
+
self.api: str = f"https://botapi.rubika.ir/v3/{token}/"
|
|
15
|
+
|
|
16
|
+
async def start(self):
|
|
17
|
+
if not self.session:
|
|
18
|
+
self.session = ClientSession()
|
|
19
|
+
|
|
20
|
+
async def stop(self):
|
|
21
|
+
if self.session:
|
|
22
|
+
await self.session.close()
|
|
23
|
+
self.session = None
|
|
24
|
+
|
|
25
|
+
async def __aenter__(self):
|
|
26
|
+
await self.start()
|
|
27
|
+
return self
|
|
28
|
+
|
|
29
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
30
|
+
await self.stop()
|
|
31
|
+
|
|
32
|
+
async def request(self, method: str, json: dict[str, Any]):
|
|
33
|
+
await self.start()
|
|
34
|
+
async with self.session.post(self.api + method, json=json) as response:
|
|
35
|
+
response.raise_for_status()
|
|
36
|
+
data: dict = await response.json()
|
|
37
|
+
return data.get("data")
|
|
38
|
+
|
|
39
|
+
async def getBytes(self, url: str) -> bytes:
|
|
40
|
+
await self.start()
|
|
41
|
+
async with self.session.get(url) as response:
|
|
42
|
+
response.raise_for_status()
|
|
43
|
+
return await response.read()
|
|
44
|
+
|
|
45
|
+
async def getName(self, url: str) -> str:
|
|
46
|
+
parser = urlparse(url)
|
|
47
|
+
return os.path.basename(parser.path)
|
|
48
|
+
|
|
49
|
+
async def requestUpload(self, upload_url: str, file: Union[str, bytes], name: Optional[str] = None):
|
|
50
|
+
data, filename = None, None
|
|
51
|
+
if isinstance(file, str):
|
|
52
|
+
path = Path(file)
|
|
53
|
+
|
|
54
|
+
if path.is_file():
|
|
55
|
+
data, filename = path.read_bytes(), name if name else path.name
|
|
56
|
+
|
|
57
|
+
elif file.startswith("http"):
|
|
58
|
+
data, filename = await self.getBytes(file), name if name else await self.getName(file)
|
|
59
|
+
|
|
60
|
+
else:
|
|
61
|
+
raise Exception(f"Can't find this file : {file}")
|
|
62
|
+
|
|
63
|
+
elif isinstance(file, bytes):
|
|
64
|
+
if name:
|
|
65
|
+
data, filename = file, name
|
|
66
|
+
else:
|
|
67
|
+
raise Exception("choice name for bytes file")
|
|
68
|
+
|
|
69
|
+
form = FormData()
|
|
70
|
+
form.add_field("file", data, filename=filename, content_type="application/octet-stream")
|
|
71
|
+
await self.start()
|
|
72
|
+
async with self.session.post(upload_url, data=form) as response:
|
|
73
|
+
response.raise_for_status()
|
|
74
|
+
data: dict = await response.json()
|
|
75
|
+
return data.get("data", {})["file_id"]
|
|
76
|
+
|
|
77
|
+
async def requestDownload(self, url: str, filename: Optional[str] = None):
|
|
78
|
+
file, name = await self.getBytes(url), filename if filename else await self.getName(url)
|
|
79
|
+
async with aiofiles.open(name, "wb") as f:
|
|
80
|
+
await f.write(file)
|
|
81
|
+
return name
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .client import Rubino
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from aiohttp import ClientSession
|
|
2
|
+
from typing import Literal, Optional, Union, Any
|
|
3
|
+
from random import randint
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Rubino:
|
|
7
|
+
def __init__(self, auth: str):
|
|
8
|
+
self.auth = auth
|
|
9
|
+
self.api = f"https://rubino{randint(1, 30)}.iranlms.ir"
|
|
10
|
+
self.client = {
|
|
11
|
+
"app_name": "Main",
|
|
12
|
+
"app_version": "3.0.2",
|
|
13
|
+
"lang_code": "fa",
|
|
14
|
+
"package": "app.rbmain.a",
|
|
15
|
+
"platform": "Android"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
async def reauest(self, method: str, data: dict[str, Any]):
|
|
20
|
+
json = {
|
|
21
|
+
"api_version": "0",
|
|
22
|
+
"auth": self.auth,
|
|
23
|
+
"client": self.client,
|
|
24
|
+
"data": data,
|
|
25
|
+
"method": method
|
|
26
|
+
}
|
|
27
|
+
async with ClientSession() as session:
|
|
28
|
+
async with session.post(self.api, json=json) as response:
|
|
29
|
+
response.raise_for_status()
|
|
30
|
+
return await response.json()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def get_post_by_share_link(self, post_link: str):
|
|
34
|
+
return await self.reauest("getPostByShareLink", {"share_string": post_link.split("/")[-1]})
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async def add_post_view_count(self, post_id: str, post_profile_id: str):
|
|
38
|
+
data = {"post_id": post_id, "post_profile_id": post_profile_id}
|
|
39
|
+
return await self.reauest("addPostViewCount", data)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
async def add_view_story(self, story_profile_id: str, story_ids: Union[str, list[str]], profile_id: Optional[str] = None):
|
|
43
|
+
story_ids = story_ids if isinstance(story_ids, list) else [story_ids]
|
|
44
|
+
data = {"story_profile_id": story_profile_id, "story_ids": story_ids, "profile_id": profile_id}
|
|
45
|
+
return await self.reauest("addViewStory", data)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
async def is_exist_username(self, username: str):
|
|
49
|
+
username = username.replace("@", "")
|
|
50
|
+
return await self.reauest("isExistUsername", {"username": username})
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
async def create_page(self, username: str, name: str, bio: Optional[str] = None):
|
|
54
|
+
return await self.reauest("createPage", {"username": username, "name": name, "bio": bio})
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
async def add_comment(self, content: str, post_id: str, post_profile_id: str, profile_id: Optional[str] = None):
|
|
58
|
+
rnd = randint(100000, 999999999)
|
|
59
|
+
data = {"content": content, "post_id": post_id, "post_profile_id": post_profile_id, "profile_id": profile_id, "rnd": rnd}
|
|
60
|
+
return await self.reauest("addComment", data)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
async def request_follow(self, followee_id: str, f_type: Literal["Follow", "Unfollow"] = "Follow", profile_id: Optional[str] = None):
|
|
64
|
+
data = {"f_type": f_type, "followee_id": followee_id, "profile_id": profile_id}
|
|
65
|
+
return self.reauest("requestFollow", data)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
async def set_block_profile(self, block_id: str, action: Literal["Block", "Unblock"] = "Block", profile_id: Optional[str] = None):
|
|
69
|
+
data = {"block_id": block_id, "action": action, "profile_id": profile_id}
|
|
70
|
+
return self.reauest("setBlockProfile", data)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
async def get_comments(self, post_id: str, post_profile_id: str, limit: Optional[int] = 100, profile_id: Optional[str] = None):
|
|
74
|
+
data = {
|
|
75
|
+
"post_id": post_id,
|
|
76
|
+
"post_profile_id": post_profile_id,
|
|
77
|
+
"limit": limit,
|
|
78
|
+
"profile_id": profile_id,
|
|
79
|
+
"equal": False,
|
|
80
|
+
"sort": "FromMax"
|
|
81
|
+
}
|
|
82
|
+
return await self.reauest("getComments", data)
|