Skip to content

AiverAiva/meoww

Repository files navigation

🐾 Meoww

A modern Discord bot built with Deno 2 and Discordeno v21, featuring smart link previews, music playback, and fun interactions.

Deno Discordeno License: MIT

🌐 Website

Landing page at https://meoww.weikuwu.me with EN and 繁體中文 support.

Route Language
/en/ English
/zh-TW/ 繁體中文

Tech Stack: Astro + SSG

Commands:

cd website
yarn install
yarn dev      # Development server
yarn build    # Production build
yarn preview  # Preview production build

Environment:

  • Node.js >= 22.12.0

✨ Features

🔗 Smart Link Previews

Preview links from popular platforms directly in Discord. Supported platforms:

Platform Support Type Auto Preview
Twitter / X Full Yes
Threads Full Yes
Pornhub Full Yes
Pixiv Full Yes
WNACG Full Yes
nHentai Full Yes

🎵 Music Playback

Lavalink-based music system with rich features:

  • Queue Management: Add, remove, and organize your music queue
  • Auto-Disconnect: Automatically leaves when the voice channel is empty
  • Now Playing: Displays current track information with controls
  • High Quality: Streams audio without quality loss

💝 Fun Interactions

Express yourself with animated GIF interactions:

  • Patpat Command: Use /patpat as a slash command or right-click menu action
  • Animated GIFs: Custom GIF generation with avatar overlays
  • Smooth Animations: Frame-based GIF creation for fluid motion

🛡️ Safety Features

  • NSFW Detection: Automatically detects and handles NSFW content appropriately
  • Channel Validation: Ensures commands are used in appropriate channels

🏗️ Modern Architecture

Built with modern development practices:

  • Modular Commands: Clean, organized command structure
  • Component V2 UI: Modern Discord interaction components
  • Event-Driven: Responsive event handling system
  • LogTape Logging: Structured, performant logging

📋 Requirements

Prerequisites

Discord Intents

Your bot requires the following intents:

Intent Purpose
Guilds Access to server information
GuildMessages Message events in servers
MessageContent Read message content
GuildVoiceStates Voice state updates for music

🚀 Getting Started

1. Clone and Configure

git clone https://github.com/AiverAiva/meoww.git
cd meoww
cp .env.example .env

2. Configure Environment

Edit the .env file with your credentials:

DISCORD_TOKEN=your_discord_bot_token_here
LAVALINK_HOST=localhost:2333
LAVALINK_PASSWORD=your_lavalink_password

3. Run the Bot

Development mode (with file watching):

deno task dev

Production mode:

deno task start

🐳 Docker Deployment

Building the Image

docker build -t meoww-bot .

Running the Container

docker run -d \
  --name meoww \
  -e DISCORD_TOKEN=your_token \
  -e LAVALINK_HOST=lavalink-server \
  -e LAVALINK_PASSWORD=your_password \
  meoww-bot

Docker Compose

Create a docker-compose.yml file:

version: "3.8"

services:
  meoww:
    build: .
    container_name: meoww
    environment:
      DISCORD_TOKEN: your_discord_bot_token_here
      LAVALINK_HOST: lavalink:2333
      LAVALINK_PASSWORD: your_lavalink_password
    depends_on:
      - lavalink

  lavalink:
    image: ghcr.io/lavalink-devs/lavalink:4
    container_name: lavalink
    environment:
      SERVER_PORT: 2333
      LAVALINK_ADMIN_PASSWORD: your_lavalink_password
    volumes:
      - lavalink_data:/home/lavalink

volumes:
  lavalink_data:

Start with:

docker-compose up -d

📁 Project Structure

meoww/
├── assets/
│   └── patpat/
│       ├── bg.png              # Patpat GIF background
│       ├── overlay.png         # Avatar overlay mask
│       ├── cat.png             # Cat ears overlay
│       ├── cat Overlay.png     # Secondary cat overlay
│       ├── 1.png to 24.png     # GIF animation frames
│       └── fonts/
│           └── impact.ttf      # Font for text rendering
│
├── commands/                   # Bot commands
│   ├── mod.ts                  # Command module exports
│   ├── registry.ts             # Command registry and mapping
│   ├── ping.ts                 # Ping command (Component V2 example)
│   ├── patpat.ts               # Patpat GIF generation command
│   ├── preview.ts              # Link preview command
│   └── music.ts                # Music playback commands
│
├── events/                     # Event handlers
│   ├── mod.ts                  # Event module exports
│   ├── ready.ts                # Bot ready event handler
│   ├── interactionCreate.ts    # Slash/button/select menu handlers
│   └── messageCreate.ts        # Message event handlers
│
├── interactions/               # Interaction definitions
│   ├── commands/                # Slash command definitions
│   ├── components/             # Button and select menu handlers
│   └── messages/               # Message component handlers
│
├── listeners/
│   └── message/                # Message-based listeners
│       └── autoResponders.ts   # Auto-response handlers
│
├── utils/                      # Utility modules
│   ├── previewers/             # Link preview fetchers
│   │   ├── mod.ts              # Preview aggregator (getAnyPreview)
│   │   ├── twitter.ts          # Twitter/X preview
│   │   ├── threads.ts          # Threads preview
│   │   ├── pornhub.ts          # Pornhub preview
│   │   ├── pixiv.ts            # Pixiv preview
│   │   ├── wnacg.ts            # WNACG preview
│   │   └── nhentai.ts          # nHentai preview
│   │
│   ├── gif/                    # GIF generation utilities
│   │   └── patpat_generator.ts # Patpat GIF builder
│   │
│   ├── logger.ts               # LogTape logger configuration
│   ├── lavalink.ts             # Lavalink manager setup
│   ├── components_v2.ts         # Component V2 helpers
│   └── ui_factory.ts           # UI element factory
│
├── main.ts                     # Bot entry point
├── deno.json                   # Deno configuration
├── Dockerfile                  # Docker build file
├── .env.example                # Environment template
├── .gitignore                  # Git ignore rules
└── LICENSE                     # MIT License

