326 lines
8.6 KiB
Python
326 lines
8.6 KiB
Python
|
# Tg utils v2.22
|
|||
|
# 14/06/2021
|
|||
|
# https://t.me/ssleg © 2020 – 2021
|
|||
|
|
|||
|
import logging
|
|||
|
from datetime import datetime
|
|||
|
|
|||
|
import psycopg2
|
|||
|
from telethon import TelegramClient
|
|||
|
|
|||
|
|
|||
|
class PgServer:
|
|||
|
"""класс postgres-сервер"""
|
|||
|
|
|||
|
__slots__ = ['__con', '__control_flag', '__cursor', '__db_name']
|
|||
|
|
|||
|
def __init__(self, dbc=None, db_name='mydb'):
|
|||
|
if dbc is None:
|
|||
|
self.__con = psycopg2.connect(database=db_name,
|
|||
|
user='postgres',
|
|||
|
password='1234',
|
|||
|
host='127.0.0.1',
|
|||
|
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
|
|||
|
|
|||
|
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)
|
|||
|
|
|||
|
return False
|
|||
|
|
|||
|
def __del__(self):
|
|||
|
self.__cursor.close()
|
|||
|
if self.__control_flag:
|
|||
|
self.__con.close()
|
|||
|
else:
|
|||
|
self.__con.rollback()
|
|||
|
|
|||
|
|
|||
|
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
|
|||
|
self.__debug = debug
|
|||
|
|
|||
|
def lock(self):
|
|||
|
self.__srv.exec('update locks set status=True where lock_name=%s', (self.__lock_name,))
|
|||
|
self.__srv.commit()
|
|||
|
if self.__debug:
|
|||
|
levent = 'locked #' + self.__lock_name
|
|||
|
logging.info(levent)
|
|||
|
|
|||
|
def unlock(self):
|
|||
|
self.__srv.exec('update locks set status=False where lock_name=%s', (self.__lock_name,))
|
|||
|
self.__srv.commit()
|
|||
|
if self.__debug:
|
|||
|
levent = 'unlocked #' + self.__lock_name
|
|||
|
logging.info(levent)
|
|||
|
|
|||
|
def lock_status(self):
|
|||
|
row = self.__srv.exec('select status from locks where lock_name=%s', (self.__lock_name,), return_type=1)
|
|||
|
self.__srv.rollback()
|
|||
|
|
|||
|
if row is not None:
|
|||
|
lock_status = row[0]
|
|||
|
return lock_status
|
|||
|
else:
|
|||
|
return False
|
|||
|
|
|||
|
|
|||
|
class GlobalCounter:
|
|||
|
"""глобальный универсальный счетчик"""
|
|||
|
|
|||
|
__slots__ = ['__count']
|
|||
|
|
|||
|
@staticmethod
|
|||
|
def __is_valid_arg(arg):
|
|||
|
if type(arg) is int:
|
|||
|
if arg > 0:
|
|||
|
return True
|
|||
|
return False
|
|||
|
|
|||
|
def __init__(self, init_count=0):
|
|||
|
if GlobalCounter.__is_valid_arg(init_count):
|
|||
|
self.__count = init_count
|
|||
|
else:
|
|||
|
self.__count = 0
|
|||
|
|
|||
|
def increment(self, step=1):
|
|||
|
if GlobalCounter.__is_valid_arg(step):
|
|||
|
self.__count += step
|
|||
|
return True
|
|||
|
return False
|
|||
|
|
|||
|
def decrement(self, step=1):
|
|||
|
if GlobalCounter.__is_valid_arg(step):
|
|||
|
if self.__count - step >= 0:
|
|||
|
self.__count -= step
|
|||
|
return True
|
|||
|
return False
|
|||
|
|
|||
|
def get(self):
|
|||
|
return self.__count
|
|||
|
|
|||
|
def set(self, value):
|
|||
|
if GlobalCounter.__is_valid_arg(value):
|
|||
|
self.__count = value
|
|||
|
return True
|
|||
|
return False
|
|||
|
|
|||
|
def clear(self):
|
|||
|
self.__count = 0
|
|||
|
|
|||
|
def __isub__(self, other):
|
|||
|
if GlobalCounter.__is_valid_arg(other):
|
|||
|
self.__count -= other
|
|||
|
|
|||
|
def __iadd__(self, other):
|
|||
|
if GlobalCounter.__is_valid_arg(other):
|
|||
|
self.__count += other
|
|||
|
|
|||
|
def __eq__(self, other):
|
|||
|
if self.__count == other:
|
|||
|
return True
|
|||
|
return False
|
|||
|
|
|||
|
def __ge__(self, other):
|
|||
|
if self.__count >= other:
|
|||
|
return True
|
|||
|
return False
|
|||
|
|
|||
|
def __gt__(self, other):
|
|||
|
if self.__count > other:
|
|||
|
return True
|
|||
|
return False
|
|||
|
|
|||
|
def __le__(self, other):
|
|||
|
if self.__count <= other:
|
|||
|
return True
|
|||
|
return False
|
|||
|
|
|||
|
def __lt__(self, other):
|
|||
|
if self.__count <= other:
|
|||
|
return True
|
|||
|
return False
|
|||
|
|
|||
|
def __str__(self):
|
|||
|
return str(self.__count)
|
|||
|
|
|||
|
|
|||
|
class GlobalFlag:
|
|||
|
"""глобальный универсальный флаг"""
|
|||
|
|
|||
|
__slots__ = ['__flag']
|
|||
|
|
|||
|
def __init__(self):
|
|||
|
self.__flag = False
|
|||
|
|
|||
|
def set_true(self):
|
|||
|
self.__flag = True
|
|||
|
|
|||
|
def set_false(self):
|
|||
|
self.__flag = False
|
|||
|
|
|||
|
def switch(self):
|
|||
|
if self.__flag:
|
|||
|
self.__flag = False
|
|||
|
else:
|
|||
|
self.__flag = True
|
|||
|
|
|||
|
def get(self):
|
|||
|
return self.__flag
|
|||
|
|
|||
|
def __bool__(self):
|
|||
|
return self.__flag
|
|||
|
|
|||
|
def __str__(self):
|
|||
|
return str(self.__flag)
|
|||
|
|
|||
|
|
|||
|
def t_stamp():
|
|||
|
now = datetime.now()
|
|||
|
stamp = datetime.strftime(now, '%d/%m %Y %H:%M:%S')
|
|||
|
return stamp
|
|||
|
|
|||
|
|
|||
|
def t_stamp_sh():
|
|||
|
now = datetime.now()
|
|||
|
stamp = datetime.strftime(now, '%H:%M')
|
|||
|
return stamp
|
|||
|
|
|||
|
|
|||
|
# ловеркейс имени tg канала с проверкой валидности
|
|||
|
def set_ch_name_lower(teststr):
|
|||
|
i = 0
|
|||
|
rezult = ''
|
|||
|
while i < len(teststr):
|
|||
|
char = teststr[i]
|
|||
|
code = ord(char)
|
|||
|
|
|||
|
if code == 95:
|
|||
|
pass
|
|||
|
else:
|
|||
|
if 47 < code < 58:
|
|||
|
pass
|
|||
|
else:
|
|||
|
if 64 < code < 91:
|
|||
|
code += 32
|
|||
|
else:
|
|||
|
if 96 < code < 123:
|
|||
|
pass
|
|||
|
else:
|
|||
|
levent = 'ошибка конвертации канала: ' + str(i) + ' ' + str(code) + ' ' + char + ' ' + teststr
|
|||
|
logging.warning(levent)
|
|||
|
return False
|
|||
|
rezult += chr(code)
|
|||
|
i += 1
|
|||
|
|
|||
|
return rezult
|
|||
|
|
|||
|
|
|||
|
# сборка имени юзера в читабельное
|
|||
|
def set_name_printable(first, last, account=None, phone=None, ad=''):
|
|||
|
name = str(first) + ' '
|
|||
|
|
|||
|
if last is not None:
|
|||
|
name = name + str(last) + ' '
|
|||
|
|
|||
|
if account is not None:
|
|||
|
name = name + '(' + ad + str(account) + ')' + ' '
|
|||
|
|
|||
|
if phone is not None:
|
|||
|
name = name + '+' + str(phone) + ' '
|
|||
|
|
|||
|
ind = len(name)
|
|||
|
res = name[0:ind - 1]
|
|||
|
return res
|
|||
|
|
|||
|
|
|||
|
# вывод числа с разделителями тысяч
|
|||
|
def set_int_printable(integer, razd=' '):
|
|||
|
string = '{:,}'.format(integer)
|
|||
|
string = string.replace(',', razd)
|
|||
|
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)
|
|||
|
|
|||
|
n_api = name + '_api_id'
|
|||
|
row = srv.exec('select value from parameters 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)
|
|||
|
api_hash = row[0]
|
|||
|
|
|||
|
if cust_name is None:
|
|||
|
client = TelegramClient(name, api_id, api_hash)
|
|||
|
else:
|
|||
|
client = TelegramClient(cust_name, api_id, api_hash)
|
|||
|
return client
|
|||
|
|
|||
|
|
|||
|
# достает ключ бота из бд
|
|||
|
def get_bot_key(name, dbc=None):
|
|||
|
srv = PgServer(dbc)
|
|||
|
|
|||
|
bot = name + '_key'
|
|||
|
row = srv.exec('select value from parameters where name=%s', (bot,), return_type=1)
|
|||
|
bot_key = row[0]
|
|||
|
return bot_key
|