pissbot-9000/commands/message/search/maps.js
2025-02-17 17:23:08 +01:00

224 lines
No EOL
7.2 KiB
JavaScript

const { maps, mapsSupplemental } = require('#api');
const { PERMISSION_GROUPS } = require('#constants');
const { hexToDecimalColor } = require("#utils/color");
const { createEmbed } = require('#utils/embed');
const { acknowledge } = require('#utils/interactions');
const { link, icon, iconAsEmojiObject, citation, stringwrap } = require('#utils/markdown');
const { editOrReply } = require('#utils/message')
const { STATICS, STATIC_ASSETS } = require('#utils/statics')
const { Components } = require('detritus-client/lib/utils');
function renderPlaceCard(context, place) {
let cards = [createEmbed("defaultNoFooter", context, {
author: {
iconUrl: place.style.icon.url,
name: place.title,
url: place.url
},
description: `${place.address.full}`,
url: place.url,
color: hexToDecimalColor(place.style.color)
})]
if (place.display_type) {
cards[0].description = `-# ${place.display_type}\n\n` + cards[0].description
}
if (place.ratings?.score) {
let ratingString = "";
ratingString += icon("maps_star").repeat(Math.floor(place.ratings.score))
if (place.ratings.score < 5) {
if ((place.ratings.score - Math.floor(place.ratings.score)) >= 0.5) ratingString += icon("maps_star_half")
else ratingString += icon("maps_star_empty");
ratingString += icon("maps_star_empty").repeat(5 - Math.ceil(place.ratings.score))
}
cards[0].description += `\n\n> -# ${ratingString} **${place.ratings.score}** (${link(place.ratings.url, place.ratings.reviews.toLocaleString("en-US"), "Amount of user reviews")})`
}
if (place.description) {
cards[0].description += `\n\n${place.description}`
}
if(place.facts?.length) {
let fc = 1;
cards[0].fields = place.facts.map((f)=>{
let factField = {
name: f.label,
value: f.value,
inline: true
}
if(f.source){
factField.value += citation(fc++, f.source.url, f.source.label)
}
return factField;
})
}
if (place.photos?.length) {
cards[0].image = {
url: place.photos.shift()
}
if (place.photos.length) {
for (const p of place.photos) {
cards.push({
url: place.url,
image: {
url: p
}
})
}
}
}
return cards;
}
module.exports = {
name: 'maps',
aliases: ['m','map','googlemaps','gm'],
label: 'query',
metadata: {
description: 'Searches for places on Google Maps.',
description_short: 'Search google maps',
examples: ['m Empire State Building', 'm waffle houses near pentagon'],
category: 'search',
usage: 'maps <query>',
slashCommand: "maps"
},
permissionsClient: [...PERMISSION_GROUPS.baseline],
run: async (context, args) => {
await acknowledge(context);
if (!args.query) return editOrReply(context, createEmbed("warning", context, `Missing Parameter (query).`))
try {
let search = await maps(context, args.query)
search = search.response.body
// Create initial response page
let embeds = [];
let mapCard = createEmbed("default", context, {
image: {
url: search.assets.map
},
footer: {
iconUrl: STATICS.googlemaps,
text: `Map Data ©${new Date().getFullYear()} Google • ${context.application.name}`
}
})
embeds.push(mapCard)
let components = [];
// Instant Place Result
if (search.place) {
embeds = [...embeds, ...renderPlaceCard(context, search.place)]
} else {
let supplementalCache = {}
components = new Components({
timeout: 100000,
onTimeout: async()=>{
if(!context.response.deleted) await editOrReply({ embeds: context.response.embeds })
},
run: async (ctx) => {
if (ctx.userId !== context.userId) return await ctx.respond(InteractionCallbackTypes.DEFERRED_UPDATE_MESSAGE);
try {
// Disable component and update the default
let value = ctx.data.values[0];
let searchSupplemental;
for (let i = 0; i < components.components[0].components[0].options.length; i++) {
let c = components.components[0].components[0];
components.components[0].components[0].options[i].default = (components.components[0].components[0].options[i].value == value)
components.components[0].components[0].options[i].emoji = iconAsEmojiObject(`maps_${search.places[i].place.icon}_pin`)
// make the selected pin red
if(c.options[i].value === value) components.components[0].components[0].options[i].emoji = iconAsEmojiObject(`maps_location_pin`);
}
if (!supplementalCache[value]) {
components.components[0].components[0].disabled = true;
await ctx.editOrRespond({
embeds: [mapCard, createEmbed("defaultNoFooter", context, {
image: {
url: STATIC_ASSETS.chat_loading
}
})],
components
})
searchSupplemental = await mapsSupplemental(context, search.places[parseInt(value)].supplemental_key)
searchSupplemental = searchSupplemental.response.body
supplementalCache[value] = searchSupplemental
components.components[0].components[0].disabled = false;
} else {
searchSupplemental = supplementalCache[value]
}
mapCard = createEmbed("default", context, {
image: {
url: searchSupplemental.assets.map
},
footer: {
iconUrl: STATICS.googlemaps,
text: `Map Data ©${new Date().getFullYear()} Google • ${context.application.name}`
}
})
await ctx.editOrRespond({
embeds: [mapCard, ...renderPlaceCard(context, searchSupplemental.place)],
components
})
} catch (e) {
console.log(e)
components.components[0].components[0].disabled = false;
await ctx.editOrRespond({
embeds: [mapCard, createEmbed("error", context, "Something went wrong trying to view this place.")],
components
})
}
}
})
components.addSelectMenu({
type: 3,
custom_id: "place-picker",
placeholder: "Select a place",
defaultValues: [],
options: search.places.map((p, i) => ({
label: stringwrap(p.place.name, 100),
value: `${i}`,
emoji: icon(`maps_${p.place.icon}_pin`),
description: stringwrap(p.place.address, 100)
}))
})
}
return await editOrReply(context, {
embeds,
components
})
} catch (e) {
if (e.response?.body?.status && e.response.body.status == 2 && e.response.body.message) return editOrReply(context, createEmbed("warning", context, e.response.body.message))
console.log(JSON.stringify(e.raw) || e)
return editOrReply(context, createEmbed("error", context, `Something went wrong.`))
}
},
};