Skip to content
This repository was archived by the owner on Nov 17, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .env.dist
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Telegram API Token
BOT_TOKEN=
BOT_TOKEN=token

# Не надо использовать пробел после ","
ADMINS_ID=123456789,987654321
ADMINS_ID=ID

# Указываем пропускать ли боту апдейты при запуске
SKIP_UPDATES=False
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ celerybeat.pid
*.sage.py

# Environments
.env
.env.dist

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

нет, нахрена это? dist - файл-пример

.venv
env/
venv/
Expand Down
2 changes: 2 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
async def on_startup(dp):
await set_default_commands(dp)
await on_startup_notify(dp)

try:
db.create_table_stickers()
db.create_table_karma_users()
except Exception as err:
print(err)
logger.info("Бот запущен")
Expand Down
10 changes: 10 additions & 0 deletions data/cache_karma.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@


# тут мы будем хранить данные для того, чтобы не наргуржать базу данных не нужной информацией.
"""
format
{message_id: user_id}

"""
reply_message_id_user = {}

Binary file modified data/main.db
Binary file not shown.
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ services:
restart: always

env_file:
- ".env"
- ".env.dist"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dist - файл пример

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Убирай

3 changes: 2 additions & 1 deletion filters/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from aiogram import Dispatcher
from loguru import logger


from .admin_filter import IsPrivateAdmin
from .user_filters import IsContributor
from .chat_filters import IsGroup
from .chat_filters import IsPrivate
Expand All @@ -23,3 +23,4 @@ def setup(dp: Dispatcher):
dp.filters_factory.bind(IsContributor)
dp.filters_factory.bind(IsGroup)
dp.filters_factory.bind(IsPrivate)
dp.filters_factory.bind(IsPrivateAdmin)
42 changes: 42 additions & 0 deletions filters/access_karma.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from aiogram import types
from aiogram.dispatcher.filters import BoundFilter
from loguru import logger

from data.cache_karma import reply_message_id_user
from loader import db, bot


class Restriction_Karma(BoundFilter):

async def check(self, message: types.Message) -> bool:
bot_id = (await bot.get_me()).id
my_user_id = message.from_user.id
user_id_not_karma = [bot_id, my_user_id]

# чтобы нельзя было давать карму боту и самому себе
if message.reply_to_message.from_user.id in user_id_not_karma:
await message.delete()
return False

if await self._get_cached_message_value(message) is None:
await self._set_cached_message_value(message)
db.add_user(user_id=message.reply_to_message.from_user.id,
full_name=message.reply_to_message.from_user.full_name)
await message.delete()
return True

async def _set_cached_message_value(self, message: types.Message):
if not await self._get_cached_message_value(message) is None:
return
reply_message_id_user[message.reply_to_message.message_id] = message.from_user.id

async def _get_cached_message_value(self, message: types.Message):
try:
return reply_message_id_user[message.reply_to_message.message_id]
except Exception as error:
logger.info(error)





11 changes: 11 additions & 0 deletions filters/admin_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from aiogram import types
from aiogram.dispatcher.filters import BoundFilter


class IsPrivateAdmin(BoundFilter):
def __init__(self, users_id: list):
self.users_id = list(map(int, users_id))

async def check(self, message:types.Message):

return message.from_user.id in self.users_id
1 change: 1 addition & 0 deletions filters/chat_filters.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from aiogram import types
from aiogram.dispatcher.filters import BoundFilter
from loguru import logger


class IsGroup(BoundFilter):
Expand Down
2 changes: 0 additions & 2 deletions filters/is_reply.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ class IsReplyFilter(BoundFilter):
"""
Фильтр, проверяющий, явлляется ли сообщение ответом на сообщение
"""

key = "is_reply"

is_reply: bool

async def check(self, message: types.Message) -> bool:
Expand Down
1 change: 1 addition & 0 deletions handlers/essential/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .errors import dp
from .other import dp
from .metabolism import dp
from .karma import dp

__all__ = ["dp"]
72 changes: 72 additions & 0 deletions handlers/essential/karma.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import re

from aiogram import types
from aiogram.dispatcher.filters import Command, AdminFilter
from aiogram.utils.markdown import hlink, hbold

