Dieser Artikel ist der Artikel zum 24. Tag von SLP KBIT Adventskalender 2019. Es ist lange her, ich bin Gakki. Dieses Mal habe ich Slackbot erstellt, also werde ich eine Aufzeichnung davon schreiben.
In meinem Kreis wird Slack als Hauptkontaktwerkzeug mit ** freiem Plan ** verwendet. Unter solchen Umständen verwenden viele Mitglieder es als Arbeitsbereich Manchmal werden Erwähnungen zu nicht verwandten Themen gemacht, deshalb habe ich mich gefragt, ob ich das lindern könnte. Ich habe beschlossen, einen Bot zu erstellen, der Benutzergruppen verwalten kann. (Es ist nicht sinnvoll, Benachrichtigungen für die meisten Nachrichten zu aktivieren ...)
Ich habe auf die Website von [hier] verwiesen (https://qiita.com/croissant1028/items/8d6334b76576762df349).
Von hier aus beginnen wir mit dem Hauptthema. Ich werde es in den folgenden Inhalten separat schreiben.
Um die diesmal erstellte Benutzergruppe zu verwalten, Da dies nicht nur mit der Berechtigung als Bot-Benutzer möglich war, haben wir die erforderliche Berechtigung wie folgt festgelegt.
Die Ordnerstruktur ist wie folgt. Die Verarbeitung über die Funktion des Bot-Benutzers hinaus wird in my_mention.py und subMethod.py beschrieben und von run.py of main importiert.
Dieses Mal haben wir eine Gruppe von Befehlen zum Verwalten von Benutzergruppen implementiert. Außerdem habe ich einen Fragebogen-bezogenen Befehl erstellt, sodass ich ein wenig darüber schreiben werde. Die Hauptfunktionen sind wie folgt.
Als Prämisse werde ich zunächst das Konzept der diesmal erstellten Benutzergruppe erläutern. Wie bereits erwähnt, ist der Arbeitsbereich mit dem Bot ein kostenloser Plan API-Methoden für Benutzergruppen können nicht verwendet werden. Erstellen Sie daher ein Wörterbuch mit dem Schlüssel als Benutzergruppenname und dem Wert als Array von Gruppenmitgliedern. Ich habe beschlossen, es zu einer Pseudo-Benutzergruppe zu machen, indem ich es in einer statischen Datei speichere. Bitte haben Sie Verständnis dafür, dass der Inhalt des Wörterbuchs in den nachfolgenden Programmen angezeigt wird.
Das Programm ist wie folgt.
@respond_to('create\s([a-zA-Z0-9]*)\s([\w\s,]+)')
def create_usergroup(message, usergroup_name, member):
usergroup = subMethod.get_usergroup_list()
member_list = subMethod.get_member()['members']
for usergroup_dict in usergroup:
if usergroup_dict['usergroup_name'] == usergroup_name:
message.send("`" + usergroup_name+' is already exist.`\n> please choose another name.')
return
data = {}
member_id = []
data['usergroup_name'] = usergroup_name
try:
member_name = [x.strip() for x in member.split(',')]
except AttributeError:
member_name = []
member_id = member
ml_id = [ml['id'] for ml in member_list]
ml_name = [ml['name'] for ml in member_list]
ml_rname = [ml['real_name'] if 'real_name' in ml else 'no_name' for ml in member_list]
ml_dname = [ml['profile']['display_name'] for ml in member_list]
for mn in member_name:
if mn in ml_name:
member_id.append(ml_id[ml_name.index(mn)])
elif mn in ml_rname:
member_id.append(ml_id[ml_rname.index(mn)])
elif mn in ml_dname:
member_id.append(ml_id[ml_dname.index(mn)])
else:
message.send("`" + mn + " is not in this channel`")
data['member'] = member_id
usergroup.append(data)
subMethod.set_usergroup_list(usergroup)
message.send('Created a usergroup')
Es wird ausgeführt, wenn eine Nachricht im Format "create {Benutzergruppenname} {Mitgliedsname, ...}" empfangen wird. Überprüfen Sie als interner Prozess zunächst, ob die angegebene Benutzergruppe bereits erstellt wurde. Wenn es nach der Überprüfung noch nicht vorhanden ist, erstellen Sie es und fügen Sie Mitglieder hinzu. Zu diesem Zeitpunkt wird gleichzeitig bestätigt, ob das angegebene Mitglied im Arbeitsbereich vorhanden ist. Im Arbeitsbereich vorhandene Benutzer können mithilfe der user_list-Methode eine Liste abrufen. Das Problem hierbei ist jedoch das Format. In Slack können Benutzer Werte in drei Formaten haben: Benutzer-ID, vollständiger Name und Anzeigename. Da es schwierig ist, beim Senden einer Nachricht eine ID zu senden, werden Sie meines Erachtens den vollständigen Namen oder den Anzeigenamen angeben Ich habe es möglich gemacht, dort eine gegenseitige Bekehrung durchzuführen. Wenn der Benutzer nach diesem Vorgang vorhanden ist, wird die ID hinzugefügt, und wenn sie nicht vorhanden ist, wird eine Fehlermeldung gesendet. Der Grund für das Hinzufügen der ID wird im folgenden Abschnitt über die Erwähnung von Gruppen erläutert. Wenn es ausgeführt wird, ist es wie folgt.
Das Programm ist wie folgt.
@respond_to('delete_usergroup\s([a-zA-Z0-9]*)')
def delete_usergroup(message, usergroup_name):
usergroup = subMethod.get_usergroup_list()
usergroup_name_list = [x['usergroup_name'] for x in usergroup]
if usergroup_name not in usergroup_name_list:
message.send("`" + usergroup_name + ' is not exist.`\n> type `@secretary list` and check usergroup_name')
return
new_usergroup = []
for usergroup_dict in usergroup:
if usergroup_dict['usergroup_name'] == usergroup_name:
continue
new_usergroup.append(usergroup_dict)
subMethod.set_usergroup_list(new_usergroup)
message.send('Deleted a usergroup')
Empfängt und führt eine Nachricht im Format "delete_usergroup {usergroup name}" aus. In dieser Hinsicht ist es fast nur eine Wörterbuchoperation. Wenn eine bestimmte Benutzergruppe vorhanden ist, löschen Sie diese einfach aus dem Wörterbuch. Wenn nicht, wird eine Fehlermeldung gesendet. Wenn ich versuche, es zu benutzen, sieht es so aus.
Das Programm ist wie folgt.
@respond_to('add\s([a-zA-Z0-9]*)\s([\w\s,]+)')
def add_member(message, usergroup_name, member):
usergroup = subMethod.get_usergroup_list()
usergroup_name_list = [usergroup_dict['usergroup_name'] for usergroup_dict in usergroup]
if usergroup_name not in usergroup_name_list:
message.send("`" + usergroup_name + " is not exist`\n> please type `@secretary list` and check usergroup_name.")
return
member_list = subMethod.get_member()['members']
usergroup_member = subMethod.get_usergroup_member(usergroup_name)
member_id = []
try:
member_name = [x.strip() for x in member.split(',')]
except AttributeError:
member_name = []
member_id = member
add_member_name = []
for mn in member_name:
if mn not in usergroup_member:
add_member_name.append(mn)
else:
message.send("`" + mn + ' already belongs`')
ml_id = [ml['id'] for ml in member_list]
ml_name = [ml['name'] for ml in member_list]
ml_rname = [ml['real_name'] if 'real_name' in ml else 'no_name' for ml in member_list]
ml_dname = [ml['profile']['display_name'] for ml in member_list]
for mn in add_member_name:
if mn in ml_name:
member_id.append(ml_id[ml_name.index(mn)])
elif mn in ml_rname:
member_id.append(ml_id[ml_rname.index(mn)])
elif mn in ml_dname:
member_id.append(ml_id[ml_dname.index(mn)])
else:
message.send("`" + mn + " is not in this channel`")
if len(member_id) == 0:
message.send("`No one will add`")
return
for usergroup_dict in usergroup:
if usergroup_dict['usergroup_name'] == usergroup_name:
usergroup_dict['member'].extend(member_id)
usergroup_dict['member'] = list(set(usergroup_dict['member']))
break
subMethod.set_usergroup_list(usergroup)
message.send('Added some member')
@respond_to('delete\s([a-zA-Z0-9]*)\s([\w\s,]+)')
def delete_member(message, usergroup_name, member):
usergroup = subMethod.get_usergroup_list()
usergroup_name_list = [usergroup_dict['usergroup_name'] for usergroup_dict in usergroup]
if usergroup_name not in usergroup_name_list:
message.send("`" + usergroup_name + " is not exist`\n> type `@secretary list` and check usergroup_name")
return
member_list = subMethod.get_member()['members']
member_id = []
try:
member_name = [x.strip() for x in member.split(',')]
except AttributeError:
member_name = []
member_id = member
ml_id = [ml['id'] for ml in member_list]
ml_name = [ml['name'] for ml in member_list]
ml_rname = [ml['real_name'] if 'real_name' in ml else 'no_name' for ml in member_list]
ml_dname = [ml['profile']['display_name'] for ml in member_list]
for mn in member_name:
if mn in ml_name:
member_id.append(ml_id[ml_name.index(mn)])
elif mn in ml_rname:
member_id.append(ml_id[ml_rname.index(mn)])
elif mn in ml_dname:
member_id.append(ml_id[ml_dname.index(mn)])
else:
message.send("`" + mn + " is not in this channel`")
if len(member_id) == 0:
message.send("`No one will delete`")
return
for usergroup_dict in usergroup:
if usergroup_dict['usergroup_name'] == usergroup_name:
for mi in member_id:
if mi not in usergroup_dict['member']:
message.send("`" + ml_name[ml_id.index(mi)] + " doesn't belong to this`")
else:
usergroup_dict['member'].remove(mi)
break
subMethod.set_usergroup_list(usergroup)
message.send('Deleted some member')
Hinzufügen eines Mitglieds zu einer Benutzergruppe für die Nachricht add {Benutzergruppenname} {Mitgliedsname,…}
Löscht Mitglieder aus der Benutzergruppe für die Nachricht "Löschen {Benutzergruppenname} {Mitgliedsname, ...}".
Die zusätzliche Verarbeitung entspricht der Erstellungsverarbeitung, wenn die angegebene Benutzergruppe vorhanden ist.
Wenn beim Löschen die angegebene Benutzergruppe vorhanden ist, werden die zu dieser Benutzergruppe gehörenden Mitglieder nacheinander gelöscht.
Es ist ein Fehler, wenn die angegebene Benutzergruppe und die angegebenen Mitglieder nicht vorhanden sind.
Das Programm ist wie folgt.
@listen_to('@[a-zA-Z0-9]+\s([\s\S]*)')
def reply_to_thread(message, text):
usergroup = subMethod.get_usergroup_list()
message.body['text'].replace('\n', ' ')
mention = message.body['text'].split()[0].strip('@')
mention_dict = []
for dictionary in usergroup:
if dictionary['usergroup_name'] == mention:
mention_dict = dictionary
break
if len(mention_dict) == 0:
message.send('`' + mention + ' is not exist`')
return
sentence = ""
for member in mention_dict['member']:
sentence = sentence + "<@" + member + "> "
sentence = sentence + "\n"
message.send(sentence,
thread_ts=message.thread_ts)
Diese Methode unterscheidet sich von den zuvor geschriebenen Inhalten.
Die vorherigen Methoden können nur in Verbindung mit der Erwähnung an den Bot ausgeführt werden.
Diese Methode antwortet auf Nachrichten der Form @ {Benutzergruppenname} {Nachricht}
ohne sie.
Die als Antwort geschriebene Methode muss erwähnt werden, und die als Listen geschriebene Methode ist nicht erforderlich.
Obwohl es sich um einen internen Prozess handelt, wird das am Anfang der Nachricht enthaltene @ {Benutzergruppenname} extrahiert und
Extrahiert den Wert des Elements mit dem angegebenen Benutzergruppennamen als Schlüssel.
Wie bereits erläutert, ist value ein Array-Format. Die for-Anweisung nimmt die Elemente einzeln heraus und kombiniert sie, um eine Nachricht zu erstellen.
Dies ist die zu erwähnende Nachricht.
Hier wird ID beim Erwähnen im Leerlauf verwendet. Daher war es notwendig, sich die ID zu merken.
Wenn die erstellte Nachricht an TL gesendet wird, wird sie nur dann gestört, wenn sich eine große Anzahl von Mitgliedern in der Benutzergruppe befindet.
Daher wird die Nachricht dieses Mal in Form eines Threads für die ursprüngliche Nachricht gesendet.
Die Methode zum Senden an einen Thread lautet "message.send (Satz, thread_ts = message.thread_ts)".
Der eigentliche Bildschirm sieht wie folgt aus.
Die Methoden für Benutzergruppen lauten wie folgt. Zusätzlich zu den oben genannten eine Liste von Gruppen und Mitgliedern, Es gibt Dinge wie das Ändern des Gruppennamens und das Kombinieren von Benutzergruppen, aber ich werde sie weglassen, da sie bisher kombiniert werden können.
Als ich einen Fragebogen mit Slack nahm, versuchte ich, eine Reaktion auf die Nachricht zu bekommen. Bei diesem Format war es sehr mühsam, die Reaktionen einzeln zu sehen und zu bestätigen, wer wo abgestimmt hat. Wenn Sie eine Benutzergruppe erstellen und die Personen, die den Fragebogen beantworten, in einer Benutzergruppe zusammenfassen, Ich dachte, dass der Bot damit umgehen könnte, also machte ich ungefähr zwei Funktionen. (Es scheint, dass kürzlich eine einfache Umfrage veröffentlicht wurde ...)
Das Programm ist wie folgt.
@respond_to('count')
def count_up_reaction(message):
response = subMethod.get_message(message.body['channel'],
message.thread_ts)
if not response:
message.direct_reply("Can't use count method in DM")
return
sentence = ''
if 'reactions' in response['messages'][0]:
data = response['messages'][0]['reactions']
sorted_data = sorted(data, reverse=True, key=lambda x:x['count'])
sentence = response['messages'][0]['text'] + '\n\n*Result*\n'
for datum in sorted_data:
sentence = sentence + ":" + datum['name'] + ":" + " "
for user in datum['users']:
sentence = sentence + "<@" + user + "> "
sentence = sentence + "\n"
else:
sentence = 'No reactions'
message.direct_reply(sentence)
Es wird ausgeführt, indem "count" an den Thread der Nachricht gesendet wird, für die Sie die Reaktionen aggregieren möchten. Wenn Sie die Nachricht oben im Thread erhalten, gibt es einen Teil, der die Reaktionsdaten zusammenfasst. Organisieren Sie sie also. Die Reaktionsdaten sind in der folgenden Form enthalten. Da es sich um ein Wörterbuch handelt, erfasst es Daten, formt sie und sendet sie an den Benutzer, der per DM "count" gesendet hat. Der Ausführungsbildschirm ist wie unten gezeigt.
Das Programm ist wie folgt.
@respond_to('diff')
def check_reactor(message):
response = subMethod.get_message(message.body['channel'],
message.thread_ts)
if not response:
message.direct_reply("Can't use count method in DM")
return
target_usergroup = response['messages'][0]['text'].replace('\n', ' ').split()[0].strip('@')
all_target_audience = subMethod.get_usergroup_member_id(target_usergroup)
if len(all_target_audience) == 0:
sentence = 'No specified user group'
elif 'reactions' in response['messages'][0]:
data = response['messages'][0]['reactions']
reacted_users = []
reacted_users.extend([user for datum in data for user in datum['users']])
target_audience = []
target_audience.extend([user for user in all_target_audience if user not in reacted_users])
sentence = "*Hasn't yet reacted*\n"
for user in target_audience:
sentence = sentence + "<@" + user + ">\n"
else:
sentence = "*Hasn't yet reacted*\n"
for user in all_target_audience:
sentence = sentence + "<@" + user + ">\n"
message.direct_reply(sentence)
Geben Sie wie bei Erwähnungen von Benutzergruppen die Zielbenutzergruppe am Anfang der Nachricht an. Senden Sie dann "diff" an den Thread der Zielnachricht, um die Aggregation durchzuführen. Extrahieren Sie zunächst die Zielbenutzergruppe aus der Nachricht und rufen Sie das Mitgliederarray ab. Als nächstes erhalten Sie eine Liste der Benutzer mit Reaktionen auf irgendeine Weise. Wenn Sie diese beiden erhalten können, extrahieren Sie die Benutzer, die nur in einem der beiden Arrays vorhanden sind. Ordnen Sie sie an und senden Sie sie per DM. Der Ausführungsbildschirm ist wie unten gezeigt.
Die Einführung von Slackbot kann intuitiv über die GUI erfolgen, und Bei der Funktionsimplementierung hatte ich den Eindruck, dass es relativ einfach ist, an Python zu arbeiten, da es eine gute Bibliothek gibt. Derzeit gibt es noch wenige Funktionen, daher werde ich auch in Zukunft weiter programmieren. Außerdem schreibe ich wie immer den gleichen Prozess an verschiedenen Stellen, Der Dateiname ist ebenfalls schlecht, daher befindet er sich in einem schrecklichen Zustand. Ich möchte das Refactoring fest machen. Schließlich wurde dieser Code auf GitHub hochgeladen. Schauen Sie also bitte nach, wenn Sie möchten. Ich habe auch über Docker geschrieben. Wenn Sie also eine Umgebung haben, in der Sie Docker verwenden können, können Sie es meiner Meinung nach verwenden, sobald Sie das Token festgelegt haben.
Recommended Posts