diff --git a/commands/interaction/context/audio.js b/commands/interaction/context/audio.js index 8b55858..c2d3dc4 100644 --- a/commands/interaction/context/audio.js +++ b/commands/interaction/context/audio.js @@ -11,6 +11,14 @@ const urlr = /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\. module.exports = { name: 'Music Platforms', type: ApplicationCommandTypes.MESSAGE, + contexts: [ + 0, + 1, + 2 + ], + integrationTypes: [ + 1 + ], run: async (context, args) => { try{ await context.respond({data: {}, type: InteractionCallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}) diff --git a/commands/interaction/context/ocr.js b/commands/interaction/context/ocr.js index 0ad7e8d..c4e296d 100644 --- a/commands/interaction/context/ocr.js +++ b/commands/interaction/context/ocr.js @@ -11,9 +11,17 @@ const { STATICS } = require('../../../labscore/utils/statics'); module.exports = { name: 'OCR', type: ApplicationCommandTypes.MESSAGE, + contexts: [ + 0, + 1, + 2 + ], + integrationTypes: [ + 1 + ], run: async (context, args) => { try{ - await context.respond({data: { flags: MessageFlags.EPHEMERAL }, type: InteractionCallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}) + await context.respond({data: {}, type: InteractionCallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}) const { message } = args; @@ -23,11 +31,11 @@ module.exports = { } else { delete attachment; } - if(!attachment) return context.editOrRespond({ embeds: [createEmbed("warning", context, "No images found.")], flags: MessageFlags.EPHEMERAL }) + if(!attachment) return context.editOrRespond({ embeds: [createEmbed("warning", context, "No images found.")] }) let ocr = await googleVisionOcr(context, attachment) - if(ocr.response.body.status == 1) return context.editOrRespond({ embeds: [createEmbed("warning", context, ocr.response.body.text)], flags: MessageFlags.EPHEMERAL }) + if(ocr.response.body.status == 1) return context.editOrRespond({ embeds: [createEmbed("warning", context, ocr.response.body.text)] }) await context.editOrRespond({ embeds: [createEmbed("default", context, { @@ -39,8 +47,7 @@ module.exports = { iconUrl: STATICS.google, text: `Google Cloud Vision • ${context.application.name} • Took ${ocr.timings}s` } - })], - flags: MessageFlags.EPHEMERAL + })] }) }catch(e){ console.log(e) diff --git a/commands/interaction/context/ocrtr.js b/commands/interaction/context/ocrtr.js new file mode 100644 index 0000000..ec16043 --- /dev/null +++ b/commands/interaction/context/ocrtr.js @@ -0,0 +1,71 @@ +const { Constants } = require('detritus-client'); +const { InteractionCallbackTypes, ApplicationCommandTypes, MessageFlags } = Constants; + +const { googleVisionOcr, googleTranslate } = require('../../../labscore/api'); +const { getMessageAttachment, validateAttachment } = require('../../../labscore/utils/attachment'); + +const { createEmbed } = require('../../../labscore/utils/embed'); +const { codeblock, icon, pill } = require('../../../labscore/utils/markdown'); +const { STATICS } = require('../../../labscore/utils/statics'); +const { editOrReply } = require('../../../labscore/utils/message'); +const { TRANSLATE_LANGUAGE_MAPPINGS, TRANSLATE_LANGUAGES } = require('../../../labscore/constants'); + +module.exports = { + name: 'OCR Translate', + type: ApplicationCommandTypes.MESSAGE, + contexts: [ + 0, + 1, + 2 + ], + integrationTypes: [ + 1 + ], + run: async (context, args) => { + try{ + await context.respond({data: {}, type: InteractionCallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}) + + const { message } = args; + + let attachment = getMessageAttachment(message) + if(attachment && validateAttachment(attachment, "image")){ + attachment = attachment.url + } else { + delete attachment; + } + if(!attachment) return editOrReply(context, createEmbed("warning", context, "No images found.")) + + let ocr = await googleVisionOcr(context, attachment) + + if(ocr.response.body.status == 1) return editOrReply(context, createEmbed("warning", context, ocr.response.body.text)) + + try{ + let translate = await googleTranslate(context, ocr.response.body.text, "en", "auto") + + let fromFlag = TRANSLATE_LANGUAGE_MAPPINGS[translate.response.body.language.from || sourceLanguage] || '' + let toFlag = TRANSLATE_LANGUAGE_MAPPINGS[translate.response.body.language.to] || '' + + return editOrReply(context, createEmbed("default", context, { + description: `${icon("locale")} ​ ${fromFlag} ${pill(TRANSLATE_LANGUAGES[translate.response.body.language.from || sourceLanguage])} ​ ​ ​​${icon("arrow_right")} ​ ​ ​ ​${toFlag} ${pill(TRANSLATE_LANGUAGES[translate.response.body.language.to])}\n${codeblock("ansi", [translate.response.body.translation.substr(0,4000)])}`, + thumbnail: { + url: attachment + }, + footer: { + iconUrl: STATICS.google, + text: `Google Cloud Vision • ${context.application.name}` + } + })) + }catch(e){ + console.log(e) + if(e.response?.body?.status && e.response.body.status == 2) return editOrReply(context, createEmbed("error", context, `Unable to translate text.`)) + return editOrReply(context, createEmbed("error", context, `Something went wrong.`)) + } + }catch(e){ + console.log(e) + await context.editOrRespond({ + embeds: [createEmbed("error", context, "Unable to perform Optical Character Recognition.")], + flags: MessageFlags.EPHEMERAL + }) + } + }, +}; \ No newline at end of file diff --git a/commands/interaction/slash/info/avatar.js b/commands/interaction/slash/info/avatar.js index 07bd696..a6d7168 100644 --- a/commands/interaction/slash/info/avatar.js +++ b/commands/interaction/slash/info/avatar.js @@ -7,7 +7,15 @@ const { editOrReply } = require('../../../../labscore/utils/message'); module.exports = { description: 'Get someones avatar.', - name: 'avatar', + name: 'avatar2', + contexts: [ + 0, + 1, + 2 + ], + integrationTypes: [ + 1 + ], options: [ { name: 'user', diff --git a/commands/interaction/slash/search/google-images.js b/commands/interaction/slash/search/google-images.js new file mode 100644 index 0000000..b62de8b --- /dev/null +++ b/commands/interaction/slash/search/google-images.js @@ -0,0 +1,74 @@ +const { createEmbed, formatPaginationEmbeds, page } = require('../../../../labscore/utils/embed') +const { editOrReply } = require('../../../../labscore/utils/message') +const { STATICS } = require('../../../../labscore/utils/statics') + +const { paginator } = require('../../../../labscore/client'); +const { googleImages } = require('../../../../labscore/api'); + +const { ApplicationCommandOptionTypes, InteractionCallbackTypes } = require('detritus-client/lib/constants'); + +function createImageResultPage(context, result) { + let res = page(createEmbed("default", context, { + author: { + iconUrl: `https://www.google.com/s2/favicons?domain=${encodeURIComponent(result.url)}&sz=256`, + name: result.title, + url: result.url + }, + image: { + url: result.image + }, + footer: { + iconUrl: STATICS.google, + text: `Google Images • ${context.application.name}` + } + })) + if (result.thumbnail) res.embeds[0].thumbnail = { url: result.thumbnail }; + return res; +} + +module.exports = { + name: 'image', + label: 'query', + aliases: ['i', 'img'], + description: 'Search the web for images on Google.', + contexts: [ + 0, + 1, + 2 + ], + integrationTypes: [ + 1 + ], + options: [ + { + name: 'query', + description: 'Image search query.', + type: ApplicationCommandOptionTypes.TEXT, + required: true + } + ], + run: async (context, args) => { + await context.respond({data: {}, type: InteractionCallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}) + + try { + let search = await googleImages(context, args.query, false) //safesearch is always on + search = search.response + + if (search.body.status == 2) return editOrReply(context, createEmbed("error", context, search.body.message)) + + let pages = [] + for (const res of search.body.results) { + pages.push(createImageResultPage(context, res)) + } + + if (!pages.length) return editOrReply(context, createEmbed("warning", context, `No results found.`)) + await paginator.createPaginator({ + context, + pages: formatPaginationEmbeds(pages) + }); + } catch (e) { + console.log(e) + return editOrReply(context, createEmbed("error", context, `Unable to perform google search.`)) + } + }, +}; \ No newline at end of file diff --git a/commands/interaction/slash/search/google.js b/commands/interaction/slash/search/google.js new file mode 100644 index 0000000..c475206 --- /dev/null +++ b/commands/interaction/slash/search/google.js @@ -0,0 +1,100 @@ +const { createEmbed, formatPaginationEmbeds, page } = require('../../../../labscore/utils/embed') +const { link, citation } = require('../../../../labscore/utils/markdown') +const { editOrReply } = require('../../../../labscore/utils/message') +const { STATICS } = require('../../../../labscore/utils/statics') + +const { paginator } = require('../../../../labscore/client'); +const { google } = require('../../../../labscore/api'); + +const { ApplicationCommandOptionTypes, InteractionCallbackTypes } = require('detritus-client/lib/constants'); + +function createSearchResultPage(context, result){ + let res; + switch(result.type){ + case 1: // Search Result Entry + res = page(createEmbed("default", context, { + author: { + iconUrl: `https://www.google.com/s2/favicons?domain=${encodeURIComponent(result.url)}&sz=256`, + name: result.title, + url: result.url + }, + description: result.content, + footer: { + iconUrl: STATICS.google, + text: `Google • ${context.application.name}` + } + })) + + if(result.thumbnail) res.embeds[0].thumbnail = { url: result.thumbnail }; + break; + case 2: // Knowledge Graph Entry + let header = result.card.title; + if(result.card.url) header = link(result.card.url, result.card.title) + res = page(createEmbed("default", context, { + description: `**${header}**\n`, + footer: { + iconUrl: STATICS.google, + text: `Google Knowledge Graph • ${context.application.name}` + } + })) + + if(result.card.image) res.embeds[0].thumbnail = { url: result.card.image }; + if(result.card.description) res.embeds[0].description += `*${result.card.description}*\n` + if(result.card.content){ + let cnt = result.card.content.replace(/\n/g, '') + if(cnt.endsWith(" ")) cnt = cnt.substr(0,cnt.length - 1) + res.embeds[0].description += "\n" + cnt + citation(1, result.card.url, "Source") + } + break; + default: + res = page(createEmbed("error", context, "Unknown GoogleResult Type: " + result.type)) + break; + } + return res; +} + +module.exports = { + name: 'google', + description: 'Search Google for websites.', + contexts: [ + 0, + 1, + 2 + ], + integrationTypes: [ + 1 + ], + options: [ + { + name: 'query', + description: 'Google search query.', + type: ApplicationCommandOptionTypes.TEXT, + required: true + } + ], + run: async (context, args) => { + await context.respond({data: {}, type: InteractionCallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}) + + try{ + let search = await google(context, args.query, false) // safe search is always on + search = search.response + + if(search.body.status == 2) return editOrReply(context, createEmbed("error", context, search.body.message)) + + let pages = [] + for(const res of search.body.results){ + pages.push(createSearchResultPage(context, res)) + } + + if(!pages.length) return editOrReply(context, createEmbed("warning", context, `No results found.`)) + + await paginator.createPaginator({ + context, + pages: formatPaginationEmbeds(pages) + }); + }catch(e){ + console.log(e) + return editOrReply(context, createEmbed("error", context, `Unable to perform google search.`)) + } + }, +}; \ No newline at end of file diff --git a/commands/interaction/slash/search/lyrics.js b/commands/interaction/slash/search/lyrics.js new file mode 100644 index 0000000..b954574 --- /dev/null +++ b/commands/interaction/slash/search/lyrics.js @@ -0,0 +1,102 @@ +const { createEmbed, formatPaginationEmbeds, page } = require('../../../../labscore/utils/embed') +const { editOrReply } = require('../../../../labscore/utils/message') +const { STATICS } = require('../../../../labscore/utils/statics') + +const { lyrics } = require('../../../../labscore/api'); +const { paginator } = require('../../../../labscore/client'); + +const { ApplicationCommandOptionTypes, InteractionCallbackTypes } = require('detritus-client/lib/constants'); +const { smallIconPill } = require('../../../../labscore/utils/markdown'); + +const META_FIELDS = { + "Album": "stat_videos", + "Released": "note" +} + +function renderMetadata(metadata){ + const pills = [] + for(const m of metadata){ + if(!META_FIELDS[m.id]) continue; + pills.push(smallIconPill(META_FIELDS[m.id], `${m.id}: ${m.value}`)) + } + return pills.join(' ') +} + +function createLyricsPage(context, search, fields){ + let em = createEmbed("default", context, { + author: { + iconUrl: search.body.track.artist_cover, + name: `${search.body.track.title} by ${search.body.track.artist}` + }, + fields: fields, + footer: { + iconUrl: STATICS.musixmatch, + text: `Musixmatch • ${context.application.name}` + } + }) + if(search.body.track.cover) em.thumbnail = { url: search.body.track.cover } + if(search.body.track.metadata.length) em.description = renderMetadata(search.body.track.metadata) + return em; +} + +module.exports = { + name: 'lyrics', + description: 'Search for song lyrics.', + contexts: [ + 0, + 1, + 2 + ], + integrationTypes: [ + 1 + ], + options: [ + { + name: 'query', + description: 'Song name or partial lyrics.', + type: ApplicationCommandOptionTypes.TEXT, + required: true + } + ], + run: async (context, args) => { + await context.respond({data: {}, type: InteractionCallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}) + + try{ + let search = await lyrics(context, args.query) + search = search.response + + if(search.body.status == 2) return editOrReply(context, createEmbed("error", context, search.body.message)) + let fields = []; + + for(const f of search.body.lyrics.split('\n\n')){ + fields.push({ + name: '​', + value: f, + inline: false + }) + } + + let pages = [] + while(fields.length) { + let pageFields = fields.splice(0,3) + + // Display less fields if they take up too much vertical space + while(pageFields.map((f)=>f.value).join('\n').split('\n').length >= 30 && pageFields[1]){ + fields.unshift(pageFields[pageFields.length - 1]) + pageFields = pageFields.splice(0, pageFields.length - 1) + } + + pages.push(page(createLyricsPage(context, search, pageFields))) + } + + await paginator.createPaginator({ + context, + pages: formatPaginationEmbeds(pages) + }); + }catch(e){ + if(e.response?.body?.status && e.response.body.status == 2 && e.response.body.message) return editOrReply(context, createEmbed("error", context, e.response.body.message)) + console.log(JSON.stringify(e.raw)) + return editOrReply(context, createEmbed("error", context, `Something went wrong.`)) + } + }, +}; \ No newline at end of file diff --git a/commands/interaction/slash/search/wolfram-alpha.js b/commands/interaction/slash/search/wolfram-alpha.js new file mode 100644 index 0000000..6b1cf31 --- /dev/null +++ b/commands/interaction/slash/search/wolfram-alpha.js @@ -0,0 +1,84 @@ +const { createEmbed, formatPaginationEmbeds, page } = require('../../../../labscore/utils/embed') +const { editOrReply } = require('../../../../labscore/utils/message') +const { STATICS } = require('../../../../labscore/utils/statics') + +const { paginator } = require('../../../../labscore/client'); +const { wolframAlpha } = require('../../../../labscore/api'); +const { citation } = require('../../../../labscore/utils/markdown'); + +const { ApplicationCommandOptionTypes, InteractionCallbackTypes } = require('detritus-client/lib/constants'); + +function createWolframPage(context, pod, query, sources) { + let res = page(createEmbed("default", context, { + author: { + name: pod.title, + url: `https://www.wolframalpha.com/input?i=${encodeURIComponent(query)}` + }, + description: undefined, + footer: { + iconUrl: STATICS.wolframalpha, + text: `Wolfram|Alpha • ${context.application.name}` + } + })) + if (pod.icon) res.embeds[0].author.iconUrl = pod.icon + if (pod.value) res.embeds[0].description = pod.value.substr(0, 1000) + if (pod.value && pod.refs) { + for (const r of pod.refs) { + let src = Object.values(sources).filter((s) => s.ref == r)[0] + if (!src) continue; + + // Only add a direct source if one is available + if (src.collections) { + res.embeds[0].description += citation(r, src.url, src.title + ' | ' + src.collections[0].text) + continue; + } + if (src.url) res.embeds[0].description += citation(r, src.url, src.title) + } + } + if (pod.image) res.embeds[0].image = { url: pod.image }; + return res; +} + +module.exports = { + name: 'wolframalpha', + description: 'Compute a query via Wolfram|Alpha.', + contexts: [ + 0, + 1, + 2 + ], + integrationTypes: [ + 1 + ], + options: [ + { + name: 'query', + description: 'Computational Query.', + type: ApplicationCommandOptionTypes.TEXT, + required: true + } + ], + run: async (context, args) => { + await context.respond({data: {}, type: InteractionCallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}) + + try { + let search = await wolframAlpha(context, args.query) + search = search.response + + if (search.body.status == 1) return editOrReply(context, createEmbed("warning", context, search.body.message)) + + let pages = [] + for (const res of search.body.data) { + pages.push(createWolframPage(context, res, args.query, search.body.sources)) + } + + await paginator.createPaginator({ + context, + pages: formatPaginationEmbeds(pages) + }); + } catch (e) { + console.log(e) + return editOrReply(context, createEmbed("error", context, `Unable to perform Wolfram|Alpha search.`)) + } + }, +}; \ No newline at end of file diff --git a/commands/interaction/slash/utils/dictionary.js b/commands/interaction/slash/utils/dictionary.js new file mode 100644 index 0000000..dbf5617 --- /dev/null +++ b/commands/interaction/slash/utils/dictionary.js @@ -0,0 +1,97 @@ +const { createEmbed, formatPaginationEmbeds, page } = require('../../../../labscore/utils/embed') +const { link, iconPill, smallPill, icon, iconLinkPill, pill } = require('../../../../labscore/utils/markdown') +const { editOrReply } = require('../../../../labscore/utils/message') + +const { paginator } = require('../../../../labscore/client'); +const { dictionary } = require('../../../../labscore/api'); + +const { ApplicationCommandOptionTypes, InteractionCallbackTypes } = require('detritus-client/lib/constants'); +const { TRANSLATE_LANGUAGE_MAPPINGS, DICTIONARY_LANGUAGES } = require('../../../../labscore/constants'); + +const LABELS = { + "offensive": `${iconPill("warning", "Offensive")}` +} + +function createDictionaryPage(context, result, index, language){ + let phon = '' + if(result.phonetic) phon = `\n*${result.phonetic}*` + + let e = createEmbed("default", context, { + description: `${icon("definition")} **${link(`https://en.wiktionary.org/wiki/${encodeURIComponent(result.word)}`, result.word, "Definition on Wiktionary")}**`, + fields: [] + }) + + if(result.phonetic) e.description += smallPill(result.phonetic) + + if(language !== "en") e.description += `\n${TRANSLATE_LANGUAGE_MAPPINGS[language]} ${pill(DICTIONARY_LANGUAGES[language])}` + + let word = result.entries[index] + let defItms = [] + + + let i = 1; + for(const def of word.definitions.splice(0, 6)){ + let entry = `${i}. ${def.definition}` + if(def.example) entry += `\n - *${def.example}*` + if(def.synonyms) entry += `\n${icon("empty")}${def.synonyms.splice(0, 4).map((s)=>smallPill(s)).join(' ')}` + defItms.push(entry) + i++ + } + + if(word.definitions.length >= 6 ) defItms.push(iconLinkPill("link", `https://www.google.com/search?q=define+${encodeURIComponent(result.word)}`, 'More results', 'View More Results')) + + let type = word.type + if(word.labels) type += " " + word.labels.map((label)=>{if(LABELS[label]) return LABELS[label]; else return ""}).join(' ') + + e.description += `\n\n**${type}**\n${defItms.join('\n\n')}` + + return page(e); +} + +module.exports = { + name: 'define', + description: 'Look up the definition of a word in the dictionary.', + contexts: [ + 0, + 1, + 2 + ], + integrationTypes: [ + 1 + ], + options: [ + { + name: 'term', + description: 'Term to look up.', + type: ApplicationCommandOptionTypes.TEXT, + required: true + } + ], + run: async (context, args) => { + await context.respond({data: {}, type: InteractionCallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}) + + try{ + let search = await dictionary(context, args.term, "en") + search = search.response + + if(search.body.status == 1) return editOrReply(context, createEmbed("warning", context, search.body.message)) + + let pages = [] + + let i = 0; + for(const d of search.body.results[0].entries){ + pages.push(createDictionaryPage(context, search.body.results[0], i, "en")) + i++; + } + + await paginator.createPaginator({ + context, + pages: formatPaginationEmbeds(pages) + }); + }catch(e){ + console.log(e) + if(e.response?.body?.status && e.response.body.status == 2) return editOrReply(context, createEmbed("warning", context, e.response.body.message)) + return editOrReply(context, createEmbed("error", context, `Unable to perform dictionary lookup.`)) + } + }, +}; \ No newline at end of file diff --git a/commands/interaction/slash/utils/screenshot.js b/commands/interaction/slash/utils/screenshot.js new file mode 100644 index 0000000..97a1d6b --- /dev/null +++ b/commands/interaction/slash/utils/screenshot.js @@ -0,0 +1,61 @@ +const { createEmbed } = require("../../../../labscore/utils/embed"); +const { editOrReply } = require("../../../../labscore/utils/message"); + +const { webshot } = require("../../../../labscore/api/obelisk"); + +const { ApplicationCommandOptionTypes, InteractionCallbackTypes } = require('detritus-client/lib/constants'); + +module.exports = { + name: 'screenshot', + description: 'Create a screenshot of a website.', + contexts: [ + 0, + 1, + 2 + ], + integrationTypes: [ + 1 + ], + options: [ + { + name: 'url', + description: 'Website URL.', + type: ApplicationCommandOptionTypes.TEXT, + required: true + } + ], + run: async (context, args) => { + await context.respond({data: {}, type: InteractionCallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}) + + await editOrReply(context, createEmbed("loading", context, `Creating website screenshot...`)) + + try { + const t = Date.now(); + + let ss = await webshot(context, args.url, context.channel.nsfw) + + if (ss.response.body.status && ss.response.body.status !== 3) { + if (ss.response.body.image) return await editOrReply(context, + createEmbed("image", context, { + url: ss.response.body.image, + time: ((Date.now() - t) / 1000).toFixed(2) + }) + ) + return await editOrReply(context, createEmbed("error", context, "Unable to create screenshot.")) + } + + return await editOrReply(context, { + embeds: [createEmbed("image", context, { + url: "screenshot.png", + time: ((Date.now() - t) / 1000).toFixed(2) + })], + files: [{ filename: "screenshot.png", value: ss.response.body }] + }) + } catch (e) { + console.log(e) + return await editOrReply(context, createEmbed("image", context, { + url: "https://bignutty.gitlab.io/webstorage4/v2/assets/screenshot/brand-update-2024/scr_unavailable.png" + })) + } + } +}; \ No newline at end of file diff --git a/commands/interaction/slash/utils/weather.js b/commands/interaction/slash/utils/weather.js new file mode 100644 index 0000000..f000314 --- /dev/null +++ b/commands/interaction/slash/utils/weather.js @@ -0,0 +1,76 @@ +const { createEmbed } = require('../../../../labscore/utils/embed') +const { editOrReply } = require('../../../../labscore/utils/message') + +const { darksky } = require('../../../../labscore/api'); +const { pill, iconPill, smallPill, weatherIcon, timestamp } = require('../../../../labscore/utils/markdown'); + +const { ApplicationCommandOptionTypes, InteractionCallbackTypes } = require('detritus-client/lib/constants'); +const { STATICS } = require('../../../../labscore/utils/statics'); + +module.exports = { + name: 'weather', + description: 'Check the weather at a location.', + contexts: [ + 0, + 1, + 2 + ], + integrationTypes: [ + 1 + ], + options: [ + { + name: 'location', + description: 'City or place to check.', + type: ApplicationCommandOptionTypes.TEXT, + required: true + } + ], + run: async (context, args) => { + await context.respond({data: {}, type: InteractionCallbackTypes.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE}) + + try{ + let data = await darksky(context, args.location) + + data = data.response.body + + let description = `### ${weatherIcon(data.result.current.icon.id)} ​ ​ ​ ​ ${Math.floor(data.result.current.temperature.current)}°C • ${data.result.current.condition.label}\n\n${pill("Feels like")} ${smallPill(Math.floor(data.result.current.temperature.feels_like) + "°C")} ​ ​ ​ ​ ${pill("Wind")} ${smallPill(data.result.current.wind.speed + " km/h")}` + + let secondaryPills = []; + if(data.result.current.humidity > 0) secondaryPills.push(`${pill("Humidity")} ${smallPill(Math.floor(data.result.current.humidity * 100) + "%")}`) + if(data.result.current.uvindex > 0) secondaryPills.push(`${pill("UV Index")} ${smallPill(data.result.current.uvindex)}`) + + if(secondaryPills.length >= 1) description += '\n' + secondaryPills.join(` ​ ​ ​ ​ `) + + description += `\n\n${iconPill("sun", "Sunrise")} ${timestamp(data.result.current.sun.sunrise, "t")} ​ ​ ${iconPill("moon", "Sunset")} ${timestamp(data.result.current.sun.sunset, "t")}` + + // Render Forecasts + description += `\n` + for(const i of data.result.forecast){ + description += `\n${pill(i.day)} ​ ​ ${weatherIcon(i.icon)}` + if(Math.floor(i.temperature.max).toString().length == 1) description += `${pill(Math.floor(i.temperature.max) + "°C ")}` + else description += `${pill(Math.floor(i.temperature.max) + "°C")}` + description += `​**/**​` + if(Math.floor(i.temperature.min).toString().length == 1) description += `${smallPill(Math.floor(i.temperature.min) + "°C ")}` + else description += `${smallPill(Math.floor(i.temperature.min) + "°C")}` + } + + + let e = createEmbed("default", context, { + description, + timestamp: new Date(data.result.current.date) + }) + + e.footer.iconUrl = STATICS.weather + if(data.result.location) e.footer.text = data.result.location //+ " • " + context.client.user.username + + if(data.result.current.icon) e.thumbnail = { url: data.result.current.icon.url } + if(data.result.current.image) e.image = { url: data.result.current.image } + + return editOrReply(context, e) + }catch(e){ + console.log(e) + return editOrReply(context, createEmbed("warning", context, `No weather data available for given location.`)) + } + }, +}; \ No newline at end of file diff --git a/labscore/paginator/structures/BasePaginator.js b/labscore/paginator/structures/BasePaginator.js index cbb9535..5c72d0d 100644 --- a/labscore/paginator/structures/BasePaginator.js +++ b/labscore/paginator/structures/BasePaginator.js @@ -9,9 +9,16 @@ module.exports = class BasePaginator extends EventEmitter { this.commandMessage = data.commandMessage || null; this.pages = data.pages; this.index = 0; - this.targetUser = data.targetUser || this.message.author.id; - this.editOrReply = data.context.editOrReply.bind(data.context); + this.targetUser = data.targetUser || this.message?.author?.id || data.context?.user?.id; + + this.isInteractionPaginator = false; + this.editOrReply; + if(data.context.editOrReply) this.editOrReply = data.context.editOrReply.bind(data.context); + if(data.context.editOrRespond){ + this.editOrReply = data.context.editOrRespond.bind(data.context); + this.isInteractionPaginator = true; + } } static asMessage(ctx) { @@ -39,12 +46,13 @@ module.exports = class BasePaginator extends EventEmitter { } async update(data) { + if(this.isInteractionPaginator) return; if (this.isShared) { for (const m of this.commandMessage.values()) { if(!m.deleted) await m.edit(data); } } else if (this.commandMessage) { - if(!this.commandMessage.deleted) this.commandMessage.edit(data); + if(!this.commandMessage.deleted) this.commandMessage.edit(data).catch((e)=>{}); } } diff --git a/labscore/paginator/structures/Paginator.js b/labscore/paginator/structures/Paginator.js index 10ca176..f14e800 100644 --- a/labscore/paginator/structures/Paginator.js +++ b/labscore/paginator/structures/Paginator.js @@ -153,7 +153,7 @@ module.exports = class Paginator { if (!(l instanceof InteractionPaginator)) continue; if (!l.commandMessage) continue; - if (l.isCommandMessage(data.context.message.id)) { + if (data.context.message?.id && l.isCommandMessage(data.context.message.id)) { listener = l } } diff --git a/labscore/utils/embed.js b/labscore/utils/embed.js index 9ba7f6b..e47cf5c 100644 --- a/labscore/utils/embed.js +++ b/labscore/utils/embed.js @@ -164,7 +164,10 @@ module.exports.formatPaginationEmbeds = function(embeds){ formatted.push(ne) } else if (e.embeds){ ne.embeds = e.embeds.map((se)=>{ - se.footer.text = se.footer.text + ` • Page ${i}/${l}` + if(se.footer) se.footer.text = se.footer.text + ` • Page ${i}/${l}` + else se.footer = { + text: `Page ${i}/${l}` + } return se; })