First Commit

This commit is contained in:
Raven Scott 2023-03-25 19:09:44 +02:00
commit 0ec7419cb7
12 changed files with 416 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
node_modules
.env
package-lock.json
cache

38
README.md Normal file
View File

@ -0,0 +1,38 @@
# rAI - Serge Discord Bot
This readme is incomplete.
Message intents are NOT supported in this bot, this is due to the verification that Discord is enabling.
Structure:
**commands** - This folder contains commands
**event** - This folder contains files related to discord.js events. (Like "ready", "interactionCreate")
**handler** - This folder contains files that read the commands folders contents.
**index.js** - This is the main file to run the bot.
1) Use ```npm i ```
2) Create a .env file ``` touch .env```
3) Edit .env
```
TOKEN = token
INTERNAL_IP =
PUBLIC_URL =
```
4) Go to Handler -- > index.js and change "GUIDIDHERE" to your Discord Server's Guild ID
5) Go into https://discord.com/developers/applications and enable Privileged Intents.
6) Run the bot ```node index.js```
Want to make this better? Issue a pull request!

21
commands/Info/about.js Normal file
View File

@ -0,0 +1,21 @@
const { EmbedBuilder } = require('discord.js');
let cpu = require('cpu-load')
module.exports = {
name: "about",
description: "Info about the bot",
run: async (client, interaction) => {
cpu(1000, function (load) {
const embed = new EmbedBuilder()
.setColor("#FF0000")
.setTitle("About rAI")
.setDescription(`Latency : ${client.ws.ping}ms\n\nrAI is a bot managed by \`snxraven#8205\` running an LLM called Alpaca.\n\nSpecs: Intel i7-1065G7 (8) @ 3.900GHz with 11 GB of RAM\nChat is set to 7 Threads\nConfigured Memory Speed: 3733 MT/s\nUSB Liveboot\n\nSingle Task Only - 256 Max Token Output`)
.setTimestamp()
.setFooter({ text: `Requested by ${interaction.user.tag}`, iconURL: `${interaction.user.displayAvatarURL()}` });
interaction.followUp({ embeds: [embed] });
})
},
};

58
commands/Info/chat.js Normal file
View File

@ -0,0 +1,58 @@
const { MessageEmbed } = require('discord.js');
const axios = require('axios');
const jsonfile = require('jsonfile');
let session2;
let isProcessing = false; // Semaphore variable
module.exports = {
name: 'chat',
description: 'Chat with Alpaca using rAI',
options: [{
"name": "query",
"description": "The thing you want to ask",
"required": true,
"type": 3 // 6 is type USER
}],
run: async (client, interaction) => {
const file = './cache/' + interaction.user.id;
let chatToSend = interaction.options._hoistedOptions[0].value;
// Check if another request is already being processed
if (isProcessing) {
interaction.editReply('Sorry, another request is already being processed. Please try again in a few minutes.');
return;
}
// Set the semaphore to true
isProcessing = true;
await jsonfile.readFile(file, async function (err, session) {
if (err) return interaction.editReply('Please create a session using /create-session.');
session2 = session.id;
if (!session2) {
console.log("No Session!");
isProcessing = false;
return;
}
let prompt = interaction.options._hoistedOptions[0].value.replace(" ", "+");
const headers = {
'authority': 'rai.snxraven.me',
'accept': 'text/event-stream',
};
console.log(session);
const response = await axios.post(`http://${process.env.INTERNAL_IP}:8008/api/chat/` + session2 + '/question?prompt=' + prompt, {
headers
});
console.log(response.data.answer);
interaction.editReply(response.data.answer);
// Set the semaphore to false
isProcessing = false;
});
},
};

38
commands/Info/new-chat.js Normal file
View File

@ -0,0 +1,38 @@
const { EmbedBuilder } = require('discord.js');
var unirest = require('unirest');
const jsonfile = require('jsonfile')
module.exports = {
name: "create-session",
description: "create a new session chat",
private: true,
run: async (client, interaction) => {
const file = './cache/' + interaction.user.id
unirest
.post(`https://${process.env.PUBLIC_URL}/api/chat`)
.headers({ 'Accept': 'application/json', 'Content-Type': 'application/json' })
.auth({
user: 'rai',
pass: 'ilikeai',
sendImmediately: true
})
.then((response) => {
console.log(response)
const obj = { id: response.body }
jsonfile.writeFile(file, obj, function (err) {
if (err) console.error(err)
})
const embed = new EmbedBuilder()
.setColor("#FF0000")
.setTitle("New Chat Session Started!")
.setDescription(`New Chat Session ID: \n` + response.body)
.setTimestamp()
.setFooter({ text: `Requested by ${interaction.user.tag}`, iconURL: `${interaction.user.displayAvatarURL()}` });
interaction.followUp({ embeds: [embed] });
})
},
};

View File

@ -0,0 +1,27 @@
const { EmbedBuilder } = require('discord.js');
var unirest = require('unirest');
const jsonfile = require('jsonfile')
module.exports = {
name: "view-session-id",
description: "View your currently assigned session ID",
private: true,
run: async (client, interaction) => {
const file = './cache/' + interaction.user.id
jsonfile.readFile(file, function (err, obj) {
if (err) return interaction.editReply('Please create a session using /create-session.');
console.dir(obj)
const embed = new EmbedBuilder()
.setColor("#FF0000")
.setTitle("New Chat Session Started!")
.setDescription(`Current Session ID: \n` + obj.id)
.setTimestamp()
.setFooter({ text: `Requested by ${interaction.user.tag}`, iconURL: `${interaction.user.displayAvatarURL()}` });
interaction.followUp({ embeds: [embed] });
})
},
};

View File

