diff --git a/src/commandDetails/coin/leaderboard.ts b/src/commandDetails/coin/leaderboard.ts index 5a3e379f..a62cd385 100644 --- a/src/commandDetails/coin/leaderboard.ts +++ b/src/commandDetails/coin/leaderboard.ts @@ -10,6 +10,7 @@ import { import { getCurrentCoinLeaderboard, getCoinBalanceByUserId, + getUserPrivacy, UserCoinEntry, getUserIdCurrentCoinPosition } from '../../components/coin'; @@ -27,6 +28,7 @@ const getCurrentCoinLeaderboardEmbed = async ( // Initialise user's coin balance if they have not already const userBalance = await getCoinBalanceByUserId(currentUserId); const currentPosition = await getUserIdCurrentCoinPosition(currentUserId); + const isUserPrivate = await getUserPrivacy(currentUserId); const leaderboardArray: string[] = []; for (let i = 0; i < leaderboard.length && leaderboardArray.length < limit; i++) { @@ -38,8 +40,11 @@ const getCurrentCoinLeaderboardEmbed = async ( continue; } if (user.bot) continue; - const userTag = user?.tag ?? ''; - const userCoinEntryText = `${leaderboardArray.length + 1}. ${userTag} - ${userCoinEntry.balance} ${getCoinEmoji()}`; + const userTag = user?.tag; + const displayTag = userTag && !isUserPrivate ? userTag : ''; + const userCoinEntryText = `${leaderboardArray.length + 1}. ${displayTag} - ${ + userCoinEntry.balance + } ${getCoinEmoji()}`; leaderboardArray.push(userCoinEntryText); } const currentLeaderboardText = leaderboardArray.join('\n'); diff --git a/src/commandDetails/coin/privacy.ts b/src/commandDetails/coin/privacy.ts new file mode 100644 index 00000000..4155afda --- /dev/null +++ b/src/commandDetails/coin/privacy.ts @@ -0,0 +1,64 @@ +import { container } from '@sapphire/framework'; +import { Permissions, User } from 'discord.js'; +import { + CodeyCommandDetails, + CodeyCommandOptionType, + CodeyCommandResponseType, + SapphireMessageExecuteType +} from '../../codeyCommand'; +import { getUserPrivacy, changeUserPrivacy } from '../../components/coin'; + +// Update coin leaderboard privacy of a user +const coinPrivacyExecuteCommand: SapphireMessageExecuteType = async (client, messageFromUser, args) => { + if (!(>messageFromUser.member?.permissions).has('ADMINISTRATOR')) { + return `You do not have permission to use this command.`; + } + + // First mandatory argument is user + const user = args['user']; + if (!user) { + throw new Error('please enter a valid user mention or ID for leaderboard privacy update.'); + } + + // Second mandatory argument is privacy + const privacy = args['privacy']; + if (typeof privacy !== 'number' || (privacy !== 0 && privacy !== 1)) { + throw new Error('please enter 0/1 for public/private.'); + } + + // Adjust privacy + await changeUserPrivacy(user.id, privacy); + + // Get new privacy + const newPrivacy = await getUserPrivacy(user.id); + return `${user.username} is now ${newPrivacy ? 'private' : 'not private'}.`; +}; + +export const coinPrivacyCommandDetails: CodeyCommandDetails = { + name: 'privacy', + aliases: ['p'], + description: 'Update the leaderboard privacy of a user.', + detailedDescription: `**Examples:** + \`${container.botPrefix}coin privacy @Codey 1\``, + + isCommandResponseEphemeral: false, + messageWhenExecutingCommand: 'Updating leaderboard privacy...', + executeCommand: coinPrivacyExecuteCommand, + codeyCommandResponseType: CodeyCommandResponseType.STRING, + + options: [ + { + name: 'user', + description: 'The user to adjust the privacy of,', + type: CodeyCommandOptionType.USER, + required: true + }, + { + name: 'privacy', + description: 'The privacy to set the specified user to,', + type: CodeyCommandOptionType.NUMBER, + required: true + } + ], + subcommandDetails: {} +}; diff --git a/src/commands/coin/coin.ts b/src/commands/coin/coin.ts index 9ae14d76..de4fc03f 100644 --- a/src/commands/coin/coin.ts +++ b/src/commands/coin/coin.ts @@ -5,6 +5,7 @@ import { coinCheckCommandDetails } from '../../commandDetails/coin/check'; import { coinInfoCommandDetails } from '../../commandDetails/coin/info'; import { coinUpdateCommandDetails } from '../../commandDetails/coin/update'; import { coinCurrentLeaderboardCommandDetails } from '../../commandDetails/coin/leaderboard'; +import { coinPrivacyCommandDetails } from '../../commandDetails/coin/privacy'; const coinCommandDetails: CodeyCommandDetails = { name: 'coin', @@ -19,13 +20,16 @@ const coinCommandDetails: CodeyCommandDetails = { \`${container.botPrefix}coin info\` \`${container.botPrefix}coin i\` \`${container.botPrefix}coin update @Codey 100\` -\`${container.botPrefix}coin update @Codey 0 Reset Codey's balance.\``, +\`${container.botPrefix}coin u @Codey 0 Reset Codey's balance.\` +\`${container.botPrefix}coin privacy @Codey 1\` +\`${container.botPrefix}coin p @Codey 0\``, options: [], subcommandDetails: { adjust: coinAdjustCommandDetails, check: coinCheckCommandDetails, info: coinInfoCommandDetails, update: coinUpdateCommandDetails, + privacy: coinPrivacyCommandDetails, leaderboard: coinCurrentLeaderboardCommandDetails }, defaultSubcommandDetails: coinCheckCommandDetails diff --git a/src/components/coin.ts b/src/components/coin.ts index 262f6c7b..a66f1ba5 100644 --- a/src/components/coin.ts +++ b/src/components/coin.ts @@ -81,6 +81,30 @@ export const getCoinBalanceByUserId = async (userId: string): Promise => return _.get(res, 'balance', 0); }; +/* + Returns 1 or 0 for whether user is private +*/ +export const getUserPrivacy = async (userId: string): Promise => { + const db = await openDB(); + // Query user privacy from DB. + const res = await db.get('SELECT is_private FROM user_coin WHERE user_id = ?', userId); + // If user doesn't have a privacy value, default to false (public). + return _.get(res, 'is_private', 0); +}; + +export const changeUserPrivacy = async (userId: string, privacy: number): Promise => { + const db = await openDB(); + await db.run( + ` + INSERT INTO user_coin (user_id, is_private) VALUES (?, ?) + ON CONFLICT(user_id) + DO UPDATE SET is_private = ?`, + userId, + privacy, + privacy + ); +}; + /* If user doesn't exist, create row with newBalance as the balance. Otherwise, update balance to newBalance. diff --git a/src/components/db.ts b/src/components/db.ts index 0527fd63..9da9a2c2 100644 --- a/src/components/db.ts +++ b/src/components/db.ts @@ -92,7 +92,8 @@ const initUserCoinTable = async (db: Database): Promise => { ` CREATE TABLE IF NOT EXISTS user_coin ( user_id VARCHAR(255) PRIMARY KEY NOT NULL, - balance INTEGER NOT NULL CHECK(balance>=0) + balance INTEGER NOT NULL CHECK(balance>=0), + is_private INTEGER CHECK(is_private IN (0, 1)) ) ` );