fulvia/modules/seen.py

158 lines
4.5 KiB
Python
Raw Normal View History

2018-03-16 03:13:43 -04:00
#!/usr/bin/env python3
"""
When was this user last seen.
"""
2018-05-29 13:58:03 -04:00
import os
2018-03-16 03:13:43 -04:00
import time
import argparse
2018-03-16 03:13:43 -04:00
import threading
from datetime import datetime
from sqlite3 import OperationalError
2018-05-25 07:22:56 -04:00
from requests.structures import CaseInsensitiveDict
2019-10-08 12:39:13 -04:00
import config
2018-03-16 03:13:43 -04:00
from tools.time import relativeTime
2018-05-29 13:58:03 -04:00
from module import commands, example, hook, require_chanmsg, rate
2018-03-16 03:13:43 -04:00
def load_database(bot):
"""
Loads all entries from the 'seen' table in the bot's database and
returns them.
"""
2018-05-25 07:22:56 -04:00
data = CaseInsensitiveDict()
2018-03-16 03:13:43 -04:00
seens = bot.db.execute("SELECT * FROM seen").fetchall()
for seen in seens:
2018-05-25 07:22:56 -04:00
nick, seen = seen[0].lower(), seen[1:]
2018-03-16 03:13:43 -04:00
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)")
2018-03-16 03:13:43 -04:00
con.commit()
con.close()
2018-03-16 03:56:45 -04:00
bot.memory["seen_lock"] = threading.Lock()
bot.memory["seen"] = load_database(bot)
bot.memory["seen_last_dump"] = time.time()
2018-05-29 13:58:03 -04:00
@rate(1)
2018-03-16 03:13:43 -04:00
@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.
-l, --last - reports when the user was last seen. This is the default.
-f, --first - reports when the user was first seen.
-m, --message - includes the first/last message the user sent.
-c, --context - includes irc logs before and after their last message as context. Implies --message.
"""
2020-01-07 18:58:19 -05:00
if len(trigger.args) < 2:
return bot.reply("Seen who?")
2018-03-16 03:13:43 -04:00
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")
2018-05-29 13:58:03 -04:00
parser.add_argument("-c", "--context", action="store_true")
2020-01-07 18:58:19 -05:00
args = parser.parse_args(trigger.args[1:])
2018-03-16 03:13:43 -04:00
if args.nick == bot.nick:
2018-03-16 03:13:43 -04:00
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:]
2018-03-16 03:13:43 -04:00
else:
return bot.msg(f"I haven't seen \x0308{args.nick}")
2018-03-16 03:13:43 -04:00
timestamp = datetime.fromtimestamp(timestamp)
2019-10-08 12:39:13 -04:00
t_format = config.default_time_format
2018-03-16 03:13:43 -04:00
timestamp = datetime.strftime(timestamp, t_format)
2019-10-08 12:39:13 -04:00
reltime = relativeTime(datetime.now(), timestamp)
2018-03-16 03:13:43 -04:00
if args.first:
msg = "First"
else:
msg = "Last"
msg += f" heard from \x0308{args.nick}\x03 at {timestamp} " \
2018-03-16 03:13:43 -04:00
+ f"(\x0312{reltime} ago\x03) in \x0312{channel}"
if args.message:
2018-03-16 03:13:43 -04:00
msg += f'\x03 with "\x0308{message}\x03"'
2018-05-25 15:21:18 -04:00
bot.msg(msg)
2018-03-16 03:13:43 -04:00
2018-05-29 13:58:03 -04:00
if args.context:
num_con_lines = 2
fname = os.path.join(bot.log_path, bot.hostname,channel,timestamp[1:11])
fname += ".log"
if not os.path.isfile(fname):
return bot.msg("Context not available.")
with open(fname, "r") as file:
data = file.read().splitlines()
matches = [line for line in data if line.startswith(timestamp)]
if not matches:
return bot.msg("Context not available")
index = data.index(matches[0]) # a bit lazy, but w/e
start = max([index - num_con_lines, 0])
end = min([index + num_con_lines+1, len(data) - 1])
bot.msg("Context:")
bot.msg("\n".join(data[start:end]))
del data
2018-03-16 03:13:43 -04:00
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 (?, ?, ?, ?, ?, ?, ?)",
2018-03-16 03:13:43 -04:00
(nick,) + seen)
bot.memory["seen_lock"].release()
@hook(True)
@require_chanmsg
def seen_hook(bot, trigger):
2019-03-19 07:03:37 -04:00
bot.memory["seen_lock"].acquire()
2020-01-07 18:58:19 -05:00
last = (time.time(), trigger.channel, ' '.join(trigger.args))
if not trigger.nick in bot.memory["seen"]:
2020-01-07 18:58:19 -05:00
first = (time.time(), trigger.channel, ' '.join(trigger.args))
else:
first = bot.memory["seen"][trigger.nick][:3]
seen = first + last
2018-03-16 03:13:43 -04:00
bot.memory["seen"][trigger.nick] = seen
2019-03-19 07:03:37 -04:00
bot.memory["seen_lock"].release()
2018-03-16 03:13:43 -04:00
2018-05-27 20:03:00 -04:00
if time.time() - bot.memory["seen_last_dump"] > 1:
2018-03-16 03:13:43 -04:00
# only dump once a minute at most
dump_seen_db(bot)
bot.memory["seen_last_dump"] = time.time()