diff --git a/app.py b/app.py index f85d1b8..03c9c3d 100644 --- a/app.py +++ b/app.py @@ -296,13 +296,37 @@ def badRequest(e): def internalServerError(e): return jsonify({'error': str(e)}), 500 +# why should i have a manifest.json file when i can just make it a route +@api_bp.route("/manifest.json", methods=['GET']) +def pwaManifest(): + # not sure about theme_color but whateva + return jsonify({ + "short_name": const.appName, + "name": cfg['instance']['title'], + "icons": [ + { + "src": url_for("static", filename="icons/favicon/android-chrome-192x192.png"), + "sizes": "192x192", + "type": "image/png" + }, + { + "src": url_for("static", filename="icons/favicon/android-chrome-512x512.png"), + "sizes": "512x512", + "type": "image/png" + } + ], + "start_url": "/", + "display": "standalone", + "theme_color": cfg['style']['accentLight'], + "background_color": "" + }) + # -- question routes -- @api_bp.route('/add_question/', methods=['POST']) def addQuestion(): from_who = request.form.get('from_who', cfg['anonName']) question = request.form.get('question', '') - antispam = request.form.get('antispam', '') cw = request.form.get('cw', '') if not question: @@ -310,32 +334,7 @@ def addQuestion(): if len(question) > int(cfg['charLimit']) or len(from_who) > int(cfg['charLimit']): abort(400, "Question exceeds the character limit") - if not antispam: - abort(400, "Anti-spam word must not be empty") - - antispam_wordlist = func.readPlainFile(const.antiSpamFile, split=True) - antispam_valid = antispam in antispam_wordlist - if not antispam_valid: - # return a generic error message so bad actors wouldn't figure out the antispam list - return {'error': 'An error has occurred'}, 500 - - blacklist = func.readPlainFile(const.blacklistFile, split=True) - - for bad_word in blacklist: - if bad_word in question or bad_word in from_who: - # return a generic error message so bad actors wouldn't figure out the blacklist - return {'error': 'An error has occurred'}, 500 - - conn = func.connectToDb() - cursor = conn.cursor() - - app.logger.debug("[CatAsk/API/add_question] INSERT'ing new question into database") - - cursor.execute("INSERT INTO questions (from_who, content, answered, cw) VALUES (%s, %s, %s, %s)", (from_who, question, False, cw)) - cursor.close() - conn.close() - - return {'message': 'Question asked successfully!'}, 201 + return func.addQuestion(from_who, question, cw) @api_bp.route('/delete_question/', methods=['DELETE']) @loginRequired diff --git a/functions.py b/functions.py index f45761f..1af2327 100644 --- a/functions.py +++ b/functions.py @@ -128,6 +128,75 @@ def getQuestion(question_id: int): conn.close() return question +def addQuestion(from_who, question, cw, noAntispam=False): + + if cfg['antispam']['type'] == 'basic': + antispam = request.form.get('antispam', '') + elif cfg['antispam']['type'] == 'recaptcha': + antispam = request.form.get('g-recaptcha-response', '') + elif cfg['antispam']['type'] == 'turnstile': + antispam = request.form.get('cf-turnstile-response', '') + elif cfg['antispam']['type'] == 'frc': + antispam = request.form.get('frc-captcha-response', '') + + if cfg['antispam']['enabled'] and not noAntispam: + + if cfg['antispam']['type'] == 'basic': + if not antispam: + abort(400, "Anti-spam word must not be empty") + + antispam_wordlist = readPlainFile(const.antiSpamFile, split=True) + antispam_valid = antispam in antispam_wordlist + if not antispam_valid: + # return a generic error message so bad actors wouldn't figure out the antispam list + return {'error': 'An error has occurred'}, 500 + # it's probably bad to hardcode the siteverify urls, but meh, that will do for now + elif cfg['antispam']['type'] == 'recaptcha': + r = requests.post( + 'https://www.google.com/recaptcha/api/siteverify', + data={'response': antispam, 'secret': cfg['antispam']['recaptcha']['secretkey']} + ) + json_r = r.json() + success = json_r['success'] + if not success: + return {'error': 'An error has occurred'}, 500 + elif cfg['antispam']['type'] == 'turnstile': + r = requests.post( + 'https://challenges.cloudflare.com/turnstile/v0/siteverify', + data={'response': antispam, 'secret': cfg['antispam']['turnstile']['secretkey']} + ) + json_r = r.json() + success = json_r['success'] + if not success: + return {'error': 'An error has occurred'}, 500 + elif cfg['antispam']['type'] == 'frc': + url = 'https://global.frcapi.com/api/v2/captcha/siteverify' + headers = {'X-API-Key': cfg['antispam']['frc']['apikey']} + data = {'response': antispam, 'sitekey': cfg['antispam']['frc']['sitekey']} + r = requests.post(url, data=data, headers=headers) + json_r = r.json() + success = json_r['success'] + if not success: + return {'error': 'An error has occurred'}, 500 + + blacklist = readPlainFile(const.blacklistFile, split=True) + + for bad_word in blacklist: + if bad_word in question or bad_word in from_who: + # return a generic error message so bad actors wouldn't figure out the blacklist + return {'error': 'An error has occurred'}, 500 + + conn = connectToDb() + cursor = conn.cursor() + + app.logger.debug("[CatAsk/API/add_question] INSERT'ing new question into database") + + cursor.execute("INSERT INTO questions (from_who, content, answered, cw) VALUES (%s, %s, %s, %s)", (from_who, question, False, cw)) + cursor.close() + conn.close() + + return {'message': 'Question asked successfully!'}, 201 + def getAnswer(question_id: int): conn = connectToDb() cursor = conn.cursor(dictionary=True)