first commit

This commit is contained in:
synt-xerror
2026-04-14 21:15:05 -03:00
commit eecef0be88
44 changed files with 1372 additions and 0 deletions

160
forca/index.js Normal file
View File

@@ -0,0 +1,160 @@
/**
* plugins/forca/index.js
*
* Hangman game plugin with isolated i18n.
* Game state is stored internally per chat.
*/
import { CMD_PREFIX } from "../../config.js";
import { createPluginI18n } from "../../utils/pluginI18n.js";
const { t } = createPluginI18n(import.meta.url);
// Game states
const activeGames = new Map(); // chatId -> { word, theme, lives, progress }
const activeParticipants = new Map(); // chatId -> Set of users who reacted
export let hangmanActive = false;
// Sample words
const WORDS = [
{ word: "python", theme: "Programming Language" },
{ word: "javascript", theme: "Programming Language" },
{ word: "java", theme: "Programming Language" },
{ word: "dog", theme: "Animal" },
{ word: "cat", theme: "Animal" },
{ word: "elephant", theme: "Animal" },
{ word: "giraffe", theme: "Animal" },
{ word: "guitar", theme: "Musical Instrument" },
{ word: "piano", theme: "Musical Instrument" },
{ word: "drums", theme: "Musical Instrument" },
{ word: "violin", theme: "Musical Instrument" },
{ word: "soccer", theme: "Sport" },
{ word: "basketball", theme: "Sport" },
{ word: "swimming", theme: "Sport" },
{ word: "tennis", theme: "Sport" },
{ word: "brazil", theme: "Country" },
{ word: "japan", theme: "Country" },
{ word: "canada", theme: "Country" },
{ word: "france", theme: "Country" },
{ word: "mars", theme: "Planet" },
{ word: "venus", theme: "Planet" },
{ word: "jupiter", theme: "Planet" },
{ word: "saturn", theme: "Planet" },
{ word: "minecraft", theme: "Game" },
{ word: "fortnite", theme: "Game" },
{ word: "roblox", theme: "Game" },
{ word: "amongus", theme: "Game" },
{ word: "rose", theme: "Flower" },
{ word: "sunflower", theme: "Flower" },
{ word: "tulip", theme: "Flower" },
{ word: "orchid", theme: "Flower" },
{ word: "scissors", theme: "Object" },
{ word: "notebook", theme: "Object" },
{ word: "computer", theme: "Object" },
{ word: "phone", theme: "Object" },
{ word: "moon", theme: "Celestial Body" },
{ word: "sun", theme: "Celestial Body" },
{ word: "star", theme: "Celestial Body" },
{ word: "comet", theme: "Celestial Body" },
{ word: "ocean", theme: "Nature" },
{ word: "mountain", theme: "Nature" },
];
// Generate word with underscores
const generateProgress = word =>
word.replace(/[a-zA-Z]/g, "_");
export default async function ({ msg, api }) {
const chatId = api.chat.id;
const sub = msg.args[1];
// ── Main game command
if (msg.is(CMD_PREFIX + "forca")) {
if (!sub) {
await api.send(
`${t("title")}\n\n` +
`\`${CMD_PREFIX}forca start\`${t("startCommand")}\n` +
`\`${CMD_PREFIX}forca stop\`${t("stopCommand")}`
);
return;
}
if (sub === "start") {
hangmanActive = true;
// Get random word
const random = WORDS[Math.floor(Math.random() * WORDS.length)];
// Initialize game
activeGames.set(chatId, {
word: random.word.toLowerCase(),
theme: random.theme,
lives: 6,
progress: generateProgress(random.word)
});
activeParticipants.set(chatId, new Set()); // reset participants
await api.send(
t("started", {
theme: random.theme,
word: generateProgress(random.word),
lives: 6
})
);
return;
}
if (sub === "stop") {
activeGames.delete(chatId);
activeParticipants.delete(chatId);
await api.send(t("stopped"));
return;
}
await api.send(
`${t("invalidCommand", { sub })} \`${CMD_PREFIX}forca start\` ${t("or")} \`${CMD_PREFIX}forca stop\`.`
);
return;
}
// ── Game attempts
const game = activeGames.get(chatId);
if (!game) return; // No active game
const attempt = msg.body.trim().toLowerCase();
if (!/^[a-z]$/.test(attempt)) return; // single letters only
// Check if letter is in word
let hit = false;
let newProgress = game.progress.split("");
for (let i = 0; i < game.word.length; i++) {
if (game.word[i] === attempt) {
newProgress[i] = attempt;
hit = true;
}
}
game.progress = newProgress.join("");
if (!hit) game.lives--;
// Feedback for group
if (game.progress === game.word) {
await msg.reply(t("won", { word: game.word }));
activeGames.delete(chatId);
activeParticipants.delete(chatId);
return;
}
if (game.lives <= 0) {
await msg.reply(t("lost", { word: game.word }));
activeGames.delete(chatId);
activeParticipants.delete(chatId);
return;
}
await msg.reply(
`${t("status", { word: game.progress, lives: game.lives })}\n` +
(hit ? t("correct") : t("wrong"))
);
}

