use stickers instead of text/link results

This commit is contained in:
Jannes Höke 2016-04-20 00:55:56 +02:00
parent f04d8d32e5
commit 9a763936cd
2 changed files with 197 additions and 65 deletions

133
bot.py
View file

@ -1,9 +1,10 @@
import logging import logging
from datetime import datetime from datetime import datetime
from random import randint from random import randint
from uuid import uuid4
from telegram import InlineQueryResultArticle, ParseMode, Message, Chat, \ from telegram import InlineQueryResultArticle, ParseMode, Message, Chat, \
Emoji, InputTextMessageContent Emoji, InputTextMessageContent, InlineQueryResultCachedSticker as Sticker
from telegram.ext import Updater, InlineQueryHandler, \ from telegram.ext import Updater, InlineQueryHandler, \
ChosenInlineResultHandler, CommandHandler, MessageHandler, filters ChosenInlineResultHandler, CommandHandler, MessageHandler, filters
from telegram.utils.botan import Botan from telegram.utils.botan import Botan
@ -33,10 +34,11 @@ help_text = "Follow these steps:\n\n" \
"3. After at least two players have joined, start the game with" \ "3. After at least two players have joined, start the game with" \
" /start\n" \ " /start\n" \
"4. Type <code>@mau_mau_bot</code> into your chat box and hit " \ "4. Type <code>@mau_mau_bot</code> into your chat box and hit " \
"space, or click the <code>via @mau_mau_bot</code> text above " \ "space, or click the <code>via @mau_mau_bot</code> text next to " \
"messages. You will see the cards that you can play, any extra " \ "messages. You will see your cards (some greyed out), any extra " \
"options like drawing, your other cards (those you can not play " \ "options like drawing, and a <b>?</b> to see the current game " \
"at the moment) and an option to see the current game state. " \ "state. The greyed out cards are those you can not play at the " \
"moment." \
"Tap an option to execute the selected action. \n\n" \ "Tap an option to execute the selected action. \n\n" \
"Players can join the game at any time, though you currently " \ "Players can join the game at any time, though you currently " \
"can not play more than one game at a time. To leave a game, " \ "can not play more than one game at a time. To leave a game, " \
@ -169,8 +171,8 @@ def start_game(bot, update):
chat_id = update.message.chat_id chat_id = update.message.chat_id
game = gm.chatid_game[chat_id] game = gm.chatid_game[chat_id]
if False and game.current_player is None or \ if game.current_player is None or \
False and game.current_player is game.current_player.next: game.current_player is game.current_player.next:
bot.sendMessage(chat_id, text="At least two players must /join " bot.sendMessage(chat_id, text="At least two players must /join "
"the game before you can start it") "the game before you can start it")
elif game.started: elif game.started:
@ -178,9 +180,8 @@ def start_game(bot, update):
else: else:
game.play_card(game.last_card) game.play_card(game.last_card)
game.started = True game.started = True
bot.sendPhoto(chat_id, bot.sendSticker(chat_id,
photo=game.last_card.get_image_link(), sticker=c.STICKERS[str(game.last_card)])
caption="First Card")
bot.sendMessage(chat_id, bot.sendMessage(chat_id,
text="First player: " + text="First player: " +
display_name(game.current_player.user)) display_name(game.current_player.user))
@ -221,14 +222,8 @@ def reply_to_query(bot, update):
if game.choosing_color: if game.choosing_color:
add_choose_color(results) add_choose_color(results)
else: else:
playable = list(sorted(player.playable_cards()))
for card in playable:
add_play_card(card, results)
if not player.drew: if not player.drew:
add_draw(player, results, add_draw(player, results)
could_play_card=bool(len(playable)))
else: else:
add_pass(results) add_pass(results)
@ -236,7 +231,19 @@ def reply_to_query(bot, update):
if game.last_card.special == c.DRAW_FOUR and game.draw_counter: if game.last_card.special == c.DRAW_FOUR and game.draw_counter:
add_call_bluff(results) add_call_bluff(results)
add_other_cards(playable, player, results, game) playable = player.playable_cards()
for card in sorted(player.cards):
add_play_card(game, card, results,
can_play=(card in playable))
if False or game.choosing_color:
add_other_cards(playable, player, results, game)
elif user_id != game.current_player.user.id or not game.started:
for card in sorted(player.cards):
add_play_card(game, card, results, can_play=False)
else:
add_gameinfo(game, results)
for result in results: for result in results:
result.id += ':%d' % player.anti_cheat result.id += ':%d' % player.anti_cheat
@ -261,19 +268,12 @@ def add_other_cards(playable, player, results, game):
if not playable: if not playable:
playable = list() playable = list()
players = list() players = player_list(game)
current_player = game.current_player
itplayer = current_player.next
add_player(current_player, players)
while itplayer is not current_player:
add_player(itplayer, players)
itplayer = itplayer.next
results.append( results.append(
InlineQueryResultArticle( InlineQueryResultArticle(
"hand", "hand",
title="Not playable (tap for game state):", title="Cards (tap for game state):",
description=', '.join([repr(card) for card in description=', '.join([repr(card) for card in
list_subtract(player.cards, playable)]), list_subtract(player.cards, playable)]),
input_message_content=InputTextMessageContent( input_message_content=InputTextMessageContent(
@ -285,6 +285,17 @@ def add_other_cards(playable, player, results, game):
) )
def player_list(game):
players = list()
current_player = game.current_player
itplayer = current_player.next
add_player(current_player, players)
while itplayer is not current_player:
add_player(itplayer, players)
itplayer = itplayer.next
return players
def add_no_game(results): def add_no_game(results):
results.append( results.append(
InlineQueryResultArticle( InlineQueryResultArticle(
@ -309,13 +320,10 @@ def add_not_started(results):
) )
def add_draw(player, results, could_play_card): def add_draw(player, results):
results.append( results.append(
InlineQueryResultArticle( Sticker(
"draw", "draw", sticker_file_id=c.STICKERS['option_draw'],
title=("No suitable cards..." if not could_play_card else
"I don't want to play a card..."),
description="Draw!",
input_message_content= input_message_content=
InputTextMessageContent('Drawing %d card(s)' InputTextMessageContent('Drawing %d card(s)'
% (player.game.draw_counter or 1)) % (player.game.draw_counter or 1))
@ -323,12 +331,26 @@ def add_draw(player, results, could_play_card):
) )
def add_gameinfo(game, results):
players = player_list(game)
results.append(
Sticker(
"gameinfo",
sticker_file_id=c.STICKERS['option_info'],
input_message_content=InputTextMessageContent(
"Current player: " + display_name(game.current_player.user) +
"\n" +
"Last card: " + repr(game.last_card) + "\n" +
"Players: " + " -> ".join(players))
)
)
def add_pass(results): def add_pass(results):
results.append( results.append(
InlineQueryResultArticle( Sticker(
"pass", "pass", sticker_file_id=c.STICKERS['option_pass'],
title="Pass",
description="Don't play a card",
input_message_content=InputTextMessageContent('Pass') input_message_content=InputTextMessageContent('Pass')
) )
) )
@ -336,29 +358,32 @@ def add_pass(results):
def add_call_bluff(results): def add_call_bluff(results):
results.append( results.append(
InlineQueryResultArticle( Sticker(
"call_bluff", "call_bluff",
title="Call their bluff!", sticker_file_id=c.STICKERS['option_bluff'],
description="Risk it!",
input_message_content= input_message_content=
InputTextMessageContent("I'm calling your bluff!") InputTextMessageContent("I'm calling your bluff!")
) )
) )
def add_play_card(card, results): def add_play_card(game, card, results, can_play):
results.append( players = player_list(game)
InlineQueryResultArticle(str(card),
title="Play card", if can_play:
thumb_url=card.get_thumb_link(), results.append(
description=repr(card), Sticker(str(card), sticker_file_id=c.STICKERS[str(card)])
input_message_content= )
InputTextMessageContent( else:
('<a href="%s">\xad</a>' results.append(
'Played card ' + repr(card)) Sticker(str(uuid4()), sticker_file_id=c.STICKERS_GREY[str(card)],
% card.get_image_link(), input_message_content=InputTextMessageContent(
parse_mode=ParseMode.HTML)) "Current player: " + display_name(
) game.current_player.user) +
"\n" +
"Last card: " + repr(game.last_card) + "\n" +
"Players: " + " -> ".join(players)))
)
def add_player(itplayer, players): def add_player(itplayer, players):
@ -385,6 +410,8 @@ def process_result(bot, update):
if result_id in ('hand', 'gameinfo', 'nogame'): if result_id in ('hand', 'gameinfo', 'nogame'):
return return
elif len(result_id) == 36: # UUID result
return
elif int(anti_cheat) != last_anti_cheat: elif int(anti_cheat) != last_anti_cheat:
bot.sendMessage(chat_id, bot.sendMessage(chat_id,
text="Cheat attempt by %s" % display_name(player.user)) text="Cheat attempt by %s" % display_name(player.user))

129
card.py
View file

@ -39,10 +39,123 @@ DRAW_FOUR = 'draw_four'
SPECIALS = (CHOOSE, DRAW_FOUR) SPECIALS = (CHOOSE, DRAW_FOUR)
IMAGE_PATTERN = 'https://raw.githubusercontent.com/jh0ker/mau_mau_bot/' \ STICKERS = {
'master/images/jpg/%s.jpg' 'b_0': 'BQADBAAD2QEAAl9XmQAB--inQsYcLTsC',
THUMB_PATTERN = 'https://raw.githubusercontent.com/jh0ker/mau_mau_bot/' \ 'b_1': 'BQADBAAD2wEAAl9XmQABBzh4U-rFicEC',
'master/images/thumb/%s.jpg' 'b_2': 'BQADBAAD3QEAAl9XmQABo3l6TT0MzKwC',
'b_3': 'BQADBAAD3wEAAl9XmQAB2y-3TSapRtIC',
'b_4': 'BQADBAAD4QEAAl9XmQABT6nhOuolqKYC',
'b_5': 'BQADBAAD4wEAAl9XmQABwRfmekGnpn0C',
'b_6': 'BQADBAAD5QEAAl9XmQABQITgUsEsqxsC',
'b_7': 'BQADBAAD5wEAAl9XmQABVhPF6EcfWjEC',
'b_8': 'BQADBAAD6QEAAl9XmQABP6baig0pIvYC',
'b_9': 'BQADBAAD6wEAAl9XmQAB0CQdsQs_pXIC',
'b_draw': 'BQADBAAD7QEAAl9XmQAB00Wii7R3gDUC',
'b_skip': 'BQADBAAD8QEAAl9XmQAB_RJHYKqlc-wC',
'b_reverse': 'BQADBAAD7wEAAl9XmQABo7D0B9NUPmYC',
'g_0': 'BQADBAAD9wEAAl9XmQABb8CaxxsQ-Y8C',
'g_1': 'BQADBAAD-QEAAl9XmQAB9B6ti_j6UB0C',
'g_2': 'BQADBAAD-wEAAl9XmQABYpLjOzbRz8EC',
'g_3': 'BQADBAAD_QEAAl9XmQABKvc2ZCiY-D8C',
'g_4': 'BQADBAAD_wEAAl9XmQABJB52wzPdHssC',
'g_5': 'BQADBAADAQIAAl9XmQABp_Ep1I4GA2cC',
'g_6': 'BQADBAADAwIAAl9XmQABaaMxxa4MihwC',
'g_7': 'BQADBAADBQIAAl9XmQABv5Q264Crz8gC',
'g_8': 'BQADBAADBwIAAl9XmQABjMH-X9UHh8sC',
'g_9': 'BQADBAADCQIAAl9XmQAB26fZ2fW7vM0C',
'g_draw': 'BQADBAADCwIAAl9XmQAB64jIZrgXrQUC',
'g_skip': 'BQADBAADDwIAAl9XmQAB17yhhnh46VQC',
'g_reverse': 'BQADBAADDQIAAl9XmQAB_xcaab0DkegC',
'r_0': 'BQADBAADEQIAAl9XmQABiUfr1hz-zT8C',
'r_1': 'BQADBAADEwIAAl9XmQAB5bWfwJGs6Q0C',
'r_2': 'BQADBAADFQIAAl9XmQABHR4mg9Ifjw0C',
'r_3': 'BQADBAADFwIAAl9XmQABYBx5O_PG2QIC',
'r_4': 'BQADBAADGQIAAl9XmQABTQpGrlvet3cC',
'r_5': 'BQADBAADGwIAAl9XmQABbdLt4gdntBQC',
'r_6': 'BQADBAADHQIAAl9XmQABqEI274p3lSoC',
'r_7': 'BQADBAADHwIAAl9XmQABCw8u67Q4EK4C',
'r_8': 'BQADBAADIQIAAl9XmQAB8iDJmLxp8ogC',
'r_9': 'BQADBAADIwIAAl9XmQAB_HCAww1kNGYC',
'r_draw': 'BQADBAADJQIAAl9XmQABuz0OZ4l3k6MC',
'r_skip': 'BQADBAADKQIAAl9XmQAC2AL5Ok_ULwI',
'r_reverse': 'BQADBAADJwIAAl9XmQABu2tIeQTpDvUC',
'y_0': 'BQADBAADKwIAAl9XmQAB_nWoNKe8DOQC',
'y_1': 'BQADBAADLQIAAl9XmQABVprAGUDKgOQC',
'y_2': 'BQADBAADLwIAAl9XmQABqyT4_YTm54EC',
'y_3': 'BQADBAADMQIAAl9XmQABGC-Xxg_N6fIC',
'y_4': 'BQADBAADMwIAAl9XmQABbc-ZGL8kApAC',
'y_5': 'BQADBAADNQIAAl9XmQAB67QJZIF6XAcC',
'y_6': 'BQADBAADNwIAAl9XmQABJg_7XXoITsoC',
'y_7': 'BQADBAADOQIAAl9XmQABVrd7OcS2k34C',
'y_8': 'BQADBAADOwIAAl9XmQABRpJSahBWk3EC',
'y_9': 'BQADBAADPQIAAl9XmQAB9MwJWKLJogYC',
'y_draw': 'BQADBAADPwIAAl9XmQABaPYK8oYg84cC',
'y_skip': 'BQADBAADQwIAAl9XmQABO_AZKtxY6IMC',
'y_reverse': 'BQADBAADQQIAAl9XmQABZdQFahGG6UQC',
'draw_four': 'BQADBAAD9QEAAl9XmQABVlkSNfhn76cC',
'colorchooser': 'BQADBAAD8wEAAl9XmQABl9rUOPqx4E4C',
'option_draw': 'BQADBAADyAIAAl9XmQABpYfYFs0pgCkC',
'option_pass': 'BQADBAADxgIAAl9XmQABz8c6BNl49S4C',
'option_bluff': 'BQADBAADygIAAl9XmQABJoLfB9ntI2UC',
'option_info': 'BQADBAADxAIAAl9XmQABC5v3Z77VLfEC'
}
STICKERS_GREY = {
'b_0': 'BQADBAADRQIAAl9XmQAB1IfkQ5xAiK4C',
'b_1': 'BQADBAADRwIAAl9XmQABbWvhTeKBii4C',
'b_2': 'BQADBAADSQIAAl9XmQABS1djHgyQokMC',
'b_3': 'BQADBAADSwIAAl9XmQABwQ6VTbgY-MIC',
'b_4': 'BQADBAADTQIAAl9XmQABAlKUYha8YccC',
'b_5': 'BQADBAADTwIAAl9XmQABMvx8xVDnhUEC',
'b_6': 'BQADBAADUQIAAl9XmQABDEbhP1Zd31kC',
'b_7': 'BQADBAADUwIAAl9XmQABXb5XQBBaAnIC',
'b_8': 'BQADBAADVQIAAl9XmQABgL5HRDLvrjgC',
'b_9': 'BQADBAADVwIAAl9XmQABtO3XDQWZLtYC',
'b_draw': 'BQADBAADWQIAAl9XmQAB2kk__6_2IhMC',
'b_skip': 'BQADBAADXQIAAl9XmQABEGJI6CaH3vcC',
'b_reverse': 'BQADBAADWwIAAl9XmQAB_kZA6UdHXU8C',
'g_0': 'BQADBAADYwIAAl9XmQABGD5a9oG7Yg4C',
'g_1': 'BQADBAADZQIAAl9XmQABqwABZHAXZIg0Ag',
'g_2': 'BQADBAADZwIAAl9XmQABTI3mrEhojRkC',
'g_3': 'BQADBAADaQIAAl9XmQABVi3rUyzWS3YC',
'g_4': 'BQADBAADawIAAl9XmQABZIf5ThaXnpUC',
'g_5': 'BQADBAADbQIAAl9XmQABNndVJSQCenIC',
'g_6': 'BQADBAADbwIAAl9XmQABpoy1c4ZkrvwC',
'g_7': 'BQADBAADcQIAAl9XmQABDeaT5fzxwREC',
'g_8': 'BQADBAADcwIAAl9XmQABLIQ06ZM5NnAC',
'g_9': 'BQADBAADdQIAAl9XmQABel-mC7eXGsMC',
'g_draw': 'BQADBAADdwIAAl9XmQABOHEpxSztCf8C',
'g_skip': 'BQADBAADewIAAl9XmQABDaQdMxjjPsoC',
'g_reverse': 'BQADBAADeQIAAl9XmQABek1lGz7SJNAC',
'r_0': 'BQADBAADfQIAAl9XmQABWrxoiXcsg0EC',
'r_1': 'BQADBAADfwIAAl9XmQABlav-bkgSgRcC',
'r_2': 'BQADBAADgQIAAl9XmQABDjZkqfJ4AdAC',
'r_3': 'BQADBAADgwIAAl9XmQABT7lH7VVcy3MC',
'r_4': 'BQADBAADhQIAAl9XmQAB1arPC5x0LrwC',
'r_5': 'BQADBAADhwIAAl9XmQABWvs7xkCDldkC',
'r_6': 'BQADBAADiQIAAl9XmQABjwABH5ZonWn8Ag',
'r_7': 'BQADBAADiwIAAl9XmQABjekJfm4fBDIC',
'r_8': 'BQADBAADjQIAAl9XmQABqFjchpsJeEkC',
'r_9': 'BQADBAADjwIAAl9XmQAB-sKdcgABdNKDAg',
'r_draw': 'BQADBAADkQIAAl9XmQABtw9RPVDHZOQC',
'r_skip': 'BQADBAADlQIAAl9XmQABtG2GixCxtX4C',
'r_reverse': 'BQADBAADkwIAAl9XmQABz2qyEbabnVsC',
'y_0': 'BQADBAADlwIAAl9XmQABAb3ZwTGS1lMC',
'y_1': 'BQADBAADmQIAAl9XmQAB9v5qJk9R0x8C',
'y_2': 'BQADBAADmwIAAl9XmQABCsgpRHC2g-cC',
'y_3': 'BQADBAADnQIAAl9XmQAB3kLLXCv-qY0C',
'y_4': 'BQADBAADnwIAAl9XmQAB7R_y-NexNLIC',
'y_5': 'BQADBAADoQIAAl9XmQABl-7mwsjD-cMC',
'y_6': 'BQADBAADowIAAl9XmQABwbVsyv2MfPkC',
'y_7': 'BQADBAADpQIAAl9XmQABoBqC0JsemVwC',
'y_8': 'BQADBAADpwIAAl9XmQABpkwAAeh9ldlHAg',
'y_9': 'BQADBAADqQIAAl9XmQABpSBEUfd4IM8C',
'y_draw': 'BQADBAADqwIAAl9XmQABMt-2zW0VYb4C',
'y_skip': 'BQADBAADrwIAAl9XmQABIDf-_TuuxtEC',
'y_reverse': 'BQADBAADrQIAAl9XmQABm9M0Zh-_UwkC',
'draw_four': 'BQADBAADYQIAAl9XmQAB_HWlvZIscDEC',
'colorchooser': 'BQADBAADXwIAAl9XmQABY_ksDdMex-wC'
}
class Card(object): class Card(object):
@ -77,14 +190,6 @@ class Card(object):
""" Needed for sorting the cards """ """ Needed for sorting the cards """
return str(self) < str(other) return str(self) < str(other)
def get_image_link(self):
""" Returns a link to the image of this card """
return IMAGE_PATTERN % str(self)
def get_thumb_link(self):
""" Returns a link to the thumbnail-image of this card """
return THUMB_PATTERN % str(self)
def from_str(string): def from_str(string):
""" Decode a Card object from a string """ """ Decode a Card object from a string """