feat: add integrations and mobile-ready setup

Add bundled JSON quote fallback, responsive UI, Discord slash commands, Android setup documentation, and complete integration installation instructions. Set the Tauri application version to 1.1.0 for the release.
This commit is contained in:
2026-09-16 17:03:27 -04:00
parent 4e24e2d989
commit 84fd2da49c
9 changed files with 217 additions and 138 deletions

View File

@@ -0,0 +1,36 @@
import { Client, GatewayIntentBits } from "discord.js";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, resolve } from "node:path";
const root = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
const quotes = JSON.parse(readFileSync(resolve(root, "src-tauri/data/quotes.json"), "utf8"));
const challenges = new Map();
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
function encrypt(text, type) {
if (type === "atbash") return text.replace(/[A-Z]/g, letter => String.fromCharCode(90 - (letter.charCodeAt(0) - 65)));
const shift = Math.floor(Math.random() * 25) + 1;
return { text: text.replace(/[A-Z]/g, letter => String.fromCharCode(65 + (letter.charCodeAt(0) - 65 + shift) % 26)), key: `Caesar shift ${shift}` };
}
client.once("ready", () => console.log(`Cipher Master connected as ${client.user.tag}`));
client.on("interactionCreate", async interaction => {
if (!interaction.isChatInputCommand()) return;
const id = `${interaction.guildId}:${interaction.user.id}`;
if (interaction.commandName === "cipher") {
const type = interaction.options.getString("type") ?? "caesar";
const plaintext = quotes[Math.floor(Math.random() * quotes.length)].toUpperCase();
const encrypted = encrypt(plaintext, type);
const challenge = typeof encrypted === "string" ? { text: encrypted, key: "Atbash: reversed alphabet" } : encrypted;
challenges.set(id, { ...challenge, plaintext, type });
await interaction.reply({ content: `**${type.toUpperCase()} CHALLENGE**\n\n\`${challenge.text}\``, ephemeral: false });
} else if (interaction.commandName === "hint" || interaction.commandName === "solution") {
const challenge = challenges.get(id);
if (!challenge) return interaction.reply({ content: "Create a challenge first with `/cipher`.", ephemeral: true });
const content = interaction.commandName === "hint" ? `Cipher: **${challenge.type}**. ${challenge.type === "caesar" ? "Try counting the alphabet shift." : "Map each letter to its mirror in the alphabet."}` : `Plaintext: **${challenge.plaintext}**\nKey: **${challenge.key}**`;
await interaction.reply({ content, ephemeral: true });
}
});
client.login(process.env.DISCORD_TOKEN);