class SignupForm(UserCreationForm): username = forms.RegexField( label=_('username'), max_length=20, regex=r'^[\w_]+$', help_text= "Required. 20 characters or fewer. Letters, digits and _ only.", error_messages={ 'invalid': "This value may contain only letters, numbers and _ characters." }) email = forms.EmailField(label=_('email'), ) def clean_email(self): email = self.cleaned_data.get('email').strip() if email: if User.objects.filter(email=email).exists() == True: raise forms.ValidationError('This email is already used.') return email def save(self, commit=True): user = super(SignupForm, self).save(commit=False) user.email = self.cleaned_data['email'] if commit: user.save() return user
class Reaction(models.Model): actor = models.ForeignKey(settings.AUTH_USER_MODEL, db_index=True) topic = models.ForeignKey('self', null=True, blank=True, db_index=True, related_name='topic_reactions') target = models.ForeignKey('self', null=True, blank=True, db_index=True, related_name='target_reactions') title = models.CharField(max_length=100, db_index=True, verbose_name=_('title')) contents = models.TextField(max_length=65535, verbose_name=_('contents')) url = models.CharField(max_length=100, blank=True, default='') url_title = models.CharField(max_length=100, null=True, blank=True) url_description = models.CharField(max_length=255, null=True, blank=True) url_image = models.CharField(max_length=100, null=True, blank=True) score = models.PositiveIntegerField(default=0, db_index=True, verbose_name=_('score')) topic_score = models.PositiveIntegerField(default=0, db_index=True) deleted = models.BooleanField(default=False, db_index=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return str(self.id) def get_tree(self): reaction_tree = [] reaction_tree.append(self) for reaction in reaction_tree: if reaction.target is not None: reaction = reaction.target reaction_tree.append(reaction) return reaction_tree def get_current_generation(self): if self.target is not None: return self.target.target_reactions.all().order_by('-score') else: return Reaction.objects.filter(pk=self.pk).order_by('-score') def get_previous_generation(self): if self.target is not None: return self.target.get_current_generation() else: return None def get_next_generation(self): return self.target_reactions.all().order_by('-score') def get_family(self): return Reaction.objects.filter(topic=self.topic)
async def check_explicit(self, message: types.Message): from explicit import find_explicit text = message.text chat = message.chat user = message.from_user # message without text skip if not text: return # is explicit found? result = await find_explicit(text) if not result: await self.cb.register_message(user_id=user.id, intent='normal message') return logger.info(f'Found explicit in message: {text}') await self.cb.register_message(user_id=user.id, intent='explicit message') # let's delete bad message await self.delete_message(message) # notify user try: jail[user.id] += 1 except KeyError: jail[user.id] = 1 user_link = md.hlink(user.full_name, f'tg://user?id={user.id}') if jail.get(user.id) <= 2: text = _('Ай-ай-ай, {user_link}!', user_link=user_link) await self.say(chat.id, text) return if 2 < jail.get(user.id) < 5: text = _('{user_link}, я же тебя предупреждал... Иди молчать.', user_link=user_link) await self.say(chat.id, text) await aio.sleep(1) await self.restrict_user(chat.id, user.id, 5 * 60 * jail.get(user.id)) return if jail.get(user.id) >= 5: text = _('{user_link}, я же тебя предупреждал... Иди в бан.', user_link=user_link) await self.say(chat.id, text) await aio.sleep(1) await self.kick(chat.id, user.id, 24 * 60 * 60) jail[user.id] = 3 return
async def welcome(message: types.Message): """ Welcomes self and say HELP Said welcome message if enabled """ chat = message.chat new_users = message.new_chat_members # a little delay before welcome await types.ChatActions.typing(sleep=2) # say help when bot added to new chat if await moder.me in new_users: logger.info(f'TrueModer added to chat {chat.full_name} ({chat.id})') markup = types.InlineKeyboardMarkup() markup.add( types.InlineKeyboardButton(text=f'ℹ️ Описание', url=config.FAQ_LINK)) text = _( f"<b>Привет! Я бот-модератор!</b> \n\n" f"Чтобы я смог следить за этой группой, мне нужно дать следующие права администратора: \n" f"- удалять сообщения; \n" f"- блокировать пользователей; \n" f"- закреплять сообщения. \n\n" f"Подробности в описании:") await moder.say(chat.id, text, reply_markup=markup)
class UserForm(forms.ModelForm): email = forms.EmailField(label=_('email'), ) class Meta: model = User fields = ( 'email', 'last_name', 'first_name', )
async def start_private(message: types.Message): """ Handle start and help commands in private chat :param message: :return: """ text = _('<b>Привет, я бот-модератор!</b> \n' 'Добавь меня в чат, чтобы навести там порядок') markup = types.InlineKeyboardMarkup() add_group = f'https://telegram.me/{config.BOT_NAME[1:]}?startgroup=true' markup.add(types.InlineKeyboardButton(text=f'Добавить модератора в чат', url=add_group)) await message.reply(text, reply_markup=markup, reply=False)
async def kick(self, chat_id, user_id, seconds): until = int((datetime.now() + timedelta(seconds=seconds)).timestamp()) try: await self._bot.kick_chat_member(chat_id, user_id, until) except BadRequest as error: if 'not enough rights' in str(error): logger.debug('Не хватает прав на совершение действия') text = _( 'Я бы с удовольствием произвёл блокировку, но мне не хватает администраторских прав' ) await self.say(chat_id, text) elif 'an administrator of the chat' in str(error): logger.debug(f'Зачем-то пытается ограничить админа :)') text = _('Я не могу заблокировать админа') await self.say(chat_id, text) else: logger.exception(f'BadRequest: {error}', exc_info=True) text = _('Не шмогла :(') await self.say(chat_id, text)
async def group_migrates_to_supergroup(message: types.Message): chat = message.chat logger.info( f'Group {message.migrate_from_chat_id} migrated to supergroup {chat.id}' ) markup = types.InlineKeyboardMarkup() markup.add( types.InlineKeyboardButton(text=f'ℹ️ Инструкция', url=config.FAQ_LINK)) text = _( f"<b>Отлично!</b> \n\n" f"Теперь для начала работы требуется дать мне следующие права администратора: \n" f"- удалять сообщения; \n" f"- блокировать пользователей \n" f"- закреплять сообщения. \n\n" f"Подробности в разделе Установка:") await moder.say(chat.id, text, reply_markup=markup)
import asyncio from aiogram import types from aiogram.dispatcher import CancelHandler, DEFAULT_RATE_LIMIT, ctx from aiogram.dispatcher.middlewares import BaseMiddleware from aiogram.utils import context from aiogram.utils.exceptions import Throttled from languages import underscore as _ FLOOD_LOCK_MESSAGE = _('<b>Не надо флудить!</b>') FLOOD_MUTE_TIME = 120 # seconds def rate_limit(limit: float, key=None): """ Decorator for configuring rate limit and key in different functions. :param limit: :param key: :return: """ def decorator(func): setattr(func, 'throttling_rate_limit', limit) if key: setattr(func, 'throttling_key', key) return func return decorator class ThrottlingMiddleware(BaseMiddleware):
}, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/1.9/topics/i18n/ LANGUAGE_CODE = 'ja' from languages import trans as _ LANGUAGES = [ ('en', _('english')), ('ja', _('japanese')), ] LOCALE_PATHS = (os.path.join(BASE_DIR, 'locale'), ) TIME_ZONE = 'Asia/Tokyo' USE_I18N = True USE_L10N = True USE_TZ = True # Authentication
async def restrict_user(self, chat_id, user_id, seconds=61): """ Restriction method with try :param chat_id: :param user_id: :type user_id: int :param seconds: int :return: """ until = int((datetime.now() + timedelta(seconds=seconds)).timestamp()) try: await self._bot.restrict_chat_member( chat_id, user_id, can_send_messages=False, can_send_other_messages=False, can_add_web_page_previews=False, can_send_media_messages=False, until_date=until) except BadRequest as e: if "Can't demote chat creator" in str( e) or "can't demote chat creator" in str(e): logger.debug( f"Restriction: can't demote chat creator at {chat_id}") text = _('Не могу я создателя блочить!') await self.say(chat_id, text) elif "is an administrator of the chat" in str(e): logger.debug( f"Restriction: can't demote chat admin at {chat_id}") text = _('Не могу я админа блочить!') await self.say(chat_id, text) elif "Not enough rights to restrict/unrestrict chat member" in str( e): logger.warning( f"Not enough rights to restrict/unrestrict chat member at {chat_id}" ) text = _( 'Я бы с удовольствием произвёл блокировку, но мне не хватает администраторских прав' ) await self.say(chat_id, text) else: logger.exception(f'Error: \n{e}', exc_info=True) text = _('Не шмогла :(') await self.say(chat_id, text) except RetryAfter: logging.error(f'Message limit reached! {RetryAfter}') except Unauthorized as e: logger.exception(f'Error: \n{e}', exc_info=True) except TelegramAPIError as e: logger.error(f'Error: \n{e}') else: return True
async def ban(self, message): """ Executing ban :param message: :type message: types.Message :return: None """ if not isinstance(message, types.Message): logger.error("There's no Message with ban request ") return admin = message.from_user chat = message.chat logger.info( f'moderator.ban received from {log_repr(admin)} in {log_repr(chat)}' ) # check admin rights if not await self.check_admin(admin, chat): await message.delete() await self.restrict_user(chat_id=chat.id, user_id=admin.id, seconds=30 * 60) return # check reply to forward if not message.reply_to_message: await message.reply( f'Эту команду нужно использовать в ответ на чьё-то сообщение') return abuser = message.reply_to_message.from_user if chat and abuser: how_long = await self.get_time(message) ban_before = int((datetime.now() + how_long.get(TIME)).timestamp()) need_delete = await self.check_delete(message) try: await self._bot.kick_chat_member(chat.id, abuser.id, ban_before) except BadRequest as error: if 'not enough rights' in str(error): logger.debug('Не хватает прав на совершение действия') text = _( 'Я бы с удовольствием произвёл блокировку, но мне не хватает администраторских прав' ) await self.say(chat.id, text) elif 'an administrator of the chat' in str(error): logger.debug(f'Зачем-то пытается ограничить админа :)') text = _('Я не могу заблокировать админа') await self.say(chat.id, text) else: logger.exception(f'BadRequest: {error}', exc_info=True) text = _('Я не могу заблокировать админа') await self.say(chat.id, text) else: await self._bot.send_message(chat.id, 'Готово! :)') logger.info( f"{admin.full_name} ({admin.id}) " f"ban {abuser.full_name} ({abuser.id}) " f"in {chat.full_name} ({chat.id}) for {how_long.get(TEXT)}" ) if need_delete: await self._bot.delete_message( chat.id, message.reply_to_message.message_id) else: logger.info(f"{admin.first_name} ({admin.id}) " f"хотел кого-то забанить, но не получилось :(")