def buttoncgintskill(self, query: CallbackQuery, args: List[str], card1: Optional[GameCard]) -> bool: if not card1: return self.errorHandlerQ(query, "找不到卡。") if len(args) == 3: skvalue = int(args[2]) needpt = self.evalskillcost(args[1], skvalue, card1, False) card1.interest.set(args[1], skvalue, needpt) query.edit_message_text(text="兴趣技能:" + args[1] + "的值现在是" + str(skvalue) + "。剩余技能点:" + str(card1.interest.points)) card1.group.write() if card1.skill.points or card1.interest.points: self.addskill0(card1) return True m = self.getskilllevelfromdict(card1, args[1]) mm = self.skillmaxval(args[1], card1, False) rtbuttons = self.makeIntButtons(m, mm, args[0], args[1]) rp_markup = InlineKeyboardMarkup(rtbuttons) query.edit_message_text( "更改兴趣技能点数。剩余技能点:" + str(card1.interest.points) + " 技能名称:" + args[1] + ",当前技能点:" + str(card1.interest.get(args[1])), reply_markup=rp_markup) self.workingMethod[self.lastchat] = BUTTON_CGINTSKILL return True
def draft_heart_button_click_handler(bot: telegram.Bot, _: telegram.Update, query: telegram.CallbackQuery, data) -> None: """ Обработчик кнопки выбора сердечка """ user_id = query.from_user.id draft: Optional[CardDraftSelectHeart] = cache.get( f'{CACHE_PREFIX}:draft:card:{user_id}') if draft is None or not isinstance(draft, CardDraftSelectHeart): query.answer(text='Черновик не найден') query.message.delete() return heart: str = data['heart'] chat_names = { chat.chat_id: get_chat_title(bot, chat.chat_id) for chat in draft.from_user.chats } answer = draft.select_heart(heart, chat_names) answer.original_draft_message_id = draft.original_draft_message_id cache.set(f'{CACHE_PREFIX}:draft:card:{user_id}', answer, time=TWO_DAYS) query.edit_message_text(text=answer.get_message_text(), parse_mode=HTML) query.edit_message_reply_markup( reply_markup=get_reply_markup(answer.get_message_buttons())) query.answer()
def select_time(update: Update, context: CallbackContext, query: CallbackQuery): time_btns = [[ InlineKeyboardButton(text=times[0].name, callback_data=json.dumps([ CallbackCommands.POPULARITY.SELECT_TIME, times[0].uid ])) ]] for i in range(1, 24, 3): time_btns.append([ InlineKeyboardButton(text=times[i].name, callback_data=json.dumps([ CallbackCommands.POPULARITY.SELECT_TIME, times[i].uid ])), InlineKeyboardButton(text=times[i + 1].name, callback_data=json.dumps([ CallbackCommands.POPULARITY.SELECT_TIME, times[i + 1].uid ])), InlineKeyboardButton(text=times[i + 2].name, callback_data=json.dumps([ CallbackCommands.POPULARITY.SELECT_TIME, times[i + 2].uid ])) ]) markup = InlineKeyboardMarkup(time_btns) query.edit_message_text(text='Zeit Auswählen') query.edit_message_reply_markup(reply_markup=markup)
def subscribe(update: Update, query: CallbackQuery, location: str) -> None: """ Inline command responsible for handling subscriptions :param update: Telegram Update Object for getting right user :param query: Telegram Query Object for inline functionality :param location: Location that should be toggled - Adds user to database - Toggles status of chosen location - Updates message - Saves new settings to db """ # getting chat by using the writer.add method # it checks database and adds chat if not already existing # the users chat will be returned chat = writer.add(update.effective_chat) settings = chat.settings # settings of that chat contain subscription status # if location is not subscribed - subscribing if not settings[location]: settings[location] = True query.edit_message_text(text=f'Sie haben {location} abonniert', reply_markup=kb.inline_sub_soft) # location is subscribed - settings subscription to false else: settings[location] = False query.edit_message_text(text=f'Sie haben {location} deabonniert', reply_markup=kb.inline_sub_soft) # writing db to store changes writer.write()
def export_watchlist(query: CallbackQuery): """ Wrapper for watchlist_to_csv() that handles the telegram part, edits message and sends file """ path = watchlist_to_csv(query) with open(path, 'r') as f: query.edit_message_text("Here you go:") query.message.chat.send_document(f)
def buttonsetdec(self, query: CallbackQuery, args: List[str], card1: Optional[GameCard]) -> bool: if not card1: return self.errorHandlerQ(query, "找不到卡。") dname = args[0][:args[0].find("dec")] if dname not in card1.data.alldatanames: self.sendtoAdmin("属性名错误,请检查代码") return self.errorHandlerQ(query, "属性名错误,请检查代码") if card1.data.datadec is None: return self.errorHandlerQ(query, "该卡无需设置属性降值。") decnames = card1.data.datadec[0].split('_') decval = int(args[2]) assert (card1.data.__dict__[dname] - decval >= 1) assert (card1.data.datadec[1] + decval <= 0) if len(decnames) == 2: otherdec = decnames[0] if dname == decnames[1] else decnames[1] assert (card1.data.__dict__[otherdec] + card1.data.datadec[1] + decval >= 1) card1.data.__dict__[dname] -= decval card1.data.__dict__[otherdec] += card1.data.datadec[1] + decval card1.data.datadec = None card1.generateOtherAttributes() query.edit_message_text( f"属性下降设置完成,现在基础属性:\n{str(card1.data)}\n请点击 /setjob 设置职业。") return True if len(decnames) == 3: decnames.pop(decnames.index(dname)) card1.data.__dict__[dname] -= decval card1.data.datadec = ('_'.join(decnames), card1.data.datadec[1] + decval) card1.write() query.edit_message_text(f"请继续设置属性降值,目前全部数值如下:\n{str(card1.data)}") rtbuttons = [[]] for dname in decnames: rtbuttons[0].append( InlineKeyboardButton(text=dname, callback_data="choosedec " + dname)) rp_markup = InlineKeyboardMarkup(rtbuttons) query.edit_message_reply_markup(reply_markup=rp_markup) self.workingMethod[self.lastchat] = BUTTON_CHOOSEDEC return True self.sendtoAdmin("下降属性参数长度有误") return self.errorHandlerQ(query, "下降属性参数长度有误")
def ban_roadblock_author(_bot: Bot, query: CallbackQuery) -> None: if query.message.chat.id == mods_chat: nmaps_message = retrieve_roadblock(mods_id=query.message.message_id) else: nmaps_message = retrieve_roadblock(roads_id=query.message.message_id) query.edit_message_text(BOT_USER_BANNED.format(query.from_user.name, query.from_user.id), parse_mode='markdown') with db_session: U.get(user_id=nmaps_message.author).banned = True
def buttonswitch(self, query: CallbackQuery, args: List[str]) -> bool: pl = self.forcegetplayer(self.lastchat) cdid = int(args[1]) if cdid not in pl.cards: return self.errorHandlerQ(query, "没有找到这个id的卡。") pl.controlling = pl.cards[cdid] pl.write() query.edit_message_text("修改成功,现在操作的卡是:" + pl.controlling.getname()) return True
def send_response(query: CallbackQuery, text): # display message to user try: query.edit_message_text(text=text) query.edit_message_reply_markup( reply_markup=InlineKeyboardMarkup([[]])) except BadRequest as e: # filter out weird "Message is not modified" error if 'Message is not modified' in e.message: pass else: raise e
def inlinebutton_tweet_time(update: Update, context: CallbackContext, query: CallbackQuery, args: List[str]): try: tweet_time = datetime.strptime(':'.join(args), '%H:%M').strftime("%H:%M") except ValueError: query.edit_message_text( "Sorry, I didn't understand that time. Time must be in format %H:%M" ) return redis.set(f'chat:{query.message.chat_id}:settings:tweet_time', tweet_time) query.edit_message_text(f'I will tweet at {tweet_time}')
def cancel_roadblock(bot: Bot, query: CallbackQuery) -> None: if query.message.chat.id == mods_chat: nmaps_message = retrieve_roadblock(mods_id=query.message.message_id) else: if query.from_user.last_name not in roads_staff: query.answer(BOT_NOT_ROAD_STAFF) return nmaps_message = retrieve_roadblock(roads_id=query.message.message_id) bot.send_message(nmaps_message.chat_id, BOT_REQUEST_CANCELLED_USR, reply_to_message_id=nmaps_message.chat_message_id) query.edit_message_text(BOT_REQUEST_CANCELLED.format( query.from_user.name, query.from_user.id), parse_mode='markdown')
def select_day(update: Update, context: CallbackContext, query: CallbackQuery): day_btns = [] for day in days: day_btns.append([ InlineKeyboardButton(text=day.name, callback_data=json.dumps([ CallbackCommands.POPULARITY.SELECT_DAY, day.uid ])) ]) markup = InlineKeyboardMarkup(day_btns) query.edit_message_text(text="Tag auswählen") query.edit_message_reply_markup(reply_markup=markup)
def buttondiscard(self, query: CallbackQuery, args: List[str]) -> bool: cdid = int(args[1]) card = self.getcard(cdid) if card is None: return self.errorHandlerQ(query, "找不到这个id的卡。") pl = self.forcegetplayer(self.lastchat) if not self.checkaccess(pl, card) & CANDISCARD: return self.errorHandlerQ(query, "该卡不可删除。") self.cardpop(cdid) query.edit_message_text(f"删除了:{card.getname()}。\n该删除操作不可逆。") return True
def accept_roadblock(bot: Bot, query: CallbackQuery) -> None: query.edit_message_text(BOT_SENT_TO_STAFF.format(query.from_user.name, query.from_user.id), parse_mode='markdown') nmaps_message = retrieve_roadblock(mods_id=query.message.message_id) bot.forward_message(roads_chat, nmaps_message.chat_id, nmaps_message.chat_message_id) roads_message = bot.send_message(roads_chat, BOT_NEW_ROADBLOCK, reply_markup=staff_keyboard) nmaps_message = retrieve_roadblock(mods_id=query.message.message_id) with db_session: Roadblock.get(chat_message_id=nmaps_message.chat_message_id)\ .roads_message_id = roads_message.message_id
def round_inline_handle(bot: telegram.Bot, query: telegram.CallbackQuery, gm: bool, game_round: Round): _ = partial(get_by_user, user=query.from_user) method = str(query.data) actors = game_round.get_actors() if method == 'round:next': next_count = game_round.counter + 1 if next_count >= len(actors): next_count = 0 game_round.round_counter += 1 game_round.counter = next_count game_round.save() query.answer() refresh_round_message(bot, game_round, _) elif method == 'round:prev': prev_count = game_round.counter - 1 if prev_count < 0: if game_round.round_counter <= 1: query.answer(text=_(Text.ALREADY_FIRST_TURN)) return else: prev_count = len(actors) - 1 game_round.round_counter -= 1 game_round.counter = prev_count query.answer() refresh_round_message(bot, game_round, _, refresh=True) game_round.save() elif method == 'round:remove': if not gm: raise NotGm() actors = game_round.get_actors() if len(actors) > 1: current = actors[game_round.counter % len(actors)] current.delete() query.answer() refresh_round_message(bot, game_round, _, refresh=True) else: query.answer(show_alert=True, text=_(Text.AT_LEAST_ONE_ACTOR)) elif method == 'round:finish': if not gm: raise NotGm() query.edit_message_text(_(Text.ROUND_ALREADY_FINISHED)) remove_round(bot, game_round.chat_id)
def save_private(context: CallbackContext, callback_query: CallbackQuery) -> None: if context.bot_data.get("config"): save_config(context.bot_data["config"], filename) context.chat_data.clear() keyboard = [ [ InlineKeyboardButton( context.bot_data.get("config").get("BACK"), callback_data="back") ], ] markup = InlineKeyboardMarkup(keyboard) callback_query.edit_message_text( reload_config(context), reply_markup=markup, ) logger.info(f"Private: Saved config") logger.debug(context.bot_data.get("config"))
def buttonswitchgamecard(self, query: CallbackQuery, args: List[str]) -> bool: kp = self.forcegetplayer(self.lastchat) cdid = int(args[1]) card = self.getgamecard(cdid) if card is None: return self.errorHandlerQ(query, "没有这张卡") if card.player != kp: return self.errorHandlerQ(query, "这不是你的卡片") if card.group.kp != kp: return self.errorHandlerQ(query, "你不是对应群的kp") game = card.group.game if card.group.game is not None else card.group.pausedgame assert(game is not None) game.kpctrl = card game.write() query.edit_message_text("修改操纵的npc卡成功,现在正在使用:"+card.getname()) return True
def buttonsetsex(self, query: CallbackQuery, args: List[str]) -> bool: cardi = self.findcard(self.lastchat) if cardi is None: return self.errorHandlerQ(query, "找不到卡。") sex = args[1] if sex == "other": self.addOP(self.lastchat, "setsex") query.edit_message_text("请输入具体的性别:") return True cardi.info.sex = sex cardi.write() rttext = "性别设定为" if sex == "male": rttext += "男性。" else: rttext += "女性。" query.edit_message_text(rttext) return True
def inlinebutton_timezone(update: Update, context: CallbackContext, query: CallbackQuery, args: List[str]): continents = sorted( set([x.partition('/')[0] for x in pytz.common_timezones])) location = args[0] if location == 'region_selection': reply = get_timezone_region_markup(continents) query.edit_message_text('Choose your region') query.edit_message_reply_markup(reply) elif location in pytz.all_timezones: redis.set(f'chat:{query.message.chat_id}:settings:timezone', location) tz = timezone(location) local_time = query.message.date.astimezone(tz).strftime('%X') reply = InlineKeyboardMarkup([[ (InlineKeyboardButton('Change timezone', callback_data='timezone:region_selection')) ]]) query.edit_message_text( f'Timezone of this chat was set to {location}. ' f'Looks like it was {local_time} when you sent the last /timezone command. ' 'If this is incorrect, please execute /timezone again or click the button below.' ) query.edit_message_reply_markup(reply) elif location in continents: zones = [x for x in pytz.all_timezones if x.startswith(location)] reply = InlineKeyboardMarkup([[ InlineKeyboardButton(x.partition('/')[2], callback_data=':'.join(['timezone', x])) ] for x in zones] + [[(InlineKeyboardButton( '« Back', callback_data='timezone:region_selection'))]], ) query.edit_message_text('Choose your timezone') query.edit_message_reply_markup(reply)
def buttonchoosedec(self, query: CallbackQuery, args: List[str], card1: Optional[GameCard]) -> bool: if not card1: return self.errorHandlerQ(query, "找不到卡。") if card1.data.datadec is None: return self.errorHandlerQ(query, "不需要设置降值。") dname = args[1] decnames = card1.data.datadec[0].split('_') if dname not in decnames: return self.errorHandlerQ(query, "无法为该属性设置降值。") if len(decnames) == 2: anotherdecname = decnames[0] if dname == decnames[1] else decnames[ 1] rtbuttons = self.makeIntButtons( max( 0, 1 - card1.data.__dict__[anotherdecname] - card1.data.datadec[1]), min(card1.data.__dict__[dname] - 1, -card1.data.datadec[1]), f"{dname}dec", "", 1) elif len(decnames) == 3: decnames.pop(decnames.index(dname)) d1 = decnames[0] d2 = decnames[1] rtbuttons = self.makeIntButtons( max( 0, 2 - card1.data.__dict__[d1] - card1.data.__dict__[d2] - card1.data.datadec[1]), min(card1.data.__dict__[dname] - 1, -card1.data.datadec[1]), f"{dname}dec", "", 1) else: raise ValueError("datadec参数错误") rp_markup = InlineKeyboardMarkup(rtbuttons) query.edit_message_text(f"选择下降值,目前全部数值如下:\n{str(card1.data)}", reply_markup=rp_markup) self.workingMethod[self.lastchat] = BUTTON_SETDEC return True
def round_inline_callback(query: telegram.CallbackQuery, gm: bool): game_round = Round.objects.filter(chat_id=query.message.chat_id).first() if not isinstance(game_round, Round): query.answer(show_alert=True, text='现在游戏没在回合状态之中') return method = str(query.data) if method == 'round:next': game_round.counter += 1 game_round.save() refresh_round_message(game_round, query=query) elif method == 'round:prev': if game_round.counter > 0: game_round.counter -= 1 refresh_round_message(game_round, query=query) game_round.save() else: query.answer(text='已经是第一回合了') elif method == 'round:remove': if not gm: raise NotGm() actors = game_round.get_actors() if len(actors) > 1: current = actors[game_round.counter % len(actors)] current.delete() refresh_round_message(game_round, query=query) else: query.answer(show_alert=True, text='至少要有一位角色在回合中') elif method == 'round:finish': if not gm: raise NotGm() remove_round(game_round.chat_id) query.edit_message_text('回合轮已结束') if isinstance(query.bot, telegram.Bot): try: query.bot.unpin_chat_message(chat_id=game_round.chat_id) except TelegramError: pass return
def buttonjob(self, query: CallbackQuery, args: List[str], card1: GameCard) -> bool: jobname = args[1] if len(args) == 2: # 切换至显示职业详情 jobinfo = self.joblist[jobname] rttext = "如果确认选择该职业,请点击下面按钮进行确认。职业信息如下\n信用点范围:" rttext += str(jobinfo[0]) + "至" + str(jobinfo[1]) + "\n" pointsrule = jobinfo[2] sep = "" for key in pointsrule: if len(key) < 4: rttext += sep + key + "*" + str(pointsrule[key]) elif len(key) == 7: rttext += sep+key[:3]+"或"+key[4:] + \ "之一*"+str(pointsrule[key]) else: rttext += sep+key[:3]+"或"+key[4:7]+"或" + \ key[8:]+"之一*"+str(pointsrule[key]) sep = "+" rttext += "\n推荐技能:\n" sep = "" for i in range(3, len(jobinfo)): rttext += sep + jobinfo[i] sep = "," rtbuttons = [[ InlineKeyboardButton(text="确认", callback_data="job " + jobname + " True"), InlineKeyboardButton(text="返回", callback_data="job " + jobname + " False") ]] rp_markup = InlineKeyboardMarkup(rtbuttons) query.edit_message_text(rttext, reply_markup=rp_markup) self.workingMethod[self.lastchat] = BUTTON_JOB return True if not card1: return self.errorHandlerQ(query, "找不到卡。") confirm = args[2] # 只能是True,或False if confirm == "False": rtbuttons = self.makejobbutton() rp_markup = InlineKeyboardMarkup(rtbuttons) query.edit_message_text("请选择职业查看详情:", reply_markup=rp_markup) self.workingMethod[self.lastchat] = BUTTON_JOB return True # 确认完成 card1.info.job = jobname query.edit_message_text("职业设置为:" + jobname + "\n现在你可以用指令 /addskill 添加技能,首先需要设置信用点。") if not self.generatePoints(card1): self.sendtoAdmin("生成技能出错,位置:buttonjob") return self.errorHandlerQ(query, "生成技能点出错!") for i in range(3, len(self.joblist[jobname])): # Classical jobs card1.suggestskill.set(self.joblist[jobname][i], self.getskilllevelfromdict( card1, self.joblist[jobname][i])) # int card1.group.write() return True
def send_roadblock_resolution(bot: Bot, query: CallbackQuery) -> None: if query.from_user.last_name not in roads_staff: query.answer(BOT_NOT_ROAD_STAFF) return nmaps_message = retrieve_roadblock(roads_id=query.message.message_id) if query.data == 'road_closed': msg = BOT_ROADBLOCK_SET_USR btn_msg = BOT_ROADBLOCK_SET elif query.data == 'road_opened': msg = BOT_ROADBLOCK_DEL_USR btn_msg = BOT_ROADBLOCK_DEL else: msg = BOT_INFOPOINT_SET_USR btn_msg = BOT_INFOPOINT_SET bot.send_message(nmaps_message.chat_id, msg, reply_to_message_id=nmaps_message.chat_message_id) query.edit_message_text(btn_msg.format(query.from_user.name, query.from_user.id), parse_mode='markdown')
def buttonaddintskill(self, query: CallbackQuery, args: List[str], card1: Optional[GameCard]) -> bool: """响应KeyboardButton的addintskill请求。 因为使用的是能翻页的列表,所以有可能位置1的参数是`page`, 且位置2的参数是页码。""" if args[1] == "page": rttext, rtbuttons = self.showskillpages(int(args[2]), card1) query.edit_message_text(rttext) query.edit_message_reply_markup(InlineKeyboardMarkup(rtbuttons)) self.workingMethod[self.lastchat] = BUTTON_ADDINTSKILL return True if len(args) == 3: skvalue = int(args[2]) needpt = self.evalskillcost(args[1], skvalue, card1, False) card1.interest.set(args[1], skvalue, needpt) query.edit_message_text(text="兴趣技能:" + args[1] + "的值现在是" + str(skvalue) + "。剩余技能点:" + str(card1.interest.points)) card1.write() if card1.skill.points or card1.interest.points: self.addskill0(card1) else: self.sendto( card1.player, "接下来,如果没有设置过的话,请使用 /setname 设置姓名、 /setsex 设置性别、 /setbkg 设置背景信息。" ) self.reply( card1.player.id, "背景设定中必要的部分有:故事、信仰、重要之人、意义非凡之地、珍视之物、性格特质。如果需要帮助,请点击`/help setbkg`并发送给我。", parse_mode="MarkdownV2") return True m = self.getskilllevelfromdict(card1, args[1]) mm = self.skillmaxval(args[1], card1, False) rtbuttons = self.makeIntButtons(m, mm, args[0], args[1]) rp_markup = InlineKeyboardMarkup(rtbuttons) query.edit_message_text("添加兴趣技能。剩余技能点:" + str(card1.interest.points) + " 技能名称:" + args[1], reply_markup=rp_markup) self.workingMethod[self.lastchat] = BUTTON_ADDINTSKILL return True
def display_watchlist(query: CallbackQuery): """ :param query: Invoked Query Inline command for display of all watched domains\n Sends csv file if too many characters (4096 chars)\n - entries are ordered from first to expire to last to expire :return: None """ # get entries entries = get_entries_by_chat_id(query.message.chat.id) # sort entries by expiry date (first to expire comes first) entries = utl.sort_by_expiry(entries) # build answer string response = "__Your watched domains__:\n\n" for e in entries: response += f"{utl.mk_link(e.domain, e.port)} \nexpiry: *{e.not_after.date()}* - last checked {e.last_checked.replace(microsecond=0)}\n\n" resp = utl.prep_for_md(response, ignore=['*', '_']) print(resp) # catch too long messages - transition to sending csv file if len(resp) > 4096: file = watchlist_to_csv(query, entries) # send file written in watchlist_to_csv with open(file, 'r') as f: query.edit_message_text( "The list is too long for display - here you go:") query.message.chat.send_document(f) return try: query.edit_message_text(resp, reply_markup=kb.main_menu, parse_mode='MarkdownV2') except BadRequest as e: # TODO: Handle bad request when my-list button is clicked again -> ignore that command in query? print("Bad request") print(e) query.edit_message_text(response, reply_markup=kb.main_menu)
def _(self, query: CallbackQuery, **dialog): query.answer() query.edit_message_text(**dialog)
def request_roadblock_info(_bot: Bot, query: CallbackQuery) -> None: query.edit_message_text(BOT_INVESTIGATING.format(query.from_user.name, query.from_user.id), reply_markup=investigation_keyboard, parse_mode='markdown')
def more_menu(query: CallbackQuery): """Sends more options menu""" query.edit_message_text('Here you go', reply_markup=kb.more_menu)
def main_menu(query: CallbackQuery): """Sends main menu, equivalent to commands.send_menu but inline""" query.edit_message_text(cmd.get_main_menu(query.message.chat_id), reply_markup=kb.main_menu, parse_mode='MarkdownV2')
def queryError(query: CallbackQuery) -> False: try: query.edit_message_text(text="这个按钮请求已经无效了", reply_markup=None) except BadRequest: query.delete_message() return False