Da es hier noch nicht viele Threads zum Thema Synology Chat und Chat Integration gibt, dachte ich mir, ich teile hier mal meine ersten Schritte in Richtung eines ChatBots.
Nachdem ich
dieses Support-Dokument gefunden habe, war ich sofort Feuer und Flamme irgendetwas mit dieser Schnittstelle zu machen. Der Gedanke an einen eigenen, self-hosted Bot à la Google Assistent, mit dem ich mich in einer Chat-Umgebung austauschen kann, hat mich einfach begeistert.
Um mich mit php vertraut zu machen habe ich ein Skript für Incoming Webhooks zusammengeklöppelt, womit ein php-fähiges Gerät also in Eigeninitiative Nachrichten in Chat postet und was von der Shell oder in Skripten ausgeführt werden kann. Dank geht dabei an
heavygale und
diesen Beitrag, von dem ich die Funktion send_chat() geklaut habe :D Ohne die hätte ich gar nicht gewusst, wie ich anzufangen habe.
Hier ist der Code:
Code:
/*
Basic message-script for Synology Chat. Written for PHP 5.4 and above.
Usage:
php chatbot.php [Bot] [Message Type] [Content]
Examples:
/bin/php chatbot.php TestBot Message1
/bin/php chatbot.php SynoBot Text "Testnachricht"
/bin/php chatbot.php TestBot URL "http://example.org"
"Message Type" can be either one of the pre-definded messages below or one of the following: "Text", "URL" or "File".
For those three the [Content] Parameter as string is needed, in form of plain text for "Text" or an URL for "URL" and "File"
Pre-defined Messages:
[Message1]
[Message2]
[Bootup]
[Shutdown]
[KlingelEvent]
*/
// Device name for message integration
$source = "Syno1"; //Syno2, RaspPi, etc.
// Webhook URLs for different Bots
$Bots = [
TestBot => "https://example.org/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=1&token=XXXXXXXXX",
SynoBot => "https://example.org/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=1&token=XXXXXXXXX",
KlingelBot => "https://example.org/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=1&token=XXXXXXXXX",
];
// Chat users to address, so they get Push Notifications. @channel equals every member in a channel
$Users = [
"@channel",
"@User1",
"@User2",
];
function send_chat($webhook, $message) {
$opts = ['http' =>
[
'method' => 'POST',
'content' => $message,
],
'ssl' =>
[
'verify_peer' => true //Toggle SSL-verification
],
];
$context = stream_context_create($opts);
return file_get_contents($webhook, false, $context);
}
function set_payload($Text) {
$a = 'payload={"text": "' . $Text . '"}';
return $a;
}
function set_payload_long($Type, $Text) {
switch ($Type) {
case "Text":
$b = set_payload($Text);
break;
case "URL":
$b = 'Link <"' . $Text . '">';
$b = set_payload($b);
break;
case "File":
$b = 'payload={"text": "File Link", "file_url": "' . $Text . '"}';
break;
default:
$b = error_message($Type, true);
echo 'Second Argument invalid: [Text],[URL] or [File] allowed. Usage: php chatbot.php [Bot] [Type] [Content]';
}
return $b;
}
//Pre-definded messages. Add new Messages to your liking.
function pre_build($Type) {
global $Users;
global $source;
switch($Type) {
case "Message1":
$c = $Users[1] . ' Dies ist eine Testnachricht';
$c = set_payload($c);
break;
case "Message2":
$c = $Users[2] . ' Dies ist eine zweite Testnachricht';
$c = set_payload($c);
break;
case "Bootup":
$c = $Users[1] . ' ' . $source . ' ist hochgefahren';
$c = set_payload($c);
break;
case "Shutdown":
$c = $Users[1] . ' ' . $source . ' fährt herunter';
$c = set_payload($c);
break;
case "KlingelEvent":
$c = $Users[0] . ' ' . date("d.m.y | H:i") . ' Es hat #geklingelt';
$c = set_payload($c);
break;
default:
$c = error_message($Type, true);
echo "Invalid arguments. See chatbot.php for pre-defined messages";
}
return $c;
}
//Set $notify to true or false in case you want to get an error message in the Chat App or not
function error_message($fault, $notify) {
global $source;
if($notify) {
$d = "'" . $fault . "' from " . $source . ": Interpretation failed";
$d = set_payload($d);
} else {
$d = NULL;
}
return $d;
}
if(isset($argv[3])) {
$payload = set_payload_long($argv[2], $argv[3]);
$url = $Bots[$argv[1]];
send_chat($url, $payload);
} elseif (isset($argv[1]) && isset($argv[2])) {
foreach($Bots as $key => $value) {
if ($argv[1] == $key) {
$payload = pre_build($argv[2]);
send_chat($value, $payload);
break;
}
}
} else {
echo 'Invalid arguments. See chatbot.php for usage.';
}
Dies ist im Grunde nur ein glorifizierter Weg folgenden curl-Befehl zu benutzen:
Code:
curl -X POST -H "Content-Type: application/json" -d 'payload={"text": "cURL Test"}' "https://example.org/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=1&token=XXXXXXXXX"
bzw. diese URL im Browser zu öffnen:
Code:
"https://example.org/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=1&token=XXXXXXXXX&payload={"text":"Testnachricht"}"
Der Hintergedanke war einfach, dass man das Skript auf ein php-fähiges Gerät kopiert und immer alle URLs für die verschiedenen Bots zusammen mit ein paar vordefinierten Nachrichten parat hat, um den Aufruf zu erleichtern.
Das ist mein erstes php-Skript, für Verbesserungsvorschläge wäre ich sehr dankbar. Außerdem würden mich eure Ideen interessieren, wofür man die Chat-Integration noch so benutzen kann. Als Beispiel stehen im Skript Bootup- und Shutdown-Nachrichten sowie ein KlingelEvent, was ein an die Haustürklingel angeschlossener Raspberry Pi absetzen kann, komplett mit Uhrzeit und Hashtag und allem, man muss ja mit der Zeit gehen (im doppelten Sinne) :D
P.S. Gerade tüftle ich an einem Skript für Outgoing Webhooks, was für mich viel spannender ist. Damit kann man per Trigger-Wort oder /-Befehl Antworten nach Bedarf anfordern, wie z.B. Online-Stati von verschiedenen Geräten, Messwerte von Smart-Home-Geräten usw.
Wenn ich da was vorzuweisen habe, werde ich es hier posten.
Grüße