commands/handlers/releases-handler.js

const { RAWG_API_BASE, RAWG_BASE } = require('../../config.json');

/**
 * Releases Command
 * @namespace releases
 * @memberof Commands
 */

/**
 * Get list of releases
 * @param {{year: number, month: number, ...args}} - Request parameters 
 * @returns {{name: string, slug: string, released: string}[]}
 * @memberof Commands.releases
 */
const getReleasesFromRAWG = async ({ year = new Date(Date.now()).getFullYear(), month = new Date(Date.now()).getMonth(), size = 25, ...args } = {}) => {
    return await fetch(
        `${RAWG_API_BASE}/games/calendar/${year}/${month}?`
        + new URLSearchParams({
            key: process.env.RAWG_TOKEN,
            // for some reason 'added' is the popularity ordering, where the top of '-added' is the most popular
            ordering: '-added',
            popular: 'true',
            page_size: size,
            ...args
        }));
}

/**
 * Tranform game release details to text
 * @param {{name: string, slug: string, released: string}} game Game details
 * @returns {string}
 * @memberof Commands.releases
 */
const getTextFromGameDetail = (game) => {
    return `\t• <a href="${RAWG_BASE}/games/${game?.slug}">${game.name}</a>`
        + (game?.released ? ` — ${(new Date(game.released)).toLocaleDateString('ru-RU')}` : '' )
        + '\n';
}

/**
 * Transform a list of game release detail to a single text
 * @param {{name: string, slug: string, released: string}[]} list List of game details
 * @returns {string}
 * @memberof Commands.releases
 */
const transformReleasesList = (list) => {
    return list
        // need to sort by date, since ordered by popilarity
        .sort((a, b) => a.released.split('-')[2] - b.released.split('-')[2])
        .reduce((acc, game) => acc += `${getTextFromGameDetail(game)}`, 'Релизы:\n');
}

/**
 * @type {Common.CommandDefintion}
 * @memberof Commands.releases
 */
exports.definition = {
    command_name: 'releases',
    args: [
        {
            name: 'query',
            type: 'string',
            description: 'Дата в формате год-месяц, например 2008-07',
            optional: true
        }
    ],
    limit: 1,
    is_inline: true,
    description: 'Возвраащет список релизов из RAWG.io'
};
/**
 * @type {boolean}
 * @memberof Commands.releases
 */
exports.condition = !!process.env.RAWG_TOKEN;

/**
 * @type {Common.CommandHandler}
 * @memberof Commands.releases
 */
exports.handler = async (interaction) => {
    const arg = interaction.args?.[0];
    
    let year, month;

    if (!arg?.match(/\d{4}-\d{1,2}/)?.length) {
        // use current date instead
        // return {
        //     type: 'error',
        //     text: 'Для запроса нужно предоставить дату, например <code>2008-07</code>.'
        // }
        const date = new Date(Date.now());
        [year, month] = [date.getFullYear(), date.getMonth()];
    }
    else {
        [[_, year, month]] = [...arg.matchAll(/(?<year>\d{4})-(?<month>\d{1,2})/g)];
    }


    return getReleasesFromRAWG({ year, month })
        .then(async (res) => {
            interaction.logger.silly(`Received response from RAWG/games/calendar`);
            if (!res.ok) {
                interaction.logger.error(`Non-200 response from RAWG [status:${res.status}] [statusText:${res.statusText}]`, { api_response: JSON.stringify(res)});
                return {
                    type: 'error',
                    text: 'Что-то не задалось с поиском, попробуй ещё раз'
                };
            }
            let json = await res.json();
            if (!json?.results?.length) {
                return {
                    type: 'error',
                    text: 'Не смог ничего найти, попробуй другой запрос'
                };
            }

            const releases = [...json.results];

            return {
                type: 'text',
                text: transformReleasesList(releases),
                overrides: {
                    followup: { text: 'Полный список', url: `${RAWG_BASE}/video-game-releases/${year}-${month}` }
                }
            };
        })
        .catch((err) => {
            interaction.logger.error(`Error while getting release calendar from RAWG`, { error: err.stack || err});
            throw err;
        });
};