-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
163 additions
and
106 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import requests | ||
from bot.config import get_config | ||
from bot.handlers.other.event_handler import EventHandler, build_board_keyboard | ||
from bot.handlers.parse.photos import _get_base64_photo | ||
from bot.models import BotState | ||
from codenames.game.board import Board | ||
from codenames.game.card import Card | ||
|
||
# Board -> Fixing | ||
|
||
|
||
class ParseBoardHandler(EventHandler): | ||
def handle(self): | ||
photo_base64 = _get_base64_photo(photos=self.update.message.photo) | ||
self.send_text("Working on it. This might take a minute ⏳️") | ||
parsing_state = self.session.parsing_state | ||
parsed_words = _parse_board_words(photo_base64=photo_base64, language=parsing_state.language) | ||
words = [word if word else str(i) for i, word in enumerate(parsed_words)] | ||
cards = [Card(word=word, color=color) for word, color in zip(words, parsing_state.card_colors)] | ||
parsed_board = Board(language=parsing_state.language, cards=cards) | ||
keyboard = build_board_keyboard(table=parsed_board.as_table, is_game_over=True) | ||
message = "🎉 Done! Here's the board.\nClick on any card to fix it. When you are done, send me /done." | ||
text = self.send_markdown(text=message, reply_markup=keyboard) | ||
self.update_session(last_keyboard_message_id=text.message_id, parsing_state=None) | ||
return BotState.PARSE_FIXES | ||
|
||
|
||
def _parse_board_words(photo_base64: str, language: str) -> list[str]: | ||
env_config = get_config() | ||
url = f"{env_config.base_parser_url}/parse-board" | ||
payload = {"board_image_b64": photo_base64, "language": language} | ||
response = requests.get(url=url, json=payload, timeout=80) | ||
response.raise_for_status() | ||
response_json = response.json() | ||
words = response_json.get("words") | ||
return words |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from bot.handlers.other.event_handler import EventHandler | ||
from bot.models import BotState | ||
|
||
# Fixing | ||
|
||
|
||
class ParseFixesHandler(EventHandler): | ||
def handle(self): | ||
text = self.update.message.text.lower().strip() | ||
if text == "/done": | ||
return | ||
self.send_text("🧩 Please send me a picture of the fixed board:") | ||
return BotState.PARSE_BOARD |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from bot.handlers.other.event_handler import EventHandler | ||
from bot.models import BotState, ParsingState | ||
from the_spymaster_util.logger import get_logger | ||
|
||
log = get_logger(__name__) | ||
|
||
# Entrypoint -> Language | ||
|
||
LANGUAGES_CODES = { | ||
"hebrew": "heb", | ||
"hnglish": "eng", | ||
"hussian": "rus", | ||
} | ||
|
||
|
||
class ParseHandler(EventHandler): | ||
def handle(self): | ||
keyboard = _build_language_options_keyboard() | ||
parsing_state = ParsingState() | ||
self.update_session(parsing_state=parsing_state) | ||
# Language selection | ||
self.send_markdown("🔤 Pick cards language:", reply_markup=keyboard) | ||
return BotState.PARSE_LANGUAGE | ||
|
||
|
||
def _build_language_options_keyboard() -> list[str]: | ||
keyboard = [language.title() for language in LANGUAGES_CODES.keys()] | ||
return keyboard |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
from bot.handlers.other.event_handler import EventHandler | ||
from bot.handlers.parse.parse_handler import LANGUAGES_CODES, log | ||
from bot.models import BotState | ||
|
||
# Language -> Map | ||
|
||
|
||
class ParseLanguageHandler(EventHandler): | ||
def handle(self): | ||
text = self.update.message.text.lower() | ||
language_code = _get_language_code(text) | ||
log.info(f"Setting language: '{language_code}'") | ||
self.update_parsing_state(language=language_code) | ||
# Map parsing | ||
self.send_text("🗺️ Please send me a picture of the map:") | ||
return BotState.PARSE_MAP | ||
|
||
|
||
def _get_language_code(text: str) -> str: | ||
text = text.lower().strip() | ||
if text in LANGUAGES_CODES: | ||
return LANGUAGES_CODES[text] | ||
log.info(f"Unknown language: '{text}'") | ||
language_code = text[:3] | ||
return language_code |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import requests | ||
from bot.config import get_config | ||
from bot.handlers.other.event_handler import EventHandler | ||
from bot.handlers.parse.photos import _get_base64_photo | ||
from bot.models import BotState, ParsingState | ||
from codenames.game.color import CardColor | ||
|
||
|
||
# Map -> Board | ||
class ParseMapHandler(EventHandler): | ||
def handle(self): | ||
photo_base64 = _get_base64_photo(photos=self.update.message.photo) | ||
card_colors = _parse_map_colors(photo_base64) | ||
self._send_as_emoji_table(card_colors) | ||
parsing_state = ParsingState(language="heb", card_colors=card_colors) | ||
self.update_session(parsing_state=parsing_state) | ||
# Board parsing | ||
self.send_text("🧩 Please send me a picture of the board:") | ||
return BotState.PARSE_BOARD | ||
|
||
def _send_as_emoji_table(self, card_colors: list[CardColor]): | ||
result = "I got: \n\n" | ||
for i in range(0, len(card_colors), 5): | ||
row = card_colors[i : i + 5] | ||
row_emojis = " ".join(card.emoji for card in row) | ||
result += f"{row_emojis}\n" | ||
result += "\nYou will have a chance to fix any mistakes later." | ||
self.send_text(result) | ||
|
||
|
||
def _parse_map_colors(photo_base64: str) -> list[CardColor]: | ||
env_config = get_config() | ||
url = f"{env_config.base_parser_url}/parse-color-map" | ||
payload = {"map_image_b64": photo_base64} | ||
response = requests.get(url=url, json=payload, timeout=15) | ||
response.raise_for_status() | ||
response_json = response.json() | ||
map_colors = response_json.get("map_colors") | ||
card_colors = [CardColor(color) for color in map_colors] | ||
return card_colors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import base64 | ||
|
||
from bot.handlers.parse.parse_handler import log | ||
from bot.models import BadMessageError | ||
from telegram import PhotoSize | ||
|
||
|
||
def _get_base64_photo(photos: list[PhotoSize]) -> str: | ||
if not photos: | ||
raise BadMessageError("No photo found in message") | ||
log.info(f"Got {len(photos)} photos, downloading the largest one") | ||
photo_meta = _pick_largest_photo(photos) | ||
photo_ptr = photo_meta.get_file() | ||
photo_bytes = photo_ptr.download_as_bytearray() | ||
photo_base64 = base64.b64encode(photo_bytes).decode("utf-8") | ||
log.info("Downloaded and encoded photo") | ||
return photo_base64 | ||
|
||
|
||
def _pick_largest_photo(photos: list[PhotoSize]) -> PhotoSize: | ||
return max(photos, key=lambda photo: photo.file_size) |
This file was deleted.
Oops, something went wrong.