zynk/cmd_greeting_or_chat.h
hanez 3b97b4d902 0.41.2 Implement comprehensive flood protection for IRC bot.
Phase 1: Incoming Protocol-Level Protection
- Added MAX_LINES_PER_POLL = 50 constant to limit lines processed per
  poll iteration in irc_feed(), preventing burst flooding.
- Added poll_lines_left counter to Session struct, reset each poll cycle.
- Changed RateLimitEntry to track by user@host instead of nick, preventing
  trivial bypass via nick cycling.
- Parse userhost from IRC prefix (nick!user@host) in irc_handle().
- Added violation tracking to RateLimitEntry for escalating penalties.

Phase 2: Outgoing Message Throttling
- Added OUTGOING_DELAY_MS = 100 constant for minimum delay between sends.
- Modified net_send() with timestamp-based throttling using clock_gettime().
- Added 200ms delay between lines in !gitlog output (cmd_gitlog.h).
- Added 150ms delay between AI response chunks (ai.h).

Phase 3: Rate Limit Improvements
- Increased RATE_LIMIT_MAX from 8 to 32 for larger tracking buffer.
- Added TELL_DELIVER_MAX = 5 to limit messages per nick delivery.
- Added AI_COOLDOWN_SECS = 5 to prevent rapid AI query re-submission.

Phase 4: Command-Specific Fixes
- Added rate_limit_check() to cmd_greeting_or_chat.h for casual chat.
- Limited tell_deliver() to 5 messages per nick, excess stays queued.
- Added 5-second cooldown after AI query completion before next query.

Files modified: zynk.h, zynk.c, irc.h, net.h, ai.h, db.h, and all
19 command header files to pass current_userhost to rate_limit_check().
2026-07-25 20:37:07 +02:00

62 lines
2.4 KiB
C

#ifndef CMD_GREETING_OR_CHAT_H
#define CMD_GREETING_OR_CHAT_H
#include "zynk.h"
/*
* cmd_greeting_or_chat - Handle casual chat messages and direct address.
*
* Checks if the message starts with the bot's nick followed by ':', and
* if so strips that prefix to get the actual message. Matches known
* greeting/casual phrases (hi, hey, hello, bye, jojo, whatsup, waddup,
* German phrases) with hardcoded responses. If the message doesn't match
* any known phrase but was addressed to the bot by nick, forwards it to
* ai_ask() in plan mode for an AI-powered conversation response.
*
* Parameters:
* s - The IRC session.
* msg - The raw message text.
* reply_target - Channel or nick to reply to.
* src_nick - The nick of the sender.
*
* Returns: void.
*/
void cmd_greeting_or_chat(Session *s, const char *msg, const char *reply_target, const char *src_nick) {
int nicklen = strlen(s->nick);
const char *cmd = msg;
if (strncasecmp(msg, s->nick, nicklen) == 0 && msg[nicklen] == ':') {
cmd = msg + nicklen + 1;
while (*cmd == ' ') cmd++;
if (!*cmd) cmd = msg;
}
char resp[1024];
int matched = 0;
if (strcasecmp(cmd, "hi") == 0 || strcasecmp(cmd, "hey") == 0 || strcasecmp(cmd, "hello") == 0) {
snprintf(resp, sizeof resp, "Hi!"); matched = 1;
} else if (strcasecmp(cmd, "bye") == 0 || strcasecmp(cmd, "goodbye") == 0) {
snprintf(resp, sizeof resp, "Bye!"); matched = 1;
} else if (strcasecmp(cmd, "jojo") == 0) {
snprintf(resp, sizeof resp, "Jo!"); matched = 1;
} else if (strcasecmp(cmd, "whatsup") == 0) {
snprintf(resp, sizeof resp, "Not much!"); matched = 1;
} else if (strcasecmp(cmd, "waddup") == 0) {
snprintf(resp, sizeof resp, "Yo!"); matched = 1;
} else if (strcasecmp(cmd, "waddup yo") == 0) {
snprintf(resp, sizeof resp, "Yo!"); matched = 1;
} else if (strcasecmp(cmd, "deine muddi") == 0 || strcasecmp(cmd, "deine mutter") == 0) {
snprintf(resp, sizeof resp, "Ey, lass das!"); matched = 1;
} else if (strcasecmp(cmd, "penis") == 0) {
snprintf(resp, sizeof resp, "..."); matched = 1;
}
if (matched) {
if (rate_limit_check(src_nick, reply_target, current_userhost) < 0) return;
irc_reply(s, reply_target, src_nick, resp);
log_stamp(); fprintf(stderr, CLR_CYAN "CHAT %s from %s:" CLR_RESET " %s\n", reply_target, src_nick, resp);
return;
}
if (cmd != msg) {
ai_ask(s, cmd, reply_target, src_nick, NULL);
}
}
#endif