Initial commit

This commit is contained in:
2024-07-17 23:35:45 +03:00
parent 7a1a025471
commit a7bfd5ed4a
42 changed files with 2041 additions and 2 deletions

0
utils/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

250
utils/db.py Normal file
View File

@@ -0,0 +1,250 @@
import logging
import asyncpg
import redis.asyncio as redis
from config import POSTGRES_NAME, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST, POSTGRES_PORT, REDIS_NAME, \
REDIS_HOST, REDIS_PORT, REDIS_PASSWORD
create_tables_query = """
CREATE TABLE IF NOT EXISTS ban_words
(id SERIAL PRIMARY KEY,
word TEXT NOT NULL);
CREATE TABLE IF NOT EXISTS message
(id SERIAL PRIMARY KEY,
text TEXT NOT NULL,
media TEXT,
buttons TEXT NOT NULL,
included BOOL NOT NULL);
CREATE TABLE IF NOT EXISTS ban_media
(id SERIAL PRIMARY KEY,
video BOOL NOT NULL,
photo BOOL NOT NULL);
"""
exist_query = """
SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = $1)
"""
class Postgres:
def __init__(self):
self.conn = None
async def connect(self):
self.conn = await asyncpg.connect(
database=POSTGRES_NAME,
user=POSTGRES_USER,
password=POSTGRES_PASSWORD,
host=POSTGRES_HOST,
port=POSTGRES_PORT,
)
async def create_tables(self) -> None:
"""
Создаёт таблицы если их нет
:return:
"""
await self.connect()
try:
async with self.conn.transaction():
message_exist = await self.conn.fetchval(
exist_query, 'message'
)
ban_media_exist = await self.conn.fetchval(
exist_query, 'ban_media'
)
await self.conn.execute(
create_tables_query
)
if not message_exist:
await self.create_row(
table_name='message',
data_to_insert={
'text': 'Сообщение',
'media': '',
'buttons': '',
'included': False
}
)
if not ban_media_exist:
await self.create_row(
table_name='ban_media',
data_to_insert={
'photo': True,
'video': True,
}
)
except Exception as e:
logging.error(f'Ошибка в create_tables {e}')
finally:
await self.conn.close()
async def get_data(self, table_name: str, columns='*', query_filter=None) -> list:
"""
Получить данные нужной таблицы по указанным фильтрам
:param columns: Название колонн с нужными данными
:param query_filter: Фильтры запроса в формате {колонка: её значение}
:param table_name: Название таблицы для запроса
:return: False в случае ошибки, словарь с данными в случае успеха
"""
if query_filter is None:
query_filter = {}
await self.connect()
try:
if isinstance(columns, str):
columns = [columns]
full_query = f"SELECT {','.join(columns)} FROM {table_name}"
if query_filter:
query_filter = ' AND '.join(
[f"{key} = '{value}'" for key, value in query_filter.items()]
)
full_query += f' WHERE {query_filter}'
async with self.conn.transaction():
result = await self.conn.fetch(full_query)
return result
except Exception as e:
logging.error(f'Ошибка в get_data {e}')
finally:
await self.conn.close()
return []
async def update_data(self, new_data: dict, query_filter: dict, table_name: str) -> bool:
"""
Обновляет данные по заданным фильтрам
:param new_data: Новые данные в формате {Колонка: новое значение}
:param query_filter: Фильтры запроса в формате {колонка: её значение}
:param table_name: Название таблицы для запроса
:return: True в случае успеха, False в случае ошибки
"""
await self.connect()
try:
dollar_data = {key: f"${i + 1}" for i, key in enumerate(new_data)}
values = ', '.join(f'{key} = {value}' for key, value in dollar_data.items())
full_query = f"UPDATE {table_name} SET {values}"
if query_filter:
query_filter = ' AND '.join([f"{key} = '{value}'" for key, value in query_filter.items()])
full_query += f' WHERE {query_filter}'
async with self.conn.transaction():
await self.conn.execute(full_query, *new_data.values())
return True
except Exception as e:
logging.error(f'Ошибка в update_data {e}')
return False
finally:
await self.conn.close()
async def create_row(self, data_to_insert: dict, table_name: str) -> bool:
"""
Создаёт новую строку с данными
:param data_to_insert: Список, где ключ - название столбика, значение - значение столбика в новой строчке
:param table_name: Название таблицы, куда вставляем данные
:return: id последней вставленной строки
"""
await self.connect()
try:
dollars = [f"${i + 1}" for i in range(len(data_to_insert))]
full_query = f"INSERT INTO {table_name} ({', '.join(data_to_insert.keys())}) VALUES ({', '.join(dollars)})"
async with self.conn.transaction():
await self.conn.execute(full_query, *data_to_insert.values())
return True
except Exception as e:
logging.error(f'Ошибка в create_row {e}')
return False
finally:
await self.conn.close()
async def query(self, query_text: str):
"""
Прямой запрос к бд
:param query_text: sql запрос
:return: Результат sql запроса
"""
await self.connect()
try:
async with self.conn.transaction():
await self.conn.execute(query_text)
except Exception as e:
logging.error(f'Ошибка в query {e}')
finally:
await self.conn.close()
class Redis:
def __init__(self):
self.conn = None
async def connect(self):
try:
self.conn = await redis.Redis(
host=REDIS_HOST,
port=REDIS_PORT,
db=REDIS_NAME,
password=REDIS_PASSWORD,
decode_responses=True,
encoding='utf-8'
)
except Exception as e:
logging.error('redis connect', e)
async def delete_key(self, *keys: str | int) -> str | int:
await self.connect()
try:
return await self.conn.delete(*keys)
except Exception as e:
logging.error('redis delete_key', e)
finally:
await self.conn.close()
async def update_list(self, key: str | int, *values) -> str | int:
await self.connect()
try:
return await self.conn.rpush(key, *values)
except Exception as e:
logging.error('redis update_data', e)
finally:
await self.conn.close()
async def get_list(self, key: str | int) -> list:
await self.connect()
try:
data = await self.conn.lrange(name=str(key), start=0, end=-1)
return data
except Exception as e:
logging.error('redis get_data', e)
return []
finally:
await self.conn.close()
async def update_dict(self, key: str | int, value: dict) -> str | int:
await self.connect()
try:
return await self.conn.hset(name=str(key), mapping=value)
except Exception as e:
logging.error('redis update', e)
finally:
await self.conn.close()
async def get_dict(self, key: str | int) -> dict:
await self.connect()
try:
data = await self.conn.hgetall(name=str(key))
return data
except Exception as e:
logging.error('redis get', e)
return []
finally:
await self.conn.close()

