Compare commits

...

5 Commits

Author SHA1 Message Date
cafa0e3afd Fix 2025-04-21 16:00:43 +02:00
5a769c96a0 Fix 2025-04-21 15:57:27 +02:00
f1d023c9a1 Fix 2025-04-21 15:42:36 +02:00
cfce98a42f Update 2025-04-21 15:40:56 +02:00
abe0cbb173 New structure 2025-04-21 13:51:01 +02:00
53 changed files with 69 additions and 111 deletions

View File

@@ -49,26 +49,26 @@ jobs:
with: with:
url: ${{ secrets.WEBHOOK_URL }} url: ${{ secrets.WEBHOOK_URL }}
- # -
name: Invoke deployment hook (worker) # name: Invoke deployment hook (worker)
uses: joelwmale/webhook-action@master # uses: joelwmale/webhook-action@master
with: # with:
url: ${{ secrets.WEBHOOK_URL_2 }} # url: ${{ secrets.WEBHOOK_URL_2 }}
- # -
name: Invoke deployment hook (scheduler) # name: Invoke deployment hook (scheduler)
uses: joelwmale/webhook-action@master # uses: joelwmale/webhook-action@master
with: # with:
url: ${{ secrets.WEBHOOK_URL_3 }} # url: ${{ secrets.WEBHOOK_URL_3 }}
- # -
name: Invoke deployment hook (stream_notifications) # name: Invoke deployment hook (stream_notifications)
uses: joelwmale/webhook-action@master # uses: joelwmale/webhook-action@master
with: # with:
url: ${{ secrets.WEBHOOK_URL_4 }} # url: ${{ secrets.WEBHOOK_URL_4 }}
- # -
name: Invoke deployment hook (web_app) # name: Invoke deployment hook (web_app)
uses: joelwmale/webhook-action@master # uses: joelwmale/webhook-action@master
with: # with:
url: ${{ secrets.WEBHOOK_URL_5 }} # url: ${{ secrets.WEBHOOK_URL_5 }}

2
.gitignore vendored
View File

@@ -3,3 +3,5 @@
.DS_Store .DS_Store
.vscode .vscode
*.cpython-*.pyc

View File

