Skip to content

Commit

Permalink
Merge pull request #73 from Tibo-Ulens/feature/confession-replies
Browse files Browse the repository at this point in the history
add confession replies
  • Loading branch information
Tibo-Ulens authored Jan 15, 2024
2 parents 43d5835 + e8870b7 commit 0733dde
Show file tree
Hide file tree
Showing 6 changed files with 269 additions and 17 deletions.
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: all fmt migrate down dbd setup
.PHONY: all dev fmt lint setup dbd migrate psql chd redis down

all:
docker compose up --build freud_bot freud_bot_webconfig
Expand Down Expand Up @@ -27,5 +27,11 @@ migrate: dbd
psql: dbd
docker exec -it freud_bot_db psql -d freud_bot -h freud_bot_db -U postgres_user

chd:
docker compose up --build freud_bot_cache --remove-orphans -d

redis: chd
docker exec -it freud_bot_cache redis-cli -h freud_bot_cache -p 6379

down:
docker compose down
12 changes: 10 additions & 2 deletions bot/bot.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import asyncio
from contextlib import suppress
import importlib.util
from typing import Sequence

import logging
from logging import Logger
import os
from typing import Sequence

import discord
from discord.abc import Snowflake
from discord.ext import commands
from discord.utils import MISSING
import redis.asyncio as redis

from bot.log.guild_adapter import GuildAdapter

Expand All @@ -26,6 +28,9 @@ def __init__(self, *args, **kwargs):
self.discord_logger: GuildAdapter = None
self.loop = asyncio.get_running_loop()

self.redis = redis.Redis.from_url(os.environ["CH_URL"], decode_responses=True)
logger.info("cache connected")

@classmethod
async def create(cls) -> "Bot":
"""Create and return a new bot instance"""
Expand Down Expand Up @@ -112,6 +117,9 @@ async def close(self) -> None:
await super().close()
logger.info("client closed")

await self.redis.aclose()
logger.info("cache closed")

await self.db.dispose()
logger.info("database closed")

Expand Down
106 changes: 93 additions & 13 deletions bot/extensions/fun/confess.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import random
from enum import Enum
import logging

import discord
from discord import (
Expand All @@ -11,7 +12,9 @@
Colour,
Member,
)
from discord.ext.commands import Context
from discord.ui import View, Button
from redis.asyncio import Redis

from models.config import Config
from models.profile_statistics import ProfileStatistics
Expand All @@ -24,6 +27,9 @@
from bot.extensions import ErrorHandledCog


logger = logging.getLogger("bot")


class ConfessionType(Enum):
NORMAL = (None, "🥷 Anonymous Confession 🥷", "Confession sent")
RUSSIAN = (
Expand Down Expand Up @@ -56,12 +62,16 @@ def __init__(
confession: str,
poster: Member,
type_: ConfessionType,
reply: str | None,
redis: Redis,
confession_channel: TextChannel,
approval_channel: TextChannel,
):
self.confession = confession
self.poster = poster
self.type_ = type_
self.reply = reply
self.redis = redis
self.confession_channel = confession_channel
self.approval_channel = approval_channel

Expand All @@ -72,8 +82,13 @@ async def send_pending(self):
description=self.confession,
)

if self.reply is not None:
pending_embed.set_author(name=f"Reply to #{self.reply}")

pending_view = PendingApprovalView(
redis=self.redis,
confession=pending_embed,
reply=self.reply,
confession_channel=self.confession_channel,
poster=self.poster,
chance=self.type_.chance,
Expand All @@ -88,13 +103,17 @@ async def send_pending(self):
class PendingApprovalView(View):
def __init__(
self,
redis: Redis,
confession: Embed,
reply: str | None,
confession_channel: TextChannel,
poster: Member,
chance: None | float,
chance: float | None,
):
super().__init__(timeout=None)
self.redis = redis
self.confession = confession
self.reply = reply
self.confession_channel = confession_channel
self.poster = poster
self.chance = chance
Expand All @@ -104,7 +123,10 @@ async def approve(self, ia: Interaction, _btn: Button):
for item in self.children:
item.disabled = True

confession_id = await self.redis.incr("confessionid")

self.confession.colour = Colour.from_str("#3fc03f")
self.confession.title = f"{self.confession.title} (#{confession_id})"

await self.message.edit(embed=self.confession, view=self)
await ia.response.defer()
Expand All @@ -118,7 +140,26 @@ async def approve(self, ia: Interaction, _btn: Button):

actual_confession.add_field(name="Sent By", value=self.poster.mention)

await self.confession_channel.send(embed=actual_confession)
if self.reply is not None:
reply_msg_id = int(await self.redis.get(f"confession:{self.reply}"))
reply_msg = self.confession_channel.get_partial_message(reply_msg_id)

try:
thread = await reply_msg.create_thread(
name="confession", reason="confession reply"
)
except discord.errors.HTTPException as err:
if err.code == 160004:
thread = self.confession_channel.get_thread(reply_msg_id)
else:
raise err

actual_msg = await thread.send(embed=actual_confession)
else:
actual_msg = await self.confession_channel.send(embed=actual_confession)

await self.redis.set(f"confession:{confession_id}", actual_msg.id)
await self.redis.expire(f"confession:{confession_id}", 86400)

@discord.ui.button(label="⨯", style=ButtonStyle.red)
async def reject(self, ia: Interaction, _btn: Button):
Expand All @@ -136,8 +177,13 @@ class Confess(ErrorHandledCog):
name="confess", description="Confession related commands", guild_only=True
)