44
utils/defs.py Normal file
View File

@@ -0,0 +1,44 @@
import logging
from aiogram.types import Message
import pandas
from utils.db import Postgres
async def delete_msg(msg: Message) -> None:
"""
Безопасно удаляет сообщение
:param msg: Message
:return: True, если текст является ссылкой, иначе False.
"""
try:
await msg.delete()
except:
pass
async def create_xlsx() -> str:
"""
Составляет xlsx файл с данными бан слова
:return: Путь к готовому xlsx файлу
"""
try:
p = Postgres()
ban_words = await p.get_data(
table_name='ban_words'
)
table_dict = {'ID': [], 'Слово': []}
for ban_word in ban_words:
table_dict['ID'].append(ban_word['id'])
table_dict['Слово'].append(ban_word['word'])
df = pandas.DataFrame(table_dict)
file_path = 'data/ban_words.xlsx'
df.to_excel(file_path, index=False)
return file_path
except Exception as e:
logging.error('Ошибка в create_xlsx', e)

73
utils/middleware.py Normal file
View File

@@ -0,0 +1,73 @@
# from aiogram import BaseMiddleware
# from aiogram.types import TelegramObject, Update
#
# from typing import Callable, Dict, Any, Awaitable
# from utils.defs import delete_msg
# from utils.db import Postgres, Redis
# from templates.message import send_preview
#
#
# class DeleteMessage(BaseMiddleware):
# """
# Мидлвари удаляющая сообщения с бан вордами
# """
#
# async def __call__(
# self,
# handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
# event: Update,
# data: Dict[str, Any]
# ) -> Any:
# if not event.message:
# return await handler(event, data)
# if not (event.message.chat.type == 'group' or
# event.message.chat.type == 'supergroup'):
# return await handler(event, data)
#
# ban = False
# r = Redis()
# p = Postgres()
#
# ban_words = await r.get_list(
# key='ban_words'
# )
# if not ban_words:
# ban_words = await p.get_data(
# table_name='ban_words'
# )
# ban_words = [word['word'] for word in ban_words]
# await r.delete_key(
# 'ban_words'
# )
# await r.update_list(
# 'ban_words',
# *ban_words
# )
#
# for ban_word in ban_words:
# print(ban_word)
# if ban_word in event.message.text.lower():
# print(event.message.text.lower(), 'нашёл')
# ban = True
#
# if ban:
# await delete_msg(
# msg=event.message
# )
# message_data = await p.get_data(
# table_name='message'
# )
#
# if event.message.from_user.username:
# username = f'@{event.message.from_user.username}'
# else:
# username = event.message.from_user.full_name
#
# if message_data[0]['included']:
# await send_preview(
# chat_id=event.message.chat.id,
# message_data=message_data[0],
# username=username
# )
#
# return await handler(event, data)