@@ -1,19 +1,22 @@
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS builder
WORKDIR /opt/
COPY ./pyproject.toml ./uv.lock ./
RUN --mount=type=ssh uv venv \
&& uv sync --frozen
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim
ENV PATH="/opt/venv/bin:$PATH"
COPY ./src /app
COPY --from=builder /opt/.venv /opt/venv
COPY ./scripts/*.sh / COPY ./scripts/*.sh /
RUN chmod +x /*.sh RUN chmod +x /*.sh
WORKDIR /app WORKDIR /app
COPY ./pyproject.toml ./ ENTRYPOINT ["uv", "run", "-m"]
COPY ./uv.lock ./
RUN uv venv && uv sync --frozen
COPY ./src ./src
ENV PATH="/app/.venv/bin:$PATH"
EXPOSE 80
CMD ["uv", "run", "src/main.py"]

View File

@@ -1,3 +1,5 @@
#! /usr/bin/env sh #! /usr/bin/env sh
uv run ./src/main.py $1 cd src
uv run $1

View File

@@ -1,3 +0,0 @@
#! /usr/bin/env sh
uv run --directory src taskiq scheduler core.broker:scheduler modules.tasks

View File

@@ -1,3 +0,0 @@
#! /usr/bin/env sh
uv run --directory src uvicorn modules.web_app.app:app --host 0.0.0.0 --port 80

View File

@@ -1,3 +0,0 @@
#! /usr/bin/env sh
uv run --directory src taskiq worker core.broker:broker modules.tasks

View File

@@ -1,31 +1,38 @@
from pydantic import BaseModel from pydantic import BaseModel
class TwitchConfig(BaseModel): class TwitchConfig(BaseModel):
id: int id: int
name: str name: str
class NotificationsConfig(BaseModel): class NotificationsConfig(BaseModel):
start_stream: str start_stream: str
change_category: str | None = None change_category: str | None = None
redemption_reward: str | None = None redemption_reward: str | None = None
class GamesListConfig(BaseModel): class GamesListConfig(BaseModel):
channel_id: int channel_id: int
message_id: int message_id: int
class DiscordConfig(BaseModel): class DiscordConfig(BaseModel):
guild_id: int guild_id: int
notifications_channel_id: int notifications_channel_id: int
games_list: GamesListConfig | None = None games_list: GamesListConfig | None = None
roles: dict[str, int] | None = None roles: dict[str, int] | None = None
class TelegramConfig(BaseModel): class TelegramConfig(BaseModel):
notifications_channel_id: int notifications_channel_id: int
class IntegrationsConfig(BaseModel): class IntegrationsConfig(BaseModel):
discord: DiscordConfig | None = None discord: DiscordConfig | None = None
telegram: TelegramConfig | None = None telegram: TelegramConfig | None = None
class StreamerConfig(BaseModel): class StreamerConfig(BaseModel):
twitch: TwitchConfig twitch: TwitchConfig
notifications: NotificationsConfig notifications: NotificationsConfig

View File

@@ -1,4 +1,4 @@
from domain.streamers import StreamerConfig from applications.common.domain.streamers import StreamerConfig
from .base import BaseRepository from .base import BaseRepository

View File

@@ -1,4 +1,4 @@
from domain.users import CreateUser, User from applications.common.domain.users import CreateUser, User
from .base import BaseRepository from .base import BaseRepository
@@ -18,10 +18,10 @@ class UserRepository(BaseRepository):
) )
@classmethod @classmethod
async def get_or_create_user(cls, newUser: CreateUser) -> User: async def get_or_create_user(cls, new_user: CreateUser) -> User:
filter_data = {} filter_data = {}
for provider, data in newUser.oauths.items(): for provider, data in new_user.oauths.items():
filter_data[f"oauths.{provider}.id"] = data.id filter_data[f"oauths.{provider}.id"] = data.id
async with cls.connect() as collection: async with cls.connect() as collection:
@@ -29,7 +29,7 @@ class UserRepository(BaseRepository):
filter_data, filter_data,
{ {
"$setOnInsert": { "$setOnInsert": {
**newUser.model_dump(), **new_user.model_dump(),
} }
}, },
upsert=True, upsert=True,

View File

@@ -0,0 +1,13 @@
from asyncio import run
from applications.games_list.discord import client, logger
from core.config import config
async def start_discord_sevice():
logger.info("Starting Discord service...")
await client.start(config.DISCORD_BOT_TOKEN)
run(start_discord_sevice())

View File

@@ -5,13 +5,13 @@ from discord.abc import Messageable
from discord import Object from discord import Object
from discord import app_commands from discord import app_commands
from modules.games_list.games_list import GameList, GameItem from applications.common.repositories.streamers import StreamerConfigRepository
from applications.games_list.games_list import GameList, GameItem
from core.config import config from core.config import config
from repositories.streamers import StreamerConfigRepository
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
async def get_game_list_channel_to_message_map() -> dict[int, int]: async def get_game_list_channel_to_message_map() -> dict[int, int]:
@@ -240,9 +240,3 @@ async def replace(interaction: discord.Interaction, game: str, new: str):
await game_list.save() await game_list.save()
await interaction.response.send_message("Игра заменена!", ephemeral=True) await interaction.response.send_message("Игра заменена!", ephemeral=True)
async def start_discord_sevice():
logger.info("Starting Discord service...")
await client.start(config.DISCORD_BOT_TOKEN)

View File

@@ -1,45 +0,0 @@
import logging
import sys
from modules.games_list import start as start_games_list_module
from modules.stream_notifications import start as start_stream_notifications_module
from core.mongo import mongo_manager
from core.redis import redis_manager
from core.broker import broker
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
async def main():
logger.info("Starting services...")
if len(sys.argv) != 2:
raise RuntimeError("Usage: python main.py <module>")
module = sys.argv[1]
await mongo_manager.init()
await redis_manager.init()
if not broker.is_worker_process:
await broker.startup()
if module == "games_list":
await start_games_list_module()
elif module == "stream_notifications":
await start_stream_notifications_module()
else:
raise RuntimeError(f"Unknown module: {module}")
exit(0)
if __name__ == "__main__":
from asyncio import run
run(main())

View File

@@ -1,7 +0,0 @@
from .discord import start_discord_sevice
start = start_discord_sevice
__all__ = ["start"]

View File

@@ -1,2 +0,0 @@
from modules.scheduler_sync.tasks import * # noqa: F403
from modules.stream_notifications.tasks import * # noqa: F403