telegram_bots/bots/modules/cyberlina.py

155 lines
6.5 KiB
Python
Raw Normal View History

2019-11-27 18:21:24 +00:00
import os
from datetime import timedelta, datetime, time
from random import choice, seed
from uuid import uuid4
import humanize
2019-11-27 20:10:15 +00:00
import markovify
2019-11-27 18:21:24 +00:00
from django.db import models
2019-12-02 08:44:13 +00:00
from django.utils.timezone import localdate, now, make_aware, localtime
2019-11-27 18:21:24 +00:00
from jsoneditor.forms import JSONEditor
from telegram import Update, Chat, User, InlineQueryResultArticle, InputTextMessageContent
from telegram.error import BadRequest
from telegram.ext import Dispatcher, CallbackContext, MessageHandler, Filters, CommandHandler, InlineQueryHandler
from telegram.utils.helpers import mention_html
from bots.models import TelegramBotModuleConfig
class CyberLinaBotModuleConfig(TelegramBotModuleConfig):
2021-03-11 20:43:54 +00:00
first_part = models.JSONField(default=list)
second_part = models.JSONField(default=list)
third_part = models.JSONField(default=list)
emoji = models.JSONField(default=list)
already_ran = models.JSONField(default=list)
welcome_reactions = models.JSONField(default=list)
inline_reactions = models.JSONField(default=list)
_mtg_data = models.JSONField(default=dict, blank=True, null=True)
2019-11-27 21:12:36 +00:00
_mtg_corpus = models.TextField(null=True, blank=True)
2019-11-27 19:23:57 +00:00
mtg_train = models.TextField(null=True, blank=True)
2019-11-27 18:21:24 +00:00
MODULE_NAME = 'Киберлиночка'
CUSTOM_WIDGETS = {
'first_part': JSONEditor(),
'second_part': JSONEditor(),
'third_part': JSONEditor(),
'emoji': JSONEditor(),
'already_ran': JSONEditor(),
'welcome_reactions': JSONEditor(),
'inline_reactions': JSONEditor(),
}
2019-11-27 21:12:36 +00:00
EXCLUDE_FIELDS = '_mtg_data', '_mtg_corpus',
2019-11-27 18:21:24 +00:00
2019-11-27 20:31:09 +00:00
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
try:
self.markovify = markovify.Text.from_dict(self._mtg_data)
except:
pass
2019-11-27 18:21:24 +00:00
def message_handler(self, update: Update, ctx: CallbackContext):
if not update.effective_chat or not update.effective_user:
return
CyberLinaUser.from_tg_obj(self, update.effective_chat, update.effective_user)
def goodmorning_handler(self, update: Update, ctx: CallbackContext):
2019-11-27 18:39:57 +00:00
if not all([self.first_part, self.second_part,
self.third_part, self.emoji]):
2019-11-27 18:21:24 +00:00
return update.effective_message.reply_text('Я не настроена :c')
seed(os.urandom(128))
self.message_handler(update, ctx)
chat = self.chats.get(chat_id=update.effective_chat.id)
if chat.last_run and (chat.last_run >= localdate() or
2019-12-02 08:44:13 +00:00
chat.last_run + timedelta(1) == localdate() and localtime().hour < 6):
2019-11-27 18:21:24 +00:00
humanize.i18n.activate('ru_RU')
time_left = make_aware(datetime.combine(chat.last_run + timedelta(1), time(6, 0))) - now()
return update.effective_message.reply_text(
2019-11-27 18:39:57 +00:00
choice(self.already_ran).format(
2019-11-27 18:21:24 +00:00
name=chat.last_choice.name,
time=humanize.naturaldelta(time_left)
)
)
while True:
user = chat.users.order_by('?').first() # type: CyberLinaUser
if not user:
return update.effective_message.reply_text('Нет известных юзеров в чате')
try:
member = ctx.bot.get_chat_member(chat.chat_id, user.user_id)
CyberLinaUser.from_tg_obj(self, update.effective_chat, member.user)
break
except BadRequest:
user.delete()
msg = '{}, {}! {}, {} {}'.format(
2019-11-27 18:39:57 +00:00
choice(self.first_part),
choice(self.second_part),
2019-11-27 18:21:24 +00:00
mention_html(user.user_id, user.name),
2019-11-27 18:39:57 +00:00
choice(self.third_part),
choice(self.emoji),
2019-11-27 18:21:24 +00:00
)
update.effective_chat.send_message(msg, parse_mode='html')
chat.last_run = localdate()
chat.last_choice = user
chat.save()
def inline_query_handler(self, update: Update, ctx: CallbackContext):
if not self.inline_reactions:
return
seed(os.urandom(128))
2019-11-27 20:33:00 +00:00
markov_msg = ''
for i in range(3):
2019-11-27 20:34:08 +00:00
markov_msg += (self.markovify.make_sentence(tries=100) or '') + ' '
2019-11-27 18:21:24 +00:00
results = [
InlineQueryResultArticle(
id=uuid4(),
title='Не нажимай >_<',
2019-11-27 18:39:57 +00:00
input_message_content=InputTextMessageContent(choice(self.inline_reactions))
2019-11-27 19:23:57 +00:00
),
InlineQueryResultArticle(
id=uuid4(),
title='ФлаБеПроЛейка',
2019-11-27 20:33:00 +00:00
input_message_content=InputTextMessageContent(markov_msg)
2019-11-27 19:23:57 +00:00
),
2019-11-27 18:21:24 +00:00
]
2019-11-27 18:36:33 +00:00
update.inline_query.answer(results, cache_time=0)
2019-11-27 18:21:24 +00:00
def build_dispatcher(self, dispatcher: Dispatcher):
dispatcher.add_handler(CommandHandler('goodmorning', self.goodmorning_handler))
dispatcher.add_handler(MessageHandler(Filters.all, self.message_handler))
dispatcher.add_handler(InlineQueryHandler(self.inline_query_handler))
return dispatcher
2019-11-27 19:23:57 +00:00
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
if self.mtg_train:
2019-11-27 21:12:36 +00:00
self._mtg_corpus += '\n' + self.mtg_train
self._mtg_data = markovify.Text(self._mtg_corpus).to_dict()
self.mtg_train = None
2019-11-27 19:23:57 +00:00
super().save(force_insert, force_update, using, update_fields)
2019-11-27 18:21:24 +00:00
class CyberLinaChat(models.Model):
config = models.ForeignKey(CyberLinaBotModuleConfig, on_delete=models.CASCADE, related_name='chats')
name = models.TextField()
chat_id = models.BigIntegerField(db_index=True)
last_run = models.DateField(null=True, blank=True)
last_choice = models.ForeignKey('CyberLinaUser', on_delete=models.SET_NULL, null=True, blank=True, related_name='+')
class Meta:
unique_together = 'config', 'chat_id',
class CyberLinaUser(models.Model):
chat = models.ForeignKey(CyberLinaChat, on_delete=models.CASCADE, related_name='users')
user_id = models.BigIntegerField(db_index=True)
name = models.TextField()
@staticmethod
def from_tg_obj(config: CyberLinaBotModuleConfig, chat: Chat, user: User):
chat_title = chat.title or user.full_name
chat, _ = CyberLinaChat.objects.update_or_create(config=config, chat_id=chat.id,
defaults={'name': chat_title})
CyberLinaUser.objects.update_or_create(chat=chat, user_id=user.id,
defaults={'name': user.full_name})
class Meta:
unique_together = 'chat', 'user_id',