tinybot-eth 0.5.0__tar.gz → 0.6.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tinybot-eth
3
- Version: 0.5.0
3
+ Version: 0.6.0
4
4
  Summary: Minimal Python framework for building crypto bots
5
5
  Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
@@ -8,6 +8,7 @@ Requires-Dist: web3==7.14.1
8
8
  Requires-Dist: eth-abi==5.2.0
9
9
  Requires-Dist: eth-account==0.13.7
10
10
  Requires-Dist: python-telegram-bot==22.7
11
+ Requires-Dist: croniter==6.2.2
11
12
 
12
13
  # tinybot
13
14
 
@@ -34,6 +35,7 @@ bot = TinyBot(rpc_url, name="my bot")
34
35
 
35
36
  bot.listen(event="AuctionKicked", handler=on_kick, ...)
36
37
  bot.every(180, check_expired)
38
+ bot.cron("0 * * * *", hourly_check)
37
39
 
38
40
  await bot.run()
39
41
  ```
@@ -132,6 +134,19 @@ Handler signature: `async fn(bot)`
132
134
 
133
135
  ---
134
136
 
137
+ ### `bot.cron(expression, handler, name="", notify_errors=True) -> CronTask`
138
+
139
+ Register a cron-scheduled task. Uses standard cron expressions.
140
+
141
+ ```python
142
+ bot.cron("0 * * * *", notify_ending_soon) # every hour at :00
143
+ bot.cron("*/30 * * * *", check_something) # every 30 minutes
144
+ ```
145
+
146
+ Handler signature: `async fn(bot)`
147
+
148
+ ---
149
+
135
150
  ### `bot.get_listener(name) -> EventListener`
136
151
 
137
152
  Get a registered listener by name. Raises `ValueError` if not found.
@@ -1,14 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: tinybot-eth
3
- Version: 0.5.0
4
- Summary: Minimal Python framework for building crypto bots
5
- Requires-Python: >=3.12
6
- Description-Content-Type: text/markdown
7
- Requires-Dist: web3==7.14.1
8
- Requires-Dist: eth-abi==5.2.0
9
- Requires-Dist: eth-account==0.13.7
10
- Requires-Dist: python-telegram-bot==22.7
11
-
12
1
  # tinybot
13
2
 
14
3
  Minimal Python framework for building crypto bots.
@@ -34,6 +23,7 @@ bot = TinyBot(rpc_url, name="my bot")
34
23
 
35
24
  bot.listen(event="AuctionKicked", handler=on_kick, ...)
36
25
  bot.every(180, check_expired)
26
+ bot.cron("0 * * * *", hourly_check)
37
27
 
38
28
  await bot.run()
39
29
  ```
@@ -132,6 +122,19 @@ Handler signature: `async fn(bot)`
132
122
 
133
123
  ---
134
124
 
125
+ ### `bot.cron(expression, handler, name="", notify_errors=True) -> CronTask`
126
+
127
+ Register a cron-scheduled task. Uses standard cron expressions.
128
+
129
+ ```python
130
+ bot.cron("0 * * * *", notify_ending_soon) # every hour at :00
131
+ bot.cron("*/30 * * * *", check_something) # every 30 minutes
132
+ ```
133
+
134
+ Handler signature: `async fn(bot)`
135
+
136
+ ---
137
+
135
138
  ### `bot.get_listener(name) -> EventListener`
136
139
 
137
140
  Get a registered listener by name. Raises `ValueError` if not found.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tinybot-eth"
3
- version = "0.5.0"
3
+ version = "0.6.0"
4
4
  description = "Minimal Python framework for building crypto bots"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -9,6 +9,7 @@ dependencies = [
9
9
  "eth-abi==5.2.0",
10
10
  "eth-account==0.13.7",
11
11
  "python-telegram-bot==22.7",
12
+ "croniter==6.2.2",
12
13
  ]
13
14
 
14
15
  [tool.setuptools.packages.find]
@@ -8,7 +8,9 @@ from web3 import Web3
8
8
  from tinybot.executor import Executor
9
9
  from tinybot.state import State
10
10
  from tinybot.tg import DEV_GROUP_CHAT_ID, notify_group_chat
11
- from tinybot.types import EventHandler, EventListener, PeriodicTask, TaskHandler
11
+ from croniter import croniter
12
+
13
+ from tinybot.types import CronTask, EventHandler, EventListener, PeriodicTask, TaskHandler
12
14
  from tinybot.utils import event_id, event_signature
13
15
 
14
16
 
@@ -20,6 +22,7 @@ class TinyBot:
20
22
  self.executor = Executor(self.w3, private_key) if private_key else None
21
23
  self._listeners: list[EventListener] = []
22
24
  self._tasks: list[PeriodicTask] = []
25
+ self._crons: list[tuple[CronTask, croniter]] = []
23
26
 
24
27
  # -------------------------------------------------------------------------
