MartMeet 0.1.0__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.
- martmeet-0.1.0/MartMeet.egg-info/PKG-INFO +22 -0
- martmeet-0.1.0/MartMeet.egg-info/SOURCES.txt +14 -0
- martmeet-0.1.0/MartMeet.egg-info/dependency_links.txt +1 -0
- martmeet-0.1.0/MartMeet.egg-info/requires.txt +1 -0
- martmeet-0.1.0/MartMeet.egg-info/top_level.txt +1 -0
- martmeet-0.1.0/PKG-INFO +22 -0
- martmeet-0.1.0/README.md +12 -0
- martmeet-0.1.0/martmeet/__init__.py +11 -0
- martmeet-0.1.0/martmeet/bot.py +149 -0
- martmeet-0.1.0/martmeet/client.py +65 -0
- martmeet-0.1.0/martmeet/exceptions.py +8 -0
- martmeet-0.1.0/martmeet/handlers.py +13 -0
- martmeet-0.1.0/martmeet/types.py +98 -0
- martmeet-0.1.0/martmeet/utils.py +12 -0
- martmeet-0.1.0/pyproject.toml +22 -0
- martmeet-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: MartMeet
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python library for building bots
|
|
5
|
+
Author: MartMeet
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: requests>=2.28.0
|
|
10
|
+
|
|
11
|
+
# MartMeet
|
|
12
|
+
|
|
13
|
+
### Async Python Framework for codemeet Messenger Bots
|
|
14
|
+
|
|
15
|
+
MartMeet is an asynchronous Python framework for building bots for CodeMeet Messenger.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
Install MartMeet using pip:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install MartMeet
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
MartMeet.egg-info/PKG-INFO
|
|
4
|
+
MartMeet.egg-info/SOURCES.txt
|
|
5
|
+
MartMeet.egg-info/dependency_links.txt
|
|
6
|
+
MartMeet.egg-info/requires.txt
|
|
7
|
+
MartMeet.egg-info/top_level.txt
|
|
8
|
+
martmeet/__init__.py
|
|
9
|
+
martmeet/bot.py
|
|
10
|
+
martmeet/client.py
|
|
11
|
+
martmeet/exceptions.py
|
|
12
|
+
martmeet/handlers.py
|
|
13
|
+
martmeet/types.py
|
|
14
|
+
martmeet/utils.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests>=2.28.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
martmeet
|
martmeet-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: MartMeet
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python library for building bots
|
|
5
|
+
Author: MartMeet
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: requests>=2.28.0
|
|
10
|
+
|
|
11
|
+
# MartMeet
|
|
12
|
+
|
|
13
|
+
### Async Python Framework for codemeet Messenger Bots
|
|
14
|
+
|
|
15
|
+
MartMeet is an asynchronous Python framework for building bots for CodeMeet Messenger.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
Install MartMeet using pip:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install MartMeet
|
martmeet-0.1.0/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import inspect
|
|
3
|
+
|
|
4
|
+
from .client import Client
|
|
5
|
+
from .types import Message
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Bot:
|
|
9
|
+
def __init__(self, token):
|
|
10
|
+
if not token:
|
|
11
|
+
raise ValueError("Bot token is required")
|
|
12
|
+
|
|
13
|
+
self.token = token
|
|
14
|
+
self.client = Client(token)
|
|
15
|
+
|
|
16
|
+
self._commands = {}
|
|
17
|
+
self._texts = {}
|
|
18
|
+
self._message_handlers = []
|
|
19
|
+
|
|
20
|
+
self._offset = None
|
|
21
|
+
self._running = False
|
|
22
|
+
|
|
23
|
+
def command(self, command):
|
|
24
|
+
def decorator(function):
|
|
25
|
+
self._commands[command] = function
|
|
26
|
+
return function
|
|
27
|
+
|
|
28
|
+
return decorator
|
|
29
|
+
|
|
30
|
+
def text(self, text):
|
|
31
|
+
def decorator(function):
|
|
32
|
+
self._texts[text] = function
|
|
33
|
+
return function
|
|
34
|
+
|
|
35
|
+
return decorator
|
|
36
|
+
|
|
37
|
+
def message(self):
|
|
38
|
+
def decorator(function):
|
|
39
|
+
self._message_handlers.append(function)
|
|
40
|
+
return function
|
|
41
|
+
|
|
42
|
+
return decorator
|
|
43
|
+
|
|
44
|
+
def send_message(self, chat_id, text):
|
|
45
|
+
return self.client.send_message(
|
|
46
|
+
chat_id,
|
|
47
|
+
text
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
async def _call_handler(self, handler, message):
|
|
51
|
+
result = handler(message)
|
|
52
|
+
|
|
53
|
+
if inspect.isawaitable(result):
|
|
54
|
+
await result
|
|
55
|
+
|
|
56
|
+
async def _process_update(self, update):
|
|
57
|
+
if not isinstance(update, dict):
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
message_data = update.get("message")
|
|
61
|
+
|
|
62
|
+
if not message_data:
|
|
63
|
+
return
|
|
64
|
+
|
|
65
|
+
# مهم: خود Bot را به Message میدهیم
|
|
66
|
+
message = Message(
|
|
67
|
+
message_data,
|
|
68
|
+
bot=self
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
text = message.text or ""
|
|
72
|
+
|
|
73
|
+
if text.startswith("/"):
|
|
74
|
+
command = text.split()[0]
|
|
75
|
+
|
|
76
|
+
handler = self._commands.get(command)
|
|
77
|
+
|
|
78
|
+
if handler:
|
|
79
|
+
await self._call_handler(
|
|
80
|
+
handler,
|
|
81
|
+
message
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
handler = self._texts.get(text)
|
|
85
|
+
|
|
86
|
+
if handler:
|
|
87
|
+
await self._call_handler(
|
|
88
|
+
handler,
|
|
89
|
+
message
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
for handler in self._message_handlers:
|
|
93
|
+
await self._call_handler(
|
|
94
|
+
handler,
|
|
95
|
+
message
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
async def _polling(self):
|
|
99
|
+
self._running = True
|
|
100
|
+
|
|
101
|
+
print("[MartMeet 0.1.0] Running...")
|
|
102
|
+
|
|
103
|
+
while self._running:
|
|
104
|
+
try:
|
|
105
|
+
result = self.client.get_updates(
|
|
106
|
+
offset=self._offset
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
updates = []
|
|
110
|
+
|
|
111
|
+
if isinstance(result, dict):
|
|
112
|
+
updates = result.get(
|
|
113
|
+
"result",
|
|
114
|
+
[]
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
for update in updates:
|
|
118
|
+
update_id = update.get(
|
|
119
|
+
"update_id"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
if update_id is not None:
|
|
123
|
+
self._offset = update_id + 1
|
|
124
|
+
|
|
125
|
+
await self._process_update(
|
|
126
|
+
update
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
except Exception as error:
|
|
130
|
+
print(
|
|
131
|
+
f"[MartMeet] Error: {error}"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
await asyncio.sleep(2)
|
|
135
|
+
|
|
136
|
+
def stop(self):
|
|
137
|
+
self._running = False
|
|
138
|
+
|
|
139
|
+
def run(self):
|
|
140
|
+
try:
|
|
141
|
+
asyncio.run(
|
|
142
|
+
self._polling()
|
|
143
|
+
)
|
|
144
|
+
except KeyboardInterrupt:
|
|
145
|
+
self.stop()
|
|
146
|
+
|
|
147
|
+
print(
|
|
148
|
+
"[MartMeet 0.1.0] Stopped."
|
|
149
|
+
)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
BASE_URL = "https://botapi.codemeet.chat"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class APIError(Exception):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Client:
|
|
12
|
+
def __init__(self, token):
|
|
13
|
+
self.token = token
|
|
14
|
+
self.base_url = f"{BASE_URL}/bot{token}"
|
|
15
|
+
|
|
16
|
+
def request(self, method, params=None, timeout=30):
|
|
17
|
+
url = f"{self.base_url}/{method}"
|
|
18
|
+
|
|
19
|
+
response = requests.post(
|
|
20
|
+
url,
|
|
21
|
+
json=params or {},
|
|
22
|
+
timeout=timeout
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
data = response.json()
|
|
27
|
+
except ValueError:
|
|
28
|
+
raise APIError(
|
|
29
|
+
f"Invalid API response: {response.text}"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
if response.status_code >= 400:
|
|
33
|
+
raise APIError(
|
|
34
|
+
data.get("description", response.text)
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
if isinstance(data, dict) and data.get("ok") is False:
|
|
38
|
+
raise APIError(
|
|
39
|
+
data.get("description", "API request failed")
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
return data
|
|
43
|
+
|
|
44
|
+
def get_updates(self, offset=None, timeout=30):
|
|
45
|
+
params = {
|
|
46
|
+
"timeout": timeout
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if offset is not None:
|
|
50
|
+
params["offset"] = offset
|
|
51
|
+
|
|
52
|
+
return self.request(
|
|
53
|
+
"getUpdates",
|
|
54
|
+
params=params,
|
|
55
|
+
timeout=timeout + 5
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def send_message(self, chat_id, text):
|
|
59
|
+
return self.request(
|
|
60
|
+
"sendMessage",
|
|
61
|
+
{
|
|
62
|
+
"chat_id": chat_id,
|
|
63
|
+
"text": text
|
|
64
|
+
}
|
|
65
|
+
)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class Handler:
|
|
2
|
+
def __init__(self):
|
|
3
|
+
self.handlers = []
|
|
4
|
+
|
|
5
|
+
def add(self, function, handler_type=None, value=None):
|
|
6
|
+
self.handlers.append({
|
|
7
|
+
"function": function,
|
|
8
|
+
"type": handler_type,
|
|
9
|
+
"value": value
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
def get_all(self):
|
|
13
|
+
return self.handlers
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
class User:
|
|
2
|
+
def __init__(self, data=None):
|
|
3
|
+
data = data or {}
|
|
4
|
+
|
|
5
|
+
self.id = data.get("id")
|
|
6
|
+
self.is_bot = data.get("is_bot", False)
|
|
7
|
+
self.first_name = data.get("first_name")
|
|
8
|
+
self.username = data.get("username")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Chat:
|
|
12
|
+
def __init__(self, data=None):
|
|
13
|
+
data = data or {}
|
|
14
|
+
|
|
15
|
+
self.id = data.get("id")
|
|
16
|
+
self.type = data.get("type")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Message:
|
|
20
|
+
def __init__(self, data=None, bot=None):
|
|
21
|
+
data = data or {}
|
|
22
|
+
|
|
23
|
+
self._data = data
|
|
24
|
+
self.bot = bot
|
|
25
|
+
|
|
26
|
+
self.message_id = data.get("message_id")
|
|
27
|
+
self.date = data.get("date")
|
|
28
|
+
|
|
29
|
+
self.chat = Chat(
|
|
30
|
+
data.get("chat")
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
self.chat_id = self.chat.id
|
|
34
|
+
|
|
35
|
+
self.from_user = User(
|
|
36
|
+
data.get("from")
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
self.text = data.get("text")
|
|
40
|
+
|
|
41
|
+
async def reply(self, text):
|
|
42
|
+
if self.bot is None:
|
|
43
|
+
raise RuntimeError(
|
|
44
|
+
"Message is not connected to a Bot"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
return self.bot.send_message(
|
|
48
|
+
self.chat_id,
|
|
49
|
+
text
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
def __getitem__(self, key):
|
|
53
|
+
return self._data[key]
|
|
54
|
+
|
|
55
|
+
def get(self, key, default=None):
|
|
56
|
+
return self._data.get(
|
|
57
|
+
key,
|
|
58
|
+
default
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class CallbackQuery:
|
|
63
|
+
def __init__(self, data=None):
|
|
64
|
+
data = data or {}
|
|
65
|
+
|
|
66
|
+
self.id = data.get("id")
|
|
67
|
+
|
|
68
|
+
self.from_user = User(
|
|
69
|
+
data.get("from")
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
self.message = Message(
|
|
73
|
+
data.get("message")
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
self.data = data.get("data")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class Update:
|
|
80
|
+
def __init__(self, data=None):
|
|
81
|
+
data = data or {}
|
|
82
|
+
|
|
83
|
+
self.update_id = data.get(
|
|
84
|
+
"update_id"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
self.message = None
|
|
88
|
+
self.callback_query = None
|
|
89
|
+
|
|
90
|
+
if data.get("message"):
|
|
91
|
+
self.message = Message(
|
|
92
|
+
data.get("message")
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
if data.get("callback_query"):
|
|
96
|
+
self.callback_query = CallbackQuery(
|
|
97
|
+
data.get("callback_query")
|
|
98
|
+
)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "MartMeet"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python library for building bots"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
|
|
13
|
+
authors = [
|
|
14
|
+
{name = "MartMeet"}
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
dependencies = [
|
|
18
|
+
"requests>=2.28.0"
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[tool.setuptools.packages.find]
|
|
22
|
+
include = ["martmeet*"]
|
martmeet-0.1.0/setup.cfg
ADDED