summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormakefu <github@syntax-fehler.de>2020-12-07 09:32:22 +0100
committermakefu <github@syntax-fehler.de>2020-12-07 09:32:22 +0100
commit66fca80e30ae6c933433fcfc4664d162defb45b3 (patch)
tree37495b0d2d98255211ed6a6e3c7bfd5cd3fb5d16
parent04f5e5d0f425bdaabab0eb162b603ed5d0cb4a65 (diff)
kalauerbot: implement kalauer recording and rejection counter
-rw-r--r--kalauerbot/bot.py328
1 files changed, 195 insertions, 133 deletions
diff --git a/kalauerbot/bot.py b/kalauerbot/bot.py
index 448e3d0..c4359d7 100644
--- a/kalauerbot/bot.py
+++ b/kalauerbot/bot.py
@@ -4,6 +4,7 @@ import random
import json
import os
import logging
+from datetime import datetime
from googletrans import LANGUAGES,Translator
logging.basicConfig(level=logging.DEBUG)
log = logging.getLogger("Kalauerbot")
@@ -34,6 +35,21 @@ class Kalauerbot(MatrixBot):
def active_db(self):
return dict(self._get_active())
+ def active_db(self):
+ return dict(self._get_active())
+
+ def _get_db(self):
+ for name,entry in self.db.items():
+ if name == "__chosen__":
+ continue # skip the __chosen__ special object
+ yield entry
+
+ def _get_all_kalauer(self):
+ for name,entry in self.db.items():
+ if name == "__chosen__": continue
+ for record in entry.get('record',[]):
+ yield name,record['date'],record['text']
+
def _get_active(self):
for name,entry in self.db.items():
if name == "__chosen__":
@@ -43,145 +59,191 @@ class Kalauerbot(MatrixBot):
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
+ sender = event['sender']
+ if self.user_id == 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,args = 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)
- chosen = random.choices(names,weights=weights)[0]
- chosen_weight = db[chosen]['weight']
- all_weight = sum(weights)
- prob = round(chosen_weight / all_weight * 100,1)
- crosscheck = random.choices(names,weights=weights,k=100000)
- say(f"{chosen} was chosen with a probability of {prob}% to be the next kalauer könig, congratulations!\n" +
- f"cross-check: { crosscheck.count(chosen):,} out of 100,000 rolls were {chosen}")
-
- db["__chosen__"] = chosen
- self.save_db()
+ try:
+ 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}
- 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
+ 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
+ !record <name> <text> - record a kalauer for someone
+ kalauer: <text> - record your kalauer
+ !kalauer - one of the old kalauers
+ """)
+
+ try: command,args= msg.split(" ",1)
+ except: command,args = 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, "rejected":0, "active": True}
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
+ 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 == "!demand":
- name = args.strip()
- if not name:
- say("When demanding a player, you must define who you actually want")
- elif 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"the name '{name}' does not exist in the database, add the user before demanding a kalauer from him")
- self.save_db()
- elif command == "!list":
- all_weight = sum([db[a]["weight"] for a in db if a != "__chosen__" and db[a]["active"]] )
- txt = "Kalauer roster:\n\n"
- for name,entry in db.items():
- if name == '__chosen__': continue
- prob = round(entry['weight']/all_weight * 100,1)
- txt += f"* {name} - {entry['weight']} weight ({prob if entry['active'] else 0}%) - {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]
+ 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)
+ chosen = random.choices(names,weights=weights)[0]
+ chosen_weight = db[chosen]['weight']
+ all_weight = sum(weights)
+ prob = round(chosen_weight / all_weight * 100,1)
+ crosscheck = random.choices(names,weights=weights,k=100000)
+ say(f"{chosen} was chosen with a probability of {prob}% to be the next kalauer könig, congratulations!\n" +
+ f"cross-check: { crosscheck.count(chosen):,} out of 100,000 rolls were {chosen}")
+
+ db["__chosen__"] = chosen
+ 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"""{chosen}, your kalauer has been approved! Your total number of approved kalauers is {db[chosen]['total']}\n\nPlease choose a new potential kalauer könig by typing in `!choose` to let the kalauerbot choose or `!demand <name>` to force your choice\n\nDo not forget to record your kalauer with `kalauer: the funniest joke`. Someone else can also record the kalauer for you via `!record <username> the funniest joke`""")
+ 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:
+ db[db['__chosen__']]['rejected'] = db[db['__chosen__']].get('rejected',0) + 1
+ say(f"{chosen}, your kalauer privilege was revoked and your reject counter increased to {db[db['__chosen__']]['rejected']}, nobody is chosen now. Choose another kalauer könig with `!choose`")
+ db["__chosen__"] = None
+ self.save_db()
+ elif command == "!demand":
+ name = args.strip()
+ if not name:
+ say("When demanding a player, you must define who you actually want")
+ elif 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"the name '{name}' does not exist in the database, add the user before demanding a kalauer from him")
+ self.save_db()
+ elif command == "!list":
+ all_weight = sum([db[a]["weight"] for a in db if a != "__chosen__" and db[a]["active"]] )
+ txt = "Kalauer roster:\n\n"
+ for name,entry in db.items():
+ if name == '__chosen__': continue
+ prob = round(entry['weight']/all_weight * 100,1)
+ txt += f"* {name} - {entry['weight']} weight ({prob if entry['active'] else 0}%) - {entry['total']} approved and {entry.get('rejected',0)} rejected {'(active)' if entry['active'] else '(inactive)'}\n"
+ say(txt)
+ elif command == "!identify":
+ name = args.strip()
+ if name not in db:
+ say(f"Name {name} is not in kalauerdb, cannot identify")
+ else:
+ say(f"Your matrix ID {sender} is now associated to the name {name}")
+ db[name]['id'] = sender
+ self.save_db()
+ 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 == "!record":
+ name,text = args.split(" ",1)
+ if not name in db:
+ say(f'cannot find the name {name} in the kalauer roster')
+ else:
+ entry = db[name]
+ if entry.get('record',None) != list: entry['record'] = []
+ say(f'Thank you for recording the kalauer! It is now associated to the user {name}')
+ entry['record'].append({ 'date': datetime.now().isoformat(), 'kalauer': text})
+ self.save_db()
+ elif command == "kalauer:":
+ text = args.strip()
+ for name,entry in self.db.items():
+ if name == "__chosen__": continue
+ if entry.get('id','') == sender:
+ say(f'Thank you for recording the kalauer! It is now associated to you ({name})')
+ if entry.get('record',None) != list:
+ entry['record'] = []
+ entry['record'].append({ 'date':
+ datetime.now().isoformat(),
+ 'kalauer': text})
+ break
+ else:
+ say('cannot associate your username to a kalauer user, please run `!identify <name>` before')
+
+ self.save_db()
+
+ elif command == "!kalauer":
+ # TODO: this feature is currently broken
+ #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)
+ name,date,text = random.choice(list(self._get_all_kalauer()))
+ date = datetime.fromisoformat(date)
+ say(f"{text} - {name} ({date.strftime('%d.%m.%Y')})" ) # TODO
+ #if ret.pronunciation:
+ # say(f"Pronounced: {ret.pronunciation}")
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}")
+
+ log.debug(f"Receive message {msg}")
+ except Exception as e:
+ say("Something went wrong when trying to process the command, so sorry!")
+ log.debug(e)
def main():
allowlist = os.environ.get("KALAUER_ALLOWLIST",None)