Skip to content

Commit

Permalink
Drawing output result (#10)
Browse files Browse the repository at this point in the history
* drawing works fine

* ref cleaning
  • Loading branch information
Alex-Kopylov authored Feb 26, 2024
1 parent 4a217c5 commit b3a1dc7
Show file tree
Hide file tree
Showing 11 changed files with 307 additions and 54 deletions.
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ authors = ["alex"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.12"
python = ">=3.11,<3.13"
aiosqlite = "^0.19.0"
python-dotenv = "^1.0.1"
python-telegram-bot = "^20.7"
pydantic = "^2.5.3"
cairosvg = "^2.7.1"


[build-system]
Expand Down
2 changes: 1 addition & 1 deletion src/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os
from pathlib import Path
from typing import Literal, List, Tuple
from typing import Tuple

from dotenv import load_dotenv

Expand Down
18 changes: 15 additions & 3 deletions src/data_models/Game.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from datetime import datetime
from typing import Literal

from pydantic import BaseModel, field_validator

from src import config


class Game(BaseModel):
poll_id: int
Expand All @@ -18,7 +19,18 @@ def validate_results(cls, v: dict) -> Literal["CH", "DH", "FW", "LW"]:
return "CH"
if "I'm Dead Hitler" in outcomes:
return "DH"
if "I'm Liberal Winner" in outcomes:
if (
"I'm Liberal Winner"
or "I'm Hitler Looser"
or "I'm Fascistic Looser" in outcomes
):
return "LW"
if "I'm Fascistic Winner" in outcomes:
if (
"I'm Fascistic Winner"
or "I'm Hitler Winner"
or "I'm Liberal Looser" in outcomes
):
return "FW"
raise ValueError(
f"Invalid results '{v}' for Game. Results must be one of {config.GAME_POLL_OUTCOMES}"
)
3 changes: 1 addition & 2 deletions src/data_models/Player.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from typing import Optional

from pydantic import BaseModel, field_validator


Expand All @@ -15,4 +14,4 @@ class Player(BaseModel):
@field_validator("is_bot", mode="after")
@classmethod
def validate_bot(cls, v: bool) -> str:
return "TRUE" if v else "FALSE" # sqlite3 does not support boolean type
return "TRUE" if v else "FALSE" # sqlite3 does not support a boolean type
3 changes: 1 addition & 2 deletions src/data_models/Poll.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from datetime import datetime
from typing import Literal

from pydantic import BaseModel
from typing import Literal


class Poll(BaseModel):
Expand Down
13 changes: 11 additions & 2 deletions src/data_models/Record.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from enum import Enum
from typing import Literal, Optional
from src import config

from pydantic import BaseModel, field_validator

from src import config


class Record(BaseModel):
creator_id: int
Expand Down Expand Up @@ -39,3 +40,11 @@ def shorten_role(
raise ValueError(
f"Invalid role '{v}' for Record. Role must be one of {config.GAME_POLL_OUTCOMES}"
)

def get_team(self) -> Optional[Literal["Fascist", "Liberal"]]:
if self.role in {"CH", "DH", "FW", "FL", "HL"}:
return "Fascist"
elif self.role in {"LW", "LL"}:
return "Liberal"
else:
return None
14 changes: 7 additions & 7 deletions src/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@

async def get_db() -> aiosqlite.Connection:
if not getattr(get_db, "db", None):
db = await aiosqlite.connect(config.SQLITE_DB_FILE_PATH,
timeout=60 * 60 * 24 * 1 # 1 day
)
db = await aiosqlite.connect(
config.SQLITE_DB_FILE_PATH, timeout=60 * 60 * 24 * 1 # 1 day
)
get_db.db = db

return get_db.db


async def fetch_all(
sql: LiteralString, params: Iterable[Any] | None = None
sql: LiteralString, params: Iterable[Any] | None = None
) -> list[dict]:
cursor = await _get_cursor(sql, params)
rows = await cursor.fetchall()
Expand All @@ -26,7 +26,7 @@ async def fetch_all(


async def fetch_one(
sql: LiteralString, params: Iterable[Any] | None = None
sql: LiteralString, params: Iterable[Any] | None = None
) -> dict | None:
cursor = await _get_cursor(sql, params)
row = await cursor.fetchone()
Expand All @@ -36,7 +36,7 @@ async def fetch_one(


async def execute(
sql: LiteralString, params: Iterable[Any] | None = None, *, autocommit: bool = True
sql: LiteralString, params: Iterable[Any] | None = None, *, autocommit: bool = True
) -> None:
db = await get_db()
await db.execute(sql, params)
Expand All @@ -53,7 +53,7 @@ async def _async_close_db() -> None:


async def _get_cursor(
sql: LiteralString, params: Iterable[Any] | None
sql: LiteralString, params: Iterable[Any] | None
) -> aiosqlite.Cursor:
db = await get_db()
db.row_factory = aiosqlite.Row
Expand Down
6 changes: 3 additions & 3 deletions src/handlers/game.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram import Update
from telegram.ext import ContextTypes

from src import config
from src.data_models.Playroom import Playroom
from src.services.db_service import save_playroom
from src.utils import message_is_poll, is_message_from_group_chat


async def game(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
Expand All @@ -21,7 +21,7 @@ async def game(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
)

# Save some info about the poll the bot_data for later use in receive_poll_answer
game_metadata = {
game_metadata = { # TODO write it to DB
message.poll.id: {
"questions": questions,
"message_id": message.id, # will be game_id
Expand Down
64 changes: 37 additions & 27 deletions src/handlers/save.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

from src.data_models.Game import Game
from src.data_models.Record import Record
from src.utils import message_is_poll, is_message_from_group_chat
from src import db
from src.services.db_service import save_record, save_game
from src.services.draw_result_image import draw_result_image
from src.utils import message_is_poll, is_message_from_group_chat


async def _pass_checks(
Expand Down Expand Up @@ -67,41 +67,51 @@ async def save(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
msg_with_poll = (
update.effective_message.reply_to_message
) # get a poll from reply message
if await _pass_checks(msg_with_poll, update, context):
if await _pass_checks(msg_with_poll=msg_with_poll, update=update, context=context):
await context.bot.stop_poll(update.effective_chat.id, msg_with_poll.id)

poll_data = context.bot_data[msg_with_poll.poll.id]
await asyncio.gather(
*[
save_record(
Record(
creator_id=poll_data["creator_id"],
player_id=player_id,
playroom_id=poll_data["chat_id"],
game_id=poll_data["message_id"],
role=result,
),
)
for player_id, result in poll_data["results"].items()
]
)
records = [
Record(
creator_id=poll_data["creator_id"],
player_id=player_id,
playroom_id=poll_data["chat_id"],
game_id=poll_data["message_id"],
role=result,
)
for player_id, result in poll_data["results"].items()
]
# await asyncio.gather(*[save_record(record) for record in records])
game = Game(
poll_id=poll_data["message_id"],
chat_id=poll_data["chat_id"],
creator_id=poll_data["creator_id"],
results=poll_data["results"].copy(),
)
await save_game(game)
await update.effective_message.reply_text(
"The Game has been saved!. Results: {}".format(game.results)
)
# Delete the poll
await context.bot.delete_message(
chat_id=game.chat_id,
message_id=game.poll_id
# post-game tasks
await asyncio.gather(
*[
*[save_record(record) for record in records],
save_game(game),
context.bot.delete_message(
chat_id=game.chat_id, message_id=game.poll_id
),
update.effective_message.delete(),
context.bot.send_photo(
photo=(
await draw_result_image(
records=records,
result=game.results,
update=update,
context=context,
)
),
chat_id=game.chat_id,
caption="The Game has been saved!",
disable_notification=True,
),
]
)
# Delete this callback /save message
await update.effective_message.delete()
else:
await update.effective_message.reply_text(
"Something went wrong. Can't process your request."
Expand Down
6 changes: 0 additions & 6 deletions src/services/db_service.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import logging
import sqlite3

from src.data_models.Playroom import Playroom
import logging
import sqlite3

from src.data_models.Game import Game
from src.data_models.Player import Player
from src.data_models.Game import Game
from src.data_models.Player import Player
from src.data_models.Playroom import Playroom
Expand Down
Loading

0 comments on commit b3a1dc7

Please sign in to comment.