fulvia/modules/seen.py

133 lines
3.6 KiB
Python
Executable File

#!/usr/bin/env python3
"""
When was this user last seen.
"""
import time
import argparse
import threading
from datetime import datetime
from sqlite3 import OperationalError
from requests.structures import CaseInsensitiveDict
from tools.time import relativeTime
from module import commands, example, hook, require_chanmsg
def load_database(bot):
"""
Loads all entries from the 'seen' table in the bot's database and
returns them.
"""
data = CaseInsensitiveDict()
seens = bot.db.execute("SELECT * FROM seen").fetchall()
for seen in seens:
nick, seen = seen[0].lower(), seen[1:]
data[nick] = seen
return data
def setup(bot):
con = bot.db.connect()
cur = con.cursor()
try:
cur.execute("SELECT * FROM seen").fetchone()
except OperationalError:
cur.execute("CREATE TABLE seen("
"nick TEXT PRIMARY KEY,"
"first_timestamp INTEGER,"
"first_channel TEXT,"
"first_message TEXT,"
"last_timestamp INTEGER,"
"last_channel TEXT,"
"last_message TEXT)")
con.commit()
con.close()
bot.memory["seen_lock"] = threading.Lock()
bot.memory["seen"] = load_database(bot)
bot.memory["seen_last_dump"] = time.time()
@commands('seen')
@example(".seen Nigger -l", "Last heard from Nigger at [1997-03-12 16:30:00] "\
+"with \"Just going to the store for some smokes babe I'll be right back\"")
@example(".seen Soma_QM", "I haven't seen Soma_QM")
def seen(bot, trigger):
"""
Reports when and where the user was last/first seen.
--last [-l] reports when the user was last seen. This is the default.
--first [-f] reports when the user was first seen.
--message [-m] includes the first/last message the user sent.
"""
if not trigger.group(2):
return bot.reply("Seen who?")
parser = argparse.ArgumentParser()
parser.add_argument("nick")
parser.add_argument("-l", "--last", action="store_true", default=True)
parser.add_argument("-f", "--first", action="store_true")
parser.add_argument("-m", "--message", action="store_true")
args = parser.parse_args(trigger.group[3:])
if args.nick == bot.nick:
return bot.reply("I'm right here!")
if args.nick in bot.memory["seen"]:
if args.first:
timestamp, channel, message = bot.memory["seen"][args.nick][:3]
else:
timestamp, channel, message = bot.memory["seen"][args.nick][3:]
else:
return bot.msg(f"I haven't seen \x0308{args.nick}")
timestamp = datetime.fromtimestamp(timestamp)
t_format = bot.config.core.default_time_format
timestamp = datetime.strftime(timestamp, t_format)
reltime = relativeTime(bot.config, datetime.now(), timestamp)
if args.first:
msg = "First"
else:
msg = "Last"
msg += f" heard from \x0308{args.nick}\x03 at {timestamp} " \
+ f"(\x0312{reltime} ago\x03) in \x0312{channel}"
if args.message:
msg += f'\x03 with "\x0308{message}\x03"'
bot.msg(msg)
def dump_seen_db(bot):
"""
Dumps the seen database into the bot's database.
"""
bot.memory["seen_lock"].acquire()
for nick, seen in bot.memory["seen"].items():
bot.db.execute("INSERT OR REPLACE INTO seen "
"(nick, first_timestamp, first_channel, first_message,"
"last_timestamp, last_channel, last_message)"
"VALUES (?, ?, ?, ?, ?, ?, ?)",
(nick,) + seen)
bot.memory["seen_lock"].release()
@hook(True)
@require_chanmsg
def seen_hook(bot, trigger):
last = (time.time(), trigger.channel, trigger.group(0))
if not trigger.nick in bot.memory["seen"]:
first = (time.time(), trigger.channel, trigger.group(0))
else:
first = bot.memory["seen"][trigger.nick][:3]
seen = first + last
bot.memory["seen"][trigger.nick] = seen
if time.time() - bot.memory["seen_last_dump"] > 60:
# only dump once a minute at most
dump_seen_db(bot)
bot.memory["seen_last_dump"] = time.time()