booru
This commit is contained in:
parent
2f09b99d0b
commit
2eaadf2208
9 changed files with 224 additions and 31 deletions
|
@ -8,6 +8,7 @@
|
|||
"author": "",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"booru": "^2.6.8",
|
||||
"discord.js": "^14.16.3",
|
||||
"dotenv": "^16.4.5",
|
||||
"groq-sdk": "^0.7.0"
|
||||
|
|
|
@ -8,6 +8,9 @@ importers:
|
|||
|
||||
.:
|
||||
dependencies:
|
||||
booru:
|
||||
specifier: ^2.6.8
|
||||
version: 2.6.8
|
||||
discord.js:
|
||||
specifier: ^14.16.3
|
||||
version: 14.16.3
|
||||
|
@ -17,9 +20,6 @@ importers:
|
|||
groq-sdk:
|
||||
specifier: ^0.7.0
|
||||
version: 0.7.0
|
||||
uwuifier:
|
||||
specifier: ^4.2.2
|
||||
version: 4.2.2
|
||||
|
||||
packages:
|
||||
|
||||
|
@ -90,6 +90,10 @@ packages:
|
|||
asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
|
||||
booru@2.6.8:
|
||||
resolution: {integrity: sha512-/MN9Q5Yd3jBvOXgG05SLsdbGHFUWx6yoLYKU0xIoTWDsNlliUqM8Aj581pBujqFhg4E/Pi9cHdpMRN/FqustUA==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
|
||||
combined-stream@1.0.8:
|
||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
@ -122,6 +126,10 @@ packages:
|
|||
fast-deep-equal@3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||
|
||||
fast-xml-parser@4.5.0:
|
||||
resolution: {integrity: sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==}
|
||||
hasBin: true
|
||||
|
||||
form-data-encoder@1.7.2:
|
||||
resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==}
|
||||
|
||||
|
@ -172,6 +180,9 @@ packages:
|
|||
encoding:
|
||||
optional: true
|
||||
|
||||
strnum@1.0.5:
|
||||
resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==}
|
||||
|
||||
tr46@0.0.3:
|
||||
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||
|
||||
|
@ -191,9 +202,6 @@ packages:
|
|||
resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==}
|
||||
engines: {node: '>=18.17'}
|
||||
|
||||
uwuifier@4.2.2:
|
||||
resolution: {integrity: sha512-Fhtj3Yg3rrDTEs+L1fqkgM3VYGJrP4U9GY+4fPdw08T5kzOB8NSosZnZfa5Zhv1Hh7NCpH5G6t1DIZyM1wPK1w==}
|
||||
|
||||
web-streams-polyfill@4.0.0-beta.3:
|
||||
resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==}
|
||||
engines: {node: '>= 14'}
|
||||
|
@ -303,6 +311,11 @@ snapshots:
|
|||
|
||||
asynckit@0.4.0: {}
|
||||
|
||||
booru@2.6.8:
|
||||
dependencies:
|
||||
fast-xml-parser: 4.5.0
|
||||
undici: 6.19.8
|
||||
|
||||
combined-stream@1.0.8:
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
|
@ -339,6 +352,10 @@ snapshots:
|
|||
|
||||
fast-deep-equal@3.1.3: {}
|
||||
|
||||
fast-xml-parser@4.5.0:
|
||||
dependencies:
|
||||
strnum: 1.0.5
|
||||
|
||||
form-data-encoder@1.7.2: {}
|
||||
|
||||
form-data@4.0.0:
|
||||
|
@ -388,6 +405,8 @@ snapshots:
|
|||
dependencies:
|
||||
whatwg-url: 5.0.0
|
||||
|
||||
strnum@1.0.5: {}
|
||||
|
||||
tr46@0.0.3: {}
|
||||
|
||||
ts-mixer@6.0.4: {}
|
||||
|
@ -400,8 +419,6 @@ snapshots:
|
|||
|
||||
undici@6.19.8: {}
|
||||
|
||||
uwuifier@4.2.2: {}
|
||||
|
||||
web-streams-polyfill@4.0.0-beta.3: {}
|
||||
|
||||
webidl-conversions@3.0.1: {}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const { ContextMenuCommandBuilder, ApplicationCommandType, InteractionContextType, ApplicationIntegrationType, AttachmentBuilder, EmbedBuilder } = require('discord.js');
|
||||
const { ContextMenuCommandBuilder, ApplicationCommandType, InteractionContextType, ApplicationIntegrationType, AttachmentBuilder, EmbedBuilder } = require("discord.js");
|
||||
|
||||
const data = new ContextMenuCommandBuilder()
|
||||
.setName('Describe Image(s)')
|
||||
.setName("Describe Image(s)")
|
||||
.setType(ApplicationCommandType.Message)
|
||||
.setContexts([
|
||||
InteractionContextType.Guild,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const { ContextMenuCommandBuilder, ApplicationCommandType, InteractionContextType, ApplicationIntegrationType } = require('discord.js');
|
||||
const { ContextMenuCommandBuilder, ApplicationCommandType, InteractionContextType, ApplicationIntegrationType } = require("discord.js");
|
||||
|
||||
const data = new ContextMenuCommandBuilder()
|
||||
.setName('Summarize')
|
||||
.setName("Summarize")
|
||||
.setType(ApplicationCommandType.Message)
|
||||
.setContexts([
|
||||
InteractionContextType.Guild,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const { InteractionContextType, ApplicationIntegrationType, SlashCommandBuilder, EmbedBuilder } = require('discord.js');
|
||||
const { InteractionContextType, ApplicationIntegrationType, SlashCommandBuilder, EmbedBuilder } = require("discord.js");
|
||||
|
||||
const data = new SlashCommandBuilder()
|
||||
.setName('prompt')
|
||||
.setName("prompt")
|
||||
.setDescription("Prompt an AI model with data")
|
||||
.addStringOption(builder =>
|
||||
builder //
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const { ContextMenuCommandBuilder, ApplicationCommandType, InteractionContextType, ApplicationIntegrationType } = require('discord.js');
|
||||
const { ContextMenuCommandBuilder, ApplicationCommandType, InteractionContextType, ApplicationIntegrationType } = require("discord.js");
|
||||
|
||||
const data = new ContextMenuCommandBuilder()
|
||||
.setName('Query AI')
|
||||
.setName("Query AI")
|
||||
.setType(ApplicationCommandType.Message)
|
||||
.setContexts([
|
||||
InteractionContextType.Guild,
|
||||
|
|
175
src/commands/fun/gelbooru.js
Normal file
175
src/commands/fun/gelbooru.js
Normal file
|
@ -0,0 +1,175 @@
|
|||
const { InteractionContextType, ApplicationIntegrationType, SlashCommandBuilder, EmbedBuilder, escapeMarkdown, bold } = require("discord.js");
|
||||
const { basename, extname } = require("node:path");
|
||||
const Booru = require('booru');
|
||||
|
||||
const boorus = [];
|
||||
for (const site of Object.keys(Booru.sites)) {
|
||||
boorus.push({
|
||||
name: site,
|
||||
value: site
|
||||
})
|
||||
}
|
||||
|
||||
const defaultBooru = "gelbooru.com";
|
||||
|
||||
const data = new SlashCommandBuilder()
|
||||
.setName("booru")
|
||||
.setDescription("Select a random image from any booru")
|
||||
.addStringOption(builder =>
|
||||
builder //
|
||||
.setName("tags")
|
||||
.setRequired(true)
|
||||
.setDescription("Tags to search for")
|
||||
)
|
||||
.addStringOption(builder =>
|
||||
builder //
|
||||
.setName("booru")
|
||||
.setRequired(false)
|
||||
.setDescription("Booru board to search (default: gelbooru)")
|
||||
.addChoices(boorus)
|
||||
)
|
||||
.setContexts([
|
||||
InteractionContextType.Guild,
|
||||
InteractionContextType.BotDM,
|
||||
InteractionContextType.PrivateChannel
|
||||
])
|
||||
.setIntegrationTypes([
|
||||
ApplicationIntegrationType.GuildInstall,
|
||||
ApplicationIntegrationType.UserInstall
|
||||
]);
|
||||
|
||||
function isEmbeddableFileType(ext) {
|
||||
return ['.jpg', '.jpeg', '.png', '.gif'].includes(ext)
|
||||
}
|
||||
|
||||
function notEmpty(str) {
|
||||
return str.trim() !== ''
|
||||
}
|
||||
|
||||
const regexCutTags = /[\S\s]{1,75}[^,]{0,25}/;
|
||||
function formatTags(tags) {
|
||||
const tagString = tags.join(', ')
|
||||
|
||||
if (tagString.length < 100) {
|
||||
return tagString
|
||||
}
|
||||
|
||||
const tagCutMatch = tagString.match(regexCutTags) ?? []
|
||||
return `${escapeMarkdown(tagCutMatch[0] ?? '')}...`
|
||||
}
|
||||
|
||||
const ratingEmojis = {
|
||||
s: '<:rating_safe:1293819920978804829>',
|
||||
g: '<:rating_general:1293819929199513610>',
|
||||
q: '<:rating_questionable:1293819907099725925>',
|
||||
e: '<:rating_explicit:1293819893795389491>',
|
||||
u: '<:rating_unknown:1293819936845594665>',
|
||||
}
|
||||
|
||||
function formatRating(rating) {
|
||||
return ratingEmojis[rating] ?? rating.toUpperCase()
|
||||
}
|
||||
|
||||
function formatScore(score) {
|
||||
if (score > 0) {
|
||||
return `<:green_arrow_up:1293819944399667222> ${score}`
|
||||
} else if (score < 0) {
|
||||
return `<:red_arrow_down:1293819951764869181> ${score}`
|
||||
} else {
|
||||
return `<:yellow_tilde:1293819958643396608> ${score}`
|
||||
}
|
||||
}
|
||||
|
||||
function isNSFWPost(post) {
|
||||
return !['s', 'g'].includes(post.rating)
|
||||
}
|
||||
|
||||
function formatTime(time) {
|
||||
return `${(Number(time) / 1e6).toFixed(2)}ms`
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
data,
|
||||
async execute(interaction) {
|
||||
const tags = interaction.options.getString("tags").split(" ");
|
||||
const booru = interaction.options.getString("booru") ?? defaultBooru;
|
||||
|
||||
await interaction.deferReply();
|
||||
console.log(booru, tags);
|
||||
|
||||
const startTime = process.hrtime.bigint();
|
||||
|
||||
var post = null;
|
||||
while (post == null) {
|
||||
var newPost = (await Booru.search(booru, tags, { limit: 1, random: true }))[0];
|
||||
if (newPost == null) {
|
||||
await interaction.followUp("Could not find any post matching tags.");
|
||||
return;
|
||||
}
|
||||
if (isNSFWPost(newPost)) continue;
|
||||
post = newPost;
|
||||
}
|
||||
|
||||
const endTime = process.hrtime.bigint();
|
||||
const timeTaken = endTime - startTime;
|
||||
|
||||
const ext = extname((post['data']).file_name ?? post.fileUrl ?? '').toLowerCase();
|
||||
|
||||
const leadingDescription = [
|
||||
`**Score:** ${formatScore(post.score)}`,
|
||||
`**Rating:** ${formatRating(post.rating)}`,
|
||||
`[File URL](${post.fileUrl})`,
|
||||
`\`${ext}\``,
|
||||
].join(' | ')
|
||||
|
||||
const description = [leadingDescription, `**Tags:** ${formatTags(post.tags)}`]
|
||||
.filter(notEmpty)
|
||||
.join('\n')
|
||||
|
||||
const footerText = [
|
||||
post.booru.domain,
|
||||
post.id,
|
||||
timeTaken ? formatTime(timeTaken) : '',
|
||||
].filter(notEmpty).join(' · ')
|
||||
|
||||
|
||||
if (isEmbeddableFileType(ext)) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor("#cba6f7")
|
||||
.setTitle(`Post #${post.id}`)
|
||||
.setURL(post.postView)
|
||||
//.setDescription(description)
|
||||
.setFields([{
|
||||
name: "Score",
|
||||
value: formatScore(post.score),
|
||||
inline: true
|
||||
}, {
|
||||
name: "Rating",
|
||||
value: formatRating(post.rating),
|
||||
inline: true
|
||||
}, {
|
||||
name: "File",
|
||||
value: `[${basename(post.fileUrl)}](${post.fileUrl})`,
|
||||
inline: true
|
||||
}, {
|
||||
name: "Tags",
|
||||
value: formatTags(post.tags),
|
||||
inline: false
|
||||
}])
|
||||
.setImage(post.fileUrl)
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: `https://${post.booru.domain}/favicon.ico`,
|
||||
})
|
||||
|
||||
await interaction.followUp({ embeds: [embed] });
|
||||
} else {
|
||||
await interaction.followUp(
|
||||
'>>> ' + bold(`[Post #${post.id}](<${post.postView}>)`) + "\n" +
|
||||
description + "\n" +
|
||||
footerText
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
const { ContextMenuCommandBuilder, ApplicationCommandType, InteractionContextType, ApplicationIntegrationType, AttachmentBuilder } = require('discord.js');
|
||||
const { ContextMenuCommandBuilder, ApplicationCommandType, InteractionContextType, ApplicationIntegrationType, AttachmentBuilder } = require("discord.js");
|
||||
|
||||
const data = new ContextMenuCommandBuilder()
|
||||
.setName('Message Information')
|
||||
.setName("Message Information")
|
||||
.setType(ApplicationCommandType.Message)
|
||||
.setContexts([
|
||||
InteractionContextType.Guild,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const { ContextMenuCommandBuilder, ApplicationCommandType, InteractionContextType, ApplicationIntegrationType } = require('discord.js');
|
||||
const { ContextMenuCommandBuilder, ApplicationCommandType, InteractionContextType, ApplicationIntegrationType } = require("discord.js");
|
||||
|
||||
const data = new ContextMenuCommandBuilder()
|
||||
.setName('User Information')
|
||||
.setName("User Information")
|
||||
.setType(ApplicationCommandType.User)
|
||||
.setContexts([
|
||||
InteractionContextType.Guild,
|
||||
|
|
Loading…
Reference in a new issue