Connect a Discord server via OAuth (bot authorization) and schedule/publish messages to its channels, with mentions and rich embeds. - Connect: custom Socialite Discord provider (bot scope) maps the authorized guild to a SocialAccount; throws if no server was authorized. - Publish: DiscordPublisher posts via the global bot token, validates the chosen channel belongs to the connected guild (anti cross-guild), optimizes media, builds allowed_mentions only from explicit mention chips (no accidental pings), and renders rich embeds. - Compose: per-post channel picker (live lookup), mention autocomplete and an embed editor, gated by a required-channel compliance rule; Discord post preview. - Enum/config/content-type wiring, ConnectionVerifier health check, throttled lookup endpoints, i18n (en/es/pt-BR), and tests. Operators must create a Discord application and set DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET, DISCORD_BOT_TOKEN and DISCORD_CLIENT_REDIRECT.
59 lines
1.9 KiB
PHP
59 lines
1.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\App;
|
|
|
|
use App\Enums\SocialAccount\Platform as SocialPlatform;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\App\Discord\IndexDiscordMentionRequest;
|
|
use App\Models\SocialAccount;
|
|
use App\Services\Social\Discord\DiscordClient;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
class DiscordController extends Controller
|
|
{
|
|
public function __construct(private DiscordClient $discord) {}
|
|
|
|
public function channels(Request $request, SocialAccount $account): JsonResponse
|
|
{
|
|
$this->authorizeDiscordAccount($request, $account);
|
|
|
|
// Degrade to an empty list on a transient Discord outage — the picker
|
|
// shows "no channels" rather than erroring; the publish path still
|
|
// retries (channels() throws there).
|
|
return response()->json([
|
|
'channels' => rescue(
|
|
fn () => $this->discord->channels((string) $account->platform_user_id),
|
|
[],
|
|
report: false,
|
|
),
|
|
]);
|
|
}
|
|
|
|
public function mentions(IndexDiscordMentionRequest $request, SocialAccount $account): JsonResponse
|
|
{
|
|
$this->authorizeDiscordAccount($request, $account);
|
|
|
|
return response()->json([
|
|
'mentions' => $this->discord->mentions(
|
|
(string) $account->platform_user_id,
|
|
(string) $request->validated('q', ''),
|
|
),
|
|
]);
|
|
}
|
|
|
|
private function authorizeDiscordAccount(Request $request, SocialAccount $account): void
|
|
{
|
|
$workspace = $request->user()->currentWorkspace;
|
|
|
|
abort_unless(
|
|
$workspace && $account->workspace_id === $workspace->id && $account->platform === SocialPlatform::Discord,
|
|
Response::HTTP_FORBIDDEN,
|
|
);
|
|
|
|
$this->authorize('view', $workspace);
|
|
}
|
|
}
|