From 0695343e650c01240fa2b1b878f25eabbb142694 Mon Sep 17 00:00:00 2001 From: niansa Date: Mon, 11 Jan 2021 17:00:46 +0100 Subject: [PATCH] Fixes --- config.h | 1 + controllers/views.cc | 110 +++++++++++++++++++++++++++++------------- controllers/views.h | 4 +- views/botregister.csp | 10 ++-- 4 files changed, 84 insertions(+), 41 deletions(-) diff --git a/config.h b/config.h index 935bb82..019c571 100644 --- a/config.h +++ b/config.h @@ -12,3 +12,4 @@ #define CLIENT_ID "797565592835457024" #define CLIENT_SECRET "8ZbKPseob8n1UmLLunPb06MNUKfPGRi1" #define REDIRECT_URI "http://localhost:8082/discordauth" +#define BOT_TOKEN "Nzk3NTY1NTkyODM1NDU3MDI0.X_oU1w.fCVL8j58pphoEaU7e3q4yH7cFa4" diff --git a/controllers/views.cc b/controllers/views.cc index b5ae9b5..9a3d4ed 100644 --- a/controllers/views.cc +++ b/controllers/views.cc @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include "../config.h" @@ -18,17 +19,6 @@ static unordered_map last_votes; -views::views() { - db = drogon::app().getDbClient(); -} - -void views::start( - const HttpRequestPtr&, std::function &&callback - ) -{ - callback(HttpResponse::newRedirectionResponse("/bots/@all", HttpStatusCode::k301MovedPermanently)); -} - Bot deserializeBot(orm::Row row) { Bot thisbot; # define sf(f) thisbot.f = row[#f] @@ -58,8 +48,50 @@ std::string dbEsc(const std::string& src) { return fres.str(); } +auto errPage(const std::exception& e) { + HttpViewData data; + data.insert("message", e.what()); + + auto resp = HttpResponse::newHttpViewResponse("exception.csp", data); + resp->setStatusCode(HttpStatusCode::k500InternalServerError); + return resp; +} + +void getUser(uint64_t user_id, std::function callback) { + auto discordapi = HttpClient::newHttpClient("https://discord.com"); + auto req = HttpRequest::newHttpRequest(); + req->setPath("/api/v8/users/"+std::to_string(user_id)); + req->setMethod(HttpMethod::Get); + req->addHeader("Authorization", "Bot " BOT_TOKEN); + discordapi->sendRequest(req, [callback, user_id] (ReqResult, const HttpResponsePtr &response) { + if (response->getStatusCode() == HttpStatusCode::k200OK) { + auto &json = *response->getJsonObject().get(); + auto avatar_hash = json["avatar"].asString(); + if (avatar_hash.empty()) { + json["avatar_url"] = "https://cdn.discordapp.com/embed/avatars/"+std::to_string(std::stoi(json["discriminator"].asString()) % 5)+".png"; + } else { + json["avatar_url"] = "https://cdn.discordapp.com/avatars/"+std::to_string(user_id)+"/"+avatar_hash+".png"; + } + callback(json); + } else { + callback({}); + } + }); +} + auto dbErr = [](const orm::DrogonDbException &) {}; +views::views() { + db = drogon::app().getDbClient(); +} + +void views::start( + const HttpRequestPtr&, std::function &&callback + ) +{ + callback(HttpResponse::newRedirectionResponse("/bots/@all", HttpStatusCode::k301MovedPermanently)); +} + void LoginFilter::doFilter(const HttpRequestPtr &req, FilterCallback &&fcb, FilterChainCallback &&fccb) { if (req->session()->isAuthed()) { fccb(); @@ -153,12 +185,13 @@ void views::botvote(const HttpRequestPtr& req, std::function &&callback - ) { +void views::botregister_view(const HttpRequestPtr& req, std::function &&callback, + const std::string& error) { auto session = req->session(); // Display page HttpViewData data; data.insert("owner", session->get("discord_user_fullname")); + data.insert("error", error); callback(HttpResponse::newHttpViewResponse("botregister.csp", data)); } @@ -166,33 +199,42 @@ void views::botregister_submit(const HttpRequestPtr& req, std::functionsession(); // Get and check parameters - auto onError = [callback] (const std::exception& e) { - HttpViewData data; - data.insert("message", e.what()); - - auto resp = HttpResponse::newHttpViewResponse("exception.csp", data); - resp->setStatusCode(HttpStatusCode::k500InternalServerError); - callback(resp); + auto onError = [callback] (const std::string& e) { + callback(HttpResponse::newRedirectionResponse("register?error="+e)); }; try { - auto name = req->getParameter("name"); + auto app_id = std::stoul(req->getParameter("app_id")); auto short_description = req->getParameter("short_description"); auto long_description = req->getParameter("long_description"); - auto avatar_url = req->getParameter("avatar_url"); auto support_server = req->getParameter("support_server"); auto prefix = req->getParameter("prefix"); - auto app_id = std::stoul(req->getParameter("app_id")); - // Perform database operation - db->execSqlAsync(fmt::format("INSERT INTO bots (name, short_description, long_description, avatar_url, owner, support_server, prefix, owner_id, app_id, votes, approved) " - "VALUES('{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', 0, 'f')", - dbEsc(name), dbEsc(short_description), dbEsc(long_description), dbEsc(avatar_url), session->get("discord_user_fullname"), dbEsc(support_server), dbEsc(prefix), session->get("discord_user_id"), app_id), - [app_id, callback] (const orm::Result &) { - callback(HttpResponse::newRedirectionResponse(std::to_string(app_id)+"/detail")); - }, [onError] (const orm::DrogonDbException &e) { - onError(e.base()); - }); - } catch (std::exception& e) { - onError(e); + // Check if bot already exists + db->execSqlAsync("select 1 from bots where app_id ='"+std::to_string(app_id)+"'", + [=] (const orm::Result &r) { + if (not r.empty()) { + onError("Bot%20has%20already%20been%20registered"); + return; + } + // Get bots avatar + getUser(app_id, [=] (const Json::Value& botuser) { + // Check result + if (botuser.empty() or not botuser["bot"].asBool()) { + onError("Invalid%20client%20ID"); + return; + } + // Perform database operation + db->execSqlAsync(fmt::format("INSERT INTO bots (name, short_description, long_description, avatar_url, owner, support_server, prefix, owner_id, app_id, votes, approved) " + "VALUES('{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', 0, 'f')", + dbEsc(botuser["username"].asString()), dbEsc(short_description), dbEsc(long_description), dbEsc(botuser["avatar_url"].asString()), session->get("discord_user_fullname"), dbEsc(support_server), dbEsc(prefix), session->get("discord_user_id"), app_id), + [app_id, callback] (const orm::Result &) { + callback(HttpResponse::newRedirectionResponse(std::to_string(app_id)+"/detail")); + }, [onError] (const orm::DrogonDbException &e) { + onError(e.base().what()); + }); + }); + }, dbErr); + } catch (std::exception& e) { + onError(e.what()); } } diff --git a/controllers/views.h b/controllers/views.h index 5da07b9..327463f 100644 --- a/controllers/views.h +++ b/controllers/views.h @@ -27,7 +27,7 @@ public: void botlist(const HttpRequestPtr&, std::function &&); void botdetail(const HttpRequestPtr&, std::function &&, uint64_t); void botvote(const HttpRequestPtr&, std::function &&, uint64_t); - void botregister_view(const HttpRequestPtr&, std::function &&); + void botregister_view(const HttpRequestPtr&, std::function &&, const std::string&); void botregister_submit(const HttpRequestPtr&, std::function &&); void discordauth(const HttpRequestPtr&, std::function &&, const std::string&); void discorddeauth(const HttpRequestPtr&, std::function &&); @@ -36,7 +36,7 @@ public: ADD_METHOD_TO(views::start, "/", Get); ADD_METHOD_TO(views::botlist, "/bots/@all", Get); ADD_METHOD_TO(views::botlist, "/bots/@me", Get, "LoginFilter"); - ADD_METHOD_TO(views::botregister_view, "/bots/register", Get, "LoginFilter"); + ADD_METHOD_TO(views::botregister_view, "/bots/register?error={1}", Get, "LoginFilter"); ADD_METHOD_TO(views::botregister_submit, "/bots/register", Post, "LoginFilter"); ADD_METHOD_TO(views::botdetail, "/bots/{1}/detail", Get); ADD_METHOD_TO(views::botvote, "/bots/{1}/vote", Get, "LoginFilter"); diff --git a/views/botregister.csp b/views/botregister.csp index 0f39219..4e943ea 100644 --- a/views/botregister.csp +++ b/views/botregister.csp @@ -1,4 +1,5 @@ <%c++ auto owner = @@.get("owner");%> +<%c++ auto error = @@.get("error");%> @@ -14,14 +15,13 @@

Registering a bot

-

Name

-

Owner

-

Avatar URL

-

Short description

+ {%error%} +

Client ID

+

Short description

Long description

Prefix

Permanent support server invite code

-

Client ID

+

Owner