*/ /** * @return array */ public function make(User $recipient, BlueprintInterface $blueprint): array { $activityType = trim((string) $this->settings->get('sbp-jm-msteams-webhook.activity_type', 'systemDefault')); $forumName = trim((string) $this->settings->get('forum_title', 'Flarum')) ?: 'Flarum'; $iconId = trim((string) $this->settings->get('sbp-jm-msteams-webhook.icon_id', '')); // Diskussionstitel + URL dynamisch aus dem Subject ziehen // $discussionTitle = $this->resolveDiscussionTitle($blueprint) ?? $forumName; // $discussionUrl = $this->resolveSubjectUrl($blueprint) ?? 'https://forum.sbp.de'; // $previewSnippet = $this->buildPreviewText($blueprint); $discussionTitle = 'Backup-Strategie für Forum'; $discussionUrl = 'https://forum.sbp.de/d/34-which-file-extensions-are-allowed-for-uploads/2'; $previewSnippet = 'Bitte prüft, ob wir tägliche Snapshots brauchen.'; $reasonText = 'Neue Antwort in beobachteter Diskussion'; // Freie Actor+Reason-Zeile für systemDefault $reasonText = match ($blueprint::getType()) { 'newPost' => 'There was a new answer in one of your folloed posts', 'postMentioned' => 'Your post has been mentioned', 'userMentioned' => 'You have been mentioned', 'postLiked' => 'Your post has been liked', default => 'New sbp forum update', }; // Teams-App-/Tab-Ziel aus deinem aktuellen Manifest $teamsManifestAppId = 'd92b1be6-ea92-46b1-bcb0-c08ffdd1a61a'; $teamsEntityId = '8ffe419f-ca44-4627-a4b2-f223da2d07aa'; $discussionTitle = 'Backup-Strategie für Forum'; $discussionUrl = 'https://forum.sbp.de/d/34-which-file-extensions-are-allowed-for-uploads/2'; $subEntityId = 'discussion:34:2'; $contextJson = json_encode([ 'subEntityId' => $subEntityId, ], JSON_UNESCAPED_SLASHES); $teamsDeepLink = sprintf( 'https://teams.microsoft.com/l/entity/%s/%s?tenantId=%s&webUrl=%s&label=%s&context=%s', rawurlencode('d92b1be6-ea92-46b1-bcb0-c08ffdd1a61a'), rawurlencode('8ffe419f-ca44-4627-a4b2-f223da2d07aa'), rawurlencode('e2052793-a0f4-47d8-a3a3-52c926e79df5'), rawurlencode($discussionUrl), rawurlencode($discussionTitle), rawurlencode($contextJson) ); $payload = [ 'topic' => [ 'source' => 'text', 'value' => $discussionTitle, 'webUrl' => $teamsDeepLink, ], 'activityType' => $activityType !== '' ? $activityType : 'systemDefault', 'previewText' => [ 'content' => mb_substr($previewSnippet, 0, 150), ], 'templateParameters' => [ [ 'name' => 'systemDefaultText', 'value' => $reasonText, ], ], ]; if ($iconId !== '') { $payload['iconId'] = $iconId; } if (($payload['activityType'] ?? 'systemDefault') !== 'systemDefault') { $payload['templateParameters'] = [ [ 'name' => 'notificationText', 'value' => mb_substr($previewSnippet, 0, 150), ], ]; } return $payload; } protected function buildPreviewText(BlueprintInterface $blueprint): string { if ($blueprint::getType() === 'teamsTest') { return 'Flarum ➜ Teams Test erfolgreich angestoßen'; } $actor = $blueprint->getFromUser(); $actorName = $actor instanceof User ? (string) ($actor->display_name ?? $actor->username ?? 'Jemand') : 'Jemand'; $type = $blueprint::getType(); $subject = $blueprint->getSubject(); $subjectTitle = null; if ($subject instanceof Discussion) { $subjectTitle = (string) $subject->title; } elseif ($subject instanceof Post && $subject->discussion) { $subjectTitle = (string) $subject->discussion->title; } $text = match ($type) { 'newPost' => sprintf('%s hat in einer beobachteten Diskussion geantwortet', $actorName), 'postMentioned' => sprintf('%s hat dich in einem Beitrag erwähnt', $actorName), 'userMentioned' => sprintf('%s hat dich erwähnt', $actorName), 'postLiked' => sprintf('%s hat einen Beitrag von dir geliked', $actorName), 'discussionRenamed' => sprintf('%s hat eine Diskussion umbenannt', $actorName), default => sprintf('%s: neue Flarum-Benachrichtigung (%s)', $actorName, $type), }; if ($subjectTitle) { $text .= ' – ' . $subjectTitle; } return mb_substr($text, 0, 150); } protected function resolveDiscussionTitle(BlueprintInterface $blueprint): ?string { $subject = $blueprint->getSubject(); if ($subject instanceof Discussion) { return (string) $subject->title; } if ($subject instanceof Post && $subject->discussion) { return (string) $subject->discussion->title; } return null; } protected function resolveSubjectUrl(BlueprintInterface $blueprint): ?string { $baseUrl = rtrim((string) $this->settings->get('sbp-jm-msteams-webhook.forum_base_url', ''), '/'); if ($baseUrl === '') { return null; } $subject = $blueprint->getSubject(); if ($subject instanceof Discussion) { return sprintf('%s/d/%s', $baseUrl, $subject->id); } if ($subject instanceof Post) { $discussionId = $subject->discussion_id; $postNumber = $subject->number; if ($discussionId !== null && $postNumber !== null) { return sprintf('%s/d/%s/%s', $baseUrl, $discussionId, $postNumber); } } return $baseUrl; } protected function buildChainId(User $recipient, BlueprintInterface $blueprint): int { $subject = $blueprint->getSubject(); $subjectId = is_object($subject) && isset($subject->id) ? (string) $subject->id : '0'; return abs(crc32(implode('|', [ (string) $recipient->id, $blueprint::getType(), $subjectId, ]))); } }