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().
58 lines
1.9 KiB
C
58 lines
1.9 KiB
C
#ifndef CMD_SEEN_H
|
|
#define CMD_SEEN_H
|
|
|
|
#include "zynk.h"
|
|
|
|
/*
|
|
* cmd_seen - Handle the "!seen <nick>" command.
|
|
*
|
|
* Looks up the given nick in the seen database and reports when they
|
|
* were last seen, in which channel, and what action they were performing.
|
|
* Special-cases: checking yourself returns "You are right here, duh!",
|
|
* checking the bot returns "I am right here!", and unknown nicks return
|
|
* "I have never seen <nick>". Rate-limited.
|
|
*
|
|
* Parameters:
|
|
* s - The IRC session.
|
|
* msg - The raw IRC message text.
|
|
* reply_target - Channel or nick to send the response to.
|
|
* src_nick - The nick of the user who issued the command.
|
|
*
|
|
* Returns: 1 if the command was matched, 0 otherwise.
|
|
*/
|
|
int cmd_seen(Session *s, const char *msg, const char *reply_target, const char *src_nick) {
|
|
if (strncmp(msg, "!seen", 5) != 0) return 0;
|
|
if (msg[5] != ' ') return 0;
|
|
if (rate_limit_check(src_nick, reply_target, current_userhost) < 0) return 1;
|
|
const char *rest = msg + 6;
|
|
while (*rest == ' ') rest++;
|
|
if (!*rest) {
|
|
irc_reply(s, reply_target, src_nick, "Usage: !seen <nick>");
|
|
return 1;
|
|
}
|
|
char target[32];
|
|
int i = 0;
|
|
while (*rest && *rest != ' ' && i < 31) target[i++] = *rest++;
|
|
target[i] = 0;
|
|
if (strcasecmp(target, src_nick) == 0) {
|
|
irc_reply(s, reply_target, src_nick, "You are right here, duh!");
|
|
return 1;
|
|
}
|
|
if (strcasecmp(target, s->nick) == 0) {
|
|
irc_reply(s, reply_target, src_nick, "I am right here!");
|
|
return 1;
|
|
}
|
|
char *result = seen_lookup(target);
|
|
if (result) {
|
|
irc_reply(s, reply_target, src_nick, result);
|
|
free(result);
|
|
} else {
|
|
char resp[128];
|
|
snprintf(resp, sizeof resp, "I have never seen %s", target);
|
|
irc_reply(s, reply_target, src_nick, resp);
|
|
}
|
|
log_stamp(); fprintf(stderr, CLR_CYAN "SEEN %s from %s in %s" CLR_RESET "\n", target, src_nick, reply_target);
|
|
return 1;
|
|
}
|
|
|
|
#endif
|