started work on extractIcons

This commit is contained in:
flyingtoasters
2025-04-03 12:41:18 -04:00
parent ac8a8a7c31
commit 6f09f9a7f3
6 changed files with 266 additions and 13 deletions

View File

@@ -9,6 +9,7 @@
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"@discordjs/rest": "^2.4.3",
"axios": "^1.8.4",
"discord-interactions": "^4.0.0",
"itty-router": "^5.0.9"
@@ -182,6 +183,62 @@
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@discordjs/collection": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.1.tgz",
"integrity": "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==",
"license": "Apache-2.0",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/discordjs/discord.js?sponsor"
}
},
"node_modules/@discordjs/rest": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.4.3.tgz",
"integrity": "sha512-+SO4RKvWsM+y8uFHgYQrcTl/3+cY02uQOH7/7bKbVZsTfrfpoE62o5p+mmV+s7FVhTX82/kQUGGbu4YlV60RtA==",
"license": "Apache-2.0",
"dependencies": {
"@discordjs/collection": "^2.1.1",
"@discordjs/util": "^1.1.1",
"@sapphire/async-queue": "^1.5.3",
"@sapphire/snowflake": "^3.5.3",
"@vladfrangu/async_event_emitter": "^2.4.6",
"discord-api-types": "^0.37.119",
"magic-bytes.js": "^1.10.0",
"tslib": "^2.6.3",
"undici": "6.21.1"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/discordjs/discord.js?sponsor"
}
},
"node_modules/@discordjs/rest/node_modules/undici": {
"version": "6.21.1",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz",
"integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==",
"license": "MIT",
"engines": {
"node": ">=18.17"
}
},
"node_modules/@discordjs/util": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.1.tgz",
"integrity": "sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g==",
"license": "Apache-2.0",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/discordjs/discord.js?sponsor"
}
},
"node_modules/@emnapi/runtime": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz",
@@ -1309,6 +1366,26 @@
"url": "https://opencollective.com/unts"
}
},
"node_modules/@sapphire/async-queue": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.5.tgz",
"integrity": "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==",
"license": "MIT",
"engines": {
"node": ">=v14.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/@sapphire/snowflake": {
"version": "3.5.5",
"resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.5.tgz",
"integrity": "sha512-xzvBr1Q1c4lCe7i6sRnrofxeO1QTP/LKQ6A6qy0iB4x5yfiSfARMEQEghojzTNALDTcv8En04qYNIco9/K9eZQ==",
"license": "MIT",
"engines": {
"node": ">=v14.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/@sindresorhus/is": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
@@ -1435,6 +1512,16 @@
"@types/node": "*"
}
},
"node_modules/@vladfrangu/async_event_emitter": {
"version": "2.4.6",
"resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.6.tgz",
"integrity": "sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA==",
"license": "MIT",
"engines": {
"node": ">=v14.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/acorn": {
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
@@ -2071,6 +2158,12 @@
"node": ">=0.3.1"
}
},
"node_modules/discord-api-types": {
"version": "0.37.119",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.119.tgz",
"integrity": "sha512-WasbGFXEB+VQWXlo6IpW3oUv73Yuau1Ig4AZF/m13tXcTKnMpc/mHjpztIlz4+BM9FG9BHQkEXiPto3bKduQUg==",
"license": "MIT"
},
"node_modules/discord-interactions": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/discord-interactions/-/discord-interactions-4.0.0.tgz",
@@ -3299,6 +3392,12 @@
"node": ">=8"
}
},
"node_modules/magic-bytes.js": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.10.0.tgz",
"integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==",
"license": "MIT"
},
"node_modules/make-dir": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
@@ -4277,10 +4376,10 @@
}
},
"node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
"dev": true
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
"node_modules/type-check": {
"version": "0.4.0",
@@ -4701,6 +4800,39 @@
}
}
},
"@discordjs/collection": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.1.tgz",
"integrity": "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="
},
"@discordjs/rest": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.4.3.tgz",
"integrity": "sha512-+SO4RKvWsM+y8uFHgYQrcTl/3+cY02uQOH7/7bKbVZsTfrfpoE62o5p+mmV+s7FVhTX82/kQUGGbu4YlV60RtA==",
"requires": {
"@discordjs/collection": "^2.1.1",
"@discordjs/util": "^1.1.1",
"@sapphire/async-queue": "^1.5.3",
"@sapphire/snowflake": "^3.5.3",
"@vladfrangu/async_event_emitter": "^2.4.6",
"discord-api-types": "^0.37.119",
"magic-bytes.js": "^1.10.0",
"tslib": "^2.6.3",
"undici": "6.21.1"
},
"dependencies": {
"undici": {
"version": "6.21.1",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz",
"integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ=="
}
}
},
"@discordjs/util": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.1.tgz",
"integrity": "sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g=="
},
"@emnapi/runtime": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz",
@@ -5259,6 +5391,16 @@
"integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
"dev": true
},
"@sapphire/async-queue": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.5.tgz",
"integrity": "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg=="
},
"@sapphire/snowflake": {
"version": "3.5.5",
"resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.5.tgz",
"integrity": "sha512-xzvBr1Q1c4lCe7i6sRnrofxeO1QTP/LKQ6A6qy0iB4x5yfiSfARMEQEghojzTNALDTcv8En04qYNIco9/K9eZQ=="
},
"@sindresorhus/is": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
@@ -5375,6 +5517,11 @@
"@types/node": "*"
}
},
"@vladfrangu/async_event_emitter": {
"version": "2.4.6",
"resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.6.tgz",
"integrity": "sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA=="
},
"acorn": {
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
@@ -5836,6 +5983,11 @@
"integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
"dev": true
},
"discord-api-types": {
"version": "0.37.119",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.119.tgz",
"integrity": "sha512-WasbGFXEB+VQWXlo6IpW3oUv73Yuau1Ig4AZF/m13tXcTKnMpc/mHjpztIlz4+BM9FG9BHQkEXiPto3bKduQUg=="
},
"discord-interactions": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/discord-interactions/-/discord-interactions-4.0.0.tgz",
@@ -6709,6 +6861,11 @@
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
"dev": true
},
"magic-bytes.js": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.10.0.tgz",
"integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ=="
},
"make-dir": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
@@ -7392,10 +7549,9 @@
}
},
"tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
"dev": true
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"type-check": {
"version": "0.4.0",

View File

@@ -18,6 +18,7 @@
"author": "Justin Beckwith <justin.beckwith@gmail.com>",
"license": "MIT",
"dependencies": {
"@discordjs/rest": "^2.4.3",
"axios": "^1.8.4",
"discord-interactions": "^4.0.0",
"itty-router": "^5.0.9"

View File

@@ -45,6 +45,7 @@ export function INVITE_EXEC(request, env, interaction) {
});
};
/*******************************************
* /ping
*******************************************/
@@ -61,6 +62,7 @@ export function PING_EXEC(request, env, interaction) {
})
};
/*******************************************
* /server
*******************************************/
@@ -81,6 +83,7 @@ Verification level: ${interaction.guild.verificationLevel}`,
})
};
/*******************************************
* /user
*******************************************/
@@ -100,6 +103,7 @@ nickname: ${interaction.member.nick}`,
})
};
/*******************************************
* /yoto-store <url>
* /yoto-store url: https://us.yotoplay.com/products/paw-patrol-pup-pack
@@ -129,6 +133,7 @@ export async function YOTO_STORE_EXEC(request, env, interaction) {
});
}
/*******************************************
* /yoto-playlist <url> <show>
* /yoto-playlist url: https://yoto.io/hMkni?84brH2BNuhyl=e79sopPfwKnBL
@@ -212,9 +217,41 @@ export async function EXTRACT_AUDIO_EXEC(request, env, interaction) {
const markdown = formatDataAsMarkdown(data);
return new JsonResponse({
type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
//flags: InteractionResponseFlags.EPHEMERAL, //only show the message to the user who invoked the command
flags: InteractionResponseFlags.EPHEMERAL, //only show the message to the user who invoked the command
data: {
content: markdown,
}
});
};
/*******************************************
* /extract-icons <url>
* TODO -- this is incomplete
*******************************************/
import { GetIconURLs } from './yotoplaylist.js';
export const EXTRACT_ICONS_COMMAND = {
name: 'extract-icons',
description: 'Get icon files from a playlist URL.\n this is incomplete.',
options: [
{
name: 'url',
description: 'URL of the playlist page. e.g.: https://yoto.io/hMkni?84brH2BNuhyl=e79sopPfwKnBL',
required: true,
type: 3,
}
],
};
export async function EXTRACT_ICONS_EXEC(request, env, interaction) {
const url = interaction.data.options[0].value;
const data = await GetIconURLs(url);
const markdown = formatDataAsMarkdown(data);
return new JsonResponse({
type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
flags: InteractionResponseFlags.EPHEMERAL, //only show the message to the user who invoked the command
data: {
content: markdown,
}
});
};