@staticmethod
async def confess_inner(ia: Interaction, confession: str, type_: ConfessionType):
async def confess_inner(
self,
ia: Interaction,
confession: str,
type_: ConfessionType,
reply: str | None = None,
):
config = await Config.get(ia.guild_id)
approval_channel = discord.utils.get(
ia.guild.channels, id=config.confession_approval_channel
Expand All @@ -146,10 +192,29 @@ async def confess_inner(ia: Interaction, confession: str, type_: ConfessionType)
ia.guild.channels, id=config.confession_channel
)

if reply is not None:
reply_msg_id = await self.bot.redis.get(f"confession:{reply}")
if reply_msg_id is None:
await ia.response.send_message(
f"{reply} is not a valid confession ID", ephemeral=True
)
return
else:
try:
await confession_channel.fetch_message(int(reply_msg_id))
except discord.errors.HTTPException:
await ia.response.send_message(
f"{reply} is not a valid confession ID (keep in mind that you cannot reply to other replies)",
ephemeral=True,
)
return

confession_wrapper = Confession(
confession=confession,
poster=ia.user,
type_=type_,
reply=reply,
redis=self.bot.redis,
confession_channel=confession_channel,
approval_channel=approval_channel,
)
Expand All @@ -163,34 +228,49 @@ async def confess_inner(ia: Interaction, confession: str, type_: ConfessionType)
@confess_group.command(
name="normal", description="send a normal, anonymous confession"
)
@app_commands.describe(confession="The confession you want to post")
@app_commands.describe(
confession="The confession you want to post",
reply="The ID of the confession you want to reply to",
)
@check_has_config_option("confession_approval_channel")
@check_has_config_option("confession_channel")
@check_user_is_verified()
async def normal_confess(self, ia: Interaction, confession: str):
await self.confess_inner(ia, confession, ConfessionType.NORMAL)
async def normal_confess(
self, ia: Interaction, confession: str, reply: str | None = None
):
await self.confess_inner(ia, confession, ConfessionType.NORMAL, reply)

@confess_group.command(
name="russian",
description="send a russian roulette confession with a 1 in 6 chance of not being anonymous",
)
@app_commands.describe(confession="The confession you want to post")
@app_commands.describe(
confession="The confession you want to post",
reply="The ID of the confession you want to reply to",
)
@check_has_config_option("confession_approval_channel")
@check_has_config_option("confession_channel")
@check_user_is_verified()
async def russian_confess(self, ia: Interaction, confession: str):
await self.confess_inner(ia, confession, ConfessionType.RUSSIAN)
async def russian_confess(
self, ia: Interaction, confession: str, reply: str | None = None
):
await self.confess_inner(ia, confession, ConfessionType.RUSSIAN, reply)

@confess_group.command(
name="extreme",
description="send an extreme roulette confession with a 1 in 2 chance of not being anonymous",
)
@app_commands.describe(confession="The confession you want to post")
@app_commands.describe(
confession="The confession you want to post",
reply="The ID of the confession you want to reply to",
)
@check_has_config_option("confession_approval_channel")
@check_has_config_option("confession_channel")
@check_user_is_verified()
async def russian_confess(self, ia: Interaction, confession: str):
await self.confess_inner(ia, confession, ConfessionType.EXTREME)
async def russian_confess(
self, ia: Interaction, confession: str, reply: str | None = None
):
await self.confess_inner(ia, confession, ConfessionType.EXTREME, reply)


async def setup(bot: Bot):
Expand Down
21 changes: 21 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ services:
environment:
- DB_URL=postgresql+asyncpg://postgres_user@freud_bot_db/freud_bot
- PGPASSWORD=postgres_password

- CH_URL=redis://@freud_bot_cache:6379/0
logging:
options:
max-size: "4096m"
Expand All @@ -15,6 +17,7 @@ services:
- smtp_credentials
depends_on:
- freud_bot_db
- freud_bot_cache

freud_bot_dev:
build:
Expand All @@ -25,6 +28,8 @@ services:
environment:
- DB_URL=postgresql+asyncpg://postgres_user@freud_bot_db/freud_bot
- PGPASSWORD=postgres_password

- CH_URL=redis://@freud_bot_cache:6379/0
logging:
options:
max-size: "4096m"
Expand All @@ -33,6 +38,7 @@ services:
- smtp_credentials
depends_on:
- freud_bot_db
- freud_bot_cache

freud_bot_webconfig:
image: ghcr.io/tibo-ulens/freud_bot_webconfig:latest
Expand Down Expand Up @@ -100,6 +106,21 @@ services:
timeout: 5s
retries: 2

freud_bot_cache:
image: redis:7.2-alpine
container_name: freud_bot_cache
restart: unless-stopped
logging:
options:
max-size: "4096m"
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10m
timeout: 5s
retries: 2

volumes:
freud_bot_data:
external: true
Expand Down
Loading

0 comments on commit 0733dde

Please sign in to comment.