commit 540a61fb452b741b1932ecee40669eaf1fb75ab5 Author: Showdown76py Date: Sat Mar 2 21:41:56 2024 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6abb551 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +.env +database.db diff --git a/bot/app.py b/bot/app.py new file mode 100644 index 0000000..3ee763b --- /dev/null +++ b/bot/app.py @@ -0,0 +1,26 @@ +import discord, asyncio +import os +from discord.ext import commands +from discord import app_commands +import database.controller + +intents = discord.Intents.default() +intents.members = True +intents.dm_messages = True + +app = commands.Bot(command_prefix=",", intents=intents) +app.db = database.controller.Database("database.db") + + +# load cogs +async def load_cogs(): + for filename in os.listdir("bot/commands"): + if filename.endswith(".py"): + await app.load_extension(f"bot.commands.{filename[:-3]}") + + +@app.event +async def on_ready(): + print("Running") + await load_cogs() + await app.tree.sync() diff --git a/bot/commands/SubscribeCommand.py b/bot/commands/SubscribeCommand.py new file mode 100644 index 0000000..f2ceeb1 --- /dev/null +++ b/bot/commands/SubscribeCommand.py @@ -0,0 +1,32 @@ +from database.controller import Database +import discord +from discord import app_commands +from discord.ext import commands + + +class SubscribeCommand(commands.Cog): + def __init__(self, app: commands.Bot) -> None: + self.app = app + + @app_commands.command( + name="subscribe", description="Subscribe to BeReal. notifications." + ) + async def subscribe(self, interaction: discord.Interaction) -> None: + result = self.app.db.add_subscriber(interaction.user.id) + if result: + await interaction.response.send_message( + ":information_source: You have been subscribed to **BeReal. notifications**\n\ +:arrow_right: You will receive every day notifications whenever it's\ +time to BeReal.\n:warning: You may unsubscribe at any time using `/unsubscribe`.", + ephemeral=True, + ) + else: + await interaction.response.send_message( + ":information_source: You are already subscribed to **BeReal. notifications**\ +\n:warning: You may unsubscribe at any time using `/unsubscribe`.", + ephemeral=True, + ) + + +async def setup(app: commands.Bot) -> None: + await app.add_cog(SubscribeCommand(app)) diff --git a/bot/commands/UnsubscribeCommand.py b/bot/commands/UnsubscribeCommand.py new file mode 100644 index 0000000..f908296 --- /dev/null +++ b/bot/commands/UnsubscribeCommand.py @@ -0,0 +1,31 @@ +import discord +from discord import app_commands +from discord.ext import commands + + +class UnsubscribeCommand(commands.Cog): + def __init__(self, app: commands.Bot) -> None: + self.app = app + + @app_commands.command( + name="unsubscribe", description="Unsubscribe to BeReal. notifications." + ) + async def unsubscribe(self, interaction: discord.Interaction) -> None: + result = self.app.db.remove_subscriber(interaction.user.id) + if result: + await interaction.response.send_message( + ":information_source: You have been unsubscribed to **BeReal. notifications**\n\ +:arrow_right: You will **no longer receive** every day notifications whenever it's\ +time to BeReal.\n:warning: You may re-subscribe at any time using `/subscribe`.", + ephemeral=True, + ) + else: + await interaction.response.send_message( + ":information_source: You are already not subscribed to **BeReal. notifications**\ +\n:warning: You may subscribe at any time using `/subscribe`.", + ephemeral=True, + ) + + +async def setup(app: commands.Bot) -> None: + await app.add_cog(UnsubscribeCommand(app)) diff --git a/database.db.exemple b/database.db.exemple new file mode 100644 index 0000000..6938bf7 Binary files /dev/null and b/database.db.exemple differ diff --git a/database/Subscriber.py b/database/Subscriber.py new file mode 100644 index 0000000..a638d80 --- /dev/null +++ b/database/Subscriber.py @@ -0,0 +1,8 @@ +from dataclasses import dataclass + + +@dataclass +class Subscriber: + id: int + user_id: int + since: str diff --git a/database/controller.py b/database/controller.py new file mode 100644 index 0000000..cb18825 --- /dev/null +++ b/database/controller.py @@ -0,0 +1,40 @@ +import sqlite3 +from database.Subscriber import Subscriber + +db = sqlite3.connect("database.db") + + +class Database: + def __init__(self, filename: str) -> None: + db = sqlite3.connect(filename) + + def add_subscriber(self, user_id=int): + cursor = db.cursor() + cursor.execute("SELECT user_id FROM subscribers WHERE user_id = ?", (user_id,)) + result = cursor.fetchone() + if result: + return False + else: + cursor.execute( + "INSERT INTO subscribers (user_id, since) VALUES (?, DATETIME('now'))", + (user_id,), + ) + db.commit() + return True + + def get_subscribers(self): + cursor = db.cursor() + cursor.execute("SELECT user_id FROM subscribers") + result = cursor.fetchall() + return [Subscriber(id=row[0], user_id=row[1], since=row[2]) for row in result] + + def remove_subscriber(self, user_id=int): + cursor = db.cursor() + cursor.execute("SELECT user_id FROM subscribers WHERE user_id = ?", (user_id,)) + result = cursor.fetchone() + if result: + cursor.execute("DELETE FROM subscribers WHERE user_id = ?", (user_id,)) + db.commit() + return True + else: + return False diff --git a/main.py b/main.py new file mode 100644 index 0000000..6d5c2a0 --- /dev/null +++ b/main.py @@ -0,0 +1,17 @@ +import os +from dotenv import load_dotenv + +load_dotenv() + +from bot.app import app +from webserver.webapp import webapp + +PORT = os.environ.get("PORT") + + +@app.listen() +async def on_ready(): + app.loop.create_task(webapp.run_task("0.0.0.0", PORT)) + + +app.run(os.environ.get("DISCORD_TOKEN")) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8269411 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +quart +discord.py +python-dotenv diff --git a/webserver/page/bereal_time.py b/webserver/page/bereal_time.py new file mode 100644 index 0000000..c151c17 --- /dev/null +++ b/webserver/page/bereal_time.py @@ -0,0 +1,19 @@ +from quart import Blueprint, render_template, jsonify, request + +bereal_time = Blueprint("bereal_time", __name__, template_folder="templates") + + +@bereal_time.route("/post", methods=["POST"]) +async def time_to_bereal(): + # May be coming from those IPs: + # 66.228.40.136 (us-east1.dbsrv.net) + # 2600:3c03::f03c:92ff:febe:a263/64 + # fe80::f03c:92ff:febe:a263/64 + + data = await request.get_json() + return {"error": 200, "message": "Success"} + + +@bereal_time.errorhandler(405) +async def method_not_allowed(e): + return jsonify({"error": 405, "message": "Method not allowed"}), 405 diff --git a/webserver/webapp.py b/webserver/webapp.py new file mode 100644 index 0000000..b217873 --- /dev/null +++ b/webserver/webapp.py @@ -0,0 +1,6 @@ +from quart import Quart + +from webserver.page.bereal_time import bereal_time + +webapp = Quart(__name__) +webapp.register_blueprint(bereal_time, url_prefix="/time_to_bereal")