From 01a10135d89b952989c5333f4151a6f009123d84 Mon Sep 17 00:00:00 2001 From: bignutty <3515180-bignutty@users.noreply.gitlab.com> Date: Wed, 12 Feb 2025 00:53:10 +0100 Subject: [PATCH] [nextgen] implement supplemental data retrieval --- commands/message/search/anime.js | 105 +++++++++++++++++++------------ labscore/utils/markdown.js | 14 ++++- 2 files changed, 78 insertions(+), 41 deletions(-) diff --git a/commands/message/search/anime.js b/commands/message/search/anime.js index 441c4d6..c87d75d 100644 --- a/commands/message/search/anime.js +++ b/commands/message/search/anime.js @@ -1,11 +1,10 @@ -const { anime } = require('#api'); -const { paginator } = require('#client'); -const { PERMISSION_GROUPS, OMNI_ANIME_FORMAT_TYPES, COLORS, COLORS_HEX} = require('#constants'); +const { anime, animeSupplemental} = require('#api'); +const { PERMISSION_GROUPS, OMNI_ANIME_FORMAT_TYPES, COLORS_HEX} = require('#constants'); const { hexToDecimalColor } = require("#utils/color"); const { createEmbed, formatPaginationEmbeds, page } = require('#utils/embed'); const { acknowledge } = require('#utils/interactions'); -const { smallPill, link, pill, stringwrap, stringwrapPreserveWords} = require('#utils/markdown'); +const { smallPill, link, pill, stringwrapPreserveWords, timestamp, TIMESTAMP_FLAGS} = require('#utils/markdown'); const { editOrReply } = require('#utils/message'); const DynamicCardStack = require("../../../labscore/cardstack/DynamicCardStack"); @@ -62,8 +61,10 @@ function renderAnimeResultsPage(context, res){ return page(result, {}, { episodes_key: res.supplemental.episodes, + characters_key: res.supplemental.characters, name: res.title, - color: hexToDecimalColor(res.color || COLORS_HEX.embed) + color: hexToDecimalColor(res.color || COLORS_HEX.embed), + cover: res.cover }); } @@ -91,7 +92,7 @@ module.exports = { let search = await anime(context, args.query, context.channel.nsfw) search = search.response - if(search.body.status == 2) return editOrReply(context, createEmbed("error", context, search.body.message)) + if(search.body.status === 2) return editOrReply(context, createEmbed("error", context, search.body.message)) let pages = [] for(const res of search.body.results){ @@ -109,7 +110,7 @@ module.exports = { // Next to pagination or new row inline: false, visible: true, - condition: (page)=>{ + condition: (page) => { return (page.getState("episodes_key") !== null) }, renderLoadingState: (pg) => { @@ -121,31 +122,35 @@ module.exports = { color: pg.getState("color") }) }, - // Will resolve all conditions at paginator creation time - precompute_conditions: true, - resolvePage: (pg)=>{ - // If an interactive button for this index hasn't been - // resolved yet, run this code - pg.getState("episodes_key"); // -> supplemental key + resolvePage: async (pg) => { + let episodes = await animeSupplemental(context, pg.getState("episodes_key")); - /* Resolve supplemental key via api */ - console.log("get episodes for " + pg.getState("episodes_key")) - - let i = 0; - return [ - createEmbed("default", context, { - description: `-# ${pg.getState("name")} › **Episodes**\n\nepisode page ${i++}`, - color: pg.getState("color") - }), - createEmbed("default", context, { - description: `-# ${pg.getState("name")} › **Episodes**\n\nepisode page ${i++}`, - color: pg.getState("color") - }), - createEmbed("default", context, { - description: `-# ${pg.getState("name")} › **Episodes**\n\nepisode page ${i++}`, - color: pg.getState("color") + let cards = episodes.response.body.episodes.map((e) => { + let card = createEmbed("default", context, { + color: pg.getState("color"), + description: `-# ${pg.getState("name")} › **Episodes**\n## `, + fields: [] }) - ].map((p)=>page(p)); + + // Render episode number if available + if (e.episode) card.description += `${e.episode}: ` + card.description += e.title; + + if (e.description) card.description += `\n\n\n${stringwrapPreserveWords(e.description, 600)}`; + if (e.image) card.image = {url: e.image}; + if (pg.getState("cover")) card.thumbnail = {url: pg.getState("cover")}; + + if (e.duration) card.fields.push({name: "Length", value: e.duration + " min", inline: true}) + if (e.date) card.fields.push({ + name: "Aired", + value: timestamp(e.date, TIMESTAMP_FLAGS.LONG_DATE), + inline: true + }) + + return page(card) + }) + + return formatPaginationEmbeds(cards); } }, characters_button: { @@ -153,24 +158,46 @@ module.exports = { label: "Characters", // Next to pagination or new row inline: false, - condition: (page)=>{ + visible: true, + condition: (page) => { return (page.getState("characters_key") !== null) }, - resolvePage: (page)=>{ - // If an interactive button for this index hasn't been - // resolved yet, run this code - page.getState("characters_key"); // -> supplemental key + renderLoadingState: (pg) => { + return createEmbed("default", context, { + description: `-# ${pg.getState("name")} › **Characters**`, + image: { + url: STATIC_ASSETS.card_skeleton + }, + color: pg.getState("color") + }) + }, + resolvePage: async (pg) => { + let characters = await animeSupplemental(context, pg.getState("characters_key")); - /* Resolve supplemental key via api */ + let cards = characters.response.body.characters.map((c) => { + let card = createEmbed("default", context, { + color: pg.getState("color"), + description: `-# ${pg.getState("name")} › **Characters**\n## ${link(c.url, c.name.full)}`, + fields: [] + }) - return [...cards]; + if (c.description) card.description += `\n\n\n${stringwrapPreserveWords(c.description, 600)}`; + if (c.image) card.image = {url: c.image}; + if (pg.getState("cover")) card.thumbnail = {url: pg.getState("cover")}; + + if (c.age) card.fields.push({name: "Age", value: c.age, inline: true}) + + return page(card) + }) + + return formatPaginationEmbeds(cards); } } } }); }catch(e){ - if(e.response?.body?.status == 1) return editOrReply(context, createEmbed("warning", context, e.response?.body?.message)) - if(e.response?.body?.status == 2) return editOrReply(context, createEmbed("warning", context, e.response?.body?.message)) + if(e.response?.body?.status === 1) return editOrReply(context, createEmbed("warning", context, e.response?.body?.message)) + if(e.response?.body?.status === 2) return editOrReply(context, createEmbed("warning", context, e.response?.body?.message)) console.log(e) return editOrReply(context, createEmbed("error", context, `Unable to perform anime search.`)) diff --git a/labscore/utils/markdown.js b/labscore/utils/markdown.js index fa7422e..28f7f0d 100644 --- a/labscore/utils/markdown.js +++ b/labscore/utils/markdown.js @@ -24,7 +24,7 @@ function _icon(icon){ // Ensures potentially user-provided content won't escape pill components function _escapeCodeblock(content){ - return content.toString().replace(/\`/g, 'ˋ'); + return content.toString().replace(/`/g, 'ˋ'); } module.exports.icon = _icon; @@ -55,7 +55,7 @@ module.exports.weatherIcon = function(icon){ } module.exports.highlight = function(content = ""){ - return "`" + content.toString().replace(/\`/g, 'ˋ') + "`" + return "`" + content.toString().replace(/`/g, 'ˋ') + "`" } /** @@ -76,6 +76,16 @@ module.exports.link = function(url, masked, tooltip = "", embed = false){ return url } +module.exports.TIMESTAMP_FLAGS = Object.freeze({ + SHORT_TIME: "t", + LONG_TIME: "T", + SHORT_DATE: "d", + LONG_DATE: "D", + SHORT_DATE_TIME: "f", + LONG_DATE_TIME: "F", + RELATIVE_TIME: "R" +}) + module.exports.timestamp = function(time, flag = "t"){ return `` }