forwards-long-jump / discotron

Modular Discord bot supporting plugins hosted on git repositories
MIT License
3 stars 5 forks source link

Make the WebAPI REST "compliant" #83

Open Blatoy opened 4 years ago

Blatoy commented 4 years ago

At the moment we only use POST, we should implement the other actions (PUT, GET, PUT, DELETE, ...) and allow to specify which one to use bot-side

Blatoy commented 4 years ago

So far we have:

        webAPI.registerAction("get-guild-admins", (data, reply, discordUserId, discordGuildId) => {
            // Do something...
            reply({});
        }, "guildAdmin");

A suggestion of what we could do:

        webAPI.registerEndpoint("guild-admins", {
            GET: {
                dataFormat: { name: "string", members: "array" }, // Could auto-error if missing ?
                authLevel: "everyone|owner|guildAdmin|loggedIn", // Pick one (work the same as currently)
                action: (data, response, trustedData) => {
                    console.log(data); // {name: "Discotron", members: [...]} follows format defined above, can't be trusted
                    console.log(trustedData); // {userId: "348294829335248", discordGuildId: "45238095809368"} retrieved using app token and check guild permission first, can be trusted
                    response.success({}); // Can reply whatever we want (could maybe have a replyDataFormat as well?)
                    response.error("error message"); // Error message that will be displayed in a popup? The idea is to make it so we don't have to have custom error handling everywhere.
                    // if response not called, auto success if nothing was thrown, otherwise generic error"(we do not want to display default js error messages)
                }
            },
            POST: { /**/ }
        });
Blatoy commented 4 years ago

It would actually probably be better to create one file per endpoint, and automatically use it as the api endpoint name

RedMser commented 4 years ago

Finalized design:

Server side

module.exports = {
    GET: {
        authLevel: "everyone|owner|guildAdmin|loggedIn", // Pick one (work the same as currently)
        /**
         * @param {object} userData Untrusted data by user
         * @param {string} userData.name Name of thing
         * @param {object} trustedData Data by discotron
         * @returns {object} Data for user.
         */
        action: (userData, trustedData) => {
            console.log(userData); // {name: "Discotron", members: [...]} follows format defined above, can't be trusted
            console.log(trustedData); // {userId: "348294829335248", discordGuildId: "45238095809368"} retrieved using app token and check guild permission first, can be trusted
            // GET Must return not-undefined, or auto error, POST / PUT / DELETE don't
            const error = "err";

            userData.guildId // is auth?
            if (error) {
                throw new ClientError("Custom message displayed in the client"); // -> { error: "custom msg" }
            }
            if (error) {
                throw new ClientError({ message: "Lel couldn't pull repo", type: CONSTANT_ERROR_CODE }); // -> { error: {msg: "custom msg", code: 0} }
            }

            return {/* user data */ }; // -> { data: { user data } }
        },
        timeToLive: 6.9 // in minutes
    },
    POST: { /**/ }
};

Client side

function loadGuilds() {
    const g = await webApi.get("guilds");
    // for each g add g to html
}

webApi.clearCache("guild/*");
loadGuilds();

cache = { "guild/admin": [
    { parameters: 
        { "id": "23842394823984" }, 
        cacheData: {} ,
        validUntil: 38459384539458934
    }
    ] 
}

try {
    // Results can be cached if WAIT
    const results = await webApi.get("guild/lock-channel", {guildId: guildId, channels: []});
} catch (err) {
    // err.dsd
}

window.onerror = (err) => {
    if (err instanceof ClientError) {
        // red banner of sad as default error handler
    }
}
RedMser commented 4 years ago
WebAPI.get("guilds/get-admins", {}); // plugin based on where we call this from (check URL)
WebAPI.get("/dashboard/guilds/get-admins", {}); // always dashboard api
WebAPI.get("/plugin-name/test", {}); // plugin's custom endpoint