Skip to content

Commit 5acbba1

Browse files
author
Kile
committed
Code quality cleanups
1 parent fcf74b1 commit 5acbba1

28 files changed

+1199
-924
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Env file
22
.env
33

4+
# SonarQube scan config
5+
.scannerwork/
6+
47
# VSCode config
58
.vscode/
69

api/Dockerfile

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Use an official Rust runtime as a parent image
22
FROM rust:1.78 AS base
33

4+
ARG MYUID=1000
5+
ARG MYGID=1000
6+
47
# Set the working directory in the container
58
WORKDIR /app
69

@@ -14,20 +17,30 @@ WORKDIR /app/api
1417
# Runs in development and production on port 8000 (in the container)
1518
EXPOSE 8000
1619

17-
FROM base as prod
20+
FROM base AS prod
1821

1922
# Build the Rust application
2023
RUN cargo build --release
2124

25+
# Create a user and group to run the application
26+
RUN groupadd -g "${MYGID}" api \
27+
&& useradd --create-home --no-log-init -u "${MYUID}" -g "${MYGID}" api
28+
USER api
29+
2230
# Set the binary as the entrypoint
2331
CMD ["./target/release/api"]
2432

2533
# run without release flag for development
26-
FROM base as dev
34+
FROM base AS dev
2735

2836
# Build the Rust application no cache
2937
RUN cargo build
3038

39+
# Create a user and group to run the application
40+
RUN groupadd -g "${MYGID}" api \
41+
&& useradd --create-home --no-log-init -u "${MYUID}" -g "${MYGID}" api
42+
USER api
43+
3144
# Set the binary as the entrypoint
3245
CMD ["./target/debug/api"]
3346

docker-compose.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ services:
1414
build:
1515
context: "./zmq_proxy"
1616
target: ${MODE:-prod} # dev/prod
17+
args:
18+
- "MYUID=${MYUID:-1000}"
19+
- "MYGID=${MYGID:-1000}"
1720
environment:
1821
- ZMQ_CLIENT_ADDRESS=tcp://*:5559
1922
- ZMQ_SERVER_ADDRESS=tcp://*:5560
@@ -26,6 +29,9 @@ services:
2629
context: ./
2730
dockerfile: ./api/Dockerfile
2831
target: ${MODE:-prod} # dev/prod
32+
args:
33+
- "MYUID=${MYUID:-1000}"
34+
- "MYGID=${MYGID:-1000}"
2935
container_name: rust_api
3036
ports:
3137
- "6060:7650"
@@ -44,6 +50,9 @@ services:
4450
context: ./
4551
dockerfile: ./killua/Dockerfile
4652
target: ${MODE:-prod} # dev/prod
53+
args:
54+
- "MYUID=${MYUID:-1000}"
55+
- "MYGID=${MYGID:-1000}"
4756
container_name: python_bot
4857
restart: unless-stopped
4958
environment:

killua/Dockerfile

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Use an official Python runtime as a parent image
22
FROM python:3.9-slim AS base
33

4+
ARG MYUID=1000
5+
ARG MYGID=1000
6+
47
# Set the working directory in the container
58
WORKDIR /app
69

@@ -21,14 +24,25 @@ RUN apt-get update && apt-get install -y git
2124
# Install C++ cause a dependency needs it
2225
RUN apt-get install -y g++
2326

27+
# Clean up the cache
28+
RUN apt-get clean
29+
2430
# Upgrade pip
2531
RUN pip3 install --no-cache-dir --upgrade pip
2632

2733
# Install any needed packages specified in requirements.txt
2834
RUN pip3 install --no-cache-dir -r requirements.txt
2935

3036
FROM base AS dev
37+
# Create a user and group to run the application
38+
RUN groupadd -g "${MYGID}" python \
39+
&& useradd --create-home --no-log-init -u "${MYUID}" -g "${MYGID}" python
40+
USER python
3141
CMD ["python3", "-m", "killua", "--development", "--docker"]
3242

33-
FROM base as prod
43+
FROM base AS prod
44+
# Create a user and group to run the application
45+
RUN groupadd -g "${MYGID}" python \
46+
&& useradd --create-home --no-log-init -u "${MYUID}" -g "${MYGID}" python
47+
USER python
3448
CMD ["python3", "-m", "killua", "--docker"]

killua/bot.py

Lines changed: 97 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from logging import info
1414
from inspect import signature, Parameter
1515
from functools import partial
16-
from typing import Coroutine, Union, Dict, List, Optional
16+
from typing import Coroutine, Union, Dict, List, Optional, Tuple
1717

1818
from .migrate import migrate_requiring_bot
1919
from .static.enums import Category
@@ -48,6 +48,10 @@ async def get_prefix(bot: "BaseBot", message: discord.Message):
4848
# in case message.guild is `None` or something went wrong getting the prefix the bot still NEEDS to react to mentions and k!
4949
return commands.when_mentioned_or("k!")(bot, message)
5050

51+
class KilluaAPIException(Exception):
52+
"""Raised when the Killua API returns an error"""
53+
def __init__(self, message: str):
54+
self.message = message
5155

