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.
@@ -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
+ requests>=2.28.0
@@ -0,0 +1 @@
1
+ martmeet
@@ -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,12 @@
1
+ # MartMeet
2
+
3
+ ### Async Python Framework for codemeet Messenger Bots
4
+
5
+ MartMeet is an asynchronous Python framework for building bots for CodeMeet Messenger.
6
+
7
+ ## Installation
8
+
9
+ Install MartMeet using pip:
10
+
11
+ ```bash
12
+ pip install MartMeet
@@ -0,0 +1,11 @@
1
+ from .bot import Bot
2
+ from .client import Client
3
+ from .types import Message
4
+
5
+ __version__ = "0.1.0"
6
+
7
+ __all__ = [
8
+ "Bot",
9
+ "Client",
10
+ "Message",
11
+ ]
@@ -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,8 @@
1
+ class MartMeetError(Exception):
2
+ """Base exception for MartMeet."""
3
+ pass
4
+
5
+
6
+ class APIError(MartMeetError):
7
+ """API request error."""
8
+ pass
@@ -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,12 @@
1
+ def is_command(text, command):
2
+ if not text:
3
+ return False
4
+
5
+ return text.startswith(command)
6
+
7
+
8
+ def clean_text(text):
9
+ if not text:
10
+ return ""
11
+
12
+ return text.strip()
@@ -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*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+