feat: add Cat module with /cat and /catgif commands using TheCatAPI
All checks were successful
Auto Build and Push Docker Image / build (push) Successful in 7s
All checks were successful
Auto Build and Push Docker Image / build (push) Successful in 7s
This commit is contained in:
@@ -6,5 +6,8 @@ TWITCH_USERNAME=dein_twitch_username
|
||||
TWITCH_OAUTH_TOKEN=oauth:xxxxxxxxxxxxxxxxxx
|
||||
BOT_OWNER_ID=deine_discord_user_id
|
||||
|
||||
# Optional: TheCatAPI Key für höheres Ratenlimit (default: leer / kostenlos)
|
||||
THECATAPI_KEY=
|
||||
|
||||
# Optional: Automatische Slash-Command Registrierung bei Bot-Start (default: true)
|
||||
AUTO_DEPLOY=true
|
||||
@@ -19,7 +19,8 @@ The bot uses a **Modular Command & Event Loading** pattern with **ESM (ECMAScrip
|
||||
10. **Welcome/Goodbye System:** Guild member add/remove events with customizable messages.
|
||||
11. **Logging System:** Configurable event logging (messages, roles, moderation, etc.) via centralized `EventLogger`.
|
||||
12. **Role Selection System:** Self-service role assignment via select menus with support for exclusive categories and max-role limits.
|
||||
13. **Centralized Event Logger:** Kapsel event logs into `EventLogger.sendLog()` to eliminate duplicated logging logic across event files.
|
||||
13. **Cat & CatGIF System:** TheCatAPI integration for random cat images and GIFs (`CatManager`).
|
||||
14. **Centralized Event Logger:** Kapsel event logs into `EventLogger.sendLog()` to eliminate duplicated logging logic across event files.
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
@@ -37,6 +38,7 @@ pixelpoebel/
|
||||
│ ├── Command.ts
|
||||
│ ├── Database.ts # Database with Transaction, Indexes & Surgical Caching
|
||||
│ ├── EventLogger.ts # Centralized event logging helper
|
||||
│ ├── CatManager.ts # TheCatAPI HTTP request helper
|
||||
│ ├── TwitchManager.ts # Batch Polling & Transaction logic
|
||||
│ ├── TwitchMonitor.ts # IRC Monitoring & Webhook reuse
|
||||
│ ├── TwitchCache.ts # IRC Message FIFO Cache
|
||||
|
||||
@@ -72,6 +72,8 @@ npm run deploy
|
||||
### Öffentlich
|
||||
- `/ping` – Latenz test
|
||||
- `/help` – Alle Befehle
|
||||
- `/cat [typ]` – Zufälliges Katzenbild oder Katzen-GIF (Auswahl: Bild / GIF)
|
||||
- `/catgif` – Zufälliges Katzen-GIF direkt posten
|
||||
- `/twitch online <channel>` – Twitch-Status
|
||||
- `/twitch list` – Überwachte Kanäle
|
||||
- `/twitch help` – Twitch-Hilfe
|
||||
|
||||
40
src/commands/utility/cat.ts
Normal file
40
src/commands/utility/cat.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { SlashCommandBuilder, EmbedBuilder } from 'discord.js';
|
||||
import { Command } from '../../structures/Command.js';
|
||||
import { CatManager } from '../../structures/CatManager.js';
|
||||
|
||||
const command: Command = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('cat')
|
||||
.setDescription('Postet ein zufälliges Katzenbild oder Katzen-GIF.')
|
||||
.addStringOption(option =>
|
||||
option.setName('typ')
|
||||
.setDescription('Wähle zwischen Bild oder GIF')
|
||||
.setRequired(false)
|
||||
.addChoices(
|
||||
{ name: 'Bild', value: 'image' },
|
||||
{ name: 'GIF', value: 'gif' }
|
||||
))
|
||||
.setDMPermission(true),
|
||||
category: 'Public',
|
||||
async execute(interaction: any) {
|
||||
const type = (interaction.options.getString('typ') as 'image' | 'gif') || 'image';
|
||||
await interaction.deferReply();
|
||||
|
||||
const imageUrl = await CatManager.fetchCatImage(type);
|
||||
if (!imageUrl) {
|
||||
await interaction.editReply('❌ Konnte kein Katzenbild laden. Bitte versuche es später erneut.');
|
||||
return;
|
||||
}
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(type === 'gif' ? '🐱 Zufälliges Katzen-GIF' : '🐱 Zufälliges Katzenbild')
|
||||
.setURL(imageUrl)
|
||||
.setImage(imageUrl)
|
||||
.setColor(0xf39c12)
|
||||
.setTimestamp();
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
},
|
||||
};
|
||||
|
||||
export default command;
|
||||
31
src/commands/utility/catgif.ts
Normal file
31
src/commands/utility/catgif.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { SlashCommandBuilder, EmbedBuilder } from 'discord.js';
|
||||
import { Command } from '../../structures/Command.js';
|
||||
import { CatManager } from '../../structures/CatManager.js';
|
||||
|
||||
const command: Command = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('catgif')
|
||||
.setDescription('Postet direkt ein zufälliges Katzen-GIF.')
|
||||
.setDMPermission(true),
|
||||
category: 'Public',
|
||||
async execute(interaction: any) {
|
||||
await interaction.deferReply();
|
||||
|
||||
const imageUrl = await CatManager.fetchCatImage('gif');
|
||||
if (!imageUrl) {
|
||||
await interaction.editReply('❌ Konnte kein Katzen-GIF laden. Bitte versuche es später erneut.');
|
||||
return;
|
||||
}
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('🐱 Zufälliges Katzen-GIF')
|
||||
.setURL(imageUrl)
|
||||
.setImage(imageUrl)
|
||||
.setColor(0xf39c12)
|
||||
.setTimestamp();
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
},
|
||||
};
|
||||
|
||||
export default command;
|
||||
26
src/structures/CatManager.ts
Normal file
26
src/structures/CatManager.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
export class CatManager {
|
||||
static async fetchCatImage(type: 'image' | 'gif' = 'image'): Promise<string | null> {
|
||||
const apiKey = process.env.THECATAPI_KEY || '';
|
||||
const mimeTypes = type === 'gif' ? 'gif' : 'jpg,png';
|
||||
const url = `https://api.thecatapi.com/v1/images/search?mime_types=${mimeTypes}`;
|
||||
|
||||
try {
|
||||
const headers: Record<string, string> = {};
|
||||
if (apiKey) {
|
||||
headers['x-api-key'] = apiKey;
|
||||
}
|
||||
|
||||
const response = await fetch(url, { headers });
|
||||
if (!response.ok) return null;
|
||||
|
||||
const data: any = await response.json();
|
||||
if (Array.isArray(data) && data.length > 0 && data[0].url) {
|
||||
return data[0].url;
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('[CAT] Error fetching cat image:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user