Compare commits

..

46 Commits

Author SHA1 Message Date
70d0d31e20 Merge pull request 'metric' (#82) from metric into master
Reviewed-on: #82
2025-07-17 23:32:42 +03:00
Egor Matveev
5581786225 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 25s
Deploy Prod / Push (pull_request) Successful in 11s
Deploy Prod / Deploy prod (pull_request) Successful in 10s
2025-07-17 23:27:52 +03:00
Egor Matveev
66b4348957 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 5s
Deploy Prod / Push (pull_request) Successful in 9s
Deploy Prod / Deploy prod (pull_request) Successful in 11s
2025-06-15 17:24:52 +03:00
Egor Matveev
33901b0a82 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 9s
Deploy Dev / Deploy dev (pull_request) Successful in 17s
2025-06-15 17:13:54 +03:00
Egor Matveev
7b9d264ef9 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 8s
Deploy Dev / Push (pull_request) Successful in 10s
Deploy Dev / Deploy dev (pull_request) Successful in 12s
2025-06-15 17:08:15 +03:00
Egor Matveev
a707a8b93e fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 7s
Deploy Dev / Push (pull_request) Successful in 10s
Deploy Dev / Deploy dev (pull_request) Successful in 18s
2025-06-15 16:49:40 +03:00
Egor Matveev
df3354a536 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 7s
Deploy Dev / Push (pull_request) Successful in 9s
Deploy Dev / Deploy dev (pull_request) Successful in 17s
2025-06-15 16:45:51 +03:00
Egor Matveev
6a8f18300b fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 7s
Deploy Dev / Push (pull_request) Successful in 9s
Deploy Dev / Deploy dev (pull_request) Successful in 11s
2025-06-15 16:40:44 +03:00
Egor Matveev
b575ba5717 fix 2025-06-15 16:40:18 +03:00
Egor Matveev
24b1d39e10 fix 2025-06-15 16:39:33 +03:00
Egor Matveev
d61c665b6c fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 8s
Deploy Dev / Push (pull_request) Successful in 10s
Deploy Dev / Deploy dev (pull_request) Successful in 15s
2025-06-15 16:00:22 +03:00
Egor Matveev
4f0114e99a fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 9s
Deploy Dev / Deploy dev (pull_request) Successful in 12s
2025-06-15 14:53:13 +03:00
Egor Matveev
0cab3e52cb fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 9s
Deploy Dev / Deploy dev (pull_request) Successful in 12s
2025-06-15 14:45:14 +03:00
Egor Matveev
2d292dfc46 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 9s
Deploy Dev / Deploy dev (pull_request) Successful in 12s
2025-06-15 14:42:46 +03:00
Egor Matveev
72c5823ccd fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 9s
Deploy Dev / Deploy dev (pull_request) Successful in 15s
2025-06-15 14:40:14 +03:00
Egor Matveev
e0e7564fcc fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 9s
Deploy Dev / Deploy dev (pull_request) Successful in 12s
2025-06-15 05:27:31 +03:00
Egor Matveev
2bff8983b5 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 9s
Deploy Dev / Deploy dev (pull_request) Successful in 17s
2025-06-15 05:11:23 +03:00
Egor Matveev
4af857e2f3 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 9s
Deploy Dev / Deploy dev (pull_request) Successful in 12s
2025-06-15 05:07:16 +03:00
Egor Matveev
ef1d60e368 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 5s
Deploy Prod / Push (pull_request) Successful in 8s
Deploy Prod / Deploy prod (pull_request) Successful in 12s
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 8s
Deploy Dev / Deploy dev (pull_request) Successful in 19s
2024-12-31 02:52:49 +03:00
Egor Matveev
8828bfd05b fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 8s
Deploy Dev / Deploy dev (pull_request) Successful in 9s
2024-12-31 02:49:03 +03:00
Egor Matveev
5a8d6c6488 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 7s
Deploy Prod / Push (pull_request) Successful in 14s
Deploy Prod / Deploy prod (pull_request) Successful in 11s
2024-12-28 14:23:20 +03:00
Egor Matveev
f27122ce56 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 7s
Deploy Prod / Push (pull_request) Successful in 8s
Deploy Prod / Deploy prod (pull_request) Successful in 10s
2024-12-28 14:18:34 +03:00
Egor Matveev
c509cb0b32 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 24s
Deploy Prod / Push (pull_request) Successful in 17s
Deploy Prod / Deploy prod (pull_request) Successful in 19s
2024-12-28 13:49:39 +03:00
Administrator
0785997e6e fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 11s
Deploy Dev / Deploy dev (pull_request) Successful in 13s
Deploy Prod / Build (pull_request) Successful in 6s
Deploy Prod / Push (pull_request) Successful in 9s
Deploy Prod / Deploy prod (pull_request) Successful in 13s
2024-12-22 23:49:53 +03:00
Administrator
7742138ec8 fix
Some checks failed
Deploy Dev / Build (pull_request) Failing after 23s
Deploy Dev / Push (pull_request) Has been skipped
Deploy Dev / Deploy dev (pull_request) Has been skipped
2024-12-22 23:47:31 +03:00
Administrator
4d03af75d8 fix 2024-12-22 22:20:02 +03:00
Administrator
5a00dad803 add
All checks were successful
Deploy Dev / Build (pull_request) Successful in 24s
Deploy Dev / Push (pull_request) Successful in 21s
Deploy Dev / Deploy dev (pull_request) Successful in 33s
Deploy Prod / Build (pull_request) Successful in 11s
Deploy Prod / Push (pull_request) Successful in 19s
Deploy Prod / Deploy prod (pull_request) Successful in 22s
2024-12-21 19:27:00 +03:00
7ed7afbef4 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 8s
Deploy Prod / Push (pull_request) Successful in 10s
Deploy Prod / Deploy prod (pull_request) Successful in 18s
2024-12-08 19:56:33 +03:00
73cc7b2c03 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 9s
Deploy Dev / Push (pull_request) Successful in 8s
Deploy Dev / Deploy dev (pull_request) Successful in 11s
2024-12-08 19:42:19 +03:00
5dbacec1b0 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 8s
Deploy Dev / Push (pull_request) Successful in 10s
Deploy Dev / Deploy dev (pull_request) Successful in 13s
2024-12-08 19:40:13 +03:00
0b6dc3af1a fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 8s
Deploy Dev / Push (pull_request) Successful in 10s
Deploy Dev / Deploy dev (pull_request) Successful in 9s
2024-12-08 13:45:11 +03:00
98d69fff70 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 7s
Deploy Dev / Deploy dev (pull_request) Successful in 10s
2024-12-08 13:43:04 +03:00
0dbae621ab fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 9s
Deploy Dev / Push (pull_request) Successful in 7s
Deploy Dev / Deploy dev (pull_request) Successful in 11s
2024-12-08 12:05:54 +03:00
b4dd0a4b7b fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 7s
Deploy Dev / Push (pull_request) Successful in 10s
Deploy Dev / Deploy dev (pull_request) Successful in 10s
2024-12-08 11:48:41 +03:00
bb4c6d4748 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 8s
Deploy Dev / Deploy dev (pull_request) Successful in 8s
2024-12-08 11:35:54 +03:00
92fe0c1999 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 8s
Deploy Dev / Deploy dev (pull_request) Successful in 12s
2024-12-08 11:34:08 +03:00
ec2c39ed35 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 7s
Deploy Dev / Deploy dev (pull_request) Successful in 11s
2024-12-08 11:26:07 +03:00
a4b580eab6 Merge branch 'master' of https://gitea.sprinthub.ru/self/botalka
All checks were successful
Deploy Dev / Build (pull_request) Successful in 32s
Deploy Dev / Push (pull_request) Successful in 14s
Deploy Dev / Deploy dev (pull_request) Successful in 10s
2024-12-08 11:21:47 +03:00
b3e44c4532 grpc 2024-12-08 11:20:54 +03:00
df2a7c3bb1 Update daemons/mailbox.py
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 8s
Deploy Dev / Deploy dev (pull_request) Successful in 10s
2024-12-02 22:38:50 +03:00
784a2ed393 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 8s
Deploy Dev / Deploy dev (pull_request) Successful in 10s
2024-12-02 21:53:24 +03:00
2527524ca4 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 7s
Deploy Dev / Deploy dev (pull_request) Successful in 10s
Deploy Prod / Build (pull_request) Successful in 6s
Deploy Prod / Push (pull_request) Successful in 9s
Deploy Prod / Deploy prod (pull_request) Successful in 11s
2024-11-30 13:29:59 +03:00
a991bb7714 types
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 7s
Deploy Dev / Deploy dev (pull_request) Successful in 10s
2024-11-30 12:58:40 +03:00
d195a6cc44 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 8s
Deploy Dev / Push (pull_request) Successful in 10s
Deploy Dev / Deploy dev (pull_request) Successful in 14s
Deploy Prod / Build (pull_request) Successful in 5s
Deploy Prod / Push (pull_request) Successful in 12s
Deploy Prod / Deploy prod (pull_request) Successful in 16s
2024-11-29 20:31:23 +03:00
05dc1ceda2 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 35s
Deploy Dev / Push (pull_request) Successful in 12s
Deploy Dev / Deploy dev (pull_request) Successful in 13s
2024-11-29 20:24:55 +03:00
aae0871671 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 8s
Deploy Dev / Deploy dev (pull_request) Successful in 8s
Deploy Prod / Build (pull_request) Successful in 6s
Deploy Prod / Push (pull_request) Successful in 7s
Deploy Prod / Deploy prod (pull_request) Successful in 9s
2024-11-28 23:07:50 +03:00
5 changed files with 85 additions and 33 deletions

3
.gitignore vendored
View File

@@ -119,3 +119,6 @@ GitHub.sublime-settings
.history .history
local_platform.json local_platform.json
*pb2*
schemas

View File

@@ -1,3 +1,5 @@
import pydantic
from telebot import apihelper from telebot import apihelper
from daemons import base from daemons import base
@@ -5,6 +7,13 @@ from utils import platform
from utils import queues from utils import queues
class Message(pydantic.BaseModel):
project: str
name: str
body: dict
method: str = 'send_message'
class Daemon(base.Daemon, queues.TasksHandlerMixin): class Daemon(base.Daemon, queues.TasksHandlerMixin):
def execute(self): def execute(self):
self.poll() self.poll()
@@ -13,18 +22,19 @@ class Daemon(base.Daemon, queues.TasksHandlerMixin):
def queue_name(self): def queue_name(self):
return 'botalka_mailbox' return 'botalka_mailbox'
def process(self, payload): def process(self, payload: dict):
bot = platform.platform_client.get_config('bots')[payload['project']][payload['name']] message = Message.model_validate(payload)
bot = platform.platform_client.get_config('bots')[message.project][message.name]
if not bot['mailbox_enabled']: if not bot['mailbox_enabled']:
return return
if bot['type'] == 'telegram': if bot['type'] == 'telegram':
token = bot['secrets']['telegram_token'] token = bot['secrets']['telegram_token']
self.process_telegram(token, payload['body']) self.process_telegram(token, message.method, message.body)
else: else:
print('Unknown bot type:', bot['type']) print('Unknown bot type:', bot['type'])
def process_telegram(self, token, payload): def process_telegram(self, token, method, payload):
try: try:
apihelper.send_message(token, **payload) getattr(apihelper, method)(token, **payload)
except Exception as exc: except Exception as exc:
print('Error', str(exc)) print('Error', str(exc))

View File

@@ -1,7 +1,7 @@
import multiprocessing
import telebot import telebot
import threading import multiprocessing
import time import time
import json
from daemons import base from daemons import base
from utils import platform from utils import platform
@@ -10,39 +10,37 @@ from utils import queues
class Daemon(base.Daemon): class Daemon(base.Daemon):
def __init__(self): def __init__(self):
self.telegram_bots: dict[str, dict[str, multiprocessing.Process|None]] = {} self.processes: dict[str, multiprocessing.Process|None] = {}
def execute(self): def execute(self):
while True: while True:
bots = platform.platform_client.get_config('bots') bots = platform.platform_client.get_config('bots')
for project_name, project in bots.items(): for project_name, project in bots.items():
if project_name not in self.telegram_bots:
self.telegram_bots[project_name] = {}
for bot_name, bot_info in project.items(): for bot_name, bot_info in project.items():
if bot_name not in self.telegram_bots[project_name]: key = f'{project_name}_{bot_name}'
self.telegram_bots[project_name][bot_name] = None proc = self.processes.get(key)
bot = self.telegram_bots[project_name][bot_name]
if bot_info.get('poll_enabled'): if bot_info.get('poll_enabled'):
if bot is not None and bot.is_alive: if proc and proc.is_alive():
print(f'process for {project_name} {bot_name} is alive') print(f'process for {project_name} {bot_name} is alive')
continue continue
print(f'starting process for {project_name} {bot_name}') print(f'starting process for {project_name} {bot_name}')
bot = telebot.TeleBot(bot_info['secrets']['telegram_token']) process = multiprocessing.Process(target=self.start_polling, args=(bot_info['secrets']['telegram_token'], bot_info['queue']))
self.start_polling(bot, bot_info['queue'], project_name, bot_name) process.start()
self.processes[key] = process
print(f'started process for {project_name} {bot_name}') print(f'started process for {project_name} {bot_name}')
else: else:
if bot is None: if proc is None:
print(f'process for {project_name} {bot_name} is not alive') print(f'process for {project_name} {bot_name} is not alive')
continue continue
print(f'terminating process for {project_name} {bot_name}') print(f'terminating process for {project_name} {bot_name}')
bot.terminate() proc.terminate()
self.telegram_bots[project_name][bot_name] = None self.processes[key] = None
print(f'terminated process for {project_name} {bot_name}') print(f'terminated process for {project_name} {bot_name}')
time.sleep(10) time.sleep(10)
def start_polling(self, bot: telebot.TeleBot, queue: str, project_name: str, bot_name: str): def start_polling(self, token: str, queue: str):
@bot.message_handler() bot = telebot.TeleBot(token)
@bot.message_handler(content_types=['audio', 'photo', 'voice', 'video', 'document', 'animation', 'text', 'location', 'contact', 'sticker', 'video_note'])
def do_action(message: telebot.types.Message): def do_action(message: telebot.types.Message):
queues.set_task(queue, message.json, 1) queues.set_task(queue, message.json, 1)
process = multiprocessing.Process(target=bot.polling) bot.polling()
self.telegram_bots[project_name][bot_name] = process

View File

@@ -1,6 +1,10 @@
certifi==2024.8.30 annotated-types==0.7.0
certifi==2024.12.14
charset-normalizer==3.4.0 charset-normalizer==3.4.0
idna==3.10 idna==3.10
pydantic==2.10.4
pydantic_core==2.27.2
pyTelegramBotAPI==4.1.1 pyTelegramBotAPI==4.1.1
requests==2.32.3 requests==2.32.3
urllib3==2.2.3 typing_extensions==4.12.2
urllib3==2.3.0

View File

@@ -1,4 +1,10 @@
from concurrent.futures import ThreadPoolExecutor
import datetime
import json
import os import os
import traceback
import uuid
import zoneinfo
import requests import requests
import time import time
@@ -15,24 +21,55 @@ class QueuesException(Exception):
class TasksHandlerMixin: class TasksHandlerMixin:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.executor = ThreadPoolExecutor(max_workers=1)
def _send_metric(self, start: datetime.datetime, end: datetime.datetime, success: bool):
def send():
requests.post(f'{QUEUES_URL}/api/v1/metric', json={
'service': 'botalka',
'queue': self.queue_name,
'success': success,
'timestamp': start.strftime("%Y-%m-%dT%H:%M:%S") + "Z",
"success": success,
"execution_time_ms": (end - start).microseconds // 1000,
"environment": stage,
})
self.executor.submit(send)
def poll(self): def poll(self):
while True: while True:
try:
response = requests.get(f'{QUEUES_URL}/api/v1/take', headers={'queue': self.queue_name}).json() response = requests.get(f'{QUEUES_URL}/api/v1/take', headers={'queue': self.queue_name}).json()
except requests.JSONDecodeError:
print('Unable to decode json')
time.sleep(3)
continue
task = response.get('task') task = response.get('task')
if not task: if not task:
time.sleep(0.2) time.sleep(0.2)
continue continue
start = datetime.datetime.now(zoneinfo.ZoneInfo("Europe/Moscow"))
try: try:
print(f'process task with id {task["id"]}, attempt {task["attempt"]}')
self.process(task['payload']) self.process(task['payload'])
success = True
except Exception as exc: except Exception as exc:
print(f'Error processing message id={task["id"]}, payload={task["payload"]}, exc={exc}') print(f'Error processing message id={task["id"]}, payload={task["payload"]}, exc={exc}')
continue traceback.print_stack()
success = False
end = datetime.datetime.now(zoneinfo.ZoneInfo("Europe/Moscow"))
if success:
try: try:
resp = requests.post(f'{QUEUES_URL}/api/v1/finish', json={'id': task['id']}) resp = requests.post(f'{QUEUES_URL}/api/v1/finish', json={'id': task['id']})
if resp.status_code != 202: if resp.status_code != 202:
raise QueuesException raise QueuesException
print(f'finish task with id {task["id"]}')
except: except:
print(f'Failed to finish task id={task["id"]}') print(f'Failed to finish task id={task["id"]}')
self._send_metric(start, end, success)
@property @property
def queue_name(self): def queue_name(self):