Example #1
0
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)
Example #2
0
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))
Example #3
0
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)
Example #4
0
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)
Example #5
0
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