This commit is contained in:
Zodiac 2025-02-18 23:48:49 -08:00
parent a64e9554c6
commit 3cd621d350

View File

@ -1,17 +1,41 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
IRC Bot Plugin for Tracking User Activity with TinyDB.
This plugin tracks user join times, messages, and nickname changes. Provides
a !seen command to check last activity. Stores data in "seen.json".
"""
IRC Bot Plugin for Tracking User Activity with TinyDB
This module implements an IRC bot plugin to track various activities of users in an IRC channel,
including their join times, messages sent, and nickname changes. The plugin uses TinyDB for
persistent storage of user data.
Features:
- Tracks when users join a channel.
- Logs user messages with timestamps.
- Monitors nickname changes.
- Provides a '!seen' command to retrieve the last activity of a specified user.
Dependencies:
- irc3
- tinydb
- ircstyle
- logging
- re
- irc3: For IRC protocol handling.
- tinydb: For managing user data in a JSON file.
- ircstyle: For formatting IRC messages with color and style.
- logging: For error logging.
- humanize: For converting time differences into human-readable format.
Usage:
- Install required packages: pip install irc3 tinydb ircstyle humanize
- Use within an IRC bot framework that utilizes irc3 plugins.
Storage:
- User data is stored in 'seen.json' in the same directory as this script.
Author:
- Zodiac
Date:
- 02/18/2025
Note:
- Ensure your bot environment has write permissions for the JSON database file.
"""
from datetime import datetime
@ -20,6 +44,7 @@ import irc3
from irc3.plugins.command import command
import ircstyle
import logging
import humanize
def truncate(text, length=50):
"""Truncate text to specified length, appending "..." if truncated."""
@ -114,7 +139,7 @@ class UserActivityTracker:
user = self.users.get(self.User.nick == requested_nick)
if not user:
msg = ircstyle.style(f"🚫 {requested_nick} has never been observed.", fg="red")
msg = ircstyle.style(f" {requested_nick} has never been observed.", fg="red")
self.bot.privmsg(target, msg)
return
@ -132,37 +157,33 @@ class UserActivityTracker:
# Last join - only if time exists
if 'last_join' in user and user['last_join']:
try:
join_time = datetime.fromisoformat(user['last_join']).strftime('%Y-%m-%d %H:%M:%S')
response.append(ircstyle.style("🕒 Last join: ", fg="cyan") + ircstyle.style(join_time, fg="white"))
except ValueError:
response.append(ircstyle.style("🕒 Last join: ", fg="cyan") + ircstyle.style("Invalid Time Format", fg="white"))
response.append(ircstyle.style("🕒 Last join: ", fg="cyan") +
ircstyle.style(humanize.naturaltime(datetime.now() - datetime.fromisoformat(user['last_join'])), fg="white"))
# Last message
if 'last_message' in user and user['last_message']:
try:
msg_time = datetime.fromisoformat(user['last_message']['time']).strftime('%Y-%m-%d %H:%M:%S')
msg_text = truncate(user['last_message']['text'])
response.append(
ircstyle.style("💬 Last message: ", fg="green") +
ircstyle.style(f"[{msg_time}] ", fg="grey") +
ircstyle.style(humanize.naturaltime(datetime.now() - datetime.fromisoformat(user['last_message']['time'])), fg="grey") + " " +
ircstyle.style(msg_text, fg="white", italics=True)
)
except (ValueError, KeyError):
except KeyError:
response.append(ircstyle.style("💬 Last message: ", fg="green") + ircstyle.style("Invalid or Missing Data", fg="white"))
# Last nick change
if 'last_nick_change' in user and user['last_nick_change']:
try:
change_time = datetime.fromisoformat(user['last_nick_change']['time']).strftime('%Y-%m-%d %H:%M:%S')
old_nick = user['last_nick_change']['old']
new_nick = user['last_nick_change']['new']
response.append(
ircstyle.style(f"📛 Nickname change: ", fg="purple") +
ircstyle.style(f"Changed from {old_nick} to {new_nick} at {change_time}", fg="white")
ircstyle.style(f"🆔 Nickname change: ", fg="purple") +
ircstyle.style(f"Changed from {old_nick} to {new_nick} ", fg="white") +
ircstyle.style(humanize.naturaltime(datetime.now() - datetime.fromisoformat(user['last_nick_change']['time'])), fg="white")
)
except (ValueError, KeyError):
response.append(ircstyle.style(f"📛 Nickname change: ", fg="purple") + ircstyle.style("Invalid or Missing Data", fg="white"))
except KeyError:
response.append(ircstyle.style(f"🆔 Nickname change: ", fg="purple") + ircstyle.style("Invalid or Missing Data", fg="white"))
if len(response) == 1: # Only header present
response.append(ircstyle.style("No tracked activities.", fg="yellow"))
@ -172,4 +193,4 @@ class UserActivityTracker:
except Exception as e:
self.log.error(f"Error in !seen command: {e}")
self.bot.privmsg(target, ircstyle.style(" Internal error processing request.", fg="red", bold=True))
self.bot.privmsg(target, ircstyle.style("🚨 Internal error processing request.", fg="red", bold=True))