telegram_bots/bots/modules/cyberlina.py

156 lines
6.4 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 jsonfield import JSONField
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):
2019-11-27 18:39:57 +00:00
first_part = JSONField(default='[]')
second_part = JSONField(default='[]')
third_part = JSONField(default='[]')
emoji = JSONField(default='[]')
already_ran = JSONField(default='[]')
welcome_reactions = JSONField(default='[]')
inline_reactions = JSONField(default='[]')
2019-11-27 19:23:57 +00:00
_mtg_data = JSONField(default={}, 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',