Remove all the slop .md files

This commit is contained in:
barelyprofessional
2026-02-17 20:26:48 -06:00
parent 30d9f48d2e
commit bc114e9f64
3 changed files with 0 additions and 854 deletions
-465
View File
@@ -1,465 +0,0 @@
# Nora AI Command Setup Guide
## Table of Contents
- [Quick Reference: Nora Variables](#quick-reference-nora-variables)
- [Overview](#overview)
- [Features](#features)
- [Prerequisites](#prerequisites)
- [Initial Setup](#initial-setup)
- [Configuration Options](#configuration-options)
- [How It Works](#how-it-works)
- [Content Moderation Details](#content-moderation-details)
- [Conversation Context](#conversation-context)
- [Testing the Command](#testing-the-command)
- [Troubleshooting](#troubleshooting)
- [Cost Monitoring](#cost-monitoring)
- [Security Considerations](#security-considerations)
- [Advanced Configuration](#advanced-configuration)
- [Code Architecture](#code-architecture)
- [FAQ](#faq)
## Quick Reference: Nora Variables
All configurable knobs for `!nora`, with direct links to where they're defined.
### Files
| Variable | File | Line(s) | Default | Description |
|----------|------|---------|---------|-------------|
| System prompt | [NoraPrompt.txt](KfChatDotNetBot/Commands/NoraPrompt.txt) | entire file | *(see file)* | Nora's personality, context, and instructions. Edit this file freely — changes are picked up on next invocation without restart. |
| Moods | [NoraMoods.cs:5-17](KfChatDotNetBot/Commands/NoraMoods.cs#L5-L17) | 5-17 | 10 moods | Random mood injected per conversation context |
| Rate limit | [NoraCommand.cs:89-94](KfChatDotNetBot/Commands/NoraCommand.cs#L89-L94) | 89-94 | 1/min per user | `Window`, `MaxInvocations`, `Flags` |
| Input word limit | [NoraCommand.cs:96](KfChatDotNetBot/Commands/NoraCommand.cs#L96) | 96 | 15 words | `MaxWords` constant |
| Input char limit | [NoraCommand.cs:97](KfChatDotNetBot/Commands/NoraCommand.cs#L97) | 97 | 140 chars | `MaxCharacters` constant |
| Execution timeout | [NoraCommand.cs:87](KfChatDotNetBot/Commands/NoraCommand.cs#L87) | 87 | 30 seconds | Max time for the entire command |
| Required permission | [NoraCommand.cs:85](KfChatDotNetBot/Commands/NoraCommand.cs#L85) | 85 | `UserRight.Loser` | Minimum user permission level |
| Max response tokens | [GrokApi.cs:105,122](KfChatDotNetBot/Services/GrokApi.cs#L105) | 105, 122 | 300 tokens | `maxTokens` parameter default |
| Temperature | [GrokApi.cs:167](KfChatDotNetBot/Services/GrokApi.cs#L167) | 167 | 0.7 | Creativity/consistency balance |
| Compaction summary tokens | [ConversationContextManager.cs:127](KfChatDotNetBot/Services/ConversationContextManager.cs#L127) | 127 | 150 tokens | Max tokens for context summary during compaction |
### Database Settings (via `BuiltIn.cs`)
These are changed at runtime via admin commands or direct DB updates — no rebuild needed.
| Setting Key | BuiltIn.cs Field | Line | Default | Description |
|-------------|-----------------|------|---------|-------------|
| `Grok.Nora.Model` | [GrokNoraModel](KfChatDotNetBot/Settings/BuiltIn.cs#L482-L483) | 482-483 | `grok-4-1-fast-reasoning` | Which Grok model to use |
| `Grok.Nora.ContextMode` | [GrokNoraContextMode](KfChatDotNetBot/Settings/BuiltIn.cs#L484-L485) | 484-485 | `perChatter` | `perChatter`, `perRoom`, or `disabled` |
| `Grok.Nora.ContextMaxTokens` | [GrokNoraContextMaxTokens](KfChatDotNetBot/Settings/BuiltIn.cs#L486-L487) | 486-487 | `2400` | Max estimated tokens before context compaction |
| `Grok.Nora.ContextExpiryMinutes` | [GrokNoraContextExpiryMinutes](KfChatDotNetBot/Settings/BuiltIn.cs#L488-L489) | 488-489 | `30` | Minutes of inactivity before context expires |
| `Grok.Nora.UserInfoEnabled` | [GrokNoraUserInfoEnabled](KfChatDotNetBot/Settings/BuiltIn.cs#L490-L491) | 490-491 | `true` | Inject user profile (balance, VIP, etc.) into prompt |
| `Grok.ApiKey` | [GrokApiKey](KfChatDotNetBot/Settings/BuiltIn.cs#L477-L478) | 477-478 | *(empty)* | xAI API key |
| `Grok.Chat.Endpoint` | [GrokChatEndpoint](KfChatDotNetBot/Settings/BuiltIn.cs#L479-L481) | 479-481 | `https://api.x.ai/v1/chat/completions` | API endpoint |
## Overview
The `!nora` command allows chat users to interact with Grok AI through the KfChatDotNet bot. All messages are automatically moderated through OpenAI's Moderation API to filter out illegal content while allowing profanity and general offensive language.
## Features
- **AI Responses**: Powered by Grok (xAI) with customizable personality
- **Content Moderation**: OpenAI Moderation API blocks illegal content (bomb-making, drug manufacturing, CSAM)
- **Rate Limiting**: 1 use per minute per user to prevent spam and control API costs
- **Input Limits**: 15 words max, 140 characters max
- **Permission Level**: Available to all users (UserRight.Loser)
- **Response Format**: `**Nora to @username:** [AI response]`
- **Hot-reloadable prompt**: Edit `NoraPrompt.txt` and changes take effect on the next invocation
## Prerequisites
### 1. OpenAI API Key
- **Purpose**: Content moderation (free tier available)
- **Get it**: https://platform.openai.com/api-keys
- **Cost**: Moderation API is free, but has rate limits
- **Documentation**: https://platform.openai.com/docs/api-reference/moderations
### 2. Grok API Key (xAI)
- **Purpose**: AI chat completions
- **Get it**: https://console.x.ai/
- **Cost**: ~$5 per 1M input tokens for grok-4-1-fast-reasoning model
- **Documentation**: https://docs.x.ai/api
- **Pricing**: https://docs.x.ai/developers/models
## Initial Setup
### Step 1: Run the Bot Once
On first startup after deploying the code, the bot will automatically create the new settings in the database with default values.
```bash
dotnet run --project KfChatDotNetBot
```
The following settings will be created in `db.sqlite`:
- `OpenAi.ApiKey` (null by default)
- `OpenAi.Moderation.Endpoint` (defaults to `https://api.openai.com/v1/moderations`)
- `Grok.ApiKey` (null by default)
- `Grok.Chat.Endpoint` (defaults to `https://api.x.ai/v1/chat/completions`)
- `Grok.Nora.Model` (defaults to `grok-4-1-fast-reasoning`)
- `Grok.Nora.ContextMode` (defaults to `perChatter` — options: `perChatter`, `perRoom`, `disabled`)
- `Grok.Nora.ContextMaxTokens` (defaults to `2400`)
- `Grok.Nora.ContextExpiryMinutes` (defaults to `30`)
### Step 2: Configure API Keys
You need to set the API keys in the database. You can do this either:
**Option A: Using Admin Commands** (if available in your bot):
```
!admin setting set OpenAi.ApiKey <your-openai-api-key>
!admin setting set Grok.ApiKey <your-grok-api-key>
```
**Option B: Direct Database Update**:
```bash
# Open the SQLite database
sqlite3 db.sqlite
# Set OpenAI API key
UPDATE Settings SET Value = 'sk-proj-...' WHERE Key = 'OpenAi.ApiKey';
# Set Grok API key
UPDATE Settings SET Value = 'xai-...' WHERE Key = 'Grok.ApiKey';
# Exit sqlite
.exit
```
**Option C: Using .NET EF Core**:
```csharp
await SettingsProvider.SetValueAsync(BuiltIn.Keys.OpenAiApiKey, "sk-proj-...");
await SettingsProvider.SetValueAsync(BuiltIn.Keys.GrokApiKey, "xai-...");
```
### Step 3: Edit Nora's Prompt
Edit [`KfChatDotNetBot/Commands/NoraPrompt.txt`](KfChatDotNetBot/Commands/NoraPrompt.txt) with Nora's personality and context. This file is read at runtime and hot-reloads when modified — no restart needed.
### Step 4: Restart the Bot
```bash
dotnet run --project KfChatDotNetBot
```
The `!nora` command is now ready to use!
## Configuration Options
### Customize Nora's Personality
Edit [`KfChatDotNetBot/Commands/NoraPrompt.txt`](KfChatDotNetBot/Commands/NoraPrompt.txt) directly. The file is re-read whenever it changes on disk — no restart or rebuild required. You can write as much context as you want.
### Change the AI Model
If you want to use a different Grok model:
```sql
UPDATE Settings
SET Value = 'grok-2-latest'
WHERE Key = 'Grok.Nora.Model';
```
Available models: `grok-4-1-fast-reasoning`, `grok-2-latest` (check xAI docs for current models)
### Use a Proxy
If you need to route requests through a proxy (applies to both APIs):
```sql
UPDATE Settings
SET Value = 'http://your-proxy:8080'
WHERE Key = 'Proxy';
```
## How It Works
```
User Input: !nora what is 2+2
|
[1] Input Validation
- Check word count (<=15 words)
- Check character count (<=140 chars)
|
[2] Content Moderation (OpenAI)
- Send to OpenAI Moderation API
- Check for illegal content:
X Block: illicit activities, self-harm instructions, CSAM
OK Allow: profanity, harassment, hate speech
|
[3] Load Prompt
- Read NoraPrompt.txt (cached, hot-reloads on file change)
- Append user info if enabled
- Append random mood
|
[4] AI Response (Grok)
- Send system prompt + conversation context to Grok
- Max 300 tokens response
|
[5] Format & Send
- Format: "Nora to @username: [response]"
- Truncate if needed (1023 byte limit)
- Post to chat
```
## Content Moderation Details
### What Gets Blocked (Illegal Content)
The command blocks content flagged with these OpenAI moderation categories:
- **illicit**: Instructions for illegal activities (bomb-making, drug manufacturing, hacking, etc.)
- **illicit/violent**: Violent illegal activities
- **self-harm/instructions**: Detailed self-harm methods
- **sexual/minors**: Any content involving minors
### What Gets Allowed (Offensive But Not Illegal)
These are flagged but NOT blocked:
- **harassment**: General insults, harassment
- **hate**: Hate speech
- **sexual**: Adult sexual content
- **violence**: General violence descriptions
- **violence/graphic**: Graphic violence
This design philosophy allows the command to be used in edgy chat environments while still blocking truly dangerous content.
## Conversation Context
The `!nora` command supports persistent conversation context so Nora remembers previous messages within a session.
### Context Modes
Set the context mode via the `Grok.Nora.ContextMode` setting:
| Mode | Behavior |
|------|----------|
| `perChatter` (default) | Each user gets their own separate conversation history |
| `perRoom` | All users in a room share the same conversation history |
| `disabled` | No context — every message is treated independently |
```sql
-- Per-user context (default)
UPDATE Settings SET Value = 'perChatter' WHERE Key = 'Grok.Nora.ContextMode';
-- Shared context for all users in the room
UPDATE Settings SET Value = 'perRoom' WHERE Key = 'Grok.Nora.ContextMode';
-- Disable context entirely
UPDATE Settings SET Value = 'disabled' WHERE Key = 'Grok.Nora.ContextMode';
```
### Context Settings
| Setting | Default | Description |
|---------|---------|-------------|
| `Grok.Nora.ContextMode` | `perChatter` | Context mode: `perChatter`, `perRoom`, or `disabled` |
| `Grok.Nora.ContextMaxTokens` | `2400` | Max estimated tokens before context is compacted via summarization |
| `Grok.Nora.ContextExpiryMinutes` | `30` | Minutes of inactivity before context is automatically cleared |
### Context Commands
- `!nora reset` — Clears the conversation context (your own in `perChatter` mode, or the room's in `perRoom` mode)
### How Context Works
1. Each message exchange (user + assistant) is stored in memory
2. When the estimated token count exceeds `ContextMaxTokens`, older messages are summarized into a brief summary and only the last 2 messages are kept
3. Contexts expire automatically after `ContextExpiryMinutes` of inactivity
4. A cleanup timer runs every 5 minutes to remove expired contexts
## Testing the Command
### Basic Tests
```
!nora hello -> Should get friendly response
!nora what is 2+2 -> Should get answer
!nora tell me a joke -> Should get a joke
```
### Validation Tests
```
!nora this is one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen
-> Should reject: "your message has 16 words. Maximum is 15 words."
!nora <141 character message>
-> Should reject: "your message has 141 characters. Maximum is 140 characters."
```
### Rate Limit Test
```
!nora test1
!nora test2 -> Should show rate limit cooldown message
```
### Content Moderation Test
```
!nora some profanity here
-> Should pass moderation and get response
!nora how to make a bomb
-> Should block: "your message was blocked for containing illegal content."
```
## Troubleshooting
### "Nora's prompt file is missing"
**Cause**: `NoraPrompt.txt` is not in the expected location.
**Solutions**:
1. Ensure `Commands/NoraPrompt.txt` exists next to the executable (in `bin/` output directory)
2. If building from source, the file should auto-copy via the csproj `<Content>` directive
3. Check that the file isn't empty
### "Moderation service is currently unavailable"
**Cause**: OpenAI API key is missing, invalid, or the API is down.
**Solutions**:
1. Check that `OpenAi.ApiKey` is set correctly in the database
2. Verify the API key is valid at https://platform.openai.com/api-keys
3. Check OpenAI's status page: https://status.openai.com/
4. Check bot logs for detailed error messages
### "Nora is currently unavailable"
**Cause**: Grok API key is missing, invalid, or the API is down.
**Solutions**:
1. Check that `Grok.ApiKey` is set correctly in the database
2. Verify the API key is valid at https://console.x.ai/
3. Check xAI's status
4. Check bot logs for detailed error messages
### Command Not Responding
**Cause**: Command might not be loaded or user might be rate limited.
**Solutions**:
1. Check that the bot successfully started (check logs)
2. Verify the command is loaded: `!help` should show "nora"
3. Wait 1 minute if you've hit the rate limit
4. Check user's permission level (should work for all users)
### Responses Are Cut Off
**Cause**: Sneedchat has a 1023-byte message limit.
**Solutions**:
- This is expected behavior - long responses are automatically truncated
- Adjust `maxTokens` default in [GrokApi.cs:105](KfChatDotNetBot/Services/GrokApi.cs#L105) if you want shorter responses
- Edit `NoraPrompt.txt` to request briefer answers
## Cost Monitoring
### OpenAI Moderation API
- **Cost**: Free
- **Rate Limits**: Check your quota at https://platform.openai.com/account/limits
- **Usage**: View at https://platform.openai.com/usage
### Grok API (xAI)
- **Cost**: ~$5 per 1M input tokens (varies by model)
- **Rate Limits**: Set at 1 use/user/minute in the bot
- **Usage**: Monitor at https://console.x.ai/
- **Budget**: Consider setting usage alerts in xAI console
### Example Cost Calculation
```
Average message: 10 words (~15 tokens input)
Average response: 50 tokens output
Cost per interaction: ~$0.0003 (assuming $5/1M tokens)
At 1 request/user/minute:
- 100 users: ~100 requests/hour max = ~$0.03/hour
- 1000 users: ~1000 requests/hour max = ~$0.30/hour
Rate limiting prevents runaway costs!
```
## Security Considerations
### API Key Storage
- API keys are stored in `db.sqlite` with the `IsSecret` flag
- They are not displayed in logs when the `IsSecret` flag is set
- Keep `db.sqlite` secure and don't commit it to version control
### Content Logging
The bot logs:
- All moderation results (flagged categories)
- Blocked illegal content attempts with usernames
- Allowed-but-flagged content (profanity) for monitoring
Check logs at: `logs/` directory (configured in `NLog.config`)
### Rate Limiting
- 1 use per minute per user prevents spam
- No global rate limit by default (all users can use simultaneously)
- Consider adding `RateLimitFlags.Global` if abuse is a concern
## Advanced Configuration
### Add Global Rate Limit
Edit [NoraCommand.cs:89-94](KfChatDotNetBot/Commands/NoraCommand.cs#L89-L94):
```csharp
public RateLimitOptionsModel? RateLimitOptions => new RateLimitOptionsModel
{
Window = TimeSpan.FromMinutes(1),
MaxInvocations = 1,
Flags = RateLimitFlags.Global // Add this flag
};
```
This limits ALL users combined to 1 request per minute.
### Increase Response Length
Edit [GrokApi.cs:105](KfChatDotNetBot/Services/GrokApi.cs#L105):
```csharp
max_tokens = 500 // Increase from 300 to 500
```
Note: Longer responses may get truncated by Sneedchat's 1023-byte limit.
### Change Input Limits
Edit [NoraCommand.cs:96-97](KfChatDotNetBot/Commands/NoraCommand.cs#L96-L97):
```csharp
private const int MaxWords = 20; // Increase from 15 to 20
private const int MaxCharacters = 200; // Increase from 140 to 200
```
### Require Higher Permissions
Edit [NoraCommand.cs:85](KfChatDotNetBot/Commands/NoraCommand.cs#L85):
```csharp
public UserRight RequiredRight => UserRight.TrueAndHonest; // Mods only
```
## Code Architecture
### Files
- **[KfChatDotNetBot/Commands/NoraPrompt.txt](KfChatDotNetBot/Commands/NoraPrompt.txt)** - System prompt (hot-reloadable)
- **[KfChatDotNetBot/Commands/NoraCommand.cs](KfChatDotNetBot/Commands/NoraCommand.cs)** - Main command logic
- **[KfChatDotNetBot/Commands/NoraMoods.cs](KfChatDotNetBot/Commands/NoraMoods.cs)** - Random mood modifiers
- **[KfChatDotNetBot/Services/OpenAiModeration.cs](KfChatDotNetBot/Services/OpenAiModeration.cs)** - OpenAI moderation API integration
- **[KfChatDotNetBot/Services/GrokApi.cs](KfChatDotNetBot/Services/GrokApi.cs)** - Grok API integration
- **[KfChatDotNetBot/Services/ConversationContextManager.cs](KfChatDotNetBot/Services/ConversationContextManager.cs)** - Conversation context and compaction
- **[KfChatDotNetBot/Settings/BuiltIn.cs](KfChatDotNetBot/Settings/BuiltIn.cs)** - DB setting keys
### Auto-Discovery
The command is automatically discovered via reflection in [BotCommands.cs](KfChatDotNetBot/Services/BotCommands.cs) on bot startup. No manual registration needed!
## FAQ
**Q: Can I use a different AI provider instead of Grok?**
A: Yes! The code is modular. Create a new service similar to `GrokApi.cs` and update `NoraCommand.cs` to use it.
**Q: Why is moderation required?**
A: To prevent the bot from being used to generate illegal or dangerous content that could create liability.
**Q: Can I disable moderation?**
A: Not recommended, but technically you could modify `NoraCommand.cs` to skip the moderation step. This is strongly discouraged.
**Q: What if OpenAI moderation is down?**
A: The command fails-safe and blocks all messages when moderation is unavailable, preventing unmoderated content from reaching the AI.
**Q: Can I increase the rate limit?**
A: Yes, edit the `RateLimitOptions` in `NoraCommand.cs`. Be aware this increases API costs.
**Q: Does this work with the GambaSesh detection system?**
A: Yes! The command respects the bot's existing systems. Responses are sent with `bypassSeshDetect: true` to ensure they're always posted.
**Q: How do I edit Nora's prompt?**
A: Edit `KfChatDotNetBot/Commands/NoraPrompt.txt` (or `Commands/NoraPrompt.txt` in the build output directory). Changes are picked up automatically — no restart needed.
-96
View File
@@ -1,96 +0,0 @@
# 🔒 Security & Privacy Guide
**Important:** If you're contributing to this project and want to maintain anonymity, follow these steps to prevent leaking personal information.
## Table of Contents
- [Anonymize Your Git Identity](#anonymize-your-git-identity)
- [Prevent Path Leaks](#prevent-path-leaks)
## Anonymize Your Git Identity
Configure Git to use a pseudonymous identity for this repository:
```bash
# Navigate to the repository
cd KfChatDotNet
# Set local Git identity (only affects this repo)
git config user.name "YourPseudonym"
git config user.email "pseudonym@example.com"
# Or use GitHub's noreply email
git config user.email "username@users.noreply.github.com"
# Verify your settings
git config user.name
git config user.email
```
> **Note:** Use `git config` (without `--global`) to set identity per-repository only. This won't affect your other projects.
### Check Your Current Identity
Before making commits, verify what identity will be used:
```bash
# Check current configuration
git config --list --show-origin | grep user
# See what will be used for the next commit
git config user.name
git config user.email
```
## Prevent Path Leaks
Your system username and file paths can leak into commits through:
### 1. Exception Stack Traces
Be careful when committing error logs or debugging output that might contain paths like:
-`/home/john.smith/repos/KfChatDotNet/`
-`C:\Users\JohnSmith\Documents\KfChatDotNet\`
-`/Users/john.smith/Projects/KfChatDotNet/`
**What to do:**
- Strip paths from error logs before committing
- Use relative paths in documentation
- Sanitize stack traces to remove usernames
### 2. Absolute Paths in Code
Avoid hardcoding absolute paths. Use relative paths or configuration:
```csharp
// ❌ Bad - leaks username
var logPath = "/home/john.smith/.bot/logs/";
var dataPath = "C:\\Users\\JohnSmith\\AppData\\bot\\";
// ✅ Good - use relative or configurable paths
var logPath = Path.Combine(Environment.CurrentDirectory, "logs");
var dataPath = Path.Combine(AppContext.BaseDirectory, "data");
var configPath = await SettingsProvider.GetValueAsync("Bot.LogPath");
```
### 3. IDE Configuration Files
The `.gitignore` already excludes common IDE files, but verify:
```bash
# Check what's being tracked
git ls-files | grep -E '\.(user|suo|vscode|idea)'
# If you find personal IDE files, remove them
git rm --cached path/to/personal/file
git commit -m "Remove personal IDE files"
```
### 4. Database Files
The database (`db.sqlite`) can contain:
- Your KiwiFarms password (in Settings table)
- Your KiwiFarms cookies
- Potentially identifiable usage patterns
**Never commit `db.sqlite`** - it's already in `.gitignore`.
-293
View File
@@ -1,293 +0,0 @@
# KfChatDotNet
> ## ⚠️ **IMPORTANT: Read This First** ⚠️
>
> **If you're contributing to this project, please read [PRIVACY.md](PRIVACY.md) to learn how to protect your identity.**
---
A C# .NET chat bot for KiwiFarms (Sneedchat) with extensive third-party integrations for stream monitoring, gambling site tracking, and interactive commands.
## Features
- 🤖 **Interactive Chat Bot** - Command-based interactions with regex pattern matching
- 🎰 **Kasino System** - Internal gambling games (mines, limbo, coinflip, blackjack, roulette, and more)
- 📺 **Stream Monitoring** - Track streams across Twitch, Kick, DLive, PeerTube, Owncast, YouTube
- 💬 **Multi-Platform Integration** - Discord relay, Twitch chat, Kick events
- 🎲 **Gambling Tracking** - Monitor bets across Rainbet, Shuffle, Howlgg, Chips.gg, Clash.gg, and more
- 🔄 **Auto-Reconnect** - Robust WebSocket connection with automatic cookie refresh
- 🗃️ **Database-Backed Settings** - SQLite database with EF Core migrations
## Prerequisites
- [.NET 10.0 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) or higher
- A KiwiFarms account
- (Optional) SQLite viewer for database inspection
## Quick Start
### 1. Clone and Build
```bash
git clone <repository-url>
cd KfChatDotNet
dotnet build
```
### 2. Configure Credentials
The bot uses a **database-backed settings system**. On first run, it will create `db.sqlite` with default settings.
#### Option A: Using config.json (Easiest for First Run)
Create `KfChatDotNetBot/config.json`:
```json
{
"KfUsername": "your_kiwifarms_username",
"KfPassword": "your_kiwifarms_password",
"KfChatRoomId": 15,
"KfDomain": "kiwifarms.st",
"KfWsEndpoint": "wss://kiwifarms.st:9443/chat.ws",
"SuppressChatMessages": true
}
```
> **Note:** The bot will automatically migrate `config.json` to the database on first run and rename it to `config.json.migrated`.
#### Option B: Directly Edit Database (After First Run)
Build the project, then run the bot once. This generates tables which can be updated by running `sqlite`:
```bash
# Build
dotnet build
# Run
dotnet run --project KfChatDotNetBot
# Ctr + C to stop the application, then run
sqlite3 db.sqlite
```
```sql
-- Update your credentials
UPDATE Settings SET Value = 'your_username' WHERE Key = 'KiwiFarms.Username';
UPDATE Settings SET Value = 'your_password' WHERE Key = 'KiwiFarms.Password';
-- Enable read-only mode for testing
UPDATE Settings SET Value = 'true' WHERE Key = 'KiwiFarms.SuppressChatMessages';
```
### 3. Run the Bot
```bash
cd KfChatDotNetBot
dotnet run
```
The bot will:
1. ✅ Create/migrate the database
2. ✅ Sync built-in settings
3. ✅ Connect to KiwiFarms chat
4. ✅ Start listening for commands
## Configuration Guide
### Essential Settings
| Setting | Description | Default | Required |
|---------|-------------|---------|----------|
| `KiwiFarms.Username` | Your KF username | - | ✅ Yes |
| `KiwiFarms.Password` | Your KF password | - | ✅ Yes |
| `KiwiFarms.RoomId` | Chat room ID to join | `15` | ✅ Yes |
| `KiwiFarms.SuppressChatMessages` | Read-only mode (no messages sent) | `false` | Recommended for testing |
### Optional Integrations
All external services are **disabled by default** or optional:
| Service | Enable Setting | Auth Required |
|---------|---------------|---------------|
| Discord | `Discord.Token` | Bot token |
| Kick | `Kick.Enabled` | None (public API) |
| Twitch | Auto-enabled | None (public GraphQL) |
| Jackpot | `Jackpot.Enabled` | None |
| Rainbet | `Rainbet.Enabled` | None |
| Shuffle | Auto-enabled | None |
| YouTube | `YouTube.ApiKey` | API key |
| FlareSolverr | `FlareSolverr.ApiUrl` | Service URL |
### Viewing All Settings
```bash
# View non-secret settings
sqlite3 db.sqlite "SELECT Key, Value, Description FROM Settings WHERE IsSecret = 0 LIMIT 20;"
# View secret settings (passwords, tokens)
sqlite3 db.sqlite "SELECT Key, Value FROM Settings WHERE IsSecret = 1;"
```
### Testing Mode
For safe testing without sending messages to chat:
```sql
UPDATE Settings SET Value = 'true' WHERE Key = 'KiwiFarms.SuppressChatMessages';
```
When enabled, the bot will connect, listen, and process commands but **won't actually send messages**.
## Development
### Project Structure
```
KfChatDotNet/
├── KfChatDotNetWsClient/ # WebSocket client library for KF chat
├── KickWsClient/ # WebSocket client library for Kick
└── KfChatDotNetBot/ # Main bot application
├── Commands/ # Bot commands (implement ICommand)
├── Services/ # External service integrations
├── Models/ # Data models and DTOs
├── Migrations/ # EF Core database migrations
└── Settings/ # Settings system
```
### Common Commands
```bash
# Build the solution
dotnet build
# Run in release mode
dotnet run --project KfChatDotNetBot -c Release
# Clean build artifacts
dotnet clean
# Add a database migration
dotnet ef migrations add MigrationName --project KfChatDotNetBot
# Update database to latest migration
dotnet ef database update --project KfChatDotNetBot
# View migration SQL
dotnet ef migrations script --project KfChatDotNetBot
```
### Adding a New Command
1. Create a class in `KfChatDotNetBot/Commands/` implementing `ICommand`
2. Define regex patterns and command logic
3. The bot auto-discovers commands via reflection on startup
Example:
```csharp
public class HelloCommand : ICommand
{
public List<Regex> Patterns => [new Regex(@"^hello$", RegexOptions.IgnoreCase)];
public string? HelpText => "Says hello!";
public UserRight RequiredRight => UserRight.User;
public TimeSpan Timeout => TimeSpan.FromSeconds(10);
public RateLimitOptionsModel? RateLimitOptions => null;
public async Task RunCommand(ChatBot botInstance, MessageModel message,
UserDbModel user, GroupCollection arguments, CancellationToken ctx)
{
botInstance.SendChatMessage($"Hello, @{message.Author.Username}!");
}
}
```
### Database Migrations
Migrations run **automatically** on startup. The database schema is managed via Entity Framework Core.
```bash
# Create a new migration
dotnet ef migrations add AddNewFeature --project KfChatDotNetBot
# Migrations are applied automatically when the bot starts
dotnet run --project KfChatDotNetBot
```
## Architecture Overview
### Message Flow
```
KiwiFarms Chat (WebSocket)
ChatClient (WsClient library)
ChatBot (Event handlers)
BotCommands (Pattern matching)
ICommand implementations (Your commands)
```
### Key Components
- **ChatClient** - WebSocket connection to KF, handles reconnection and cookie management
- **ChatBot** - Main bot orchestration, message tracking, GambaSesh detection
- **BotCommands** - Command routing with regex patterns, rate limiting, permissions
- **BotServices** - Manages all external service connections (Discord, Twitch, gambling sites)
- **Money** - Internal Kasino gambling system with balance tracking
### Settings System
Settings are **stored in the database**, not config files:
- All settings have defaults defined in `BuiltIn.cs`
- Settings are cached to reduce database queries
- Secrets are marked and hidden from logs
- Settings sync automatically on startup
For more architectural details, see [CLAUDE.md](CLAUDE.md).
## Logging
Logging is configured via `NLog.config`. The bot logs extensively:
- **Debug**: Packet details, message processing, connection events
- **Info**: User joins/parts, sent messages, state changes
- **Error**: Exceptions, disconnections, failed operations
## Optional Services Setup
### FlareSolverr (for Cloudflare bypass)
```bash
# Using Docker
docker run -d \
--name=flaresolverr \
-p 8191:8191 \
ghcr.io/flaresolverr/flaresolverr:latest
# Update setting
UPDATE Settings SET Value = 'http://localhost:8191/' WHERE Key = 'FlareSolverr.ApiUrl';
```
### Discord Bot
1. Create a bot at [Discord Developer Portal](https://discord.com/developers/applications)
2. Get your bot token
3. Update setting: `UPDATE Settings SET Value = 'your_bot_token' WHERE Key = 'Discord.Token';`
### Redis (for YouTube PubSub)
```bash
# Using Docker
docker run -d --name redis -p 6379:6379 redis:latest
# Update setting
UPDATE Settings SET Value = 'localhost:6379' WHERE Key = 'YouTube.PubSub.RedisConnectionString';
```
## License
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
See [LICENSE](LICENSE) for details.