From ec5c6be01a0f89923eccc8301240719653721272 Mon Sep 17 00:00:00 2001 From: Peter Lohse Date: Wed, 2 Jul 2025 10:05:52 +0200 Subject: [PATCH 1/5] remove acp menu --- acpMenu.xml | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 acpMenu.xml diff --git a/acpMenu.xml b/acpMenu.xml deleted file mode 100644 index 4f0d60c..0000000 --- a/acpMenu.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - From d5bb46601759cf39d7199654f5f59d845f33afa1 Mon Sep 17 00:00:00 2001 From: Peter Lohse Date: Wed, 2 Jul 2025 10:06:41 +0200 Subject: [PATCH 2/5] cleanup files --- acpTemplateDelete.xml | 6 ------ fileDelete.xml | 6 ------ package.xml | 19 ++++--------------- 3 files changed, 4 insertions(+), 27 deletions(-) delete mode 100644 acpTemplateDelete.xml delete mode 100644 fileDelete.xml diff --git a/acpTemplateDelete.xml b/acpTemplateDelete.xml deleted file mode 100644 index 5cc13e3..0000000 --- a/acpTemplateDelete.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/fileDelete.xml b/fileDelete.xml deleted file mode 100644 index fb7f12a..0000000 --- a/fileDelete.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - files/lib/system/discord/SecretFormField.class.php - - diff --git a/package.xml b/package.xml index 7c15d1e..46100de 100644 --- a/package.xml +++ b/package.xml @@ -6,8 +6,8 @@ Discord-API API to cummincate with Discord. API um mit Discord zu kommunizieren. - 2.7.2 - 2024-10-22 + 2.8.0 + 2025-07-02 https://creativecommons.org/publicdomain/zero/1.0/deed.en @@ -15,7 +15,7 @@ https://hanashi.dev/ - com.woltlab.wcf + com.woltlab.wcf com.woltlab.wcf @@ -26,25 +26,14 @@ - acp/database/install_dev.hanashi.wsc.discord-api.php - - - - + - - - - - - - acp/database/install_dev.hanashi.wsc.discord-api.php From 16f99b6b85569d436a8fe34cc33bbe95a6d742ec Mon Sep 17 00:00:00 2001 From: Peter Lohse Date: Wed, 2 Jul 2025 10:48:27 +0200 Subject: [PATCH 3/5] make discord bot list to grid view --- acptemplates/discordBotList.tpl | 78 +--------------- .../lib/acp/page/DiscordBotListPage.class.php | 40 ++------ .../bootstrap/dev.hanashi.wsc.discord-api.php | 9 ++ .../DiscordBotInteractionCollecting.class.php | 13 +++ .../hanashi/discord/bot/DeleteBot.class.php | 31 +++++++ .../admin/DiscordBotGridView.class.php | 91 +++++++++++++++++++ .../admin/DiscordBotInteractions.class.php | 30 ++++++ 7 files changed, 187 insertions(+), 105 deletions(-) create mode 100644 files/lib/event/interaction/admin/DiscordBotInteractionCollecting.class.php create mode 100644 files/lib/system/endpoint/controller/hanashi/discord/bot/DeleteBot.class.php create mode 100644 files/lib/system/gridView/admin/DiscordBotGridView.class.php create mode 100644 files/lib/system/interaction/admin/DiscordBotInteractions.class.php diff --git a/acptemplates/discordBotList.tpl b/acptemplates/discordBotList.tpl index 88ec652..50cb942 100644 --- a/acptemplates/discordBotList.tpl +++ b/acptemplates/discordBotList.tpl @@ -13,80 +13,8 @@ -{hascontent} -
- {content} - {pages print=true assign=pagesLinks controller='DiscordBotList' link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder"} - {/content} -
-{/hascontent} - -{if $objects|count} -
- - - - - - - - - - {event name='columns'} - - - - - {foreach from=$objects item=discordBot} - - - - - - - - {event name='columnsItem'} - - {/foreach} - -
{lang}wcf.global.objectID{/lang}{lang}wcf.acp.discordBotList.botName{/lang}{lang}wcf.acp.discordBotList.server{/lang}{lang}wcf.global.date{/lang}
- {icon size=16 name='pencil'} - {objectAction action="delete" objectTitle=$discordBot->botName} - - {event name='icons'} - - {#$discordBot->botID} - - {$discordBot->botName} - - {if !$discordBot->guildIcon|empty} - - {/if} - {$discordBot->guildName} - - {time time=$discordBot->botTime} -
-
- -
- {hascontent} -
- {content}{unsafe:$pagesLinks}{/content} -
- {/hascontent} - - {hascontent} - - {/hascontent} -
-{else} -

{lang}wcf.global.noItems{/lang}

-{/if} +
+ {unsafe:$gridView->render()} +
{include file='footer'} \ No newline at end of file diff --git a/files/lib/acp/page/DiscordBotListPage.class.php b/files/lib/acp/page/DiscordBotListPage.class.php index daf1977..0ba6fe9 100644 --- a/files/lib/acp/page/DiscordBotListPage.class.php +++ b/files/lib/acp/page/DiscordBotListPage.class.php @@ -2,8 +2,10 @@ namespace wcf\acp\page; -use wcf\data\discord\bot\DiscordBotList; -use wcf\page\SortablePage; +use Override; +use wcf\page\AbstractGridViewPage; +use wcf\system\gridView\AbstractGridView; +use wcf\system\gridView\admin\DiscordBotGridView; /** * Übersicht aller Discord-Bots @@ -13,35 +15,13 @@ * @license Freie Lizenz (https://hanashi.dev/freie-lizenz/) * @package WoltLabSuite\Core\Acp\Page */ -class DiscordBotListPage extends SortablePage +final class DiscordBotListPage extends AbstractGridViewPage { - /** - * @inheritDoc - */ - public $neededPermissions = ['admin.discord.canManageConnection']; - - /** - * @inheritDoc - */ public $activeMenuItem = 'wcf.acp.menu.link.configuration.discord.discordBotList'; - /** - * @inheritDoc - */ - public $objectListClassName = DiscordBotList::class; - - /** - * @inheritDoc - */ - public $defaultSortField = 'botID'; - - /** - * @inheritDoc - */ - public $defaultSortOrder = 'ASC'; - - /** - * @inheritDoc - */ - public $validSortFields = ['botID', 'botName', 'guildID', 'guildName', 'botTime']; + #[Override] + protected function createGridView(): AbstractGridView + { + return new DiscordBotGridView(); + } } diff --git a/files/lib/bootstrap/dev.hanashi.wsc.discord-api.php b/files/lib/bootstrap/dev.hanashi.wsc.discord-api.php index 725d164..395e13f 100644 --- a/files/lib/bootstrap/dev.hanashi.wsc.discord-api.php +++ b/files/lib/bootstrap/dev.hanashi.wsc.discord-api.php @@ -5,7 +5,9 @@ use wcf\acp\page\DiscordWebhookListPage; use wcf\event\acp\dashboard\box\PHPExtensionCollecting; use wcf\event\acp\menu\item\ItemCollecting; +use wcf\event\endpoint\ControllerCollecting; use wcf\event\worker\RebuildWorkerCollecting; +use wcf\system\endpoint\controller\hanashi\discord\bot\DeleteBot; use wcf\system\event\EventHandler; use wcf\system\menu\acp\AcpMenuItem; use wcf\system\request\LinkHandler; @@ -77,4 +79,11 @@ static function (RebuildWorkerCollecting $event) { $event->register(DiscordWebhookAvatarRebuildDataWorker::class, 0); } ); + + EventHandler::getInstance()->register( + ControllerCollecting::class, + static function (ControllerCollecting $event) { + $event->register(new DeleteBot()); + } + ); }; diff --git a/files/lib/event/interaction/admin/DiscordBotInteractionCollecting.class.php b/files/lib/event/interaction/admin/DiscordBotInteractionCollecting.class.php new file mode 100644 index 0000000..e9676ff --- /dev/null +++ b/files/lib/event/interaction/admin/DiscordBotInteractionCollecting.class.php @@ -0,0 +1,13 @@ +checkPermissions(['admin.discord.canManageConnection']); + + $action = new DiscordBotAction([$bot], 'delete'); + $action->executeAction(); + + return new JsonResponse([]); + } +} diff --git a/files/lib/system/gridView/admin/DiscordBotGridView.class.php b/files/lib/system/gridView/admin/DiscordBotGridView.class.php new file mode 100644 index 0000000..6705418 --- /dev/null +++ b/files/lib/system/gridView/admin/DiscordBotGridView.class.php @@ -0,0 +1,91 @@ +addColumns([ + GridViewColumn::for('botID') + ->label('wcf.global.objectID') + ->renderer(new ObjectIdColumnRenderer()) + ->sortable(), + GridViewColumn::for('botName') + ->label('wcf.acp.discordBotList.botName') + ->sortable() + ->titleColumn() + ->filter(new TextFilter()), + GridViewColumn::for('guildName') + ->label('wcf.acp.discordBotList.server') + ->renderer([ + new class extends DefaultColumnRenderer { + public function render(mixed $value, mixed $context = null): string + { + \assert($context instanceof DiscordBot); + + $content = ''; + if (!empty($context->guildIcon)) { + $content = \sprintf( + '', + $context->guildID, + $context->guildIcon + ); + } + + return $content . $context->guildName; + } + }, + ]) + ->sortable() + ->filter(new TextFilter()), + GridViewColumn::for('botTime') + ->label('wcf.global.date') + ->renderer(new TimeColumnRenderer()) + ->sortable() + ->filter(new TimeFilter()), + ]); + + $provider = new DiscordBotInteractions(); + $provider->addInteractions([ + new Divider(), + new EditInteraction(DiscordBotEditForm::class), + ]); + $this->setInteractionProvider($provider); + + $this->setSortField('botID'); + $this->setSortOrder('ASC'); + } + + #[Override] + public function isAccessible(): bool + { + return WCF::getSession()->getPermission('admin.discord.canManageConnection'); + } + + #[Override] + protected function createObjectList(): DatabaseObjectList + { + return new DiscordBotList(); + } +} diff --git a/files/lib/system/interaction/admin/DiscordBotInteractions.class.php b/files/lib/system/interaction/admin/DiscordBotInteractions.class.php new file mode 100644 index 0000000..065f4e3 --- /dev/null +++ b/files/lib/system/interaction/admin/DiscordBotInteractions.class.php @@ -0,0 +1,30 @@ +addInteractions([ + new DeleteInteraction('hanashi/discord/bot/%s'), + ]); + + EventHandler::getInstance()->fire( + new DiscordBotInteractionCollecting($this) + ); + } + + #[Override] + public function getObjectClassName(): string + { + return DiscordBot::class; + } +} From 1ad8b35fdaa72402277d59f4ac6ad2973440a91f Mon Sep 17 00:00:00 2001 From: Peter Lohse Date: Wed, 2 Jul 2025 10:50:52 +0200 Subject: [PATCH 4/5] fix workflow --- .github/workflows/codestyle.yml | 2 +- .github/workflows/php.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml index eb3fa0a..47b8f6a 100644 --- a/.github/workflows/codestyle.yml +++ b/.github/workflows/codestyle.yml @@ -13,7 +13,7 @@ jobs: - name: Setup PHP with tools uses: shivammathur/setup-php@v2 with: - php-version: '8.0' + php-version: '8.3' extensions: ctype, dom, exif, gd, gmp, hash, intl, json, libxml, mbstring, opcache, pcre, pdo, pdo_mysql, zlib tools: cs2pr, phpcs, php-cs-fixer - name: phpcs diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index dc44d63..49050ac 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -15,6 +15,7 @@ jobs: - '8.1' - '8.2' - '8.3' + - '8.4' steps: - name: Set up PHP uses: shivammathur/setup-php@v2 From a5de0cc928c0b465a44bb8e41786ca27ed8f4049 Mon Sep 17 00:00:00 2001 From: Peter Lohse Date: Wed, 2 Jul 2025 11:28:54 +0200 Subject: [PATCH 5/5] make discord webhook to grid view --- acptemplates/discordBotList.tpl | 2 +- acptemplates/discordWebhookList.tpl | 89 +---------------- .../lib/acp/page/DiscordBotListPage.class.php | 8 ++ .../acp/page/DiscordWebhookListPage.class.php | 47 ++------- .../bootstrap/dev.hanashi.wsc.discord-api.php | 2 + ...cordWebhookInteractionCollecting.class.php | 13 +++ .../discord/webhook/DeleteWebhook.class.php | 31 ++++++ .../admin/DiscordWebhookGridView.class.php | 99 +++++++++++++++++++ .../DiscordWebhookInteractions.class.php | 30 ++++++ 9 files changed, 193 insertions(+), 128 deletions(-) create mode 100644 files/lib/event/interaction/admin/DiscordWebhookInteractionCollecting.class.php create mode 100644 files/lib/system/endpoint/controller/hanashi/discord/webhook/DeleteWebhook.class.php create mode 100644 files/lib/system/gridView/admin/DiscordWebhookGridView.class.php create mode 100644 files/lib/system/interaction/admin/DiscordWebhookInteractions.class.php diff --git a/acptemplates/discordBotList.tpl b/acptemplates/discordBotList.tpl index 50cb942..47293f7 100644 --- a/acptemplates/discordBotList.tpl +++ b/acptemplates/discordBotList.tpl @@ -14,7 +14,7 @@
- {unsafe:$gridView->render()} + {unsafe:$gridView->render()}
{include file='footer'} \ No newline at end of file diff --git a/acptemplates/discordWebhookList.tpl b/acptemplates/discordWebhookList.tpl index 5e5774a..f495db5 100644 --- a/acptemplates/discordWebhookList.tpl +++ b/acptemplates/discordWebhookList.tpl @@ -6,91 +6,8 @@ -{hascontent} -
- {content} - {pages print=true assign=pagesLinks controller='DiscordWebhookList' link="pageNo=%d&sortField=$sortField&sortOrder=$sortOrder"} - {/content} -
-{/hascontent} - -{if $objects|count} -
- - - - - - - - - - - - {event name='columns'} - - - - - {foreach from=$objects item=webhook} - - - - - - - - - - {event name='columnsItem'} - - {/foreach} - -
{lang}wcf.global.objectID{/lang}{lang}wcf.acp.discordWebhookList.channelID{/lang}{lang}wcf.acp.discordWebhookList.webhookTitle{/lang}{lang}wcf.acp.discordWebhookList.webhookName{/lang}{lang}wcf.acp.discordBotList.server{/lang}{lang}wcf.global.date{/lang}
- {objectAction action="delete" objectTitle=$webhook->webhookName} - - {event name='icons'} - - {$webhook->webhookID} - - {if $channels[$webhook->botID][$webhook->channelID]|isset} - {$channels[$webhook->botID][$webhook->channelID]['name']}
({$webhook->channelID}) - {else} - {$webhook->channelID} - {/if} -
- {$webhook->webhookTitle} - - {$webhook->webhookName} - - {if !$webhook->getDiscordBot()->guildIcon|empty} - - {/if} - {$webhook->getDiscordBot()->guildName} - - {time time=$webhook->webhookTime} -
-
- -
- {hascontent} -
- {content}{unsafe:$pagesLinks}{/content} -
- {/hascontent} - - {hascontent} - - {/hascontent} -
-{else} -

{lang}wcf.global.noItems{/lang}

-{/if} +
+ {unsafe:$gridView->render()} +
{include file='footer'} \ No newline at end of file diff --git a/files/lib/acp/page/DiscordBotListPage.class.php b/files/lib/acp/page/DiscordBotListPage.class.php index 0ba6fe9..82b81fc 100644 --- a/files/lib/acp/page/DiscordBotListPage.class.php +++ b/files/lib/acp/page/DiscordBotListPage.class.php @@ -17,6 +17,14 @@ */ final class DiscordBotListPage extends AbstractGridViewPage { + /** + * @inheritDoc + */ + public $neededPermissions = ['admin.discord.canManageConnection']; + + /** + * @inheritDoc + */ public $activeMenuItem = 'wcf.acp.menu.link.configuration.discord.discordBotList'; #[Override] diff --git a/files/lib/acp/page/DiscordWebhookListPage.class.php b/files/lib/acp/page/DiscordWebhookListPage.class.php index c375136..e399910 100644 --- a/files/lib/acp/page/DiscordWebhookListPage.class.php +++ b/files/lib/acp/page/DiscordWebhookListPage.class.php @@ -3,10 +3,9 @@ namespace wcf\acp\page; use Override; -use wcf\data\discord\webhook\DiscordWebhookList; -use wcf\page\SortablePage; -use wcf\system\cache\builder\DiscordGuildChannelsCacheBuilder; -use wcf\system\WCF; +use wcf\page\AbstractGridViewPage; +use wcf\system\gridView\AbstractGridView; +use wcf\system\gridView\admin\DiscordWebhookGridView; /** * Übersicht der erstellten Discord-Webhooks @@ -16,7 +15,7 @@ * @license Freie Lizenz (https://hanashi.dev/freie-lizenz/) * @package WoltLabSuite\Core\Acp\Page */ -class DiscordWebhookListPage extends SortablePage +final class DiscordWebhookListPage extends AbstractGridViewPage { /** * @inheritDoc @@ -28,43 +27,9 @@ class DiscordWebhookListPage extends SortablePage */ public $activeMenuItem = 'wcf.acp.menu.link.configuration.discord.discordWebhookList'; - /** - * @inheritDoc - */ - public $objectListClassName = DiscordWebhookList::class; - - /** - * @inheritDoc - */ - public $defaultSortField = 'webhookID'; - - /** - * @inheritDoc - */ - public $defaultSortOrder = 'ASC'; - - /** - * @inheritDoc - */ - public $validSortFields = ['channelID', 'botID', 'webhookID', 'webhookName', 'webhookTitle', 'webhookTime']; - - protected array $channels = []; - #[Override] - public function readData() + protected function createGridView(): AbstractGridView { - parent::readData(); - - $this->channels = DiscordGuildChannelsCacheBuilder::getInstance()->getData(); - } - - #[Override] - public function assignVariables() - { - parent::assignVariables(); - - WCF::getTPL()->assign([ - 'channels' => $this->channels, - ]); + return new DiscordWebhookGridView(); } } diff --git a/files/lib/bootstrap/dev.hanashi.wsc.discord-api.php b/files/lib/bootstrap/dev.hanashi.wsc.discord-api.php index 395e13f..2a60665 100644 --- a/files/lib/bootstrap/dev.hanashi.wsc.discord-api.php +++ b/files/lib/bootstrap/dev.hanashi.wsc.discord-api.php @@ -8,6 +8,7 @@ use wcf\event\endpoint\ControllerCollecting; use wcf\event\worker\RebuildWorkerCollecting; use wcf\system\endpoint\controller\hanashi\discord\bot\DeleteBot; +use wcf\system\endpoint\controller\hanashi\discord\webhook\DeleteWebhook; use wcf\system\event\EventHandler; use wcf\system\menu\acp\AcpMenuItem; use wcf\system\request\LinkHandler; @@ -84,6 +85,7 @@ static function (RebuildWorkerCollecting $event) { ControllerCollecting::class, static function (ControllerCollecting $event) { $event->register(new DeleteBot()); + $event->register(new DeleteWebhook()); } ); }; diff --git a/files/lib/event/interaction/admin/DiscordWebhookInteractionCollecting.class.php b/files/lib/event/interaction/admin/DiscordWebhookInteractionCollecting.class.php new file mode 100644 index 0000000..0065171 --- /dev/null +++ b/files/lib/event/interaction/admin/DiscordWebhookInteractionCollecting.class.php @@ -0,0 +1,13 @@ +checkPermissions(['admin.discord.canManageWebhooks']); + + $action = new DiscordWebhookAction([$bot], 'delete'); + $action->executeAction(); + + return new JsonResponse([]); + } +} diff --git a/files/lib/system/gridView/admin/DiscordWebhookGridView.class.php b/files/lib/system/gridView/admin/DiscordWebhookGridView.class.php new file mode 100644 index 0000000..fade96e --- /dev/null +++ b/files/lib/system/gridView/admin/DiscordWebhookGridView.class.php @@ -0,0 +1,99 @@ +addColumns([ + GridViewColumn::for('webhookID') + ->label('wcf.global.objectID') + ->sortable(), + GridViewColumn::for('channelID') + ->label('wcf.acp.discordWebhookList.channelID') + ->renderer([ + new class extends DefaultColumnRenderer { + public function render(mixed $value, mixed $context = null): string + { + \assert($context instanceof DiscordWebhook); + + $channels = DiscordGuildChannelsCacheBuilder::getInstance()->getData(); + + if (!isset($channels[$context->botID][$value])) { + return $value; + } + + return \sprintf('%s
(%s)', $channels[$context->botID][$value]['name'], $value); + } + }, + ]) + ->sortable(), + GridViewColumn::for('webhookTitle') + ->label('wcf.acp.discordWebhookList.webhookTitle') + ->titleColumn() + ->sortable() + ->filter(new TextFilter()), + GridViewColumn::for('webhookName') + ->label('wcf.acp.discordWebhookList.webhookName') + ->sortable() + ->filter(new TextFilter()), + GridViewColumn::for('botID') + ->label('wcf.acp.discordBotList.server') + ->renderer([ + new class extends DefaultColumnRenderer { + public function render(mixed $value, mixed $context = null): string + { + \assert($context instanceof DiscordWebhook); + + $bot = $context->getDiscordBot(); + + $content = ''; + if (!empty($bot->guildIcon)) { + $content = \sprintf( + '', + $bot->guildID, + $bot->guildIcon + ); + } + + return $content . $bot->guildName; + } + }, + ]), + GridViewColumn::for('webhookTime') + ->label('wcf.global.date') + ->renderer(new TimeColumnRenderer()) + ->sortable() + ->filter(new TimeFilter()), + ]); + + $provider = new DiscordWebhookInteractions(); + $this->setInteractionProvider($provider); + + $this->setSortField('webhookID'); + $this->setSortOrder('ASC'); + } + + #[Override] + protected function createObjectList(): DatabaseObjectList + { + return new DiscordWebhookList(); + } +} diff --git a/files/lib/system/interaction/admin/DiscordWebhookInteractions.class.php b/files/lib/system/interaction/admin/DiscordWebhookInteractions.class.php new file mode 100644 index 0000000..0055802 --- /dev/null +++ b/files/lib/system/interaction/admin/DiscordWebhookInteractions.class.php @@ -0,0 +1,30 @@ +addInteractions([ + new DeleteInteraction('hanashi/discord/webhook/%s'), + ]); + + EventHandler::getInstance()->fire( + new DiscordWebhookInteractionCollecting($this) + ); + } + + #[Override] + public function getObjectClassName(): string + { + return DiscordBot::class; + } +}