from data.cache_karma import reply_message_id_user
from data.config import ADMINS_ID
from filters import IsGroup, IsReplyFilter, IsPrivate, IsPrivateAdmin
from filters.access_karma import Restriction_Karma
from loader import dp, bot, db
from utils.misc import rate_limit
from utils.misc.karma import karma, url


@dp.message_handler(IsPrivate(), IsPrivateAdmin(ADMINS_ID), Command("clear"))
async def clear_cache_message_id_karma(message: types.Message):
size = None

if type(reply_message_id_user) is dict:
size = 144
if len(reply_message_id_user) > 8:
size += 12 * (len(reply_message_id_user) - 8)
await message.answer(f"Памяти в кэше {size}\n"
"Было очищено")
reply_message_id_user.clear()

@rate_limit(limit=0)
@dp.message_handler(IsGroup(), Command("top_karma", prefixes="!/"))
async def result_top_users(message: types.Message):
name_bot = await bot.get_me()
command_parse = re.compile(r"(!top_karma|/top_karma) ?(\d+)?")
a = command_parse.match(message.text)
limit = a.group(2)

if limit is None:
limit = 10

if int(limit) > 20:
limit = 20

list_top_users = db.select_karma_top(limit=limit)
text_messages = [f"Топ участников чата по карме: {hbold(name_bot.full_name)}"]

for count, user_object in enumerate(list_top_users, 1):
user_id, karma_user, full_name = user_object
text = f"{count}. {hlink(full_name, url(user_id))} - {karma_user} 💋"
text_messages.append(text)

await message.answer("\n".join(text_messages))

@rate_limit(limit=60)
@dp.message_handler(IsGroup(), IsReplyFilter(is_reply=True), Restriction_Karma(), text=["+", "-"])
async def give_karma_user(message: types.Message):

answer = message.text
text_with_karma = {"+": (1, "пополнил"),
"-": (-1, "понизил")}
karma(message, karma=text_with_karma[f"{answer}"][0])

user = hlink(message.from_user.first_name, message.from_user.url)
text = text_with_karma.get(answer)[1]
to_user = hlink(message.reply_to_message.from_user.first_name, message.reply_to_message.from_user.url)
get_karma = str(text_with_karma.get(answer)[0])
total_karma = db.select_karma_user(user_id=message.reply_to_message.from_user.id)[0][1] # получаем общую карму пользователя

