Compare commits

..

No commits in common. "00e1cedfcd6489796e3a59d0ebebe26be0ec5d4d" and "c05794ad99f07ac8db4bf6d52fd80216dfd65718" have entirely different histories.

18 changed files with 50 additions and 521 deletions

View File

@ -4,7 +4,6 @@
/* eslint-disable */ /* eslint-disable */
import type { PlayerSchema } from './PlayerSchema'; import type { PlayerSchema } from './PlayerSchema';
export type GetUserResponse = { export type GetUserResponse = {
discordId?: (string | null);
isAdmin?: boolean; isAdmin?: boolean;
realUser: (PlayerSchema | null); realUser: (PlayerSchema | null);
steamId: string; steamId: string;

View File

@ -3,7 +3,6 @@
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
export type PlayerSchema = { export type PlayerSchema = {
discordId?: (string | null);
isAdmin?: boolean; isAdmin?: boolean;
steamId: string; steamId: string;
username: string; username: string;

View File

@ -6,7 +6,6 @@ import type { RoleSchema } from './RoleSchema';
export type ViewTeamMembersResponse = { export type ViewTeamMembersResponse = {
availability: Array<number>; availability: Array<number>;
createdAt: string; createdAt: string;
discordId?: (string | null);
isAdmin?: boolean; isAdmin?: boolean;
isTeamLeader?: boolean; isTeamLeader?: boolean;
playtime: number; playtime: number;

View File

@ -16,7 +16,6 @@ export const useAuthStore = defineStore("auth", () => {
const hasCheckedAuth = ref(false); const hasCheckedAuth = ref(false);
const isAdmin = ref(false); const isAdmin = ref(false);
const realUser = ref<PlayerSchema | null>(null); const realUser = ref<PlayerSchema | null>(null);
const discordId = ref<string | null>("");
const router = useRouter(); const router = useRouter();
@ -40,7 +39,6 @@ export const useAuthStore = defineStore("auth", () => {
user.value = response; user.value = response;
isAdmin.value = response.isAdmin || (response.realUser?.isAdmin ?? false); isAdmin.value = response.isAdmin || (response.realUser?.isAdmin ?? false);
realUser.value = response.realUser ?? null; realUser.value = response.realUser ?? null;
discordId.value = response.discordId ?? "";
return response; return response;
}, },
@ -118,7 +116,6 @@ export const useAuthStore = defineStore("auth", () => {
username, username,
isAdmin, isAdmin,
realUser, realUser,
discordId,
isLoggedIn, isLoggedIn,
hasCheckedAuth, hasCheckedAuth,
isRegistering, isRegistering,

View File

@ -1,20 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { useAuthStore } from "@/stores/auth"; import { useAuthStore } from "@/stores/auth";
import { computed, onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
//const baseUrl = window.location.origin;
const redirectUri = computed(() => {
return encodeURIComponent(window.location.origin + "/settings");
});
const oauthUrl = computed(() => {
return "https://discord.com/oauth2/authorize" +
"?client_id=1372254613692219392" +
"&response_type=code" +
`&redirect_uri=${redirectUri.value}` +
"&scope=identify";
});
const displayName = ref(""); const displayName = ref("");
@ -39,29 +25,6 @@ onMounted(() => {
</h3> </h3>
<input v-model="displayName" /> <input v-model="displayName" />
</div> </div>
<div class="form-group margin">
<h3>
Discord Account
</h3>
<!--p>
Link your Discord account to your profile to enable Discord
integration features. Contact
<a href="https://discord.com/users/195789918474207233">@pyrofromcsgo</a>
if you would like to manually link your account without logging in
through Discord.
</p-->
<p v-if="authStore.discordId">
Linked to Discord account <code>{{ authStore.discordId }}</code>.
</p>
<p v-else>
Discord OAuth is not yet implemented.
Contact <a href="https://discord.com/users/195789918474207233">@pyrofromcsgo</a>
if you would like to link your Discord account.
</p>
<!--a :href="oauthUrl">
<button>Link Discord Account</button>
</a-->
</div>
<div class="form-group margin"> <div class="form-group margin">
<div class="action-buttons"> <div class="action-buttons">
<button class="accent" @click="save">Save</button> <button class="accent" @click="save">Save</button>

View File

@ -1,5 +1,5 @@
# Use an official Python runtime as a parent image # Use an official Python runtime as a parent image
FROM python:3.13-slim FROM python:3.12-slim
COPY requirements.txt / COPY requirements.txt /

View File

@ -3,8 +3,7 @@ from flask import Flask
from flask_migrate import Migrate from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import MetaData from sqlalchemy import MetaData
from sqlalchemy.engine import create_engine from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import DeclarativeBase, scoped_session, sessionmaker
from celery import Celery, Task from celery import Celery, Task
class BaseModel(DeclarativeBase): class BaseModel(DeclarativeBase):
@ -75,24 +74,7 @@ metadata = MetaData(naming_convention=convention)
def create_db() -> SQLAlchemy: def create_db() -> SQLAlchemy:
return SQLAlchemy(model_class=BaseModel, metadata=metadata) return SQLAlchemy(model_class=BaseModel, metadata=metadata)
def create_isolated_db_session(database_uri: str | None):
database_uri = environ.get("DATABASE_URI") or DATABASE_URI
if not database_uri:
raise ValueError("Database URI is not provided")
engine = create_engine(database_uri)
isolated_db = scoped_session(
sessionmaker(
autocommit=False,
autoflush=False,
bind=engine,
)
)
return isolated_db
app = create_app() app = create_app()
#db = SQLAlchemy(model_class=BaseModel, metadata=metadata) #db = SQLAlchemy(model_class=BaseModel, metadata=metadata)
db = create_db() db = create_db()
db_session: scoped_session = db.session
migrate = Migrate(app, db, render_as_batch=True) migrate = Migrate(app, db, render_as_batch=True)

View File

@ -1,192 +0,0 @@
import os
import discord
from discord.ext import commands
import app_db
import models
from models.event import Event
from models.player import Player
from models.player_event import PlayerEvent
from models.player_team import PlayerTeam
app_db.db_session = app_db.create_isolated_db_session(None)
guild_id_str = os.getenv("GUILD_ID")
guild_id = discord.Object(id=int(guild_id_str)) if guild_id_str else None
discord_token = os.getenv("DISCORD_TOKEN")
if not discord_token:
raise ValueError("DISCORD_TOKEN environment variable not set.")
class EventModal(discord.ui.Modal):
event_name = discord.ui.TextInput(
label="Event Name",
placeholder="Enter the event name",
)
event_description = discord.ui.TextInput(
label="Event Description",
placeholder="Describe the event",
style=discord.TextStyle.long,
)
def __init__(self, event: Event):
self.event = event
self.event_name.default = event.name
self.event_description.default = event.description
super().__init__(title="Event Details")
async def on_submit(self, interaction: discord.Interaction):
player_team = app_db.db_session.query(
PlayerTeam
).where(
PlayerTeam.team_id == self.event.team_id,
).join(
Player,
Player.steam_id == PlayerTeam.player_id
).where(
Player.discord_id == interaction.user.id
).one_or_none()
if not player_team or not player_team.is_team_leader:
await interaction.response.send_message(
"You are not authorized to edit this event.",
ephemeral=True
)
self.event.name = self.event_name.value
self.event.description = self.event_description.value
app_db.db_session.commit()
self.event.update_discord_message()
await interaction.response.send_message("Event details updated.", ephemeral=True)
async def handle_update_attendance(
player: Player,
event: Event,
interaction: discord.Interaction,
custom_id: str
):
player_event = app_db.db_session.query(
PlayerEvent
).where(
PlayerEvent.player_id == player.steam_id,
PlayerEvent.event_id == event.id
).one_or_none()
if custom_id == "click_not_attending":
if player_event:
app_db.db_session.delete(player_event)
app_db.db_session.commit()
event.update_discord_message()
await interaction.response.defer()
if not player_event:
player_event = PlayerEvent()
player_event.event_id = event.id
player_event.player_id = player.steam_id
app_db.db_session.add(player_event)
player_event.has_confirmed = custom_id == "click_attending"
app_db.db_session.commit()
event.update_discord_message()
await interaction.response.defer()
class Client(commands.Bot):
async def on_ready(self):
if guild_id:
try:
synced = await self.tree.sync(guild=guild_id)
print(f"Ready! Synced {len(synced)} commands.")
except Exception as e:
print(f"Failed to sync commands: {e}")
pass
async def on_interaction(self, interaction: discord.Interaction):
if interaction.response.is_done():
return
if interaction.type == discord.InteractionType.component and interaction.message:
# Handle button interactions here
if interaction.data is None or not "custom_id" in interaction.data:
return
interactions = [
"click_attending",
"click_pending",
"click_not_attending",
"click_edit_event",
]
if interaction.data["custom_id"] in interactions:
interaction_type = interaction.data["custom_id"]
player = app_db.db_session.query(
Player
).where(
Player.discord_id == interaction.user.id
).one_or_none()
if not player:
await interaction.response.send_message(
"This Discord account is not linked to a player. " +
"Contact <@195789918474207233> to link your account.",
ephemeral=True
)
# log the interaction
user = await self.fetch_user(195789918474207233)
if user:
await user.send(
f"User <@{interaction.user.id}> tried to " +
"interact with an event but their account is " +
"not linked to a player."
)
return
event = app_db.db_session.query(
Event
).where(
Event.discord_message_id == interaction.message.id
).one_or_none()
if event and player:
if interaction_type == "click_edit_event":
await interaction.response.send_modal(EventModal(event))
else:
await handle_update_attendance(player, event, interaction, interaction_type)
intents = discord.Intents.default()
client = Client(command_prefix="!", intents=intents)
@client.tree.command(
name="setup-announcement-webhook",
description="Set up announcements webhook in this channel",
guild=guild_id
)
@discord.app_commands.guild_only()
@discord.app_commands.default_permissions(manage_webhooks=True)
async def setup_announcements(interaction: discord.Interaction):
await interaction.response.send_message(
"Setting up announcement webhook. Any existing webhooks madde by " +
"this command will be deleted.",
ephemeral=True
)
channel = interaction.channel
assert isinstance(channel, discord.TextChannel)
for webhook in await channel.webhooks():
if webhook.user == client.user:
await webhook.delete()
webhook = await channel.create_webhook(name="availabili.tf webhook")
content = (
f"Webhook created: {webhook.url}\n" +
"Use this webhook URL in the Discord integration settings of your " +
"team to receive interactive announcements."
)
await interaction.followup.send(content, ephemeral=True)
client.run(discord_token)

View File

@ -25,12 +25,11 @@ class GetUserResponse(PlayerSchema):
real_user: PlayerSchema | None real_user: PlayerSchema | None
@classmethod @classmethod
def from_model(cls, player: Player): def from_model(cls, model: Player):
return GetUserResponse( return GetUserResponse(
steam_id=str(player.steam_id), steam_id=str(model.steam_id),
username=player.username, username=model.username,
is_admin=player.is_admin, is_admin=model.is_admin,
discord_id=str(player.discord_id),
real_user=None, real_user=None,
) )
@ -45,9 +44,12 @@ class GetUserResponse(PlayerSchema):
@requires_authentication @requires_authentication
def get_user(player: Player, auth_session: AuthSession): def get_user(player: Player, auth_session: AuthSession):
if auth_session.player.steam_id != player.steam_id: if auth_session.player.steam_id != player.steam_id:
response = GetUserResponse.from_model(player) return GetUserResponse(
response.real_user = PlayerSchema.from_model(auth_session.player) steam_id=str(player.steam_id),
return response.dict(by_alias=True) username=player.username,
is_admin=player.is_admin,
real_user=PlayerSchema.from_model(auth_session.player)
).dict(by_alias=True)
return GetUserResponse.from_model(player).dict(by_alias=True) return GetUserResponse.from_model(player).dict(by_alias=True)
@api_login.post("/authenticate") @api_login.post("/authenticate")

View File

@ -1,32 +0,0 @@
"""Make players.discord_id unique
Revision ID: 251a8108d7ff
Revises: f4330df94c44
Create Date: 2025-05-14 16:44:16.817690
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '251a8108d7ff'
down_revision = 'f4330df94c44'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('players', schema=None) as batch_op:
batch_op.create_unique_constraint("uq_players_discord_id", ['discord_id'])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('players', schema=None) as batch_op:
batch_op.drop_constraint("uq_players_discord_id", type_='unique')
# ### end Alembic commands ###

View File

@ -1,32 +0,0 @@
"""Add uniqueness constraints
Revision ID: 8a37924fd1be
Revises: 251a8108d7ff
Create Date: 2025-05-15 09:52:01.887077
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '8a37924fd1be'
down_revision = '251a8108d7ff'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('events', schema=None) as batch_op:
batch_op.create_unique_constraint('uq_events_discord_message_id', ['discord_message_id'])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('events', schema=None) as batch_op:
batch_op.drop_constraint('uq_events_discord_message_id', type_='unique')
# ### end Alembic commands ###

View File

@ -1,32 +0,0 @@
"""Add players.discord_id field
Revision ID: f4330df94c44
Revises: f8588cdf998e
Create Date: 2025-05-14 14:06:29.368594
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'f4330df94c44'
down_revision = 'f8588cdf998e'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('players', schema=None) as batch_op:
batch_op.add_column(sa.Column('discord_id', sa.BigInteger(), nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('players', schema=None) as batch_op:
batch_op.drop_column('discord_id')
# ### end Alembic commands ###

View File

@ -1,14 +1,13 @@
from datetime import datetime from datetime import datetime
import requests
import threading import threading
from sqlalchemy.orm import mapped_column, relationship, scoped_session from sqlalchemy.orm import mapped_column, relationship
from sqlalchemy.orm.attributes import Mapped from sqlalchemy.orm.attributes import Mapped
from sqlalchemy.orm.properties import ForeignKey from sqlalchemy.orm.properties import ForeignKey
from sqlalchemy.orm.session import Session
from sqlalchemy.schema import UniqueConstraint from sqlalchemy.schema import UniqueConstraint
from sqlalchemy.types import TIMESTAMP, BigInteger, Integer, String, Text from sqlalchemy.types import TIMESTAMP, BigInteger, Integer, String, Text
from sqlalchemy.sql import func from sqlalchemy.sql import func
from sqlalchemy_utc import UtcDateTime from sqlalchemy_utc import UtcDateTime
from discord_webhook import DiscordWebhook
import app_db import app_db
import spec import spec
import os import os
@ -27,7 +26,7 @@ class Event(app_db.BaseModel):
description: Mapped[str | None] = mapped_column(Text, nullable=True) description: Mapped[str | None] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=func.now()) created_at: Mapped[datetime] = mapped_column(TIMESTAMP, server_default=func.now())
discord_message_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, unique=True) discord_message_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
team: Mapped["Team"] = relationship("Team", back_populates="events") team: Mapped["Team"] = relationship("Team", back_populates="events")
players: Mapped[list["PlayerEvent"]] = relationship( players: Mapped[list["PlayerEvent"]] = relationship(
@ -41,7 +40,7 @@ class Event(app_db.BaseModel):
) )
def get_maximum_matching(self): def get_maximum_matching(self):
players_teams_roles = app_db.db_session.query( players_teams_roles = app_db.db.session.query(
PlayerTeamRole PlayerTeamRole
).join( ).join(
PlayerTeam PlayerTeam
@ -90,10 +89,7 @@ class Event(app_db.BaseModel):
if player.role: if player.role:
player_info += f"**{player.role.role.name}:** " player_info += f"**{player.role.role.name}:** "
if player.player.discord_id: player_info += f"{player.player.username}"
player_info += f"<@{player.player.discord_id}>"
else:
player_info += f"{player.player.username}"
if player.has_confirmed: if player.has_confirmed:
player_info += "" player_info += ""
@ -109,6 +105,8 @@ class Event(app_db.BaseModel):
else: else:
ringers_needed_msg = f" **({ringers_needed} ringers needed)**" ringers_needed_msg = f" **({ringers_needed} ringers needed)**"
domain = os.environ.get("DOMAIN", "availabili.tf")
return "\n".join([ return "\n".join([
f"# {self.name}", f"# {self.name}",
"", "",
@ -117,95 +115,47 @@ class Event(app_db.BaseModel):
f"<t:{start_timestamp}:f>", f"<t:{start_timestamp}:f>",
"\n".join(players_info), "\n".join(players_info),
f"Maximum roles filled: {matchings}" + ringers_needed_msg, f"Maximum roles filled: {matchings}" + ringers_needed_msg,
#"", "",
#"[Confirm attendance here]" + "[Confirm attendance here]" +
# f"(https://{domain}/team/id/{self.team.id})", f"(https://{domain}/team/id/{self.team.id})",
]) ])
def get_discord_message_components(self):
domain = os.environ.get("DOMAIN", "availabili.tf")
return [
{
"type": 10,
"content": self.get_discord_content(),
},
{
"type": 1,
"components": [
{
"type": 2,
"label": "",
"style": 3,
"custom_id": "click_attending"
},
{
"type": 2,
"label": "",
"style": 2,
"custom_id": "click_pending"
},
{
"type": 2,
"label": "",
"style": 2,
"custom_id": "click_not_attending"
},
{
"type": 2,
"label": "Edit",
"style": 2,
"custom_id": "click_edit_event"
},
{
"type": 2,
"label": "View in browser",
"style": 5,
"url": f"https://{domain}/team/id/{self.team_id}"
}
]
}
]
def get_or_create_webhook(self): def get_or_create_webhook(self):
integration = app_db.db_session.query( integration = app_db.db.session.query(
TeamDiscordIntegration TeamDiscordIntegration
).where( ).where(
TeamDiscordIntegration.team_id == self.team_id TeamDiscordIntegration.team_id == self.team_id
).first() ).first()
if not integration: if not integration:
return None, "" return None
webhook = { if self.discord_message_id:
"username": integration.webhook_bot_name, return DiscordWebhook(
"avatar_url": integration.webhook_bot_profile_picture, integration.webhook_url,
"flags": 1 << 15, id=str(self.discord_message_id),
} username=integration.webhook_bot_name,
avatar_url=integration.webhook_bot_profile_picture,
return webhook, integration.webhook_url )
else:
return DiscordWebhook(
integration.webhook_url,
username=integration.webhook_bot_name,
avatar_url=integration.webhook_bot_profile_picture,
)
def update_discord_message(self): def update_discord_message(self):
domain = os.environ.get("DOMAIN", "availabili.tf") webhook = self.get_or_create_webhook()
webhook, webhook_url = self.get_or_create_webhook()
if webhook: if webhook:
params = "?with_components=true&wait=true" webhook.content = self.get_discord_content()
webhook["components"] = self.get_discord_message_components() if webhook.id:
if self.discord_message_id:
# fire and forget # fire and forget
#threading.Thread(target=webhook.edit).start() threading.Thread(target=webhook.edit).start()
del webhook["username"]
del webhook["avatar_url"]
webhook_url += f"/messages/{self.discord_message_id}"
requests.patch(webhook_url + params, json=webhook)
else: else:
#webhook.execute() webhook.execute()
response = requests.post(webhook_url + params, json=webhook) if webhook_id := webhook.id:
response = response.json()
if webhook_id := response["id"]:
self.discord_message_id = int(webhook_id) self.discord_message_id = int(webhook_id)
app_db.db_session.commit() app_db.db.session.commit()
else: else:
raise Exception("Failed to create webhook") raise Exception("Failed to create webhook")

View File

@ -13,7 +13,6 @@ class Player(app_db.BaseModel):
steam_id: Mapped[int] = mapped_column(BigInteger, primary_key=True) steam_id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
username: Mapped[str] = mapped_column(String(63)) username: Mapped[str] = mapped_column(String(63))
is_admin: Mapped[bool] = mapped_column(default=False) is_admin: Mapped[bool] = mapped_column(default=False)
discord_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True, unique=True)
teams: Mapped[list["PlayerTeam"]] = relationship(back_populates="player") teams: Mapped[list["PlayerTeam"]] = relationship(back_populates="player")
auth_sessions: Mapped[list["AuthSession"]] = relationship(back_populates="player") auth_sessions: Mapped[list["AuthSession"]] = relationship(back_populates="player")
@ -26,15 +25,13 @@ class PlayerSchema(spec.BaseModel):
steam_id: str steam_id: str
username: str username: str
is_admin: bool = False is_admin: bool = False
discord_id: str | None = None
@classmethod @classmethod
def from_model(cls, player: Player): def from_model(cls, player: Player):
return cls( return cls(
steam_id=str(player.steam_id), steam_id=str(player.steam_id),
username=player.username, username=player.username,
is_admin=player.is_admin, is_admin=player.is_admin
discord_id=str(player.discord_id) if player.discord_id else None
) )

View File

@ -9,7 +9,7 @@ Flask-SQLAlchemy
SQLAlchemy-Utc SQLAlchemy-Utc
# form/data validation # form/data validation
pydantic==2.11.4 pydantic==2.9.2
spectree==1.4.1 # generates OpenAPI documents for us to make TypeScript API spectree==1.4.1 # generates OpenAPI documents for us to make TypeScript API
# clients based on our pydantic models # clients based on our pydantic models
@ -22,9 +22,6 @@ requests
pytz # timezone handling pytz # timezone handling
discord-webhook # for sending messages to Discord webhooks discord-webhook # for sending messages to Discord webhooks
discord.py
https://github.com/HumanoidSandvichDispenser/Clyde/releases/download/test/discord_clyde-0.2.0-py3-none-any.whl
#discord-clyde
celery[redis] celery[redis]

View File

@ -1,6 +1,4 @@
import os from flask import Blueprint, abort, make_response
from flask import Blueprint, abort, make_response, request
import requests
from spectree import Response from spectree import Response
from middleware import requires_admin, requires_authentication from middleware import requires_admin, requires_authentication
from models.player import Player, PlayerSchema from models.player import Player, PlayerSchema
@ -10,11 +8,6 @@ from app_db import db
api_user = Blueprint("user", __name__, url_prefix="/user") api_user = Blueprint("user", __name__, url_prefix="/user")
# TODO: use env vars
DISCORD_TOKEN_URL = "https://discord.com/api/oauth2/token"
DISCORD_CLIENT_ID = "1372254613692219392" #os.getenv("DISCORD_CLIENT_ID")
DISCORD_CLIENT_SECRET = os.getenv("DISCORD_CLIENT_SECRET")
class SetUsernameJson(BaseModel): class SetUsernameJson(BaseModel):
username: str username: str
@ -85,34 +78,3 @@ def unset_doas(**_):
resp = make_response({ }, 204) resp = make_response({ }, 204)
resp.delete_cookie("doas", httponly=True) resp.delete_cookie("doas", httponly=True)
return resp return resp
#class DiscordAuthQuery(BaseModel):
# code: str
# redirect_uri: str
#
#@api_user.post("/discord-authenticate")
#@spec.validate(
# operation_id="discord_authenticate"
#)
#@requires_authentication
#def discord_authenticate(query: DiscordAuthQuery, player: Player, **_):
# if not DISCORD_CLIENT_ID or not DISCORD_CLIENT_SECRET:
# abort(500, "The site is not configured to use Discord authentication")
#
# data = {
# "client_id": DISCORD_CLIENT_ID,
# "client_secret": DISCORD_CLIENT_SECRET,
# "grant_type": "authorization_code",
# "code": query.code,
# "redirect_uri": query.redirect_uri,
# "scope": "identify"
# }
# response = requests.post(DISCORD_TOKEN_URL, data)
# access_token = response.json()["access_token"]
#
# headers = {
# "authorization": f"Bearer {access_token}"
# }
# response = requests.get("https://discord.com/api/v10/users/@me", headers=headers)
#
# id = response.json()[]

View File

@ -30,8 +30,6 @@ services:
- ./backend-flask:/app - ./backend-flask:/app
networks: networks:
- prod-network - prod-network
env_file:
- .env
environment: environment:
- FLASK_DEBUG=0 - FLASK_DEBUG=0
- FLASK_CELERY_BROKER_URL=redis://redis:6379/0 - FLASK_CELERY_BROKER_URL=redis://redis:6379/0
@ -45,7 +43,7 @@ services:
# ETL job (runs with the same source as the backend) # ETL job (runs with the same source as the backend)
celery-worker: celery-worker:
container_name: worker-production container_name: worker-production
command: celery -A make_celery.celery_app worker --loglevel=info --concurrency=1 command: celery -A make_celery.celery_app worker --loglevel=info --concurrency=1 -B
image: backend-flask-production image: backend-flask-production
environment: environment:
- CELERY_BROKER_URL=redis://redis:6379/0 - CELERY_BROKER_URL=redis://redis:6379/0
@ -55,24 +53,10 @@ services:
- ./backend-flask:/app - ./backend-flask:/app
networks: networks:
- prod-network - prod-network
env_file:
- .env
depends_on: depends_on:
- redis - redis
- db - db
# discord bot
discord-bot:
container_name: discord-bot
command: python discord_bot.py
image: backend-flask-production
volumes:
- ./backend-flask:/app
networks:
- prod-network
env_file:
- .env
# message broker # message broker
redis: redis:
image: redis:alpine image: redis:alpine

View File

@ -22,7 +22,7 @@ services:
# ETL job (runs with the same source as the backend) # ETL job (runs with the same source as the backend)
celery-worker: celery-worker:
container_name: worker container_name: worker
command: celery -A make_celery.celery_app worker --loglevel=info --concurrency=1 command: celery -A make_celery.celery_app worker --loglevel=info --concurrency=1 -B
environment: environment:
- CELERY_BROKER_URL=redis://redis:6379/0 - CELERY_BROKER_URL=redis://redis:6379/0
- CELERY_RESULT_BACKEND=redis://redis:6379/0 - CELERY_RESULT_BACKEND=redis://redis:6379/0
@ -35,20 +35,6 @@ services:
depends_on: depends_on:
- redis - redis
# discord bot
discord-bot:
container_name: discord-bot
command: python discord_bot.py
image: backend-flask
volumes:
- ./backend-flask:/app
networks:
- dev-network
env_file:
- .env
environment:
- DATABASE_URI=sqlite:///instance/db.sqlite3
# message broker # message broker
redis: redis:
image: redis:alpine image: redis:alpine