V1.1.0-dev-3 (#6)
* New Name, New Version * New default branch name * Migrate to database for long term storage * Fix uncaught call to a promise * Reverse the leaderboard * QoL and Bug fixes * Handle server timeout * Pretty help message
This commit is contained in:
parent
1433b723c3
commit
83a05374cf
4
.github/workflows/docker-image.yml
vendored
4
.github/workflows/docker-image.yml
vendored
@ -2,9 +2,9 @@ name: Docker Image CI
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ "master" ]
|
branches: [ "main" ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ "master" ]
|
branches: [ "main" ]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DHUB_UNAME: ${{ secrets.DHUB_UNAME }}
|
DHUB_UNAME: ${{ secrets.DHUB_UNAME }}
|
||||||
|
39
README.md
39
README.md
@ -15,30 +15,33 @@ Add the bot to your server and make sure it has the proper permissions (`Send Me
|
|||||||
|
|
||||||
## Database Structure
|
## Database Structure
|
||||||
|
|
||||||
### Table: guildinfo
|
### Table: guild_info
|
||||||
```
|
```
|
||||||
+-----------------+-------------+------+-----+---------+----------------+
|
+------------------------+-------------+------+-----+---------+----------------+
|
||||||
| Field | Type | Null | Key | Default | Extra |
|
| Field | Type | Null | Key | Default | Extra |
|
||||||
+-----------------+-------------+------+-----+---------+----------------+
|
+------------------------+-------------+------+-----+---------+----------------+
|
||||||
| id | int(10) | NO | PRI | NULL | auto_increment |
|
| guild_id | varchar(50) | NO | PRI | NULL | auto_increment |
|
||||||
| guild_id | varchar(50) | NO | | NULL | |
|
| tree_message_id | varchar(50) | NO | | | |
|
||||||
| tree_message_id | varchar(50) | NO | | NULL | |
|
| tree_channel_id | varchar(50) | NO | | | |
|
||||||
| tree_channel_id | varchar(50) | NO | | NULL | |
|
| leaderboard_message_id | varchar(50) | NO | | | |
|
||||||
| rank_message_id | varchar(50) | NO | | NULL | |
|
| leaderboard_channel_id | varchar(50) | NO | | | |
|
||||||
| rank_channel_id | varchar(50) | NO | | NULL | |
|
| tree_height | varchar(10) | NO | | 0 | |
|
||||||
| tree_height | varchar(10) | NO | | NULL | |
|
+------------------------+-------------+------+-----+---------+----------------+
|
||||||
+-----------------+-------------+------+-----+---------+----------------+
|
|
||||||
```
|
```
|
||||||
### Table: treeinfo
|
### Table: leaderboard_info
|
||||||
```
|
```
|
||||||
+-----------+--------------+------+-----+---------+----------------+
|
+-------------+--------------+------+-----+---------+----------------+
|
||||||
| Field | Type | Null | Key | Default | Extra |
|
| Field | Type | Null | Key | Default | Extra |
|
||||||
+-----------+--------------+------+-----+---------+----------------+
|
+-------------+--------------+------+-----+---------+----------------+
|
||||||
| id | int(10) | NO | PRI | NULL | auto_increment |
|
| id | int(10) | NO | PRI | NULL | auto_increment |
|
||||||
| treename | varchar(100) | NO | | NULL | |
|
| guild_id | varchar(50) | NO | | | |
|
||||||
| treerank | int(10) | NO | | NULL | |
|
| tree_name | varchar(100) | NO | | | |
|
||||||
| timestamp | varchar(50) | NO | | NULL | |
|
| tree_rank | int(10) | NO | | | |
|
||||||
+-----------+--------------+------+-----+---------+----------------+
|
| tree_height | int(10) | NO | | 0 | |
|
||||||
|
| has_pin | tinyint(1) | NO | | 0 | |
|
||||||
|
| timestamp | varchar(50) | NO | | | |
|
||||||
|
+-------------+--------------+------+-----+---------+----------------+
|
||||||
```
|
```
|
||||||
|
|
||||||
## Changes to Implement
|
## Changes to Implement
|
||||||
|
@ -4,9 +4,18 @@
|
|||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"title": "Silvanus Help",
|
"title": "Silvanus Help",
|
||||||
"info": "This bot will analyze your tree (from the Grow A Tree Bot by Limbo Labs) and compare its growth to other trees displayed on the leaderboard.\n\nThis bot assumes that there is a single </tree:972648557796524032> message and a single </top trees:1051840665362894950> message that everyone uses. If everyone creates their own </tree:972648557796524032> and </top trees:1051840665362894950>, the reference messages will have to be updated every time, or old data will be displayed.\n\nSeeing old data? Try running </setup:1065407649363005561> again, sometimes configurations get lost.",
|
"info": "Silvanus is the ultimate Grow A Tree companion bot! Quickly compare your server's tree to others on the leaderboard with automatic calculation of tree height differences, active growth detection, watering time calculations, and more! Get started with </help:1065346941166297129> and </setup:1065407649363005561>, then check out </compare:1065346941166297128>.\n\nImportant Note: Silvanus is only as up-to-date as your server's Tree and Tallest Trees messages. Make sure to refresh them before refreshing Silvanus' Compare message.\n\nFor the best experience we recommend the use of a single </tree:972648557796524032> and </top trees:1051840665362894950> message, otherwise make sure to run </setup:1065407649363005561> each time you run </compare:1065346941166297128>.",
|
||||||
"setup": "To begin analyzing your Tree, first you must set up the reference messages.\n\n1. Run </setup:1065407649363005561> in the channel(s) that contain your server's tree and leaderboard messages.\n2. Now simply run </compare:1065346941166297128> where you want your analysis to be visible.",
|
"setup": "To begin analyzing your Tree, first you must set up the reference messages.\n\n1. Run </setup:1065407649363005561> in the channel(s) that contain your server's tree and leaderboard messages.\n2. Now simply run </compare:1065346941166297128> where you want your analysis to be visible.",
|
||||||
"permissions": "At a minimum, Silvanus requires permissions to `Send Messages` and `Send Messages in Threads` if applicable. If Analyzer is given permission to `Manage Messages`, the bot will delete the `.settree` and `.setranks` messages to reduce spam."
|
"permissions": "At a minimum, Silvanus requires permissions to `Send Messages` and `Send Messages in Threads` if applicable. If Analyzer is given permission to `Manage Messages`, the bot will delete the `.settree` and `.setranks` messages to reduce spam.",
|
||||||
|
"allCommands": "</compare:1065346941166297128> | </setup:1065407649363005561> | </watertime:1066970330029113444> | </setupinfo:1065413032374706196> | </reset:1065412317052944476> | </help:1065346941166297129>"
|
||||||
|
},
|
||||||
|
"commands": {
|
||||||
|
"compare": "</compare:1065346941166297128>",
|
||||||
|
"setup": "</setup:1065407649363005561>",
|
||||||
|
"watertime": "</watertime:1066970330029113444>",
|
||||||
|
"setupinfo": "</setupinfo:1065413032374706196>",
|
||||||
|
"reset": "</reset:1065412317052944476>",
|
||||||
|
"help": "</help:1065346941166297129>"
|
||||||
},
|
},
|
||||||
"embeds": {
|
"embeds": {
|
||||||
"footer": "Silvanus is not affiliated with Grow A Tree or Limbo Labs",
|
"footer": "Silvanus is not affiliated with Grow A Tree or Limbo Labs",
|
||||||
@ -20,7 +29,8 @@
|
|||||||
"cancel": "❌"
|
"cancel": "❌"
|
||||||
},
|
},
|
||||||
"urls": {
|
"urls": {
|
||||||
"avatar": "https://cdn.discordapp.com/avatars/513184762073055252/12227aa23a06d5178853e59b72c7487b.webp?size=128"
|
"avatar": "https://cdn.discordapp.com/avatars/513184762073055252/12227aa23a06d5178853e59b72c7487b.webp?size=128",
|
||||||
|
"supportServer": "https://discord.gg/g5JRGn7PxU"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"noGuild": "Setup has not been completed yet. Try running </setup:1065407649363005561> or </help setup:1065346941166297129>"
|
"noGuild": "Setup has not been completed yet. Try running </setup:1065407649363005561> or </help setup:1065346941166297129>"
|
||||||
|
4
main.js
4
main.js
@ -56,4 +56,8 @@ client.on('interactionCreate', async interaction => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
process.on('unhandledRejection', error => {
|
||||||
|
console.error('Unhandled promise rejection:', error);
|
||||||
|
});
|
||||||
|
|
||||||
client.login(token);
|
client.login(token);
|
232
modules/dbfn.js
Normal file
232
modules/dbfn.js
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
const dotenv = require('dotenv');
|
||||||
|
dotenv.config();
|
||||||
|
const debugMode = process.env.DEBUG || true;
|
||||||
|
const mysql = require('mysql');
|
||||||
|
let db = mysql.createConnection({
|
||||||
|
host : process.env.DBHOST,
|
||||||
|
user : process.env.DBUSER,
|
||||||
|
password : process.env.DBPASS,
|
||||||
|
database : process.env.DBNAME,
|
||||||
|
port : process.env.DBPORT
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Table Structures
|
||||||
|
guild_info
|
||||||
|
+------------------------+-------------+------+-----+---------+----------------+
|
||||||
|
| Field | Type | Null | Key | Default | Extra |
|
||||||
|
+------------------------+-------------+------+-----+---------+----------------+
|
||||||
|
| guild_id | varchar(50) | NO | PRI | NULL | auto_increment |
|
||||||
|
| tree_name | varchar(100)| NO | | | |
|
||||||
|
| tree_height | varchar(10) | NO | | 0 | |
|
||||||
|
| tree_message_id | varchar(50) | NO | | | |
|
||||||
|
| tree_channel_id | varchar(50) | NO | | | |
|
||||||
|
| leaderboard_message_id | varchar(50) | NO | | | |
|
||||||
|
| leaderboard_channel_id | varchar(50) | NO | | | |
|
||||||
|
+------------------------+-------------+------+-----+---------+----------------+
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
leaderboard
|
||||||
|
+-------------+--------------+------+-----+---------+----------------+
|
||||||
|
| Field | Type | Null | Key | Default | Extra |
|
||||||
|
+-------------+--------------+------+-----+---------+----------------+
|
||||||
|
| id | int(10) | NO | PRI | NULL | auto_increment |
|
||||||
|
| guild_id | varchar(50) | NO | | | |
|
||||||
|
| tree_name | varchar(100) | NO | | | |
|
||||||
|
| tree_rank | int(10) | NO | | | |
|
||||||
|
| tree_height | int(10) | NO | | 1 | |
|
||||||
|
| has_pin | tinyint(1) | NO | | 0 | |
|
||||||
|
| timestamp | varchar(50) | NO | | | |
|
||||||
|
+-------------+--------------+------+-----+---------+----------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
db.connect((err) => {
|
||||||
|
if (err) throw `Error connecting to the database: ${err.message}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
db.on('error', function(err) {
|
||||||
|
db = mysql.createConnection({
|
||||||
|
host : process.env.DBHOST,
|
||||||
|
user : process.env.DBUSER,
|
||||||
|
password : process.env.DBPASS,
|
||||||
|
database : process.env.DBNAME,
|
||||||
|
port : process.env.DBPORT
|
||||||
|
});
|
||||||
|
db.connect((err) => {
|
||||||
|
if (err) throw `Error connecting to the database: ${err.message}`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
createGuildTables(guildId) {
|
||||||
|
// Create the guild-information and rank-information tables to be used.
|
||||||
|
const createGuildInfoTableQuery = "CREATE TABLE IF NOT EXISTS guild_info(guild_id VARCHAR(50) NOT NULL, tree_name VARCHAR(100) NOT NULL DEFAULT 'Run /setup where your tree is.', tree_height INT(10) NOT NULL DEFAULT 0, tree_message_id VARCHAR(50) NOT NULL DEFAULT 'Run /setup where your tree is.', tree_channel_id VARCHAR(50) NOT NULL DEFAULT 'Run /setup where your tree is.', leaderboard_message_id VARCHAR(50) NOT NULL DEFAULT 'Run /setup where your leaderboard is.', leaderboard_channel_id VARCHAR(50) NOT NULL DEFAULT 'Run /setup where your leaderboard is.', CONSTRAINT guild_pk PRIMARY KEY (guild_id))";
|
||||||
|
const createLeaderboardTableQuery = "CREATE TABLE IF NOT EXISTS leaderboard(id INT(10) NOT NULL AUTO_INCREMENT,guild_id VARCHAR(50) NOT NULL,tree_name VARCHAR(100) NOT NULL,tree_rank INT(10) NOT NULL,tree_height INT(10) NOT NULL DEFAULT 1,has_pin TINYINT(1) NOT NULL DEFAULT 0,timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, CONSTRAINT id_pk PRIMARY KEY(id))";
|
||||||
|
// TODO run the queries, then add a call to this function at the beginning of main.js or functions.js
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
db.query(createGuildInfoTableQuery, (err) => {
|
||||||
|
if (err) {
|
||||||
|
reject("Error creating the guild_info table: " + err.message);
|
||||||
|
console.error("Offending query: " + createGuildInfoTableQuery);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
db.query(createLeaderboardTableQuery, (err) => {
|
||||||
|
if (err) {
|
||||||
|
reject("Error creating the leaderboard table: " + err.message);
|
||||||
|
console.error("Offending query: " + createLeaderboardTableQuery);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve({ "status": "Successfully checked both tables.", "data": null })
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getGuildInfo(guildId) {
|
||||||
|
// Get a server's tree information from the database
|
||||||
|
const selectGuildInfoQuery = `SELECT tree_name, tree_height, tree_message_id, tree_channel_id, leaderboard_message_id, leaderboard_channel_id FROM guild_info WHERE guild_id = ${db.escape(guildId)}`;
|
||||||
|
// TODO run this query and return a promise then structure the output into a GuildInfo object. resolve with { "status": , "data": guildInfo }
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
db.query(selectGuildInfoQuery, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
reject("Error fetching guild information: " + err.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*const guildInfo = { "guildId": "123",
|
||||||
|
"treeName": "name",
|
||||||
|
"treeHeight": 123,
|
||||||
|
"treeMessageId": "123",
|
||||||
|
"treeChannelId": "123",
|
||||||
|
"leaderboardMessageId": "123",
|
||||||
|
"leaderboardChannelId": "123"
|
||||||
|
};*/
|
||||||
|
if (res.length == 0) {
|
||||||
|
reject("There is no database entry for your guild yet. Try running /setup");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
row = res[0];
|
||||||
|
const guildInfo = { "guildId": row.guild_id,
|
||||||
|
"treeName": row.tree_name,
|
||||||
|
"treeHeight": row.tree_height,
|
||||||
|
"treeMessageId": row.tree_message_id,
|
||||||
|
"treeChannelId": row.tree_channel_id,
|
||||||
|
"leaderboardMessageId": row.leaderboard_message_id,
|
||||||
|
"leaderboardChannelId": row.leaderboard_channel_id
|
||||||
|
};
|
||||||
|
resolve({ "status": "Successfully fetched guild information", "data": guildInfo })
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setGuildInfo(guildInfo) {
|
||||||
|
// Returns a Promise, resolve({ "status": "", "data": null })
|
||||||
|
// guildInfo = { "guildId": "123", "treeName": "name", "treeHeight": 123, "treeMessageId": "123", "treeChannelId": "123", "leaderboardMessageId": "123", "leaderboardChannelId": "123"}
|
||||||
|
// Set a server's tree information in the database
|
||||||
|
const insertGuildInfoQuery = `INSERT INTO guild_info (guild_id, tree_name, tree_height, tree_message_id, tree_channel_id, leaderboard_message_id, leaderboard_channel_id) VALUES (${db.escape(guildInfo.guildId)}, ${db.escape(guildInfo.treeName)}, ${db.escape(guildInfo.treeHeight)},${db.escape(guildInfo.treeMessageId)}, ${db.escape(guildInfo.treeChannelId)}, ${db.escape(guildInfo.leaderboardMessageId)}, ${db.escape(guildInfo.leaderboardChannelId)}) ON DUPLICATE KEY UPDATE tree_name = ${db.escape(guildInfo.treeName)},tree_height = ${db.escape(guildInfo.treeHeight)},tree_message_id = ${db.escape(guildInfo.treeMessageId)},tree_channel_id = ${db.escape(guildInfo.treeChannelId)},leaderboard_message_id = ${db.escape(guildInfo.leaderboardMessageId)},leaderboard_channel_id = ${db.escape(guildInfo.leaderboardChannelId)}`;
|
||||||
|
// TODO run this query and return a promise, then resolve with { "status": , "data": null }
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
db.query(insertGuildInfoQuery, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
reject("Error setting the guild info: " + err.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve({ "status": "Successfully set the guild information", "data": null });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setTreeInfo(guildInfo) {
|
||||||
|
// Returns a Promise, resolve({ "status": "", "data": null })
|
||||||
|
// guildInfo = { "guildId": "123", "treeName": "name", "treeHeight": 123, "treeMessageId": "123", "treeChannelId": "123", "leaderboardMessageId": "123", "leaderboardChannelId": "123"}
|
||||||
|
// Set a server's tree information in the database)
|
||||||
|
const insertGuildInfoQuery = `INSERT INTO guild_info (guild_id, tree_name, tree_height, tree_message_id, tree_channel_id) VALUES (${db.escape(guildInfo.guildId)}, ${db.escape(guildInfo.treeName)}, ${db.escape(guildInfo.treeHeight)},${db.escape(guildInfo.treeMessageId)}, ${db.escape(guildInfo.treeChannelId)}) ON DUPLICATE KEY UPDATE tree_name = ${db.escape(guildInfo.treeName)},tree_height = ${db.escape(guildInfo.treeHeight)},tree_message_id = ${db.escape(guildInfo.treeMessageId)},tree_channel_id = ${db.escape(guildInfo.treeChannelId)}`;
|
||||||
|
// TODO run this query and return a promise, then resolve with { "status": , "data": null }
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
db.query(insertGuildInfoQuery, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
reject("Error setting the guild info: " + err.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve({ "status": "Successfully set the guild information", "data": null });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setLeaderboardInfo(guildInfo) {
|
||||||
|
// Returns a Promise, resolve({ "status": "", "data": null })
|
||||||
|
// guildInfo = { "guildId": "123", "treeName": "name", "treeHeight": 123, "treeMessageId": "123", "treeChannelId": "123", "leaderboardMessageId": "123", "leaderboardChannelId": "123"}
|
||||||
|
// Set a server's tree information in the database
|
||||||
|
const insertGuildInfoQuery = `INSERT INTO guild_info (guild_id, leaderboard_message_id, leaderboard_channel_id) VALUES (${db.escape(guildInfo.guildId)}, ${db.escape(guildInfo.leaderboardMessageId)}, ${db.escape(guildInfo.leaderboardChannelId)}) ON DUPLICATE KEY UPDATE leaderboard_message_id = ${db.escape(guildInfo.leaderboardMessageId)},leaderboard_channel_id = ${db.escape(guildInfo.leaderboardChannelId)}`;
|
||||||
|
// TODO run this query and return a promise, then resolve with { "status": , "data": null }
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
db.query(insertGuildInfoQuery, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
reject("Error setting the guild info: " + err.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve({ "status": "Successfully set the guild information", "data": null });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
deleteGuildInfo(guildId) {
|
||||||
|
// Returns a Promise, resolve({ "status": "", "data": null })
|
||||||
|
// guildInfo = { "guildId": "123", "treeName": "name", "treeHeight": 123, "treeMessageId": "123", "treeChannelId": "123", "leaderboardMessageId": "123", "leaderboardChannelId": "123"}
|
||||||
|
// Set a server's tree information in the database
|
||||||
|
const deleteGuildInfoQuery = `DELETE FROM guild_info WHERE guild_id = ${db.escape(guildId)}`;
|
||||||
|
// TODO run this query and return a promise, then resolve with { "status": , "data": null }
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
db.query(deleteGuildInfoQuery, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
reject("Error deleting the guild info: " + err.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve({ "status": "Successfully deleted the guild information", "data": null });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getLeaderboard(guildId) {
|
||||||
|
// Returns a Promise, resolve({ "status": "", "data": leaderboard })
|
||||||
|
const selectLeaderboardQuery = `SELECT id, tree_name, tree_rank, tree_height, has_pin FROM leaderboard WHERE guild_id = ${db.escape(guildId)} ORDER BY id DESC LIMIT 10`;
|
||||||
|
// TODO run the query and return a promise then process the results. resolve with { "status": , "data": leaderboard }
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
db.query(selectLeaderboardQuery, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
reject("Error fetching the most recent leaderboard: " + err.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let leaderboard = [];
|
||||||
|
res.forEach(row => {
|
||||||
|
leaderboard.push({
|
||||||
|
"treeName": row.tree_name,
|
||||||
|
"treeRank": row.tree_rank,
|
||||||
|
"treeHeight": row.tree_height,
|
||||||
|
"hasPin": row.has_pin
|
||||||
|
});
|
||||||
|
});
|
||||||
|
resolve({ "status": "Successfully fetched leaderboard.", "data": leaderboard });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
uploadLeaderboard(leaderboard) {
|
||||||
|
// Returns a Promise, resolve({ "status": "", "data": res })
|
||||||
|
// leaderboard = { "guildId": 1234, "entries": [ { "treeHeight": 12, "treeRank": 34, "treeName": "name", "hasPin": false }, {...}, {...} ] }
|
||||||
|
const insertLeaderboardQuery = "INSERT INTO `leaderboard` (guild_id, tree_name, tree_rank, tree_height, has_pin) VALUES ?";
|
||||||
|
const leaderboardValues = [];
|
||||||
|
leaderboard.entries.forEach(ranking => {
|
||||||
|
leaderboardValues.push([leaderboard.guildId, ranking.treeName, ranking.treeRank, ranking.treeHeight, ranking.hasPin]);
|
||||||
|
});
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
db.query(insertLeaderboardQuery, [leaderboardValues], (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
reject("Error uploading the leaderboard: " + err.message);
|
||||||
|
console.error(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve({ "status": "Successfully uploaded the leaderboard", "data": res });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
db
|
||||||
|
};
|
@ -3,6 +3,7 @@
|
|||||||
const dotenv = require('dotenv');
|
const dotenv = require('dotenv');
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
const isDev = process.env.isDev;
|
const isDev = process.env.isDev;
|
||||||
|
const package = require('../package.json');
|
||||||
|
|
||||||
// filesystem
|
// filesystem
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
@ -13,9 +14,15 @@ const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = Discord;
|
|||||||
|
|
||||||
// Various imports from other files
|
// Various imports from other files
|
||||||
const config = require('../data/config.json');
|
const config = require('../data/config.json');
|
||||||
let guildInfo = require('../data/guildInfo.json');
|
|
||||||
const strings = require('../data/strings.json');
|
const strings = require('../data/strings.json');
|
||||||
const slashCommandFiles = fs.readdirSync('./slash-commands/').filter(file => file.endsWith('.js'));
|
const slashCommandFiles = fs.readdirSync('./slash-commands/').filter(file => file.endsWith('.js'));
|
||||||
|
const dbfn = require('./dbfn.js');
|
||||||
|
|
||||||
|
dbfn.createGuildTables().then(res => {
|
||||||
|
console.log(res.status);
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
|
||||||
const functions = {
|
const functions = {
|
||||||
// Functions for managing and creating Collections
|
// Functions for managing and creating Collections
|
||||||
@ -53,7 +60,7 @@ const functions = {
|
|||||||
.setColor(strings.embeds.color)
|
.setColor(strings.embeds.color)
|
||||||
.setTitle('Tree Growth Comparison')
|
.setTitle('Tree Growth Comparison')
|
||||||
.setDescription(content)
|
.setDescription(content)
|
||||||
.setFooter({text: strings.embeds.footer});
|
.setFooter({text: `v${package.version} - ${strings.embeds.footer}`});
|
||||||
const messageContents = { embeds: [embed], components: [refreshActionRow] };
|
const messageContents = { embeds: [embed], components: [refreshActionRow] };
|
||||||
return messageContents;
|
return messageContents;
|
||||||
},
|
},
|
||||||
@ -62,7 +69,7 @@ const functions = {
|
|||||||
.setColor(strings.embeds.color)
|
.setColor(strings.embeds.color)
|
||||||
.setTitle(strings.help.title)
|
.setTitle(strings.help.title)
|
||||||
.setDescription(content)
|
.setDescription(content)
|
||||||
.setFooter({ text: strings.embeds.footer });
|
.setFooter({ text: `v${package.version} - ${strings.embeds.footer}` });
|
||||||
const privateBool = private == 'true';
|
const privateBool = private == 'true';
|
||||||
const messageContents = { embeds: [embed], ephemeral: privateBool };
|
const messageContents = { embeds: [embed], ephemeral: privateBool };
|
||||||
return messageContents;
|
return messageContents;
|
||||||
@ -72,7 +79,7 @@ const functions = {
|
|||||||
.setColor(0xFF0000)
|
.setColor(0xFF0000)
|
||||||
.setTitle('Error!')
|
.setTitle('Error!')
|
||||||
.setDescription("Error: " + content)
|
.setDescription("Error: " + content)
|
||||||
.setFooter({ text: strings.embeds.footer });
|
.setFooter({ text: `v${package.version} - ${strings.embeds.footer}` });
|
||||||
const messageContents = { embeds: [embed], ephemeral: true };
|
const messageContents = { embeds: [embed], ephemeral: true };
|
||||||
return messageContents;
|
return messageContents;
|
||||||
},
|
},
|
||||||
@ -81,7 +88,7 @@ const functions = {
|
|||||||
.setColor(0x8888FF)
|
.setColor(0x8888FF)
|
||||||
.setTitle('Information')
|
.setTitle('Information')
|
||||||
.setDescription(content)
|
.setDescription(content)
|
||||||
.setFooter({ text: strings.embeds.footer });
|
.setFooter({ text: `v${package.version} - ${strings.embeds.footer}` });
|
||||||
const messageContents = { embeds: [embed], ephemeral: true };
|
const messageContents = { embeds: [embed], ephemeral: true };
|
||||||
return messageContents;
|
return messageContents;
|
||||||
}
|
}
|
||||||
@ -89,21 +96,29 @@ const functions = {
|
|||||||
rankings: {
|
rankings: {
|
||||||
parse(interaction) {
|
parse(interaction) {
|
||||||
return new Promise ((resolve, reject) => {
|
return new Promise ((resolve, reject) => {
|
||||||
if (guildInfo[interaction.guildId] == undefined) {
|
dbfn.getGuildInfo(interaction.guildId).then(res => {
|
||||||
|
const guildInfo = res.data;
|
||||||
|
if (guildInfo.guildId == "") {
|
||||||
reject(strings.error.noGuild);
|
reject(strings.error.noGuild);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (guildInfo[interaction.guildId].rankMessageId != undefined) {
|
if (guildInfo.leaderboardMessageId != undefined) {
|
||||||
interaction.guild.channels.fetch(guildInfo[interaction.guildId].rankChannelId).then(c => {
|
interaction.guild.channels.fetch(guildInfo.leaderboardChannelId).then(c => {
|
||||||
c.messages.fetch(guildInfo[interaction.guildId].rankMessageId).then(rankMessage => {
|
c.messages.fetch(guildInfo.leaderboardMessageId).then(leaderboardMessage => {
|
||||||
if ((rankMessage.embeds.length == 0) || (rankMessage.embeds[0].data.title != 'Tallest Trees' )) {
|
if ((leaderboardMessage.embeds.length == 0) || (leaderboardMessage.embeds[0].data.title != 'Tallest Trees' )) {
|
||||||
reject("This doesn't appear to be a valid ``/top trees`` message.");
|
reject("This doesn't appear to be a valid ``/top trees`` message.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let lines = rankMessage.embeds[0].data.description.split('\n');
|
let lines = leaderboardMessage.embeds[0].data.description.split('\n');
|
||||||
let rankings = [];
|
let leaderboard = {
|
||||||
|
"guildId": interaction.guildId,
|
||||||
|
"entries": []
|
||||||
|
};
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
|
// Breakdown each line separating it on each -
|
||||||
let breakdown = lines[i].split(' - ');
|
let breakdown = lines[i].split(' - ');
|
||||||
|
|
||||||
|
// Check if the first part, the ranking, has these emojis to detect first second and third place
|
||||||
if (breakdown[0].includes('🥇')) {
|
if (breakdown[0].includes('🥇')) {
|
||||||
breakdown[0] = '``#1 ``'
|
breakdown[0] = '``#1 ``'
|
||||||
} else if (breakdown[0].includes('🥈')) {
|
} else if (breakdown[0].includes('🥈')) {
|
||||||
@ -112,87 +127,111 @@ const functions = {
|
|||||||
breakdown[0] = '``#3 ``'
|
breakdown[0] = '``#3 ``'
|
||||||
}
|
}
|
||||||
|
|
||||||
let trimmedRank = breakdown[0].slice(breakdown[0].indexOf('#') + 1, breakdown[0].lastIndexOf('``'));
|
// Clean off the excess and get just the number from the rank, make sure it's an int not string
|
||||||
|
let trimmedRank = parseInt(breakdown[0].slice(breakdown[0].indexOf('#') + 1, breakdown[0].lastIndexOf('``')));
|
||||||
|
|
||||||
|
// Clean off the excess and get just the tree name
|
||||||
let trimmedName = breakdown[1].slice(breakdown[1].indexOf('``') + 2);
|
let trimmedName = breakdown[1].slice(breakdown[1].indexOf('``') + 2);
|
||||||
trimmedName = trimmedName.slice(0, trimmedName.indexOf('``'));
|
trimmedName = trimmedName.slice(0, trimmedName.indexOf('``'));
|
||||||
|
|
||||||
|
// Clean off the excess and get just the tree height, make sure it's a 1 decimal float
|
||||||
let trimmedHeight = parseFloat(breakdown[2].slice(0, breakdown[2].indexOf('ft'))).toFixed(1);
|
let trimmedHeight = parseFloat(breakdown[2].slice(0, breakdown[2].indexOf('ft'))).toFixed(1);
|
||||||
let isMyTree = false;
|
let isMyTree = false;
|
||||||
let isMaybeMyTree = false;
|
let isMaybeMyTree = false;
|
||||||
if (breakdown[2].includes('📍')) isMyTree = true;
|
if (breakdown[2].includes('📍')) isMyTree = true;
|
||||||
if (breakdown[1].includes(guildInfo[interaction.guildId].treeName)) maybeMyTree = true;
|
if (breakdown[1].includes(guildInfo.treeName)) maybeMyTree = true;
|
||||||
|
|
||||||
rankings.push({
|
// "entries": [ { "treeHeight": 12, "treeRank": 34, "treeName": "name" }, ] }
|
||||||
rank: trimmedRank,
|
|
||||||
name: trimmedName,
|
|
||||||
height: trimmedHeight,
|
leaderboard.entries.push({
|
||||||
myTree: isMyTree,
|
treeRank: trimmedRank,
|
||||||
maybeMyTree: isMaybeMyTree
|
treeName: trimmedName,
|
||||||
|
treeHeight: trimmedHeight,
|
||||||
|
hasPin: isMyTree
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
guildInfo[interaction.guildId].rankings = rankings;
|
dbfn.uploadLeaderboard(leaderboard).then(res => {
|
||||||
fs.writeFileSync('./data/guildInfo.json', JSON.stringify(guildInfo));
|
console.log(res.status);
|
||||||
guildInfo = require('../data/guildInfo.json');
|
resolve(res.status);
|
||||||
resolve(rankings);
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
reject("The rankMessageId is undefined somehow");
|
reject("The leaderboardMessageId is undefined somehow");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
compare(interaction) {
|
compare(interaction) {
|
||||||
if (guildInfo[interaction.guildId] == undefined) {
|
return new Promise((resolve, reject) => {
|
||||||
return strings.error.noGuild;
|
dbfn.getGuildInfo(interaction.guildId).then(res => {
|
||||||
}
|
const guildInfo = res.data;
|
||||||
let treeHeight = parseFloat(guildInfo[interaction.guildId].treeHeight).toFixed(1);
|
guildInfo.guildId = interaction.guildId;
|
||||||
if ((guildInfo[interaction.guildId].rankings.length > 0) && (treeHeight > 0)) {
|
|
||||||
|
let treeHeight = parseFloat(guildInfo.treeHeight).toFixed(1);
|
||||||
|
dbfn.getLeaderboard(interaction.guildId).then(res => {
|
||||||
|
const leaderboard = res.data;
|
||||||
|
|
||||||
let replyString = 'Current Tree Height: ' + treeHeight + 'ft\n\n';
|
let replyString = 'Current Tree Height: ' + treeHeight + 'ft\n\n';
|
||||||
guildInfo[interaction.guildId].rankings.forEach(treeRanking => {
|
leaderboard.reverse().forEach(treeRanking => {
|
||||||
let difference = parseFloat(treeRanking.height).toFixed(1) - treeHeight;
|
let difference = parseFloat(treeRanking.treeHeight).toFixed(1) - treeHeight;
|
||||||
let decimal = (treeRanking.height % 1).toFixed(1);
|
let decimal = (treeRanking.treeHeight % 1).toFixed(1);
|
||||||
let growthIndicator = "";
|
let growthIndicator = "";
|
||||||
if (decimal > 0) {
|
if (decimal > 0) {
|
||||||
growthIndicator += "[+]";
|
growthIndicator += "[+]";
|
||||||
}
|
}
|
||||||
const absDifference = parseFloat(Math.abs(difference)).toFixed(1);
|
const absDifference = parseFloat(Math.abs(difference)).toFixed(1);
|
||||||
if (treeRanking.myTree) {
|
if (treeRanking.hasPin) {
|
||||||
replyString += "This is your tree. ";
|
replyString += "This is your tree. ";
|
||||||
} else if (treeRanking.maybeMyTree) {
|
} else if ((treeRanking.treeHeight == treeHeight) && (treeRanking.treeName == guildInfo.treeName)) {
|
||||||
replyString += "This might be your tree. Same height, same name. ";
|
replyString += "This might be your tree. Same height, same name. ";
|
||||||
} else {
|
} else {
|
||||||
if (difference > 0) {
|
if (difference > 0) {
|
||||||
replyString += `#${treeRanking.rank} - ${absDifference}ft${growthIndicator} shorter `;
|
replyString += `#${treeRanking.treeRank} - ${absDifference}ft${growthIndicator} shorter `;
|
||||||
} else if (difference < 0) {
|
} else if (difference < 0) {
|
||||||
replyString += `#${treeRanking.rank} - ${absDifference}ft${growthIndicator} taller `;
|
replyString += `#${treeRanking.treeRank} - ${absDifference}ft${growthIndicator} taller `;
|
||||||
} else if (difference == 0) {
|
} else if (difference == 0) {
|
||||||
replyString += `#${treeRanking.rank} - Same Height${growthIndicator} `;
|
replyString += `#${treeRanking.treeRank} - Same Height${growthIndicator} `;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
replyString += `[${functions.getWaterTime(treeRanking.height)} mins]\n`;
|
replyString += `[${functions.getWaterTime(treeRanking.treeHeight)} mins]\n`;
|
||||||
|
});
|
||||||
|
resolve('Here\'s how your tree compares: \n' + replyString);
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}).catch(err => {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
return 'Here\'s how your tree compares: \n' + replyString;
|
|
||||||
} else {
|
|
||||||
console.error('Not configured correctly\n' + 'Guild ID: ' + interaction.guildId + '\nGuild Info: ' + JSON.stringify(guildInfo[interaction.guildId]));
|
|
||||||
return 'Not configured correctly';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tree: {
|
tree: {
|
||||||
parse(interaction) {
|
parse(interaction) {
|
||||||
let input;
|
let input;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (guildInfo[interaction.guildId] == undefined) {
|
dbfn.getGuildInfo(interaction.guildId).then(res => {
|
||||||
|
const guildInfo = res.data;
|
||||||
|
guildInfo.guildId = interaction.guildId;
|
||||||
|
if (guildInfo == undefined) {
|
||||||
reject(`The guild entry hasn't been created yet. [${interaction.guildId || interaction.commandGuildId}]`);
|
reject(`The guild entry hasn't been created yet. [${interaction.guildId || interaction.commandGuildId}]`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (guildInfo[interaction.guildId].treeMessageId != "") {
|
if (guildInfo.treeMessageId != "Run /setup where your tree is.") {
|
||||||
interaction.guild.channels.fetch(guildInfo[interaction.guildId].treeChannelId).then(c => {
|
interaction.guild.channels.fetch(guildInfo.treeChannelId).then(c => {
|
||||||
c.messages.fetch(guildInfo[interaction.guildId].treeMessageId).then(m => {
|
c.messages.fetch(guildInfo.treeMessageId).then(m => {
|
||||||
if ( (m.embeds.length == 0) || !(m.embeds[0].data.description.includes('Your tree is')) ) {
|
if ( (m.embeds.length == 0) || !(m.embeds[0].data.description.includes('Your tree is')) ) {
|
||||||
reject("This doesn't appear to be a valid ``/tree`` message.");
|
reject("This doesn't appear to be a valid ``/tree`` message.");
|
||||||
return;
|
return;
|
||||||
@ -200,57 +239,69 @@ const functions = {
|
|||||||
input = m.embeds[0].data.description;
|
input = m.embeds[0].data.description;
|
||||||
let treeName = m.embeds[0].data.title;
|
let treeName = m.embeds[0].data.title;
|
||||||
let lines = input.split('\n');
|
let lines = input.split('\n');
|
||||||
guildInfo[interaction.guildId].treeHeight = parseFloat(lines[0].slice(lines[0].indexOf('is') + 3, lines[0].indexOf('ft'))).toFixed(1);
|
guildInfo.treeHeight = parseFloat(lines[0].slice(lines[0].indexOf('is') + 3, lines[0].indexOf('ft'))).toFixed(1);
|
||||||
guildInfo[interaction.guildId].treeName = treeName;
|
guildInfo.treeName = treeName;
|
||||||
fs.writeFileSync('./data/guildInfo.json', JSON.stringify(guildInfo));
|
dbfn.setTreeInfo(guildInfo).then(res => {
|
||||||
guildInfo = require('../data/guildInfo.json');
|
|
||||||
resolve("The reference tree message has been saved/updated.");
|
resolve("The reference tree message has been saved/updated.");
|
||||||
});
|
});
|
||||||
|
});
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
console.error('treeMessageId undefined');
|
console.error('treeMessageId undefined');
|
||||||
reject("There was an unknown error while setting the tree message.");
|
reject("There was an unknown error while setting the tree message.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
reject(err);
|
||||||
|
console.error(err);
|
||||||
|
return;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
refresh(interaction) {
|
refresh(interaction) {
|
||||||
functions.rankings.parse(interaction).then(r1 => {
|
functions.rankings.parse(interaction).then(r1 => {
|
||||||
functions.tree.parse(interaction).then(r2 => {
|
functions.tree.parse(interaction).then(r2 => {
|
||||||
const embed = functions.builders.comparisonEmbed(functions.rankings.compare(interaction), functions.builders.refreshAction())
|
functions.rankings.compare(interaction).then(res => {
|
||||||
|
const embed = functions.builders.comparisonEmbed(res, functions.builders.refreshAction())
|
||||||
interaction.update(embed);
|
interaction.update(embed);
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
|
console.error(e);
|
||||||
interaction.reply(functions.builders.errorEmbed(e));
|
interaction.reply(functions.builders.errorEmbed(e));
|
||||||
});
|
});
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
|
console.error(e);
|
||||||
interaction.reply(functions.builders.errorEmbed(e));
|
interaction.reply(functions.builders.errorEmbed(e));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
reset(guildId) {
|
reset(guildId) {
|
||||||
delete guildInfo[guildId];
|
return new Promise((resolve, reject) => {
|
||||||
fs.writeFileSync('./data/guildInfo.json', JSON.stringify(guildInfo));
|
dbfn.deleteGuildInfo(guildId).then(res => {
|
||||||
guildInfo = require('../data/guildInfo.json');
|
resolve(res);
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
reject(err);
|
||||||
return;
|
return;
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
getInfo(guildId) {
|
getInfo(guildId) {
|
||||||
const thisGuildInfo = guildInfo[guildId];
|
return new Promise((resolve, reject) => {
|
||||||
if (thisGuildInfo != undefined) {
|
dbfn.getGuildInfo(guildId).then(res => {
|
||||||
let thisGuildInfoString = "";
|
let guildInfo = res.data;
|
||||||
if (thisGuildInfo.treeMessageId != "") {
|
let guildInfoString = "";
|
||||||
thisGuildInfoString += `Tree Message: https://discord.com/channels/${guildId}/${thisGuildInfo.treeChannelId}/${thisGuildInfo.treeMessageId}\n`;
|
guildInfoString += `Tree Message: https://discord.com/channels/${guildId}/${guildInfo.treeChannelId}/${guildInfo.treeMessageId}\n`;
|
||||||
|
guildInfoString += `Rank Message: https://discord.com/channels/${guildId}/${guildInfo.leaderboardChannelId}/${guildInfo.leaderboardMessageId}\n`;
|
||||||
}
|
resolve(`Here is your servers setup info:\n${guildInfoString}`);
|
||||||
if (thisGuildInfo.rankMessageId != "") {
|
}).catch(err => {
|
||||||
thisGuildInfoString += `Rank Message: https://discord.com/channels/${guildId}/${thisGuildInfo.rankChannelId}/${thisGuildInfo.rankMessageId}\n`;
|
console.error(err);
|
||||||
}
|
reject(err);
|
||||||
if (thisGuildInfo.treeHeight != "") {
|
return;
|
||||||
thisGuildInfoString += `Tree Height: ${thisGuildInfo.treeHeight}\n`;
|
})
|
||||||
}
|
});
|
||||||
return `Here is your servers setup info:\n${thisGuildInfoString}`;
|
|
||||||
} else {
|
|
||||||
return "Your guild hasn't been set up yet.";
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
getWaterTime(size) {
|
getWaterTime(size) {
|
||||||
return Math.floor((Math.pow(size * 0.07 + 5, 1.1) / 60));
|
return Math.floor((Math.pow(size * 0.07 + 5, 1.1) / 60));
|
||||||
|
15
package.json
15
package.json
@ -1,23 +1,24 @@
|
|||||||
{
|
{
|
||||||
"name": "treeanalyzer",
|
"name": "silvanus",
|
||||||
"version": "1.0.5",
|
"version": "1.1.0",
|
||||||
"description": "Analyze Grow A Tree",
|
"description": "Grow A Tree Comparison Tool",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/voidf1sh/treeanalyzer.git"
|
"url": "git+https://github.com/voidf1sh/silvanus.git"
|
||||||
},
|
},
|
||||||
"author": "Skylar Grant",
|
"author": "Skylar Grant",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/voidf1sh/treeanalyzer/issues"
|
"url": "https://github.com/voidf1sh/silvanus/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/voidf1sh/treeanalyzer#readme",
|
"homepage": "https://github.com/voidf1sh/silvanus#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"discord.js": "^14.7.1",
|
"discord.js": "^14.7.1",
|
||||||
"dotenv": "^16.0.3"
|
"dotenv": "^16.0.3",
|
||||||
|
"mysql": "^2.18.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,18 @@ module.exports = {
|
|||||||
.setName('compare')
|
.setName('compare')
|
||||||
.setDescription('See how your tree compares to other trees!'),
|
.setDescription('See how your tree compares to other trees!'),
|
||||||
async execute(interaction) {
|
async execute(interaction) {
|
||||||
const embed = fn.builders.comparisonEmbed(fn.rankings.compare(interaction), fn.builders.refreshAction());
|
interaction.deferReply().then(() => {
|
||||||
interaction.reply(embed);
|
fn.rankings.compare(interaction).then(res => {
|
||||||
|
const embed = fn.builders.comparisonEmbed(res, fn.builders.refreshAction());
|
||||||
|
interaction.editReply(embed).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}).catch(err => {
|
||||||
|
interaction.editReply(fn.builders.errorEmbed(err)).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
})
|
||||||
},
|
},
|
||||||
};
|
};
|
@ -14,7 +14,7 @@ module.exports = {
|
|||||||
{ name: "True", value: "true" },
|
{ name: "True", value: "true" },
|
||||||
{ name: "False", value: "false" })),
|
{ name: "False", value: "false" })),
|
||||||
execute(interaction) {
|
execute(interaction) {
|
||||||
const helpEmbed = fn.builders.helpEmbed(`${strings.help.info}\n\n**Setup**\n${strings.help.setup}`, interaction.options.getString('private'));
|
const helpEmbed = fn.builders.helpEmbed(`${strings.help.info}\n\n**Setup**\n${strings.help.setup}\n\n**All Commands**\n${strings.help.allCommands}\n\n**Support Server**\n${strings.urls.supportServer}`, interaction.options.getString('private'));
|
||||||
interaction.reply(helpEmbed);
|
interaction.reply(helpEmbed);
|
||||||
},
|
},
|
||||||
};
|
};
|
@ -6,7 +6,19 @@ module.exports = {
|
|||||||
.setName('reset')
|
.setName('reset')
|
||||||
.setDescription('Reset all message assignments in your server'),
|
.setDescription('Reset all message assignments in your server'),
|
||||||
execute(interaction) {
|
execute(interaction) {
|
||||||
fn.reset(interaction.guildId);
|
interaction.deferReply({ ephemeral: true }).then(() => {
|
||||||
interaction.reply(fn.builders.embed("Assignments Reset"));
|
fn.reset(interaction.guildId).then(res => {
|
||||||
|
interaction.editReply(fn.builders.embed("Assignments Reset")).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
interaction.editReply("There was a problem deleting your guild information, contact @voidf1sh#0420 for help.").catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
@ -1,7 +1,7 @@
|
|||||||
const { SlashCommandBuilder } = require('discord.js');
|
const { SlashCommandBuilder } = require('discord.js');
|
||||||
const fn = require('../modules/functions.js');
|
const fn = require('../modules/functions.js');
|
||||||
const guildInfo = require('../data/guildInfo.json');
|
|
||||||
const strings = require('../data/strings.json');
|
const strings = require('../data/strings.json');
|
||||||
|
const dbfn = require('../modules/dbfn.js');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
data: new SlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
@ -9,41 +9,57 @@ module.exports = {
|
|||||||
.setDescription('Attempt automatic configuration of the bot.'),
|
.setDescription('Attempt automatic configuration of the bot.'),
|
||||||
execute(interaction) {
|
execute(interaction) {
|
||||||
interaction.deferReply({ ephemeral: true }).then(function () {
|
interaction.deferReply({ ephemeral: true }).then(function () {
|
||||||
if (guildInfo[interaction.guildId] == undefined) {
|
/*const guildInfo = { "guildId": "123",
|
||||||
guildInfo[interaction.guildId] = {
|
"treeName": "name",
|
||||||
"treeMessageId": "",
|
"treeHeight": 123,
|
||||||
"treeChannelId": "",
|
"treeMessageId": "123",
|
||||||
"rankMessageId": "",
|
"treeChannelId": "123",
|
||||||
"rankChannelId": "",
|
"leaderboardMessageId": "123",
|
||||||
"treeName": "",
|
"leaderboardChannelId": "123"
|
||||||
"treeHeight": 0,
|
};*/
|
||||||
"rankings": []
|
const guildInfo = { "guildId": interaction.guildId,
|
||||||
|
"treeName": "name",
|
||||||
|
"treeHeight": 123,
|
||||||
|
"treeMessageId": "123",
|
||||||
|
"treeChannelId": "123",
|
||||||
|
"leaderboardMessageId": "123",
|
||||||
|
"leaderboardChannelId": "123"
|
||||||
};
|
};
|
||||||
}
|
|
||||||
interaction.channel.messages.fetch({ limit: 20 }).then(function (msgs) {
|
interaction.channel.messages.fetch({ limit: 20 }).then(function (msgs) {
|
||||||
let treeFound = false;
|
let treeFound = false;
|
||||||
let rankFound = false;
|
let leaderboardFound = false;
|
||||||
msgs.reverse().forEach(msg => {
|
msgs.reverse().forEach(msg => {
|
||||||
if (msg.embeds.length > 0) {
|
if (msg.embeds.length > 0) {
|
||||||
if (msg.embeds[0].data.description.includes("Your tree is")) {
|
if (msg.embeds[0].data.description.includes("Your tree is")) {
|
||||||
treeFound = true;
|
treeFound = true;
|
||||||
guildInfo[interaction.guildId].treeChannelId = msg.channelId;
|
guildInfo.treeName = msg.embeds[0].title;
|
||||||
guildInfo[interaction.guildId].treeMessageId = msg.id;
|
guildInfo.treeChannelId = msg.channelId;
|
||||||
fn.tree.parse(msg);
|
guildInfo.treeMessageId = msg.id;
|
||||||
} else if (msg.embeds[0].data.title == "Tallest Trees") {
|
} else if (msg.embeds[0].data.title == "Tallest Trees") {
|
||||||
rankFound = true;
|
leaderboardFound = true;
|
||||||
guildInfo[interaction.guildId].rankChannelId = msg.channelId;
|
guildInfo.leaderboardChannelId = msg.channelId;
|
||||||
guildInfo[interaction.guildId].rankMessageId = msg.id;
|
guildInfo.leaderboardMessageId = msg.id;
|
||||||
fn.rankings.parse(msg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (treeFound && !(rankFound)) {
|
if (treeFound && !(leaderboardFound)) {
|
||||||
|
dbfn.setTreeInfo(guildInfo).then(res => {
|
||||||
interaction.editReply(fn.builders.embed(strings.status.treeNoLeaderboard));
|
interaction.editReply(fn.builders.embed(strings.status.treeNoLeaderboard));
|
||||||
} else if (!(treeFound) && rankFound) {
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
} else if (!(treeFound) && leaderboardFound) {
|
||||||
|
dbfn.setLeaderboardInfo(guildInfo).then(res => {
|
||||||
interaction.editReply(fn.builders.embed(strings.status.leaderboardNoTree));
|
interaction.editReply(fn.builders.embed(strings.status.leaderboardNoTree));
|
||||||
} else if (treeFound && rankFound) {
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
} else if (treeFound && leaderboardFound) {
|
||||||
|
dbfn.setGuildInfo(guildInfo).then(res => {
|
||||||
interaction.editReply(fn.builders.embed(strings.status.treeAndLeaderboard));
|
interaction.editReply(fn.builders.embed(strings.status.treeAndLeaderboard));
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -6,7 +6,16 @@ module.exports = {
|
|||||||
.setName('setupinfo')
|
.setName('setupinfo')
|
||||||
.setDescription('View information about how the bot is set up in your server'),
|
.setDescription('View information about how the bot is set up in your server'),
|
||||||
execute(interaction) {
|
execute(interaction) {
|
||||||
const embed = fn.builders.embed(fn.getInfo(interaction.guildId));
|
interaction.deferReply({ephemeral: true}).then(() => {
|
||||||
interaction.reply(embed);
|
fn.getInfo(interaction.guildId).then(res => {
|
||||||
|
const embed = fn.builders.embed(res);
|
||||||
|
interaction.editReply(embed);
|
||||||
|
}).catch(err => {
|
||||||
|
interaction.editReply(err);
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user