25
28
  # Registration
@@ -77,6 +80,26 @@ class TinyBot:
77
80
  self._tasks.append(task)
78
81
  return task
79
82
 
83
+ def cron(
84
+ self,
85
+ expression: str,
86
+ handler: TaskHandler,
87
+ name: str = "",
88
+ notify_errors: bool = True,
89
+ ) -> CronTask:
90
+ name = name or handler.__name__
91
+ if any(task.name == name for task, _ in self._crons):
92
+ raise ValueError(f"cron '{name}' already registered")
93
+ task = CronTask(
94
+ name=name,
95
+ expression=expression,
96
+ handler=handler,
97
+ notify_errors=notify_errors,
98
+ )
99
+ cron = croniter(expression, datetime.now())
100
+ self._crons.append((task, cron))
101
+ return task
102
+
80
103
  # -------------------------------------------------------------------------
81
104
  # Getters
82
105
  # -------------------------------------------------------------------------
@@ -149,7 +172,7 @@ class TinyBot:
149
172
  except Exception as e:
150
173
  await self._handle_error(e, listener.name, listener.notify_errors)
151
174
 
152
- async def _poll_task(self, task: PeriodicTask) -> None:
175
+ async def _poll_periodic(self, task: PeriodicTask) -> None:
153
176
  now = time.time()
154
177
  if now - task._last_run < task.interval:
155
178
  return
@@ -160,6 +183,16 @@ class TinyBot:
160
183
  except Exception as e:
161
184
  await self._handle_error(e, task.name, task.notify_errors)
162
185
 
186
+ async def _poll_cron(self, task: CronTask, cron: croniter) -> None:
187
+ now = datetime.now()
188
+ next_run = cron.get_current(datetime)
189
+ if now >= next_run:
190
+ try:
191
+ await task.handler(self)
192
+ except Exception as e:
193
+ await self._handle_error(e, task.name, task.notify_errors)
194
+ cron.get_next(datetime)
195
+
163
196
  # -------------------------------------------------------------------------
164
197
  # Run
165
198
  # -------------------------------------------------------------------------
@@ -175,5 +208,7 @@ class TinyBot:
175
208
  for listener in self._listeners:
176
209
  await self._poll_listener(listener)
177
210
  for task in self._tasks:
178
- await self._poll_task(task)
211
+ await self._poll_periodic(task)
212
+ for task, cron in self._crons:
213
+ await self._poll_cron(task, cron)
179
214
  await asyncio.sleep(tick)
@@ -44,3 +44,11 @@ class PeriodicTask:
44
44
  handler: TaskHandler
45
45
  notify_errors: bool = True
46
46
  _last_run: float = 0
47
+
48
+
49
+ @dataclass
50
+ class CronTask:
51
+ name: str
52
+ expression: str
53
+ handler: TaskHandler
54
+ notify_errors: bool = True
@@ -1,3 +1,15 @@
1
+ Metadata-Version: 2.4
2
+ Name: tinybot-eth
3
+ Version: 0.6.0
4
+ Summary: Minimal Python framework for building crypto bots
5
+ Requires-Python: >=3.12
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: web3==7.14.1
8
+ Requires-Dist: eth-abi==5.2.0
9
+ Requires-Dist: eth-account==0.13.7
10
+ Requires-Dist: python-telegram-bot==22.7
11
+ Requires-Dist: croniter==6.2.2
12
+
1
13
  # tinybot
2
14
 
3
15
  Minimal Python framework for building crypto bots.
@@ -23,6 +35,7 @@ bot = TinyBot(rpc_url, name="my bot")
23
35
 
24
36
  bot.listen(event="AuctionKicked", handler=on_kick, ...)
25
37
  bot.every(180, check_expired)
38
+ bot.cron("0 * * * *", hourly_check)
26
39
 
27
40
  await bot.run()
28
41
  ```
@@ -121,6 +134,19 @@ Handler signature: `async fn(bot)`
121
134
 
122
135
  ---
123
136
 
137
+ ### `bot.cron(expression, handler, name="", notify_errors=True) -> CronTask`
138
+
139
+ Register a cron-scheduled task. Uses standard cron expressions.
140
+
141
+ ```python
142
+ bot.cron("0 * * * *", notify_ending_soon) # every hour at :00
143
+ bot.cron("*/30 * * * *", check_something) # every 30 minutes
144
+ ```
145
+
146
+ Handler signature: `async fn(bot)`
147
+
148
+ ---
149
+
124
150
  ### `bot.get_listener(name) -> EventListener`
125
151
 
126
152
  Get a registered listener by name. Raises `ValueError` if not found.
@@ -2,3 +2,4 @@ web3==7.14.1
2
2
  eth-abi==5.2.0
3
3
  eth-account==0.13.7
4
4
  python-telegram-bot==22.7
5
+ croniter==6.2.2
File without changes
File without changes