await message.answer(R"""{user} {text} {to_user} карму на {get_karma}
Текущая карма: {total_karma}""".format(user=user,
text=text,
to_user=to_user,
get_karma=get_karma,
total_karma=total_karma))
1 change: 0 additions & 1 deletion handlers/groups/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ async def help(message: types.Message):
"/gay [цель*] - Тест на гея" "\n"
"/biba - Проверить бибу" "\n"
"/roll - Случайное число" "\n"
"/metabolism - Узнать свою суточную норму калорий" "\n"
"\n"
"{warning}".format(
header1=hbold("Основные комманды"),
Expand Down
1 change: 1 addition & 0 deletions handlers/groups/service_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ async def left_chat_member(message: types.Message):
return False

# Проверяем вышел ли пользователь сам

if message.left_chat_member.id == message.from_user.id:
await message.answer(f"{message.left_chat_member.get_mention(as_html=True)} вышел из чата.")
until_date = datetime.datetime.now() + datetime.timedelta(days=1)
Expand Down
1 change: 1 addition & 0 deletions handlers/private/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from filters import IsPrivate
from keyboards.inline import start_markup
from loader import dp
from utils.misc import rate_limit


@dp.message_handler(IsPrivate(), Command("start", prefixes="/"))
Expand Down
3 changes: 2 additions & 1 deletion middlewares/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from aiogram import Dispatcher
from loguru import logger

from .throttling import ThrottlingMiddleware

from .throttling import ThrottlingMiddleware

def setup(dp: Dispatcher):
logger.info("Подключение middlewares...")
dp.middleware.setup(ThrottlingMiddleware())

14 changes: 11 additions & 3 deletions middlewares/throttling.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,39 @@
from aiogram.dispatcher.handler import CancelHandler, current_handler
from aiogram.dispatcher.middlewares import BaseMiddleware
from aiogram.utils.exceptions import Throttled
from loguru import logger


class ThrottlingMiddleware(BaseMiddleware):
"""
Simple middleware
"""

def __init__(self, limit=DEFAULT_RATE_LIMIT, key_prefix='antiflood_'):
def __init__(self, limit=DEFAULT_RATE_LIMIT,
limit_karma=1,
key_prefix='antiflood_'):
self.rate_limit = limit
self.prefix = key_prefix

super(ThrottlingMiddleware, self).__init__()

# noinspection PyUnusedLocal
async def on_process_message(self, message: types.Message, data: dict):
handler = current_handler.get()
dispatcher = Dispatcher.get_current()

if handler:
limit = getattr(handler, 'throttling_rate_limit', self.rate_limit)
key = getattr(handler, 'throttling_key', f"{self.prefix}_{handler.__name__}")
else:
limit = self.rate_limit
key = f"{self.prefix}_message"
try:
logger.info(limit)

await dispatcher.throttle(key, rate=limit)
except Throttled as t:

await self.message_throttled(message, t)
raise CancelHandler()

Expand All @@ -42,9 +50,9 @@ async def message_throttled(self, message: types.Message, throttled: Throttled):
key = f"{self.prefix}_message"
delta = throttled.rate - throttled.delta
if throttled.exceeded_count <= 2:
service_message = await message.reply('Too many requests! ')
service_message = await message.answer('Не надо так часто.')

await asyncio.sleep(5)
await asyncio.sleep(2)
await service_message.delete()
await message.delete()
try:
Expand Down
73 changes: 65 additions & 8 deletions utils/db_api/sqlite.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import sqlite3

from loguru import logger


class Database:
def __init__(self, path_to_db="main.db"):
Expand All @@ -13,7 +15,7 @@ def execute(self, sql: str, parameters: tuple = None, fetchone=False, fetchall=F
if not parameters:
parameters = ()
connection = self.connection
connection.set_trace_callback(logger)
# connection.set_trace_callback(logger)
cursor = connection.cursor()
data = None
cursor.execute(sql, parameters)
Expand Down Expand Up @@ -55,11 +57,66 @@ def select_all_sets(self):
"""
return self.execute(sql, fetchall=True)

def create_table_karma_users(self):

"""
Создаем таблицу с название USERS_KARMA
колонки:
user_id : integer
karma: integer

"""
sql = """CREATE TABLE USERS_KARMA (

user_id INTEGER PRIMARY KEY,
karma INTEGER,
full_name varchar 255
)
"""
self.execute(sql, commit=True)

def update_karma(self, user_id: int, karma: int = 0):

# если статус update_karma = True, мы обновляем карму
now_karma = self.select_karma_user(user_id=user_id)[0][1]

now_karma += karma
sql = "UPDATE USERS_KARMA SET karma = ? WHERE user_id = ?"
return self.execute(sql, parameters=(now_karma, user_id), commit=True)

def add_user(self, user_id: int, full_name: str, karma: int = 0):
try:
sql = "INSERT INTO USERS_KARMA (user_id, full_name, karma) VALUES (?,?,?)"
self.execute(sql, parameters=(user_id, full_name, karma), commit=True)
except Exception as e:
logger.info(e)

def select_karma_user(self, user_id: int):
"""
Выводим пользователя из базы данных по юзеру
"""
sql = "SELECT * FROM USERS_KARMA WHERE user_id = ?"
return self.execute(sql, parameters=(user_id,), fetchall=True)

def select_karma_top(self, limit: int = 10):
"""
Функция в котором мы определяем количество топ пользователей
группы по набранным баллам

parameters:
limit - int , default = 10 users
"""

sql = "SELECT * FROM USERS_KARMA ORDER BY karma DESC"
setting_limit = " LIMIT " + str(limit)
sql += setting_limit

return self.execute(sql, fetchall=True)

def logger(statement):
print(f"""
_____________________________________________________
Executing:
{statement}
_____________________________________________________
""")
# def logger(statement):
# print(f"""
# _____________________________________________________
# Executing:
# {statement}
# _____________________________________________________
# """)
Loading