14
forca/locale/en.json Normal file
View File

@@ -0,0 +1,14 @@
{
"title": "Hangman Game",
"startCommand": "starts the game",
"stopCommand": "stops the game",
"started": "Hangman game started!\n\nTheme: *{{theme}}*\nWord: `{{word}}`\nLives: {{lives}}\n\nType a letter to guess!",
"stopped": "Hangman game ended.",
"invalidCommand": "Subcommand *{{sub}}* does not exist.\nUse",
"or": "or",
"won": "Congratulations! Complete word: `{{word}}`",
"lost": "Game over! Word was: `{{word}}`",
"status": "Word: `{{word}}`\nLives: {{lives}}",
"correct": "Got the letter!",
"wrong": "Wrong letter!"
}

14
forca/locale/es.json Normal file
View File

@@ -0,0 +1,14 @@
{
"title": "Juego del Ahorcado",
"startCommand": "inicia el juego",
"stopCommand": "detiene el juego",
"started": "¡Juego del Ahorcado iniciado!\n\nTema: *{{theme}}*\nPalabra: `{{word}}`\nVidas: {{lives}}\n\nEscribe una letra para adivinar!",
"stopped": "Juego del Ahorcado terminado.",
"invalidCommand": "El subcomando *{{sub}}* no existe.\nUsa",
"or": "o",
"won": "¡Felicitaciones! Palabra completa: `{{word}}`",
"lost": "¡Fin del juego! La palabra era: `{{word}}`",
"status": "Palabra: `{{word}}`\nVidas: {{lives}}",
"correct": "¡Letra correcta!",
"wrong": "¡Letra incorrecta!"
}

14
forca/locale/pt.json Normal file
View File

@@ -0,0 +1,14 @@
{
"title": "Jogo da Forca",
"startCommand": "inicia o jogo",
"stopCommand": "encerra o jogo",
"started": "Jogo da Forca iniciado!\n\nTema: *{{theme}}*\nPalavra: `{{word}}`\nVidas: {{lives}}\n\nDigite uma letra para adivinhar!",
"stopped": "Jogo da Forca encerrado.",
"invalidCommand": "Subcomando *{{sub}}* não existe.\nUse",
"or": "ou",
"won": "Parabéns! Palavra completa: `{{word}}`",
"lost": "Fim de jogo! Palavra era: `{{word}}`",
"status": "Palavra: `{{word}}`\nVidas: {{lives}}",
"correct": "Acertou a letra!",
"wrong": "Errou a letra!"
}

7
forca/manyplug.json Normal file
View File

@@ -0,0 +1,7 @@
{
"name": "forca",
"version": "1.0.0",
"category": "games",
"service": false,
"dependencies": {}
}