diff --git a/backend/src/__init__.py b/backend/src/__init__.py index 0650e51..d50c229 100644 --- a/backend/src/__init__.py +++ b/backend/src/__init__.py @@ -22,7 +22,15 @@ counterNs, ) -namespaces = [aliasNs, discordNs, keyNs, quotesNs, albumsNs, lastFmNs, counterNs] +namespaces = [ + aliasNs, + discordNs, + keyNs, + quotesNs, + albumsNs, + lastFmNs, + counterNs, +] isDev = os.getenv("FLASK_ENV", "PROD") == "development" BOT_API_TOKEN = os.getenv("BOT_API_TOKEN", "BOT_API_TOKEN") # DISCORD_ID = os.getenv("DISCORD_CLIENT_ID", "DISCORD_CLIENT_ID") @@ -30,26 +38,26 @@ def create_app(config_class=Config): - myApp = Flask(__name__) - myApp.config.from_object(config_class) - api.init_app(myApp) + my_app = Flask(__name__) + my_app.config.from_object(config_class) + api.init_app(my_app) for ns in namespaces: api.add_namespace(ns) - db.init_app(myApp) - migrate.init_app(myApp, db) - if "SECRET_KEY" in os.environ and not app.config["TESTING"]: - myApp.secret_key = os.environ["SECRET_KEY"] + db.init_app(my_app) + migrate.init_app(my_app, db) + if "SECRET_KEY" in os.environ and not my_app.config["TESTING"]: + my_app.secret_key = os.environ["SECRET_KEY"] else: - myApp.logger.warning( + my_app.logger.warning( "PLEASE SET A SECRET KEY, USING A DEFAULT KEY IS SAD TIMES" ) - myApp.secret_key = "supersekrit" + my_app.secret_key = "supersekrit" # blueprint = make_discord_blueprint( # client_id=DISCORD_ID, client_secret=DISCORD_SECRET, scope=["identify", "guilds"] # ) # app.register_blueprint(blueprint, url_prefix="/login") - return myApp + return my_app app = create_app(Config) diff --git a/backend/src/routes/quotes.py b/backend/src/routes/quotes.py index a4f0b87..ce50a58 100644 --- a/backend/src/routes/quotes.py +++ b/backend/src/routes/quotes.py @@ -1,8 +1,7 @@ -from flask_restplus import Namespace from flask import request +from flask_restplus import Namespace, Resource, fields, abort from src import db -from src.models import Quotes, DiscordServer, ServerGroup -from flask_restplus import Resource, fields, abort +from src.models import Quotes from sqlalchemy.sql import func from src.utils import server_group_join, get_group_id @@ -19,8 +18,22 @@ ) +def apply_search_query(query, search): + """ + Applies the given search string as a LIKE %% filter on the given query. + If the search string is None/empty, returns the original query + """ + if search: + search_lower = search.lower() + return query.filter( + func.lower(Quotes.quote_str).like(f"%{search_lower}%") + | func.lower(Quotes.author).like(f"%{search_lower}%") + ) + return query + + @ns.route("//") -@ns.param("server_type", "The sever type (discord, irc, etc)") +@ns.param("server_type", "The server type (discord, irc, etc)") @ns.param("server_id", "The id of the server") class QuoteList(Resource): "Shows all Quotes and lets you post to add a new one" @@ -28,6 +41,7 @@ class QuoteList(Resource): @ns.doc("list_quotes") @ns.marshal_with(quoteModel) def get(self, server_type, server_id): + # Could potentially add a ?search= param here too, to filter the list return server_group_join(Quotes, server_type, server_id).all() @ns.doc("create_quote") @@ -50,7 +64,9 @@ def post(self, server_type, server_id): def get_quote(server_type, server_id, quote_id): quote = ( - server_group_join(Quotes, server_type, server_id).filter(Quotes.id == quote_id) + server_group_join(Quotes, server_type, server_id).filter( + Quotes.id == quote_id + ) ).first() if quote is None: abort(404, f"quote with id {quote_id} does not exist") @@ -77,19 +93,23 @@ def delete(self, server_type, server_id, quote_id): return "" -@ns.route("///") -class QuiteSearchRoute(Resource): - @ns.doc("get_search_quote") +@ns.route("///random") +@ns.param("server_type", "The server type (discord, irc, etc)") +@ns.param("server_id", "The id of the server") +class QuoteRandomRoute(Resource): + @ns.doc("get_random_quote") @ns.marshal_with(quoteModel) - def get(self, server_type, server_id, search_str): - search_str = search_str.lower() - searchOr = func.lower(Quotes.quote_str).like(f"%{search_str}%") | func.lower( - Quotes.author - ).like(f"%{search_str}%") - quotes = ( - server_group_join(Quotes, server_type, server_id).filter(searchOr).all() + def get(self, server_type, server_id): + search = request.args.get("search") + quote = ( + apply_search_query( + server_group_join(Quotes, server_type, server_id), search + ) + .order_by(func.random()) + .limit(1) + .first() ) - if quotes is None or len(quotes) == 0: - abort(404, f"quote not found") - else: - return quotes + + if quote: + return quote + abort(404, f"no quotes") diff --git a/bot/thiccBot/cogs/quotes.py b/bot/thiccBot/cogs/quotes.py index 16060f6..797dd24 100644 --- a/bot/thiccBot/cogs/quotes.py +++ b/bot/thiccBot/cogs/quotes.py @@ -1,17 +1,13 @@ from discord.ext import commands -import discord from thiccBot.cogs.utils import checks from thiccBot.cogs.utils.paginator import Pages -from thiccBot.cogs.utils.logError import log_and_send_error -import random import logging -from pprint import pprint log = logging.getLogger(__name__) -def get_str(quote_str, author): - return f'"{quote_str}" - {author}' +def format_quote(quote): + return f'"{quote["quote"]}" - {quote["author"]}' class Quotes(commands.Cog): @@ -22,16 +18,19 @@ async def get_rand_quote(self, ctx): server_id = ctx.guild.id async def on_200(r): - data = await r.json() - quoute_info = random.choice(data) - await ctx.send(get_str(quoute_info["quote"], quoute_info["author"])) + quote = await r.json() + await ctx.send(format_quote(quote)) + + async def on_404(r): + await ctx.send("No quotes") await self.bot.request_helper( "get", - f"/quotes/discord/{server_id}", + f"/quotes/discord/{server_id}/random", ctx, error_prefix="Error getting quotes", success_function=on_200, + error_handler={404: on_404}, ) @commands.group(name="quotes", aliases=["quote"]) @@ -47,17 +46,19 @@ async def quote_search(self, ctx, search: str): server_id = ctx.guild.id async def on_200(r): - data = await r.json() - chosen = random.choice(data) - await ctx.send(get_str(chosen["quote"], chosen["author"])) + quote = await r.json() + await ctx.send(format_quote(quote)) + + async def on_404(r): + await ctx.send("No quotes") - # TODO: specific error when quote is not found await self.bot.request_helper( "get", - f"/quotes/discord/{server_id}/{search}", + f"/quotes/discord/{server_id}/random?search={search}", ctx, error_prefix="Error searching for quotes", success_function=on_200, + error_handler={404: on_404}, ) @quotes.command(name="list") @@ -65,8 +66,8 @@ async def quotes_list(self, ctx): """List all the quotes for this server""" server_id = ctx.guild.id - def quote_page_entry(quoute_info): - return f"{quoute_info['id']}: {get_str(quoute_info['quote'], quoute_info['author'])}" + def quote_page_entry(quote_info): + return f"{quote_info['id']}: {format_quote(quote_info)}" async def on_200(r): data = await r.json() @@ -96,7 +97,8 @@ async def quote_save(self, ctx, quote_str: str, author: str): server_id = ctx.guild.id async def on_200(r): - await ctx.send(f"Saved quote: {get_str(quote_str, author)}") + quote = await r.json() + await ctx.send(f"Saved quote: {format_quote(quote)}") await self.bot.request_helper( "post", @@ -111,7 +113,7 @@ async def on_200(r): @checks.is_bot_admin() async def quote_delete(self, ctx, quote_id): """Deletes the specified quote - + Pass the quote id to delete, you can get them by using \"quote list\" """ server_id = ctx.guild.id