def draw(update: Update, context: CallbackContext): query = update.callback_query user_id = update.effective_user.id chat_data = context.chat_data game_id = query.data[4:14] # somehow this button is there, but no game is running if "game_id" not in chat_data: no_game(update, context, "join_no_game_running") return # somehow this button is there, but another game is running elif chat_data["game_id"] != game_id: no_game(update, context, "wrong_game") return starter_id = chat_data["players"][0]["user_id"] lang = chat_data["lang"] if not user_id == starter_id: query.answer(get_string(lang, "not_starter"), show_alert=True) return unmasked_id = int(query.data[14:]) if unmasked_id == user_id: query.answer(get_string(lang, "vote_yourself"), show_alert=True) return query.edit_message_reply_markup(None) chat_id = update.effective_message.chat.id who_wins(context, chat_id, unmasked_id)
def player_join(update: Update, context: CallbackContext): query = update.callback_query chat_data = context.chat_data first_name = name_generator(update.effective_user.first_name) user_id = update.effective_user.id chat_id = update.effective_chat.id # somehow, this callback button is there, but we aren't in join mode, so we handle this now :D if "message" not in chat_data: group_helpers.no_game(update, context, "join_no_game_running") return starter = mention_html(chat_data["starter"]["user_id"], chat_data["starter"]["first_name"]) remove = False for player in chat_data["players"]: player_id = player["user_id"] # player leaves if user_id == player_id: # we do this so player can change their name between joining and leaving chat_data["players"].remove({ "user_id": user_id, "first_name": player["first_name"] }) # we need them in here so we can mention them later. Looks stupid, I know chat_data["left_players"][user_id] = first_name query.answer(get_string(chat_data["lang"], "player_leaves_query")) remove = True break if not remove: # if they left and rejoined before the timer run through, they are still in this dict. If not, nothing happens chat_data["left_players"].pop(user_id, None) chat_data["players"].append({ "user_id": user_id, "first_name": first_name }) query.answer(get_string(chat_data["lang"], "player_joins_query")) players = group_helpers.players_mentions(chat_data["players"]) job = context.job_queue.get_jobs_by_name(chat_id)[0] job.context["players"] = chat_data["players"] job.context["left_players"] = chat_data["left_players"] text = get_string(chat_data["lang"], "start_game").format(starter, players, *chat_data["settings"]) if len(chat_data["players"]) == MAX_PLAYERS: query.edit_message_text(text, parse_mode=ParseMode.HTML) payload = job.context job.schedule_removal() new_context = context setattr(new_context, "job", Job(timer, interval=42, name=chat_id, context=payload)) timer(context) return button = [[ InlineKeyboardButton(get_string(chat_data["lang"], "start_button"), callback_data="join") ]] query.edit_message_text(text, parse_mode=ParseMode.HTML, reply_markup=InlineKeyboardMarkup(button))
def secret_word(update: Update, context: CallbackContext): query = update.callback_query user_id = update.effective_user.id chat_data = context.chat_data game_id = query.data[4:] # somehow this button is there, but no game is running if "game_id" not in chat_data: no_game(update, context, "join_no_game_running") return # somehow this button is there, but another game is running elif chat_data["game_id"] != game_id: no_game(update, context, "wrong_game") return lang = chat_data["lang"] if user_id not in [user["user_id"] for user in chat_data["players"]]: query.answer(get_string(lang, "user_not_in_game"), show_alert=True) return if chat_data["chameleon"]["user_id"] == user_id: query.answer(get_string(lang, "player_is_chameleon"), show_alert=True) else: query.answer(get_string(lang, "secret_word").format(chat_data["secret"]), show_alert=True)
def vote(update: Update, context: CallbackContext): query = update.callback_query chat_data = context.chat_data user_id = update.effective_user.id game_id = query.data[4:14] # somehow this button is there, but no game is running if "game_id" not in chat_data: no_game(update, context, "join_no_game_running") return # somehow this button is there, but another game is running elif chat_data["game_id"] != game_id: no_game(update, context, "wrong_game") return vote_id = int(query.data[14:]) lang = chat_data["lang"] if user_id not in [user["user_id"] for user in chat_data["players"]]: query.answer(get_string(lang, "user_not_in_game"), show_alert=True) return players = chat_data["players"] if user_id in chat_data["voted"]: query.answer(get_string(lang, "already_voted"), show_alert=True) return elif user_id == vote_id: query.answer(get_string(lang, "vote_yourself"), show_alert=True) return else: pass for player in players: if vote_id == player["user_id"]: if "votes" in player: player["votes"] += 1 else: player["votes"] = 1 break chat_data["voted"].append(user_id) query.answer(get_string(lang, "voted")) voters = players.copy() for voter_id in chat_data["voted"]: for index, voter in enumerate(voters): if voter["user_id"] == voter_id: del voters[index] if len(players) is not len(chat_data["voted"]): buttons = vote_buttons(players, chat_data["game_id"]) words = wordlist(players) text = get_string(lang, "final_word_list").format(words) + "\n" + get_string(lang, "vote_list").\ format(player_mention_string(voters)) query.edit_message_text(text, reply_markup=InlineKeyboardMarkup(buttons), parse_mode=ParseMode.HTML) else: words = wordlist(players) text = get_string(lang, "final_word_list").format(words) + "\n" + get_string(lang, "vote_list").\ format(player_mention_string(voters)) query.edit_message_text(text, parse_mode=ParseMode.HTML) votes = [] for player in players: if "votes" in player: votes.append((player["votes"], player["user_id"])) else: votes.append((0, player["user_id"])) # this works cause https://docs.python.org/3/howto/sorting.html#key-functions. Do I have any idea why? no votes = sorted(votes, key=lambda votes: votes[0], reverse=True) # this means, we have a draw, so the first person who had to say a word (cause disadvantage) can decide if votes[0][0] == votes[1][0]: same_votes = [] for vote_number in votes: if vote_number[0] is not votes[0][0]: break else: voter_id = vote_number[1] for player in players: if player["user_id"] == voter_id: same_votes.append({ "user_id": voter_id, "first_name": player["first_name"] }) break text = get_string(lang, "draw").format( mention_html(players[0]["user_id"], players[0]["first_name"])) buttons = draw_buttons(same_votes, chat_data["game_id"]) query.message.reply_html( text, reply_markup=InlineKeyboardMarkup(buttons), quote=False) else: chat_id = update.effective_message.chat.id unmasked_id = votes[0][1] who_wins(context, chat_id, unmasked_id)
def player_join(update: Update, context: CallbackContext): query = update.callback_query chat_data = context.chat_data first_name = name_generator(update.effective_user.first_name) user_id = update.effective_user.id chat_id = update.effective_chat.id # check if the chat data is from a different state if "message" not in chat_data: # this means there is no game starting/running if "game_id" not in chat_data: group_helpers.no_game(update, context, "join_no_game_running") return # this means there is a game starting, but the button wasn't removed yet if chat_data["game_id"] == query.data.split("_")[1]: query.answer(get_string(chat_data["lang"], "join_while_starting")) return # if we are here, there is a newer game running and someone hit the button of an old one group_helpers.no_game(update, context, "join_old_button") return starter = mention_html(chat_data["starter"]["user_id"], chat_data["starter"]["first_name"]) remove = False for player in chat_data["players"]: player_id = player["user_id"] # player leaves if user_id == player_id: # we do this so player can change their name between joining and leaving chat_data["players"].remove({ "user_id": user_id, "first_name": player["first_name"] }) # we need them in here so we can mention them later. Looks stupid, I know chat_data["left_players"][user_id] = first_name if "flood" in chat_data: query.answer(get_string(chat_data["lang"], "player_leaves_query_flood"), show_alert=True) else: query.answer( get_string(chat_data["lang"], "player_leaves_query")) remove = True break if not remove: # if they left and rejoined before the timer run through, they are still in this dict. If not, nothing happens chat_data["left_players"].pop(user_id, None) chat_data["players"].append({ "user_id": user_id, "first_name": first_name }) if "flood" in chat_data: query.answer(get_string(chat_data["lang"], "player_joins_query_flood"), show_alert=True) else: query.answer(get_string(chat_data["lang"], "player_joins_query")) players = group_helpers.players_mentions(chat_data["players"]) try: job = context.job_queue.get_jobs_by_name(chat_id)[0] except IndexError: # this means the game already started, we are going to return, but quickly notify teh player they didnt made it mention = mention_html(user_id, first_name) context.bot.send_message( chat_id, get_string(chat_data["lang"], "player_joins_query").format(mention), parse_mode="HTML") return job.context["players"] = chat_data["players"] job.context["left_players"] = chat_data["left_players"] text = get_string(chat_data["lang"], "start_game").format(starter, players, *chat_data["settings"]) if len(chat_data["players"]) == MAX_PLAYERS: query.edit_message_text(text, parse_mode=ParseMode.HTML) payload = job.context job.schedule_removal() new_context = context setattr(new_context, "job", Job(timer, interval=42, name=chat_id, context=payload)) timer(context) return if "flood" in chat_data: return button = [[ InlineKeyboardButton(get_string(chat_data["lang"], "start_button"), callback_data="join_" + chat_data["game_id"]) ]] try: query.edit_message_text(text, parse_mode=ParseMode.HTML, reply_markup=InlineKeyboardMarkup(button)) except RetryAfter as e: context.job_queue.run_once(flood_error, e.retry_after + 2, context=chat_data, name="flood for " + str(chat_id)) chat_data["flood"] = True