-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0f7d921
commit c5cf4d2
Showing
40 changed files
with
2,360 additions
and
197 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const joi_1 = __importDefault(require("joi")); | ||
const envVarsSchema = joi_1.default.object() | ||
.keys({ | ||
NODE_ENV: joi_1.default.string().valid('production', 'development', 'test').required(), | ||
DB_HOST: joi_1.default.string().required().description('Mongo DB url'), | ||
DB_PORT: joi_1.default.string().required().description('Mongo DB port'), | ||
DB_USER: joi_1.default.string().required().description('Mongo DB username'), | ||
DB_PASSWORD: joi_1.default.string().required().description('Mongo DB password'), | ||
DB_NAME: joi_1.default.string().required().description('Mongo DB name'), | ||
RABBIT_HOST: joi_1.default.string().required().description('RabbitMQ url'), | ||
RABBIT_PORT: joi_1.default.string().required().description('RabbitMQ port'), | ||
RABBIT_USER: joi_1.default.string().required().description('RabbitMQ username'), | ||
RABBIT_PASSWORD: joi_1.default.string().required().description('RabbitMQ password'), | ||
DISCROD_CLIENT_ID: joi_1.default.string().required().description('Discord clinet id'), | ||
DISCORD_CLIENT_SECRET: joi_1.default.string().required().description('Discord clinet secret'), | ||
DISCORD_BOT_TOKEN: joi_1.default.string().required().description('Discord bot token'), | ||
SENTRY_DSN: joi_1.default.string().required().description('Sentry DSN'), | ||
SENTRY_ENV: joi_1.default.string().valid('production', 'development', 'local', 'test').required(), | ||
REDIS_HOST: joi_1.default.string().required().description('Reids host'), | ||
REDIS_PORT: joi_1.default.string().required().description('Reids port'), | ||
REDIS_PASSWORD: joi_1.default.string().required().description('Reids password').allow(''), | ||
LOG_LEVEL: joi_1.default.string().required().description('Min allowed log level'), | ||
}) | ||
.unknown(); | ||
const { value: envVars, error } = envVarsSchema.prefs({ errors: { label: 'key' } }).validate(process.env); | ||
if (error) { | ||
throw new Error(`Config validation error: ${error.message}`); | ||
} | ||
exports.default = { | ||
env: envVars.NODE_ENV, | ||
mongoose: { | ||
serverURL: `mongodb://${envVars.DB_USER}:${envVars.DB_PASSWORD}@${envVars.DB_HOST}:${envVars.DB_PORT}/${envVars.DB_NAME}`, | ||
dbURL: `mongodb://${envVars.DB_USER}:${envVars.DB_PASSWORD}@${envVars.DB_HOST}:${envVars.DB_PORT}`, | ||
}, | ||
redis: { | ||
host: envVars.REDIS_HOST, | ||
port: envVars.REDIS_PORT, | ||
password: envVars.REDIS_PASSWORD, | ||
}, | ||
rabbitMQ: { | ||
url: `amqp://${envVars.RABBIT_USER}:${envVars.RABBIT_PASSWORD}@${envVars.RABBIT_HOST}:${envVars.RABBIT_PORT}`, | ||
}, | ||
discord: { | ||
clientId: envVars.DISCROD_CLIENT_ID, | ||
clientSecret: envVars.DISCORD_CLIENT_SECRET, | ||
botToken: envVars.DISCORD_BOT_TOKEN, | ||
}, | ||
sentry: { | ||
dsn: envVars.SENTRY_DSN, | ||
env: envVars.SENTRY_ENV, | ||
}, | ||
logger: { | ||
level: envVars.LOG_LEVEL, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const pino_1 = __importDefault(require("pino")); | ||
const index_1 = __importDefault(require("./index")); | ||
exports.default = (0, pino_1.default)({ | ||
level: index_1.default.logger.level, | ||
formatters: { | ||
level: label => { | ||
return { level: label.toUpperCase() }; | ||
}, | ||
}, | ||
timestamp: () => `,"timestamp":"${new Date(Date.now()).toISOString()}"`, | ||
bindings: (bindings) => { | ||
return { | ||
pid: bindings.pid, | ||
host: bindings.hostname, | ||
}; | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.closeConnection = void 0; | ||
const logger_1 = __importDefault(require("../config/logger")); | ||
const logger = logger_1.default.child({ module: 'Connection' }); | ||
/** | ||
* Closes a given Mongoose connection. | ||
* @param {Connection} connection - The Mongoose connection object to be closed. | ||
* @returns {Promise<void>} - A promise that resolves when the connection has been successfully closed. | ||
* @throws {MongooseError} - If there is an error closing the connection, it is logged to the console and the error is thrown. | ||
*/ | ||
async function closeConnection(connection) { | ||
try { | ||
await connection.close(); | ||
logger.info({ database: connection.name }, 'The connection to database has been successfully closed'); | ||
} | ||
catch (error) { | ||
logger.fatal({ database: connection.name, error }, 'Failed to close the connection to the database'); | ||
} | ||
} | ||
exports.closeConnection = closeConnection; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.connectDB = void 0; | ||
const mongoose_1 = __importDefault(require("mongoose")); | ||
const config_1 = __importDefault(require("../config")); | ||
const logger_1 = __importDefault(require("../config/logger")); | ||
async function connectDB() { | ||
mongoose_1.default.set('strictQuery', false); | ||
mongoose_1.default | ||
.connect(config_1.default.mongoose.serverURL) | ||
.then(() => { | ||
logger_1.default.info({ url: config_1.default.mongoose.serverURL }, 'Connected to MongoDB!'); | ||
}) | ||
.catch(error => logger_1.default.error({ url: config_1.default.mongoose.serverURL, error }, 'Failed to connect to MongoDB!')); | ||
} | ||
exports.connectDB = connectDB; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const logger_1 = __importDefault(require("../../config/logger")); | ||
const logger = logger_1.default.child({ module: 'ChannelService' }); | ||
/** | ||
* Create a channel in the database. | ||
* @param {Connection} connection - Mongoose connection object for the database. | ||
* @param {IChannel} channel - The channel object to be created. | ||
* @returns {Promise<IChannel|null>} - A promise that resolves to the created channel object. | ||
*/ | ||
async function createChannel(connection, channel) { | ||
try { | ||
return await connection.models.Channel.create(channel); | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
} | ||
catch (error) { | ||
if (error.code == 11000) { | ||
logger.warn({ database: connection.name, channel_id: channel.channelId }, 'Failed to create duplicate channel'); | ||
return null; | ||
} | ||
logger.error({ database: connection.name, channel_id: channel.channelId, error }, 'Failed to create channel'); | ||
return null; | ||
} | ||
} | ||
/** | ||
* Create channels in the database. | ||
* @param {Connection} connection - Mongoose connection object for the database. | ||
* @param {IChannel[]} channels - An array of channel objects to be created. | ||
* @returns {Promise<IChannel[] | []>} - A promise that resolves to an array of the created channel objects. | ||
*/ | ||
async function createChannels(connection, channels) { | ||
try { | ||
return await connection.models.Channel.insertMany(channels, { ordered: false }); | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
} | ||
catch (error) { | ||
if (error.code == 11000) { | ||
logger.warn({ database: connection.name }, 'Failed to create duplicate channels'); | ||
return []; | ||
} | ||
logger.error({ database: connection.name, error }, 'Failed to create channels'); | ||
return []; | ||
} | ||
} | ||
/** | ||
* Get a channel from the database based on the filter criteria. | ||
* @param {Connection} connection - Mongoose connection object for the database. | ||
* @param {object} filter - An object specifying the filter criteria to match the desired channel entry. | ||
* @returns {Promise<IChannel | null>} - A promise that resolves to the matching channel object or null if not found. | ||
*/ | ||
async function getChannel(connection, filter) { | ||
return await connection.models.Channel.findOne(filter); | ||
} | ||
/** | ||
* Get channels from the database based on the filter criteria. | ||
* @param {Connection} connection - Mongoose connection object for the database. | ||
* @param {object} filter - An object specifying the filter criteria to match the desired channel entries. | ||
* @returns {Promise<IChannel[] | []>} - A promise that resolves to an array of the matching channel objects. | ||
*/ | ||
async function getChannels(connection, filter) { | ||
return await connection.models.Channel.find(filter); | ||
} | ||
/** | ||
* Update a channel in the database based on the filter criteria. | ||
* @param {Connection} connection - Mongoose connection object for the database. | ||
* @param {object} filter - An object specifying the filter criteria to match the desired channel entry. | ||
* @param {IChannelUpdateBody} updateBody - An object containing the updated channel data. | ||
* @returns {Promise<IChannel | null>} - A promise that resolves to the updated channel object or null if not found. | ||
*/ | ||
async function updateChannel(connection, filter, updateBody) { | ||
try { | ||
const channel = await connection.models.Channel.findOne(filter); | ||
if (!channel) { | ||
return null; | ||
} | ||
Object.assign(channel, updateBody); | ||
return await channel.save(); | ||
} | ||
catch (error) { | ||
logger.error({ database: connection.name, filter, updateBody, error }, 'Failed to update channel'); | ||
return null; | ||
} | ||
} | ||
/** | ||
* Update multiple channels in the database based on the filter criteria. | ||
* @param {Connection} connection - Mongoose connection object for the database. | ||
* @param {object} filter - An object specifying the filter criteria to match multiple channel entries. | ||
* @param {IChannelUpdateBody} updateBody - An object containing the updated channel data. | ||
* @returns {Promise<number>} - A promise that resolves to the number of updated channel entries. | ||
*/ | ||
async function updateChannels(connection, filter, updateBody) { | ||
try { | ||
const updateResult = await connection.models.Channel.updateMany(filter, updateBody); | ||
return updateResult.modifiedCount || 0; | ||
} | ||
catch (error) { | ||
logger.error({ database: connection.name, filter, updateBody, error }, 'Failed to update channels'); | ||
return 0; | ||
} | ||
} | ||
/** | ||
* Handle the logic for creating or updating channels in the database. | ||
* @param {Connection} connection - Mongoose connection object for the specific guild database. | ||
* @param {TextChannel | VoiceChannel | CategoryChannel} channel - The Discord.js Channel object containing the full channel details. | ||
* @returns {Promise<void>} - A promise that resolves when the create or update operation is complete. | ||
* | ||
*/ | ||
async function handelChannelChanges(connection, channel) { | ||
const commonFields = getNeededDateFromChannel(channel); | ||
try { | ||
const channelDoc = await updateChannel(connection, { channelId: channel.id }, commonFields); | ||
if (!channelDoc) { | ||
await createChannel(connection, commonFields); | ||
} | ||
} | ||
catch (error) { | ||
logger.error({ guild_id: connection.name, channel_id: channel.id, error }, 'Failed to handle channel changes'); | ||
} | ||
} | ||
/** | ||
* Extracts necessary fields from a Discord.js GuildMember object to form an IGuildMember object. | ||
* @param {TextChannel | VoiceChannel | CategoryChannel} channel - The Discord.js Channel object containing the full channel details. | ||
* @returns {IChannel} - The extracted data in the form of an IChannel object. | ||
*/ | ||
function getNeededDateFromChannel(channel) { | ||
return { | ||
channelId: channel.id, | ||
name: channel.name, | ||
parentId: channel.parentId, | ||
permissionOverwrites: Array.from(channel.permissionOverwrites.cache.values()).map(overwrite => ({ | ||
id: overwrite.id, | ||
type: overwrite.type, | ||
allow: overwrite.allow.bitfield.toString(), | ||
deny: overwrite.deny.bitfield.toString(), | ||
})), | ||
}; | ||
} | ||
exports.default = { | ||
createChannel, | ||
createChannels, | ||
updateChannel, | ||
getChannel, | ||
getChannels, | ||
updateChannels, | ||
handelChannelChanges, | ||
getNeededDateFromChannel, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const db_1 = require("@togethercrew.dev/db"); | ||
const logger_1 = __importDefault(require("../../config/logger")); | ||
const logger = logger_1.default.child({ module: 'GuildService' }); | ||
/** | ||
* get guild by query | ||
* @param {Object} filter | ||
* @returns {Promise<IGuild | null>} | ||
*/ | ||
async function getGuild(filter) { | ||
return db_1.Guild.findOne(filter); | ||
} | ||
/** | ||
* Retrieve and return multiple guild entries that match the provided filter. | ||
* @param {object} filter - Filter criteria to match the desired guild entries. | ||
* @returns {Promise<object[]>} - A promise that resolves to an array of matching guild entries. | ||
*/ | ||
async function getGuilds(filter) { | ||
return await db_1.Guild.find(filter); | ||
} | ||
/** | ||
* Update the guild entry that matches the provided filter with the provided data. | ||
* @param {object} filter - Filter criteria to match the desired guild entry for update. | ||
* @param {IGuildUpdateBody} updateBody - Updated information for the guild entry. | ||
* @returns {Promise<object|null>} - A promise that resolves to the updated guild entry, or null if not found. | ||
*/ | ||
async function updateGuild(filter, updateBody) { | ||
try { | ||
const guild = await db_1.Guild.findOne(filter); | ||
if (!guild) { | ||
return null; | ||
} | ||
Object.assign(guild, updateBody); | ||
return await guild.save(); | ||
} | ||
catch (error) { | ||
logger.error({ database: 'RnDAO', filter, updateBody, error }, 'Failed to update guild'); | ||
return null; | ||
} | ||
} | ||
/** | ||
* Update multiple guild entries that match the provided filter with the provided data. | ||
* @param {object} filter - Filter criteria to match the desired guild entries for update. | ||
* @param {IGuildUpdateBody} updateBody - Updated information for the guild entry. | ||
* @returns {Promise<number>} - A promise that resolves to the number of guild entries updated. | ||
*/ | ||
async function updateManyGuilds(filter, updateBody) { | ||
try { | ||
const updateResult = await db_1.Guild.updateMany(filter, updateBody); | ||
const modifiedCount = updateResult.modifiedCount; | ||
return modifiedCount; | ||
} | ||
catch (error) { | ||
logger.error({ database: 'RnDAO', filter, updateBody, error }, 'Failed to update guilds'); | ||
return 0; | ||
} | ||
} | ||
async function checkBotAccessToGuild(client, guildId) { | ||
if (!client.guilds.cache.has(guildId)) { | ||
await updateGuild({ guildId }, { isDisconnected: false }); | ||
return false; | ||
} | ||
return true; | ||
} | ||
exports.default = { | ||
getGuild, | ||
getGuilds, | ||
updateGuild, | ||
updateManyGuilds, | ||
checkBotAccessToGuild, | ||
}; |
Oops, something went wrong.