From e3baa82f75e0753bc9462f8cc26e796dfa28f084 Mon Sep 17 00:00:00 2001 From: Kyrch Date: Thu, 26 Oct 2023 20:34:04 -0300 Subject: [PATCH] feat: discord thread action (#594) --- .env.example | 5 + app/Constants/Config/ServiceConstants.php | 2 + app/Enums/Discord/EmbedColor.php | 1 + .../Actions/Discord/DiscordThreadAction.php | 128 ++++++++++++++++++ app/Nova/Resources/Wiki/Anime.php | 8 ++ config/services.php | 7 + lang/en/nova.php | 11 ++ 7 files changed, 162 insertions(+) create mode 100644 app/Nova/Actions/Discord/DiscordThreadAction.php diff --git a/.env.example b/.env.example index 841ce8070..f1e915142 100644 --- a/.env.example +++ b/.env.example @@ -251,6 +251,11 @@ POSTMARK_TOKEN= DISCORD_BOT_API_TOKEN= DB_UPDATES_DISCORD_CHANNEL= ADMIN_DISCORD_CHANNEL= +SUBMISSIONS_DISCORD_CHANNEL= +WINTER_DISCORD_FORUM_TAG= +SPRING_DISCORD_FORUM_TAG= +SUMMER_DISCORD_FORUM_TAG= +FALL_DISCORD_FORUM_TAG= MAL_CLIENT_ID=null DO_BEARER_TOKEN=null OPENAI_BEARER_TOKEN=null diff --git a/app/Constants/Config/ServiceConstants.php b/app/Constants/Config/ServiceConstants.php index 4e28d3d33..ec3adc797 100644 --- a/app/Constants/Config/ServiceConstants.php +++ b/app/Constants/Config/ServiceConstants.php @@ -13,5 +13,7 @@ class ServiceConstants final public const DB_UPDATES_DISCORD_CHANNEL_QUALIFIED = 'services.discord.db_updates_discord_channel'; + final public const SUBMISSIONS_DISCORD_CHANNEL_QUALIFIED = 'services.discord.submissions_discord_channel'; + final public const OPENAI_BEARER_TOKEN = 'services.openai.token'; } diff --git a/app/Enums/Discord/EmbedColor.php b/app/Enums/Discord/EmbedColor.php index 0283f8d2d..f25dff818 100644 --- a/app/Enums/Discord/EmbedColor.php +++ b/app/Enums/Discord/EmbedColor.php @@ -12,4 +12,5 @@ enum EmbedColor: int case GREEN = 3066993; case YELLOW = 16776960; case RED = 15158332; + case PURPLE = 10092799; } diff --git a/app/Nova/Actions/Discord/DiscordThreadAction.php b/app/Nova/Actions/Discord/DiscordThreadAction.php new file mode 100644 index 000000000..fc2ccbf1d --- /dev/null +++ b/app/Nova/Actions/Discord/DiscordThreadAction.php @@ -0,0 +1,128 @@ +first(); + $name = $fields->get('name'); + + $imagePath = $anime->images()->where(Image::ATTRIBUTE_FACET, ImageFacet::COVER_LARGE)->first()->path; + $image = Storage::disk(Config::get('image.disk'))->url($imagePath); + + $animepage = json_decode(file_get_contents(base_path('composer.json')), true)['homepage'] . 'anime/'; + $description = '**Synopsis:** ' . strip_tags($anime->synopsis) . "\n\n" . '**Link:** ' . $animepage . $anime->slug; + + Http::withToken(Config::get('services.discord.token'), 'Bot') + ->asMultipart() + ->attach('file', file_get_contents($image), 'image.jpg') + ->post("https://discord.com/api/v10/channels/{$this->getDiscordChannel()}/threads", [ + 'payload_json' => json_encode([ + 'name' => $name, + 'applied_tags' => $this->getAppliedTags($anime->season->value), + 'message' => [ + 'embeds' => [ + [ + 'color' => EmbedColor::PURPLE, + 'title' => $anime->name, + 'description' => $description, + ] + ], + ] + ]) + ])->throw(); + + return $models; + } + + /** + * Get Discord forum channel the thread will be created to. + * + * @return string + */ + private function getDiscordChannel(): string + { + return Config::get(ServiceConstants::SUBMISSIONS_DISCORD_CHANNEL_QUALIFIED); + } + + /** + * Get the IDs of the tags applied to the thread. + * + * @param int $season + * @return array + */ + private function getAppliedTags(int $season): array + { + $map = [ + AnimeSeason::WINTER->value => Config::get('services.discord.submissions_forum_tags.winter'), + AnimeSeason::SPRING->value => Config::get('services.discord.submissions_forum_tags.spring'), + AnimeSeason::SUMMER->value => Config::get('services.discord.submissions_forum_tags.summer'), + AnimeSeason::FALL->value => Config::get('services.discord.submissions_forum_tags.fall') + ]; + + return $map[$season] === null + ? [] + : [$map[$season]]; + } + + /** + * Get the fields available on the action. + * + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @return array + */ + public function fields(NovaRequest $request) + { + $anime = $request->findModelQuery()->first(); + + return array_merge( + parent::fields($request), + [ + Text::make(__('nova.actions.discord.thread.name'), 'name') + ->default($anime->name ?? '') + ->required() + ->rules(['required', 'max:100']) + ->maxlength(100) + ->enforceMaxlength() + ->help(__('nova.actions.discord.thread.help')) + ] + ); + } +} \ No newline at end of file diff --git a/app/Nova/Resources/Wiki/Anime.php b/app/Nova/Resources/Wiki/Anime.php index 9afb26823..80a05c15c 100644 --- a/app/Nova/Resources/Wiki/Anime.php +++ b/app/Nova/Resources/Wiki/Anime.php @@ -8,6 +8,8 @@ use App\Enums\Models\Wiki\ResourceSite; use App\Models\Wiki\Anime as AnimeModel; use App\Models\Wiki\ExternalResource as ExternalResourceModel; +use App\Models\Wiki\Video as VideoModel; +use App\Nova\Actions\Discord\DiscordThreadAction; use App\Nova\Actions\Models\Wiki\Anime\AttachAnimeResourceAction; use App\Nova\Actions\Models\Wiki\Anime\BackfillAnimeAction; use App\Nova\Lenses\Anime\Image\AnimeCoverLargeLens; @@ -288,6 +290,12 @@ public function actions(NovaRequest $request): array return array_merge( parent::actions($request), [ + (new DiscordThreadAction()) + ->confirmButtonText(__('nova.actions.base.confirmButtonText')) + ->cancelButtonText(__('nova.actions.base.cancelButtonText')) + ->exceptOnIndex() + ->canSeeWhen('create', VideoModel::class), + (new BackfillAnimeAction($request->user())) ->confirmButtonText(__('nova.actions.anime.backfill.confirmButtonText')) ->cancelButtonText(__('nova.actions.base.cancelButtonText')) diff --git a/config/services.php b/config/services.php index 952040fa0..9ccb386c3 100644 --- a/config/services.php +++ b/config/services.php @@ -37,6 +37,13 @@ 'token' => env('DISCORD_BOT_API_TOKEN'), 'db_updates_discord_channel' => env('DB_UPDATES_DISCORD_CHANNEL'), 'admin_discord_channel' => env('ADMIN_DISCORD_CHANNEL'), + 'submissions_discord_channel' => env('SUBMISSIONS_DISCORD_CHANNEL'), + 'submissions_forum_tags' => [ + 'winter' => env('WINTER_DISCORD_FORUM_TAG'), + 'spring' => env('SPRING_DISCORD_FORUM_TAG'), + 'summer' => env('SUMMER_DISCORD_FORUM_TAG'), + 'fall' => env('FALL_DISCORD_FORUM_TAG') + ] ], 'mal' => [ diff --git a/lang/en/nova.php b/lang/en/nova.php index 9eae748d6..d8bca566f 100644 --- a/lang/en/nova.php +++ b/lang/en/nova.php @@ -55,6 +55,11 @@ ], 'name' => 'Backfill Anime', ], + 'discord' => [ + 'thread' => [ + 'name' => 'Create Thread Discord' + ] + ] ], 'audio' => [ 'delete' => [ @@ -72,6 +77,12 @@ 'cancelButtonText' => 'Cancel', 'confirmButtonText' => 'Confirm', ], + 'discord' => [ + 'thread' => [ + 'name' => 'Name', + 'help' => 'The name of the thread to be created. Use the default name or a shorter synonym if it exceeds 100 characters.' + ] + ], 'dump' => [ 'dump' => [ 'confirmButtonText' => 'Dump',