Skip to content

Commit 8019d43

Browse files
committed
ENHANCEMENTS:
- RestAPI added /linkme (credits James B)
1 parent 3077895 commit 8019d43

File tree

2 files changed

+79
-2
lines changed

2 files changed

+79
-2
lines changed

plugins/gamemaster/upload.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def __init__(self, plugin: "GameMaster", server: Server, message: discord.Messag
2323

2424
async def create_embed(self, att: discord.Attachment) -> None:
2525
async with aiohttp.ClientSession() as session:
26-
async with session.get(att.url) as response:
26+
async with session.get(att.url, proxy=self.node.proxy, proxy_auth=self.node.proxy_auth) as response:
2727
if response.status != 200:
2828
await self.channel.send(_('Error {} while reading JSON file!').format(response.status))
2929
return

plugins/restapi/commands.py

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import asyncio
22
import logging
33
import os
4+
import psycopg
5+
import random
46
import shutil
57
import uvicorn
68

79
from core import Plugin, DEFAULT_TAG
8-
from datetime import datetime
10+
from datetime import datetime, timedelta, timezone
911
from fastapi import FastAPI, APIRouter, Form
1012
from psycopg.rows import dict_row
1113
from services.bot import DCSServerBot
@@ -15,6 +17,12 @@
1517
app: Optional[FastAPI] = None
1618

1719

20+
# Bit field constants
21+
BIT_USER_LINKED = 1
22+
BIT_LINK_IN_PROGRESS = 2
23+
BIT_FORCE_OPERATION = 4
24+
25+
1826
class RestAPI(Plugin):
1927

2028
def __init__(self, bot: DCSServerBot):
@@ -30,6 +38,7 @@ def __init__(self, bot: DCSServerBot):
3038
self.router.add_api_route(prefix + "/getuser", self.getuser, methods=["POST"])
3139
self.router.add_api_route(prefix + "/missilepk", self.missilepk, methods=["POST"])
3240
self.router.add_api_route(prefix + "/stats", self.stats, methods=["POST"])
41+
self.router.add_api_route(prefix + "/linkme", self.linkme, methods=["POST"])
3342
self.app = app
3443
self.config = Config(app=self.app, host=cfg['listen'], port=cfg['port'], log_level=logging.ERROR,
3544
use_colors=False)
@@ -182,6 +191,74 @@ async def stats(self, nick: str = Form(default=None), date: str = Form(default=N
182191
data['kdrByModule'] = await cursor.fetchall()
183192
return data
184193

194+
async def linkme(self,
195+
discord_id: str = Form(..., description="Discord user ID (snowflake)", example="123456789012345678"),
196+
force: bool = Form(False, description="Force the operation", example=True)):
197+
198+
async def create_token() -> str:
199+
while True:
200+
try:
201+
token = str(random.randint(1000, 9999))
202+
cursor.execute("""
203+
INSERT INTO players (ucid, discord_id, last_seen)
204+
VALUES (%s, %s, NOW() AT TIME ZONE 'utc')
205+
""", (token, discord_id))
206+
return token
207+
except psycopg.errors.UniqueViolation:
208+
pass
209+
210+
self.log.debug(f'Calling /link with discord_id="{discord_id}", force="{force}"')
211+
async with self.apool.connection() as conn:
212+
async with conn.cursor(row_factory=dict_row) as cursor:
213+
214+
# Check if discord_id exists
215+
await cursor.execute("SELECT ucid, last_seen FROM players WHERE discord_id = %s", (discord_id,))
216+
result = await cursor.fetchone()
217+
218+
rc = 0
219+
token = None
220+
now = datetime.now(tz=timezone.utc)
221+
222+
if result:
223+
ucid, last_seen = result
224+
225+
if len(ucid) == 4: # UCID is stored as a 4-character string
226+
# Linking already in progress
227+
token = ucid
228+
rc |= BIT_LINK_IN_PROGRESS
229+
if force:
230+
rc |= BIT_FORCE_OPERATION
231+
cursor.execute("""
232+
UPDATE players
233+
SET last_seen = (NOW() AT TIME ZONE 'utc')
234+
WHERE discord_id = %s
235+
""", (discord_id, ))
236+
expiry_timestamp = (now + timedelta(hours=48)).isoformat()
237+
else:
238+
expiry_timestamp = (last_seen + timedelta(hours=48)).isoformat()
239+
else:
240+
# User already linked
241+
rc |= BIT_USER_LINKED
242+
if force:
243+
rc |= BIT_FORCE_OPERATION
244+
token = await create_token()
245+
expiry_timestamp = (now + timedelta(hours=48)).isoformat()
246+
else:
247+
expiry_timestamp = None
248+
else:
249+
token = await create_token()
250+
expiry_timestamp = (datetime.now() + timedelta(hours=48)).isoformat()
251+
# Set bit_field for new user
252+
rc = 0 # Default bit_field for new user
253+
if force:
254+
rc |= BIT_FORCE_OPERATION # Set force operation flag
255+
256+
return {
257+
"token": token,
258+
"timestamp": expiry_timestamp,
259+
"rc": rc
260+
}
261+
185262

186263
async def setup(bot: DCSServerBot):
187264
global app

0 commit comments

Comments
 (0)