summaryrefslogtreecommitdiffstats
path: root/kalauerbot/bot.py
blob: 9556ce5cf077b07f001296f3928c8dc40bacb073 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
from matrixbot import MatrixBot
from functools import partial
import random
import json
import os
import logging
from googletrans import LANGUAGES,Translator
logging.basicConfig(level=logging.DEBUG)
log = logging.getLogger("Kalauerbot")
version = "1.0.0"

class Kalauerbot(MatrixBot):
    def __init__(self,host,display_name,token,user_id,dbpath = "kalauerdb.json",allowlist=None):
        log.debug(f"dbpath: {dbpath}")
        log.debug(f"allowlist: {allowlist}")
        self.allowlist = allowlist
        self.dbpath=dbpath
        self.load_db()
        super().__init__(host,display_name,token,user_id)

    def load_db(self):
        try:
            log.info(f"loading entries from {self.dbpath}")
            self.db = json.load(open(self.dbpath))
            log.debug(self.db)
        except:
            log.info(f"Cannot open {self.dbpath}, creating empty db")
            self.db = { "__chosen__": None }
            self.save_db()
    def save_db(self):
        json.dump(self.db,open(self.dbpath,"w+"))
        log.debug(f"saving db to {self.dbpath}")

    def active_db(self):
        return dict(self._get_active())

    def _get_active(self):
        for name,entry in self.db.items():
            if name == "__chosen__":
                continue # skip the __chosen__ special object
            elif entry['active']:
                yield name,entry
            else:
                log.debug(f"skipping {name} because user is inactive")
                continue
    def process_event(self, room, event):
        if self.user_id == event['sender']: return # don't answer own message
        if event['type'] != 'm.room.message': return
        msg = event['content']['body']
        if self.allowlist and room.room_id not in self.allowlist:
            log.debug("Ignoring message {msg} because {room.room_id} is not in allowlist")
        say = partial(self.say,room)
        db = self.db
        chosen = db['__chosen__']
        if msg == "!help" or msg == "!commands":
            say(f"""
    Kalauerbot Version {version}

    available commands:
      !add <name>        - add a new person to the kalauer roster (alias: !activate, !reactivate)
      !delete <name>     - deactivate the person from the roster (alias: !remove, !deactivate, !freeze)
      !deactivate <name> - deactivate person (e.g. because he is in holiday)
      !activate <name>   - re-activate person
      !kill              - ultimately remove person from kalauer roster (cannot be reversed)
      !choose            - choose the next person to be the kalauer könig
      !who               - find out who was chosen to be todays kalauer könig (alias: !wer, !current)
      !ok                - confirm the kalauer (alias: !gut !passt !reicht !approved)
      !reject            - reject the kalauer (alias: !zu-gut !zu-schlecht !französisch !french)
      !demand <name>     - demand a certain person to be the new kalauer könig
      !list              - list the current roster and weight,totals
      !kalauer          - an emergency kalauer
""")

        try: command,args= msg.split(" ",1)
        except: command = msg

        if command in ["!add", "!activate", "!reactivate"]:
            name = args.strip()
            if name in db and db[name]['active']:
                say(f"{name} already part of the kalauer roster")
            elif name in db and not db[name]['active']:
                say(f"Reactivating {name}. Welcome back to the world of fun, {name}!")
                db[name]['active'] = True
            else:
                say(f"{name} has been added to the kalauer roster, starting weight is 1")
                db[name] = { "weight": 1, "total":0, "active": True}
            self.save_db()
        elif command in ["!delete","!remove","!deactivate","!freeze"]:
            name = args.strip()
            if name not in db:
                say(f"Cannot deactiate someone who was never in kalauer db")
            elif name in db and db[name]['active']:
                say(f"Deactivating {name}, see you soon!")
                db[name]['active'] = False
            else:
                say(f"{name} was already deactivated in the kalauer db")
            self.save_db()
        elif command == "!choose":
            # TODO: refactor this, maybe?
            names = []
            weights = []
            for name,entity in self.active_db().items():
                names.append(name)
                weights.append(entity['weight'])
            log.debug(names)
            log.debug(weights)
            db["__chosen__"] = chosen = random.choices(names,weights=weights)[0]
            say(f"{chosen} was chosen to be the next kalauer könig, congratulations!")
            self.save_db()

        elif command in ["!who","!wer", "!current"]:
            if chosen:
                say(f"{chosen} was chosen to be the next kalauer könig")
            else:
                say(f"Nobody was chosen to be the the kalauer könig, start the process with `!choose`")
        elif command in [ "!ok", "!approved", "!gut", "!passt", "!reicht" ]:
            if not db['__chosen__']:
                say("Nobody is nominated, cannot approve kalauer")
            else:
                log.info("Increasing weight of all active persons")
                for name in self.active_db():
                    db[name]['weight'] += 1
                log.info("The kalauer könig gets his weight set to 0")
                db[chosen]['weight'] = 0
                db[chosen]['total'] += 1
                say(f"""Your kalauer has been approved, your total number of approved kalauers is {db[chosen]['total']}\n\n{chosen}, please choose a new potential kalauer könig by typing in `!choose` to let the kalauerbot choose or `!demand <name>` to force your choice""")
                log.debug("Unsetting current chosen")
                db["__chosen__"] = None
                self.save_db()
        elif command in [ "!reject", "!zu-gut", "!zu-schlecht", "!französisch", "!french"]:
            if not db['__chosen__']:
                say("Nobody is nominated, cannot reject kalauer")
            else:
                say(f"{chosen}, your kalauer privilege was revoked, nobody is chosen now. Choose another kalauer könig with `!choose`")
                db["__chosen__"] = None
                self.save_db()
        elif command == "!demand":
            name = args.strip()
            if name in self.active_db():
                say(f"The previous kalauer könig demands user {name} to be the next kalauer könig. The rules of the Kalauer are divine and shall be respected.")
                db["__chosen__"] = name
            elif name in db:
                say(f"{name} is currently not active, cannot be chosen")
            else:
                say(f"{name} name does not exist in the database, add the user before demanding a kalauer from him")
            self.save_db()
        elif command == "!list":
            txt = "Kalauer roster:\n\n"
            for name,entry in db.items():
                if name == '__chosen__': continue
                txt += f"* {name} - {entry['weight']} weight - {entry['total']} total {'(active)' if entry['active'] else '(inactive)'}\n"
            say(txt)
        elif command == "!kill":
            name = args.strip()
            if name in db:
                say(f"Ultimately removing {name} from Kalauer König db (weight: {db[name]['weight']},total: {db[name]['total']}), we will miss you!")
                del db[name]
            else:
                say(f"Cannot delete someone who was never in the kalauer db")
            self.save_db()
        elif command == "!kalauer":
            kalauer = "Wie nennt man einen dicken Vegetarier? Biotonne!"
            #kalauer = "What do you call a fat vegetarian? Compost bin"
            translator = Translator()
            lang = random.choice(list(LANGUAGES))
            ret = translator.translate(kalauer,src='de',dest=lang)
            log.debug(ret)
            say(f"Your emergency kalauer in {LANGUAGES[lang]}: {ret.text}" ) #needs a newer googletrans
            if ret.pronunciation:
                say(f"Pronounced: {ret.pronunciation}")
        else:

            log.debug(f"Receive message {msg}")

def main():
    allowlist = os.environ.get("KALAUER_ALLOWLIST",None)
    if allowlist:
        allowlist = allowlist.split(',')
    bot = Kalauerbot(
        host = os.environ.get("MATRIX_SERVER","ext01.citadel.team")
        display_name = "Kalauerbot",
        token = os.environ['MATRIX_TOKEN'],
        user_id = os.environ["MATRIX_ID"],
        dbpath = os.environ.get("KALAUER_DBPATH",None) or "kalauerdb.json",
        allowlist = allowlist
    )
    bot.start()


if __name__ == "__main__":
    main()