⚙️ Configuration

Environment Variables

Variable Required Default Description
DISCORD_TOKEN Yes Your Discord bot token
LAVALINK_HOST No localhost:2333 Lavalink server (include port like localhost:2333)
LAVALINK_PASSWORD No youshallnotpass Lavalink server password

Discord Intents

Intent Enabled Reason
Guilds Yes Required for server access
GuildMessages Yes Message event handling
MessageContent Yes Link detection
GuildVoiceStates Yes Music playback

📚 Commands Reference

Slash Commands

Command Description
/ping Basic ping command to verify bot is responsive
/patpat [user] Send a patpat GIF to the specified user

Message Context Menu

Command Description
Preview Link Right-click any message with a link to preview it

User Context Menu

Command Description
patpat Right-click a user to send them a patpat GIF

🛠️ Development Guide

Adding a New Command

Create a new command file in commands/:

// commands/mycommand.ts
import { type Command, createCommand } from "../deps.ts";

export const myCommand = createCommand({
  meta: {
    name: "mycommand",
    description: "Description of my command",
  },
  contextMenu: {
    type: "message" as const, // or "user"
    // For slash commands, omit contextMenu
  },
  run(ctx) {
    // Your command logic here
    return ctx.respond({
      content: "Hello from my command!",
    });
  },
});

Register in commands/mod.ts:

import { myCommand } from "./mycommand.ts";

export const commands = [pingCommand, previewCommand, patpatCommand, myCommand];

Adding a Link Previewer

Create a new previewer in utils/previewers/:

// utils/previewers/myplatform.ts
import type { PreviewResult } from "./mod.ts";

const MYPLATFORM_REGEX = /myplatform\.com\/watch\?v=(\w+)/;

export async function fetchMyPlatform(url: string): Promise<PreviewResult | null> {
  const match = url.match(MYPLATFORM_REGEX);
  if (!match) return null;

  // Fetch and parse the page
  const response = await fetch(url);
  const html = await response.text();

  // Extract metadata
  const title = extractTitle(html);
  const thumbnail = extractThumbnail(html);

  return {
    title,
    description: "My platform content",
    thumbnail,
    url,
  };
}

Register in utils/previewers/mod.ts:

import { fetchMyPlatform } from "./myplatform.ts";

export async function getAnyPreview(url: string): Promise<PreviewResult | null> {
  // Chain through existing previewers
  return (
    await fetchTwitter(url) ||
    await fetchPornhub(url) ||
    await fetchPixiv(url) ||
    await fetchWNACG(url) ||
    await fetchNhentai(url) ||
    await fetchMyPlatform(url) ||  // Add your new previewer here
    null
  );
}

Adding an Event Handler

Create an event file in events/:

// events/myEvent.ts
import type { Bot, EventOptions } from "../deps.ts";

export const myEvent: EventOptions = {
  name: "myEvent",
  type: "once" as const, // or "every"
  run(bot: Bot) {
    // Your event logic
    console.log("My event fired!");
  },
};

Register in events/mod.ts:

import { myEvent } from "./myEvent.ts";

export const events = [readyEvent, interactionCreateEvent, messageCreateEvent, myEvent];

🤝 Contributing

Contributions are welcome! Feel free to submit issues and pull requests.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

💬 Support

📄 License

This project is licensed under the MIT License.

View the full license: LICENSE

Created by AiverAiva💜

🙏 Acknowledgments

  • Discordeno — Powerful Discord API wrapper for Deno
  • LogTape — Structured logging for Deno applications
  • lavalink-client — Lavalink integration for Discord bots
  • jimp — Image processing in pure JavaScript

Made with ❤️ and Deno

About

A modern Discord bot with smart link previews, music playback, and adorable interactions.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors