Files
limoka/hikariatama/ftg/leomatch.py
2025-07-10 21:02:34 +03:00

375 lines
14 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# █ █ ▀ █▄▀ ▄▀█ █▀█ ▀
# █▀█ █ █ █ █▀█ █▀▄ █
# © Copyright 2022
# https://t.me/hikariatama
#
# 🔒 Licensed under the GNU AGPLv3
# 🌐 https://www.gnu.org/licenses/agpl-3.0.html
# meta desc: Simplifies the interaction with @leomatchbot - Rejects slag, allows you to create filters by age, cities, blacklisted words.
# meta pic: https://static.dan.tatar/leomatch_icon.png
# meta banner: https://mods.hikariatama.ru/badges/leomatch.jpg
# meta developer: @hikarimods
# requires: russian-names
# scope: hikka_only
# scope: hikka_min 1.3.0
__version__ = (2, 0, 3)
import asyncio
import logging
import re
import time
from typing import Iterable, Optional
from russian_names import RussianNames
from telethon.tl.types import Message
from .. import loader, utils
logger = logging.getLogger(__name__)
@loader.tds
class LeomatchMod(loader.Module):
"""Simplifies the interaction with @leomatchbot - Rejects slag, allows you to create filters by age, cities, blacklisted words. Check .config for more info"""
strings = {"name": "Leomatch"}
strings_ru = {
"_cls_doc": (
"Упрощает взаимодействие с @leomatchbot - отклоняет шлак, позволяет"
" создавать фильтры по возрасту, городам, черному списку слов. Загляни в"
" .config для подробной информации"
),
}
_last_decline = 0
_queue = []
_groups = {}
def __init__(self):
self.config = loader.ModuleConfig(
loader.ConfigValue(
"min_age",
0,
(
"Минимальный возраст собеседника - будет автоматически отклонять"
" всех, кто младше"
),
validator=loader.validators.Integer(minimum=0),
),
loader.ConfigValue(
"max_age",
100,
(
"Максимальный возраст собеседника - будет автоматически отклонять"
" всех, кто старше"
),
validator=loader.validators.Integer(minimum=0),
),
loader.ConfigValue(
"blacklist_cities",
[],
(
"Список городов, пользователи из которых будут автоматически"
" отклоняться"
),
validator=loader.validators.Series(),
),
loader.ConfigValue(
"whitelist_cities",
[],
(
"Список городов для белого списка. Пользователи из других городов"
" будут автоматически отклоняться"
),
validator=loader.validators.Series(),
),
loader.ConfigValue(
"blacklist_words",
[],
(
"Если в анкете пользователя есть слово из этого списка, она будет"
" автоматически отклонена"
),
validator=loader.validators.Series(),
),
loader.ConfigValue(
"whitelist_words",
[],
(
"Если в анкете пользователя есть нет слов из этого списка, она"
" будет автоматически отклонена"
),
validator=loader.validators.Series(),
),
loader.ConfigValue(
"decline_slag",
True,
"Отклонять ли шлак (Подпишитесь на наш ТикТок и др.)",
validator=loader.validators.Boolean(),
),
loader.ConfigValue(
"enable",
True,
"Включить ли модуль",
validator=loader.validators.Boolean(),
),
loader.ConfigValue(
"minimal_len",
0,
"Минимальное количество слов в анкете",
validator=loader.validators.Integer(minimum=0),
),
loader.ConfigValue(
"log",
True,
"Отправлять в логи информацию о причинах отклонения анкет",
validator=loader.validators.Boolean(),
),
loader.ConfigValue(
"delay",
5,
"Задержка между автоматическим отклонением анкет",
validator=loader.validators.Integer(minimum=3),
),
loader.ConfigValue(
"no_female",
False,
"Автоматически отклонять девушек",
validator=loader.validators.Boolean(),
),
loader.ConfigValue(
"no_male",
False,
"Автоматически отклонять парней",
validator=loader.validators.Boolean(),
),
)
async def client_ready(self):
names = RussianNames()
await utils.run_sync(names._fill_base)
self.female_names = map(lambda x: x.lower(), names._base["woman"]["name"])
self.male_names = map(lambda x: x.lower(), names._base["man"]["name"])
@loader.loop(interval=1, autostart=True)
async def loop(self):
if not self._queue:
return
if self._last_decline + self.config["delay"] > time.time():
await asyncio.sleep(self._last_decline + self.config["delay"] - time.time())
self._last_decline = time.time()
log, answer = self._queue.pop(0)
async with self._client.conversation(1234060895) as conv:
m = await conv.send_message(answer)
await conv.get_response()
await m.delete()
if self.config["log"] and log:
logger.info(log)
async def _decline(
self,
message: Message,
log: Optional[str] = None,
answer: Optional[str] = "👎",
):
for m in [message] + (
[m for m in self._groups[message.grouped_id]]
if message.grouped_id and message.grouped_id in self._groups
else []
):
await m.delete()
self._queue += [(log, answer)]
@staticmethod
def _in(needle: str, haystack: Iterable, alter: str) -> bool:
"""
Checks for occurence of needle in haystack using smart method
:param needle: string to search for
:param haystack: iterable to search in
:param alter: string to search in if needle is not a one word
:return: True if needle is found in haystack, False otherwise
"""
return (
True
if needle.strip().lower() in map(lambda x: x.lower().strip(), haystack)
else " " in needle and needle.strip().lower() in alter.lower()
)
@loader.watcher(chat_id=1234060895, out=True)
async def out_watcher(self, _):
if self._queue:
self._queue = []
logger.info("Останавливаюсь, т.к. ты отправил сообщение")
return
@loader.watcher("in", from_id=1234060895)
async def watcher(self, message: Message):
if not self.config["enable"]:
return
if (
"Пригласи друзей и получи больше" in message.raw_text
and "Твоя статистика" not in message.raw_text
):
self._queue = []
logger.info("Останавливаюсь, т.к. закончились доступные лайки")
return
if message.grouped_id:
self._groups.setdefault(message.grouped_id, []).append(message)
if self.config["decline_slag"] and (
(
"Подпишись на канал Дайвинчика" in message.raw_text
and "https://t.me/leoday" in message.text
)
or (
"Бот не запрашивает личные данные и не идентифицирует пользователей по"
" паспортным данным"
in message.raw_text
)
or (
"хочешь больше просмотров в TikTok?" in message.raw_text
and "tiktok.com/tag/дайвинчик" in message.raw_text
)
or (
"Пришли свое расположение и увидишь анкеты рядом с тобой"
in message.raw_text
)
):
await self._decline(
message,
"Отклонил какой-то шлак",
"Продолжить просмотр анкет",
)
return
if self.config["decline_slag"] and message.raw_text == "Это все, идем дальше?":
await self._decline(
message,
"Автоматически продолжаю просмотр анкет",
"Смотреть анкеты",
)
return
if (
message.raw_text.count(",") < 2
or message.raw_text.startswith("Кому-то понравилась твоя анкета:")
or "Отлично! Надеюсь хорошо проведете время ;) Начинай общаться"
in message.raw_text
):
return
words = re.sub(
r" {2,}",
" ",
"".join(
(
symbol
if symbol
in "abcdefghijklmnopqrstuvwxyzёйцукенгшщзхъфывапролджэячсмитьбю1234567890 "
else " "
)
for symbol in (
""
if len(message.raw_text.lower().split(",", maxsplit=2)) < 3
or "" not in message.raw_text
else message.raw_text.lower()
.split(",", maxsplit=2)[2]
.split("")[1]
)
),
).split()
user = (
message.raw_text.split("")[0].strip()
if "" in message.raw_text
else message.raw_text
)
user_name = user.split(",")[0].strip().lower()
if (
self.config["no_female"]
and user_name in self.female_names
or self.config["no_male"]
and user_name in self.male_names
):
await self._decline(message, f"{user} отклонен по несовпадению пола")
if self.config["minimal_len"] and len(list(words)) < self.config["minimal_len"]:
await self._decline(
message,
f"{user} отклонен из-за слишком короткой анкеты",
)
return
if (
self.config["blacklist_cities"]
and len(message.raw_text.split(",")) >= 3
and message.raw_text.split(",")[2].split()[0].lower().strip()
in map(lambda x: x.lower().strip(), self.config["blacklist_cities"])
):
await self._decline(
message,
f"{user} отклонен из-за наличия города в черном списке",
)
return
if (
self.config["whitelist_cities"]
and len(message.raw_text.split(",")) >= 3
and message.raw_text.split(",")[2].split()[0].lower().strip()
not in map(lambda x: x.lower().strip(), self.config["whitelist_cities"])
):
await self._decline(
message,
f"{user} отклонен из-за отсутствия города в белом списке",
)
return
if self.config["blacklist_words"] and any(
self._in(word, words, message.raw_text)
for word in self.config["blacklist_words"]
):
await self._decline(message, f"{user} отклонен из-за слов в черном списке")
return
if self.config["whitelist_words"] and not any(
self._in(word, words, message.raw_text)
for word in self.config["whitelist_words"]
):
await self._decline(
message,
f"{user} отклонен из-за отсутствия в анкете слов из белого списка",
)
return
if (
self.config["min_age"]
and len(message.raw_text.split(",")) >= 2
and message.raw_text.split(",")[1].strip().isdigit()
and int(message.raw_text.split(",")[1].strip()) < self.config["min_age"]
):
await self._decline(message, f"{user} отклонен из-за младшего возраста")
return
if (
self.config["max_age"]
and len(message.raw_text.split(",")) >= 2
and message.raw_text.split(",")[1].strip().isdigit()
and int(message.raw_text.split(",")[1].strip()) > self.config["max_age"]
):
await self._decline(message, f"{user} отклонен из-за старшего возраста")
return