Add tests for privacy interaction
This commit is contained in:
		| @@ -3,32 +3,38 @@ | ||||
| const DiscordTypes = require("discord-api-types/v10") | ||||
| const {discord, sync, db, select} = require("../../passthrough") | ||||
| const {id: botID} = require("../../../addbot") | ||||
| const {InteractionMethods} = require("snowtransfer") | ||||
|  | ||||
| /** @type {import("../../d2m/actions/create-space")} */ | ||||
| const createSpace = sync.require("../../d2m/actions/create-space") | ||||
|  | ||||
| /** | ||||
|  * @param {DiscordTypes.APIChatInputApplicationCommandGuildInteraction} interaction | ||||
|  * @param {{createSpace: typeof createSpace}} di | ||||
|  * @returns {AsyncGenerator<{[k in keyof InteractionMethods]?: Parameters<InteractionMethods[k]>[2]}>} | ||||
|  */ | ||||
| async function interact({id, token, data, guild_id}) { | ||||
| async function* _interact({data, guild_id}, {createSpace}) { | ||||
| 	// Check guild is bridged | ||||
| 	const current = select("guild_space", "privacy_level", {guild_id}).pluck().get() | ||||
| 	if (current == null) return { | ||||
| 		type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource, | ||||
| 		data: { | ||||
| 			content: "This server isn't bridged to Matrix, so you can't set the Matrix privacy level.", | ||||
| 			flags: DiscordTypes.MessageFlags.Ephemeral | ||||
| 		} | ||||
| 	InteractionMethods.prototype.createInteractionResponse | ||||
| 	if (current == null) { | ||||
| 		return yield {createInteractionResponse: { | ||||
| 			type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource, | ||||
| 			data: { | ||||
| 				content: "This server isn't bridged to Matrix, so you can't set the Matrix privacy level.", | ||||
| 				flags: DiscordTypes.MessageFlags.Ephemeral | ||||
| 			} | ||||
| 		}} | ||||
| 	} | ||||
|  | ||||
| 	// Get input level | ||||
| 	/** @type {DiscordTypes.APIApplicationCommandInteractionDataStringOption[] | undefined} */ // @ts-ignore | ||||
| 	const options = data.options | ||||
| 	const input = options?.[0].value || "" | ||||
| 	const input = options?.[0]?.value || "" | ||||
| 	const levels = ["invite", "link", "directory"] | ||||
| 	const level = levels.findIndex(x => input === x) | ||||
| 	if (level === -1) { | ||||
| 		return discord.snow.interaction.createInteractionResponse(id, token, { | ||||
| 		return yield {createInteractionResponse: { | ||||
| 			type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource, | ||||
| 			data: { | ||||
| 				content: "**Usage: `/privacy <level>`**. This will set who can join the space on Matrix-side. There are three levels:" | ||||
| @@ -38,22 +44,37 @@ async function interact({id, token, data, guild_id}) { | ||||
| 					+ `\n**Current privacy level: \`${levels[current]}\`**`, | ||||
| 				flags: DiscordTypes.MessageFlags.Ephemeral | ||||
| 			} | ||||
| 		}) | ||||
| 		}} | ||||
| 	} | ||||
|  | ||||
| 	await discord.snow.interaction.createInteractionResponse(id, token, { | ||||
| 	yield {createInteractionResponse: { | ||||
| 		type: DiscordTypes.InteractionResponseType.DeferredChannelMessageWithSource, | ||||
| 		data: { | ||||
| 			flags: DiscordTypes.MessageFlags.Ephemeral | ||||
| 		} | ||||
| 	}) | ||||
| 	}} | ||||
|  | ||||
| 	db.prepare("UPDATE guild_space SET privacy_level = ? WHERE guild_id = ?").run(level, guild_id) | ||||
| 	await createSpace.syncSpaceFully(guild_id) // this is inefficient but OK to call infrequently on user request | ||||
|  | ||||
| 	await discord.snow.interaction.editOriginalInteractionResponse(botID, token, { | ||||
| 	yield {editOriginalInteractionResponse: { | ||||
| 		content: `Privacy level updated to \`${levels[level]}\`.` | ||||
| 	}) | ||||
| 	}} | ||||
| } | ||||
|  | ||||
| /* c8 ignore start */ | ||||
|  | ||||
| /** @param {DiscordTypes.APIChatInputApplicationCommandGuildInteraction} interaction */ | ||||
| async function interact(interaction) { | ||||
| 	for await (const response of _interact(interaction, {createSpace})) { | ||||
| 		if (response.createInteractionResponse) { | ||||
| 			// TODO: Test if it is reasonable to remove `await` from these calls. Or zip these calls with the next interaction iteration and use Promise.all. | ||||
| 			await discord.snow.interaction.createInteractionResponse(interaction.id, interaction.token, response.createInteractionResponse) | ||||
| 		} else if (response.editOriginalInteractionResponse) { | ||||
| 			await discord.snow.interaction.editOriginalInteractionResponse(botID, interaction.token, response.editOriginalInteractionResponse) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| module.exports.interact = interact | ||||
| module.exports._interact = _interact | ||||
|   | ||||
							
								
								
									
										86
									
								
								src/discord/interactions/privacy.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/discord/interactions/privacy.test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| const {test} = require("supertape") | ||||
| const DiscordTypes = require("discord-api-types/v10") | ||||
| const {select, db} = require("../../passthrough") | ||||
| const {_interact} = require("./privacy") | ||||
|  | ||||
| /** | ||||
|  * @template T | ||||
|  * @param {AsyncIterable<T>} ai | ||||
|  * @returns {Promise<T[]>} | ||||
|  */ | ||||
| async function fromAsync(ai) { | ||||
| 	const result = [] | ||||
| 	for await (const value of ai) { | ||||
| 		result.push(value) | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| test("privacy: checks if guild is bridged", async t => { | ||||
| 	const msgs = await fromAsync(_interact({ | ||||
| 		data: { | ||||
| 			options: [] | ||||
| 		}, | ||||
| 		guild_id: "0" | ||||
| 	}, {})) | ||||
| 	t.equal(msgs.length, 1) | ||||
| 	t.equal(msgs[0].createInteractionResponse.data.content, "This server isn't bridged to Matrix, so you can't set the Matrix privacy level.") | ||||
| }) | ||||
|  | ||||
| test("privacy: reports usage if there is no parameter", async t => { | ||||
| 	const msgs = await fromAsync(_interact({ | ||||
| 		data: { | ||||
| 			options: [] | ||||
| 		}, | ||||
| 		guild_id: "112760669178241024" | ||||
| 	}, {})) | ||||
| 	t.equal(msgs.length, 1) | ||||
| 	t.match(msgs[0].createInteractionResponse.data.content, /Usage: `\/privacy/) | ||||
| }) | ||||
|  | ||||
| test("privacy: reports usage for invalid parameter", async t => { | ||||
| 	const msgs = await fromAsync(_interact({ | ||||
| 		data: { | ||||
| 			options: [ | ||||
| 				{ | ||||
| 					name: "level", | ||||
| 					type: DiscordTypes.ApplicationCommandOptionType.String, | ||||
| 					value: "info" | ||||
| 				} | ||||
| 			] | ||||
| 		}, | ||||
| 		guild_id: "112760669178241024" | ||||
| 	}, {})) | ||||
| 	t.equal(msgs.length, 1) | ||||
| 	t.match(msgs[0].createInteractionResponse.data.content, /Usage: `\/privacy/) | ||||
| }) | ||||
|  | ||||
| test("privacy: updates setting and calls syncSpace for valid parameter", async t => { | ||||
| 	let called = 0 | ||||
| 	const msgs = await fromAsync(_interact({ | ||||
| 		data: { | ||||
| 			options: [ | ||||
| 				{ | ||||
| 					name: "level", | ||||
| 					type: DiscordTypes.ApplicationCommandOptionType.String, | ||||
| 					value: "directory" | ||||
| 				} | ||||
| 			] | ||||
| 		}, | ||||
| 		guild_id: "112760669178241024" | ||||
| 	}, { | ||||
| 		createSpace: { | ||||
| 			async syncSpaceFully(guildID) { | ||||
| 				called++ | ||||
| 				t.equal(guildID, "112760669178241024") | ||||
| 			} | ||||
| 		} | ||||
| 	})) | ||||
| 	t.equal(msgs.length, 2) | ||||
| 	t.equal(msgs[0].createInteractionResponse.type, DiscordTypes.InteractionResponseType.DeferredChannelMessageWithSource) | ||||
| 	t.equal(msgs[1].editOriginalInteractionResponse.content, "Privacy level updated to `directory`.") | ||||
| 	t.equal(called, 1) | ||||
| 	t.equal(select("guild_space", "privacy_level", {guild_id: "112760669178241024"}).pluck().get(), 2) | ||||
| 	// Undo database changes | ||||
| 	db.prepare("UPDATE guild_space SET privacy_level = 0 WHERE guild_id = ?").run("112760669178241024") | ||||
| }) | ||||
| @@ -140,5 +140,6 @@ file._actuallyUploadDiscordFileToMxc = function(url, res) { throw new Error(`Not | ||||
| 	require("../src/m2d/converters/emoji-sheet.test") | ||||
| 	require("../src/discord/interactions/invite.test") | ||||
| 	require("../src/discord/interactions/matrix-info.test") | ||||
| 	require("../src/discord/interactions/privacy.test") | ||||
| 	require("../src/discord/interactions/reactions.test") | ||||
| })() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Cadence Ember
					Cadence Ember