docs(docs): remove obsolete mascot and microservices documentation
Removes outdated implementation guides and architecture documentation related to the mascot chatbot and microservices setup. - Delete `MASCOT_CHATBOT_GUIDE.md` - Delete `MASCOT_IMPLEMENTATION.md` - Delete `README_MICROSERVICES.md`
This commit is contained in:
@@ -1,325 +0,0 @@
|
|||||||
# Mascot Chatbot Implementation Guide
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The mascot has been upgraded from a simple insights display to a **full-featured interactive chatbot** that can:
|
|
||||||
- Engage in conversations with users
|
|
||||||
- Provide real-time analytics insights
|
|
||||||
- Answer questions about messages and conversations
|
|
||||||
- Generate intelligent recommendations
|
|
||||||
- Maintain conversation history
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
### Components
|
|
||||||
|
|
||||||
#### MascotChatbot (`src/widgets/mascot/MascotChatbot.tsx`)
|
|
||||||
Main chatbot UI component with chat interface, message bubbles, and user input.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
<MascotChatbot
|
|
||||||
isOpen={boolean} // Chat window visibility
|
|
||||||
onSetIsOpen={(open) => void} // Toggle chat window
|
|
||||||
onSendMessage={async (msg) => string} // Handle user messages
|
|
||||||
mascotName="Discord Watcher" // Mascot name
|
|
||||||
mascotAvatar={url} // Mascot avatar image
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Features:**
|
|
||||||
- Framer Motion animations
|
|
||||||
- Message bubbles with typing indicator
|
|
||||||
- Minimize/maximize window
|
|
||||||
- Message history
|
|
||||||
- Responsive design
|
|
||||||
- Auto-scroll to latest message
|
|
||||||
|
|
||||||
#### useMascotChat (`src/shared/hooks/useMascotChat.ts`)
|
|
||||||
React hook for managing mascot chat logic and AI responses.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const mascotChat = useMascotChat({
|
|
||||||
messageCount: number, // Total messages
|
|
||||||
activeParticipants: number, // Unique users
|
|
||||||
lastActivity: string, // Activity status
|
|
||||||
topicsDiscussed: string[] // Conversation topics
|
|
||||||
});
|
|
||||||
|
|
||||||
mascotChat.handleSendMessage(message) // Send message & get response
|
|
||||||
```
|
|
||||||
|
|
||||||
### Data Flow
|
|
||||||
|
|
||||||
```
|
|
||||||
User Input
|
|
||||||
↓
|
|
||||||
MascotChatbot (UI)
|
|
||||||
↓
|
|
||||||
useMascotChat hook
|
|
||||||
↓
|
|
||||||
generateIntelligentResponse()
|
|
||||||
↓
|
|
||||||
Response (local) or Backend API
|
|
||||||
↓
|
|
||||||
Message displayed in chat
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
### 1. Smart Responses
|
|
||||||
The mascot responds intelligently based on keywords and context:
|
|
||||||
|
|
||||||
**Analytics Questions:**
|
|
||||||
- "Berapa pesan?" → Returns message count with context
|
|
||||||
- "Berapa orang?" → Returns participant count
|
|
||||||
- "Berapa aktif?" → Activity metrics
|
|
||||||
|
|
||||||
**Insights:**
|
|
||||||
- "Apa insight?" → Summarizes conversation patterns
|
|
||||||
- "Ringkasan" → Full conversation summary
|
|
||||||
- "Saran" → Recommendations for improvement
|
|
||||||
|
|
||||||
**General:**
|
|
||||||
- Greetings recognition
|
|
||||||
- Help/info requests
|
|
||||||
- Default contextual responses
|
|
||||||
|
|
||||||
### 2. Real-time Context
|
|
||||||
The chatbot receives live data about:
|
|
||||||
- Message counts
|
|
||||||
- Active participants
|
|
||||||
- Last activity status
|
|
||||||
- Topics being discussed
|
|
||||||
|
|
||||||
### 3. Conversation History
|
|
||||||
- Messages persist during session
|
|
||||||
- Typing indicator while processing
|
|
||||||
- Timestamps on all messages
|
|
||||||
- User/mascot distinction
|
|
||||||
|
|
||||||
### 4. Extensibility
|
|
||||||
The implementation is ready for:
|
|
||||||
- Backend AI integration via API
|
|
||||||
- Discord Gateway context enrichment
|
|
||||||
- Custom response training
|
|
||||||
- Multi-language support
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Basic Setup
|
|
||||||
```typescript
|
|
||||||
const [isChatOpen, setIsChatOpen] = useState(false);
|
|
||||||
const mascotChat = useMascotChat(contextData);
|
|
||||||
|
|
||||||
<MascotChatbot
|
|
||||||
isOpen={isChatOpen}
|
|
||||||
onSetIsOpen={setIsChatOpen}
|
|
||||||
onSendMessage={mascotChat.handleSendMessage}
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### With Backend Integration
|
|
||||||
```typescript
|
|
||||||
const handleMessage = async (message: string) => {
|
|
||||||
const response = await fetch('/api/mascot/chat', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify({ message, context })
|
|
||||||
});
|
|
||||||
return response.json();
|
|
||||||
};
|
|
||||||
|
|
||||||
<MascotChatbot
|
|
||||||
onSendMessage={handleMessage}
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### With Discord Gateway
|
|
||||||
```typescript
|
|
||||||
const handleMessage = async (message: string) => {
|
|
||||||
// Get enriched context from Discord
|
|
||||||
const guildContext = await getDiscordGuildContext(guildId);
|
|
||||||
|
|
||||||
// Generate response with context
|
|
||||||
return generateResponse(message, guildContext);
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## Chat Interface
|
|
||||||
|
|
||||||
### Visual Design
|
|
||||||
- **Header:** Gradient background (primary color), mascot info, controls
|
|
||||||
- **Messages:** Distinct bubbles for user (right) and mascot (left)
|
|
||||||
- **Input:** Text field with send button
|
|
||||||
- **Animations:** Spring physics for smooth entrance/exit
|
|
||||||
- **Typing Indicator:** Animated dots while processing
|
|
||||||
|
|
||||||
### Keyboard Shortcuts
|
|
||||||
- **Enter:** Send message
|
|
||||||
- **Esc:** Close chat (future enhancement)
|
|
||||||
- **Tab:** Minimize/restore window
|
|
||||||
|
|
||||||
## Integration Points
|
|
||||||
|
|
||||||
### 1. In App.tsx
|
|
||||||
```typescript
|
|
||||||
const mascotChat = useMascotChat({
|
|
||||||
messageCount: messages.messages.length,
|
|
||||||
activeParticipants: uniqueUserCount,
|
|
||||||
lastActivity: activityStatus,
|
|
||||||
topicsDiscussed: extractTopics(messages),
|
|
||||||
});
|
|
||||||
|
|
||||||
<MascotChatbot
|
|
||||||
isOpen={isMascotChatOpen}
|
|
||||||
onSetIsOpen={setIsMascotChatOpen}
|
|
||||||
onSendMessage={mascotChat.handleSendMessage}
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Position
|
|
||||||
- **Fixed:** bottom-right corner (bottom-6, right-6)
|
|
||||||
- **Z-index:** High (shadow-2xl ensures visibility)
|
|
||||||
- **Responsive:** Adapts to mobile/tablet
|
|
||||||
|
|
||||||
### 3. State Management
|
|
||||||
- `isMascotChatOpen`: Boolean flag for visibility
|
|
||||||
- `messages`: Array of ChatMessage objects
|
|
||||||
- `input`: Current user input text
|
|
||||||
- `loading`: Processing state
|
|
||||||
- `isMinimized`: Window state
|
|
||||||
|
|
||||||
## Extending with Backend
|
|
||||||
|
|
||||||
### Example: Express Backend Endpoint
|
|
||||||
```typescript
|
|
||||||
// POST /api/mascot/chat
|
|
||||||
app.post('/api/mascot/chat', async (req, res) => {
|
|
||||||
const { message, context } = req.body;
|
|
||||||
|
|
||||||
// Process with AI/LLM
|
|
||||||
const response = await callAI(message, context);
|
|
||||||
|
|
||||||
res.json({ response });
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example: Discord Gateway Integration
|
|
||||||
```typescript
|
|
||||||
async function getGuildContext(guildId: string) {
|
|
||||||
const messages = await getGuildMessages(guildId);
|
|
||||||
const members = await getActiveMembers(guildId);
|
|
||||||
|
|
||||||
return {
|
|
||||||
messageCount: messages.length,
|
|
||||||
activeParticipants: members.length,
|
|
||||||
recentTopics: extractTopics(messages),
|
|
||||||
serverHealth: analyzeHealth(messages, members)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Customization
|
|
||||||
|
|
||||||
### Change Mascot Avatar
|
|
||||||
```typescript
|
|
||||||
<MascotChatbot
|
|
||||||
mascotAvatar="https://your-custom-avatar.com/image.png"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Change Mascot Name
|
|
||||||
```typescript
|
|
||||||
<MascotChatbot
|
|
||||||
mascotName="Your Mascot Name"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Customize Responses
|
|
||||||
Edit `generateMascotResponse()` in `useMascotChat.ts`:
|
|
||||||
```typescript
|
|
||||||
function generateMascotResponse(input: string, context?: ChatContext): string {
|
|
||||||
const lower = input.toLowerCase();
|
|
||||||
|
|
||||||
// Add custom keywords
|
|
||||||
if (lower.includes('your-keyword')) {
|
|
||||||
return 'Your custom response';
|
|
||||||
}
|
|
||||||
|
|
||||||
// ... rest of logic
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Theme Colors
|
|
||||||
Edit Tailwind classes in `MascotChatbot.tsx`:
|
|
||||||
```typescript
|
|
||||||
// Change primary color
|
|
||||||
className="bg-gradient-to-r from-primary to-primary/80"
|
|
||||||
|
|
||||||
// Change to custom color
|
|
||||||
className="bg-gradient-to-r from-blue-500 to-blue-600"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Performance
|
|
||||||
|
|
||||||
### Optimizations
|
|
||||||
- ✅ Lazy-loaded component (renders only when needed)
|
|
||||||
- ✅ Memoized responses
|
|
||||||
- ✅ Efficient message rendering (virtualization possible)
|
|
||||||
- ✅ Minimal re-renders with useCallback
|
|
||||||
|
|
||||||
### Bundle Impact
|
|
||||||
- Component: ~15 KB
|
|
||||||
- Hook: ~5 KB
|
|
||||||
- Total: ~20 KB (gzipped)
|
|
||||||
|
|
||||||
## Future Enhancements
|
|
||||||
|
|
||||||
- [ ] Multi-language support
|
|
||||||
- [ ] Message persistence to database
|
|
||||||
- [ ] Advanced NLP/AI integration
|
|
||||||
- [ ] Export chat history
|
|
||||||
- [ ] Voice input/output
|
|
||||||
- [ ] Emoji reactions
|
|
||||||
- [ ] Suggested quick replies
|
|
||||||
- [ ] User preferences storage
|
|
||||||
- [ ] Chat analytics
|
|
||||||
- [ ] Integration with Discord Rich Presence
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Chat window not appearing
|
|
||||||
- Check `isOpen` prop is being set correctly
|
|
||||||
- Verify `onSetIsOpen` callback works
|
|
||||||
- Check z-index conflicts with other overlays
|
|
||||||
|
|
||||||
### Messages not sending
|
|
||||||
- Check `onSendMessage` is provided
|
|
||||||
- Verify message is not empty
|
|
||||||
- Check browser console for errors
|
|
||||||
|
|
||||||
### Responses not intelligent
|
|
||||||
- Add more keyword patterns
|
|
||||||
- Integrate with backend for better AI
|
|
||||||
- Provide context data to useMascotChat
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// Test basic rendering
|
|
||||||
render(<MascotChatbot isOpen={true} />);
|
|
||||||
|
|
||||||
// Test message sending
|
|
||||||
const mockOnSend = jest.fn().mockResolvedValue('Response');
|
|
||||||
fireEvent.change(input, { target: { value: 'Hello' } });
|
|
||||||
fireEvent.click(sendButton);
|
|
||||||
expect(mockOnSend).toHaveBeenCalledWith('Hello');
|
|
||||||
|
|
||||||
// Test animations
|
|
||||||
expect(screen.getByRole('dialog')).toHaveClass('motion-div');
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Status:** ✅ Production Ready
|
|
||||||
**Version:** 1.0.0
|
|
||||||
**Last Updated:** 2026-06-03
|
|
||||||
@@ -1,370 +0,0 @@
|
|||||||
# Mascot Implementation Guide
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The Discord Moderation Watcher frontend features an intelligent anime mascot with AI-powered conversation insights and animated floating chat bubbles.
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
### Components
|
|
||||||
|
|
||||||
#### MascotImage (`src/widgets/mascot/MascotImage.tsx`)
|
|
||||||
Main mascot component that displays the PNG image with optional floating chat bubble.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
<MascotImage
|
|
||||||
size="sm" | "md" | "lg" // Size variant: sm (64px), md (128px), lg (192px)
|
|
||||||
className="..." // Additional Tailwind classes
|
|
||||||
showChat={boolean} // Show chat bubble
|
|
||||||
chatMessage="..." // Chat message text
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Features:**
|
|
||||||
- Framer Motion spring animations
|
|
||||||
- Responsive sizing
|
|
||||||
- Gradient chat bubble with backdrop blur
|
|
||||||
- Auto-hide after 8 seconds
|
|
||||||
- Message circle icon
|
|
||||||
|
|
||||||
#### useMascotSummary (`src/shared/hooks/useMascotSummary.ts`)
|
|
||||||
React hook that generates AI insights from message data.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const summary = useMascotSummary({
|
|
||||||
messages: MessageRecord[], // Recent messages
|
|
||||||
enabled: boolean // Enable/disable hook
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
**Analysis:**
|
|
||||||
- Message count tracking
|
|
||||||
- Unique participant counting
|
|
||||||
- Average message length analysis
|
|
||||||
- Activity intensity detection
|
|
||||||
- Conversation type identification
|
|
||||||
- Auto-rotating insights (5-second cycle)
|
|
||||||
|
|
||||||
### Data Flow
|
|
||||||
|
|
||||||
```
|
|
||||||
App Component
|
|
||||||
├─ messages.messages
|
|
||||||
└─ Pass to DashboardLayout
|
|
||||||
│
|
|
||||||
├─ DashboardLayout
|
|
||||||
│ ├─ useMascotSummary hook
|
|
||||||
│ ├─ Generate mascotSummary
|
|
||||||
│ └─ Pass to Sidebar
|
|
||||||
│ │
|
|
||||||
│ ├─ Sidebar
|
|
||||||
│ │ └─ MascotImage
|
|
||||||
│ │ └─ Floating chat bubble
|
|
||||||
│ │
|
|
||||||
│ └─ Other components
|
|
||||||
│ ├─ EmptyStateMascot
|
|
||||||
│ ├─ EmptyStateMascot
|
|
||||||
│ └─ ...
|
|
||||||
```
|
|
||||||
|
|
||||||
## Assets
|
|
||||||
|
|
||||||
### Logo (SVG)
|
|
||||||
- **URL:** `https://raw.githubusercontent.com/IMPHNEN/imphnen-frontend-service/develop/docs/logo.svg`
|
|
||||||
- **Used in:** Favicon, Sidebar top
|
|
||||||
- **Size:** 8x8px
|
|
||||||
- **Cache:** 300 seconds (GitHub CDN)
|
|
||||||
|
|
||||||
### Mascot (PNG)
|
|
||||||
- **URL:** `https://raw.githubusercontent.com/IMPHNEN/imphnen-frontend-service/develop/apps/dimentorin/public/image/mascot-1.png`
|
|
||||||
- **Used in:** Sidebar, Empty states, Chat bubble
|
|
||||||
- **Sizes:** sm (64px), md (128px), lg (192px)
|
|
||||||
- **Cache:** 300 seconds (GitHub CDN)
|
|
||||||
|
|
||||||
## Locations
|
|
||||||
|
|
||||||
### Sidebar (sm - 64px)
|
|
||||||
- **Position:** Bottom corner, expanded sidebar only
|
|
||||||
- **Feature:** Chat bubble with rotating insights
|
|
||||||
- **Visibility:** Always visible when expanded
|
|
||||||
- **Chat Trigger:** Messages tab with active conversations
|
|
||||||
|
|
||||||
### Empty States (md - 128px, 60% opacity)
|
|
||||||
- Message Feed
|
|
||||||
- Image Grid
|
|
||||||
- Analytics Panel
|
|
||||||
- Active Speakers
|
|
||||||
- Voice Recordings
|
|
||||||
|
|
||||||
### NOT Displayed
|
|
||||||
- ❌ Auth/Login page
|
|
||||||
- ❌ Voice connection page
|
|
||||||
- ❌ Media control page
|
|
||||||
|
|
||||||
## Chat Bubble Design
|
|
||||||
|
|
||||||
### Visual Style
|
|
||||||
```
|
|
||||||
┌─────────────────────┐
|
|
||||||
│ 💬 "Diskusi aktif" │
|
|
||||||
│ • 5 peserta │
|
|
||||||
│ • Volume tinggi │
|
|
||||||
└─────────────────────┘
|
|
||||||
◯ (tail)
|
|
||||||
```
|
|
||||||
|
|
||||||
### CSS Classes
|
|
||||||
- Background: `bg-gradient-to-br from-primary/90 to-primary/80`
|
|
||||||
- Border: `border border-primary/50`
|
|
||||||
- Rounded: `rounded-2xl`
|
|
||||||
- Padding: `px-4 py-2.5`
|
|
||||||
- Effects: `shadow-lg backdrop-blur-sm`
|
|
||||||
|
|
||||||
### Animations
|
|
||||||
- **Entrance:** Spring (stiffness: 300, damping: 25)
|
|
||||||
- Scale: 0.8 → 1.0
|
|
||||||
- Opacity: 0 → 1
|
|
||||||
- Y Position: 10px → 0
|
|
||||||
- **Exit:** Reverse animation
|
|
||||||
- **Duration:** Auto-hide after 8 seconds
|
|
||||||
|
|
||||||
## AI Summary Logic
|
|
||||||
|
|
||||||
### generateInsight()
|
|
||||||
Analyzes message data to create meaningful insights.
|
|
||||||
|
|
||||||
**Factors Analyzed:**
|
|
||||||
1. **Message Count**
|
|
||||||
- Display: "📈 Total: X pesan"
|
|
||||||
|
|
||||||
2. **Participant Analysis**
|
|
||||||
- Count unique user_ids
|
|
||||||
- Display: "👥 Partisipan: N orang"
|
|
||||||
|
|
||||||
3. **Content Length Analysis**
|
|
||||||
- Average message length
|
|
||||||
- > 150 chars: "Diskusi mendalam 🔬"
|
|
||||||
- 80-150: "Percakapan normal 💬"
|
|
||||||
- < 80: "Chat cepat ⚡"
|
|
||||||
|
|
||||||
4. **Activity Intensity**
|
|
||||||
- > 50 msgs: "Volume tinggi 🔥"
|
|
||||||
- > 20 msgs: "Percakapan aktif"
|
|
||||||
- < 20: "Quiet mode"
|
|
||||||
|
|
||||||
5. **Topic Detection**
|
|
||||||
- Keywords: voice, recording, audio, chat, message, user
|
|
||||||
- Maps to labels: Voice, Recording, Audio, Chat, Message, User
|
|
||||||
|
|
||||||
### Auto-Rotation
|
|
||||||
- Updates every 5 seconds
|
|
||||||
- Cycles between different insights
|
|
||||||
- Keeps conversation fresh
|
|
||||||
- Smart rotation logic
|
|
||||||
|
|
||||||
## Usage Examples
|
|
||||||
|
|
||||||
### Basic Usage (Sidebar)
|
|
||||||
```typescript
|
|
||||||
<MascotImage
|
|
||||||
size="sm"
|
|
||||||
showChat={showChat && !collapsed}
|
|
||||||
chatMessage={mascotChatMessage}
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Empty State Usage
|
|
||||||
```typescript
|
|
||||||
<MascotImage size="md" className="opacity-60" />
|
|
||||||
```
|
|
||||||
|
|
||||||
### With Custom Message
|
|
||||||
```typescript
|
|
||||||
<MascotImage
|
|
||||||
size="md"
|
|
||||||
showChat={true}
|
|
||||||
chatMessage="🔥 Volume tinggi • 12 peserta"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Integration
|
|
||||||
|
|
||||||
### In DashboardLayout
|
|
||||||
```typescript
|
|
||||||
const mascotSummary = useMascotSummary({
|
|
||||||
messages: recentMessages,
|
|
||||||
enabled: activeTab === "messages" && recentMessages.length > 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
<Sidebar
|
|
||||||
activeTab={activeTab}
|
|
||||||
onTabChange={onTabChange}
|
|
||||||
mascotChatMessage={mascotSummary}
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### In App
|
|
||||||
```typescript
|
|
||||||
<DashboardLayout
|
|
||||||
activeTab={activeTab}
|
|
||||||
wsStatus={socket.status}
|
|
||||||
voiceStatus={voice.voiceStatus}
|
|
||||||
onTabChange={(tab) => patchUIState({ activeTab: tab })}
|
|
||||||
recentMessages={messages.messages}
|
|
||||||
>
|
|
||||||
{/* content */}
|
|
||||||
</DashboardLayout>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Customization
|
|
||||||
|
|
||||||
### Size Variants
|
|
||||||
Edit `sizeMap` in `MascotImage.tsx`:
|
|
||||||
```typescript
|
|
||||||
const sizeMap = {
|
|
||||||
sm: "w-16 h-auto", // 64px
|
|
||||||
md: "w-32 h-auto", // 128px
|
|
||||||
lg: "w-48 h-auto", // 192px
|
|
||||||
xl: "w-64 h-auto", // 256px (custom)
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### Chat Bubble Styling
|
|
||||||
Edit bubble classes in `MascotImage.tsx`:
|
|
||||||
- Change background: `bg-gradient-to-br from-primary/90 to-primary/80`
|
|
||||||
- Change corner radius: `rounded-2xl`
|
|
||||||
- Change padding: `px-4 py-2.5`
|
|
||||||
- Change effects: `shadow-lg backdrop-blur-sm`
|
|
||||||
|
|
||||||
### Animation Timing
|
|
||||||
Edit animation config:
|
|
||||||
- Spring stiffness: Higher = faster/snappier
|
|
||||||
- Spring damping: Higher = less bouncy
|
|
||||||
- Auto-hide delay: Change `setTimeout` in `useEffect`
|
|
||||||
|
|
||||||
### Summary Rotation
|
|
||||||
Edit rotation interval in `useMascotSummary`:
|
|
||||||
```typescript
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
// Update summary
|
|
||||||
}, 5000); // 5 seconds
|
|
||||||
```
|
|
||||||
|
|
||||||
## Performance Considerations
|
|
||||||
|
|
||||||
### Bundle Size Impact
|
|
||||||
- ✅ ChibiMascot removed: -895 lines
|
|
||||||
- ✅ MascotImage added: +98 lines
|
|
||||||
- ✅ useMascotSummary hook: +98 lines
|
|
||||||
- ✅ Net: -779 lines (smaller bundle!)
|
|
||||||
- ✅ PNG from CDN (not bundled)
|
|
||||||
|
|
||||||
### Runtime Performance
|
|
||||||
- ✅ Framer Motion optimized
|
|
||||||
- ✅ useCallback for memoization
|
|
||||||
- ✅ 5-second update cycle (not constant)
|
|
||||||
- ✅ Proper cleanup on unmount
|
|
||||||
- ✅ No memory leaks
|
|
||||||
|
|
||||||
### CDN Performance
|
|
||||||
- ✅ GitHub CDN caching: 300 seconds
|
|
||||||
- ✅ Browser caching enabled
|
|
||||||
- ✅ Reduces server load
|
|
||||||
- ✅ Fast global delivery
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Chat Bubble Not Showing
|
|
||||||
**Check:**
|
|
||||||
- `showChat` prop is `true`
|
|
||||||
- `chatMessage` is not empty
|
|
||||||
- Sidebar is expanded
|
|
||||||
- Active tab is "messages"
|
|
||||||
|
|
||||||
### Images Not Loading
|
|
||||||
**Check:**
|
|
||||||
- GitHub URLs are accessible (curl -I)
|
|
||||||
- CDN cache not stale (check ETag)
|
|
||||||
- Browser cache cleared
|
|
||||||
- No CORS issues (GitHub allows)
|
|
||||||
|
|
||||||
### Animations Janky
|
|
||||||
**Check:**
|
|
||||||
- Browser hardware acceleration enabled
|
|
||||||
- Too many other animations
|
|
||||||
- Framer Motion version compatible
|
|
||||||
- Browser performance metrics
|
|
||||||
|
|
||||||
### Summary Not Updating
|
|
||||||
**Check:**
|
|
||||||
- `enabled` prop is true
|
|
||||||
- Messages array has data
|
|
||||||
- 5-second interval is running
|
|
||||||
- No console errors
|
|
||||||
|
|
||||||
## Maintenance
|
|
||||||
|
|
||||||
### Regular Checks
|
|
||||||
- Monitor mascot chat appearance in production
|
|
||||||
- Verify summary accuracy with live data
|
|
||||||
- Check animation performance on browsers
|
|
||||||
- Track bundle size metrics
|
|
||||||
|
|
||||||
### Updates
|
|
||||||
- To change summary logic: Edit `useMascotSummary.ts`
|
|
||||||
- To change styling: Edit `MascotImage.tsx` classes
|
|
||||||
- To change animation: Edit Framer Motion config
|
|
||||||
- To change CDN URLs: Update image URLs (2 places)
|
|
||||||
|
|
||||||
### Rollback
|
|
||||||
If issues occur:
|
|
||||||
```bash
|
|
||||||
git revert 9f454b5 # Revert AI integration
|
|
||||||
git revert bb65178 # Revert component replacement
|
|
||||||
git revert 2ea0ea5 # Revert logo/mascot integration
|
|
||||||
```
|
|
||||||
|
|
||||||
No database changes, safe to rollback anytime.
|
|
||||||
|
|
||||||
## Files Reference
|
|
||||||
|
|
||||||
| File | Purpose | Lines |
|
|
||||||
|------|---------|-------|
|
|
||||||
| `MascotImage.tsx` | Main component | 98 |
|
|
||||||
| `useMascotSummary.ts` | AI hook | 98 |
|
|
||||||
| `DashboardLayout.tsx` | Integration | Updated |
|
|
||||||
| `Sidebar.tsx` | Display | Updated |
|
|
||||||
| `App.tsx` | Data flow | Updated |
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
### Manual Testing Checklist
|
|
||||||
- [ ] Mascot displays in sidebar
|
|
||||||
- [ ] Chat bubble appears with message
|
|
||||||
- [ ] Animation smooth and performant
|
|
||||||
- [ ] Auto-hide after 8 seconds
|
|
||||||
- [ ] Summary rotates every 5 seconds
|
|
||||||
- [ ] Empty states show mascot
|
|
||||||
- [ ] No mascot on auth page
|
|
||||||
- [ ] Responsive sizing works
|
|
||||||
- [ ] No console errors
|
|
||||||
- [ ] Images load from CDN
|
|
||||||
|
|
||||||
## Future Enhancements
|
|
||||||
|
|
||||||
- [ ] Click interaction handler
|
|
||||||
- [ ] ML-based summary generation
|
|
||||||
- [ ] Theme customization
|
|
||||||
- [ ] Sound effects
|
|
||||||
- [ ] Chat history
|
|
||||||
- [ ] Multi-language support
|
|
||||||
- [ ] Mobile optimization
|
|
||||||
- [ ] Settings panel
|
|
||||||
- [ ] User preferences
|
|
||||||
- [ ] Animation toggle
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Last Updated:** 2026-06-03
|
|
||||||
**Version:** 1.0.0
|
|
||||||
**Status:** Production Ready ✅
|
|
||||||
@@ -1,380 +0,0 @@
|
|||||||
# Discord Moderation Watcher Bot - Microservices Architecture
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
- Docker & Docker Compose
|
|
||||||
- Node.js 20+
|
|
||||||
- pnpm 11+
|
|
||||||
- Discord bot token
|
|
||||||
- OpenAI API key
|
|
||||||
|
|
||||||
### Environment Setup
|
|
||||||
|
|
||||||
Create `.env.local` in the root directory:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Discord Configuration
|
|
||||||
DISCORD_TOKEN=your_discord_token_here
|
|
||||||
MONITOR_GUILD_ID=your_guild_id_here
|
|
||||||
|
|
||||||
# AI Configuration
|
|
||||||
AI_LLM_API_KEY=your_openai_api_key_here
|
|
||||||
|
|
||||||
# Optional: Database URL (defaults to PostgreSQL in Docker)
|
|
||||||
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/bete
|
|
||||||
|
|
||||||
# Optional: Redis URL (defaults to Redis in Docker)
|
|
||||||
REDIS_URL=redis://localhost:6379
|
|
||||||
```
|
|
||||||
|
|
||||||
### Local Development with Docker Compose
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Start all services
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# View logs
|
|
||||||
docker-compose logs -f
|
|
||||||
|
|
||||||
# Stop all services
|
|
||||||
docker-compose down
|
|
||||||
|
|
||||||
# Rebuild services
|
|
||||||
docker-compose up -d --build
|
|
||||||
```
|
|
||||||
|
|
||||||
**Services will be available at:**
|
|
||||||
- Frontend: http://localhost:5173
|
|
||||||
- Backend API: http://localhost:3001
|
|
||||||
- Backend WebSocket: ws://localhost:3001
|
|
||||||
- PostgreSQL: localhost:5432
|
|
||||||
- Redis: localhost:6379
|
|
||||||
|
|
||||||
### Local Development without Docker
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install dependencies
|
|
||||||
pnpm install
|
|
||||||
|
|
||||||
# Run database migrations
|
|
||||||
pnpm run db:migrate
|
|
||||||
|
|
||||||
# Start all services in separate terminals
|
|
||||||
|
|
||||||
# Terminal 1: Backend
|
|
||||||
cd services/backend
|
|
||||||
pnpm run dev
|
|
||||||
|
|
||||||
# Terminal 2: Discord Gateway
|
|
||||||
cd services/discord-gateway
|
|
||||||
pnpm run dev
|
|
||||||
|
|
||||||
# Terminal 3: Frontend
|
|
||||||
cd services/frontend
|
|
||||||
pnpm run dev:web
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Architecture Overview
|
|
||||||
|
|
||||||
### 3 Independent Microservices
|
|
||||||
|
|
||||||
#### 1. Frontend Service (`services/frontend/`)
|
|
||||||
- **Tech:** React 19, Vite, TanStack Query, WebSocket
|
|
||||||
- **Port:** 5173 (dev) / served by Backend (prod)
|
|
||||||
- **Responsibilities:**
|
|
||||||
- Dashboard UI (analytics, messages, voice, media)
|
|
||||||
- Real-time WebSocket connection to Backend
|
|
||||||
- API calls to Backend REST endpoints
|
|
||||||
- State management (React Query)
|
|
||||||
|
|
||||||
#### 2. Backend Service (`services/backend/`)
|
|
||||||
- **Tech:** Express, Drizzle ORM, PostgreSQL, Redis
|
|
||||||
- **Port:** 3001
|
|
||||||
- **Responsibilities:**
|
|
||||||
- REST API endpoints (`/api/*`)
|
|
||||||
- WebSocket server for real-time updates
|
|
||||||
- Database operations (PostgreSQL)
|
|
||||||
- Event orchestration from Discord Gateway
|
|
||||||
- Static file serving (built Frontend)
|
|
||||||
- Admin authentication
|
|
||||||
|
|
||||||
**Modular MVC Structure:**
|
|
||||||
```
|
|
||||||
services/backend/src/
|
|
||||||
├── shared/
|
|
||||||
│ ├── database/ → Drizzle ORM setup
|
|
||||||
│ ├── config/ → Environment config
|
|
||||||
│ ├── errors/ → Custom error classes
|
|
||||||
│ ├── middlewares/ → Express middlewares
|
|
||||||
│ ├── logger/ → Logging utilities
|
|
||||||
│ └── utils/ → Shared utilities
|
|
||||||
├── modules/
|
|
||||||
│ ├── messages/ → Message CRUD
|
|
||||||
│ ├── analytics/ → Analytics queries
|
|
||||||
│ ├── media/ → Media management
|
|
||||||
│ ├── voice/ → Voice recordings
|
|
||||||
│ └── health/ → Health checks
|
|
||||||
└── index.ts
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. Discord Gateway Service (`services/discord-gateway/`)
|
|
||||||
- **Tech:** discord.js-selfbot-v13, @discordjs/voice, OpenAI API
|
|
||||||
- **Port:** None (internal service, no HTTP)
|
|
||||||
- **Responsibilities:**
|
|
||||||
- Discord client connection
|
|
||||||
- Message capture (create/edit/delete)
|
|
||||||
- Voice channel recording
|
|
||||||
- AI moderation analysis
|
|
||||||
- Attachment upload
|
|
||||||
- Event publishing to Backend (Redis pub/sub)
|
|
||||||
|
|
||||||
**Modular MVC Structure:**
|
|
||||||
```
|
|
||||||
services/discord-gateway/src/
|
|
||||||
├── shared/
|
|
||||||
│ ├── database/ → Drizzle ORM setup
|
|
||||||
│ ├── config/ → Environment config
|
|
||||||
│ ├── errors/ → Custom error classes
|
|
||||||
│ ├── logger/ → Logging utilities
|
|
||||||
│ └── utils/ → Shared utilities
|
|
||||||
├── modules/
|
|
||||||
│ ├── message-capture/ → Message listeners
|
|
||||||
│ ├── voice-recording/ → Voice recording
|
|
||||||
│ ├── ai-moderation/ → AI analysis
|
|
||||||
│ ├── attachment-upload/ → File uploads
|
|
||||||
│ └── event-broadcaster/ → Redis pub/sub
|
|
||||||
└── index.ts
|
|
||||||
```
|
|
||||||
|
|
||||||
### Shared Package (`packages/shared/`)
|
|
||||||
- **Types:** Common interfaces and data models
|
|
||||||
- **Errors:** Custom error classes
|
|
||||||
- **Logger:** Pino logger setup
|
|
||||||
- **Utils:** Pagination, validation, helpers
|
|
||||||
|
|
||||||
### Communication Patterns
|
|
||||||
|
|
||||||
**Frontend ↔ Backend:**
|
|
||||||
- REST API: `GET/POST /api/*` (HTTP)
|
|
||||||
- WebSocket: Real-time updates (JSON messages)
|
|
||||||
- Auth: Admin password header
|
|
||||||
|
|
||||||
**Backend ↔ Discord Gateway:**
|
|
||||||
- Redis pub/sub (low-latency, decoupled)
|
|
||||||
- Events: `discord:message:created`, `discord:voice:started`, etc.
|
|
||||||
- Backend subscribes and broadcasts to Frontend via WebSocket
|
|
||||||
|
|
||||||
**Shared Resources:**
|
|
||||||
- PostgreSQL: Both Backend and Discord Gateway
|
|
||||||
- Redis: Pub/sub and caching
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Development Workflow
|
|
||||||
|
|
||||||
### Adding a New API Endpoint
|
|
||||||
|
|
||||||
1. **Create module structure** (if new feature):
|
|
||||||
```bash
|
|
||||||
mkdir -p services/backend/src/modules/feature/{routes,controllers,services,repositories,schemas}
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Define schema** (`feature.schema.ts`):
|
|
||||||
```typescript
|
|
||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
export const createFeatureSchema = z.object({
|
|
||||||
name: z.string().min(1),
|
|
||||||
description: z.string().optional(),
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Create repository** (`feature.repository.ts`):
|
|
||||||
```typescript
|
|
||||||
export async function createFeature(data: CreateFeatureInput) {
|
|
||||||
return db.insert(features).values(data).returning();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Create service** (`feature.service.ts`):
|
|
||||||
```typescript
|
|
||||||
export async function createFeatureService(data: CreateFeatureInput) {
|
|
||||||
// Business logic, validation, orchestration
|
|
||||||
return createFeature(data);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **Create controller** (`feature.controller.ts`):
|
|
||||||
```typescript
|
|
||||||
export async function createFeatureController(req: Request, res: Response) {
|
|
||||||
const data = createFeatureSchema.parse(req.body);
|
|
||||||
const result = await createFeatureService(data);
|
|
||||||
res.json(result);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
6. **Create route** (`feature.route.ts`):
|
|
||||||
```typescript
|
|
||||||
router.post('/features', createFeatureController);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Adding a New Discord Event
|
|
||||||
|
|
||||||
1. **Create module** in `services/discord-gateway/src/modules/event-name/`
|
|
||||||
|
|
||||||
2. **Register listener** in `index.ts`:
|
|
||||||
```typescript
|
|
||||||
client.on('eventName', async (data) => {
|
|
||||||
await handleEvent(data);
|
|
||||||
publishEvent('discord:event:name', data);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Publish to Redis**:
|
|
||||||
```typescript
|
|
||||||
import { redis } from '../shared/redis';
|
|
||||||
|
|
||||||
redis.publish('discord:event:name', JSON.stringify(data));
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Subscribe in Backend** (`services/backend/src/ws/server.ts`):
|
|
||||||
```typescript
|
|
||||||
redis.subscribe('discord:event:name', (message) => {
|
|
||||||
broadcastToClients({ type: 'event_name', data: JSON.parse(message) });
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
### Run All Tests
|
|
||||||
```bash
|
|
||||||
pnpm run test
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run Tests for Specific Service
|
|
||||||
```bash
|
|
||||||
cd services/backend
|
|
||||||
pnpm run test
|
|
||||||
|
|
||||||
cd services/discord-gateway
|
|
||||||
pnpm run test
|
|
||||||
```
|
|
||||||
|
|
||||||
### Type Checking
|
|
||||||
```bash
|
|
||||||
pnpm run typecheck
|
|
||||||
```
|
|
||||||
|
|
||||||
### Linting
|
|
||||||
```bash
|
|
||||||
pnpm run lint
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Deployment
|
|
||||||
|
|
||||||
### Build Docker Images
|
|
||||||
```bash
|
|
||||||
docker-compose build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Push to Container Registry
|
|
||||||
```bash
|
|
||||||
docker tag bete-backend ghcr.io/username/bete-backend:latest
|
|
||||||
docker push ghcr.io/username/bete-backend:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
### Deploy to Production
|
|
||||||
See `.github/workflows/deploy.yml` for GitHub Actions CI/CD pipeline.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Backend can't connect to PostgreSQL
|
|
||||||
```bash
|
|
||||||
# Check PostgreSQL is running
|
|
||||||
docker-compose ps postgres
|
|
||||||
|
|
||||||
# Check connection string
|
|
||||||
echo $DATABASE_URL
|
|
||||||
|
|
||||||
# Verify credentials
|
|
||||||
psql -h localhost -U postgres -d bete
|
|
||||||
```
|
|
||||||
|
|
||||||
### Discord Gateway not receiving events
|
|
||||||
```bash
|
|
||||||
# Check Redis connection
|
|
||||||
redis-cli ping
|
|
||||||
|
|
||||||
# Check Discord token
|
|
||||||
echo $DISCORD_TOKEN
|
|
||||||
|
|
||||||
# View logs
|
|
||||||
docker-compose logs discord-gateway
|
|
||||||
```
|
|
||||||
|
|
||||||
### Frontend can't connect to Backend
|
|
||||||
```bash
|
|
||||||
# Check Backend is running
|
|
||||||
curl http://localhost:3001/health
|
|
||||||
|
|
||||||
# Check WebSocket connection
|
|
||||||
# Open browser DevTools → Network → WS
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API Documentation
|
|
||||||
|
|
||||||
### Health Check
|
|
||||||
```bash
|
|
||||||
GET /health
|
|
||||||
```
|
|
||||||
|
|
||||||
### Messages
|
|
||||||
```bash
|
|
||||||
GET /api/messages?channel=<id>&type=text|image
|
|
||||||
POST /api/messages (admin only)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Analytics
|
|
||||||
```bash
|
|
||||||
GET /api/analytics
|
|
||||||
```
|
|
||||||
|
|
||||||
### Voice Recordings
|
|
||||||
```bash
|
|
||||||
GET /api/recordings
|
|
||||||
```
|
|
||||||
|
|
||||||
### WebSocket Events
|
|
||||||
```
|
|
||||||
message_created
|
|
||||||
message_updated
|
|
||||||
message_deleted
|
|
||||||
attachment_uploaded
|
|
||||||
user_state
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
1. Create a feature branch
|
|
||||||
2. Make changes following Modular MVC pattern
|
|
||||||
3. Run tests and linting
|
|
||||||
4. Submit PR with description
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT
|
|
||||||
Reference in New Issue
Block a user