5256
class BaseBot(commands.AutoShardedBot):
5357
def __init__(self, *args, **kwargs):
@@ -342,6 +346,67 @@ async def callback(
342346

343347
return callback
344348

349+
async def _get_text_response_modal(
350+
self,
351+
ctx: commands.Context,
352+
text: str,
353+
timeout: int = None,
354+
timeout_message: str = None,
355+
interaction: discord.Interaction = None,
356+
*args,
357+
**kwargs
358+
) -> Union[str, None]:
359+
"""Gets a response from a textinput UI"""
360+
modal = Modal(title="Answer the question and click submit", timeout=timeout)
361+
textinput = discord.ui.TextInput(label=text, *args, **kwargs)
362+
modal.add_item(textinput)
363+
364+
if interaction:
365+
await interaction.response.send_modal(modal)
366+
else:
367+
await ctx.interaction.response.send_modal(modal)
368+
369+
await modal.wait()
370+
if modal.timed_out:
371+
if timeout_message:
372+
await ctx.send(timeout_message, delete_after=5)
373+
return
374+
await modal.interaction.response.defer()
375+
return textinput.value
376+
377+
async def _get_text_response_message(
378+
self,
379+
ctx: commands.Context,
380+
text: str,
381+
timeout: int = None,
382+
timeout_message: str = None,
383+
*args,
384+
**kwargs,
385+
) -> Union[str, None]:
386+
"""Gets a response by waiting a message sent by the user"""
387+
def check(m: discord.Message):
388+
return m.author.id == ctx.author.id
389+
390+
msg = await ctx.send(text)
391+
try:
392+
confirm_msg: discord.Message = await self.wait_for(
393+
"message", check=check, timeout=timeout
394+
)
395+
except asyncio.TimeoutError:
396+
if timeout_message:
397+
await ctx.send(timeout_message, delete_after=5)
398+
res = None
399+
else:
400+
res = confirm_msg.content
401+
402+
await msg.delete()
403+
try:
404+
await confirm_msg.delete()
405+
except discord.Forbidden:
406+
pass
407+
408+
return res
409+
345410
async def get_text_response(
346411
self,
347412
ctx: commands.Context,
@@ -352,53 +417,45 @@ async def get_text_response(
352417
*args,
353418
**kwargs,
354419
) -> Union[str, None]:
355-
"""Gets a reponse from either a textinput UI or by waiting for a response"""
420+
"""Gets a response from either a textinput UI or by waiting for a response"""
356421

357422
if (ctx.interaction and not ctx.interaction.response.is_done()) or interaction:
358-
modal = Modal(
359-
title="Anser the question(s) and click submit", timeout=timeout
423+
return await self._get_text_response_modal(
424+
ctx, text, timeout, timeout_message, interaction, *args, **kwargs
360425
)
361-
textinput = discord.ui.TextInput(label=text, *args, **kwargs)
362-
modal.add_item(textinput)
363-
364-
if interaction:
365-
await interaction.response.send_modal(modal)
366-
else:
367-
await ctx.interaction.response.send_modal(modal)
368-
369-
await modal.wait()
370-
if modal.timed_out:
371-
if timeout_message:
372-
await ctx.send(timeout_message, delete_after=5)
373-
return
374-
await modal.interaction.response.defer()
375-
376-
return textinput.value
377-
378426
else:
427+
return await self._get_text_response_message(
428+
ctx, text, timeout, timeout_message, *args, **kwargs
429+
)
379430

380-
def check(m: discord.Message):
381-
return m.author.id == ctx.author.id
431+
async def make_embed_from_api(
432+
self,
433+
image_url: str,
434+
embed: discord.Embed
435+
) -> Tuple[discord.Embed, Optional[discord.File]]:
436+
"""
437+
Makes an embed from a Killua API image url.
382438
383-
msg = await ctx.send(text)
384-
try:
385-
confirmmsg: discord.Message = await self.wait_for(
386-
"message", check=check, timeout=timeout
387-
)
388-
except asyncio.TimeoutError:
389-
if timeout_message:
390-
await ctx.send(timeout_message, delete_after=5)
391-
res = None
392-
else:
393-
res = confirmmsg.content
439+
If the bot is running in a dev environment, the image is downloaded
440+
and sent as a file.
394441
395-
await msg.delete()
396-
try:
397-
await confirmmsg.delete()
398-
except commands.Forbidden:
399-
pass
442+
Raises:
443+
KilluaAPIException: If the Killua API returns an error
444+
"""
445+
file = None
446+
if self.is_dev:
447+
# Upload the image as attachment instead
448+
data = await self.session.get(image_url)
449+
if data.status != 200:
450+
raise KilluaAPIException(await data.text())
451+
452+
extension = image_url.split(".")[-1]
453+
embed.set_image(url=f"attachment://image.{extension}")
454+
file = discord.File(BytesIO(await data.read()), f"image.{extension}")
455+
else:
456+
embed.set_image(url=image_url)
457+
return embed, file
400458

401-
return res
402459

403460
async def update_presence(self):
404461
status = await DB.const.find_one({"_id": "presence"})

killua/cogs/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
continue
2929
if spec.loader is None:
3030
continue
31-
module = spec.loader.load_module()
31+
module = spec.loader.load_module(name)
3232
# Make it a global.
3333
globals()[name] = module
3434
# Put it in the list.

0 commit comments

Comments
 (0)