def publish_bot(request): if request.is_ajax(): user_prof = UserProfile.objects.get(user=request.user) new_bot_code = json.loads(request.body)['msg'] if len(new_bot_code.strip('')) == 0: return HttpResponse("Can not publish an empty bot") # Get the last bot, and check delta try: latest_bot = Bot.objects.filter(owner=user_prof).latest('creation_date') if compare_bots(latest_bot.code, new_bot_code): error = "Can not publish this bot, looks like the previous one!" return HttpResponse(error) except ObjectDoesNotExist: # This is the first bot for this user pass bot = Bot() bot.owner = user_prof bot.code = new_bot_code bot.save() user_prof.current_bot = bot user_prof.my_buffer = new_bot_code user_prof.save() return HttpResponse(json.dumps({'success' : True}), mimetype='application/json')
def mybots(request): user_prof = UserProfile.objects.get(user=request.user) if request.method == 'POST': form = BotBufferForm(request.POST) if not form.is_valid(): print "ERROR in form!" return new_code = form.cleaned_data['code'] user_prof.code = new_code if 'publish_buffer' in request.POST: bot = Bot() bot.owner = user_prof bot.code = new_code bot.save() validate_bot.delay(bot.id, new_code) user_prof.current_bot = bot user_prof.save() return redirect('/mybots') else: form = BotBufferForm(instance=user_prof) return render(request, "my_bots.html", { 'form': form, 'user_prof': user_prof, 'tab': 'mybots', 'my_bots': reversed(Bot.objects.filter(owner=user_prof)) })
def ban_bot(bot, update, chat_data, to_ban: Bot, ban_state: bool): if to_ban.disabled and ban_state is True: update.message.reply_text( mdformat.none_action("{} is already banned.".format(to_ban)), parse_mode="markdown", ) return if not to_ban.disabled and ban_state is False: update.message.reply_text( mdformat.none_action("{} is not banned.".format(to_ban)), parse_mode="markdown", ) return if ban_state: to_ban.disable(Bot.DisabledReason.banned) update.message.reply_text("Bot was banned.") else: to_ban.enable() update.message.reply_text("Bot was unbanned.") to_ban.save() from components.explore import send_bot_details return send_bot_details(bot, update, chat_data, to_ban)
def common_new(request): port = 6667 if request.POST: name = request.POST.get("name") server = request.POST.get("server") type = int(request.POST.get("type")) channels = request.POST.get("channels") port = request.POST.get("port") nick = name # Validate errors = {} if len(name) > 36 or len(name) < 1: errors["name"] = "Username must be 36 characters or less" # test name for invalid characters if Bot.objects.filter(name=name, server=server): errors["name"] = "Nick already taken on %s" % server if not isinstance(type, int): errors["type"] = "Invalid bot type" #TODO: Regex! if len(server) < 5: errors["server"] = "Invalid server name" #TODO: Better checking if len(channels) < 1: errors["channels"] = "Specify at least one channel" elif len(channels) > 2000: errors["channels"] = "Too many channels specified" if len(port) > 5: errors["port"] = "Invalid port number, 6667 is default" if not port: port = 6667 port = int(port) if not errors: bot = Bot(owner=request.user, name=name, nick=nick, server=server, port=port, type=type, channels=channels, status=0) bot.save() # args = (type, bot.owner_id, name, server, port, channels) args = (server, port, nick, channels) # Create the bot on the daemon bus = dbus.SessionBus() service = bus.get_object('com.excid3.bothost', '/com/excid3/bothost') new_bot = service.get_dbus_method('new_bot', 'com.excid3.bothost') new_bot(type, bot.id, args) #TODO: Display a "successfully created" message at the top of the dashboard return HttpResponseRedirect("/") locals().update(bottypes=BOT_TYPES) t = loader.get_template("common/new.html") c = RequestContext(request, locals()) return HttpResponse(t.render(c))
def delete_bot(bot, update, to_edit: Bot): username = to_edit.username to_edit.disable(Bot.DisabledReason.banned) to_edit.save() bot.formatter.send_or_edit(update.effective_user.id, "Bot has been disabled and banned.", to_edit=util.mid_from_update(update)) Statistic.of(update, 'disable', username, Statistic.IMPORTANT)
def new(request): if request.method == 'POST': form = BotForm(request.POST) if form.is_valid(): bot = Bot(**form.cleaned_data) bot.save() return HttpResponseRedirect(bot.get_absolute_url()) else: form = BotForm() return render_to_response('bots/new.html', {'form': form}, context_instance=RequestContext(request))
def accept_bot_submission(bot, update, of_bot: Bot, category): uid = util.uid_from_update(update) message_id = util.mid_from_update(update) user = User.from_update(update) try: of_bot.category = category of_bot.date_added = datetime.date.today() of_bot.approved = True of_bot.approved_by = user of_bot.save() buttons = [[ InlineKeyboardButton( "Edit {} details".format(of_bot.username), callback_data=util.callback_for_action( CallbackActions.EDIT_BOT, {"id": of_bot.id}), ) ]] reply_markup = InlineKeyboardMarkup(buttons) bot.formatter.send_or_edit( uid, "{} has been accepted to the Botlist. ".format( of_bot, settings.BOT_ACCEPTED_IDLE_TIME), to_edit=message_id, reply_markup=reply_markup, ) log_msg = "{} accepted by {}.".format(of_bot.username, uid) # notify submittant if of_bot.submitted_by != user: try: bot.sendMessage( of_bot.submitted_by.chat_id, util.success( messages.ACCEPTANCE_PRIVATE_MESSAGE.format( of_bot.username, of_bot.category)), ) log_msg += "\nUser {} was notified.".format( str(of_bot.submitted_by)) except TelegramError: log_msg += "\nUser {} could NOT be contacted/notified in private.".format( str(of_bot.submitted_by)) log.info(log_msg) except: bot.formatter.send_failure(uid, "An error has occured. Bot not added.")
async def disable_decider(bot: TelegramBot, to_check: BotModel): assert to_check.disabled_reason != BotModel.DisabledReason.banned if ( to_check.offline and to_check.offline_for > settings.DISABLE_BOT_INACTIVITY_DELTA and to_check.disabled_reason != BotModel.DisabledReason.offline ): # Disable if the bot has been offline for too long if to_check.disable(to_check.DisabledReason.offline): to_check.save() if to_check.last_response: reason = "its last response was " + helpers.slang_datetime(to_check.last_response) else: reason = "it's been offline for.. like... ever" msg = "❌ {} disabled as {}.".format(to_check, reason) log.info(msg) bot.send_message(settings.BOTLIST_NOTIFICATIONS_ID, msg, timeout=30, parse_mode='markdown') else: log.info("huhwtf") elif ( to_check.online and to_check.disabled_reason == BotModel.DisabledReason.offline ): # Re-enable if the bot is disabled and came back online if to_check.enable(): to_check.save() msg = "{} was included in the @BotList again as it came back online.".format(to_check) log.info(msg) bot.send_message(settings.BOTLIST_NOTIFICATIONS_ID, msg, timeout=30, parse_mode='markdown') else: log.info("huhwtf")
def new_channel_post(bot, update, photo=None): post = update.channel_post if post.chat.username != settings.SELF_CHANNEL_USERNAME: return text = post.text channel, created = Channel.get_or_create(chat_id=post.chat_id, username=post.chat.username) if created: channel.save() category_list = '•Share your bots to the @BotListChat using the hashtag #new' in text intro = 'Hi! Welcome' in text category = text[0] == '•' and not category_list new_bots_list = 'NEW→' in text # TODO: is this a document? if photo: pass elif category: try: # get the category meta data meta = re.match(r'•(.*?)([A-Z].*):(?:\n(.*):)?', text).groups() if len(meta) < 2: raise ValueError("Category could not get parsed.") emojis = str.strip(meta[0]) name = str.strip(meta[1]) extra = str.strip(meta[2]) if meta[2] else None try: cat = Category.get(name=name) except Category.DoesNotExist: cat = Category(name=name) cat.emojis = emojis cat.extra = extra cat.save() # get the bots in that category bots = re.findall(r'^(🆕)?.*(@\w+)( .+)?$', text, re.MULTILINE) languages = Country.select().execute() for b in bots: username = b[1] try: new_bot = Bot.by_username(username) except Bot.DoesNotExist: new_bot = Bot(username=username) new_bot.category = cat new_bot.inlinequeries = "🔎" in b[2] new_bot.official = "🔹" in b[2] extra = re.findall(r'(\[.*\])', b[2]) if extra: new_bot.extra = extra[0] # find language for lang in languages: if lang.emoji in b[2]: new_bot.country = lang if b[0]: new_bot.date_added = datetime.date.today() else: new_bot.date_added = datetime.date.today( ) - datetime.timedelta(days=31) new_bot.save() except AttributeError: log.error("Error parsing the following text:\n" + text)
def submit(): if not request.is_json: res = _error('MimeType must be application/json.') res.status_code = 400 return res content = request.get_json() try: access = APIAccess.get(APIAccess.token == content.get('token')) except APIAccess.DoesNotExist: res = _error('The access token is invalid.') res.status_code = 401 return res username = content.get('username') if username is None or not isinstance(username, str): res = _error('You must supply a username.') res.status_code = 400 return res # insert `@` if omitted username = '******' + username if username[0] != '@' else username try: Bot.get(Bot.username == username) res = _error('The bot {} is already in the BotList.'.format(username)) res.status_code = 409 return res except Bot.DoesNotExist: b = Bot(username=username) name = content.get('name') description = content.get('description') inlinequeries = content.get('inlinequeries') try: if name: if isinstance(name, str): b.name = name else: raise AttributeError('The name field must be a string.') if description: if isinstance(description, str): b.description = description else: raise AttributeError('The description field must be a string.') if inlinequeries: if isinstance(inlinequeries, bool): b.inlinequeries = inlinequeries else: raise AttributeError( 'The inlinequeries field must be a boolean.') except Exception as e: res = _error(str(e)) res.status_code = 400 return res b.date_added = datetime.date.today() b.submitted_by = access.user b.approved = False b.save() res = jsonify({'success': '{} was submitted for approval.'.format(b)}) res.status_code = 201 return res
def newbot(request): bot = Bot(name=request.GET['n']) bot.save() return HttpResponse( "successfully created bot named '{1}' with id: {0}".format( bot.id, bot.name))
def check_submission(bot, bot_checker: "BotChecker", to_check: Bot): # TODO: make this method async if bot_checker is None: return botlistbot_user = User.botlist_user_instance() log.debug("Checking bot {}...".format(to_check.username)) def reject(reason): to_check.delete_instance() msg = notify_submittant_rejected( bot, botlistbot_user, notify_submittant=True, reason=reason, to_reject=to_check, ) bot.formatter.send_message(settings.BOTLIST_NOTIFICATIONS_ID, msg) try: peer = bot_checker.resolve_bot(to_check) except UsernameNotOccupied: to_check.delete_instance() reject( "The entity you submitted either does not exist or is not a Telegram bot." ) return bot_checker.update_bot_details(to_check, peer) if to_check.userbot: reject( "You submitted the name of a Telegram user, not one of a bot. If you're trying to " "submit a userbot, please contact the BLSF directly (" "@BotListChat).") return # Check online state response = loop.run_until_complete( bot_checker.get_ping_response(to_check, timeout=18, try_inline=to_check.inlinequeries)) is_offline = not bool(response) if is_offline: reject( "The bot you sent seems to be offline, unfortunately. Feel free to submit it again " "when it's back up 😙") return now = datetime.datetime.now() to_check.last_ping = now to_check.last_response = now loop.run_until_complete(add_keywords(bot, response, to_check)) # Download profile picture if settings.DOWNLOAD_PROFILE_PICTURES: # TODO: does this work asynchronously? loop.run_until_complete( download_profile_picture(bot, bot_checker, to_check)) to_check.save() log.info(f"{to_check} was evaluated and looks good for approval.")
def new_bot_submission(bot, update, chat_data, args=None, bot_checker=None): tg_user = update.message.from_user user = User.from_telegram_object(tg_user) if util.stop_banned(update, user): return reply_to = util.original_reply_id(update) if args: text = " ".join(args) else: text = update.message.text command_no_args = (len(re.findall(r"^/new\s*$", text)) > 0 or text.lower().strip() == "/new@botlistbot") if command_no_args: update.message.reply_text( util.action_hint( "Please use this command with an argument. For example:\n/new @mybot 🔎" ), reply_to_message_id=reply_to, ) return # `#new` is already checked by handler try: username = re.match(settings.REGEX_BOT_IN_TEXT, text).groups()[0] if username.lower() == "@" + settings.SELF_BOT_NAME.lower(): log.info("Ignoring {}".format(text)) return except AttributeError: if args: update.message.reply_text( util.failure( "Sorry, but you didn't send me a bot `@username`."), quote=True, parse_mode=ParseMode.MARKDOWN, reply_to_message_id=reply_to, ) log.info("Ignoring {}".format(text)) # no bot username, ignore update return try: new_bot = Bot.by_username(username, include_disabled=True) if new_bot.disabled: update.message.reply_text( util.failure("{} is banned from the @BotList.".format( new_bot.username)), reply_to_message_id=reply_to, ) elif new_bot.approved: update.message.reply_text( util.action_hint( "Sorry fool, but {} is already in the @BotList 😉". format(new_bot.username)), reply_to_message_id=reply_to, ) else: update.message.reply_text( util.action_hint( "{} has already been submitted. Please have patience...". format(new_bot.username)), reply_to_message_id=reply_to, ) return except Bot.DoesNotExist: new_bot = Bot( revision=Revision.get_instance().next, approved=False, username=username, submitted_by=user, ) new_bot.inlinequeries = "🔎" in text new_bot.official = "🔹" in text # find language languages = Country.select().execute() for lang in languages: if lang.emoji in text: new_bot.country = lang new_bot.date_added = datetime.date.today() description_reg = re.match(settings.REGEX_BOT_IN_TEXT + " -\s?(.*)", text) description_notify = "" if description_reg: description = description_reg.group(2) new_bot.description = description description_notify = " Your description was included." new_bot.save() if (util.is_private_message(update) and util.uid_from_update(update) in settings.MODERATORS): from components.explore import send_bot_details send_bot_details(bot, update, chat_data, new_bot) else: update.message.reply_text( util.success("You submitted {} for approval.{}".format( new_bot, description_notify)), parse_mode=ParseMode.MARKDOWN, reply_to_message_id=reply_to, ) # Ask the user to fill in the bot details util.send_md_message( bot, update.effective_user.id, "Congratulations, you just submitted a bot to the @BotList. Please help us fill in the details below:", ) edit_bot(bot, update, chat_data, to_edit=new_bot) try: check_submission(bot, bot_checker, new_bot) except Exception as e: log.exception(e) return ConversationHandler.END
async def check_bot( bot, bot_checker: BotChecker, to_check: BotModel, result_queue: asyncio.Queue ): log.debug("Checking bot {}...".format(to_check.username)) try: peer = bot_checker.resolve_bot(to_check) except UsernameNotOccupied: markup = InlineKeyboardMarkup([[ InlineKeyboardButton(captions.EDIT_BOT, callback_data=util.callback_for_action( CallbackActions.EDIT_BOT, dict(id=to_check.id) )) ]]) text = "{} does not exist (anymore). Please resolve this " \ "issue manually!".format(to_check.username) try: bot.send_message(settings.BLSF_ID, text, reply_markup=markup) except BadRequest: bot.send_notification(text) return await result_queue.put('not found') if not peer: return await result_queue.put('skipped') bot_checker.update_bot_details(to_check, peer=peer) # Check online state try: response = await bot_checker.get_ping_response( to_check, timeout=30, try_inline=to_check.inlinequeries) except UnknownError as e: await result_queue.put(e.MESSAGE) return except Exception as e: log.exception(e) await result_queue.put(str(e)) return for _ in range(2): await result_queue.put('messages sent') was_offline = to_check.offline is_offline = response.empty if isinstance(response, Response) else not bool(response) now = datetime.now() to_check.last_ping = now if not is_offline: to_check.last_response = now if was_offline != is_offline: bot.send_message(settings.BOTLIST_NOTIFICATIONS_ID, '{} went {}.'.format( to_check.str_no_md, 'offline' if to_check.offline else 'online' ), timeout=40) await add_keywords(bot, response, to_check) # Download profile picture if settings.DOWNLOAD_PROFILE_PICTURES: await download_profile_picture(bot, bot_checker, to_check) to_check.save() if settings.DELETE_CONVERSATION_AFTER_PING: await bot_checker.schedule_conversation_deletion(to_check.chat_id, 10) await disable_decider(bot, to_check) await result_queue.put('offline' if to_check.offline else 'online')
def newbot(request): bot = Bot(name=request.GET['n']) bot.save() return HttpResponse("successfully created bot named '{1}' with id: {0}".format(bot.id, bot.name))