Compare commits

..

44 Commits

Author SHA1 Message Date
hogweed1
72f96576ba море спася геноцид
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-12 21:58:05 +10:00
hogweed1
81db0b2bdb море спася геноцид
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-12 21:57:58 +10:00
hogweed1
2830335b12 space genocide
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-12 21:52:47 +10:00
hogweed1
7e52c86067 be be bechka lo
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-12 21:38:25 +10:00
hogweed1
5f0d211a9b be be be
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-12 21:30:41 +10:00
hogweed1
f4a1cee509 be be be
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-12 21:28:36 +10:00
3b4454fd44 Update handlers/metrics.py
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-12 21:26:04 +10:00
f7a13962f0 init gauges once
All checks were successful
continuous-integration/drone/push Build is passing
init gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges onceinit gauges once
2025-05-12 21:25:08 +10:00
8a1013d280 Update db_logic/user_stuff.py
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-12 21:12:12 +10:00
afc9b61e92 Update db_logic/user_stuff.py
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-12 21:06:33 +10:00
825d415766 Merge pull request 'main' (#12) from RakVhalate/python_bot_exporter:main into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #12
2025-05-12 21:00:57 +10:00
567ce5f2ad fix
All checks were successful
continuous-integration/drone/pr Build is passing
2025-05-08 12:55:51 +10:00
1f3b4ec80f Metrics added 2025-05-08 12:19:36 +10:00
a67531ce98 Update .drone.yml
All checks were successful
continuous-integration/drone/push Build is passing
2025-04-10 02:29:06 +10:00
2542e601c1 Update .drone.yml
All checks were successful
continuous-integration/drone/push Build is passing
2025-04-10 02:25:35 +10:00
d173eb019b Update config.yaml
All checks were successful
continuous-integration/drone/push Build is passing
2025-04-09 03:08:26 +10:00
43148417c8 Обновить pipisa_functions/pipisa_time.py
All checks were successful
continuous-integration/drone/push Build is passing
2025-01-03 03:16:23 +10:00
9f7ae4b9a7 we r so fucking back
All checks were successful
continuous-integration/drone/push Build is passing
2024-08-11 01:07:53 +10:00
hogweed1
d41eeb3232 make pipisa secure
All checks were successful
continuous-integration/drone/push Build is passing
2024-07-03 17:38:45 +10:00
hogweed1
55e5303ab2 trying artifitial antitop !!
All checks were successful
continuous-integration/drone/push Build is passing
2024-06-29 01:51:07 +10:00
hogweed1
31235ef9ac trying artifitial antitop !
All checks were successful
continuous-integration/drone/push Build is passing
2024-06-29 01:47:23 +10:00
hogweed1
6709eebb88 trying artifitial antitop
All checks were successful
continuous-integration/drone/push Build is passing
2024-06-29 01:36:59 +10:00
Pavel_Durov
1533c5eb91 dsfs
All checks were successful
continuous-integration/drone/push Build is passing
2024-05-10 20:49:20 +03:00
Pavel_Durov
4c520b39fe asdadasdassa
All checks were successful
continuous-integration/drone/push Build is passing
2024-05-10 20:37:34 +03:00
Pavel_Durov
db842a1ceb eweww
All checks were successful
continuous-integration/drone/push Build is passing
2024-05-10 19:46:37 +03:00
Simple_Not
a571709afa #11 fixxxx scary bug
All checks were successful
continuous-integration/drone Build is passing
2024-03-19 14:12:14 +10:00
Pavel_Durov
192687a5ea теперь пипис у новеньких положительный
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-28 14:30:31 +03:00
Simple_Not
f20c90ea34 fx
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-28 14:14:41 +10:00
Pavel_Durov
1b2410afc4 только положительный пипис для новичков
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-28 14:04:58 +03:00
Simple_Not
56450bc566 fix пост-делишон
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-25 14:28:14 +10:00
Simple_Not
aa3ea439fe fix new yeatr
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-24 18:31:46 +10:00
Simple_Not
dae3f05aa7 fix new yeatr
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-24 17:54:54 +10:00
Simple_Not
66c2ef80c3 #10 теперь логгируется
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-24 14:09:31 +10:00
Simple_Not
4a3f799284 #5 another way
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-23 15:35:41 +10:00
Simple_Not
7090ab218e #5 fixxo
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-23 15:31:23 +10:00
Simple_Not
53bac66692 #5 fixxo
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-23 15:29:34 +10:00
Simple_Not
ee27dbfd7b #5 удаляем!
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-23 15:12:59 +10:00
Simple_Not
14c238ec2f меньше кода - лучше!
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-23 13:29:31 +10:00
Simple_Not
9d6d8791fd меньше кода - лучше!
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-23 13:23:04 +10:00
Simple_Not
d2b8c76817 меньше кода - лучше!
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-23 13:21:10 +10:00
Simple_Not
48d53fd1b9 меньше кода - лучше!
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-23 13:18:51 +10:00
Simple_Not
505d90aea8 меньше кода - лучше!
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-23 12:45:44 +10:00
Simple_Not
eb59091615 меньше кода - лучше!
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-23 02:26:29 +10:00
Simple_Not
c8a9936a00 меньше кода - лучше!
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-23 02:21:29 +10:00
23 changed files with 519 additions and 316 deletions

View File

@@ -7,6 +7,10 @@ platform:
os: linux os: linux
arch: amd64 arch: amd64
node:
gay: nigger
#clone: #clone:
# убрано так как сейчас не тестим ничего предварительно а сразу тянем в директорию # убрано так как сейчас не тестим ничего предварительно а сразу тянем в директорию
#disable: true #disable: true
@@ -19,11 +23,16 @@ steps:
- name: pull into the folduh - name: pull into the folduh
commands: commands:
- cd /usr/share/$DRONE_REPO_NAME - cd /usr/share/$DRONE_REPO_NAME
- su -c "git pull" jack - git pull
#- chown -R jack:jack . #- chown -R jack:jack .
when: when:
branch: branch:
- main - main
environment:
ARANGO_PASSWORD:
from_secret: arango-pwd
ARANGO_USERNAME:
from_secret: arango-usr
- name: restart systemd unit - name: restart systemd unit
commands: commands:
- systemctl restart jack_bot - systemctl restart jack_bot

3
.gitignore vendored
View File

@@ -4,4 +4,5 @@ TIME.py
.vscode .vscode
tests tests
qeqeqe qeqeqe
env env
handlers/userdata.json

45
bot.py
View File

@@ -2,36 +2,40 @@ import logging
from aiogram import executor, Bot, Dispatcher from aiogram import executor, Bot, Dispatcher
from create_bot import dp from create_bot import dp
import handlers import handlers
import json import json, logging
from global_conf import CONFIG from global_conf import CONFIG
from prometheus_client import start_http_server
def remake_field_generator(d, field='text'):
def remake_field_generator(d, field='text'): if isinstance(d, list):
for k, v in d.items(): for k2 in d:
if k == field: for id_val in remake_field_generator(k2):
d[k] = '<blank!>' yield id_val
yield v elif isinstance(d, dict):
elif isinstance(v, list): for k, v in d.items():
for k2 in v: if k == field:
for id_val in remake_field_generator(k2): d[k] = '<blank!>'
yield v
elif isinstance(v, list):
for k2 in v:
for id_val in remake_field_generator(k2):
yield id_val
elif isinstance(v, dict):
for id_val in remake_field_generator(v):
yield id_val yield id_val
elif isinstance(v, dict):
for id_val in remake_field_generator(v):
yield id_val
def filter_grammar_messages(record): def filter_grammar_messages(record):
if record.args and (not None in record.args): if record.args and (not None in record.args):
j = json.loads(record.args[2]) j = json.loads(record.args[2])
for _ in remake_field_generator(j): for _ in remake_field_generator(j):
pass pass
record.args = (record.args[0], record.args[1], json.dumps(j)) record.args = (record.args[0], record.args[1], json.dumps(j))
return True return True
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
logging.getLogger("aiogram").addFilter(filter_grammar_messages) logging.getLogger("aiogram").addFilter(filter_grammar_messages)
# pipisa.register_handlers_pipisa(dp) # pipisa.register_handlers_pipisa(dp)
# time_new_year.register_handlers_time(dp) # time_new_year.register_handlers_time(dp)
# sendalarm.register_handlers_test(dp) # sendalarm.register_handlers_test(dp)
@@ -39,10 +43,7 @@ logging.getLogger("aiogram").addFilter(filter_grammar_messages)
if __name__ == '__main__': if __name__ == '__main__':
#print(CONFIG) #print(CONFIG)
start_http_server(1337)
logging.info('Бот в строю.')
executor.start_polling(dp, skip_updates=True) executor.start_polling(dp, skip_updates=True)
logging.info('Всем пока.')

View File

@@ -1,17 +1,19 @@
--- ---
databaso: databaso:
host: 'https://arango.guaranteedstruggle.host' host: 'http://arango.guaranteedstruggle.host:8529'
user: root #user: root
pass: stolendick527 #pass: stolendick527
base: pipisa base: pipisa
collection: dicks collection: dicks
posts_removal_collection: posts_removal
telegram_token: 5724991559:AAEuLvpLsgP6LHRGMSyFtQLlR5qPQUO4b_w telegram_token: 6991523312:AAFpxPlWHfnNq2dVXM_v1GuHcrbNgWdSWBM
telegram_admins_ids: telegram_admins_ids:
- 317051301 # hogweed1 - 317051301 # hogweed1
- 226765676 # blackjack - 226765676 # blackjack
- 94830892 # viktorRMI - 94830892 # viktorRMI
- 132002803
openai: openai:
token: 5947963644:AAF_GKgMmU5ovqMpc1KXIpcf4aN0JMyKPqc token: 5947963644:AAF_GKgMmU5ovqMpc1KXIpcf4aN0JMyKPqc
api_key: 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 ## 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 api_key: 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 ## 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

View File

@@ -2,7 +2,5 @@ from aiogram import Bot, Dispatcher
from global_conf import CONFIG from global_conf import CONFIG
bot = Bot(token=CONFIG['telegram_token'], parse_mode="HTML") bot = Bot(token=CONFIG['telegram_token'], parse_mode="HTML")
dp = Dispatcher(bot) dp = Dispatcher(bot)

0
db_logic/__init__.py Normal file
View File

40
db_logic/collections.py Normal file
View File

@@ -0,0 +1,40 @@
from global_conf import CONFIG
#### https://docs.python-arango.com/en/main/
from arango import ArangoClient
import logging
import os
def get_dicks_collection():
try:
arango_client = ArangoClient(hosts=CONFIG['databaso']['host'] )
pipisa_db = arango_client.db(
CONFIG['databaso']['base'],
username=os.environ['ARANGO_USR'],
password=os.environ['ARANGO_PWD'],
#username=CONFIG['databaso']['user'],
#password=CONFIG['databaso']['pass']
)
dicks_collection = pipisa_db.collection(CONFIG['databaso']['collection'])
return dicks_collection
except Exception as e:
logging.error('ошибка DB при взятии коллекции пипис')
logging.error(e)
def get_posts_removal_collection():
try:
arango_client = ArangoClient(hosts=CONFIG['databaso']['host'])
pipisa_db = arango_client.db(
CONFIG['databaso']['base'],
username=os.environ['ARANGO_USR'],
password=os.environ['ARANGO_PWD'],
#username=CONFIG['databaso']['user'],
#password=CONFIG['databaso']['pass']
)
posts_removal_collection = pipisa_db.collection(CONFIG['databaso']['posts_removal_collection'])
return posts_removal_collection
except Exception as e:
logging.error('ошибка DB при взятии коллекции постов-на-удаление')
logging.error(e)

70
db_logic/postcleaner.py Normal file
View File

@@ -0,0 +1,70 @@
from db_logic import collections
import datetime, logging
def append_post_to_cleaning_sequence(message, type=None):
try:
novenkiy = {
'msg_id': message.message_id,
'chat_id': message.chat.id,
'type': type,
'datetimes': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
metadata = collections.get_posts_removal_collection().insert(novenkiy, overwrite_mode='update')
logging.debug('Успешно добавлен пост на удаление')
except Exception as e2:
logging.error('ошибка DB :: добавление нового поста на удаление')
logging.error(e2)
def get_posts_to_be_removed(chat_id, type=None, max_id=None):
# собираем
try:
#posts = [p for p in collections.get_posts_removal_collection().all( ) ]
if type:
posts = [p for p in collections.get_posts_removal_collection().find({'chat_id': chat_id, 'type': type}, skip=0, limit=1100) ]
else:
posts = [p for p in collections.get_posts_removal_collection().find({'chat_id': chat_id}, skip=0, limit=1100) ]
posts_ret = [ p for p in posts ]
# # for p in posts:
# # last_time = datetime.datetime.strptime(p['datetimes'], '%Y-%m-%d %H:%M:%S')
# # timediff = (datetime.datetime.now() - last_time).total_seconds()
# # if timediff > 60:
# # posts_ret.append(p)
if max_id:
posts_ret = [ p for p in posts_ret if p['msg_id'] != max_id]
else:
posts_ret = [ p for p in posts_ret if p['msg_id'] != max([pp['msg_id'] for pp in posts_ret])]
#### TODO удалять все предыдущие без учёта времени
return posts_ret
except Exception as e:
logging.error('ошибка DB :: получение постов на удаление')
logging.error(e)
def del_post(msg_id, chat_id):
# удаляем из базы
try:
candidate_cursor = collections.get_posts_removal_collection().find(
{
'msg_id': msg_id,
'chat_id': chat_id,
},
skip = 0,
limit = 1488
)
if candidate_cursor.count() > 0:
pp = candidate_cursor.pop()
else:
pp = None
collections.get_posts_removal_collection().delete(pp)
except Exception as e:
logging.error('ошибка DB :: удаление поста на удаление')
logging.error(e)

63
db_logic/tops.py Normal file
View File

@@ -0,0 +1,63 @@
from global_conf import CONFIG
from db_logic import collections
import logging
def get_tops(top_ = False, glob_ = False, chat_id = None):
if top_:
try:
dicks = [d for d in collections.get_dicks_collection().find({'chat_id': chat_id}, skip=0, limit=1100)]
except Exception as e:
logging.error('ошибка DB в /topdick')
logging.error(e)
elif glob_:
try:
dicks = [d for d in collections.get_dicks_collection().all( ) if d['user_id'] != d['chat_id']]
except Exception as e:
logging.error('ошибка DB в /globaldick')
logging.error(e)
else:
logging.error('вызывают хз что!')
top_dicks = sorted(dicks, key=lambda dick: dick['dick_size'], reverse=True)
top_dicks = top_dicks[:(min(len(top_dicks), 10))]
dickos = ''
emo = ['🏆','🚀','🍆','🍌','🐍','🐎','🌭','🌶','👌','💩']
if len(top_dicks) > 0:
for i in range(len(top_dicks)):
dickos += f' {emo[i]} {i+1}. {top_dicks[i]["user_fullname"]}: {top_dicks[i]["dick_size"]}см\n'
i += 1
return dickos
def get_antitops(top_ = False, glob_ = False, chat_id = None):
dicks = []
if top_:
try:
dicks = [d for d in collections.get_dicks_collection().find({'chat_id': chat_id}, skip=0, limit=1100)]
except Exception as e:
logging.error('ошибка DB в /topdick')
logging.error(e)
elif glob_:
try:
dicks = [d for d in collections.get_dicks_collection().all() if d['user_id'] != d['chat_id']]
except Exception as e:
logging.error('ошибка DB в /globaldick')
logging.error(e)
else:
logging.error('вызывают хз что!')
antitop_dicks = sorted(dicks, key=lambda dick: dick['dick_size'], reverse=False)
antitop_dicks = antitop_dicks[:( min(len(antitop_dicks), 10) )]
dickos = ''
emo = ['💩', '😞', '🤕', '😣', '🙁', '😐', '😑', '😶', '😒', '😕']
if len(antitop_dicks) > 0:
for i in range(len(antitop_dicks)):
dickos += f' {emo[i]} {i+1}. {antitop_dicks[i]["user_fullname"]}: {antitop_dicks[i]["dick_size"]}см\n'
i += 1
return dickos

85
db_logic/user_stuff.py Normal file
View File

@@ -0,0 +1,85 @@
from db_logic import collections
from handlers.metrics import metric_wrap
import datetime, logging
def store_new_user(message, result ):
try:
novenkiy = {
'user_id': message.from_user.id,
'user_fullname': message.from_user.full_name,
'dick_size': abs(result),
'datetimes': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
'attempts': 1,
'chat_id': message.chat.id
}
metadata = collections.get_dicks_collection().insert(novenkiy, overwrite_mode='update')
metric_wrap(message.chat.id, message.from_user.full_name, abs(result), 1)
logging.debug(f'Успешно добавлен нового пользователь @{message.from_user.username}')
except Exception as e2:
logging.error(f'ошибка DB в /dick :: добавление нового пользователя @{message.from_user.username}')
logging.error(e2)
def update_attempts(message, user ):
try:
metadata = collections.get_dicks_collection().insert(
{
'_key': user['_key'], ### этот нужен чтобы апдейт прилетал тому же юзеру
'user_id': user['user_id'] ,
'user_fullname': message.from_user.full_name,
'dick_size': user['dick_size'] ,
'datetimes': user['datetimes'] ,
'attempts': user['attempts'] + 1,
'chat_id': message.chat.id
},
overwrite_mode='update'
)
metric_wrap(message.chat.id, message.from_user.full_name, user['dick_size'], user['attempts'] + 1)
logging.debug(f'Успешно апдейтнули попытку крутить пипису @{message.from_user.username}')
except Exception as e2:
logging.error(f'ошибка DB в /dick :: обновление попытки крутить пипису @{message.from_user.username}')
logging.error(e2)
def update_dick_size(message, user, updatedDick ):
try:
metadata = collections.get_dicks_collection().insert(
{
'_key': user['_key'], ### этот нужен чтобы апдейт прилетал тому же юзеру
'user_id': user['user_id'],
'user_fullname': message.from_user.full_name,
'dick_size': updatedDick,
'datetimes': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
'attempts': user['attempts'] + 1,
'chat_id': message.chat.id
},
overwrite_mode='update'
)
metric_wrap(message.chat.id, message.from_user.full_name, updatedDick, user['attempts'] + 1)
logging.info(f'Успешно апдейтнули пипису @{message.from_user.username}')
except Exception as e2:
logging.error(f'ошибка DB в /dick :: обновление пиписы @{message.from_user.username}')
logging.error(e2)
def get_user(message):
try:
#### Чекнуть есть ли юзер в базе
candidate_cursor = collections.get_dicks_collection().find(
{
'user_id': message.from_user.id,
'chat_id': message.chat.id
},
skip = 0,
limit = 1488
)
if candidate_cursor.count() > 0:
user = candidate_cursor.pop()
else:
user = None
return user
except Exception as e:
logging.error('ошибка DB в /dick :: поиск юзера')
logging.error(e)

View File

@@ -1,12 +1,11 @@
import random import random
def RandomDick(): def RandomDick():
# Забирает рандомный синоним к слову хуй из dick_sinonims.txt # Забирает рандомный синоним к слову хуй из dick_sinonims.txt
# у линуха и винды не забывай про разные \/ # у линуха и винды не забывай про разные \/
# когда указываешь путь # кёгда указываешь путь
with open('dicktxt/dick_sinonims.txt', 'r', encoding='utf-8') as file: with open('dicktxt/dick_sinonims.txt', 'r', encoding='utf-8') as file:
words = file.readlines() words = file.readlines()
return random.choice(words).strip() return random.choice(words).strip()

View File

@@ -2,8 +2,7 @@ import yaml
import random import random
def ChangeWord(result): #выбирает рандомное слово для изменения размера пиписы def ChangeWord(result): #збiрає будь-якое слiво для змєнєння розмiра пiпiси
with open("dicktxt/dick_changes.yaml", 'r', encoding='utf-8') as f: with open("dicktxt/dick_changes.yaml", 'r', encoding='utf-8') as f:
words = yaml.load(f, Loader=yaml.Loader) words = yaml.load(f, Loader=yaml.Loader)
@@ -18,4 +17,4 @@ def ChangeWord(result): #выбирает рандомное слово для
else: else:
size_change = random.choice(dick_decr) + '' size_change = random.choice(dick_decr) + ''
return size_change return size_change

View File

@@ -1 +1,2 @@
from . import ForReadDict from . import ForReadDict

View File

@@ -1,6 +1,11 @@
import yaml import yaml
with open("config.yaml", 'r') as f: with open("config.yaml", 'r') as f:
CONFIG = yaml.load(f, Loader=yaml.Loader) CONFIG = yaml.load(f, Loader=yaml.Loader)
METRICS_INITIALIZED = False
pipisa_length_metric = None
user_attempt_metric = None
user_last_attempt_metric = None

View File

@@ -1,6 +1,4 @@
from handlers import pipisa from handlers import pipisa
from handlers import start_help from handlers import start_help
from handlers import time_new_year from handlers import time_new_year

View File

@@ -1,79 +1,57 @@
import openai from openai import AsyncOpenAI
from aiogram import types from aiogram import types
from create_bot import dp, bot from create_bot import dp, bot
import logging import logging
from global_conf import CONFIG from global_conf import CONFIG
admins = CONFIG['telegram_admins_ids']
token = CONFIG['openai']['token'] ban_comands = ['/dick','/topdick']
openai.api_key = CONFIG['openai']['api_key']
ban_comands = ['/dick','/topdick']
# Image_promt =['тупица сгенерируй','тупица сгенерируй картинку',\ # Image_promt =['тупица сгенерируй','тупица сгенерируй картинку',\
# 'тупица отправь картинку', 'тупица отправь картинку'] # 'тупица отправь картинку', 'тупица отправь картинку']
client = AsyncOpenAI(api_key="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")
# @dp.message_handler(commands=['image'])
# async def send_image(message: types.Message):
# if message.from_user.id in admins and message.chat.type == 'private':
# try:
# description = message.text.replace('/image', '').strip()
# if not description:
# await message.reply('Ты даун, описание запроса напиши после пробела')
# return
# except Exception as e:
# logging.error(f'Error in send_image: {e}')
# try:
@dp.message_handler(commands=['image']) # response = openai.Image.create(
async def send_image(message: types.Message): # prompt=message.text,
try: # n=1,
description = message.text.replace('/image', '').strip() # size="1024x1024",
# response_format="url",
if not description:
await message.reply('Ты даун, описание запроса напиши после пробела') # )
return # image_url = response['data'][0]['url']
except Exception as e: # await message.answer('Генерирую изображение...')
logging.error(f'Error in send_image: {e}') # await message.reply_photo(image_url)
try: # except Exception as e:
# await message.reply('у меня не получилось')
response = openai.Image.create( async def gpt_text(req):
prompt=message.text, completion = await client.chat.completions.create(
n=1, messages=[
size="1024x1024", {
response_format="url", "role": "user",
"content": req,
}
],
model="gpt-4",
) )
image_url = response['data'][0]['url'] return completion
await message.answer('Генерирую изображение...')
await message.reply_photo(image_url)
except Exception as e:
await message.reply('у меня не получилось')
@dp.message_handler() @dp.message_handler()
async def send(message: types.Message): async def send(message: types.Message):
if message.text.lower().startswith('тупица'): if message.from_user.id in admins and message.chat.type == 'private':
response = await gpt_text(message.text)
## TODO уточнить остатки токенов и денег await message.answer(response.choices[0].message.content)
response = openai.Completion.create(
model="text-davinci-003",
prompt=message.text[7:],
temperature=0.7,
max_tokens=1000,
top_p=1.0,
frequency_penalty=0.0,
presence_penalty=0.6,
stop=["сброс"]
)
await message.reply(response['choices'][0]['text'])
elif message.reply_to_message.from_user.is_bot:
response = openai.Completion.create(
model="text-davinci-003",
prompt=message.text,
temperature=0.7,
max_tokens=1000,
top_p=1.0,
frequency_penalty=0.0,
presence_penalty=0.6,
stop=["сброс"]
)
await message.reply(response['choices'][0]['text'])

30
handlers/metrics.py Normal file
View File

@@ -0,0 +1,30 @@
import json
import time
from prometheus_client import Gauge, Info
from global_conf import pipisa_length_metric, user_attempt_metric, user_last_attempt_metric
class user_info_struct:
user_id: str
user_fullname: str
dick_size: int
datetimes: str
attemptsCount: int
chat_id: int
def metric_wrap(chatID:int, userName: str, length: int, attemptsCount: int):
"""Pass here chat ID, username, pipisa length and attempts count to wrap them into metric."""
global pipisa_length_metric
if not pipisa_length_metric:
pipisa_length_metric = Gauge('user_length_total', 'Pipisa length', labelnames=['ChatID', 'Username'])
global user_attempt_metric
if not user_attempt_metric:
user_attempt_metric = Gauge('user_attempts_total', 'Attempts count', labelnames=['ChatID', 'Username'])
global user_last_attempt_metric
if not user_last_attempt_metric:
user_last_attempt_metric = Gauge('user_last_attempt_time', 'Last attempt time', labelnames=['ChatID', 'Username'])
pipisa_length_metric.labels(chatID, userName).set(length)
user_attempt_metric.labels(chatID, userName).set(attemptsCount)
user_last_attempt_metric.labels(chatID, userName).set(time.time_ns())

View File

@@ -2,202 +2,131 @@ from aiogram import types
from create_bot import bot, dp from create_bot import bot, dp
import random import random
from random import randint from random import randint
import datetime import datetime, logging
from dicktxt import ForReadDict, WordsChange from dicktxt import ForReadDict, WordsChange
from pipisa_functions import pipisa_time from pipisa_functions import pipisa_time
from global_conf import CONFIG from global_conf import CONFIG
from db_logic import tops, user_stuff, postcleaner
#### https://docs.python-arango.com/en/main/
from arango import ArangoClient
admins = CONFIG['telegram_admins_ids'] admins = CONFIG['telegram_admins_ids']
def get_dicks_collection():
arango_client = ArangoClient(hosts=CONFIG['databaso']['host'] )
pipisa_db = arango_client.db(
CONFIG['databaso']['base'],
username=CONFIG['databaso']['user'],
password=CONFIG['databaso']['pass']
)
dicks_collection = pipisa_db.collection(CONFIG['databaso']['collection'])
return dicks_collection
@dp.message_handler(commands=["dick"]) @dp.message_handler(commands=["dick"])
async def up_dick(message: types.Message): async def up_dick(message: types.Message):
if message.from_user.id in admins or message.chat.type != 'private': if message.from_user.id in admins or message.chat.type != 'private':
postcleaner.append_post_to_cleaning_sequence(message=message, type=f'COMMAND_CALL__DICK')
dicks_collection = get_dicks_collection() await clean_posts(chat_id=message.chat.id, type='COMMAND_CALL__DICK', max_id=message.message_id)
#### TODO уплатить нолог с 100 см для самого нищего #### TODO уплатить нолог с 100 см для самого нищего
# рандомайзер # рандомайзер
result = randint(-9,10) result = randint(-9,10)
try: #### Чекнуть есть ли юзер в базе
#### Чекнуть есть ли юзер в базе user = user_stuff.get_user(message)
candidate_cursor = dicks_collection.find(
{
'user_id': message.from_user.id,
'chat_id': message.chat.id
},
skip=0, limit=1488)
if candidate_cursor.count() > 0:
## Если есть то нарастить и отправить сообщение
user = candidate_cursor.pop() if user:
## Если есть то нарастить и отправить сообщение
if pipisa_time.rolltime(check_datetime=user['datetimes'], curr_time=datetime.datetime.now()): if pipisa_time.rolltime(check_datetime=user['datetimes'], curr_time=datetime.datetime.now()):
# пришло время крутить!! # пришло время крутить!!
updetedDick = user["dick_size"] + result
try:
dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
metadata = dicks_collection.insert(
{
'_key': user['_key'], ### этот нужен чтобы апдейт прилетал тому же юзеру
'user_id': user['user_id'],
'user_fullname': message.from_user.full_name,
'dick_size': updetedDick,
'datetimes': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
'attempts': user['attempts'] + 1,
'chat_id': message.chat.id
},
overwrite_mode='update'
)
print(f'Успешно апдейтнули пипису @{message.from_user.username}')
except Exception as e2:
print(f'ошибка в обновлении пиписы @{message.from_user.username}')
print(e2)
randomword = ForReadDict.RandomDick() updatedDick = user["dick_size"] + result
change_phrase = WordsChange.ChangeWord(result) user_stuff.update_dick_size(message, user, updatedDick)
await bot.send_message(message.chat.id, f'@{message.from_user.username}, ваш <em>{randomword}</em> {change_phrase}\ randomdickword = ForReadDict.RandomDick()
на <b>{abs(result)}</b> см!\n\ change_phrase = WordsChange.ChangeWord(result)
Теперь он равен <b>{updetedDick}</b> см! ')
else:
await bot.send_message(message.chat.id, f'@{message.from_user.username},🚫 вы уже крутили пипису, ее размер <b>{user["dick_size"]}</b> см! ')
try:
metadata = dicks_collection.insert(
{
'_key': user['_key'], ### этот нужен чтобы апдейт прилетал тому же юзеру
'user_id': user['user_id'] ,
'user_fullname': message.from_user.full_name,
'dick_size': user['dick_size'] ,
'datetimes': user['datetimes'] ,
'attempts': user['attempts'] + 1,
'chat_id': message.chat.id
},
overwrite_mode='update'
)
print(f'Успешно апдейтнули попытку крутить пипису @{message.from_user.username}')
except Exception as e2:
print(f'ошибка в обновлении попытки крутить пипису @{message.from_user.username}')
print(e2)
print(f'пользователь @{message.from_user.username} уже крутил') await bot.send_message( message.chat.id,
f'@{message.from_user.username}, ваш <em>{randomdickword}</em> {change_phrase} на <b>{abs(result)}</b> см!\nТеперь он равен <b>{updatedDick}</b> см! '
)
else:
mmm = await bot.send_message( message.chat.id,
f'@{message.from_user.username}, 🚫 вы уже крутили пипису, её размер <b>{user["dick_size"]}</b> см! '
)
user_stuff.update_attempts( message, user)
else: postcleaner.append_post_to_cleaning_sequence(message=mmm, type='ALREADY_ROLLED')
## если нету, то создать await clean_posts(chat_id=mmm.chat.id, type='ALREADY_ROLLED', max_id=mmm.message_id)
else:
try: ## если нету, то создать
novenkiy = { user_stuff.store_new_user(message, result)
'user_id': message.from_user.id,
'user_fullname': message.from_user.full_name,
'dick_size': result,
'datetimes': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
'attempts': 1,
'chat_id': message.chat.id
}
metadata = dicks_collection.insert(novenkiy, overwrite_mode='update')
if result > 0: await bot.send_message( message.chat.id,
await bot.send_message(message.chat.id, f'@{message.from_user.username}, ваш писюн показал головку 🚀\n\ f'@{message.from_user.username}, Добро пожаловать в игру! Ваш писюн показал головку 🚀\nна <b>{abs(result)}</b> см!\nТеперь он равен <b>{abs(result)}</b> см!'
на <b>{abs(result)}</b> см!\n\ )
Теперь он равен <b>{result}</b> см!')
else:
await bot.send_message(message.chat.id, f'@{message.from_user.username}, добро пожаловать в игру!🚀\n\
Ты стартуешь не с лучшей позиции, природа наградила тебя всего <b>{result}</b> см 😬')
print(f'Успешно добавлен пользователь @{message.from_user.username}')
except Exception as e1:
print('ошибка в добавлении нового пользователя')
print(e1)
except Exception as e:
print('ошибка DB в /dick')
print(e)
#### для всех отложенных сообщений
## проверить если прошло ?пять минут? с публикации
## попробовать удалить такой пост и затереть его с коллекции
## оставлять последние в чате топ- и глобал-дик, сохранять последние сообщения о приросте, сохранять последний вызов /dick и иной команды
else: else:
await message.reply('Растить елду можно только в общих чатах!') await message.reply('Растить елду можно только в общих чатах!')
@dp.message_handler(commands = ['topdick', 'globaldick'])
@dp.message_handler(commands=['topdick','globaldick'])
async def send_topchat(message: types.Message): async def send_topchat(message: types.Message):
if message.from_user.id in admins or message.chat.type != 'private': if message.from_user.id in admins or message.chat.type != 'private':
top_ = False top_ = message['text'].startswith('/topdick')
glob_ = False glob_ = message['text'].startswith('/globaldick')
dicks_collection = get_dicks_collection()
if message['text'] == '/topdick': if top_:
top_ = True dickos = tops.get_tops( top_ = True, chat_id=message.chat.id )
try: postcleaner.append_post_to_cleaning_sequence(message=message, type=f'COMMAND_CALL__TOPDICK')
dicks = dicks_collection.find({'chat_id': message.chat.id}, skip=0, limit=1100) await clean_posts(chat_id=message.chat.id, type='COMMAND_CALL__TOPDICK', max_id=message.message_id)
dicks = [d for d in dicks] elif glob_:
except Exception as e: dickos = tops.get_tops( glob_ = True )
print('ошибка DB в /topdick') postcleaner.append_post_to_cleaning_sequence(message=message, type=f'COMMAND_CALL__GLOBALDICK')
print(e) await clean_posts(chat_id=message.chat.id, type='COMMAND_CALL__GLOBALDICK', max_id=message.message_id)
elif message['text'] == '/globaldick':
glob_ = True
try:
dicks = dicks_collection.all( )
dicks = [d for d in dicks if d['user_id'] != d['chat_id']]
except Exception as e:
print('ошибка DB в /globaldick')
print(e)
else: else:
print('вызывают хз что!') logging.error('вызывают хз что!')
top_dicks = sorted(dicks, key=lambda dick: dick['dick_size'], reverse=True)
dick_limit = min(len(top_dicks), 10)
top_dicks = top_dicks[:dick_limit]
dickos = ''
emo = ['🏆','🚀','🍆','🍌','🐍','🐎','🌭','🌶','👌','💩']
if len(top_dicks) == 0: if not dickos:
await bot.send_message(message.chat.id, '🍆 Никто ничего не нарастил! 🍌') await bot.send_message(message.chat.id, '🍆 Никто ничего не нарастил! 🍌')
else: else:
for i in range(len(top_dicks)):
dickos += f' {emo[i]} {i+1}. {top_dicks[i]["user_fullname"]}: {top_dicks[i]["dick_size"]}см\n'
i += 1
if top_: if top_:
await bot.send_message(message.chat.id, '🏆Топ 10 бубылд чата🏆\n\n' + dickos) await bot.send_message(message.chat.id, '🏆Топ 10 бубылд чата🏆\n\n' + dickos)
elif glob_: elif glob_:
await bot.send_message(message.chat.id, '🏆Топ 10 пипис в мире🏆\n\n' + dickos) await bot.send_message(message.chat.id, '🏆Топ 10 пипис в мире🏆\n\n' + dickos)
else: else:
await message.reply('Работает только в общих чатах!\n'\ await message.reply('Работает только в общих чатах!\n'\
'Вы можете посмотреть топ по миру /globaldick') 'Вы можете посмотреть топ по миру /globaldick')
@dp.message_handler(commands = ['antitopdick', 'antiglobaldick'])
async def send_antitopchat(message: types.Message):
if message.from_user.id in admins or message.chat.type != 'private':
antitop_ = message['text'].startswith('/antitopdick')
antiglob_ = message['text'].startswith('/antiglobaldick')
if antitop_:
dickos = tops.get_antitops(top_=True, chat_id=message.chat.id)
postcleaner.append_post_to_cleaning_sequence(message=message, type=f'COMMAND_CALL__ANTITOPDICK')
await clean_posts(chat_id=message.chat.id, type='COMMAND_CALL__ANTITOPDICK', max_id=message.message_id)
elif antiglob_:
dickos = tops.get_antitops(glob_=True)
postcleaner.append_post_to_cleaning_sequence(message=message, type=f'COMMAND_CALL__ANTIGLOBALDICK')
await clean_posts(chat_id=message.chat.id, type='COMMAND_CALL__ANTIGLOBALDICK', max_id=message.message_id)
else:
logging.error('вызывают хз что!')
if not dickos:
await bot.send_message(message.chat.id, '🍌 У всех пользователей бубылда растёт! 🍆')
else:
if antitop_:
await bot.send_message(message.chat.id, '🚫Антитоп 10 вагись чата🚫\n\n' + dickos)
elif antiglob_:
await bot.send_message(message.chat.id, '🚫Антитоп 10 вагись в мире🚫\n\n' + dickos)
else:
await message.reply('Работает только в общих чатах!\n'\
'Вы можете посмотреть антитоп по миру /antiglobaldick')
async def clean_posts(chat_id, type=None, max_id=None):
psts = postcleaner.get_posts_to_be_removed(chat_id, type, max_id)
for p in psts:
postcleaner.del_post(chat_id=p['chat_id'], msg_id=p['msg_id'])
#### TODO проверить админит ли бот
try:
await bot.delete_message(chat_id=p['chat_id'], message_id=p['msg_id'])
except Exception as e:
logging.error('ошибка удаления поста-на-удаление')
logging.error(e)

View File

@@ -5,23 +5,14 @@ from create_bot import dp, bot
@dp.message_handler(commands=['start']) @dp.message_handler(commands=['start'])
async def start_func(message: types.Message): async def start_func(message: types.Message):
if message.chat.type == 'private': if message.chat.type == 'private':
lkb = InlineKeyboardMarkup(row_width=1).add(InlineKeyboardButton(text = 'Добавить в группу', callback_data='add_2_group')) lkb = InlineKeyboardMarkup(row_width=1).add(InlineKeyboardButton(text = 'Добавить в группу', callback_data='add_2_group'))
await message.answer(f'<b>Добро пожаловать, {message.from_user.full_name}!</b>\n' await message.answer(f'<b>Добро пожаловать, {message.from_user.full_name}!</b>\n'
'Это бот, который растит члены. Чтобы начать, добавь бота в чат'\ 'Это бот, который растит члены. Чтобы начать, добавь бота в чат'\
, reply_markup=lkb , reply_markup=lkb
) )
# TODO добавить кнопку, по которой смогут добавлять юзера в чат # TODO добавить кнопку, по которой смогут добавлять юзера в чат
@dp.callback_query_handler(text = 'add_2_group') @dp.callback_query_handler(text = 'add_2_group')
async def addgroup(callback: types.CallbackQuery): async def addgroup(callback: types.CallbackQuery):
await callback.answer('жмав') await callback.answer('жмав')

View File

@@ -4,10 +4,10 @@ import datetime
@dp.message_handler(commands=["time"]) @dp.message_handler(commands=["time"])
async def send_time(message: types.Message): async def send_time(message: types.Message):
new_year = datetime.datetime(datetime.now().year, 12, 31) #дата нового года new_year = datetime.datetime(datetime.datetime.now().year, 12, 31) #дата нового года
ct = datetime.datetime.now() #датавремя ct = datetime.datetime.now() #датавремя
cd = datetime.datetime.now().strftime("%d/%m/%Y") #дата (д,м,г) cd = datetime.datetime.now().strftime("%d/%m/%Y") #дата (д,м,г)
ct1 = ct+datetime.timedelta(hours=15) # +14 часов от сервера ct1 = ct # zoichem??? +datetime.timedelta(hours=15) # +14 часов от сервера
ct2 = ct1.strftime('%H:%M') # форматирует датувремя просто во время(ч,м) ct2 = ct1.strftime('%H:%M') # форматирует датувремя просто во время(ч,м)
raznitsa = (new_year - ct).days #отнимает от нг текущее время и получаем разницу в днях raznitsa = (new_year - ct).days #отнимает от нг текущее время и получаем разницу в днях
@@ -22,6 +22,5 @@ async def send_time(message: types.Message):
await message.reply(f'Сегодня {cd} \nВремя: {ct2} \nДо Нового Года осталось {num}') await message.reply(f'Сегодня {cd} \nВремя: {ct2} \nДо Нового Года осталось {num}')
def register_handlers_time(dp: Dispatcher): def register_handlers_time(dp: Dispatcher):
dp.register_message_handler(send_time) dp.register_message_handler(send_time)

15
jack_bot.service Normal file
View File

@@ -0,0 +1,15 @@
# пример того что лежит на хосте
[Unit]
Description=pipisa-bot
After=network.target
[Service]
User=jack
Type=simple
Restart=always
WorkingDirectory=/usr/share/python_bot
ExecStart=/usr/bin/python3 /usr/share/python_bot/bot.py
ExecStart=/usr/bin/python3 /usr/share/python_bot/bot.py
[Install]
WantedBy=multi-user.target#

View File

@@ -1,13 +1,10 @@
import unittest import unittest
import datetime import datetime
def rolltime(check_datetime , curr_time=datetime.datetime.now()): def rolltime(check_datetime , curr_time=datetime.datetime.now()):
last_time = datetime.datetime.strptime(check_datetime, '%Y-%m-%d %H:%M:%S') last_time = datetime.datetime.strptime(check_datetime, '%Y-%m-%d %H:%M:%S')
time_to_grow = curr_time.replace(hour=14, minute=8, second=8, microsecond=0) #+ datetime.timedelta(days=0) time_to_grow = curr_time.replace(hour=10, minute=0, second=0, microsecond=0) #+ datetime.timedelta(days=0)
timediff = (time_to_grow - last_time).total_seconds() timediff = (time_to_grow - last_time).total_seconds()
@@ -17,72 +14,64 @@ def rolltime(check_datetime , curr_time=datetime.datetime.now()):
# print(f'\tcurr_time : {curr_time.strftime("%Y-%m-%d %H:%M:%S")}') # print(f'\tcurr_time : {curr_time.strftime("%Y-%m-%d %H:%M:%S")}')
# print(f'\t\tsecs diff : {timediff}') # print(f'\t\tsecs diff : {timediff}')
if timediff > 86400 or (curr_time > time_to_grow and last_time < time_to_grow): if timediff > 86400 or (curr_time > time_to_grow and last_time < time_to_grow):
return True return True
else: else:
return False return False
class TestPipisa(unittest.TestCase): class TestPipisa(unittest.TestCase):
def test_very_long_ago(self): def test_very_long_ago(self):
self.assertEqual(rolltime('2021-10-11 23:44:00'), True, "Пиписа прокручена очень давно. Очевидный прокрут") self.assertEqual(rolltime('2021-10-11 23:44:00'), True, "Пиписа прокручена очень давно. Очевидный прокрут")
def test_just_after(self): def test_just_after(self):
self.assertEqual(rolltime( self.assertEqual(rolltime(
datetime.datetime.now().replace(hour=14, minute=9, second=8, microsecond=0).strftime('%Y-%m-%d %H:%M:%S') datetime.datetime.now().replace(hour=10, minute=1, second=0, microsecond=0).strftime('%Y-%m-%d %H:%M:%S')
), False, "Попытка крутить когда старый прокрут был через 1 минуту после сегодняшнего обновления роллов. Фейл.") ), False, "Попытка крутить когда старый прокрут был через 1 минуту после сегодняшнего обновления роллов. Фейл.")
def test_yesterdayroll(self): def test_yesterdayroll(self):
self.assertEqual( self.assertEqual(
rolltime( rolltime(
( (
datetime.datetime.now().replace(hour=14, minute=9, second=8, microsecond=0) - datetime.timedelta(days=1) datetime.datetime.now().replace(hour=10, minute=1, second=0, microsecond=0) - datetime.timedelta(days=1)
).strftime('%Y-%m-%d %H:%M:%S'), ).strftime('%Y-%m-%d %H:%M:%S'),
datetime.datetime.now().replace(hour=14, minute=9, second=8, microsecond=0) datetime.datetime.now().replace(hour=10, minute=1, second=0, microsecond=0)
), True, "Крутилась вчера через минуту после обновления роллов. Должно пропускать ") ), True, "Крутилась вчера через минуту после обновления роллов. Должно пропускать ")
def test_hour_before_roll(self):
def test_hour_before_roll(self):
self.assertEqual( self.assertEqual(
rolltime( rolltime(
( (
datetime.datetime.now().replace(hour=14, minute=9, second=8, microsecond=0) - datetime.timedelta(hours=1) datetime.datetime.now().replace(hour=10, minute=1, second=1, microsecond=0) - datetime.timedelta(hours=1)
).strftime('%Y-%m-%d %H:%M:%S'), ).strftime('%Y-%m-%d %H:%M:%S'),
datetime.datetime.now().replace(hour=14, minute=9, second=8, microsecond=0) datetime.datetime.now().replace(hour=10, minute=1, second=0, microsecond=0)
), True, "Крутилась последний раз за час до прокрута. Надо разрешать заново!") ), True, "Крутилась последний раз за час до прокрута. Надо разрешать заново!")
def test_after_midnight(self): def test_after_midnight(self):
self.assertEqual( self.assertEqual(
rolltime( rolltime(
( (
datetime.datetime.now().replace(hour=14, minute=9, second=8, microsecond=0) - datetime.timedelta(hours=14) datetime.datetime.now().replace(hour=10, minute=1, second=0, microsecond=0) - datetime.timedelta(hours=14)
).strftime('%Y-%m-%d %H:%M:%S'), ).strftime('%Y-%m-%d %H:%M:%S'),
datetime.datetime.now().replace(hour=0, minute=11, second=8, microsecond=0) datetime.datetime.now().replace(hour=0, minute=11, second=8, microsecond=0)
), False, "Где-то ночью прокручивается повторно. Фейл.") ), False, "Где-то ночью прокручивается повторно. Фейл.")
def test_before_midnight(self): def test_before_midnight(self):
self.assertEqual( self.assertEqual(
rolltime( rolltime(
( (
datetime.datetime.now().replace(hour=14, minute=9, second=8, microsecond=0) - datetime.timedelta(hours=15) datetime.datetime.now().replace(hour=10, minute=1, second=0, microsecond=0) - datetime.timedelta(hours=15)
).strftime('%Y-%m-%d %H:%M:%S'), ).strftime('%Y-%m-%d %H:%M:%S'),
datetime.datetime.now().replace(hour=0, minute=11, second=8, microsecond=0) - datetime.timedelta(hours=15) datetime.datetime.now().replace(hour=0, minute=11, second=8, microsecond=0) - datetime.timedelta(hours=15)
), False, "Где-то ночью прокручивается повторно. Фейл.") ), False, "Где-то ночью прокручивается повторно. Фейл.")
def test_somewhere_after(self): def test_somewhere_after(self):
self.assertEqual( self.assertEqual(
rolltime( rolltime(
( (
datetime.datetime.now().replace(hour=14, minute=26, second=8, microsecond=0) datetime.datetime.now().replace(hour=10, minute=18, second=0, microsecond=0)
).strftime('%Y-%m-%d %H:%M:%S'), ).strftime('%Y-%m-%d %H:%M:%S'),
datetime.datetime.now().replace(hour=14, minute=27, second=8, microsecond=0) datetime.datetime.now().replace(hour=10, minute=19, second=0, microsecond=0)
), False, "Сегодня уже открутили а хотят ещё. Фейл.") ), False, "Сегодня уже открутили а хотят ещё. Фейл.")
if __name__ == "__main__": if __name__ == "__main__":
unittest.main(verbosity=2) unittest.main(verbosity=2)

View File

@@ -1,3 +1,4 @@
aiogram aiogram==2.15
python-arango python-arango
pyyaml pyyaml
prometheus-client