View File

@@ -1,6 +1,8 @@
import { AWWWW_COMMAND, INVITE_COMMAND, PING_COMMAND, SERVER_COMMAND, USER_COMMAND,
YOTO_STORE_COMMAND, YOTO_PLAYLIST_COMMAND,
EXTRACT_AUDIO_COMMAND,
import { AWWWW_COMMAND, INVITE_COMMAND, SERVER_COMMAND, USER_COMMAND, //non-registered commands
PING_COMMAND, //generic
YOTO_STORE_COMMAND, //public store commands
EXTRACT_AUDIO_COMMAND, YOTO_PLAYLIST_COMMAND, //private playlist commands
EXTRACT_ICONS_COMMAND, //public playlist commands
} from './commands.js';
import dotenv from 'dotenv';
import process from 'node:process';
@@ -33,7 +35,7 @@ const url = `https://discord.com/api/applications/${applicationId}/commands`;
const reg_command = JSON.stringify([PING_COMMAND,
YOTO_STORE_COMMAND, YOTO_PLAYLIST_COMMAND,
EXTRACT_AUDIO_COMMAND,
EXTRACT_AUDIO_COMMAND, EXTRACT_ICONS_COMMAND,
]);
const del_command = JSON.stringify([]);

View File

@@ -18,6 +18,7 @@ import { USER_COMMAND, USER_EXEC } from './commands.js';
import { YOTO_PLAYLIST_COMMAND, YOTO_PLAYLIST_EXEC } from './commands.js';
import { YOTO_STORE_COMMAND, YOTO_STORE_EXEC } from './commands.js';
import { EXTRACT_AUDIO_COMMAND, EXTRACT_AUDIO_EXEC } from './commands.js';
import { EXTRACT_ICONS_COMMAND, EXTRACT_ICONS_EXEC } from './commands.js';
// Import other local requirements
import { JsonResponse } from './jsonresponse.js';
@@ -58,6 +59,10 @@ router.get('/extract-audio', (request, env) => {
return EXTRACT_AUDIO_EXEC(request, env, "webget");
});
router.get('/extract-icons', (request, env) => {
return EXTRACT_ICONS_EXEC(request, env, "webget");
});
/**
* A simple :wave: hello page to verify the worker is working.
*/
@@ -114,11 +119,32 @@ router.post('/', async (request, env) => {
case EXTRACT_AUDIO_COMMAND.name.toLowerCase():{
return EXTRACT_AUDIO_EXEC(request, env, interaction);
}
case EXTRACT_ICONS_COMMAND.name.toLowerCase():{
return EXTRACT_ICONS_EXEC(request, env, interaction);
}
default:
console.error('Unknown Command\n\n');
console.log('Interaction:', interaction);
console.log('Interaction Data:', interaction.data);
console.log('Request', request);
return new JsonResponse({ error: 'Unknown Type' }, { status: 400 });
}
}
if (interaction.type === InteractionType.MESSAGE_COMPONENT) {
// The `MESSAGE_COMPONENT` message is used for all button and select interactions.
console.log('Message Component Interaction:', interaction);
switch (interaction.data.custom_id.toLowerCase()) {
default:
console.error('Unknown Message Component\n\n');
console.log('Interaction:', interaction);
console.log('Interaction Data:', interaction.data);
console.log('Request', request);
return new JsonResponse({ error: 'Unknown Type' }, { status: 400 });
}
}
console.error('Unknown Type');
return new JsonResponse({ error: 'Unknown Type' }, { status: 400 });
});

View File

@@ -54,6 +54,37 @@ export async function GetTrackURLs(url){
}
}
export async function GetIconURLs(url){
try{
// Fetch the content from the provided URL
const response = await axios.get(url);
const contentType = response.headers['content-type'];
let card = response.data?.card;
return extractIcons(card);
} catch (e) {
return { error: e.message || "Error fetching data" };
}
}
function extractIcons(card) {
const data = []; // Declare the data array
//"props.pageProps.card.content.chapters[0].display.icon16x16"
const chapters = card.content?.chapters || [];
chapters.forEach((chapter, chapterIndex) => {
const chapterDisplayInfo = chapter.display; // Get the icon for the chapter
if (chapterDisplayInfo) {
chapter.tracks?.forEach((track, trackIndex) => {
const trackDisplayInfo = track.display; // Look for an icon for the track
const iconUrl = trackDisplayInfo?.icon16x16 || chapterDisplayInfo.icon16x16; // Fallback to chapter icon
// Push the formatted entry into the data collection
data.push(`${chapterIndex}-${trackIndex}: <${track.trackUrl}>`);
}); // Close forEach
}
});
return data; // Return the data array
}
/**
* Extracts track URLs from the card data and formats them as index: url.
*