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',
|