From e1cb6a0bbd1d396fa920ee45dd342cc03cfd9639 Mon Sep 17 00:00:00 2001 From: YuitoAkatsuki Date: Thu, 5 Dec 2024 23:17:52 +0900 Subject: [PATCH 1/7] =?UTF-8?q?:sparkles:=20RSS=E3=83=95=E3=82=A3=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=82=92=E7=99=BB=E9=8C=B2=E3=81=99=E3=82=8B=E3=82=B3?= =?UTF-8?q?=E3=83=9E=E3=83=B3=E3=83=89=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97?= =?UTF-8?q?=E3=80=81RSS=E3=83=91=E3=83=BC=E3=82=B5=E3=83=BC=E3=82=92?= =?UTF-8?q?=E5=AE=9F=E8=A3=85=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- commands/admin/feed.js | 72 ++++++++++++++++++++++++++++++++++++++++++ index.js => index.cjs | 63 ++++++++++++++++++++++++++++++------ lib/logUtils.js | 13 ++++++-- lib/rss.cjs | 9 ++++++ package-lock.json | 54 +++++++++++++++++++++++++++++-- package.json | 5 +-- 6 files changed, 200 insertions(+), 16 deletions(-) create mode 100644 commands/admin/feed.js rename index.js => index.cjs (54%) create mode 100644 lib/rss.cjs diff --git a/commands/admin/feed.js b/commands/admin/feed.js new file mode 100644 index 0000000..fd94454 --- /dev/null +++ b/commands/admin/feed.js @@ -0,0 +1,72 @@ +const { SlashCommandBuilder } = require("discord.js"); +const Discord = require("discord.js"); +const logUtils = require("../../lib/logUtils"); +const { rssGet } = require("../../lib/rss.cjs"); + +module.exports = { + guildOnly: true, + adminGuildOnly: true, + data: new SlashCommandBuilder() + .setName("feed") + .setDescription("Regist RSS feed") + .addStringOption((option) => + option.setName("url").setDescription("URL of RSS feed").setRequired(true) + ), + /** + * Executes the feed command. + * @param {CommandInteraction} i - The interaction object. + * @returns {Promise} - A promise that resolves when the execution is complete. + * @async + */ + async execute(i) { + if (i.member.permissions.has("ADMINISTRATOR") === false) { + i.reply("You don't have permission to use this command."); + return "No permission"; + } + const feed = await rssGet(i.options.getString("url")); + const embed = new Discord.EmbedBuilder() + .setTitle("Registed RSS feed") + .addFields([ + { + name: "URL", + value: ` ** ${i.options.getString("url")} ** `, + inline: true, + }, + ]) + .setFields({ + name: "Title", + value: ` ** ${feed[0].title} ** `, + inline: true, + }) + .setFields({ + name: "FirstContent", + value: ` ** ${feed[0].content} ** `, + inline: true, + }) + .setColor(i.client.conf.color.s) + .setTimestamp(); + i.reply({ embeds: [embed] }); + console.log("OK"); + try { + let log = await logUtils.readLog("v1/feed/" + i.channel.id); + if (log) { + log.data.push({ + url: i.options.getString("url"), + lastDate: feed[0].pubDate, + }); + await logUtils.loging(log, `v1/feed/${i.channel.id}`); + } else { + log = { + data: [ + { url: i.options.getString("url"), lastDate: feed[0].pubDate }, + ], + }; + await logUtils.loging(log, `v1/feed/${i.channel.id}`); + } + } catch (e) { + console.error(e); + } + console.log("OK2"); + return "No data"; + }, +}; diff --git a/index.js b/index.cjs similarity index 54% rename from index.js rename to index.cjs index abd39a1..e598a7b 100644 --- a/index.js +++ b/index.cjs @@ -1,3 +1,5 @@ +const cron = require("node-cron"); + const { Client, GatewayIntentBits, @@ -16,8 +18,8 @@ const client = new Client({ partials: [Partials.Channel], ws: { properties: { - $os: "Untitled OS", - $browser: "Untitled Browser", + $os: "Uni OS", + $browser: "Uni Browser", $device: "K8s on Proxmox VE 6.4 in Sibainu", }, }, @@ -26,16 +28,18 @@ const client = new Client({ const fs = require("fs"); const config = require("./config.js"); -const functions = { timeUtils: require("./lib/timeUtils.js"),logUtils: require("./lib/logUtils.js") }; +const functions = { + timeUtils: require("./lib/timeUtils.js"), + logUtils: require("./lib/logUtils.js"), +}; client.conf = config; client.func = functions; client.fs = fs; const cmdH = require(`./lib/commandUtils.js`); -client.commands = new Collection(); // Add this line to define the client.commands object +client.commands = new Collection(); cmdH.handling(client, fs, Collection, config); -// イベントハンドリング const eventFiles = fs .readdirSync("./events") .filter((file) => file.endsWith(".js")); @@ -46,7 +50,10 @@ for (const file of eventFiles) { client.once(event.name, (...args) => event.execute(...args, client)); } catch (error) { console.error( - `\u001b[31m[${functions.timeUtils.timeToJST(Date.now(), true)}]\u001b[0m\n`, + `\u001b[31m[${functions.timeUtils.timeToJST( + Date.now(), + true + )}]\u001b[0m\n`, error ); } @@ -55,18 +62,53 @@ for (const file of eventFiles) { client.on(event.name, (...args) => event.execute(...args, client)); } catch (error) { console.error( - `\u001b[31m[${functions.timeUtils.timeToJST(Date.now(), true)}]\u001b[0m\n`, + `\u001b[31m[${functions.timeUtils.timeToJST( + Date.now(), + true + )}]\u001b[0m\n`, error ); } } } +const { rssGet } = require("./lib/rss.cjs"); + +cron.schedule("*/1-59 * * * *", async () => { + console.log("Cron job start"); + const files = fs.readdirSync("./log/v1/feed"); + for (const file of files) { + const datas = await JSON.parse( + fs.readFileSync(`./log/v1/feed/${file}.log`) + ).data; + datas.forEach(async (data, index) => { + console.log(data.url); + const items = await rssGet(data.url); + const channel = client.channels.cache.get(file.replace(".log", "")); + for (const item of items) { + if (item.pubDate <= data.lastDate) continue; + console.log("send"); + const embed = new EmbedBuilder() + .setTitle(item.title) + .setURL(item.link) + .setDescription(item.content) + .setColor(config.color.s) + .setTimestamp(); + channel.send({ embeds: [embed] }); + datas[index].lastDate = items[0].pubDate; + functions.logUtils.loging(datas, `v1/feed/${file}`); + } + }); + } +}); + client.login(config.token); // エラー処理 (これ入れないとエラーで落ちる。本当は良くないかもしれない) process.on("uncaughtException", (error) => { - console.error(`[${functions.timeUtils.timeToJST(Date.now(), true)}] ${error.stack}`); + console.error( + `[${functions.timeUtils.timeToJST(Date.now(), true)}] ${error.stack}` + ); const embed = new EmbedBuilder() .setTitle("ERROR - uncaughtException") .setDescription("```\n" + error.stack + "\n```") @@ -79,7 +121,10 @@ process.on("uncaughtException", (error) => { process.on("unhandledRejection", (reason, promise) => { console.error( - `\u001b[31m[${functions.timeUtils.timeToJST(Date.now(), true)}] ${reason}\u001b[0m\n`, + `\u001b[31m[${functions.timeUtils.timeToJST( + Date.now(), + true + )}] ${reason}\u001b[0m\n`, promise ); const embed = new EmbedBuilder() diff --git a/lib/logUtils.js b/lib/logUtils.js index c7f80f0..de4235f 100644 --- a/lib/logUtils.js +++ b/lib/logUtils.js @@ -9,7 +9,10 @@ exports.loging = async (post_data, api_name) => { const URI = `${process.cwd()}/log/${api_name}`; try { if (!fs.existsSync(URI)) { - fs.promises.mkdir(URI, { recursive: true }); + console.log( + `[${timeUtils.timeToJST(Date.now(), true)} info]Create directory ${URI}` + ); + await fs.promises.mkdir(URI, { recursive: true }); } const data = JSON.stringify(post_data); fs.writeFile(`${URI}.log`, data, (err) => { @@ -22,7 +25,12 @@ exports.loging = async (post_data, api_name) => { ); throw err; } else { - console.log(`[${timeUtils.timeToJST(Date.now(), true)} info]Write data to ${URI}.log`); + console.log( + `[${timeUtils.timeToJST( + Date.now(), + true + )} info]Write data to ${URI}.log` + ); } }); } catch (e) { @@ -37,6 +45,7 @@ exports.loging = async (post_data, api_name) => { */ exports.readLog = async (api_name) => { const URI = `${process.cwd()}/log/${api_name}`; + if (!fs.existsSync(URI + ".log")) return null; try { const jsonString = fs.readFileSync(URI + ".log"); const data = JSON.parse(jsonString); diff --git a/lib/rss.cjs b/lib/rss.cjs new file mode 100644 index 0000000..4b5f10e --- /dev/null +++ b/lib/rss.cjs @@ -0,0 +1,9 @@ +const Parser = require('rss-parser'); +const parser = new Parser(); + +module.exports = { + rssGet: async (url) => { + let feed = await parser.parseURL(url); + return feed.items + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index bb04019..9c95938 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "untitledbot", + "name": "unibot", "version": "3.2.13", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "untitledbot", + "name": "unibot", "version": "3.2.13", "license": "MIT", "dependencies": { @@ -17,7 +17,8 @@ "discord.js": "^14.16.2", "dotenv": "^16.4.5", "install": "^0.13.0", - "node-cron": "^3.0.3" + "node-cron": "^3.0.3", + "rss-parser": "^3.13.0" } }, "node_modules/@discordjs/builders": { @@ -326,6 +327,15 @@ "url": "https://dotenvx.com" } }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -456,6 +466,22 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, + "node_modules/rss-parser": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/rss-parser/-/rss-parser-3.13.0.tgz", + "integrity": "sha512-7jWUBV5yGN3rqMMj7CZufl/291QAhvrrGpDNE4k/02ZchL0npisiYYqULF71jCEKoIiHvK/Q2e6IkDwPziT7+w==", + "license": "MIT", + "dependencies": { + "entities": "^2.0.3", + "xml2js": "^0.5.0" + } + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC" + }, "node_modules/ts-mixer": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", @@ -510,6 +536,28 @@ "optional": true } } + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } } } } diff --git a/package.json b/package.json index 2cca8f3..c5f1c85 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "The Discord Bot made by UniProject.", "main": "index.js", "scripts": { - "boot": "node index.js" + "boot": "node index.cjs" }, "repository": { "type": "git", @@ -31,6 +31,7 @@ "discord.js": "^14.16.2", "dotenv": "^16.4.5", "install": "^0.13.0", - "node-cron": "^3.0.3" + "node-cron": "^3.0.3", + "rss-parser": "^3.13.0" } } From 3abb42d3b42c418caa3a43763fafb1e241e26d9c Mon Sep 17 00:00:00 2001 From: YuitoAkatsuki Date: Thu, 5 Dec 2024 23:18:27 +0900 Subject: [PATCH 2/7] :bookmark: 3.3.0-0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9c95938..b9792a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "unibot", - "version": "3.2.13", + "version": "3.3.0-0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "unibot", - "version": "3.2.13", + "version": "3.3.0-0", "license": "MIT", "dependencies": { "@discordjs/rest": "^2.4.0", diff --git a/package.json b/package.json index c5f1c85..a494bdc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "unibot", - "version": "3.2.13", + "version": "3.3.0-0", "description": "The Discord Bot made by UniProject.", "main": "index.js", "scripts": { From 1b972519a9632f6dc008450981fbb286908a80e0 Mon Sep 17 00:00:00 2001 From: YuitoAkatsuki Date: Thu, 5 Dec 2024 23:19:59 +0900 Subject: [PATCH 3/7] :hammer: test --- argoCD/deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/argoCD/deployment.yaml b/argoCD/deployment.yaml index dae815b..3e738a5 100644 --- a/argoCD/deployment.yaml +++ b/argoCD/deployment.yaml @@ -13,7 +13,7 @@ spec: spec: containers: - name: unibot - image: registry.uniproject-tech.net/unibot/unibot:3.2.13 + image: registry.uniproject-tech.net/unibot/unibot:3.3.0-0 envFrom: - secretRef: name: unibot-env From ca76d503c2c18ffce446b9ce2cc454d43b992574 Mon Sep 17 00:00:00 2001 From: YuitoAkatsuki Date: Thu, 5 Dec 2024 23:37:22 +0900 Subject: [PATCH 4/7] =?UTF-8?q?:bug:=20=E9=96=8B=E7=99=BA=E7=94=A8?= =?UTF-8?q?=E3=82=B9=E3=82=AF=E3=83=AA=E3=83=97=E3=83=88=E3=81=AE=E9=99=A4?= =?UTF-8?q?=E5=8E=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.js b/config.js index 414c79f..59e0636 100644 --- a/config.js +++ b/config.js @@ -1,4 +1,4 @@ -(require('dotenv')).config(); +//(require('dotenv')).config(); module.exports = { adminRoleId: process.env.ROLE_ADMIN, color: { From 9515b801b3f6db19b2fbeddf837be92c367f2899 Mon Sep 17 00:00:00 2001 From: YuitoAkatsuki Date: Thu, 5 Dec 2024 23:39:20 +0900 Subject: [PATCH 5/7] :bookmark: 3.3.0-1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index b9792a2..7caef90 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "unibot", - "version": "3.3.0-0", + "version": "3.3.0-1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "unibot", - "version": "3.3.0-0", + "version": "3.3.0-1", "license": "MIT", "dependencies": { "@discordjs/rest": "^2.4.0", diff --git a/package.json b/package.json index a494bdc..9e7494f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "unibot", - "version": "3.3.0-0", + "version": "3.3.0-1", "description": "The Discord Bot made by UniProject.", "main": "index.js", "scripts": { From e5d646474c2252aff1df7ba4c94960df5dc961a2 Mon Sep 17 00:00:00 2001 From: YuitoAkatsuki Date: Thu, 5 Dec 2024 23:39:32 +0900 Subject: [PATCH 6/7] :hammer: upimg --- argoCD/deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/argoCD/deployment.yaml b/argoCD/deployment.yaml index 3e738a5..3b0da75 100644 --- a/argoCD/deployment.yaml +++ b/argoCD/deployment.yaml @@ -13,7 +13,7 @@ spec: spec: containers: - name: unibot - image: registry.uniproject-tech.net/unibot/unibot:3.3.0-0 + image: registry.uniproject-tech.net/unibot/unibot:3.3.0-1 envFrom: - secretRef: name: unibot-env From 14872580330ffefb370d8244fe7bda71eab80b2a Mon Sep 17 00:00:00 2001 From: YuitoAkatsuki Date: Sat, 7 Dec 2024 16:50:01 +0900 Subject: [PATCH 7/7] =?UTF-8?q?:sparkles:=20admin/feed=20=E3=82=B3?= =?UTF-8?q?=E3=83=9E=E3=83=B3=E3=83=89=E3=81=AE=E3=82=B5=E3=83=96=E3=82=B3?= =?UTF-8?q?=E3=83=9E=E3=83=B3=E3=83=89=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97?= =?UTF-8?q?=E3=80=81RSS=E3=83=95=E3=82=A3=E3=83=BC=E3=83=89=E3=81=AE?= =?UTF-8?q?=E7=99=BB=E9=8C=B2=E3=81=A8=E5=89=8A=E9=99=A4=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- commands/admin/feed.js | 140 ++++++++++++++++++++-------------- commands/admin/feed/delete.js | 66 ++++++++++++++++ commands/admin/feed/regist.js | 66 ++++++++++++++++ events/interactionCreate.js | 2 +- 4 files changed, 216 insertions(+), 58 deletions(-) create mode 100644 commands/admin/feed/delete.js create mode 100644 commands/admin/feed/regist.js diff --git a/commands/admin/feed.js b/commands/admin/feed.js index fd94454..d234cc1 100644 --- a/commands/admin/feed.js +++ b/commands/admin/feed.js @@ -1,72 +1,98 @@ -const { SlashCommandBuilder } = require("discord.js"); -const Discord = require("discord.js"); -const logUtils = require("../../lib/logUtils"); -const { rssGet } = require("../../lib/rss.cjs"); +const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); +const { addSubCommand, subCommandHandling } = require("../../lib/commandUtils"); +const { GetLogChannel, GetErrorChannel } = require("../../lib/channelUtils"); module.exports = { guildOnly: true, adminGuildOnly: true, - data: new SlashCommandBuilder() + handlingCommands: subCommandHandling("admin/feed"), + data: addSubCommand( + "admin/feed", + new SlashCommandBuilder() + .setName("feed") + .setDescription("RSS feed/atom feed Utilities") + ), + /*data: new SlashCommandBuilder() .setName("feed") .setDescription("Regist RSS feed") .addStringOption((option) => option.setName("url").setDescription("URL of RSS feed").setRequired(true) - ), - /** - * Executes the feed command. - * @param {CommandInteraction} i - The interaction object. - * @returns {Promise} - A promise that resolves when the execution is complete. - * @async - */ - async execute(i) { - if (i.member.permissions.has("ADMINISTRATOR") === false) { - i.reply("You don't have permission to use this command."); + ),*/ + async execute(interaction) { + if (interaction.member.permissions.has("ADMINISTRATOR") === false) { + interaction.reply({ + content: "You don't have permission to use this command.", + ephemeral: true, + }); return "No permission"; } - const feed = await rssGet(i.options.getString("url")); - const embed = new Discord.EmbedBuilder() - .setTitle("Registed RSS feed") - .addFields([ - { - name: "URL", - value: ` ** ${i.options.getString("url")} ** `, - inline: true, - }, - ]) - .setFields({ - name: "Title", - value: ` ** ${feed[0].title} ** `, - inline: true, - }) - .setFields({ - name: "FirstContent", - value: ` ** ${feed[0].content} ** `, - inline: true, - }) - .setColor(i.client.conf.color.s) - .setTimestamp(); - i.reply({ embeds: [embed] }); - console.log("OK"); + const command = this.handlingCommands.get( + interaction.options.getSubcommand() + ); + await interaction.deferReply(); + if (!command) { + console.log(`[-] Not Found: ${interaction.options.getSubcommand()}`); + return; + } try { - let log = await logUtils.readLog("v1/feed/" + i.channel.id); - if (log) { - log.data.push({ - url: i.options.getString("url"), - lastDate: feed[0].pubDate, - }); - await logUtils.loging(log, `v1/feed/${i.channel.id}`); - } else { - log = { - data: [ - { url: i.options.getString("url"), lastDate: feed[0].pubDate }, - ], - }; - await logUtils.loging(log, `v1/feed/${i.channel.id}`); + await command.execute(interaction); + console.log(`[Run] ${interaction.options.getSubcommand()}`); + + const logEmbed = new EmbedBuilder() + .setTitle("サブコマンド実行ログ") + .setDescription(`${interaction.user} がサブコマンドを実行しました。`) + .setColor(interaction.client.conf.color.s) + .setTimestamp() + .setThumbnail(interaction.user.displayAvatarURL({ dynamic: true })) + .addFields([ + { + name: "サブコマンド", + value: `\`\`\`\n/${interaction.options.getSubcommand()}\n\`\`\``, + }, + { + name: "実行サーバー", + value: + "```\n" + interaction.inGuild() + ? `${interaction.guild.name} (${interaction.guild.id})` + : "DM" + "\n```", + }, + { + name: "実行ユーザー", + value: + "```\n" + + `${interaction.user.tag}(${interaction.user.id})` + + "\n```", + }, + ]) + .setFooter({ text: `${interaction.id}` }); + const channel = await GetLogChannel(interaction); + if (channel) { + channel.send({ embeds: [logEmbed] }); + } + } catch (error) { + console.error(error); + const logEmbed = new EmbedBuilder() + .setTitle("ERROR - cmd") + .setDescription("```\n" + error.toString() + "\n```") + .setColor(config.color.e) + .setTimestamp(); + + const channel = await GetErrorChannel(interaction); + if (channel) { + channel.send({ embeds: [logEmbed] }); + } + const messageEmbed = new EmbedBuilder() + .setTitle("すみません、エラーが発生しました...") + .setDescription("```\n" + error + "\n```") + .setColor(interaction.conf.color.e) + .setTimestamp(); + + await interaction.editReply(messageEmbed); + const logChannel = await GetLogChannel(interaction); + if (logChannel) { + logChannel.send({ embeds: [messageEmbed] }); } - } catch (e) { - console.error(e); } - console.log("OK2"); - return "No data"; + return; }, }; diff --git a/commands/admin/feed/delete.js b/commands/admin/feed/delete.js new file mode 100644 index 0000000..ec2f0ce --- /dev/null +++ b/commands/admin/feed/delete.js @@ -0,0 +1,66 @@ +const { + SlashCommandSubcommandBuilder, + StringSelectMenuBuilder, + StringSelectMenuOptionBuilder, + ActionRowBuilder, + ComponentType, +} = require("discord.js"); +const logUtils = require("../../../lib/logUtils.js"); + +module.exports = { + data: new SlashCommandSubcommandBuilder() + .setName("delete") + .setDescription("delete"), + adminGuildOnly: true, + /** + * Executes the feed command. + * @param {CommandInteraction} interaction - The interaction object. + * @returns {Promise} - A promise that resolves when the execution is complete. + * @async + */ + async execute(interaction) { + const subscribed = await logUtils.readLog( + "v1/feed/" + interaction.channel.id + ); + if (!subscribed) { + interaction.editReply({ + content: "This channel is not subscribed to any feeds.", + ephemeral: true, + }); + return "No data"; + } + const select = new StringSelectMenuBuilder().setCustomId("FeedSelector"); + for (const feed of subscribed.data) { + await select.addOptions( + new StringSelectMenuOptionBuilder() + .setLabel(feed.url) + .setValue(feed.url) + .setDescription("Last Update: " + feed.lastDate) + ); + } + + const row = new ActionRowBuilder().addComponents(select); + + const response = await interaction.editReply({ + content: "Choose your starter!", + components: [row], + }); + + const collector = response.createMessageComponentCollector({ + componentType: ComponentType.StringSelect, + time: 3_600_000, + }); + + collector.on("collect", async (i) => { + const selection = i.values[0]; + const index = subscribed.data.findIndex((x) => x.url === selection); + subscribed.data.splice(index, 1); + await logUtils.loging(subscribed, `v1/feed/${interaction.channel.id}`); + await i.update({ + content: "Deleted: " + selection, + components: [], + }); + }); + return "No data"; + }, +}; diff --git a/commands/admin/feed/regist.js b/commands/admin/feed/regist.js new file mode 100644 index 0000000..35563fb --- /dev/null +++ b/commands/admin/feed/regist.js @@ -0,0 +1,66 @@ +const { SlashCommandSubcommandBuilder, EmbedBuilder } = require("discord.js"); +const Discord = require("discord.js"); +const { rssGet } = require("../../../lib/rss.cjs"); +const logUtils = require("../../../lib/logUtils.js"); + +module.exports = { + data: new SlashCommandSubcommandBuilder() + .setName("regist") + .setDescription("Regist RSS feed") + .addStringOption((option) => + option.setName("url").setDescription("URL of RSS feed").setRequired(true) + ), + adminGuildOnly: true, + /** + * Executes the feed command. + * @param {CommandInteraction} i - The interaction object. + * @returns {Promise} - A promise that resolves when the execution is complete. + * @async + */ + async execute(i) { + const feed = await rssGet(i.options.getString("url")); + try { + let log = await logUtils.readLog("v1/feed/" + i.channel.id); + console.log(log); + if (log) { + log.data.push({ + url: i.options.getString("url"), + lastDate: feed[0].pubDate, + }); + await logUtils.loging(log, `v1/feed/${i.channel.id}`); + } else { + log = { + data: [ + { url: i.options.getString("url"), lastDate: feed[0].pubDate }, + ], + }; + await logUtils.loging(log, `v1/feed/${i.channel.id}`); + } + } catch (e) { + console.error(e); + } + const embed = new Discord.EmbedBuilder() + .setTitle("Registed RSS feed") + .addFields([ + { + name: "URL", + value: ` ** ${i.options.getString("url")} ** `, + inline: true, + }, + ]) + .setFields({ + name: "Title", + value: ` ** ${feed[0].title} ** `, + inline: true, + }) + .setFields({ + name: "FirstContent", + value: ` ** ${feed[0].content} ** `, + inline: true, + }) + .setColor(i.client.conf.color.s) + .setTimestamp(); + i.editReply({ embeds: [embed] }); + return "No data"; + }, +}; diff --git a/events/interactionCreate.js b/events/interactionCreate.js index c9ca268..b7fbb4d 100644 --- a/events/interactionCreate.js +++ b/events/interactionCreate.js @@ -99,7 +99,7 @@ module.exports = { .setColor(config.color.e) .setTimestamp(); - await interaction.reply(messageEmbed); + await interaction.reply({ embeds: [messageEmbed] }); const logChannel = await GetLogChannel(interaction); if (logChannel) { logChannel.send({ embeds: [messageEmbed] });