[nextgen] implement timeout

This commit is contained in:
bignutty 2025-02-11 22:05:38 +01:00
parent c2630da9e2
commit 4e62cecf0f
2 changed files with 65 additions and 30 deletions

View file

@ -7,6 +7,8 @@ const { acknowledge } = require('#utils/interactions');
const { smallPill, link, pill, stringwrap, stringwrapPreserveWords} = require('#utils/markdown');
const { editOrReply } = require('#utils/message');
const DynamicCardStack = require("../../../labscore/cardstack/DynamicCardStack");
function renderAnimeResultsPage(context, res){
let result = createEmbed("default", context, {
author: {
@ -57,7 +59,8 @@ function renderAnimeResultsPage(context, res){
}
return page(result, {}, {
episodes_key: res.supplemental.episodes
episodes_key: res.supplemental.episodes,
name: res.title
});
}
@ -94,9 +97,8 @@ module.exports = {
if(!pages.length) return editOrReply(context, createEmbed("warning", context, `No results found.`))
await paginator.createPaginator({
context,
pages: formatPaginationEmbeds(pages),
new DynamicCardStack(context, {
cards: formatPaginationEmbeds(pages),
interactive: {
episodes_button: {
// Button Label
@ -107,16 +109,36 @@ module.exports = {
condition: (page)=>{
return (page.getState("episodes_key") !== null)
},
renderLoadingState: (pg) => {
return createEmbed("default", context, {
description: `-# ${pg.getState("name")} > **Episodes**`,
image: {
url: `https://bignutty.gitlab.io/webstorage4/v2/assets/loading/04_chat_loading.1zn1ocfb72tc.gif`
}
})
},
// Will resolve all conditions at paginator creation time
precompute_conditions: true,
resolvePage: (page)=>{
resolvePage: (pg)=>{
// If an interactive button for this index hasn't been
// resolved yet, run this code
page.getState("episodes_key"); // -> supplemental key
pg.getState("episodes_key"); // -> supplemental key
/* Resolve supplemental key via api */
console.log("get episodes for " + pg.getState("episodes_key"))
return [...cards];
let i = 0;
return [
createEmbed("default", context, {
description: `-# ${pg.getState("name")} > **Episodes**\n\nepisode page ${i++}`,
}),
createEmbed("default", context, {
description: `-# ${pg.getState("name")} > **Episodes**\n\nepisode page ${i++}`,
}),
createEmbed("default", context, {
description: `-# ${pg.getState("name")} > **Episodes**\n\nepisode page ${i++}`,
})
].map((p)=>page(p));
}
},
characters_button: {

View file

@ -34,6 +34,7 @@ class DynamicCardStack {
* @param {Object} options.interactive Interactive Components
* @param {Number} options.startingIndex Starting card index
* @param {boolean} options.loop Wrap paging
* @param {number} options.expires CardStack timeout
*/
constructor(context, options){
this.context = context;
@ -44,22 +45,28 @@ class DynamicCardStack {
this.index = options.startingIndex || 0;
this.rootIndex = this.index;
this.loopPages = options.loop || true;
this.expires = options.expires || 1*60*1000;
this.uniqueId = (Date.now()*Math.random()).toString(36);
this.pageState = [];
this.subcategoryState = SUBCATEGORY_STATE_TYPES.SINGLE_PAGE;
this.currentSelectedSubcategory = null;
console.log("now spawning")
console.log("now spawning " + this.uniqueId)
this._spawn();
}
/**
* Kills the dynamic card stack.
*/
kill(){
async kill(clearComponents){
console.log("killing " + this.uniqueId)
clearTimeout(this.timeout);
// Remove reference to free the paginator for GC
if(clearComponents) await this._edit(this.currentPage(), [])
// Remove reference to free the cardstack for GC
activeStacks.delete(this.context.message?.id);
}
@ -73,8 +80,9 @@ class DynamicCardStack {
}
_createDynamicCardStack(){
// Kill any previously active paginators
// Kill any previously active cardstacks
if(activeStacks.get(this.context.message?.id)){
console.log(this.uniqueId + " is replacing " + this._getStackByMessageId(this.context.message?.id).uniqueId);
this._getStackByMessageId(this.context.message?.id).kill();
}
@ -82,7 +90,7 @@ class DynamicCardStack {
}
/**
* Creates a new paginator in the given channel
* Creates a new cardstack in the given channel
*/
_spawn(){
try{
@ -94,7 +102,6 @@ class DynamicCardStack {
let i = 0;
for(const ac of this.cards){
if(ac["_meta"]){
console.log(ac)
this.pageState[i] = Object.assign({}, ac["_meta"]);
}
i++;
@ -109,11 +116,15 @@ class DynamicCardStack {
}
})
this.timeout = setTimeout(()=>{
console.log(this.uniqueId + " timed out.")
this.kill(true);
}, this.expires)
return this._edit({
...this.getCurrentCard(),
components: this.listener
}, true);
});
}catch(e){
console.log(e)
}
@ -153,17 +164,22 @@ class DynamicCardStack {
* Edits the cardstack message.
* Automatically applies and rerenders components.
* @param {Message} cardContent Card Content
* @param {boolean, Array} components Custom Components Array
*/
async _edit(cardContent){
async _edit(cardContent, components = false){
let message = Object.assign({}, cardContent);
this.listener.components = this._renderComponents();
message.components = this.listener;
if(!components){
this.listener.components = this._renderComponents();
message.components = this.listener;
} else {
message.components = components;
}
if(message["_meta"]) delete message["_meta"];
console.log("GOING OUT:")
console.log(JSON.stringify(message, null, 2))
//console.log("GOING OUT:")
//console.log(JSON.stringify(message, null, 2))
try{
return editOrReply(this.context, {
@ -177,7 +193,6 @@ class DynamicCardStack {
}
getCurrentCard(){
console.log(this.activeCardStack[this.index])
return this.activeCardStack[this.index];
}
@ -193,6 +208,7 @@ class DynamicCardStack {
*/
getState(key){
if(!this.pageState[this.rootIndex]) return null;
if(!this.pageState[this.rootIndex][key]) return null;
return this.pageState[this.rootIndex][key];
}
@ -209,8 +225,6 @@ class DynamicCardStack {
// First Row always starts with built-in components
for(const b of this.buttons){
console.log("len: " + this.activeCardStack.length)
console.log(this.activeCardStack)
let btn = {
type: MessageComponentTypes.BUTTON,
customId: b,
@ -237,6 +251,8 @@ class DynamicCardStack {
disabled: disabled
}
if(button.condition && typeof(button.condition) == "function") component.disabled = !button.condition(this);
if(button.label){
if(typeof(button.label) === "function") component.label = button.label(this);
else component.label = button.label;
@ -250,7 +266,6 @@ class DynamicCardStack {
else nComponentsSecondary.addButton(component);
}
console.log(JSON.stringify(nComponents))
if(nComponentsSecondary.components.length >= 1) return [nComponents, nComponentsSecondary]
return [nComponents];
}
@ -260,7 +275,6 @@ class DynamicCardStack {
* @param {ComponentContext} ctx
*/
async _handleInteraction(ctx){
console.log(ctx.data.customId)
// should be a built-in button
if(["next","previous"].includes(ctx.data.customId)){
@ -309,22 +323,21 @@ class DynamicCardStack {
data: Object.assign(processingEmbed, { components: this._renderComponents(true)})
})
console.log("resolve trigger")
try{
// TODO: cache resolved stacks
this.activeCardStack = await this.interactive_components[ctx.data.customId].resolvePage(this);
} catch(e){
this.activeCardStack = [
page(createEmbed("error", ctx, "Stack rendering failed."))
]
console.log("resolve failed:")
console.log(e)
}
console.log("resolve post")
// TODO: allow overriding index
this.index = 0;
console.log("stack resolved")
setTimeout(()=>{
console.log(this.activeCardStack)
return this._edit(Object.assign(this.currentPage(), {components:this.listener}), true)
return this._edit(Object.assign(this.currentPage(), {components:this.listener}))
}, 1500)
return;