Skip to content

feat(bots): 🐣 Start with implementing bots - #9458

Merged
nickvergessen merged 16 commits into
masterfrom
feat/1879/webhooks
Aug 7, 2023
Merged

feat(bots): 🐣 Start with implementing bots#9458
nickvergessen merged 16 commits into
masterfrom
feat/1879/webhooks

Conversation

@nickvergessen

@nickvergessen nickvergessen commented May 4, 2023

Copy link
Copy Markdown
Member

☑️ Resolves

Config (webhook.json)

{
	"secret": "At least 32 long random shared secret"
}

Receiver (webhook.php)

<?php

$configData = file_get_contents('./webhook.json');

if ($configData === false) {
	file_put_contents('./webhook.log', "[ERROR] Could not read config]\n", FILE_APPEND);
	return;
}

$config = json_decode($configData, true);

if ($config === null) {
	file_put_contents('./webhook.log', "[ERROR] Could not json_decode config\n", FILE_APPEND);
	return;
}

$signature = $_SERVER['HTTP_X_NEXTCLOUD_TALK_SIGNATURE'] ?? '';
$random = $_SERVER['HTTP_X_NEXTCLOUD_TALK_RANDOM'] ?? '';
$server = $_SERVER['HTTP_X_NEXTCLOUD_TALK_BACKEND'] ?? '';

$body = file_get_contents('php://input');
$generatedDigest = hash_hmac('sha256', $random . $body, $config['secret']);

if (!hash_equals($generatedDigest, strtolower($signature))) {
	file_put_contents('./webhook.log', "[ERROR] Message signature could not be verified\n", FILE_APPEND);
	return;
}

file_put_contents('./webhook.log', $body . "\n", FILE_APPEND);
$data = json_decode($body, true);

if ($data['type'] === 'Create') {
	file_put_contents('./webhook.log', '[OK]    ' . $data['object']['name'] . "\n", FILE_APPEND);
}

if ($config['server']) {
	$message = 'Re: ' . json_decode($data['object']['name'], true)['message'];
	$body = [
		'message' => $message,
		'referenceId' => sha1($random),
		'replyTo' => (int) $data['object']['id'],
	];

	$jsonBody = json_encode($body, JSON_THROW_ON_ERROR);

	$random = bin2hex(random_bytes(32));
	$hash = hash_hmac('sha256', $random . $message, $config['secret']);
	file_put_contents('./webhook.log', '[INFO]  Reply: Random ' . $random . "\n", FILE_APPEND);
	file_put_contents('./webhook.log', '[INFO]  Reply: Hash ' . $hash . "\n", FILE_APPEND);

	try {
		$ch = curl_init(rtrim($server, '/') . '/ocs/v2.php/apps/spreed/api/v1/bot/' . $data['target']['id'] . '/message');
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonBody);
		curl_setopt($ch, CURLOPT_USERAGENT, 'nextcloud-talk-bot/1.0');
		curl_setopt($ch, CURLOPT_HTTPHEADER, [
			'OCS-APIRequest: true',
			'Content-Type: application/json',
			'X-Nextcloud-Talk-Bot-Random: ' . $random,
			'X-Nextcloud-Talk-Bot-Signature: ' . $hash,
		]);
		$content  = curl_exec($ch);

		$error = curl_error($ch);
		if ($error) {
			file_put_contents('./webhook.log', '[ERROR] CURL error: ' . $error . "\n", FILE_APPEND);
		} elseif ($content) {
			file_put_contents('./webhook.log', '[INFO]  CURL response: ' . $content . "\n", FILE_APPEND);
		}

		curl_close($ch);
	} catch (\Exception $exception) {
		file_put_contents('./webhook.log', '[ERROR] ' . get_class($exception) . ': ' . $exception->getMessage() . "\n", FILE_APPEND);
	}
}

Webhook message received

