summaryrefslogtreecommitdiffstats
path: root/lib/Service/ProcessMentionsService.php
blob: 7f83d965bc0af2fd5f4deeaf2a229aa3fc0dccf0 (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
<?php

// Nextcloud - Social Support
// SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
// SPDX-License-Identifier: AGPL-3.0-or-later

namespace OCA\Social\Service;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use OCA\Social\Entity\Mention;
use OCA\Social\Entity\Status;
use OCP\IRequest;

class ProcessMentionsService {
	private Collection $previousMentions;
	private Collection $currentMentions;
	private IRequest $request;
	private AccountFinder $accountFinder;
	private ResolveAccountService $resolveAccountService;

	public function __construct(IRequest $request, AccountFinder $accountFinder, ResolveAccountService $resolveAccountService) {
		$this->previousMentions = new ArrayCollection();
		$this->currentMentions = new ArrayCollection();
		$this->request = $request;
		$this->accountFinder = $accountFinder;
		$this->resolveAccountService = $resolveAccountService;
	}

	public function run(Status $status) {
		if (!$status->isLocal()) {
			return;
		}

		$this->previousMentions = $status->getActiveMentions();
		$this->currentMentions = new ArrayCollection();

		if (preg_match('/@(([a-z0-9_]([a-z0-9_\.-]+[a-z0-9_]+)+)(@[[:word:]\.\-]+[[:word:]]+)?)/i', $status->getText(), $matches)) {
			$host = $this->request->getServerHost();
			for ($i = 0; $i < count($matches[0]); $i++) {
				$completeMatch = $matches[0][$i];
				$userName = $matches[2][$i];
				$domain = $matches[2][$i] === '' ? '' : substr($matches[2][$i], 1);

				$isLocal = $domain === '' || $host === $domain;
				if ($isLocal) {
					$domain = null;
				} else {
					// normalize domain name
					$domain = parse_url('https://' . $domain,  PHP_URL_HOST);
				}

				$mentionnedAccount = $this->accountFinder->findRemote($userName, $domain);
				assert($mentionnedAccount !== null);

				if (!$mentionnedAccount) {
					// try to resolve it
					$mentionnedAccount = $this->resolveAccountService->resolveMention($userName, $domain, AccountResolverOption::default());
				}

				if (!$mentionnedAccount) {
					// give up
					continue;
				}
				$mentions = $this->previousMentions->filter(fn (Mention $mention) => $mention->getAccount()->getId() === $mentionnedAccount->getId());
				if ($mentions->isEmpty()) {
					$mention = new Mention();
					$mention->setStatus($status);
					$mention->setAccount($mentionnedAccount);
				} else {
					$mention = $mentions->first();
				}
				$this->currentMentions->add($mention);
				str_replace($completeMatch, $mentionnedAccount->getAccountName(), $status->getText());
			}
		}
	}
}