add support for MySQL and SQLite3 with sqlz (Sequelize)
Signed-off-by: Rajdeep Malakar <rajdeepm.dev@gmail.com>
This commit is contained in:
		
							parent
							
								
									7a88d053e1
								
							
						
					
					
						commit
						ff93a9d7ee
					
				|  | @ -128,3 +128,8 @@ dist | ||||||
| .yarn/build-state.yml | .yarn/build-state.yml | ||||||
| .yarn/install-state.gz | .yarn/install-state.gz | ||||||
| .pnp.* | .pnp.* | ||||||
|  | 
 | ||||||
|  | # Cx-specific | ||||||
|  | package-lock.json | ||||||
|  | db.sql | ||||||
|  | db.sql-journal | ||||||
|  |  | ||||||
|  | @ -0,0 +1,59 @@ | ||||||
|  | { | ||||||
|  |   "xan.guilds": { | ||||||
|  |     "uuid": "text", | ||||||
|  |     "serverId": "text", | ||||||
|  |     "channelId": "text", | ||||||
|  |     "networks": "text", | ||||||
|  |     "client": "text" | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   "xan.messages": { | ||||||
|  |     "uuid": "text", | ||||||
|  |     "authorName": "text", | ||||||
|  |     "authorId": "text", | ||||||
|  |     "authorIcon": "text", | ||||||
|  |     "serverIcon": "text", | ||||||
|  |     "channelId": "text", | ||||||
|  |     "message": "text" | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   "xan.userBans": { | ||||||
|  |     "uuid": "text", | ||||||
|  |     "userId": "text", | ||||||
|  |     "mod": "text", | ||||||
|  |     "reason": "text" | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   "xan.messageDelivery": { | ||||||
|  |     "uuid": "text", | ||||||
|  |     "channelId": "text", | ||||||
|  |     "messageId": "text", | ||||||
|  |     "client": "text", | ||||||
|  |     "link": "text" | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   "xan.serverBans": { | ||||||
|  |     "uuid": "text", | ||||||
|  |     "serverId": "text", | ||||||
|  |     "mod": "text", | ||||||
|  |     "reason": "text" | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   "xan.userPrefs": { | ||||||
|  |     "uuid": "text", | ||||||
|  |     "userId": "text", | ||||||
|  |     "prefs": "text" | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   "xan.serverPrefs": { | ||||||
|  |     "uuid": "text", | ||||||
|  |     "serverId": "text", | ||||||
|  |     "prefs": "text" | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   "xan.networks": { | ||||||
|  |     "uuid": "text", | ||||||
|  |     "networkId": "text", | ||||||
|  |     "address": "text" | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -5,5 +5,6 @@ | ||||||
|     "xan.messages", |     "xan.messages", | ||||||
|     "xan.messageDelivery", |     "xan.messageDelivery", | ||||||
|     "xan.networks", |     "xan.networks", | ||||||
|     "xan.server_prefs" |     "xan.serverPrefs", | ||||||
|  |     "xan.userPrefs" | ||||||
| ] | ] | ||||||
|  |  | ||||||
|  | @ -10,10 +10,10 @@ module.exports.initMongoDBInstance = async (client,config,callback) => { | ||||||
| 
 | 
 | ||||||
|     var call_data = { |     var call_data = { | ||||||
|         createStore: async (name, callback) => { |         createStore: async (name, callback) => { | ||||||
|             db.createCollection(name).then(() => { |             db.createCollection(name).then(async () => { | ||||||
|                 callback(true); |                 await callback(true); | ||||||
|             }).catch(() => { |             }).catch(() => { | ||||||
|                 callback(false); |                 await callback(false); | ||||||
|             }) |             }) | ||||||
|         }, |         }, | ||||||
| 
 | 
 | ||||||
|  | @ -22,7 +22,7 @@ module.exports.initMongoDBInstance = async (client,config,callback) => { | ||||||
| 
 | 
 | ||||||
|             var found_data = await collection.find(data).toArray(); |             var found_data = await collection.find(data).toArray(); | ||||||
| 
 | 
 | ||||||
|             callback(found_data); |             await callback(found_data); | ||||||
|         }, |         }, | ||||||
| 
 | 
 | ||||||
|         insert: async (table, data, callback) => { |         insert: async (table, data, callback) => { | ||||||
|  | @ -35,7 +35,7 @@ module.exports.initMongoDBInstance = async (client,config,callback) => { | ||||||
|                 ...data |                 ...data | ||||||
|             }) |             }) | ||||||
| 
 | 
 | ||||||
|             callback(uuid) |             await callback(uuid) | ||||||
|         }, |         }, | ||||||
| 
 | 
 | ||||||
|         delete: async (table, uuid, callback) => { |         delete: async (table, uuid, callback) => { | ||||||
|  | @ -43,7 +43,7 @@ module.exports.initMongoDBInstance = async (client,config,callback) => { | ||||||
| 
 | 
 | ||||||
|             collection.deleteOne({ uuid: uuid }); |             collection.deleteOne({ uuid: uuid }); | ||||||
| 
 | 
 | ||||||
|             callback(true); |             await callback(true); | ||||||
|         }, |         }, | ||||||
| 
 | 
 | ||||||
|         search: async (table, data, callback) => { |         search: async (table, data, callback) => { | ||||||
|  | @ -51,7 +51,7 @@ module.exports.initMongoDBInstance = async (client,config,callback) => { | ||||||
| 
 | 
 | ||||||
|             var found_data = await collection.findOne(data); |             var found_data = await collection.findOne(data); | ||||||
| 
 | 
 | ||||||
|             callback(found_data); |             await callback(found_data); | ||||||
|         }, |         }, | ||||||
| 
 | 
 | ||||||
|         edit: async (table, uuid, data, callback) => { |         edit: async (table, uuid, data, callback) => { | ||||||
|  | @ -64,9 +64,9 @@ module.exports.initMongoDBInstance = async (client,config,callback) => { | ||||||
|                     uuid: uuid, |                     uuid: uuid, | ||||||
|                     ...data |                     ...data | ||||||
|                 } |                 } | ||||||
|             }) |             }); | ||||||
| 
 | 
 | ||||||
|             callback(true); |             await callback(true); | ||||||
|         }, |         }, | ||||||
| 
 | 
 | ||||||
|         build: async () => { |         build: async () => { | ||||||
|  |  | ||||||
|  | @ -1,77 +0,0 @@ | ||||||
| /** |  | ||||||
|  *  |  | ||||||
|  * @param {import('mysql2').Connection} client  |  | ||||||
|  * @param {*} callback  |  | ||||||
|  */ |  | ||||||
| module.exports.initMYSQL2Connection = async (client,config,callback) => { |  | ||||||
|     var call_data = { |  | ||||||
|         createStore: async (name, callback) => { |  | ||||||
|             client.query( |  | ||||||
|                 `CREATE TABLE ${name.replace(".","")} (id INT NOT NULL AUTO_INCREMENT , uuid VARCHAR(256) NOT NULL , data LONGTEXT NOT NULL, timestamp VARCHAR(16) NOT NULL  , PRIMARY KEY (id)) ENGINE = ${config.database_engine};`, |  | ||||||
|                 async function(err,results,fields) { |  | ||||||
|                     callback(true); |  | ||||||
|                 } |  | ||||||
|             ) |  | ||||||
|         }, |  | ||||||
| 
 |  | ||||||
|         list: async (table , callback) => { |  | ||||||
|             var fetchData = []; |  | ||||||
| 
 |  | ||||||
|             client.query( |  | ||||||
|                 `SELECT * FROM ${table.replace(".","")}`, |  | ||||||
|                 async function(err,results,fields) { |  | ||||||
|                     for(var element of results) { |  | ||||||
|                         var data = JSON.parse(element['data']); |  | ||||||
|                         await fetchData.push({ |  | ||||||
|                             uuid: element['uuid'], |  | ||||||
|                             ...data |  | ||||||
|                         }); |  | ||||||
| 
 |  | ||||||
|                         await callback(fetchData); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             ) |  | ||||||
|         }, |  | ||||||
| 
 |  | ||||||
|         search: async (table , data , callback) => { |  | ||||||
|             var fetchData = []; |  | ||||||
| 
 |  | ||||||
|             client.query( |  | ||||||
|                 `SELECT * FROM ${table.replace(".","")}`, |  | ||||||
|                 async function(err,results,fields) { |  | ||||||
|                     for(var element of results) { |  | ||||||
|                         var data = JSON.parse(element['data']); |  | ||||||
|                         if(data) |  | ||||||
|                         await fetchData.push({ |  | ||||||
|                             uuid: element['uuid'], |  | ||||||
|                             ...data |  | ||||||
|                         }); |  | ||||||
| 
 |  | ||||||
|                         await callback(fetchData); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             ) |  | ||||||
|         }, |  | ||||||
| 
 |  | ||||||
|         insert: async (table, data,callback) => { |  | ||||||
|             var uuid = require('node:crypto').randomUUID(); |  | ||||||
| 
 |  | ||||||
|             client.query( |  | ||||||
|                 `INSERT INTO ${table.replace(".","")} (uuid, data, timestamp) VALUES 
 |  | ||||||
|                     ('${uuid}', '${JSON.stringify(data)}', '${Date.now()}')`,
 |  | ||||||
|                 async function(err,result,fields) { |  | ||||||
|                     callback(uuid) |  | ||||||
|                 } |  | ||||||
|             ) |  | ||||||
|         }, |  | ||||||
| 
 |  | ||||||
|         build: async () => { |  | ||||||
|             var tables = require("./collection_tables.json"); |  | ||||||
|             for(var table of tables){ |  | ||||||
|                 call_data.createStore(table , (state) => {}); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     callback(call_data); |  | ||||||
| } |  | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | var schema = require("./collection_schemas.json"); | ||||||
|  | const { DataTypes } = require("sequelize"); | ||||||
|  | 
 | ||||||
|  | let sql = fix_schema_sql(); | ||||||
|  | let mongod = {}; | ||||||
|  | 
 | ||||||
|  | function sql_schema(type) { | ||||||
|  |   switch (type) { | ||||||
|  |     case "text": | ||||||
|  |       return DataTypes.TEXT; | ||||||
|  |     default: | ||||||
|  |       return DataTypes.TEXT; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function fix_schema_sql() { | ||||||
|  |   let __schema = {}; | ||||||
|  |   for (let key of Object.keys(schema)) { | ||||||
|  |     let obj = {}; | ||||||
|  |     for (let k of Object.keys(schema[key])) { | ||||||
|  |       obj[k] = sql_schema(schema[key][k]); | ||||||
|  |     } | ||||||
|  |     __schema[key.replaceAll(".", "__")] = obj; | ||||||
|  |   } | ||||||
|  |   return __schema; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | module.exports = { | ||||||
|  |   sql, mongod | ||||||
|  | }; | ||||||
|  | @ -0,0 +1,71 @@ | ||||||
|  | const { Sequelize } = require("sequelize"); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  *  | ||||||
|  |  * @param {Sequelize} client | ||||||
|  |  * @param {*} callback | ||||||
|  |  */ | ||||||
|  | module.exports.initSQLConnection = async (client, config, callback) => { | ||||||
|  |     let tables = {}; | ||||||
|  |     var call_data = { | ||||||
|  |         list: async (table, data, callback) => { | ||||||
|  |             console.log(`Listing ${table}`); | ||||||
|  |             let result = await tables[table].findAll({ where: data }); | ||||||
|  |             if (!result) { | ||||||
|  |               await callback(result); | ||||||
|  |             } else { | ||||||
|  |               await callback(result.map(r => r.dataValues)); | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  | 
 | ||||||
|  |         delete: async (table, uuid, callback) => { | ||||||
|  |             await tables[table].destroy({ where: { uuid: uuid } }); | ||||||
|  |             await callback(true); | ||||||
|  |         }, | ||||||
|  | 
 | ||||||
|  |         search: async (table, data, callback) => { | ||||||
|  |             console.log(`Searching ${table}`); | ||||||
|  |             var result = await tables[table].findOne({ where: data }); | ||||||
|  |             await callback(result); | ||||||
|  |         }, | ||||||
|  |         insert: async (table, data, callback) => { | ||||||
|  |             console.log(`Inserting to ${table}`); | ||||||
|  |             var uuid = require('node:crypto').randomUUID(); | ||||||
|  |             let instance = tables[table].build({ | ||||||
|  |               uuid: uuid, | ||||||
|  |               ...data | ||||||
|  |             }); | ||||||
|  |             await instance.save(); | ||||||
|  |             await callback(uuid); | ||||||
|  |         }, | ||||||
|  | 
 | ||||||
|  |         edit: async (table, uuid, data, callback) => { | ||||||
|  |             try { | ||||||
|  |                 await tables[table].update({ | ||||||
|  |                     uuid: uuid, | ||||||
|  |                     ...data | ||||||
|  |                 }, { | ||||||
|  |                     where: { uuid: uuid } | ||||||
|  |                 }); | ||||||
|  |                 await callback(true); | ||||||
|  |             } catch (e) { | ||||||
|  |                 await callback(false); | ||||||
|  |                 console.error(`Error:\n${e}`); | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         build: async () => { | ||||||
|  |             var __tables = require("./collection_tables.json"); | ||||||
|  |             var __schema = require("./schemas.js"); | ||||||
|  |             var schema = __schema.sql; | ||||||
|  |             for (var table of __tables) { | ||||||
|  |                 const model = client.define(table.replaceAll(".", "__"), schema[table.replaceAll(".", "__")], { freezeTableName: true }); | ||||||
|  |                 tables[table] = model; | ||||||
|  |             } | ||||||
|  |             await client.sync(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     callback(call_data); | ||||||
|  | } | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -18,6 +18,8 @@ | ||||||
|     "dotenv": "^16.4.5", |     "dotenv": "^16.4.5", | ||||||
|     "mongodb": "^6.4.0", |     "mongodb": "^6.4.0", | ||||||
|     "mysql2": "^3.9.2", |     "mysql2": "^3.9.2", | ||||||
|     "nodemon": "^3.1.0" |     "nodemon": "^3.1.0", | ||||||
|  |     "sequelize": "^6.37.1", | ||||||
|  |     "sqlite3": "^5.1.7" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ module.exports = { | ||||||
|         interaction.client.database.search("xan.guilds", { |         interaction.client.database.search("xan.guilds", { | ||||||
|             serverId: interaction.guild.id |             serverId: interaction.guild.id | ||||||
|         }, async (data) => { |         }, async (data) => { | ||||||
|  |             console.log(data); | ||||||
|             if(data == null){ |             if(data == null){ | ||||||
|                 interaction.client.database.insert("xan.guilds", { |                 interaction.client.database.insert("xan.guilds", { | ||||||
|                     serverId: interaction.guild.id, |                     serverId: interaction.guild.id, | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ module.exports = { | ||||||
|     discord_client_secret: process.env['discord_client_secret'] || "", |     discord_client_secret: process.env['discord_client_secret'] || "", | ||||||
| 
 | 
 | ||||||
|     // Database Configurations
 |     // Database Configurations
 | ||||||
|     // Possible Options ["mongod" , "mysqld"]
 |     // Possible Options ["mongod", "mysqld", "sqlite"]
 | ||||||
|     database_adapter: "mongod", |     database_adapter: "mongod", | ||||||
|     // If using MongoDB
 |     // If using MongoDB
 | ||||||
|     database_uri: process.env['database_uri'] || "", |     database_uri: process.env['database_uri'] || "", | ||||||
|  | @ -17,5 +17,7 @@ module.exports = { | ||||||
|     database_host: "localhost", |     database_host: "localhost", | ||||||
|     database_user: "root", |     database_user: "root", | ||||||
|     database_password: process.env['database_password'] || "", |     database_password: process.env['database_password'] || "", | ||||||
|     database_engine: "InnoDB" |     database_engine: "InnoDB", | ||||||
|  |     // If using SQLite3
 | ||||||
|  |     database_file: process.env["DATABASE_FILE"] || "" | ||||||
| } | } | ||||||
							
								
								
									
										32
									
								
								src/index.js
								
								
								
								
							
							
						
						
									
										32
									
								
								src/index.js
								
								
								
								
							|  | @ -4,7 +4,7 @@ const config = require("./config/prod"); | ||||||
| const fs = require('node:fs'); | const fs = require('node:fs'); | ||||||
| const path = require('node:path'); | const path = require('node:path'); | ||||||
| const { MongoClient } = require("mongodb"); | const { MongoClient } = require("mongodb"); | ||||||
| const mysql = require('mysql2'); | const { Sequelize } = require("sequelize"); | ||||||
| const { Client, Events, GatewayIntentBits, Collection } = require('discord.js'); | const { Client, Events, GatewayIntentBits, Collection } = require('discord.js'); | ||||||
| 
 | 
 | ||||||
| const client = new Client({ | const client = new Client({ | ||||||
|  | @ -25,17 +25,29 @@ async function main() { | ||||||
| 
 | 
 | ||||||
| 		require("../database/mongod").initMongoDBInstance(mongo_client, config, (back) => initMessageManager(back)); | 		require("../database/mongod").initMongoDBInstance(mongo_client, config, (back) => initMessageManager(back)); | ||||||
| 	} else if (config.database_adapter == "mysqld") { | 	} else if (config.database_adapter == "mysqld") { | ||||||
| 		const mysql_connection = mysql.createConnection({ | 		const mysql_conn = new Sequelize(config.database_name, config.database_user, config.database_password, { | ||||||
|       host: config.database_host, |       host: config.database_host, | ||||||
| 			user: config.database_user, |       dialect: "mysql" | ||||||
| 			password: config.database_password, |     }) | ||||||
| 			database: config.database_name, |     try { | ||||||
|  |         await mysql_conn.authenticate(); | ||||||
|  | 		    await require("../database/sqlz") | ||||||
|  |           .initSQLConnection(mysql_conn, config, async (back) => await initMessageManager(back)); | ||||||
|  | 	  } catch (e) { | ||||||
|  |         console.error(`Error:\n${e}`); | ||||||
|  |     } | ||||||
|  |   } else if (config.database_adapter == "sqlite") { | ||||||
|  |     const sql_conn = new Sequelize({ | ||||||
|  |       dialect: "sqlite", | ||||||
|  |       storage: config.database_file | ||||||
|     }); |     }); | ||||||
| 
 |     try { | ||||||
| 		mysql_connection.connect(); |       await sql_conn.authenticate(); | ||||||
| 		mysql_connection.on('error', (error) => console.error); |       await require("../database/sqlz") | ||||||
| 
 |         .initSQLConnection(sql_conn, config, async (back) => await initMessageManager(back)); | ||||||
| 		require("../database/mysqld").initMYSQL2Connection(mysql_connection, config, (back) => initMessageManager(back)); |     } catch (e) { | ||||||
|  |       console.error(`Error:\n${e}`); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ const actionMessageManager = async ( | ||||||
| ) => { | ) => { | ||||||
|     var d_data  = { |     var d_data  = { | ||||||
|         find_uuid: (messageId, authorId , cb) => { |         find_uuid: (messageId, authorId , cb) => { | ||||||
|             database.search("xan.messageDelivery" , { messageId: messageId } , (dataUid) => { |             database.search("xan.messageDelivery", { messageId }, (dataUid) => { | ||||||
|                 database.search("xan.messages", { uuid: dataUid.link }, (data) => { |                 database.search("xan.messages", { uuid: dataUid.link }, (data) => { | ||||||
|                     if (data.authorId.toString() == authorId.toString()) { |                     if (data.authorId.toString() == authorId.toString()) { | ||||||
|                         cb(dataUid.link); |                         cb(dataUid.link); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue