def json_add_suggestion(request): if request.method == "POST": text = request.POST.get('addSuggestion', '(someone input invalid text)') sug = Suggestion(text=text) sug.save() return HttpResponseRedirect('/thanks_for_suggestion') return HttpResponse("failure")
def add_keyword(bot, update, chat_data): user = User.from_telegram_object(update.effective_user) if check_suggestion_limit(bot, update, user): return kw = update.message.text bot_to_edit = chat_data.get('edit_bot') kw = helpers.format_keyword(kw) # Sanity checks if kw in settings.FORBIDDEN_KEYWORDS: update.message.reply_text('The keyword {} is forbidden.'.format(kw)) return if len(kw) <= 1: update.message.reply_text('Keywords must be longer than 1 character.') return if len(kw) >= 20: update.message.reply_text( 'Keywords must not be longer than 20 characters.') # Ignore duplicates try: Keyword.get((Keyword.name == kw) & (Keyword.entity == bot_to_edit)) return except Keyword.DoesNotExist: pass Suggestion.add_or_update(user=user, action='add_keyword', subject=bot_to_edit, value=kw) set_keywords(bot, update, chat_data, bot_to_edit) Statistic.of(update, 'added keyword to'.format(kw), bot_to_edit.username)
def post(self): suggestion = Suggestion(title=self.request.get('title'), content=self.request.get('content')) suggestion.put() self.response.out.write( self._render_template('thank_you.html') )
def accept_suggestion(bot, update, suggestion: Suggestion): user = User.from_telegram_object(update.effective_user) suggestion.apply() if suggestion.action == 'offline': suggestion_text = '{} went {}.'.format( suggestion.subject.str_no_md, 'offline' if suggestion.subject.offline else 'online') else: suggestion_text = str(suggestion) suggestion_text = suggestion_text[0].upper() + suggestion_text[1:] suggestion_text += '\nApproved by ' + user.markdown_short bot.send_message(settings.BOTLIST_NOTIFICATIONS_ID, suggestion_text, parse_mode='markdown', disable_web_page_preview=True) if user != suggestion.user.chat_id: submittant_notification = '*Thank you* {}, your suggestion has been accepted:' \ '\n\n{}'.format(util.escape_markdown(suggestion.user.first_name), str(suggestion)) try: bot.send_message(suggestion.user.chat_id, submittant_notification, parse_mode='markdown', disable_web_page_preview=True) except BadRequest: update.effective_message.reply_text("Could not contact {}.".format( suggestion.user.markdown_short), parse_mode='markdown', disable_web_page_preview=True)
def set_text_property(bot, update, chat_data, property_name, to_edit=None): uid = util.uid_from_update(update) user = User.from_update(update) if check_suggestion_limit(bot, update, user): return if to_edit: text = (util.escape_markdown(getattr(to_edit, property_name)) + "\n\n" if getattr(to_edit, property_name) else '') text += mdformat.action_hint( messages.SET_BOTPROPERTY.format( property_name, util.escape_markdown(to_edit.username), CLEAR_QUERY)) if property_name == 'description': text += ', markdown enabled.' update.effective_message.reply_text( text, reply_markup=ForceReply(selective=True), parse_mode=ParseMode.MARKDOWN) chat_data['edit_bot'] = to_edit elif update.message: value = None text = update.message.text to_edit = chat_data.get('edit_bot', None) def too_long(n): bot.formatter.send_failure( uid, "Your {} text is too long, it must be shorter " "than {} characters. Please try again.".format( property_name, n)) util.wait(bot, update) return admin.edit_bot(bot, update, chat_data, to_edit) # Validation if property_name == 'description' and len(text) > 300: return too_long(300) if property_name == 'username': value = helpers.validate_username(text) if value: to_edit = chat_data.get('edit_bot', None) else: bot.formatter.send_failure( uid, "The username you entered is not valid. Please try again..." ) return admin.edit_bot(bot, update, chat_data, to_edit) if not value: value = text if to_edit: if _is_clear_query(text): Suggestion.add_or_update(user, property_name, to_edit, None) else: Suggestion.add_or_update(user, property_name, to_edit, value) admin.edit_bot(bot, update, chat_data, to_edit) else: bot.formatter.send_failure(uid, "An unexpected error occured.")
def remove_keyword(bot, update, chat_data, context): user = User.from_telegram_object(update.effective_user) if check_suggestion_limit(bot, update, user): return to_edit = context.get('to_edit') kw = context.get('keyword') Suggestion.add_or_update(user=user, action='remove_keyword', subject=to_edit, value=kw.name) return set_keywords(bot, update, chat_data, to_edit)
def add_suggestions(payload): body = request.get_json() suggestion = body.get('suggestion', None) category = body.get('category', None) new_sug = Suggestion(suggestion=suggestion, category=category) new_sug.insert() all_suggestions = Suggestion.query.all() formatted_sugg = [sug.format() for sug in all_suggestions] return jsonify({'success': True, 'all_suggestion': formatted_sugg})
def change_category(bot, update, to_edit, category): uid = update.effective_user.id user = User.get(User.chat_id == uid) if uid == 918962: # Special for t3chno to_edit.category = category to_edit.save() else: if check_suggestion_limit(bot, update, user): return Suggestion.add_or_update(user, 'category', to_edit, category.id)
def set_country(bot, update, to_edit, country): user = User.from_update(update) if check_suggestion_limit(bot, update, user): return if isinstance(country, Country): value = country.id elif country is None or country == 'None': value = None else: raise AttributeError("Error setting country to {}.".format(country)) Suggestion.add_or_update(user, 'country', to_edit, value)
def post(self): cancel = self.request.get('cancel') day = date.fromordinal(int(self.request.get('day'))) if cancel == 'true': self.currentuser.lastvoted = day self.currentuser.put() self.render('thanks') return rating = int(self.request.get('rating')) restaurant = cgi.escape(self.request.get('restaurant')) if restaurant == "other": restaurant = cgi.escape(self.request.get('others')) suggestion = Suggestion.find(day, restaurant) author = suggestion.author if suggestion else None restaurant=db.get(restaurant) comment = cgi.escape(self.request.get('comment')) if comment != "": comment = comment.replace('\n', '<br/>') comment = RestaurantComment(text=comment, restaurant=restaurant, author=self.currentuser, rating=rating) comment.put() self.add_rating(day, restaurant, author, rating) self.render_plain('thanks')
def delete_suggestion(self, args, user): messages = [] search = '' if len(args) <= 1: raise Exception( 'Suggestion delte syntax\n```css\n.d suggestion delete "NAME"```' ) if len(args) > 1: search = ' '.join(args[1:]) suggestion = Suggestion().find(search) if not suggestion: return [f'_"{search}"_ was not found. No changes made.'] else: search = str(suggestion.text) suggestion.archived = True self.save(suggestion, user) messages.append(f'***{search}*** removed') return messages
def apply_all_changes(bot, update, chat_data, to_edit): user = User.from_update(update) user_suggestions = Suggestion.select_all_of_user(user) for suggestion in user_suggestions: suggestion.apply() refreshed_bot = Bot.get(id=to_edit.id) edit_bot(bot, update, chat_data, refreshed_bot) Statistic.of(update, "apply", refreshed_bot.username)
def get_by_sugid_user(self, sugid, user): if not isinstance(user, User): raise TypeError() try: sugid = long(sugid) except: return None sugkey = db.Key.from_path(Suggestion.kind(), sugid) return self._klass.all().filter('suggestion =', sugkey).filter('user =', user).get()
def post(self): action = cgi.escape(self.request.get('action')) if action == 'add_suggestion': restaurant = cgi.escape(self.request.get('restaurant')) if restaurant == '': self.error(400) return sug = Suggestion(restaurant=db.get(restaurant), author=self.currentuser, group=self.currentgroup) sug.put() self.currentuser.lastposted = date.today() self.currentuser.put() notify_suggestion(sug) elif action == "remove_suggestion": suggestion = cgi.escape(self.request.get('suggestion')) suggestion = db.get(suggestion) if suggestion.author.user == self.currentuser.user: suggestion.delete() else: logging.error('user: %s tried to delete suggestion he doesn\'t own' % self.currentuser.nickname) elif action == "add_comment": text = cgi.escape(self.request.get('text')) suggestion = db.get(cgi.escape(self.request.get('suggestion'))) post_comment(text, self.currentuser, suggestion) elif action == "remove_comment": comment = cgi.escape(self.request.get('comment')) comment = db.get(comment) if comment.author.user == self.currentuser.user: comment.delete() else: logging.error('user: %s tried to delete comment he doesn\'t own' % self.currentuser.nickname) else: self.error(400) return self.get()
def check_suggestion_limit(bot, update, user): cid = update.effective_chat.id if Suggestion.over_limit(user): bot.formatter.send_failure( cid, "You have reached the limit of {} suggestions. Please wait for " "the Moderators to approve of some of them.".format( settings.SUGGESTION_LIMIT)) Statistic.of(update, 'hit the suggestion limit') return True return False
def edit_bot(bot, update, chat_data, to_edit=None): uid = util.uid_from_update(update) message_id = util.mid_from_update(update) user = User.from_update(update) if not to_edit: if update.message: command = update.message.text if "edit" in command: b_id = re.match(r"^/edit(\d+)$", command).groups()[0] elif "approve" in command: b_id = re.match(r"^/approve(\d+)$", command).groups()[0] else: raise ValueError("No 'edit' or 'approve' in command.") try: to_edit = Bot.get(id=b_id) except Bot.DoesNotExist: update.message.reply_text( util.failure("No bot exists with this id.")) return else: bot.formatter.send_failure(uid, "An unexpected error occured.") return # if not to_edit.approved: # return approve_bots(bot, update, override_list=[to_edit]) pending_suggestions = Suggestion.pending_for_bot(to_edit, user) reply_markup = InlineKeyboardMarkup( _edit_bot_buttons(to_edit, pending_suggestions, uid in settings.MODERATORS)) pending_text = ("\n\n{} Some changes are pending approval{}.".format( captions.SUGGESTION_PENDING_EMOJI, "" if user.chat_id in settings.MODERATORS else " by a moderator", ) if pending_suggestions else "") meta_text = ("\n\nDate added: {}\nMember since revision {}\n" "Submitted by {}\nApproved by {}".format( to_edit.date_added, to_edit.revision, to_edit.submitted_by, to_edit.approved_by, )) bot.formatter.send_or_edit( uid, "🛃 Edit {}{}{}".format( to_edit.detail_text, meta_text if user.id in settings.MODERATORS else "", pending_text, ), to_edit=message_id, reply_markup=reply_markup, )
def name(self, args): """Display and create a new Suggestion by name Parameters ---------- args : list(str) List of strings with subcommands Returns ------- list(str) - the response messages string array """ messages = [] if len(args) < 2: raise Exception('syntax: ```css\n.d suggest "SUGGESTION TEXT"```') suggestion = Suggestion().create_new(name=self.user.name, text=' '.join(args[1:])) messages.append(suggestion.get_string(self.user)) return messages
def test_edit_get_objet(self): view = EditSuggestionView() request = RequestFactory() view.request = request self.moxx.StubOutWithMock(views, 'get_client_ip') views.get_client_ip(request).AndReturn(self.ip) self.moxx.StubOutWithMock(Box, 'get_unread') Box.get_unread(self.ip).AndReturn(Suggestion(ip_address=self.ip)) self.moxx.ReplayAll() view.get_object() self.moxx.VerifyAll()
def send_anime_recommendation(anime_lst, anime_id, comment, username, curr_list): anime_by_id = next(item for item in anime_lst['results'] if item['mal_id'] == anime_id) suggestion = Suggestion(list_id=curr_list.id, anime_id=anime_id, anime_title=anime_by_id['title'], mal_url=anime_by_id['url'], comment=comment or 'No comment from suggester.', username=username) db.session.add(suggestion) db.session.commit()
def cron_suggestions(request=None, cursor=None): q = Suggestion.all().filter('_vis =', 'public') if cursor is None: suggs = q.fetch(10) else: suggs = q.with_cursor(cursor).fetch(10) if len(suggs) >= 10: try: defer(cron_suggestions, cursor=q.cursor(), _queue="fusiontables") except PermanentTaskFailure, e: import logging logging.error('ERROR FUSIONTABLES update relevance: %s' % e)
def suggest(request): if request.method == 'POST': form = SuggestionForm(request.POST) if form.is_valid(): clean_subject = form.cleaned_data['subject'] clean_message = form.cleaned_data['message'] clean_sender = form.cleaned_data.get('sender', '*****@*****.**') stamp = datetime.now() suggestion = Suggestion( subject = clean_subject, message = clean_message, sender = clean_sender, created = stamp, last_modified = stamp ) suggestion.save() suggestion_email = render_to_string('email/suggestion_made.txt', { 'suggestion': suggestion }) people_to_email = [settings.CSESOC_SUGGEST_LIST] if form.cleaned_data.get('sender'): people_to_email.append(clean_sender) # send an email to the suggestions mailing list send_mail( '[CSESoc Suggestion] %s' % clean_subject, suggestion_email, clean_sender, people_to_email ) return render_to_response('thanks-suggestion.html', context_instance=RequestContext(request)) else: form = SuggestionForm() return render_to_response('suggest.html', context_instance=RequestContext(request, {'form': form}))
def get(self): if self.currentuser.lastposted == None: self.redirect('/profile') return group = self.currentgroup context = { 'ask_to_rate' : can_vote(self.currentuser, self.currentgroup), 'active_crew': get_active_crew(group), 'dead_crew': get_dead_crew(group), 'suggestions': Suggestion.get_todays(group), 'restaurants': Restaurant.get_for_group(group) } self.render('home', context)
def _admin_buttons(send_botlist_button=False, logs_button=False): n_unapproved = len(Bot.select().where(Bot.approved == False, Bot.disabled == False)) n_suggestions = len(Suggestion.select_all()) n_pending = len(Bot.select_pending_update()) second_row = list() if n_unapproved > 0: second_row.append( KeyboardButton( captions.APPROVE_BOTS + " {}🆕".format(mdformat.number_as_emoji(n_unapproved)))) if n_suggestions > 0: second_row.append( KeyboardButton( captions.APPROVE_SUGGESTIONS + " {}⁉️".format(mdformat.number_as_emoji(n_suggestions)))) buttons = [ [KeyboardButton(captions.EXIT), KeyboardButton(captions.REFRESH)], [ KeyboardButton(captions.FIND_OFFLINE), KeyboardButton(captions.SEND_CONFIG_FILES), ], ] update_row = list() if n_pending > 0: update_row.append( KeyboardButton(captions.PENDING_UPDATE + " {}{}".format( mdformat.number_as_emoji(n_pending), captions.SUGGESTION_PENDING_EMOJI, ))) if send_botlist_button: update_row.append(KeyboardButton(captions.SEND_BOTLIST)) if logs_button: update_row.append(KeyboardButton(captions.SEND_ACTIVITY_LOGS)) if len(update_row) > 0: buttons.insert(1, update_row) if len(second_row) > 0: buttons.insert(1, second_row) return buttons
def handle_suggestion_response(result, current_asset_id, asset_metas): for asset_meta in asset_metas: asset_id = asset_meta.asset_id # skip if it is the same id as the classified image if current_asset_id == asset_id: continue cropped_id = asset_meta.cropped_id path = fetch_cropped_path(asset_id, cropped_id) if asset_id not in result.suggestions: result.suggestions[asset_id] = Suggestion([Frame(cropped_id, asset_meta.faiss_idx, path)]) else: contains = False for frame in result.suggestions[asset_id].frames: if frame.frame_id == cropped_id: contains = True break if not contains: result.suggestions[asset_id].frames += [Frame(cropped_id, asset_meta.faiss_idx, path)]
def ban_user(_bot, update, user: User, ban_state: bool): if user.banned and ban_state is True: update.message.reply_text( mdformat.none_action("User {} is already banned.".format(user)), parse_mode="markdown", ) raise DispatcherHandlerStop if not user.banned and ban_state is False: update.message.reply_text( mdformat.none_action("User {} is not banned.".format(user)), parse_mode="markdown", ) raise DispatcherHandlerStop user.banned = ban_state if ban_state is True: with db.atomic(): user_submissions = Bot.select().where( (Bot.approved == False) & (Bot.submitted_by == user) # TODO: does this need to include `Bot.deleted == True`? ) for b in user_submissions: b.delete_instance() users_suggestions = Suggestion.select().where( (Suggestion.executed == False) & (Suggestion.user == user)) for s in users_suggestions: s.delete_instance() update.message.reply_text( mdformat.success( "User {} banned, all bot submissions and suggestions removed.". format(user)), parse_mode="markdown", ) Statistic.of(update, "ban", user.markdown_short) else: update.message.reply_text(mdformat.success( "User {} unbanned.".format(user)), parse_mode="markdown") Statistic.of(update, "unban", user.markdown_short) user.save()
def get(self): if is_morning(): day = datetime.now() - timedelta(1) day_title = "yesterday" else: day = datetime.now() day_title = "today" suggestions = Suggestion.get_for_day(day, self.currentgroup) restaurants = [ s.restaurant for s in suggestions ] res_keys = [ r.key() for r in restaurants ] other_restaurants = [] all_restaurants = Restaurant.gql("WHERE group=:1 ORDER BY name", self.currentgroup) for res in all_restaurants: if res.key() not in res_keys: other_restaurants.append(res) context = { 'day': day.toordinal(), 'day_title': day_title, 'restaurants': restaurants, 'other_restaurants': other_restaurants } self.render('rate', context)
def register(dp: Dispatcher, bot_checker: "BotChecker"): def add(*args, **kwargs): dp.add_handler(*args, **kwargs) keywords_handler = ConversationHandler( entry_points=[ InlineCallbackHandler( CallbackActions.EDIT_BOT_KEYWORDS, botproperties.set_keywords_init, serialize=lambda data: dict(to_edit=Bot.get(id=data["id"])), pass_chat_data=True, ) ], states={ BotStates.SENDING_KEYWORDS: [ MessageHandler(Filters.text, botproperties.add_keyword, pass_chat_data=True), InlineCallbackHandler( CallbackActions.REMOVE_KEYWORD, botproperties.remove_keyword, serialize=lambda data: dict( to_edit=Bot.get(id=data["id"]), keyword=Keyword.get(id=data["kwid"]), ), pass_chat_data=True, ), InlineCallbackHandler( CallbackActions.DELETE_KEYWORD_SUGGESTION, botproperties.delete_keyword_suggestion, serialize=lambda data: dict( to_edit=Bot.get(id=data["id"]), suggestion=Suggestion.get(id=data["suggid"]), ), pass_chat_data=True, ), ] }, fallbacks=[ CallbackQueryHandler( callback_router, pass_chat_data=True, pass_user_data=True, pass_job_queue=True, ) ], per_user=True, allow_reentry=False, ) add(keywords_handler) broadcasting_handler = ConversationHandler( entry_points=[ InlineCallbackHandler("broadcast", broadcasts.broadcast, pass_user_data=True), CommandHandler("broadcast", broadcasts.broadcast, pass_user_data=True), CommandHandler("bc", broadcasts.broadcast, pass_user_data=True), ], states={ BotStates.BROADCASTING: [ MessageHandler(Filters.text, broadcasts.broadcast_preview, pass_user_data=True) ] }, fallbacks=[], per_user=True, per_chat=False, allow_reentry=True, ) add(broadcasting_handler) add( CallbackQueryHandler( callback_router, pass_chat_data=True, pass_user_data=True, pass_job_queue=True, )) add( CommandHandler(("cat", "category", "categories"), select_category, pass_chat_data=True)) add( CommandHandler(("s", "search"), search_handler, pass_args=True, pass_chat_data=True)) add(MessageHandler(Filters.reply, reply_router, pass_chat_data=True), group=-1) add(MessageHandler(Filters.forwarded, forward_router, pass_chat_data=True)) add(CommandHandler("admin", admin.menu)) add(CommandHandler("a", admin.menu)) add( CommandHandler(("rej", "reject"), admin.reject_bot_submission, pass_args=True)) add( CommandHandler( ("rejsil", "rejectsil", "rejsilent", "rejectsilent"), lambda bot, update: admin.reject_bot_submission( bot, update, None, notify_submittant=False), )) # admin menu add(RegexHandler(captions.APPROVE_BOTS + ".*", admin.approve_bots)) add( RegexHandler(captions.APPROVE_SUGGESTIONS + ".*", admin.approve_suggestions)) add(RegexHandler(captions.PENDING_UPDATE + ".*", admin.pending_update)) add( RegexHandler(captions.SEND_BOTLIST, admin.prepare_transmission, pass_chat_data=True)) add(RegexHandler(captions.FIND_OFFLINE, admin.send_offline)) add(RegexHandler(captions.SEND_CONFIG_FILES, admin.send_runtime_files)) add(RegexHandler(captions.SEND_ACTIVITY_LOGS, admin.send_activity_logs)) # main menu add(RegexHandler(captions.ADMIN_MENU, admin.menu)) add(RegexHandler(captions.REFRESH, admin.menu)) add(RegexHandler(captions.CATEGORIES, select_category, pass_chat_data=True)) add(RegexHandler(captions.EXPLORE, explore.explore, pass_chat_data=True)) add(RegexHandler(captions.FAVORITES, favorites.send_favorites_list)) add(RegexHandler(captions.NEW_BOTS, show_new_bots, pass_chat_data=True)) add(RegexHandler(captions.SEARCH, search_handler, pass_chat_data=True)) add(RegexHandler(captions.CONTRIBUTING, help.contributing)) add(RegexHandler(captions.EXAMPLES, help.examples)) add(RegexHandler(captions.HELP, help.help)) add(RegexHandler("^/edit\d+$", admin.edit_bot, pass_chat_data=True), group=1) add(RegexHandler("^/approve\d+$", admin.edit_bot, pass_chat_data=True), group=1) add(CommandHandler("approve", admin.short_approve_list)) add(CommandHandler(("manybot", "manybots"), admin.manybots)) add( CommandHandler( "new", partial(contributions.new_bot_submission, bot_checker=bot_checker), pass_args=True, pass_chat_data=True, )) add( RegexHandler( ".*#new.*", lambda bot, update, chat_data: contributions.new_bot_submission( bot, update, chat_data, args=None, bot_checker=bot_checker), pass_chat_data=True, ), group=1, ) add( CommandHandler("offline", contributions.notify_bot_offline, pass_args=True)) add(RegexHandler(".*#offline.*", contributions.notify_bot_offline), group=1) add(CommandHandler("spam", contributions.notify_bot_spam, pass_args=True)) add(RegexHandler(".*#spam.*", contributions.notify_bot_spam), group=1) add(CommandHandler("help", help.help)) add(CommandHandler(("contribute", "contributing"), help.contributing)) add(CommandHandler("examples", help.examples)) add(CommandHandler("rules", help.rules)) add( CommandHandler(("addfav", "addfavorite"), favorites.add_favorite_handler, pass_args=True)) add( CommandHandler(("f", "fav", "favorites"), favorites.send_favorites_list)) add(CommandHandler(("e", "explore"), explore.explore, pass_chat_data=True)) add(CommandHandler("official", explore.show_official)) add( CommandHandler( "ban", partial(admin.ban_handler, ban_state=True), pass_args=True, pass_chat_data=True, )) add( CommandHandler( "unban", partial(admin.ban_handler, ban_state=False), pass_args=True, pass_chat_data=True, )) add(CommandHandler("t3chno", t3chnostats)) add(CommandHandler("random", eastereggs.send_random_bot)) add( CommandHandler("easteregg", eastereggs.send_next, pass_args=True, pass_job_queue=True)) add(CommandHandler("subscribe", manage_subscription)) add(CommandHandler("newbots", show_new_bots, pass_chat_data=True)) add(CommandHandler("accesstoken", access_token)) add( CommandHandler(("stat", "stats", "statistic", "statistics"), admin.send_statistic)) add( CommandHandler(("log", "logs"), admin.send_activity_logs, pass_args=True)) add( CommandHandler( ("debug", "analysis", "ana", "analyze"), lambda bot, update, args: admin.send_activity_logs( bot, update, args, Statistic.ANALYSIS), pass_args=True, )) add( CommandHandler( "info", lambda bot, update, args: admin.send_activity_logs( bot, update, args, Statistic.INFO), pass_args=True, )) add( CommandHandler( ("detail", "detailed"), lambda bot, update, args: admin.send_activity_logs( bot, update, args, Statistic.DETAILED), pass_args=True, )) add( CommandHandler( ("warn", "warning"), lambda bot, update, args: admin.send_activity_logs( bot, update, args, Statistic.WARN), pass_args=True, )) add( CommandHandler( "important", lambda bot, update, args: admin.send_activity_logs( bot, update, args, Statistic.IMPORTANT), pass_args=True, )) add( MessageHandler( Filters.text, lambda bot, update: botlistchat.text_message_logger( bot, update, log), ), group=99, ) for hashtag in HINTS.keys(): add( RegexHandler(r"{}.*".format(hashtag), botlistchat.hint_handler, pass_job_queue=True), group=1, ) add(CommandHandler(("hint", "hints"), botlistchat.show_available_hints)) add( RegexHandler( "^{}$".format(settings.REGEX_BOT_ONLY), send_bot_details, pass_chat_data=True, )) add( ChosenInlineResultHandler(inlinequeries.chosen_result, pass_chat_data=True)) add( InlineQueryHandler(inlinequeries.inlinequery_handler, pass_chat_data=True)) add(MessageHandler(Filters.all, all_handler, pass_chat_data=True), group=98)
def approve_suggestions(bot, update, page=0): uid = util.uid_from_update(update) suggestions = Suggestion.select_all() if page * settings.PAGE_SIZE_SUGGESTIONS_LIST >= len(suggestions): # old item deleted, list now too small page = page - 1 if page > 0 else 0 start = page * settings.PAGE_SIZE_SUGGESTIONS_LIST end = start + settings.PAGE_SIZE_SUGGESTIONS_LIST has_prev_page = page > 0 has_next_page = (page + 1) * settings.PAGE_SIZE_SUGGESTIONS_LIST < len( suggestions) suggestions = suggestions[start:end] if len(suggestions) == 0: bot.formatter.send_or_edit(uid, "No more suggestions available.", to_edit=util.mid_from_update(update)) return buttons = [] count = 1 text = "Please choose suggestions to accept.\n" for x in suggestions: number = str(count) + "." text += "\n{} {}".format(number, str(x)) row = [] # Should the suggestion be editable and is it too long? if x.action in Suggestion.TEXTUAL_ACTIONS: row.append( InlineKeyboardButton( "{} {}📝".format(number, Emoji.WHITE_HEAVY_CHECK_MARK), callback_data=util.callback_for_action( CallbackActions.CHANGE_SUGGESTION, { "id": x.id, "page": page }), )) else: row.append( InlineKeyboardButton( "{} {}".format(number, Emoji.WHITE_HEAVY_CHECK_MARK), callback_data=util.callback_for_action( CallbackActions.ACCEPT_SUGGESTION, { "id": x.id, "page": page }), )) row.append( InlineKeyboardButton( "{} {}".format(number, Emoji.CROSS_MARK), callback_data=util.callback_for_action( CallbackActions.REJECT_SUGGESTION, { "id": x.id, "page": page }), )) buttons.append(row) count += 1 page_arrows = list() if has_prev_page: page_arrows.append( InlineKeyboardButton( Emoji.LEFTWARDS_BLACK_ARROW, callback_data=util.callback_for_action( CallbackActions.SWITCH_SUGGESTIONS_PAGE, {"page": page - 1}), )) if has_next_page: page_arrows.append( InlineKeyboardButton( Emoji.BLACK_RIGHTWARDS_ARROW, callback_data=util.callback_for_action( CallbackActions.SWITCH_SUGGESTIONS_PAGE, {"page": page + 1}), )) buttons.append(page_arrows) reply_markup = InlineKeyboardMarkup(buttons) bot.formatter.send_or_edit( uid, util.action_hint(text), reply_markup=reply_markup, to_edit=util.mid_from_update(update), disable_web_page_preview=True, ) return CallbackStates.APPROVING_BOTS
def get(self): context = { 'suggestions': Suggestion.get_todays(self.currentgroup) } self.render('suggestions', context)
def notify_bot_offline(bot, update, args=None): tg_user = update.message.from_user user = User.from_telegram_object(tg_user) 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() == "/offline@botlistbot") if command_no_args: update.message.reply_text( util.action_hint( "Please use this command with an argument. For example:\n/offline @mybot" ), reply_to_message_id=reply_to, ) return # `#offline` is already checked by handler try: username = re.match(settings.REGEX_BOT_IN_TEXT, text).groups()[0] if username == "@" + settings.SELF_BOT_NAME: 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, ) else: log.info("Ignoring {}".format(text)) # no bot username, ignore update pass return try: offline_bot = Bot.get( fn.lower(Bot.username)**username.lower(), Bot.approved == True) try: Suggestion.get(action="offline", subject=offline_bot) except Suggestion.DoesNotExist: suggestion = Suggestion( user=user, action="offline", date=datetime.date.today(), subject=offline_bot, ) suggestion.save() update.message.reply_text( util.success( "Thank you! We will review your suggestion and set the bot offline." ), reply_to_message_id=reply_to, ) except Bot.DoesNotExist: update.message.reply_text( util.action_hint("The bot you sent me is not in the @BotList."), reply_to_message_id=reply_to, ) return ConversationHandler.END
def route_suggestion(suggestion_id): suggestion = Suggestion.get(suggestion_id) return render_template('suggestion.html', suggestion=suggestion)
def toggle_value(bot, update, property_name, to_edit, value): user = User.from_update(update) if check_suggestion_limit(bot, update, user): return Suggestion.add_or_update(user, property_name, to_edit, bool(value))
def set_keywords(bot, update, chat_data, to_edit): chat_id = util.uid_from_update(update) keywords = Keyword.select().where(Keyword.entity == to_edit) chat_data['edit_bot'] = to_edit set_keywords_msgid = chat_data.get('set_keywords_msg') pending = Suggestion.select().where( Suggestion.executed == False, Suggestion.subject == to_edit, Suggestion.action << ['add_keyword', 'remove_keyword']) pending_removal = [y for y in pending if y.action == 'remove_keyword'] # Filter keywords by name to not include removal suggestions # We don't need to do this for add_keyword suggestions, because duplicates are not allowed. keywords = [ k for k in keywords if k.name not in [s.value for s in pending_removal] ] kw_remove_buttons = [ InlineCallbackButton('{} ✖️'.format(x), callback_action=CallbackActions.REMOVE_KEYWORD, params={ 'id': to_edit.id, 'kwid': x.id }) for x in keywords ] kw_remove_buttons.extend([ InlineKeyboardButton('#{} 👓✖️'.format(x.value), callback_data=util.callback_for_action( CallbackActions.DELETE_KEYWORD_SUGGESTION, { 'id': to_edit.id, 'suggid': x.id })) for x in [y for y in pending if y.action == 'add_keyword'] ]) kw_remove_buttons.extend([ InlineKeyboardButton('#{} 👓❌'.format(x.value), callback_data=util.callback_for_action( CallbackActions.DELETE_KEYWORD_SUGGESTION, { 'id': to_edit.id, 'suggid': x.id })) for x in pending_removal ]) buttons = util.build_menu( kw_remove_buttons, 2, header_buttons=[ InlineKeyboardButton(captions.DONE, callback_data=util.callback_for_action( CallbackActions.ABORT_SETTING_KEYWORDS, {'id': to_edit.id})) ]) reply_markup = InlineKeyboardMarkup(buttons) msg = util.send_or_edit_md_message( bot, chat_id, util.action_hint( 'Send me the keywords for {} one by one...\n\n{}'.format( util.escape_markdown(to_edit.username), messages.KEYWORD_BEST_PRACTICES)), to_edit=set_keywords_msgid, reply_markup=reply_markup) if msg: # message might not have been edited if the user adds an already-existing keyword # TODO: should the user be notified about this? chat_data['set_keywords_msg'] = msg.message_id return BotStates.SENDING_KEYWORDS
def test_suggestion_unicode(self): mod = Suggestion(ip_address=self.ip) self.assertTrue(self.ip in '%s' % mod)
def test_suggestion_property(self): mod = Suggestion(ip_address=self.ip, message='x'*90) self.assertTrue(mod.message_start, 'x'*80)
def callback_router(bot, update, chat_data, user_data, job_queue): obj = json.loads(str(update.callback_query.data)) user = User.from_update(update) try: if "a" in obj: action = obj["a"] # BOTLISTCHAT if action == CallbackActions.DELETE_CONVERSATION: botlistchat.delete_conversation(bot, update, chat_data) # HELP elif action == CallbackActions.HELP: help.help(bot, update) elif action == CallbackActions.CONTRIBUTING: help.contributing(bot, update) elif action == CallbackActions.EXAMPLES: help.examples(bot, update) # BASIC QUERYING elif action == CallbackActions.SELECT_CATEGORY: select_category(bot, update, chat_data) elif action == CallbackActions.SELECT_BOT_FROM_CATEGORY: category = Category.get(id=obj["id"]) send_category(bot, update, chat_data, category) elif action == CallbackActions.SEND_BOT_DETAILS: item = Bot.get(id=obj["id"]) send_bot_details(bot, update, chat_data, item) # FAVORITES elif action == CallbackActions.TOGGLE_FAVORITES_LAYOUT: value = obj["v"] favorites.toggle_favorites_layout(bot, update, value) elif action == CallbackActions.ADD_FAVORITE: favorites.add_favorite_handler(bot, update) elif action == CallbackActions.REMOVE_FAVORITE_MENU: favorites.remove_favorite_menu(bot, update) elif action == CallbackActions.REMOVE_FAVORITE: to_remove = Favorite.get(id=obj["id"]) bot_details = to_remove.bot to_remove.delete_instance() if obj.get("details"): send_bot_details(bot, update, chat_data, bot_details) else: favorites.remove_favorite_menu(bot, update) elif action == CallbackActions.SEND_FAVORITES_LIST: favorites.send_favorites_list(bot, update) elif action == CallbackActions.ADD_ANYWAY: favorites.add_custom(bot, update, obj["u"]) elif action == CallbackActions.ADD_TO_FAVORITES: details = obj.get("details") discreet = obj.get("discreet", False) or details item = Bot.get(id=obj["id"]) favorites.add_favorite(bot, update, item, callback_alert=discreet) if details: send_bot_details(bot, update, chat_data, item) # ACCEPT/REJECT BOT SUBMISSIONS elif action == CallbackActions.APPROVE_REJECT_BOTS: custom_approve_list = [Bot.get(id=obj["id"])] admin.approve_bots(bot, update, override_list=custom_approve_list) elif action == CallbackActions.ACCEPT_BOT: to_accept = Bot.get(id=obj["id"]) admin.edit_bot_category(bot, update, to_accept, CallbackActions.BOT_ACCEPTED) # Run in x minutes, giving the moderator enough time to edit bot details job_queue.run_once( lambda b, job: botlistchat. notify_group_submission_accepted(b, job, to_accept), settings.BOT_ACCEPTED_IDLE_TIME * 60, ) elif action == CallbackActions.RECOMMEND_MODERATOR: bot_in_question = Bot.get(id=obj["id"]) admin.recommend_moderator(bot, update, bot_in_question, obj["page"]) elif action == CallbackActions.SELECT_MODERATOR: bot_in_question = Bot.get(id=obj["bot_id"]) moderator = User.get(id=obj["uid"]) admin.share_with_moderator(bot, update, bot_in_question, moderator) admin.approve_bots(bot, update, obj["page"]) elif action == CallbackActions.REJECT_BOT: to_reject = Bot.get(id=obj["id"]) notification = obj.get("ntfc", True) admin.reject_bot_submission( bot, update, None, to_reject, verbose=False, notify_submittant=notification, ) admin.approve_bots(bot, update, obj["page"]) elif action == CallbackActions.BOT_ACCEPTED: to_accept = Bot.get(id=obj["bid"]) category = Category.get(id=obj["cid"]) admin.accept_bot_submission(bot, update, to_accept, category) elif action == CallbackActions.COUNT_THANK_YOU: new_count = obj.get("count", 1) basic.count_thank_you(bot, update, new_count) # ADD BOT # elif action == CallbackActions.ADD_BOT_SELECT_CAT: # category = Category.get(id=obj['id']) # admin.add_bot(bot, update, chat_data, category) # EDIT BOT elif action == CallbackActions.EDIT_BOT: to_edit = Bot.get(id=obj["id"]) admin.edit_bot(bot, update, chat_data, to_edit) elif action == CallbackActions.EDIT_BOT_SELECT_CAT: to_edit = Bot.get(id=obj["id"]) admin.edit_bot_category(bot, update, to_edit) elif action == CallbackActions.EDIT_BOT_CAT_SELECTED: to_edit = Bot.get(id=obj["bid"]) cat = Category.get(id=obj["cid"]) botproperties.change_category(bot, update, to_edit, cat) admin.edit_bot(bot, update, chat_data, to_edit) elif action == CallbackActions.EDIT_BOT_COUNTRY: to_edit = Bot.get(id=obj["id"]) botproperties.set_country_menu(bot, update, to_edit) elif action == CallbackActions.SET_COUNTRY: to_edit = Bot.get(id=obj["bid"]) if obj["cid"] == "None": country = None else: country = Country.get(id=obj["cid"]) botproperties.set_country(bot, update, to_edit, country) admin.edit_bot(bot, update, chat_data, to_edit) elif action == CallbackActions.EDIT_BOT_DESCRIPTION: to_edit = Bot.get(id=obj["id"]) botproperties.set_text_property(bot, update, chat_data, "description", to_edit) elif action == CallbackActions.EDIT_BOT_EXTRA: to_edit = Bot.get(id=obj["id"]) # SAME IS DONE HERE, but manually botproperties.set_text_property(bot, update, chat_data, "extra", to_edit) elif action == CallbackActions.EDIT_BOT_NAME: to_edit = Bot.get(id=obj["id"]) botproperties.set_text_property(bot, update, chat_data, "name", to_edit) elif action == CallbackActions.EDIT_BOT_USERNAME: to_edit = Bot.get(id=obj["id"]) botproperties.set_text_property(bot, update, chat_data, "username", to_edit) # elif action == CallbackActions.EDIT_BOT_KEYWORDS: # to_edit = Bot.get(id=obj['id']) # botproperties.set_keywords_init(bot, update, chat_data, to_edit) elif action == CallbackActions.APPLY_ALL_CHANGES: to_edit = Bot.get(id=obj["id"]) admin.apply_all_changes(bot, update, chat_data, to_edit) elif action == CallbackActions.EDIT_BOT_INLINEQUERIES: to_edit = Bot.get(id=obj["id"]) value = bool(obj["value"]) botproperties.toggle_value(bot, update, "inlinequeries", to_edit, value) admin.edit_bot(bot, update, chat_data, to_edit) elif action == CallbackActions.EDIT_BOT_OFFICIAL: to_edit = Bot.get(id=obj["id"]) value = bool(obj["value"]) botproperties.toggle_value(bot, update, "official", to_edit, value) admin.edit_bot(bot, update, chat_data, to_edit) elif action == CallbackActions.EDIT_BOT_OFFLINE: to_edit = Bot.get(id=obj["id"]) value = bool(obj["value"]) botproperties.toggle_value(bot, update, "offline", to_edit, value) admin.edit_bot(bot, update, chat_data, to_edit) elif action == CallbackActions.EDIT_BOT_SPAM: to_edit = Bot.get(id=obj["id"]) value = bool(obj["value"]) botproperties.toggle_value(bot, update, "spam", to_edit, value) admin.edit_bot(bot, update, chat_data, to_edit) elif action == CallbackActions.CONFIRM_DELETE_BOT: to_delete = Bot.get(id=obj["id"]) botproperties.delete_bot_confirm(bot, update, to_delete) elif action == CallbackActions.DELETE_BOT: to_edit = Bot.get(id=obj["id"]) botproperties.delete_bot(bot, update, to_edit) # send_category(bot, update, chat_data, to_edit.category) elif action == CallbackActions.ACCEPT_SUGGESTION: suggestion = Suggestion.get(id=obj["id"]) components.botproperties.accept_suggestion( bot, update, suggestion) admin.approve_suggestions(bot, update, page=obj["page"]) elif action == CallbackActions.REJECT_SUGGESTION: suggestion = Suggestion.get(id=obj["id"]) suggestion.delete_instance() admin.approve_suggestions(bot, update, page=obj["page"]) elif action == CallbackActions.CHANGE_SUGGESTION: suggestion = Suggestion.get(id=obj["id"]) botproperties.change_suggestion(bot, update, suggestion, page_handover=obj["page"]) elif action == CallbackActions.SWITCH_SUGGESTIONS_PAGE: page = obj["page"] admin.approve_suggestions(bot, update, page) elif action == CallbackActions.SWITCH_APPROVALS_PAGE: admin.approve_bots(bot, update, page=obj["page"]) elif action == CallbackActions.SET_NOTIFICATIONS: set_notifications(bot, update, obj["value"]) elif action == CallbackActions.NEW_BOTS_SELECTED: show_new_bots(bot, update, chat_data, back_button=True) elif action == CallbackActions.ABORT_SETTING_KEYWORDS: to_edit = Bot.get(id=obj["id"]) admin.edit_bot(bot, update, chat_data, to_edit) # SENDING BOTLIST elif action == CallbackActions.SEND_BOTLIST: silent = obj.get("silent", False) re_send = obj.get("re", False) botlist.send_botlist(bot, update, resend=re_send, silent=silent) elif action == CallbackActions.RESEND_BOTLIST: botlist.send_botlist(bot, update, resend=True) # BROADCASTING elif action == "send_broadcast": broadcasts.send_broadcast(bot, update, user_data) elif action == "pin_message": broadcasts.pin_message(bot, update, obj["mid"]) elif action == "add_thank_you": basic.add_thank_you_button(bot, update, obj["cid"], obj["mid"]) # EXPLORING elif action == CallbackActions.EXPLORE_NEXT: explore.explore(bot, update, chat_data) except Exception as e: traceback.print_exc() # get the callback action in plaintext actions = dict(CallbackActions.__dict__) a = next(k for k, v in actions.items() if v == obj.get("a")) util.send_md_message( bot, settings.DEVELOPER_ID, "Exception in callback query for {}:\n{}\n\nWith CallbackAction {}\n\nWith data:\n{}" .format( user.markdown_short, util.escape_markdown(e), util.escape_markdown(a), util.escape_markdown(str(obj)), ), ) finally: bot.answerCallbackQuery(update.callback_query.id) return ConversationHandler.END
def test_suggestion_clean_raise(self): Suggestion.objects.create(ip_address=self.ip) mod = Suggestion(ip_address=self.ip) self.assertRaises(ValidationError, mod.clean)
def can_vote_for_day(day): return (not userinfo.voted_for_day(day) and Suggestion.get_for_day(day, group).count() > 0)