]> kaliko git repositories - sid.git/blob - sid/log.py
Switch to SPDX headers
[sid.git] / sid / log.py
1 # -*- coding: utf-8 -*-
2 # SPDX-FileCopyrightText: 2020 kaliko <kaliko@azylum.org>
3 # SPDX-License-Identifier: GPL-3.0-or-later
4
5 from datetime import datetime
6 from os import fdopen
7 from tempfile import mkstemp
8 from time import time
9
10 from .plugin import Plugin, botcmd
11
12
13 class Log(Plugin):
14     """Logs group chat participant presence.
15
16     The account running the bot need at least room moderation right to log
17     participants JIDs (fallback to nickname).
18     """
19     throttle_ts = int(time())-30
20
21     def __init__(self, bot):
22         Plugin.__init__(self, bot)
23         self.presence = list()
24         bot.add_event_handler("muc::%s::presence" %
25                               self.bot.room, self.log_presence)
26         bot.add_event_handler("muc::%s::got_online" %
27                               self.bot.room, self.log_online)
28         bot.add_event_handler("muc::%s::got_offline" %
29                               self.bot.room, self.log_offline)
30
31     def _get_jid(self, pres):
32         nick = pres['muc']['nick']
33         jid = self.bot.plugin['xep_0045'].rooms[self.bot.room][nick]['jid']
34         if not jid:
35             self.log.debug('jid not found, is bot account moderating room?')
36             return nick
37         jid = jid.split('/')[0]  # strip ressource
38         return jid
39
40     def log_online(self, pres):
41         nick = self._get_jid(pres)
42         self.log.info('got online: %s', nick)
43         self.presence.append((datetime.now(), 'online', nick))
44
45     def log_offline(self, pres):
46         nick = self._get_jid(pres)
47         self.log.info('got offline: %s', nick)
48         self.presence.append((datetime.now(), 'offline', nick))
49
50     def log_presence(self, pres):
51         nick = self._get_jid(pres)
52         self.log.debug('%s: %s', pres['muc']['nick'], pres['type'])
53         self.presence.append((datetime.now(), pres['type'], nick))
54
55     def _format_log(self):
56         log = [f'{d:%Y-%m-%d %H:%M}: {s:12} {n}' for d, s, n in self.presence]
57         return '\n'.join(log)
58
59     @botcmd(hidden=True)
60     def write(self, message, args):
61         """Dump/save room presences log
62
63         ``!write`` : Writes log to file (use mktemp and return file location as MUC message)"""
64         delay = int(time()) - Log.throttle_ts
65         if delay < 30:
66             self.log.debug('throttling file creation')
67             self.reply(message, f'wait {30-delay}s')
68             return
69         log = self._format_log()
70         mode = {'mode': 'w', 'encoding': 'utf-8'}
71         prefix = self.bot.room.split('@')[0] + '_'
72         tmp = mkstemp(prefix=prefix, text=True)
73         self.log.info('Writing to %s', tmp[1])
74         with fdopen(tmp[0], **mode) as fileo:
75             fileo.writelines(log)
76             Log.throttle_ts = int(time())
77         self.reply(message, tmp[1])
78
79     @botcmd(hidden=True)
80     def dump(self, message, args):
81         """``!dump``  : Dumps log as MUC message"""
82         self.reply(message, self._format_log())
83
84
85 # VIM MODLINE
86 # vim: ai ts=4 sw=4 sts=4 expandtab