diff --git a/commands/channels/makeprivate.js b/commands/channels/makeprivate.js new file mode 100644 index 0000000..fe5df0d --- /dev/null +++ b/commands/channels/makeprivate.js @@ -0,0 +1,124 @@ +/** + * @author Marzavec + * @summary Sets channel to private + * @version 1.0.0 + * @description Remove channel from being listed on the front page + * @module makeprivate + */ + +import { + isChannelOwner, +} from '../utility/_UAC.js'; +/* +import { + Errors, +} from '../utility/_Constants.js'; +*/ + +/** + * Executes when invoked by a remote client + * @param {Object} env - Environment object with references to core, server, socket & payload + * @public + * @return {void} + */ +export async function run({ + core, server, socket, +}) { + // must be in a channel to run this command + if (typeof socket.channel === 'undefined') { + return server.police.frisk(socket, 10); + } + + if (!socket.trip) { + return server.reply({ + cmd: 'warn', // @todo Add numeric error code as `id` + text: 'Failed to make channel private: Missing trip code.', + channel: socket.channel, // @todo Multichannel + }, socket); + } + + if (!isChannelOwner(socket.level)) { + return server.reply({ + cmd: 'info', // @todo Add numeric error code as `id` + text: 'Failed to make channel private: You may not do that', + channel: socket.channel, // @todo Multichannel + }, socket); + } + + const listingIndex = core.appConfig.data.publicChannels.indexOf(socket.channel); + + if (listingIndex === -1) { + return server.reply({ + cmd: 'warn', // @todo Add numeric error code as `id` + text: 'Failed to make channel private: This channel is already private', + channel: socket.channel, // @todo Multichannel + }, socket); + } + + core.appConfig.data.publicChannels.splice(listingIndex, 1); + + server.reply({ + cmd: 'info', // @todo Add numeric error code as `id` + text: 'This channel has been removed from the list of public channels', + channel: socket.channel, // @todo Multichannel + }, socket); + + return true; +} + +/** + * Automatically executes once after server is ready to register this modules hooks + * @param {Object} server - Reference to server environment object + * @public + * @return {void} + */ +export function initHooks(server) { + server.registerHook('in', 'chat', this.chatHook.bind(this), 26); +} + +/** + * Executes every time an incoming chat command is invoked + * @param {Object} env - Environment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/new payload, false = suppress, string = error + */ +export function chatHook({ + core, server, socket, payload, +}) { + if (typeof payload.text !== 'string') { + return false; + } + + if (payload.text.startsWith('/makeprivate')) { + this.run({ + core, + server, + socket, + payload: { + cmd: 'makeprivate', + }, + }); + + return false; + } + + return payload; +} + +/** + * Module meta information + * @public + * @typedef {Object} makeprivate/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ +export const info = { + name: 'makeprivate', + category: 'channels', + description: 'Remove channel from being listed on the front page', + usage: ` + API: { cmd: 'makeprivate' } + Text: /makeprivate`, +}; diff --git a/commands/channels/makepublic.js b/commands/channels/makepublic.js new file mode 100644 index 0000000..ec3e639 --- /dev/null +++ b/commands/channels/makepublic.js @@ -0,0 +1,172 @@ +/** + * @author Marzavec + * @summary Sets channel to public + * @version 1.0.0 + * @description Make channel publicly listed on the front page + * @module makepublic + */ + +import captcha from 'ascii-captcha'; +import { + isChannelOwner, + isModerator, +} from '../utility/_UAC.js'; +/* +import { + Errors, +} from '../utility/_Constants.js'; +*/ +import { + getChannelSettings, +} from '../utility/_Channels.js'; + +/** + * Executes when invoked by a remote client + * @param {Object} env - Environment object with references to core, server, socket & payload + * @public + * @return {void} + */ +export async function run({ + server, socket, +}) { + // must be in a channel to run this command + if (typeof socket.channel === 'undefined') { + return server.police.frisk(socket, 10); + } + + if (!socket.trip) { + return server.reply({ + cmd: 'warn', // @todo Add numeric error code as `id` + text: 'Failed to make channel public: Missing trip code.', + channel: socket.channel, // @todo Multichannel + }, socket); + } + + if (isModerator(socket.level) || !isChannelOwner(socket.level)) { + return server.reply({ + cmd: 'info', // @todo Add numeric error code as `id` + text: 'Failed to make channel public: You may not do that', + channel: socket.channel, // @todo Multichannel + }, socket); + } + + socket.pubCaptcha = { + solution: captcha.generateRandomText(7), + }; + + server.reply({ + cmd: 'warn', + text: 'Enter the following to make channel public (case-sensitive):', + channel: socket.channel, // @todo Multichannel + }, socket); + + server.reply({ + cmd: 'captcha', + text: captcha.word2Transformedstr(socket.pubCaptcha.solution), + channel: socket.channel, // @todo Multichannel + }, socket); + + return true; +} + +/** + * Automatically executes once after server is ready to register this modules hooks + * @param {Object} server - Reference to server environment object + * @public + * @return {void} + */ +export function initHooks(server) { + server.registerHook('in', 'chat', this.chatHook.bind(this), 26); +} + +/** + * Executes every time an incoming chat command is invoked + * @param {Object} env - Environment object with references to core, server, socket & payload + * @public + * @return {{Object|boolean|string}} Object = same/new payload, false = suppress, string = error + */ +export function chatHook({ + core, server, socket, payload, +}) { + if (typeof payload.text !== 'string') { + return false; + } + + if (typeof socket.pubCaptcha !== 'undefined') { + if (payload.text === socket.pubCaptcha.solution) { + socket.pubCaptcha = undefined; + + const channelSettings = getChannelSettings(core.appConfig.data, socket.channel); + + if (channelSettings.owned === false || socket.trip !== channelSettings.ownerTrip) { + return server.reply({ + cmd: 'warn', // @todo Add numeric error code as `id` + text: 'Failed to make channel public: You may not do that', + channel: socket.channel, // @todo Multichannel + }, socket); + } + + if (core.appConfig.data.publicChannels.indexOf(socket.channel) !== -1) { + return server.reply({ + cmd: 'warn', // @todo Add numeric error code as `id` + text: 'Failed to make channel public: This channel is already public', + channel: socket.channel, // @todo Multichannel + }, socket); + } + + core.appConfig.data.publicChannels.push(socket.channel); + + server.broadcast({ + cmd: 'info', + text: `A new channel has been made public: ?${socket.channel}`, + channel: socket.channel, // @todo Multichannel + }, { level: (level) => isModerator(level) }); + + server.reply({ + cmd: 'info', // @todo Add numeric error code as `id` + text: 'This channel has been added to the list of public channels', + channel: socket.channel, // @todo Multichannel + }, socket); + + return false; + } + + server.police.frisk(socket, 7); + socket.terminate(); + + return false; + } + + if (payload.text.startsWith('/makepublic')) { + this.run({ + core, + server, + socket, + payload: { + cmd: 'makepublic', + }, + }); + + return false; + } + + return payload; +} + +/** + * Module meta information + * @public + * @typedef {Object} makepublic/info + * @property {string} name - Module command name + * @property {string} category - Module category name + * @property {string} description - Information about module + * @property {string} usage - Information about module usage + */ +export const info = { + name: 'makepublic', + category: 'channels', + description: 'Make channel publicly listed on the front page', + usage: ` + API: { cmd: 'makepublic' } + Text: /makepublic`, +}; diff --git a/commands/channels/renewclaim.js b/commands/channels/renewclaim.js index c37f7f6..88ca671 100644 --- a/commands/channels/renewclaim.js +++ b/commands/channels/renewclaim.js @@ -60,7 +60,7 @@ export async function run({ } const hoursLeft = Math.abs(channelSettings.claimExpires - new Date()) / (60 * 60 * 1000); - + if (hoursLeft > 24) { return server.reply({ cmd: 'warn', // @todo Add numeric error code as `id`