{
  "type": "Create",
  "actor": {
    "type": "Person",
    "id": "users/admin",
    "name": "Laura Adams"
  },
  "object": {
    "type": "Note",
    "id": "2370",
    "name": "{\"message\":\"Hello {mention-call1} \\ud83d\\udc4b\",\"parameters\":{\"mention-call1\":{\"type\":\"call\",\"id\":\"u48mn5p4\",\"name\":\"Webhooked room\",\"call-type\":\"group\",\"icon-url\":\"https:\\/\\/192.168.2.63\\/ocs\\/v2.php\\/apps\\/spreed\\/api\\/v1\\/room\\/u48mn5p4\\/avatar?v=996f0d79\"}}}"
  },
  "target": {
    "type": "Collection",
    "id": "u48mn5p4",
    "name": "Webhooked room"
  }
}

@nickvergessen nickvergessen added 2. developing feature: integration 📦 Integration with 3rd party (chat) service labels May 4, 2023
@nickvergessen nickvergessen added this to the 💜 Next Major (28) milestone May 4, 2023
@nickvergessen nickvergessen self-assigned this May 4, 2023
@nickvergessen
nickvergessen marked this pull request as draft May 4, 2023 21:50
@nickvergessen

This comment was marked as resolved.

@nickvergessen nickvergessen added feature: api 🛠️ OCS API for conversations, chats and participants feature: bots 🤖 /commands in chat messages labels Jun 2, 2023
@nickvergessen nickvergessen changed the title feat(webhooks): Start with implementing webhooks for chat messages feat(webhooks): Start with implementing bots Jul 10, 2023
@nickvergessen nickvergessen changed the title feat(webhooks): Start with implementing bots feat(bots): Start with implementing bots Jul 10, 2023
@nickvergessen nickvergessen changed the title feat(bots): Start with implementing bots feat(bots): 🐣 Start with implementing bots Jul 21, 2023
@nickvergessen

nickvergessen commented Jul 21, 2023

Copy link
Copy Markdown
Member Author

Next steps

  • Add commands to handle bots
    • List
    • Install
      • Setup
      • Remove
    • Uninstall
  • States
    • Enable
    • Disable
    • Prevent installing to new conversations
  • API for moderators to see all bots (that are setupable) and enable/disable for current conversation

@nickvergessen
nickvergessen force-pushed the feat/1879/webhooks branch 2 times, most recently from dd69534 to 1bdc64d Compare July 27, 2023 06:51
@nickvergessen
nickvergessen force-pushed the feat/1879/webhooks branch 2 times, most recently from dff4f01 to 7c5ee81 Compare August 2, 2023 18:47
@nickvergessen

Copy link
Copy Markdown
Member Author

Now with integration tests for setup/remove as moderator as well as handling all cases via OCC.

Rendering on iOS and Android also looks good:

iOS Android
photo_2023-08-02_20-54-24 photo_2023-08-02_20-51-42

So I guess API is ready to review.

@nickvergessen

Copy link
Copy Markdown
Member Author

Tests now fail due to missing #10078

Comment thread lib/Chat/ChatManager.php Outdated
Comment thread lib/Model/BotConversation.php Outdated
Comment thread lib/Model/BotServer.php Outdated
Comment thread tests/psalm-baseline.xml
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
… endpoint

Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
@nickvergessen
nickvergessen enabled auto-merge August 7, 2023 10:49
@nickvergessen
nickvergessen merged commit e68fe37 into master Aug 7, 2023
@nickvergessen
nickvergessen deleted the feat/1879/webhooks branch August 7, 2023 11:41
@nickvergessen
nickvergessen restored the feat/1879/webhooks branch August 7, 2023 13:48
@nickvergessen
nickvergessen deleted the feat/1879/webhooks branch August 24, 2023 14:34
@mkrecek234

Copy link
Copy Markdown

@nickvergessen Thanks a lot for implementing webhooks. Unfortunately I struggle to accomplish the following which was also requested in issue #1879 - Slack and most other chat solutions allow the user to easily create a token for a chat room, and based on that token create a webhook secure URL which then can be used to let any other application send a message into that chat room (no authentication then required). How can I accomplish this now programmatically? I want users to add any room to my own (non-Nextcloud) app, and let my app communicate via Nextcloud Talk to users. Thank you for a hint.

@nickvergessen

Copy link
Copy Markdown
Member Author

Responded in the issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature: api 🛠️ OCS API for conversations, chats and participants feature: bots 🤖 /commands in chat messages feature: integration 📦 Integration with 3rd party (chat) service

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

4 participants