Compare commits
37 Commits
117cbea67f
...
#27-rss-fe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfb2765f39 | ||
|
|
33680209ba | ||
|
|
f70ea4229a | ||
|
|
acadc9faee | ||
|
|
f725ec88f9 | ||
|
|
8d34b93527 | ||
|
|
918cfe06e4 | ||
|
|
e2f276e65b | ||
| 52353ec1fb | |||
|
|
750877db1a | ||
|
|
a18337d0f8 | ||
|
|
6f45a60030 | ||
|
|
1fb4728b0a | ||
|
|
ebf48c7618 | ||
|
|
11b3504f28 | ||
|
|
14171a9c13 | ||
|
|
47a03898cc | ||
|
|
2551498d2e | ||
|
|
277f7d176a | ||
|
|
066404dd10 | ||
|
|
8f2891f5d8 | ||
|
|
9f2ed48caf | ||
|
|
3f42d60efc | ||
|
|
cf9f48dfa7 | ||
|
|
bde7dbce45 | ||
|
|
a8e96ab5dc | ||
|
|
628fd80710 | ||
|
|
edb7ec41b1 | ||
|
|
0be5b059da | ||
|
|
46989942d8 | ||
|
|
ab929489b0 | ||
|
|
cf49ac414a | ||
|
|
94374b4d45 | ||
|
|
d18ffd4c11 | ||
|
|
a56c19a466 | ||
|
|
f4886f9fc5 | ||
|
|
e324ee1738 |
@@ -16,13 +16,13 @@ jobs:
|
|||||||
RUNNER_TOOL_CACHE: /toolcache
|
RUNNER_TOOL_CACHE: /toolcache
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
- name: Set up Docker BuildX
|
- name: Set up Docker BuildX
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
with: # replace it with your local IP
|
with: # replace it with your local IP
|
||||||
config-inline: |
|
config-inline: |
|
||||||
[registry."git.vpn.cusano.net"]
|
[registry."git.vpn.cusano.net"]
|
||||||
@@ -30,7 +30,7 @@ jobs:
|
|||||||
insecure = false
|
insecure = false
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: git.vpn.cusano.net # replace it with your local IP
|
registry: git.vpn.cusano.net # replace it with your local IP
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
|||||||
56
.gitea/workflows/DRBv3_docs.yaml
Normal file
56
.gitea/workflows/DRBv3_docs.yaml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
name: Update Wiki from JSDoc
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
# schedule:
|
||||||
|
# - cron: '0 0 * * 1' # Every Monday at midnight (UTC)
|
||||||
|
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODE_ENV: development
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-wiki:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout the code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '22'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Generate JSDoc
|
||||||
|
run: npm run docs
|
||||||
|
|
||||||
|
- name: Checkout the wiki repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: logan/drb-server.wiki # Replace with your wiki repository
|
||||||
|
path: wiki
|
||||||
|
|
||||||
|
- name: Output Generated Documentation
|
||||||
|
run: |
|
||||||
|
cat Home.md
|
||||||
|
ls
|
||||||
|
|
||||||
|
- name: Update wiki
|
||||||
|
run: |
|
||||||
|
cp -rf Home.md wiki/Home.md
|
||||||
|
cd wiki
|
||||||
|
git config user.name "gitea-actions"
|
||||||
|
git config user.email "gitea-actions@cusano.net"
|
||||||
|
git add .
|
||||||
|
# Check if there are any changes to commit
|
||||||
|
if git diff --cached --quiet; then
|
||||||
|
echo "No changes to commit."
|
||||||
|
else
|
||||||
|
git commit -m "Update wiki from JSDoc"
|
||||||
|
git push
|
||||||
|
fi
|
||||||
@@ -5,6 +5,8 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
pull_request:
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- "*"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint-js:
|
lint-js:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ name: DRB Tests
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- "*"
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -302,3 +302,6 @@ op25/
|
|||||||
|
|
||||||
# Ignore any local run scripts for development
|
# Ignore any local run scripts for development
|
||||||
*.bat
|
*.bat
|
||||||
|
|
||||||
|
# Ignore the auto-generated docs folder
|
||||||
|
/docs
|
||||||
@@ -12,7 +12,7 @@ RUN npm install -g node-gyp
|
|||||||
RUN npm install
|
RUN npm install
|
||||||
|
|
||||||
# Copy the rest of the application code to the working directory
|
# Copy the rest of the application code to the working directory
|
||||||
COPY . .
|
COPY ./src ./src
|
||||||
|
|
||||||
# Expose the port on which your Node.js application will run
|
# Expose the port on which your Node.js application will run
|
||||||
EXPOSE 3420
|
EXPOSE 3420
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
import { DebugBuilder } from "../../modules/debugger.mjs";
|
|
||||||
const log = new DebugBuilder("server", "discordBot.events.messageCreate");
|
|
||||||
import dotenv from "dotenv";
|
|
||||||
dotenv.config();
|
|
||||||
import { Events } from "discord.js";
|
|
||||||
import { gptInteraction } from "../addons/gptInteraction.mjs";
|
|
||||||
import { linkCop } from "../addons/linkCop.mjs";
|
|
||||||
|
|
||||||
const IGNORED_CHANNELS = process.env.IGNORED_CHANNEL_IDS.split(",");
|
|
||||||
|
|
||||||
export const name = Events.MessageCreate;
|
|
||||||
|
|
||||||
export async function execute(nodeIo, message) {
|
|
||||||
// Ignore ignored channels
|
|
||||||
if (IGNORED_CHANNELS.includes(message.channel.id)) return;
|
|
||||||
|
|
||||||
// Ignore messages from a bot
|
|
||||||
if (message.author.bot) return;
|
|
||||||
|
|
||||||
log.INFO("Message create", message);
|
|
||||||
|
|
||||||
// Check if the message mentions the bot
|
|
||||||
if (message.mentions.users.has(nodeIo.serverClient.user.id)) {
|
|
||||||
return await gptInteraction(nodeIo, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the message contains a link in a channel it shouldn't
|
|
||||||
if (await linkCop(nodeIo, message)) return;
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
import { getConfig } from "./configHandler.mjs";
|
|
||||||
|
|
||||||
class PresenceManager {
|
|
||||||
/**
|
|
||||||
* Creates an instance of PresenceManager.
|
|
||||||
* @param {import('discord.js').Client} client - The Discord client instance.
|
|
||||||
*/
|
|
||||||
constructor(client) {
|
|
||||||
this.client = client;
|
|
||||||
this.defaultStatus = "online";
|
|
||||||
this.defaultActivityType = "LISTENING";
|
|
||||||
this.defaultActivityName = "for your commands";
|
|
||||||
this.defaultUrl = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the bot's presence.
|
|
||||||
* @param {"online"|"idle"|"dnd"} status - The status of the bot (online, idle, dnd).
|
|
||||||
* @param {"PLAYING"|"STREAMING"|"LISTENING"|"WATCHING"|"COMPETING"} activityType - The type of activity.
|
|
||||||
* @param {string} activityName - The name of the activity.
|
|
||||||
* @param {string} [url=null] - The URL for STREAMING activity type (optional).
|
|
||||||
*/
|
|
||||||
setPresence(status, activityType, activityName, url = null) {
|
|
||||||
const activityOptions = {
|
|
||||||
type: activityType.toUpperCase(),
|
|
||||||
name: activityName,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (activityType.toUpperCase() === "STREAMING" && url) {
|
|
||||||
activityOptions.url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.client.user.setPresence({
|
|
||||||
status: status,
|
|
||||||
activities: [activityOptions],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the bot's presence to the default state.
|
|
||||||
*/
|
|
||||||
resetToDefault() {
|
|
||||||
const defaultPresence = getConfig("presence");
|
|
||||||
console.log("Default Presence:", defaultPresence);
|
|
||||||
|
|
||||||
// Update your bot's presence using this configuration
|
|
||||||
this.client.user.setPresence(defaultPresence);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PresenceManager;
|
|
||||||
@@ -4,6 +4,7 @@ import { FlatCompat } from "@eslint/eslintrc";
|
|||||||
import mjs from "@eslint/js";
|
import mjs from "@eslint/js";
|
||||||
import prettierConfig from "eslint-config-prettier";
|
import prettierConfig from "eslint-config-prettier";
|
||||||
import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
|
import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
|
||||||
|
import unusedImports from "eslint-plugin-unused-imports";
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
@@ -13,17 +14,34 @@ const compat = new FlatCompat({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
|
// Apply ESLint recommended settings first
|
||||||
...compat.extends().map((config) => ({
|
...compat.extends().map((config) => ({
|
||||||
...config,
|
...config,
|
||||||
files: ["**/*.mjs", "**/*.js", "**/*.cjs"],
|
files: ["src/**/*.mjs", "src/**/*.js", "src/**/*.cjs"],
|
||||||
rules: {
|
|
||||||
...config.rules,
|
|
||||||
// ...other your custom rules
|
|
||||||
"no-console": "warn",
|
|
||||||
"no-unused-vars": "warn",
|
|
||||||
"unused-imports/no-unused-imports": "error",
|
|
||||||
},
|
|
||||||
})),
|
})),
|
||||||
|
|
||||||
|
// Custom rules and plugin configuration
|
||||||
|
{
|
||||||
|
plugins: {
|
||||||
|
"unused-imports": unusedImports,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
// Custom rules here
|
||||||
|
"no-console": "warn",
|
||||||
|
"no-unused-vars": "off", // or "@typescript-eslint/no-unused-vars": "off",
|
||||||
|
"unused-imports/no-unused-imports": "error",
|
||||||
|
"unused-imports/no-unused-vars": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
vars: "all",
|
||||||
|
varsIgnorePattern: "^_",
|
||||||
|
args: "after-used",
|
||||||
|
argsIgnorePattern: "^_",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"prettier/prettier": "warn", // Integrate prettier
|
||||||
|
},
|
||||||
|
},
|
||||||
prettierConfig, // Turns off all ESLint rules that have the potential to interfere with Prettier rules.
|
prettierConfig, // Turns off all ESLint rules that have the potential to interfere with Prettier rules.
|
||||||
eslintPluginPrettierRecommended,
|
eslintPluginPrettierRecommended,
|
||||||
];
|
];
|
||||||
|
|||||||
10
jsdoc.conf
Normal file
10
jsdoc.conf
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"source": {
|
||||||
|
"includePattern": ".+([mc]?js(doc|x)?)$"
|
||||||
|
},
|
||||||
|
"plugins": ["node_modules/jsdoc-babel"],
|
||||||
|
"babel": {
|
||||||
|
"presets": [ "es2015" ],
|
||||||
|
"plugins": [ "transform-async-to-generator" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
4
makefile
4
makefile
@@ -21,10 +21,6 @@ run:
|
|||||||
-e MONGO_URL=${MONGO_URL} \
|
-e MONGO_URL=${MONGO_URL} \
|
||||||
-e DISCORD_TOKEN=${DISCORD_TOKEN} \
|
-e DISCORD_TOKEN=${DISCORD_TOKEN} \
|
||||||
-e RSS_REFRESH_INTERVAL=${RSS_REFRESH_INTERVAL} \
|
-e RSS_REFRESH_INTERVAL=${RSS_REFRESH_INTERVAL} \
|
||||||
-e WELCOME_CHANNEL_ID=${WELCOME_CHANNEL_ID} \
|
|
||||||
-e IGNORED_CHANNEL_IDS=${IGNORED_CHANNEL_IDS} \
|
|
||||||
-e LINKCOP_RESTRICTED_CHANNEL_IDS=${LINKCOP_RESTRICTED_CHANNEL_IDS} \
|
|
||||||
-e DRB_SERVER_INITIAL_PROMPT=${DRB_SERVER_INITIAL_PROMPT} \
|
|
||||||
-e OPENAI_API_KEY=${OPENAI_API_KEY} \
|
-e OPENAI_API_KEY=${OPENAI_API_KEY} \
|
||||||
-e LOG_LOCATION="./logs/server.log" \
|
-e LOG_LOCATION="./logs/server.log" \
|
||||||
-p ${SERVER_PORT}:${SERVER_PORT} \
|
-p ${SERVER_PORT}:${SERVER_PORT} \
|
||||||
|
|||||||
2329
package-lock.json
generated
2329
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,22 +2,27 @@
|
|||||||
"name": "drb-server",
|
"name": "drb-server",
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "server.js",
|
"main": "src/server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"docs": "jsdoc2md -c jsdoc.conf src/*js > Home.md",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"lint:fix": "eslint --fix .",
|
"lint:fix": "eslint --fix .",
|
||||||
"test": "mocha --timeout 5000",
|
"test": "mocha --timeout 5000",
|
||||||
"start": "node server.js"
|
"start": "node src/server.js"
|
||||||
},
|
},
|
||||||
"author": "Logan Cusano",
|
"author": "Logan Cusano",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"babel-plugin-transform-async-to-generator": "^6.24.1",
|
||||||
|
"babel-preset-es2015": "^6.24.1",
|
||||||
"chai": "^5.1.1",
|
"chai": "^5.1.1",
|
||||||
"eslint": "^9.9.0",
|
"eslint": "^9.9.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"eslint-plugin-unused-imports": "^4.1.3",
|
"eslint-plugin-unused-imports": "^4.1.3",
|
||||||
|
"jsdoc-babel": "^0.5.0",
|
||||||
|
"jsdoc-to-markdown": "^8.0.3",
|
||||||
"mocha": "^10.4.0",
|
"mocha": "^10.4.0",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"socket.io-client": "^4.7.5"
|
"socket.io-client": "^4.7.5"
|
||||||
|
|||||||
@@ -2,25 +2,37 @@ import { DebugBuilder } from "../../modules/debugger.mjs";
|
|||||||
const log = new DebugBuilder("server", "discordBot.addons.linkCop");
|
const log = new DebugBuilder("server", "discordBot.addons.linkCop");
|
||||||
import { gptHandler } from "../modules/gptHandler.mjs";
|
import { gptHandler } from "../modules/gptHandler.mjs";
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
|
import { getGuildConfig } from "../../modules/mongo-wrappers/mongoConfigWrappers.mjs";
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
const approvedLinksChannel = "767303243285790721";
|
const linkRegExp = /http[s]?:\/\/\S+/g;
|
||||||
const restrictedChannelIds =
|
|
||||||
process.env.LINKCOP_RESTRICTED_CHANNEL_IDS.split(",");
|
|
||||||
|
|
||||||
const linkRegExp =
|
|
||||||
/(?:http[s]?:\/\/)?(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)/g;
|
|
||||||
|
|
||||||
export const linkCop = async (nodeIo, message) => {
|
export const linkCop = async (nodeIo, message) => {
|
||||||
|
// Set the channel IDs based on the guild the message was sent in
|
||||||
|
const approvedLinksChannel =
|
||||||
|
(await getGuildConfig(message.guild.id, "approvedLinksChannel")) ||
|
||||||
|
"767303243285790721";
|
||||||
|
const restrictedChannelIds = await getGuildConfig(
|
||||||
|
message.guild.id,
|
||||||
|
"restrictedChannelIds",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if the message was sent in an restricted channel
|
||||||
if (
|
if (
|
||||||
message.channel.id == approvedLinksChannel ||
|
message.channel.id == approvedLinksChannel ||
|
||||||
|
!Array.isArray(restrictedChannelIds) ||
|
||||||
|
Array.isArray(restrictedChannelIds) ||
|
||||||
!restrictedChannelIds.includes(message.channel.id)
|
!restrictedChannelIds.includes(message.channel.id)
|
||||||
)
|
) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there are URLs in the sent message
|
||||||
|
const urls = [...message.content.matchAll(linkRegExp)];
|
||||||
|
log.DEBUG("Parsed URLs from message:", urls);
|
||||||
|
|
||||||
const urls = String(message.content).matchAll(linkRegExp);
|
|
||||||
if (!urls || urls.length === 0) return false;
|
if (!urls || urls.length === 0) return false;
|
||||||
log.DEBUG("Found URLs: ", urls);
|
log.INFO("Found URLs: ", urls);
|
||||||
|
|
||||||
let conversation = [];
|
let conversation = [];
|
||||||
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { SlashCommandBuilder } from "discord.js";
|
import { SlashCommandBuilder } from "discord.js";
|
||||||
import { DebugBuilder } from "../../modules/debugger.mjs";
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
import { removeSource } from "../../rss-manager/sourceManager.mjs";
|
|
||||||
import {
|
import {
|
||||||
getAllFeeds,
|
getAllFeeds,
|
||||||
deleteFeedByTitle,
|
deleteFeedByTitle,
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
import { DebugBuilder } from "../modules/debugger.mjs";
|
import { DebugBuilder } from "../modules/debugger.mjs";
|
||||||
import { Client, GatewayIntentBits, Collection } from "discord.js";
|
import { Client, GatewayIntentBits, Collection } from "discord.js";
|
||||||
import {
|
import { registerActiveCommands } from "./modules/registerCommands.mjs";
|
||||||
registerActiveCommands,
|
|
||||||
unregisterAllCommands,
|
|
||||||
} from "./modules/registerCommands.mjs";
|
|
||||||
import { RSSController } from "../rss-manager/rssController.mjs";
|
import { RSSController } from "../rss-manager/rssController.mjs";
|
||||||
import { join, dirname } from "path";
|
import { join, dirname } from "path";
|
||||||
import { readdirSync } from "fs";
|
import { readdirSync } from "fs";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
|
import PresenceManager from "./modules/presenceManager.mjs";
|
||||||
|
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
@@ -110,6 +108,10 @@ export const serverClient = new Client({
|
|||||||
serverClient.on("ready", async () => {
|
serverClient.on("ready", async () => {
|
||||||
log.INFO(`Logged in as ${serverClient.user.tag}!`);
|
log.INFO(`Logged in as ${serverClient.user.tag}!`);
|
||||||
|
|
||||||
|
// Set the presence to default
|
||||||
|
const pm = new PresenceManager(serverClient);
|
||||||
|
await pm.resetToDefault();
|
||||||
|
|
||||||
// Add and register commands
|
// Add and register commands
|
||||||
await addEnabledCommands(serverClient);
|
await addEnabledCommands(serverClient);
|
||||||
|
|
||||||
@@ -4,12 +4,15 @@ import dotenv from "dotenv";
|
|||||||
dotenv.config();
|
dotenv.config();
|
||||||
import { Events } from "discord.js";
|
import { Events } from "discord.js";
|
||||||
import { gptHandler } from "../modules/gptHandler.mjs";
|
import { gptHandler } from "../modules/gptHandler.mjs";
|
||||||
|
import { getGuildConfig } from "../../modules/mongo-wrappers/mongoConfigWrappers.mjs";
|
||||||
const welcomeChannel = process.env.WELCOME_CHANNEL_ID; // TODO - Need to add a DB section for server configs so it's not static to one server
|
|
||||||
|
|
||||||
export const name = Events.GuildMemberAdd;
|
export const name = Events.GuildMemberAdd;
|
||||||
|
|
||||||
export async function execute(nodeIo, member) {
|
export async function execute(nodeIo, member) {
|
||||||
|
const welcomeChannel = await getGuildConfig(
|
||||||
|
message.guild.id,
|
||||||
|
"welcomeChannelId",
|
||||||
|
);
|
||||||
log.INFO("New user joined the server", member);
|
log.INFO("New user joined the server", member);
|
||||||
let conversation = [];
|
let conversation = [];
|
||||||
conversation.push({
|
conversation.push({
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { DebugBuilder } from "../../modules/debugger.mjs";
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
const log = new DebugBuilder("server", "discordBot.events.interactionCreate");
|
const log = new DebugBuilder("server", "discordBot.events.interactionCreate");
|
||||||
import { Events } from "discord.js";
|
import { Events } from "discord.js";
|
||||||
|
import PresenceManager from "../modules/presenceManager.mjs";
|
||||||
|
|
||||||
export const name = Events.InteractionCreate;
|
export const name = Events.InteractionCreate;
|
||||||
|
|
||||||
@@ -8,6 +9,10 @@ export async function execute(nodeIo, interaction) {
|
|||||||
const command = interaction.client.commands.get(interaction.commandName);
|
const command = interaction.client.commands.get(interaction.commandName);
|
||||||
log.INFO("Interaction created for command: ", command);
|
log.INFO("Interaction created for command: ", command);
|
||||||
|
|
||||||
|
// Set the presence for handling interaction
|
||||||
|
const interactionPm = new PresenceManager(interaction.client);
|
||||||
|
await interactionPm.setPresence("online", "PLAYING", "handling interaction");
|
||||||
|
|
||||||
// Execute autocomplete if the user is checking autocomplete
|
// Execute autocomplete if the user is checking autocomplete
|
||||||
if (interaction.isAutocomplete()) {
|
if (interaction.isAutocomplete()) {
|
||||||
log.INFO("Running autocomplete for command: ", command.data.name);
|
log.INFO("Running autocomplete for command: ", command.data.name);
|
||||||
@@ -33,4 +38,7 @@ export async function execute(nodeIo, interaction) {
|
|||||||
|
|
||||||
// Execute the command
|
// Execute the command
|
||||||
command.execute(nodeIo, interaction);
|
command.execute(nodeIo, interaction);
|
||||||
|
|
||||||
|
// Reset the presence
|
||||||
|
await interactionPm.resetToDefault();
|
||||||
}
|
}
|
||||||
55
src/discordBot/events/messageCreate.mjs
Normal file
55
src/discordBot/events/messageCreate.mjs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||||
|
const log = new DebugBuilder("server", "discordBot.events.messageCreate");
|
||||||
|
import dotenv from "dotenv";
|
||||||
|
dotenv.config();
|
||||||
|
import { Events } from "discord.js";
|
||||||
|
import { gptInteraction } from "../addons/gptInteraction.mjs";
|
||||||
|
import { linkCop } from "../addons/linkCop.mjs";
|
||||||
|
import PresenceManager from "../modules/presenceManager.mjs";
|
||||||
|
import { getGuildConfig } from "../../modules/mongo-wrappers/mongoConfigWrappers.mjs";
|
||||||
|
|
||||||
|
export const name = Events.MessageCreate;
|
||||||
|
|
||||||
|
export async function execute(nodeIo, message) {
|
||||||
|
// Get the ignored channels from the server config
|
||||||
|
const IGNORED_CHANNELS = await getGuildConfig(
|
||||||
|
message.guild.id,
|
||||||
|
"ignoredChannels",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ignore ignored channels
|
||||||
|
if (
|
||||||
|
!Array.isArray(IGNORED_CHANNELS) ||
|
||||||
|
(Array.isArray(IGNORED_CHANNELS) &&
|
||||||
|
IGNORED_CHANNELS.includes(message.channel.id))
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore messages from a bot
|
||||||
|
if (message.author.bot) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.INFO("Message create", message);
|
||||||
|
|
||||||
|
// Set presence for reading message
|
||||||
|
const messagePm = new PresenceManager(message.client);
|
||||||
|
await messagePm.setPresence("online", "WATCHING", "latest messages");
|
||||||
|
|
||||||
|
// Check if the message mentions the bot
|
||||||
|
if (message.mentions.users.has(nodeIo.serverClient.user.id)) {
|
||||||
|
const interaction = await gptInteraction(nodeIo, message);
|
||||||
|
|
||||||
|
// Reset the presence
|
||||||
|
await messagePm.resetToDefault();
|
||||||
|
|
||||||
|
return interaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the message contains a link in a channel it shouldn't
|
||||||
|
await linkCop(nodeIo, message);
|
||||||
|
|
||||||
|
// Reset the presence
|
||||||
|
await messagePm.resetToDefault();
|
||||||
|
}
|
||||||
115
src/discordBot/modules/presenceManager.mjs
Normal file
115
src/discordBot/modules/presenceManager.mjs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
import {
|
||||||
|
getConfig,
|
||||||
|
setConfig,
|
||||||
|
} from "../../modules/mongo-wrappers/mongoConfigWrappers.mjs";
|
||||||
|
import { ActivityType, PresenceUpdateStatus } from "discord.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control the presence or activity of the discord bot.
|
||||||
|
*/
|
||||||
|
class PresenceManager {
|
||||||
|
/**
|
||||||
|
* Creates an instance of PresenceManager.
|
||||||
|
* @param {Client} client - The Discord client instance.
|
||||||
|
*/
|
||||||
|
constructor(client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the bot's presence.
|
||||||
|
* @param {"online"|"idle"|"dnd"} status - The status of the bot (online, idle, dnd).
|
||||||
|
* @param {"PLAYING"|"STREAMING"|"LISTENING"|"WATCHING"|"COMPETING"} activityType - The type of activity.
|
||||||
|
* @param {string} activityName - The name of the activity.
|
||||||
|
* @param {string} [url=null] - The URL for STREAMING activity type (optional).
|
||||||
|
*/
|
||||||
|
async setPresence(status, activityType, activityName, url = null) {
|
||||||
|
const activityOptions = {
|
||||||
|
type: this.convertActivityType(activityType),
|
||||||
|
name: activityName,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (activityType.toUpperCase() === "STREAMING" && url) {
|
||||||
|
activityOptions.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.client.user.setPresence({
|
||||||
|
status: this.convertStatus(status),
|
||||||
|
activities: [activityOptions],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the bot's presence to the default state.
|
||||||
|
*/
|
||||||
|
async resetToDefault() {
|
||||||
|
let defaultPresence = await getConfig("presence");
|
||||||
|
|
||||||
|
if (!defaultPresence) {
|
||||||
|
defaultPresence = {
|
||||||
|
status: "idle",
|
||||||
|
activities: [
|
||||||
|
{
|
||||||
|
name: "your commands",
|
||||||
|
type: "LISTENING",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
await setConfig("presence", defaultPresence);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Default Presence:", defaultPresence);
|
||||||
|
|
||||||
|
// Update your bot's presence using this configuration
|
||||||
|
await this.setPresence(
|
||||||
|
defaultPresence.status,
|
||||||
|
defaultPresence.activities[0].type,
|
||||||
|
defaultPresence.activities[0].name,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a string activity type to the corresponding ActivityType enum.
|
||||||
|
* @param {string} activityType - The activity type string.
|
||||||
|
* @returns {ActivityType} - The corresponding ActivityType enum.
|
||||||
|
*/
|
||||||
|
convertActivityType(activityType) {
|
||||||
|
switch (activityType.toUpperCase()) {
|
||||||
|
case "PLAYING":
|
||||||
|
return ActivityType.Playing;
|
||||||
|
case "STREAMING":
|
||||||
|
return ActivityType.Streaming;
|
||||||
|
case "LISTENING":
|
||||||
|
return ActivityType.Listening;
|
||||||
|
case "WATCHING":
|
||||||
|
return ActivityType.Watching;
|
||||||
|
case "COMPETING":
|
||||||
|
return ActivityType.Competing;
|
||||||
|
default:
|
||||||
|
throw new Error("Invalid activity type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a string status to the corresponding PresenceUpdateStatus enum.
|
||||||
|
* @param {string} status - The status string.
|
||||||
|
* @returns {PresenceUpdateStatus} - The corresponding PresenceUpdateStatus enum.
|
||||||
|
*/
|
||||||
|
convertStatus(status) {
|
||||||
|
switch (status.toLowerCase()) {
|
||||||
|
case "online":
|
||||||
|
return PresenceUpdateStatus.Online;
|
||||||
|
case "idle":
|
||||||
|
return PresenceUpdateStatus.Idle;
|
||||||
|
case "dnd":
|
||||||
|
return PresenceUpdateStatus.DoNotDisturb;
|
||||||
|
case "invisible":
|
||||||
|
return PresenceUpdateStatus.Invisible;
|
||||||
|
default:
|
||||||
|
throw new Error("Invalid status");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PresenceManager;
|
||||||
@@ -4,7 +4,6 @@ import {
|
|||||||
checkIfNodeIsConnectedToVC,
|
checkIfNodeIsConnectedToVC,
|
||||||
getNodeDiscordID,
|
getNodeDiscordID,
|
||||||
getNodeDiscordUsername,
|
getNodeDiscordUsername,
|
||||||
checkIfNodeHasOpenDiscordClient,
|
|
||||||
getNodeCurrentListeningSystem,
|
getNodeCurrentListeningSystem,
|
||||||
requestNodeJoinSystem,
|
requestNodeJoinSystem,
|
||||||
} from "../../modules/socketServerWrappers.mjs";
|
} from "../../modules/socketServerWrappers.mjs";
|
||||||
@@ -86,9 +85,8 @@ export const getAvailableNodes = async (nodeIo, guildId, system) => {
|
|||||||
openSockets.map(async (openSocket) => {
|
openSockets.map(async (openSocket) => {
|
||||||
openSocket = await nodeIo.sockets.sockets.get(openSocket);
|
openSocket = await nodeIo.sockets.sockets.get(openSocket);
|
||||||
// Check if the node has an existing open client (meaning the radio is already being listened to)
|
// Check if the node has an existing open client (meaning the radio is already being listened to)
|
||||||
const hasOpenClient = await checkIfNodeHasOpenDiscordClient(openSocket);
|
let currentSystem = await getNodeCurrentListeningSystem(openSocket);
|
||||||
if (hasOpenClient) {
|
if (currentSystem) {
|
||||||
let currentSystem = await getNodeCurrentListeningSystem(openSocket);
|
|
||||||
if (currentSystem != system.name) {
|
if (currentSystem != system.name) {
|
||||||
log.INFO(
|
log.INFO(
|
||||||
"Node is listening to a different system than requested",
|
"Node is listening to a different system than requested",
|
||||||
113
src/modules/mongo-wrappers/mongoConfigWrappers.mjs
Normal file
113
src/modules/mongo-wrappers/mongoConfigWrappers.mjs
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
import {
|
||||||
|
getDocumentByField,
|
||||||
|
deleteDocumentByField,
|
||||||
|
getDocumentByFields,
|
||||||
|
upsertDocumentByField,
|
||||||
|
deleteDocumentByFields,
|
||||||
|
upsertDocumentByFields,
|
||||||
|
} from "./mongoHandler.mjs"; // Import your MongoDB handlers
|
||||||
|
import { DebugBuilder } from "../debugger.mjs";
|
||||||
|
|
||||||
|
const log = new DebugBuilder("server", "mongoConfigWrappers");
|
||||||
|
|
||||||
|
const collectionName = "configurations";
|
||||||
|
|
||||||
|
// Function to get a configuration by key
|
||||||
|
export const getConfig = async (key) => {
|
||||||
|
try {
|
||||||
|
const config = await getDocumentByField(collectionName, "key", key);
|
||||||
|
log.DEBUG(`Configuration for key "${key}" retrieved:`, config);
|
||||||
|
return config ? config[key] : null; // Return null if no configuration is found
|
||||||
|
} catch (error) {
|
||||||
|
log.ERROR("Error retrieving configuration:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to set a configuration by key
|
||||||
|
export const setConfig = async (key, value) => {
|
||||||
|
// Set the config object
|
||||||
|
value = { key: value };
|
||||||
|
try {
|
||||||
|
const result = await upsertDocumentByField(
|
||||||
|
collectionName,
|
||||||
|
"key",
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
);
|
||||||
|
log.DEBUG(`Configuration for key "${key}" set:`, value, result);
|
||||||
|
return result > 0 ? key : null; // Return key if updated successfully, otherwise null
|
||||||
|
} catch (error) {
|
||||||
|
log.ERROR("Error setting configuration:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to delete a configuration by key (optional)
|
||||||
|
export const deleteConfig = async (key) => {
|
||||||
|
try {
|
||||||
|
const result = await deleteDocumentByField(collectionName, "key", key);
|
||||||
|
log.DEBUG(`Configuration for key "${key}" deleted:`, result);
|
||||||
|
return result; // Return the count of deleted documents
|
||||||
|
} catch (error) {
|
||||||
|
log.ERROR("Error deleting configuration:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to get a configuration by key for a specific guild
|
||||||
|
export const getGuildConfig = async (guildId, key) => {
|
||||||
|
try {
|
||||||
|
const config = await getDocumentByFields(
|
||||||
|
collectionName,
|
||||||
|
["guild", Number(guildId)],
|
||||||
|
["key", key],
|
||||||
|
);
|
||||||
|
log.DEBUG(
|
||||||
|
`Guild ${guildId} configuration for key "${key}" retrieved:`,
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
return config ? config[key] : null; // Return null if no configuration is found
|
||||||
|
} catch (error) {
|
||||||
|
log.ERROR("Error retrieving guild configuration:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to set a configuration by key for a specific guild
|
||||||
|
export const setGuildConfig = async (guildId, key, value) => {
|
||||||
|
// Set the config object
|
||||||
|
value = { key: value };
|
||||||
|
try {
|
||||||
|
const result = await upsertDocumentByFields(
|
||||||
|
collectionName,
|
||||||
|
value,
|
||||||
|
["guild", Number(guildId)],
|
||||||
|
["key", key],
|
||||||
|
);
|
||||||
|
log.DEBUG(`Guild ${guildId} configuration for key "${key}" set:`, value);
|
||||||
|
return result > 0 ? key : null; // Return key if updated successfully, otherwise null
|
||||||
|
} catch (error) {
|
||||||
|
log.ERROR("Error setting guild configuration:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to delete a configuration by key for a specific guild (optional)
|
||||||
|
export const deleteGuildConfig = async (guildId, key) => {
|
||||||
|
try {
|
||||||
|
const result = await deleteDocumentByFields(
|
||||||
|
collectionName,
|
||||||
|
["guild", Number(guildId)],
|
||||||
|
["key", key],
|
||||||
|
);
|
||||||
|
log.DEBUG(
|
||||||
|
`Guild ${guildId} configuration for key "${key}" deleted:`,
|
||||||
|
result,
|
||||||
|
);
|
||||||
|
return result; // Return the count of deleted documents
|
||||||
|
} catch (error) {
|
||||||
|
log.ERROR("Error deleting guild configuration:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -71,6 +71,22 @@ export const updateFeedByLink = async (link, updatedFields) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Wrapper for deactivating a feed by link
|
||||||
|
export const deactivateFeedByLink = async (link) => {
|
||||||
|
try {
|
||||||
|
const updatedCount = await updateDocumentByField(
|
||||||
|
feedCollectionName,
|
||||||
|
"link",
|
||||||
|
link,
|
||||||
|
[{'active':false}]
|
||||||
|
);
|
||||||
|
return updatedCount;
|
||||||
|
} catch (error) {
|
||||||
|
log.ERROR("Error deleting feed by link:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Wrapper for deleting a feed by link
|
// Wrapper for deleting a feed by link
|
||||||
export const deleteFeedByLink = async (link) => {
|
export const deleteFeedByLink = async (link) => {
|
||||||
try {
|
try {
|
||||||
@@ -59,10 +59,26 @@ export const getDocuments = async (collectionName) => {
|
|||||||
// Function to retrieve a document by a specific field
|
// Function to retrieve a document by a specific field
|
||||||
export const getDocumentByField = async (collectionName, field, value) => {
|
export const getDocumentByField = async (collectionName, field, value) => {
|
||||||
log.DEBUG("Getting document by field:", collectionName, field, value);
|
log.DEBUG("Getting document by field:", collectionName, field, value);
|
||||||
|
return await getDocumentByFields(collectionName, [field, value]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to retrieve a document by multiple fields
|
||||||
|
export const getDocumentByFields = async (
|
||||||
|
collectionName,
|
||||||
|
...fieldValuePairs
|
||||||
|
) => {
|
||||||
|
log.DEBUG("Getting document by fields:", collectionName, fieldValuePairs);
|
||||||
const db = await connectToDatabase();
|
const db = await connectToDatabase();
|
||||||
try {
|
try {
|
||||||
const collection = db.db().collection(collectionName);
|
const collection = db.db().collection(collectionName);
|
||||||
const document = await collection.findOne({ [field]: value });
|
|
||||||
|
// Convert the fieldValuePairs array into an object
|
||||||
|
const query = fieldValuePairs.reduce((acc, [field, value]) => {
|
||||||
|
acc[field] = value;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const document = await collection.findOne(query);
|
||||||
return document;
|
return document;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error retrieving document:", error);
|
console.error("Error retrieving document:", error);
|
||||||
@@ -72,12 +88,55 @@ export const getDocumentByField = async (collectionName, field, value) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Function to update a document by a specific field
|
||||||
|
export const upsertDocumentByField = async (
|
||||||
|
collectionName,
|
||||||
|
field,
|
||||||
|
value,
|
||||||
|
updatedFields,
|
||||||
|
) => {
|
||||||
|
log.DEBUG(
|
||||||
|
"Upsert document by field:",
|
||||||
|
collectionName,
|
||||||
|
field,
|
||||||
|
value,
|
||||||
|
updatedFields,
|
||||||
|
);
|
||||||
|
return await updateDocumentByFields(
|
||||||
|
collectionName,
|
||||||
|
updatedFields,
|
||||||
|
{ upsert: true },
|
||||||
|
[field, value],
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to update a document by a specific field
|
||||||
|
export const upsertDocumentByFields = async (
|
||||||
|
collectionName,
|
||||||
|
updatedFields,
|
||||||
|
...fieldValuePairs
|
||||||
|
) => {
|
||||||
|
log.DEBUG(
|
||||||
|
"Upsert document by fields:",
|
||||||
|
collectionName,
|
||||||
|
updatedFields,
|
||||||
|
fieldValuePairs,
|
||||||
|
);
|
||||||
|
return await updateDocumentByFields(
|
||||||
|
collectionName,
|
||||||
|
updatedFields,
|
||||||
|
{ upsert: true },
|
||||||
|
fieldValuePairs,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// Function to update a document by a specific field
|
// Function to update a document by a specific field
|
||||||
export const updateDocumentByField = async (
|
export const updateDocumentByField = async (
|
||||||
collectionName,
|
collectionName,
|
||||||
field,
|
field,
|
||||||
value,
|
value,
|
||||||
updatedFields,
|
updatedFields,
|
||||||
|
options = null,
|
||||||
) => {
|
) => {
|
||||||
log.DEBUG(
|
log.DEBUG(
|
||||||
"Update document by field:",
|
"Update document by field:",
|
||||||
@@ -85,13 +144,42 @@ export const updateDocumentByField = async (
|
|||||||
field,
|
field,
|
||||||
value,
|
value,
|
||||||
updatedFields,
|
updatedFields,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
return await updateDocumentByFields(collectionName, updatedFields, options, [
|
||||||
|
field,
|
||||||
|
value,
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to update a document by multiple fields
|
||||||
|
export const updateDocumentByFields = async (
|
||||||
|
collectionName,
|
||||||
|
updatedFields,
|
||||||
|
options,
|
||||||
|
...fieldValuePairs
|
||||||
|
) => {
|
||||||
|
log.DEBUG(
|
||||||
|
"Update document by fields:",
|
||||||
|
collectionName,
|
||||||
|
updatedFields,
|
||||||
|
options,
|
||||||
|
fieldValuePairs,
|
||||||
);
|
);
|
||||||
const db = await connectToDatabase();
|
const db = await connectToDatabase();
|
||||||
try {
|
try {
|
||||||
const collection = db.db().collection(collectionName);
|
const collection = db.db().collection(collectionName);
|
||||||
|
|
||||||
|
// Convert the fieldValuePairs array into an object
|
||||||
|
const query = fieldValuePairs.reduce((acc, [field, value]) => {
|
||||||
|
acc[field] = value;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
const result = await collection.updateOne(
|
const result = await collection.updateOne(
|
||||||
{ [field]: value },
|
query,
|
||||||
{ $set: updatedFields },
|
{ $set: updatedFields },
|
||||||
|
options,
|
||||||
);
|
);
|
||||||
log.DEBUG("Document updated:", result.modifiedCount);
|
log.DEBUG("Document updated:", result.modifiedCount);
|
||||||
return result.modifiedCount;
|
return result.modifiedCount;
|
||||||
@@ -106,10 +194,26 @@ export const updateDocumentByField = async (
|
|||||||
// Function to delete a document by a specific field
|
// Function to delete a document by a specific field
|
||||||
export const deleteDocumentByField = async (collectionName, field, value) => {
|
export const deleteDocumentByField = async (collectionName, field, value) => {
|
||||||
log.DEBUG("Delete document by field:", collectionName, field, value);
|
log.DEBUG("Delete document by field:", collectionName, field, value);
|
||||||
|
return await deleteDocumentByFields(collectionName, [field, value]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to delete a document by multiple fields
|
||||||
|
export const deleteDocumentByFields = async (
|
||||||
|
collectionName,
|
||||||
|
...fieldValuePairs
|
||||||
|
) => {
|
||||||
|
log.DEBUG("Delete document by fields:", collectionName, fieldValuePairs);
|
||||||
const db = await connectToDatabase();
|
const db = await connectToDatabase();
|
||||||
try {
|
try {
|
||||||
const collection = db.db().collection(collectionName);
|
const collection = db.db().collection(collectionName);
|
||||||
const result = await collection.deleteOne({ [field]: value });
|
|
||||||
|
// Convert the fieldValuePairs array into an object
|
||||||
|
const query = fieldValuePairs.reduce((acc, [field, value]) => {
|
||||||
|
acc[field] = value;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const result = await collection.deleteOne(query);
|
||||||
log.DEBUG("Document deleted:", result.deletedCount);
|
log.DEBUG("Document deleted:", result.deletedCount);
|
||||||
return result.deletedCount;
|
return result.deletedCount;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -10,6 +10,7 @@ import { DebugBuilder } from "../modules/debugger.mjs";
|
|||||||
import { removeSource } from "./sourceManager.mjs";
|
import { removeSource } from "./sourceManager.mjs";
|
||||||
import UserAgent from "user-agents";
|
import UserAgent from "user-agents";
|
||||||
import Parser from "rss-parser";
|
import Parser from "rss-parser";
|
||||||
|
import PresenceManager from "../discordBot/modules/presenceManager.mjs";
|
||||||
|
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
@@ -41,11 +42,19 @@ export const returnHash = (...stringsIncluded) => {
|
|||||||
export const updateFeeds = async (client) => {
|
export const updateFeeds = async (client) => {
|
||||||
if (!client) throw new Error("Client object not passed");
|
if (!client) throw new Error("Client object not passed");
|
||||||
|
|
||||||
|
// Setup presence manager
|
||||||
|
const feedPm = new PresenceManager(client);
|
||||||
|
await feedPm.setPresence("online", "WATCHING", "for RSS feed updates");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const records = await getAllFeeds();
|
const records = await getAllFeeds();
|
||||||
|
|
||||||
const sourcePromiseArray = records.map(async (source) => {
|
const sourcePromiseArray = records.map(async (source) => {
|
||||||
log.DEBUG("Processing source:", source.title);
|
log.DEBUG("Processing source:", source.title);
|
||||||
|
// Check if the feed is active
|
||||||
|
if (!source.active) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const parsedFeed = await parser.parseURL(source.link);
|
const parsedFeed = await parser.parseURL(source.link);
|
||||||
@@ -106,6 +115,7 @@ export const updateFeeds = async (client) => {
|
|||||||
|
|
||||||
await Promise.all(sourcePromiseArray);
|
await Promise.all(sourcePromiseArray);
|
||||||
log.DEBUG("All sources processed");
|
log.DEBUG("All sources processed");
|
||||||
|
await feedPm.resetToDefault();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.ERROR("Error updating feeds:", error);
|
log.ERROR("Error updating feeds:", error);
|
||||||
throw error;
|
throw error;
|
||||||
@@ -3,7 +3,7 @@ const log = new DebugBuilder("server", "sourceManager");
|
|||||||
import {
|
import {
|
||||||
createFeed,
|
createFeed,
|
||||||
getFeedByLink,
|
getFeedByLink,
|
||||||
deleteFeedByLink,
|
deactivateFeedByLink,
|
||||||
} from "../modules/mongo-wrappers/mongoFeedsWrappers.mjs";
|
} from "../modules/mongo-wrappers/mongoFeedsWrappers.mjs";
|
||||||
|
|
||||||
class SourceManager {
|
class SourceManager {
|
||||||
@@ -48,7 +48,7 @@ class SourceManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = await deleteFeedByLink(sourceURL);
|
const results = await deactivateFeedByLink(sourceURL);
|
||||||
if (!results) {
|
if (!results) {
|
||||||
log.WARN(`Failed to remove source: ${sourceURL}`);
|
log.WARN(`Failed to remove source: ${sourceURL}`);
|
||||||
return;
|
return;
|
||||||
@@ -70,6 +70,7 @@ class SourceManager {
|
|||||||
category,
|
category,
|
||||||
guild_id: guildId,
|
guild_id: guildId,
|
||||||
channel_id: channelId,
|
channel_id: channelId,
|
||||||
|
active: true
|
||||||
};
|
};
|
||||||
const record = await createFeed(feed);
|
const record = await createFeed(feed);
|
||||||
log.DEBUG("Source added:", record);
|
log.DEBUG("Source added:", record);
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
import { DebugBuilder } from "./modules/debugger.mjs";
|
import { DebugBuilder } from "./modules/debugger.mjs";
|
||||||
const log = new DebugBuilder("server", "server");
|
const log = new DebugBuilder("server", "server");
|
||||||
import { nodeIo, app, server } from "./modules/socketServer.mjs";
|
import { nodeIo, server } from "./modules/socketServer.mjs";
|
||||||
import { loadAddons } from "./modules/addonManager.mjs";
|
import { loadAddons } from "./modules/addonManager.mjs";
|
||||||
import {
|
import { serverClient } from "./discordBot/discordBot.mjs";
|
||||||
serverClient,
|
|
||||||
addEnabledEventListeners,
|
|
||||||
} from "./discordBot/discordBot.mjs";
|
|
||||||
|
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
@@ -4,11 +4,11 @@ import ioClient from "socket.io-client";
|
|||||||
import {
|
import {
|
||||||
deleteNodeByNuid,
|
deleteNodeByNuid,
|
||||||
getNodeByNuid,
|
getNodeByNuid,
|
||||||
} from "../modules/mongo-wrappers/mongoNodesWrappers.mjs";
|
} from "../src/modules/mongo-wrappers/mongoNodesWrappers.mjs";
|
||||||
import {
|
import {
|
||||||
deleteSystemByName,
|
deleteSystemByName,
|
||||||
getSystemByName,
|
getSystemByName,
|
||||||
} from "../modules/mongo-wrappers/mongoSystemsWrappers.mjs";
|
} from "../src/modules/mongo-wrappers/mongoSystemsWrappers.mjs";
|
||||||
import {
|
import {
|
||||||
nodeDisconnectWrapper,
|
nodeDisconnectWrapper,
|
||||||
checkIfNodeHasOpenDiscordClient,
|
checkIfNodeHasOpenDiscordClient,
|
||||||
@@ -19,8 +19,8 @@ import {
|
|||||||
requestBotLeaveServer,
|
requestBotLeaveServer,
|
||||||
requestNodeJoinSystem,
|
requestNodeJoinSystem,
|
||||||
requestNodeUpdate,
|
requestNodeUpdate,
|
||||||
} from "../modules/socketServerWrappers.mjs";
|
} from "../src/modules/socketServerWrappers.mjs";
|
||||||
import { nodeIo } from "../modules/socketServer.mjs";
|
import { nodeIo } from "../src/modules/socketServer.mjs";
|
||||||
|
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|||||||
Reference in New Issue
Block a user