@ -0,0 +1,56 @@
const axios = require('axios');
const jsonfile = require('jsonfile');
let session2;
function parseQuestionsAndAnswers(jsonStr) {
const obj = JSON.parse(jsonStr);
const questions = obj.questions;
const answers = questions.map(q => q.answer);
return { questions, answers };
}
module.exports = {
name: "view-session-history",
description: "View your current conversation.",
run: async (client, interaction) => {
const file = './cache/' + interaction.user.id;
await jsonfile.readFile(file, async function (err, session) {
if (err) return interaction.editReply('Please create a session using /create-session.');
session2 = session.id;
if (!session2) {
console.log("No Session!");
isProcessing = false;
return;
}
const headers = {
'authority': 'rai.snxraven.me',
'accept': 'text/event-stream',
};
const response = await axios.get(`http://${process.env.INTERNAL_IP}:8008/api/chat/` + session2, {
headers,
auth: {
username: "rai",
password: "ilikeai"
}
});
console.log(response.data)
if (!response.data.questions) return interaction.editReply("You have no history in this session yet :) ");
const result = parseQuestionsAndAnswers(JSON.stringify(response.data));
let pairsString = "";
for (const question of result.questions) {
pairsString += `***Question:*** ${question.question}\n***Answer:*** ${question.answer}\n`;
}
interaction.editReply(pairsString);
})
if (err) console.error("woo" + err)
},
};

View File

@ -0,0 +1,94 @@
const client = require("../rai");
require("dotenv").config();
const { glob } = require("glob");
const { promisify } = require("util");
const globPromise = promisify(glob);
client.on("interactionCreate", async (interaction) => {
// Slash Commands
const slashCommands = await globPromise(`${process.cwd()}/commands/*/*.js`);
const arrayOfSlashCommands = [];
// Map the slash commands into data to be processed
slashCommands.map((value) => {
const file = require(value);
const splitted = value.split("/");
const directory = splitted[splitted.length - 2];
if (!file?.name) return;
const properties = {
directory,
...file
};
client.slashCommands.set(file.name, properties);
if (["MESSAGE", "USER"].includes(file.type)) delete file.description;
// Push the data
arrayOfSlashCommands.push(file);
});
// Slash Command Handling
if (interaction.isChatInputCommand()) {
// Grabbing Command Data for this interaction
let commandData = []
// We use ForEach here to filter our array into the single commands info.
await arrayOfSlashCommands.forEach(command => {
if (command.name == interaction.commandName) {
commandData.push(command)
}
});
// Process and Parse Data
let dataToProcess = JSON.stringify(commandData[0])
let parsedData = JSON.parse(dataToProcess)
// If the command is private, set ephemeral true else, set false
console.log(parsedData)
if (parsedData.private == true) {
await interaction.deferReply({
ephemeral: true
}).catch(() => {});
} else {
await interaction.deferReply({
ephemeral: false
}).catch(() => {});
}
const cmd = client.slashCommands.get(interaction.commandName);
if (!cmd)
return interaction.followUp({
content: "An error has occurred "
});
const args = [];
for (let option of interaction.options.data) {
if (option.type === "SUB_COMMAND") {
if (option.name) args.push(option.name);
option.options?.forEach((x) => {
if (x.value) args.push(x.value);
});
} else if (option.value) args.push(option.value);
}
interaction.member = interaction.guild.members.cache.get(interaction.user.id);
cmd.run(client, interaction, args);
}
// Context Menu Handling
if (interaction.isContextMenuCommand()) {
await interaction.deferReply({
ephemeral: false
});
const command = client.slashCommands.get(interaction.commandName);
if (command) command.run(client, interaction);
}
});

5
events/ready.js Normal file
View File

@ -0,0 +1,5 @@
const client = require("../rai");
client.on("ready", () => {
console.log(`${client.user.tag} is up and ready to go!`);
});

37
handler/index.js Normal file
View File

@ -0,0 +1,37 @@
require("dotenv").config();
const { glob } = require("glob");
const { promisify } = require("util");
const globPromise = promisify(glob);
module.exports = async (client) => {
// Slash Commands
const slashCommands = await globPromise(`${process.cwd()}/commands/*/*.js`);
const arrayOfSlashCommands = [];
slashCommands.map((value) => {
const file = require(value);
const splitted = value.split("/");
const directory = splitted[splitted.length - 2];
if (!file?.name) return;
const properties = { directory, ...file };
client.slashCommands.set(file.name, properties);
if (["MESSAGE", "USER"].includes(file.type)) delete file.description;
arrayOfSlashCommands.push(file);
});
// Events
const eventFiles = await globPromise(`${process.cwd()}/events/*.js`);
eventFiles.map((value) => require(value));
// Slash Commands Register
client.on("ready", async () => {
// // Register for a single guild
// await client.guilds.cache.get("GUIDIDHERE").commands.set(arrayOfSlashCommands);
// Register for all the guilds the bot is in
await client.application.commands.set(arrayOfSlashCommands);
});
};

24
package.json Normal file
View File

@ -0,0 +1,24 @@
{
"name": "dlinuxtemplatev14",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^1.3.4",
"cpu-load": "^1.0.0",
"discord.js": "^14.0.3",
"dotenv": "^16.0.3",
"glob": "^7.2.0",
"jsonfile": "^6.1.0",
"node-fetch": "^2.6.9",
"node-free": "^1.0.0",
"sysstats": "^1.0.1",
"unirest": "^0.6.0"
}
}

14
rai.js Normal file
View File

@ -0,0 +1,14 @@
require("dotenv").config();
const { Client, Collection } = require("discord.js");
const client = new Client({ intents: 4097 });
module.exports = client;
// Global Variables
client.commands = new Collection();
client.slashCommands = new Collection();
// Initializing the project
require("./handler")(client);
client.login(process.env.TOKEN);