Обновление на 4.25

master
ssleg 2022-09-26 19:06:52 +03:00
parent 0aeaed5f18
commit 9c315d6f35
Signed by: anton
GPG Key ID: 50F7E97F96C07ECF
4 changed files with 373 additions and 178 deletions

View File

@ -1,5 +1,5 @@
# Bot I/O v1.70
# 14/06/2021
# Bot I/O v1.82
# 15/11/2021
# https://t.me/ssleg © 2020 2021
import logging
@ -20,7 +20,7 @@ client: TelegramClient
msk_hour = timedelta(hours=3)
sys_wait = 0.045
manager_runned = GlobalFlag()
manager_run = GlobalFlag()
work_queue = OutMessagesQueue()
tg_flood_wait = GlobalFlag()
last_send_time: datetime
@ -54,7 +54,7 @@ class IncomingMessagesTimeBuffer:
self.__buf = []
self.__size = size
self.__user_id = user_id
cursor.execute('select ban_count, ban_to_date from banlist where user_id=?', (user_id,))
cursor.execute('select ban_count, ban_to_date from ban_list where user_id=?', (user_id,))
row = cursor.fetchone()
if row is not None:
self.__banned_to = datetime.strptime(row[1], '%Y-%m-%d %H:%M:%S')
@ -80,17 +80,18 @@ class IncomingMessagesTimeBuffer:
def __is_valid_timing(self, mess_date):
i = self.__size - 1
sec = 0
while i > self.__size - 4:
# while i > self.__size - 4:
while i > 5:
prev_date = self.__buf[i][1]
if prev_date != 0:
tmp = mess_date - prev_date
if tmp.seconds < 1:
'''if tmp.seconds < 1:
levent = 'обнаружено слишком частое обращение: ' + str(tmp.seconds) + ' сек.'
logging.warning(levent)
return False
else:
sec += tmp.seconds
mess_date = prev_date
else:'''
sec += tmp.seconds
mess_date = prev_date
else:
return True
i -= 1
@ -98,7 +99,7 @@ class IncomingMessagesTimeBuffer:
if sec >= 5:
return True
else:
levent = 'обнаружены 4 сообщенния за ' + str(sec) + ' сек.'
levent = 'обнаружены 15 сообщений за ' + str(sec) + ' сек.'
logging.warning(levent)
return False
@ -127,10 +128,10 @@ class IncomingMessagesTimeBuffer:
if self.__ban_count == 1:
entry = (self.__user_id, self.__ban_count, str(self.__banned_to)[0:19])
cursor.execute('insert into banlist (user_id, ban_count, ban_to_date) values (?,?,?)', entry)
cursor.execute('insert into ban_list (user_id, ban_count, ban_to_date) values (?,?,?)', entry)
else:
entry = (self.__ban_count, str(self.__banned_to)[0:19], self.__user_id)
cursor.execute('update banlist set ban_count=?, ban_to_date=? where user_id=?', entry)
cursor.execute('update ban_list set ban_count=?, ban_to_date=? where user_id=?', entry)
con.commit()
return rez
@ -143,6 +144,7 @@ class IncomingMessagesTimeBuffer:
return 2
# TODO Дополнить логирование кнопок
class BotIncomingMessagesOrder:
"""класс порядка сообщений в диалогах"""
@ -157,16 +159,16 @@ class BotIncomingMessagesOrder:
mess_date = message.date + msk_hour
user_id = message.peer_id.user_id
txt = message.text
indx = self.__users.get(user_id)
if indx is None:
indx = len(self.__orders)
self.__users[user_id] = indx
index = self.__users.get(user_id)
if index is None:
index = len(self.__orders)
self.__users[user_id] = index
self.__orders.append(IncomingMessagesTimeBuffer(20, user_id))
if debug:
levent = 'открыт новый буфер, id - ' + str(user_id)
logging.info(levent)
order_result = self.__orders[indx].store_mess(mess_id, mess_date)
order_result = self.__orders[index].store_mess(mess_id, mess_date)
if debug or io_write:
if order_result not in [1, 2]:
entry = (mess_id, str(mess_date)[0:19], user_id, txt)
@ -178,15 +180,15 @@ class BotIncomingMessagesOrder:
# менеджер отложенной отправки сообщений
async def queue_manager():
if not manager_runned:
manager_runned.set_true()
if not manager_run:
manager_run.set_true()
levent = 'менеджер отложенных сообщений стартовал.'
logging.info(levent)
now = datetime.now()
delta = now - last_send_time
if delta.total_seconds() < 0:
tsec = delta.total_seconds()
seconds = abs(tsec // 1 + 1)
t_sec = delta.total_seconds()
seconds = abs(t_sec // 1 + 1)
levent = 'ожидание разрешения на отправку - ' + str(seconds) + ' сек.'
logging.info(levent)
await sleep(seconds)
@ -200,11 +202,14 @@ async def queue_manager():
user_id = entry[0]
message = entry[1]
file_name = entry[2]
buttons = entry[3]
contact_add = entry[4]
await sleep(sys_wait)
if debug:
levent = 'попытка отправки сообщения для user_id = ' + str(user_id)
logging.info(levent)
result_flag = await send_reply_message(user_id, message, file_name, log_parameter=True, from_queue=True)
result_flag = await send_reply_message(user_id, message, file_name, buttons, log_parameter=True,
contact_add=contact_add, from_queue=True)
work_queue.set_sending_result(result_flag)
if result_flag:
mess_success += 1
@ -212,7 +217,7 @@ async def queue_manager():
else:
break
manager_runned.set_false()
manager_run.set_false()
levent = 'менеджер отложенных сообщений закончил. попыток - ' + str(mess_count) + ', отправлено - ' + str(
mess_success)
logging.info(levent)
@ -220,22 +225,24 @@ async def queue_manager():
client.loop.create_task(queue_manager())
def message_to_queue(user_id, mess, file_name):
work_queue.add_message(user_id, mess, file_name)
if not manager_runned:
def message_to_queue(user_id, mess, file_name, buttons, contact_add):
work_queue.add_message(user_id, mess, file_name, buttons, contact_add)
if not manager_run:
client.loop.create_task(queue_manager())
# TODO Сделать поддержку форвардов
# отправка сообщений пользователю с соблюдением требований тг
async def send_reply_message(user_id, message, file_name=None, log_parameter=False, contact_add=True, from_queue=False):
async def send_reply_message(user_id, message, file_name=None, buttons=None, log_parameter=False, contact_add=True,
from_queue=False):
global last_send_time
now = datetime.now()
delta = now - last_send_time
if not from_queue:
find_flag, indx = work_queue.is_user_in_queue(user_id)
find_flag, index = work_queue.is_user_in_queue(user_id)
if find_flag:
message_to_queue(user_id, message, file_name)
message_to_queue(user_id, message, file_name, buttons, contact_add)
levent = 'ответ поставлен в очередь. user_id = ' + str(user_id)
logging.warning(levent)
return False
@ -245,7 +252,7 @@ async def send_reply_message(user_id, message, file_name=None, log_parameter=Fal
user_delta = now - timestamp
if user_delta.total_seconds() < 1:
if not from_queue:
message_to_queue(user_id, message, file_name)
message_to_queue(user_id, message, file_name, buttons, contact_add)
levent = 'ответ поставлен в очередь, дельта пользователя - ' + str(
user_delta.total_seconds()) + ' сек. user_id = ' + str(user_id)
logging.warning(levent)
@ -253,7 +260,7 @@ async def send_reply_message(user_id, message, file_name=None, log_parameter=Fal
if delta.total_seconds() > 0.04:
try:
await client.send_message(user_id, message, file=file_name)
await client.send_message(user_id, message, file=file_name, buttons=buttons)
last_send_time = datetime.now()
if log_parameter or debug:
@ -278,25 +285,32 @@ async def send_reply_message(user_id, message, file_name=None, log_parameter=Fal
except errors.FloodWaitError as e:
seconds = e.seconds
levent = 'антифлуд телеграм сработал, время ожидания - ' + str(seconds) + ' сек.'
levent = 'сработал телеграм flood_wait, время ожидания - ' + str(seconds) + ' сек.'
logging.warning(levent)
tg_flood_wait.set_true()
last_send_time = now + timedelta(seconds=seconds + 1)
if not from_queue:
message_to_queue(user_id, message, file_name)
message_to_queue(user_id, message, file_name, buttons, contact_add)
return False
except errors.UserIsBlockedError as e:
levent = 'пользователь заблокировал бота (user_id = ' + str(user_id) + '): ' + str(e)
if debug:
logging.warning(levent)
if from_queue:
return True
return False
except Exception as e:
levent = 'что-то пошло не так при отправке (user_id = ' + str(user_id) + '): ' + str(e)
if debug:
logging.error(levent)
else:
logging.warning(levent)
logging.error(levent)
if from_queue:
return True
return False
else:
if not from_queue:
message_to_queue(user_id, message, file_name)
message_to_queue(user_id, message, file_name, buttons, contact_add)
levent = 'ответ поставлен в очередь, дельта - ' + str(delta.total_seconds()) + ' сек. user_id = ' + str(
user_id)
logging.warning(levent)
@ -354,7 +368,7 @@ async def init(cli, debug_mode, adm_ids, io_write_mode):
account_name text
);
CREATE TABLE banlist
CREATE TABLE ban_list
(
user_id int,
ban_count int,
@ -374,14 +388,14 @@ async def init(cli, debug_mode, adm_ids, io_write_mode):
# завершение работы
async def terminate():
if manager_runned:
if manager_run:
levent = 'bot I/O, ожидание отправки всех сообщений.'
logging.info(levent)
count = 6
while count > 0:
await sleep(5)
count -= 1
if not manager_runned:
if not manager_run:
break
con.close()
levent = 'bot I/O остановлен.'

View File

@ -1,10 +1,11 @@
# Bot I/O classes v1.00
# 14/06/2021
# https://t.me/ssleg © 2020 2021
# Bot I/O classes v1.03
# 15/11/2021
# https://t.me/ssleg © 2021
from datetime import datetime
# TODO Сделать нормальную инициализацию модуля
class TgBotUsers:
"""класс хранения пользователей бота"""
@ -21,8 +22,8 @@ class TgBotUsers:
f_name = row[1]
l_name = row[2]
user_acc = row[3]
indx = len(self.__timestamps)
self.__users[user_id] = (indx, f_name, l_name, user_acc)
index = len(self.__timestamps)
self.__users[user_id] = (index, f_name, l_name, user_acc)
self.__timestamps.append(datetime(year=2020, month=1, day=1))
def is_bot_user(self, user_id):
@ -43,29 +44,29 @@ class TgBotUsers:
values (?,?,?,?)''', entry)
self.__con.commit()
timestamp = datetime.now()
indx = len(self.__timestamps)
self.__users[user_id] = (indx, f_name, l_name, user_acc)
index = len(self.__timestamps)
self.__users[user_id] = (index, f_name, l_name, user_acc)
self.__timestamps.append(timestamp)
def update_user_mess_timestamp(self, user_id):
timestamp = datetime.now()
user = self.__users.get(user_id)
if user is not None:
indx = user[0]
self.__timestamps[indx] = timestamp
index = user[0]
self.__timestamps[index] = timestamp
def get_user_mess_timestamp(self, user_id):
user = self.__users.get(user_id)
if user is not None:
indx = user[0]
return self.__timestamps[indx]
index = user[0]
return self.__timestamps[index]
else:
return datetime(year=2020, month=1, day=1)
def get_users_list(self):
excluded_users = []
now = datetime.now()
self.__cursor.execute('select user_id, ban_to_date from banlist')
self.__cursor.execute('select user_id, ban_to_date from ban_list')
for row in self.__cursor.fetchall():
banned_to = datetime.strptime(row[1], '%Y-%m-%d %H:%M:%S')
delta = now - banned_to
@ -95,21 +96,21 @@ class OutMessagesQueue:
def is_user_in_queue(self, user_id):
i = 0
finded_flag = False
found_flag = False
while i < len(self.__queue):
if self.__queue[i][0] == user_id:
finded_flag = True
found_flag = True
break
i += 1
return finded_flag, i
return found_flag, i
def add_message(self, user_id, message_text, file_name):
finded_flag, i = self.is_user_in_queue(user_id)
if not finded_flag:
def add_message(self, user_id, message_text, file_name, buttons, contact_add):
found_flag, i = self.is_user_in_queue(user_id)
if not found_flag:
self.__queue.append([user_id])
self.__queue[i].append((user_id, message_text, file_name))
self.__queue[i].append((user_id, message_text, file_name, buttons, contact_add))
def get_next_message(self):
element = self.__queue[self.__position_i][1]

62
magic.py Executable file → Normal file
View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
# Magic wand v4.23
# 14/06/2021
# Magic wand v4.25
# 26/09/2021
# https://t.me/ssleg © 2020 2021
import logging
@ -18,6 +18,7 @@ from telethon import TelegramClient, events
import bot_io
import main_module
# import module_two
from tg_utils import get_tg_client, get_bot_key, GlobalFlag, GlobalCounter
# загрузка конфигурации из ini файла
@ -52,8 +53,8 @@ bot_account = bot_config.get('bot_db_account', 'bot_account')
# глобальные переменные
sigterm_flag = GlobalFlag()
logsize = GlobalCounter()
laststring = GlobalCounter()
log_size = GlobalCounter()
last_string = GlobalCounter()
error_count = GlobalCounter()
started_time: datetime
@ -61,6 +62,7 @@ next_stat = GlobalCounter(3600)
# инициализация лога и параметров подключения
log_file = RotatingFileHandler(logfile_name, 'a', maxBytes=524288, backupCount=10, encoding='utf=8')
# noinspection SpellCheckingInspection
log_file.setFormatter(logging.Formatter('%(levelname)s %(module)-13s [%(asctime)s] %(message)s'))
# noinspection PyArgumentList
logging.basicConfig(level=logging.INFO, handlers=[log_file])
@ -101,14 +103,14 @@ def get_my_version():
# записывает начальные параметры лог-файла
def init_log_var():
logsize.set(path.getsize(logfile_name))
log_size.set(path.getsize(logfile_name))
file = open(logfile_name, 'r', encoding='utf-8')
allfile = file.readlines()
all_file = file.readlines()
file.close()
laststring.set(len(allfile))
levent = 'начальные параметры этого логфайла: ' + str(logsize) + ' байт, ' + str(laststring) + ' строк.'
last_string.set(len(all_file))
levent = 'начальные параметры этого лог-файла: ' + str(log_size) + ' байт, ' + str(last_string) + ' строк.'
logging.info(levent)
@ -127,12 +129,13 @@ async def init():
await bot_io.init(client, debug, admins_ids, io_write)
await main_module.init(client, debug, admins_ids)
# await module_two.init(client)
levent = 'инициализация завершена.'
logging.info(levent)
# возвращает строку со временем аптайма
# возвращает строку со временем аптайм
def get_uptime():
now = datetime.now()
delta = now - started_time
@ -155,7 +158,7 @@ def get_up_seconds():
return delta.days * 86400 + delta.seconds
# эвент хэндлер, отвечающий за команды админа (статистика работы, рассылки)
# обработчик событий, отвечающий за команды админа (статистика работы, рассылки)
async def admins_command(event):
from_id = event.message.peer_id.user_id
command = event.message.text
@ -191,7 +194,7 @@ def stat_upload():
'Content-Type': 'application/json; charset=utf-8'
}
# noinspection HttpUrlsUsage
stat_upload_url = 'http://77.83.92.107/stat_up'
stat_upload_url = 'http://188.124.50.148/stat_up'
hash_md5 = md5(bot_key.encode())
request_json = {'protocol_version': '1.1', 'application': 'Magic Wand', 'app_version': get_my_version(),
'uptime': get_up_seconds(), 'errors': error_count.get(), 'fingerprint': hash_md5.hexdigest()}
@ -225,11 +228,11 @@ async def send_notices(mess):
logging.info(levent)
# чтение изменений логфайла и поиск ошибок в нем
# чтение изменений лог-файла и поиск ошибок в нем
def log_reader():
file = open(logfile_name, 'r', encoding='utf-8')
readcount = 0
workcount = laststring.get()
read_count = 0
work_count = last_string.get()
i = 0
flag = False
errmsg = ''
@ -237,9 +240,9 @@ def log_reader():
while i < 1:
string = file.readline()
if string != '':
readcount += 1
if readcount > workcount:
laststring.increment()
read_count += 1
if read_count > work_count:
last_string.increment()
if flag:
if len(string) > 1:
if string.find('[20') > -1:
@ -260,12 +263,12 @@ def log_reader():
file.close()
# наблюдатель за логфайлом, проверяет изменения раз в минуту
# наблюдатель за лог-файлом, проверяет изменения раз в минуту
def log_watcher():
if sigterm_flag:
filesize = path.getsize(logfile_name)
if filesize > logsize:
logsize.set(filesize)
if filesize > log_size:
log_size.set(filesize)
client.loop.call_soon(log_reader)
if bot_stats:
@ -286,7 +289,7 @@ async def terminate():
logging.info(levent)
# хэндлер сигнала сигтерм, возникающего при перезапуске системы или бота.
# обработчик сигнала sigterm, возникающего при перезапуске системы или бота.
# вызывает процедуру корректного завершения бота и модулей
# noinspection PyUnusedLocal
def sigterm_call(signum, frame):
@ -297,14 +300,15 @@ def sigterm_call(signum, frame):
client.loop.create_task(terminate())
signal.signal(signal.SIGTERM, sigterm_call)
# старт telethon и основной инициализации
client.start(bot_token=bot_key)
client.loop.run_until_complete(init())
if __name__ == '__main__':
signal.signal(signal.SIGTERM, sigterm_call)
started_time = datetime.now()
client.add_event_handler(admins_command, events.NewMessage(chats=admins_ids, incoming=True))
client.loop.call_later(60, log_watcher)
client.start(bot_token=bot_key)
client.loop.run_until_complete(init())
client.run_until_disconnected()
started_time = datetime.now()
client.add_event_handler(admins_command, events.NewMessage(chats=admins_ids, incoming=True))
client.loop.call_later(60, log_watcher)
client.run_until_disconnected()

View File

@ -1,79 +1,144 @@
# Tg utils v2.22
# 14/06/2021
# Tg utils v2.50
# 10/10/2021
# https://t.me/ssleg © 2020 2021
import logging
from datetime import datetime
from time import sleep
import psycopg2
import psycopg2.extensions
from telethon import TelegramClient
# TODO Добавить executemany и executescript
class PgServer:
"""класс postgres-сервер"""
__slots__ = ['__con', '__control_flag', '__cursor', '__db_name']
__slots__ = ['__con', '__cursor', '__db_name', '__db_host', '__retry_count', '__version', '__connected']
def __init__(self, dbc=None, db_name='mydb'):
if dbc is None:
self.__con = psycopg2.connect(database=db_name,
def __init__(self, db_name='tg_bots', db_host='127.0.0.1'):
self.__con: psycopg2.extensions.connection
self.__cursor: psycopg2.extensions.cursor
self.__db_name = db_name
self.__db_host = db_host
self.__retry_count = 0
self.__connected = False
self.__version = ''
self.__establish_connect(first_connect=True)
def __establish_connect(self, first_connect=False):
self.__connected = False
while not self.__connected and self.__retry_count < 3:
self.__connected = self.__connect(first_connect=first_connect)
if not self.__connected:
self.__retry_count += 1
sleep(1)
if not self.__connected:
if first_connect:
levent = 'postgresql, подключиться к базе не удалось.'
else:
levent = 'postgresql, восстановить соединение не удалось.'
logging.error(levent)
else:
if not first_connect:
levent = 'postgresql, соединение восстановлено.'
logging.info(levent)
else:
sql = "select setting from pg_config where name='VERSION'"
row = self.exec(sql, return_type=1)
self.__version = row[0]
def __connect(self, first_connect=False):
try:
if not first_connect:
self.__cursor.close()
self.__con.close()
self.__con = psycopg2.connect(database=self.__db_name,
user='postgres',
password='1234',
host='127.0.0.1',
host=self.__db_host,
port='5432')
self.__control_flag = True
self.__db_name = db_name
else:
self.__con = dbc
self.__control_flag = False
self.__db_name = ''
self.__cursor = self.__con.cursor()
def commit(self):
self.__con.commit()
def rollback(self):
self.__con.rollback()
def exec(self, sql, req_data=None, return_type=None, retry_count=0):
try:
if req_data is not None:
self.__cursor.execute(sql, req_data)
else:
self.__cursor.execute(sql)
if return_type is not None:
if return_type == 0:
return self.__cursor.fetchall()
else:
return self.__cursor.fetchone()
else:
return True
self.__cursor = self.__con.cursor()
self.__retry_count = 0
return True
except Exception as e:
levent = 'postgres error: ' + str(e)
logging.error(levent)
if self.__control_flag:
if retry_count < 3:
self.__con.close()
self.__con = psycopg2.connect(database=self.__db_name,
user='postgres',
password='1234',
host='127.0.0.1',
port='5432')
self.__cursor = self.__con.cursor()
return self.exec(sql, req_data, return_type, retry_count=retry_count + 1)
if first_connect:
levent = 'postgresql, ошибка подключения к бд: ' + str(e)
else:
levent = 'postgresql, ошибка при восстановлении подключения: ' + str(e)
logging.warning(levent)
return False
def __del__(self):
self.__cursor.close()
if self.__control_flag:
self.__con.close()
else:
def commit(self):
if self.__connected:
self.__con.commit()
return True
return
def rollback(self):
if self.__connected:
self.__con.rollback()
return True
return False
def exec(self, sql, req_data=None, return_type=None):
if self.__connected:
try:
if req_data is not None:
self.__cursor.execute(sql, req_data)
else:
self.__cursor.execute(sql)
if return_type is not None:
if return_type == 0:
return self.__cursor.fetchall()
else:
return self.__cursor.fetchone()
else:
return True
except psycopg2.IntegrityError as e:
levent = 'postgresql, ошибка целостности данных: ' + str(e.pgerror)
logging.error(levent)
return False
except psycopg2.OperationalError as e:
disconnect_codes = ['57P01', '57P02', '57P03']
if e.pgcode in disconnect_codes:
levent = 'postgresql отвалился, ошибка: ' + str(e.pgerror)
logging.warning(levent)
self.__establish_connect()
if not self.__connected:
return False
else:
return self.exec(sql, req_data, return_type)
else:
levent = 'postgresql, операционная ошибка: ' + str(e)
logging.error(levent)
return False
except Exception as e:
levent = 'postgresql, ошибка: ' + str(e)
logging.error(levent)
return False
return False
def is_connected(self):
return self.__connected
def get_version(self):
return self.__version
def __str__(self):
return self.__version
def __del__(self):
if self.__connected:
self.__cursor.close()
self.__con.close()
class PgLock:
@ -81,9 +146,9 @@ class PgLock:
__slots__ = ['__srv', '__cursor', '__lock_name', '__debug']
def __init__(self, dbc=None, lck='default_lock', debug=False):
self.__srv = PgServer(dbc)
self.__lock_name = lck
def __init__(self, lock_name='default', debug=False):
self.__srv = PgServer()
self.__lock_name = lock_name
self.__debug = debug
def lock(self):
@ -157,16 +222,23 @@ class GlobalCounter:
def __isub__(self, other):
if GlobalCounter.__is_valid_arg(other):
self.__count -= other
return self
def __iadd__(self, other):
if GlobalCounter.__is_valid_arg(other):
self.__count += other
return self
def __eq__(self, other):
if self.__count == other:
return True
return False
def __ne__(self, other):
if self.__count != other:
return True
return False
def __ge__(self, other):
if self.__count >= other:
return True
@ -183,7 +255,7 @@ class GlobalCounter:
return False
def __lt__(self, other):
if self.__count <= other:
if self.__count < other:
return True
return False
@ -221,6 +293,119 @@ class GlobalFlag:
return str(self.__flag)
class GlobalFloat:
"""глобальная универсальная переменная"""
__slots__ = ['__value']
@staticmethod
def __is_valid_arg(arg):
if type(arg) is int or type(arg) is float:
return True
return False
def __init__(self, init_value=0):
if GlobalFloat.__is_valid_arg(init_value):
self.__value = float(init_value)
else:
self.__value = 0
def get(self):
return self.__value
def set(self, value):
if GlobalFloat.__is_valid_arg(value):
self.__value = float(value)
return True
return False
def __isub__(self, other):
if GlobalFloat.__is_valid_arg(other):
self.__value -= other
return self
def __iadd__(self, other):
if GlobalFloat.__is_valid_arg(other):
self.__value += other
return self
def __radd__(self, other):
if GlobalFloat.__is_valid_arg(other):
return other + self.__value
def __rsub__(self, other):
if GlobalFloat.__is_valid_arg(other):
return other - self.__value
def __add__(self, other):
if GlobalFloat.__is_valid_arg(other):
return self.__value + other
def __sub__(self, other):
if GlobalFloat.__is_valid_arg(other):
return self.__value - other
def __eq__(self, other):
if self.__value == other:
return True
return False
def __ne__(self, other):
if self.__value != other:
return True
return False
def __ge__(self, other):
if self.__value >= other:
return True
return False
def __gt__(self, other):
if self.__value > other:
return True
return False
def __le__(self, other):
if self.__value <= other:
return True
return False
def __lt__(self, other):
if self.__value < other:
return True
return False
def __str__(self):
return str(round(self.__value, 2))
class ErrorClass:
"""класс возврата ошибки с кодом"""
__slots__ = ['__success', '__error_code']
def __init__(self):
self.__success = True
self.__error_code = 0
def set_error(self, error_code: int):
self.__success = False
if 0 < error_code < 1000 and type(error_code) == int:
self.__error_code = error_code
def get_error_code(self):
return self.__error_code
def __bool__(self):
return self.__success
def __str__(self):
if self.__success:
return 'No error'
else:
return 'Error code: ' + str(self.__error_code)
def t_stamp():
now = datetime.now()
stamp = datetime.strftime(now, '%d/%m %Y %H:%M:%S')
@ -233,12 +418,12 @@ def t_stamp_sh():
return stamp
# ловеркейс имени tg канала с проверкой валидности
def set_ch_name_lower(teststr):
# lowercase имени tg канала с проверкой валидности
def set_ch_name_lower(test_str):
i = 0
rezult = ''
while i < len(teststr):
char = teststr[i]
result = ''
while i < len(test_str):
char = test_str[i]
code = ord(char)
if code == 95:
@ -253,13 +438,13 @@ def set_ch_name_lower(teststr):
if 96 < code < 123:
pass
else:
levent = 'ошибка конвертации канала: ' + str(i) + ' ' + str(code) + ' ' + char + ' ' + teststr
levent = 'ошибка конвертации канала: ' + str(i) + ' ' + str(code) + ' ' + char + ' ' + test_str
logging.warning(levent)
return False
rezult += chr(code)
result += chr(code)
i += 1
return rezult
return result
# сборка имени юзера в читабельное
@ -281,45 +466,36 @@ def set_name_printable(first, last, account=None, phone=None, ad=''):
# вывод числа с разделителями тысяч
def set_int_printable(integer, razd=' '):
def set_int_printable(integer, separator=' '):
string = '{:,}'.format(integer)
string = string.replace(',', razd)
string = string.replace(',', separator)
return string
# версия сервера постгрес
def get_server_version(dbc=None):
srv = PgServer(dbc)
sql = "select setting from pg_config where name='VERSION'"
row = srv.exec(sql, return_type=1)
version = row[0]
return version
# создает обьект клиента с параметрами из бд
def get_tg_client(name, dbc=None, cust_name=None):
srv = PgServer(dbc)
# создает объект клиента с параметрами из бд
def get_tg_client(name, custom_name=None):
srv = PgServer()
n_api = name + '_api_id'
row = srv.exec('select value from parameters where name=%s', (n_api,), return_type=1)
row = srv.exec('select value from logins where name=%s', (n_api,), return_type=1)
api_id = int(row[0])
n_hash = name + '_api_hash'
row = srv.exec('select value from parameters where name=%s', (n_hash,), return_type=1)
row = srv.exec('select value from logins where name=%s', (n_hash,), return_type=1)
api_hash = row[0]
if cust_name is None:
if custom_name is None:
client = TelegramClient(name, api_id, api_hash)
else:
client = TelegramClient(cust_name, api_id, api_hash)
client = TelegramClient(custom_name, api_id, api_hash)
return client
# достает ключ бота из бд
def get_bot_key(name, dbc=None):
srv = PgServer(dbc)
def get_bot_key(name):
srv = PgServer()
bot = name + '_key'
row = srv.exec('select value from parameters where name=%s', (bot,), return_type=1)
row = srv.exec('select value from logins where name=%s', (bot,), return_type=1)
bot_key = row[0]
return bot_key