From b18b996468b0ae0a2bee55b7ae170500c43f15e3 Mon Sep 17 00:00:00 2001 From: kyle Date: Sun, 14 Jun 2026 15:06:15 -0700 Subject: [PATCH] refactor(nc_bot_webhooks): rename app display name and logger tags to nc_bot_webhooks and update docs - appinfo/info.xml: Update app `` to `nc_bot_web_hooks`. - lib/NavigationProvider.php: Update navigation entry name to `nc_bot_web_hooks`. - lib/Controller/WebhookController.php: Update all logger tags from `NCbotwebhooks:` to `nc_bot_web_hooks:`. - lib/Cron/ImageCleanup.php: Update logger tag to `nc_bot_web_hooks:`. - lib/Service/TalkService.php: Update all logger tags from `NCbotwebhooks:` to `nc_bot_web_hooks:`. - agent.md: Update references to app name and logger tags. - architecture.md: Update references to app name. - INSTALL.md: Update references to app name and example strings. - README.md: Restructure "Installation" section (split into Initial installation, Updating using git, Local update), add "Debugging" section with diagnostic grep examples, update app name references. --- INSTALL.md | 8 +- README.md | 208 ++++++++++++++++++++++++--- agent.md | 38 ++--- appinfo/info.xml | 2 +- architecture.md | 6 +- lib/Controller/WebhookController.php | 32 ++--- lib/Cron/ImageCleanup.php | 2 +- lib/NavigationProvider.php | 2 +- lib/Service/TalkService.php | 164 ++++++++++----------- 9 files changed, 318 insertions(+), 144 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 53d5185..d45b3fc 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,4 +1,4 @@ -# NCbotwebhooks — Installation Guide +# nc_bot_webhooks — Installation Guide ## Prerequisites @@ -33,7 +33,7 @@ The bot must have admin privileges to list all Talk rooms. Grant admin access: 1. Log in to Nextcloud as **admin** 2. Go to **Settings → talk-bot → Devices & sessions** -3. Click **Add device** and give it a name (e.g., "NCbotwebhooks") +3. Click **Add device** and give it a name (e.g., "nc_bot_webhooks") 4. Copy the generated device password — you'll need this in Step 3 ## Step 2: Install the app @@ -72,7 +72,7 @@ php occ app:enable nc_bot_webhooks ## Step 3: Configure the app 1. Log in to Nextcloud as **admin** -2. Go to **Settings → Admin → NCbotwebhooks** +2. Go to **Settings → Admin → nc_bot_webhooks** 3. **Bot App Password** — Paste the device password you generated in Step 1 4. **Default Sender Name** — Set the name that appears as the message sender (default: "Webhook Bot") 5. **Image Retention** — Set how many days to keep uploaded images (default: 90) @@ -102,7 +102,7 @@ Test with curl: ```bash curl -X POST \ -H "Content-Type: application/json" \ - -d '{"content":"Test message from NCbotwebhooks","username":"CI Bot"}' \ + -d '{"content":"Test message from nc_bot_webhooks","username":"CI Bot"}' \ https://your-nextcloud-server/apps/nc_bot_webhooks/discord-webhook// ``` diff --git a/README.md b/README.md index b280dcd..1d2c606 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,9 @@ Accepts Discord webhook-compatible JSON payloads (embeds, fields, images) and Ap ## Table of Contents - [Installation](#installation) -- [Manual Deployment](#manual-deployment) + - [Initial installation using git](#initial-installation-using-git) + - [Updating using git](#updating-using-git) + - [Local update](#local-update) - [Configuration](#configuration) - [Webhook URLs](#webhook-urls) - [Payload Formats](#payload-formats) @@ -18,6 +20,7 @@ Accepts Discord webhook-compatible JSON payloads (embeds, fields, images) and Ap - [Security](#security) - [Debug Endpoint](#debug-endpoint) - [Logging](#logging) +- [Debugging](#debugging) - [Integrations](#integrations) - [Home Assistant](#home-assistant) - [Troubleshooting](#troubleshooting) @@ -26,18 +29,18 @@ Accepts Discord webhook-compatible JSON payloads (embeds, fields, images) and Ap ## Installation -### 1. Deploy the app +### Initial installation using git ```bash -cd /path/to/nextcloud/apps -cp -r /path/to/nc_bot_webhooks . +cd /path/to/nextcloud/custom_apps +git clone https://github.com/Mr-Newlove/nc_bot_webhooks.git php occ app:enable nc_bot_webhooks ``` -Or upload via the Nextcloud web UI as a ZIP (only the `nc_bot_webhooks` directory, not its parent). - ### 2. Create the bot user +Create a user named `talk-bot` with the display name "Webhook Bot". This can be done via the `occ` CLI or the admin user manager GUI. + ```bash php occ user:add --password-from-env --display-name="Webhook Bot" talk-bot ``` @@ -55,12 +58,12 @@ The bot must have admin privileges to list all Talk rooms. Grant admin access: 1. Log in to Nextcloud as **admin** (or set a password as admin, then log in as talk-bot) 2. Go to **Settings → talk-bot → Devices & sessions** -3. Click **Add device** and give it a name (e.g., "NCbotwebhooks") +3. Click **Add device** and give it a name (e.g., "nc_bot_webhooks") 4. Copy the generated device password — you'll need it in the next step ### 5. Configure the app -Go to **Settings → Admin → NCbotwebhooks**: +Go to **Settings → Admin → nc_bot_webhooks**: 1. **Bot App Password** — paste the app password from step 4 2. **Default Sender Name** — set the name that appears as the message sender (default: "Webhook Bot") @@ -72,15 +75,27 @@ Go to **Settings → Admin → NCbotwebhooks**: --- -## Manual Deployment +### Updating using git + +> **Note:** On a standard TrueNAS Scale Nextcloud Docker install, the app is located at `/var/www/html/custom_apps/nc_bot_webhooks/`. Adjust the paths below to match your deployment. + +```bash +cd /var/www/html/custom_apps/nc_bot_webhooks +git pull +cd /var/www/html +php occ app:disable nc_bot_webhooks +php occ app:enable nc_bot_webhooks +php occ config:app:delete nc_bot_webhooks routes 2>/dev/null || true +php occ maintenance:repair +``` + +--- + +### Local update > **Note:** The paths below are specific to a TrueNAS Scale Nextcloud Docker install. Adjust them to match your deployment. -This section covers updating the app on a running Nextcloud instance using the synced-file workflow. - -**Workflow:** Keep your local development copy synced to your server via the Nextcloud desktop client. Edit files locally, then deploy with the script below. - -### Update script +This workflow is for when you keep your local development copy synced to your server via the Nextcloud desktop client. Edit files locally, then deploy with the script below. ```bash cd /var/www/html @@ -90,7 +105,7 @@ rm -rf /var/www/html/custom_apps/nc_bot_webhooks/* mkdir -p /var/www/html/custom_apps/nc_bot_webhooks # Update from your synced Nextcloud files directory — adjust this path to match your setup. -cp -r "/var/www/html/data//files/TrueNAS configs/Nextcloud Hooker/nc_bot_webhooks/"* /var/www/html/custom_apps/nc_bot_webhooks/ +cp -r "/var/www/html/data//files//nc_bot_webhooks/"* /var/www/html/custom_apps/nc_bot_webhooks/ chown -R www-data:www-data /var/www/html/custom_apps/nc_bot_webhooks chmod -R u+rX,go+rX /var/www/html/custom_apps/nc_bot_webhooks @@ -99,7 +114,6 @@ cd /var/www/html php occ app:enable nc_bot_webhooks php occ config:app:delete nc_bot_webhooks routes 2>/dev/null || true php occ maintenance:repair -clear ``` > **Note:** The path `"/var/www/html/data//files//nc_bot_webhooks/"` is where your Nextcloud user's synced files land on the server (TrueNAS Docker path). Replace `` with your Nextcloud username, and adjust `/nc_bot_webhooks/` to match the directory you are syncing to. @@ -354,7 +368,167 @@ Responses include a `X-Webhook-Status` header: --- -## Troubleshooting +## Debugging + +Enable debug logging by setting the log level to `0` (debug) in your Nextcloud `config.php`: + +```php +'loglevel' => 0, +``` + +Or via `occ`: + +```bash +php occ config:app:set --value=0 core log_level +``` + +The default log file on a TrueNAS Scale Nextcloud Docker install is `/var/www/html/data/nextcloud.log`. Adjust the path if your data directory is elsewhere. + +### Diagnostic grep examples + +Each section below covers a common symptom, what to grep for, and what to look for. + +--- + +#### Webhook endpoint is being hit + +Confirm the webhook URL is receiving traffic: + +```bash +grep 'nc_bot_webhooks: receiveApprise raw request' /var/www/html/data/nextcloud.log +grep 'nc_bot_webhooks: webhook processed successfully' /var/www/html/data/nextcloud.log +``` + +**What to look for:** A `receiveApprise raw request` entry followed by a `webhook processed successfully` entry. If neither appears, the webhook isn't reaching the server (check your Discord/Apprise webhook URL, network routing, or reverse proxy). + +--- + +#### Invalid auth token + +A webhook is being rejected with `401 unauthorized`: + +```bash +grep 'nc_bot_webhooks: invalid auth token for room' /var/www/html/data/nextcloud.log +``` + +**What to look for:** The room token in the log entry. Compare it against the tokens shown in **Settings → Admin → nc_bot_webhooks**. If the token in the webhook URL doesn't match any configured token for that room, the webhook will be rejected. Regenerate the token in the admin settings and update your external service's webhook URL. + +--- + +#### Invalid JSON / malformed payload + +The webhook is being rejected with `400 bad_request`: + +```bash +grep 'nc_bot_webhooks: invalid JSON from webhook' /var/www/html/data/nextcloud.log +grep 'nc_bot_webhooks: invalid payload from apprise webhook' /var/www/html/data/nextcloud.log +``` + +**What to look for:** The parsed payload snippet in the log entry. Verify the JSON structure matches the [Discord Webhook Format](#discord-webhook-format) or [Apprise Format](#apprise-format) documented above. + +--- + +#### Message not appearing in Talk + +The webhook succeeded but the message didn't show up in the Talk room: + +```bash +grep 'nc_bot_webhooks: failed to post.*message to Talk' /var/www/html/data/nextcloud.log +grep 'nc_bot_webhooks: webhook processed successfully' /var/www/html/data/nextcloud.log +``` + +**What to look for:** +- If you see `failed to post.*message to Talk`, the app couldn't reach the Talk Chat API. Check that the bot user has an app password configured and that the bot is a participant in the target room. +- If you see `webhook processed successfully` but no error, the message was posted but Talk may have silently dropped it. Verify the bot user is listed as a participant in the Talk room. + +--- + +#### Image download/upload fails + +Images from webhooks aren't appearing inline: + +```bash +grep 'nc_bot_webhooks: Failed to download image' /var/www/html/data/nextcloud.log +grep 'nc_bot_webhooks: Failed to upload image' /var/www/html/data/nextcloud.log +grep 'nc_bot_webhooks: uploadImage — bot user not found' /var/www/html/data/nextcloud.log +grep 'nc_bot_webhooks: image processing failed' /var/www/html/data/nextcloud.log +``` + +**What to look for:** +- `Failed to download image` — the source URL is unreachable, blocked by local address filtering, or returned an error. Verify the image URL is publicly accessible. +- `Failed to upload image` — check the error message for details (quota exceeded, filesystem error, etc.). +- `uploadImage — bot user not found` — the `talk-bot` user doesn't exist. Re-run Step 2 of installation. +- `image processing failed` — image download succeeded but upload failed. Check the bot user's storage quota and permissions. + +--- + +#### Bot user not found + +Errors referencing the `talk-bot` user: + +```bash +grep 'nc_bot_webhooks: uploadImage — bot user not found' /var/www/html/data/nextcloud.log +``` + +**What to look for:** This confirms the `talk-bot` user doesn't exist in Nextcloud. Create it via `php occ user:add --password-from-env talk-bot` (Step 2 of installation). + +--- + +#### Config save fails + +Admin settings not saving: + +```bash +grep 'nc_bot_webhooks: saveConfig failed' /var/www/html/data/nextcloud.log +``` + +**What to look for:** The error message from the crypto layer. Common causes include an invalid bot password (contains characters that break encryption) or a misconfigured Nextcloud crypto backend. + +--- + +#### Room listing empty + +The "Fetch Rooms" button returns no rooms: + +```bash +grep 'nc_bot_webhooks: getAvailableTalkRooms' /var/www/html/data/nextcloud.log +grep 'nc_bot_webhooks: found.*rooms' /var/www/html/data/nextcloud.log +grep 'nc_bot_webhooks: room listing exception' /var/www/html/data/nextcloud.log +``` + +**What to look for:** +- `found 0 rooms` — the bot user may not have admin privileges. Re-grant admin access (Step 3 of installation). +- `room listing exception` — check the exception details for the root cause (Talk app not installed, database error, etc.). + +--- + +#### Image cleanup cron not running + +Images are not being purged after the retention period: + +```bash +grep 'nc_bot_webhooks: ImageCleanup' /var/www/html/data/nextcloud.log +``` + +**What to look for:** A log entry each time the cron job runs. If nothing appears, ensure system cron is configured to run `php occ cron.php` (not the "Web" cron setting in Admin settings). Check the Nextcloud system cron status: + +```bash +php occ system:cron:set --method=cron +``` + +--- + +#### Payload mapping inspection + +See exactly how the webhook payload was mapped to Talk format (verbose): + +```bash +grep 'nc_bot_webhooks: DEBUG mapped' /var/www/html/data/nextcloud.log +``` + +**What to look for:** The full mapped payload JSON. This is useful when a message appears incorrectly in Talk — compare the mapped payload against the expected Talk Chat API format. + +> **Note:** Debug logging is verbose and impacts performance. After troubleshooting, restore your log level to `2` (warning) or higher. | Problem | Solution | |---|---| diff --git a/agent.md b/agent.md index 1b7a77c..ef3a2a1 100644 --- a/agent.md +++ b/agent.md @@ -1,4 +1,4 @@ -# NCbotwebhooks — Maintenance Reference +# nc_bot_webhooks — Maintenance Reference Complete maintenance reference for the `nc_bot_webhooks` Nextcloud app. Covers every file, API interaction, data flow, design decision, and operational detail. @@ -61,7 +61,7 @@ nc_bot_webhooks/ **Key paths at runtime:** - Web URL base: `/apps/nc_bot_webhooks/` -- Admin settings path: `Settings → Admin → NCbotwebhooks` +- Admin settings path: `Settings → Admin → nc_bot_webhooks` - Bot user: `talk-bot` (must exist and be admin) - Image storage: `/nc_bot_webhooks-images//` under `talk-bot`'s personal files @@ -430,7 +430,7 @@ Admin settings form handler. Implements `ISettings`. ### lib/NavigationProvider.php -Implements `INavigationProvider`. Adds "NCbotwebhooks" entry to admin settings navigation. +Implements `INavigationProvider`. Adds "nc_bot_webhooks" entry to admin settings navigation. **Admin-only:** returns empty array if user is not admin. @@ -440,7 +440,7 @@ Implements `INavigationProvider`. Adds "NCbotwebhooks" entry to admin settings n 'id' => 'nc_bot_webhooks', 'app_id' => 'nc_bot_webhooks', 'type' => 'settings', - 'name' => 'NCbotwebhooks', + 'name' => 'nc_bot_webhooks', 'href' => linkToRoute('settings.AdminSettings#index'), 'icon' => imagePath('nc_bot_webhooks', 'app.svg'), 'order' => 0, @@ -573,7 +573,7 @@ Route definitions. All webhook routes use `{roomToken}` and `{token}` path param ```xml nc_bot_webhooks -NCbotwebhooks +nc_bot_webhooks Discord webhook bridge for Nextcloud Talk with image support Accepts Discord webhook-style JSON payloads and posts them into Nextcloud Talk rooms, preserving image attachments. 1.1.0 @@ -974,12 +974,12 @@ cp -r nc_bot_webhooks /path/to/nextcloud/apps/ # 5. Enable app php occ app:enable nc_bot_webhooks -# 6. Configure via web UI (Settings → Admin → NCbotwebhooks) +# 6. Configure via web UI (Settings → Admin → nc_bot_webhooks) ``` ### Configuring Rooms -1. Go to Settings → Admin → NCbotwebhooks +1. Go to Settings → Admin → nc_bot_webhooks 2. Enter bot app password 3. Click "Fetch Rooms" to list available Talk rooms 4. Check rooms to enable webhooks for @@ -1019,7 +1019,7 @@ UPDATE oc_appconfig SET appid = 'nc_bot_webhooks' WHERE appid = 'ncdiscordhook'; php occ background:cron ``` -**Adjust retention:** Settings → Admin → NCbotwebhooks → Image Retention (1-365 days) +**Adjust retention:** Settings → Admin → nc_bot_webhooks → Image Retention (1-365 days) **Check images directory:** ```bash @@ -1074,21 +1074,21 @@ These public methods on `TalkService` are available for programmatic debugging: ### Log Tags All log entries use: -- Logger tag: `'NCbotwebhooks:'` +- Logger tag: `'nc_bot_webhooks:'` - App tag: `'app' => 'nc_bot_webhooks'` Example log entries: ``` -NCbotwebhooks: webhook processed successfully -NCbotwebhooks: failed to post webhook message to Talk -NCbotwebhooks: message posted to room ABC123 -NCbotwebhooks: bot password not configured -NCbotwebhooks: bot not enabled for room -NCbotwebhooks: base URL not configured -NCbotwebhooks: getAvailableTalkRooms -NCbotwebhooks: found 5 rooms -NCbotwebhooks: purgeOldImages -NCbotwebhooks: purged 3 old image files +nc_bot_webhooks: webhook processed successfully +nc_bot_webhooks: failed to post webhook message to Talk +nc_bot_webhooks: message posted to room ABC123 +nc_bot_webhooks: bot password not configured +nc_bot_webhooks: bot not enabled for room +nc_bot_webhooks: base URL not configured +nc_bot_webhooks: getAvailableTalkRooms +nc_bot_webhooks: found 5 rooms +nc_bot_webhooks: purgeOldImages +nc_bot_webhooks: purged 3 old image files ``` --- diff --git a/appinfo/info.xml b/appinfo/info.xml index e3b0988..eb7228c 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -2,7 +2,7 @@ nc_bot_webhooks - NCbotwebhooks + nc_bot_webhooks Discord webhook bridge for Nextcloud Talk with image support Accepts Discord webhook-style JSON payloads and posts them into Nextcloud Talk rooms, preserving image attachments. Each room gets its own webhook URL with an auth token for security. 1.1.0 diff --git a/architecture.md b/architecture.md index de08a09..f6c0039 100644 --- a/architecture.md +++ b/architecture.md @@ -1,6 +1,6 @@ # Architecture -Overview of how NCbotwebhooks functions, its components, data flow, design decisions, and security model. +Overview of how nc_bot_webhooks functions, its components, data flow, design decisions, and security model. ## Table of Contents @@ -17,7 +17,7 @@ Overview of how NCbotwebhooks functions, its components, data flow, design decis ## High-Level Overview -NCbotwebhooks is a Nextcloud app that acts as a webhook bridge. External services (CI/CD pipelines, monitoring tools, Apprise notification gateways) send webhook payloads to the app, which validates the request, maps the payload to Nextcloud Talk's Chat API format, and posts the message as the `talk-bot` user into the target Talk room. +nc_bot_webhooks is a Nextcloud app that acts as a webhook bridge. External services (CI/CD pipelines, monitoring tools, Apprise notification gateways) send webhook payloads to the app, which validates the request, maps the payload to Nextcloud Talk's Chat API format, and posts the message as the `talk-bot` user into the target Talk room. ``` External Service ──► /discord-webhook/{room}/{token} ──┐ @@ -66,7 +66,7 @@ Each Talk room gets its own webhook URL with a unique auth token. Multiple token | Class | Responsibility | |---|---| | `Admin` | ISettings implementation — loads template, injects config, declares CSS/JS assets | -| `NavigationProvider` | INavigationProvider — adds "NCbotwebhooks" entry to admin settings navigation | +| `NavigationProvider` | INavigationProvider — adds "nc_bot_webhooks" entry to admin settings navigation | ### Frontend diff --git a/lib/Controller/WebhookController.php b/lib/Controller/WebhookController.php index 580fd1c..ebe257b 100644 --- a/lib/Controller/WebhookController.php +++ b/lib/Controller/WebhookController.php @@ -54,7 +54,7 @@ class WebhookController extends Controller { public function receive(string $roomToken, string $token): DataResponse { // Validate auth token if (!$this->talkService->validateAuthToken($roomToken, $token)) { - $this->logger->warning('NCbotwebhooks: invalid auth token for room', [ + $this->logger->warning('nc_bot_webhooks: invalid auth token for room', [ 'app' => 'nc_bot_webhooks', 'room_token' => $roomToken, ]); @@ -76,7 +76,7 @@ class WebhookController extends Controller { } } if (json_last_error() !== JSON_ERROR_NONE || !is_array($data)) { - $this->logger->warning('NCbotwebhooks: invalid JSON from webhook', [ + $this->logger->warning('nc_bot_webhooks: invalid JSON from webhook', [ 'app' => 'nc_bot_webhooks', 'room_token' => $roomToken, 'body_length' => strlen($body), @@ -168,7 +168,7 @@ class WebhookController extends Controller { } } catch (\Exception $e) { $imageError = $e->getMessage(); - $this->logger->error('NCbotwebhooks: image processing failed, continuing without images', [ + $this->logger->error('nc_bot_webhooks: image processing failed, continuing without images', [ 'app' => 'nc_bot_webhooks', 'room_token' => $roomToken, 'error' => $e->getMessage(), @@ -187,7 +187,7 @@ class WebhookController extends Controller { for ($i = 0; $i < count($fileNames); $i++) { if ($fileErrors[$i] !== UPLOAD_ERR_OK) { - $this->logger->warning('NCbotwebhooks: file upload error for attachment ' . $i, [ + $this->logger->warning('nc_bot_webhooks: file upload error for attachment ' . $i, [ 'app' => 'nc_bot_webhooks', 'error_code' => $fileErrors[$i], ]); @@ -199,7 +199,7 @@ class WebhookController extends Controller { $fileData = file_get_contents($fileTmps[$i]); if ($fileData === false || strlen($fileData) === 0) { - $this->logger->warning('NCbotwebhooks: empty or unreadable file attachment ' . $i, [ + $this->logger->warning('nc_bot_webhooks: empty or unreadable file attachment ' . $i, [ 'app' => 'nc_bot_webhooks', 'tmp_name' => $fileTmps[$i], ]); @@ -220,7 +220,7 @@ class WebhookController extends Controller { $success = $this->talkService->postToRoom($roomToken, $message, $senderName, $richObjects); if ($success) { - $this->logger->info('NCbotwebhooks: webhook processed successfully', [ + $this->logger->info('nc_bot_webhooks: webhook processed successfully', [ 'app' => 'nc_bot_webhooks', 'room_token' => $roomToken, ]); @@ -231,7 +231,7 @@ class WebhookController extends Controller { ); } - $this->logger->error('NCbotwebhooks: failed to post webhook message to Talk', [ + $this->logger->error('nc_bot_webhooks: failed to post webhook message to Talk', [ 'app' => 'nc_bot_webhooks', 'room_token' => $roomToken, ]); @@ -262,7 +262,7 @@ class WebhookController extends Controller { public function receiveApprise(string $roomToken, string $token): DataResponse { // Validate auth token if (!$this->talkService->validateAuthToken($roomToken, $token)) { - $this->logger->warning('NCbotwebhooks: invalid auth token for room', [ + $this->logger->warning('nc_bot_webhooks: invalid auth token for room', [ 'app' => 'nc_bot_webhooks', 'room_token' => $roomToken, ]); @@ -292,7 +292,7 @@ class WebhookController extends Controller { $preview = substr($body, 0, 2000); // Sanitize binary data from preview to avoid corrupting logs $preview = preg_replace('/[^\x20-\x7E\x0A\x0D\x09]/', '.', $preview); - $this->logger->info('NCbotwebhooks: receiveApprise raw request', [ + $this->logger->info('nc_bot_webhooks: receiveApprise raw request', [ 'app' => 'nc_bot_webhooks', 'room_token' => $roomToken, 'content_type' => $contentType, @@ -356,7 +356,7 @@ class WebhookController extends Controller { } if (empty($data) || !is_array($data)) { - $this->logger->warning('NCbotwebhooks: invalid payload from apprise webhook', [ + $this->logger->warning('nc_bot_webhooks: invalid payload from apprise webhook', [ 'app' => 'nc_bot_webhooks', 'room_token' => $roomToken, 'content_type' => $contentType, @@ -432,7 +432,7 @@ class WebhookController extends Controller { $mapped = $this->talkService->mapApprisePayload($data, $roomToken); } catch (\Exception $e) { $imageError = $e->getMessage(); - $this->logger->error('NCbotwebhooks: image processing failed, continuing without images', [ + $this->logger->error('nc_bot_webhooks: image processing failed, continuing without images', [ 'app' => 'nc_bot_webhooks', 'room_token' => $roomToken, 'error' => $e->getMessage(), @@ -450,7 +450,7 @@ class WebhookController extends Controller { } // DEBUG: log mapped values - $this->logger->info('NCbotwebhooks: DEBUG mapped', [ + $this->logger->info('nc_bot_webhooks: DEBUG mapped', [ 'app' => 'nc_bot_webhooks', 'message' => $mapped['message'] ?? 'EMPTY', 'senderName' => $mapped['senderName'] ?? 'EMPTY', @@ -480,7 +480,7 @@ class WebhookController extends Controller { $success = $this->talkService->postToRoom($roomToken, $message, $senderName, $richObjects); if ($success) { - $this->logger->info('NCbotwebhooks: apprise webhook processed successfully', [ + $this->logger->info('nc_bot_webhooks: apprise webhook processed successfully', [ 'app' => 'nc_bot_webhooks', 'room_token' => $roomToken, ]); @@ -491,7 +491,7 @@ class WebhookController extends Controller { ); } - $this->logger->error('NCbotwebhooks: failed to post apprise message to Talk', [ + $this->logger->error('nc_bot_webhooks: failed to post apprise message to Talk', [ 'app' => 'nc_bot_webhooks', 'room_token' => $roomToken, ]); @@ -567,7 +567,7 @@ class WebhookController extends Controller { try { $this->talkService->saveConfig($config); } catch (\Exception $e) { - $this->logger->error('NCbotwebhooks: saveConfig failed: ' . $e->getMessage(), [ + $this->logger->error('nc_bot_webhooks: saveConfig failed: ' . $e->getMessage(), [ 'app' => 'nc_bot_webhooks', 'exception' => (string)$e, ]); @@ -1118,7 +1118,7 @@ class WebhookController extends Controller { return new DataResponse($result); } catch (\Exception $e) { - $this->logger->error('NCbotwebhooks getRooms failed: ' . $e->getMessage(), ['app' => 'nc_bot_webhooks', 'exception' => (string)$e]); + $this->logger->error('nc_bot_webhooks getRooms failed: ' . $e->getMessage(), ['app' => 'nc_bot_webhooks', 'exception' => (string)$e]); return new DataResponse( ['error' => 'Server error: ' . $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR, diff --git a/lib/Cron/ImageCleanup.php b/lib/Cron/ImageCleanup.php index d6009aa..d2f4834 100644 --- a/lib/Cron/ImageCleanup.php +++ b/lib/Cron/ImageCleanup.php @@ -51,7 +51,7 @@ class ImageCleanup implements IJob { if ($count > 0) { $this->logger->info( - 'NCbotwebhooks: purged ' . $count . ' old image files', + 'nc_bot_webhooks: purged ' . $count . ' old image files', ['app' => 'nc_bot_webhooks'], ); } diff --git a/lib/NavigationProvider.php b/lib/NavigationProvider.php index a97103c..94f675b 100644 --- a/lib/NavigationProvider.php +++ b/lib/NavigationProvider.php @@ -27,7 +27,7 @@ class NavigationProvider implements INavigationProvider { 'id' => 'nc_bot_webhooks', 'app_id' => 'nc_bot_webhooks', 'type' => 'settings', - 'name' => $this->l10n->t('NCbotwebhooks'), + 'name' => $this->l10n->t('nc_bot_webhooks'), 'href' => $this->urlGenerator->linkToRoute('settings.AdminSettings#index'), 'icon' => $this->urlGenerator->imagePath('nc_bot_webhooks', 'app.svg'), 'order' => 0, diff --git a/lib/Service/TalkService.php b/lib/Service/TalkService.php index 1894448..48c63ae 100644 --- a/lib/Service/TalkService.php +++ b/lib/Service/TalkService.php @@ -295,7 +295,7 @@ class TalkService { if ($roomTable === null) { $sysPrefix = $this->config->getSystemValueString('dbtableprefix', ''); $talkPrefix = $this->config->getAppValue('spreed', 'databaseprefix', $sysPrefix); - $this->logger->warning('NCbotwebhooks: Talk tables not found', [ + $this->logger->warning('nc_bot_webhooks: Talk tables not found', [ 'app' => self::APP_ID, 'sysPrefix' => $sysPrefix, 'talkPrefix' => $talkPrefix, @@ -317,7 +317,7 @@ class TalkService { AND name NOT LIKE \'["%\''; $result = $this->db->executeQuery($sql); } catch (\Exception $e) { - $this->logger->warning('NCbotwebhooks: room name query failed, using token fallback', [ + $this->logger->warning('nc_bot_webhooks: room name query failed, using token fallback', [ 'app' => self::APP_ID, 'error' => $e->getMessage(), ]); @@ -331,7 +331,7 @@ class TalkService { $result = $this->db->executeQuery($sql); } - $this->logger->info('NCbotwebhooks: getAvailableTalkRooms', [ + $this->logger->info('nc_bot_webhooks: getAvailableTalkRooms', [ 'app' => self::APP_ID, 'room_table' => $roomTable, ]); @@ -343,14 +343,14 @@ class TalkService { } $result->closeCursor(); - $this->logger->info('NCbotwebhooks: found ' . count($rooms) . ' rooms', [ + $this->logger->info('nc_bot_webhooks: found ' . count($rooms) . ' rooms', [ 'app' => self::APP_ID, 'rooms' => array_keys($rooms), ]); return $rooms; } catch (\Exception $e) { - $this->logger->error('NCbotwebhooks: room listing exception', [ + $this->logger->error('nc_bot_webhooks: room listing exception', [ 'app' => self::APP_ID, 'error' => $e->getMessage(), 'file' => $e->getFile(), @@ -447,7 +447,7 @@ class TalkService { } $result->closeCursor(); } catch (\Exception $e) { - $this->logger->warning('NCbotwebhooks: information_schema query failed', [ + $this->logger->warning('nc_bot_webhooks: information_schema query failed', [ 'app' => self::APP_ID, 'error' => $e->getMessage(), ]); @@ -671,7 +671,7 @@ class TalkService { * Returns: { message, senderName, richObjects } */ public function mapApprisePayload(array $data, string $roomToken = ''): array { - $this->logger->info('NCbotwebhooks: mapApprisePayload input', [ + $this->logger->info('nc_bot_webhooks: mapApprisePayload input', [ 'app' => self::APP_ID, 'type' => $data['type'] ?? 'none', 'has_attachments' => !empty($data['attachments']), @@ -782,7 +782,7 @@ class TalkService { } $filePath = $attachment['path'] ?? ''; - $this->logger->info('NCbotwebhooks: attachment path', [ + $this->logger->info('nc_bot_webhooks: attachment path', [ 'app' => self::APP_ID, 'path' => $filePath, 'url_key' => $attachment['url'] ?? 'none', @@ -918,14 +918,14 @@ class TalkService { $body = $response->getBody(); $statusCode = $response->getStatusCode(); - $this->logger->info('NCbotwebhooks: image download response', [ + $this->logger->info('nc_bot_webhooks: image download response', [ 'app' => self::APP_ID, 'url' => $url, 'status_code' => $statusCode, 'body_length' => strlen($body), ]); if (strlen($body) === 0) { - $this->logger->warning('NCbotwebhooks: image download returned empty body', [ + $this->logger->warning('nc_bot_webhooks: image download returned empty body', [ 'app' => self::APP_ID, 'url' => $url, 'status_code' => $statusCode, @@ -935,7 +935,7 @@ class TalkService { return ['data' => $body, 'mimeType' => $mimeType]; } catch (\Exception $e) { - $this->logger->warning('NCbotwebhooks: Failed to download image: ' . $url . ' — ' . $e->getMessage(), ['app' => self::APP_ID]); + $this->logger->warning('nc_bot_webhooks: Failed to download image: ' . $url . ' — ' . $e->getMessage(), ['app' => self::APP_ID]); return null; } } @@ -948,12 +948,12 @@ class TalkService { public function uploadImage(string $roomToken, string $filename, string $data, string $mimeType): ?string { $bot = $this->userManager->get('talk-bot'); if (!$bot) { - $this->logger->error('NCbotwebhooks: uploadImage — bot user not found', ['app' => self::APP_ID]); + $this->logger->error('nc_bot_webhooks: uploadImage — bot user not found', ['app' => self::APP_ID]); return null; } try { - $this->logger->info('NCbotwebhooks: uploadImage start', [ + $this->logger->info('nc_bot_webhooks: uploadImage start', [ 'app' => self::APP_ID, 'roomToken' => $roomToken, 'filename' => $filename, @@ -961,7 +961,7 @@ class TalkService { 'bot_uid' => $bot->getUID(), ]); $userFolder = $this->rootFolder->getUserFolder($bot->getUID()); - $this->logger->info('NCbotwebhooks: getUserFolder succeeded', [ + $this->logger->info('nc_bot_webhooks: getUserFolder succeeded', [ 'app' => self::APP_ID, 'userFolder_type' => get_class($userFolder), ]); @@ -970,19 +970,19 @@ class TalkService { $imagesDir = null; try { $imagesDir = $userFolder->get(self::IMAGES_DIR); - $this->logger->info('NCbotwebhooks: images dir already exists', [ + $this->logger->info('nc_bot_webhooks: images dir already exists', [ 'app' => self::APP_ID, 'path' => self::IMAGES_DIR, ]); } catch (\OCP\Files\NotFoundException $e) { - $this->logger->info('NCbotwebhooks: creating images dir', [ + $this->logger->info('nc_bot_webhooks: creating images dir', [ 'app' => self::APP_ID, 'path' => self::IMAGES_DIR, ]); $userFolder->newFolder(self::IMAGES_DIR); $imagesDir = $userFolder->get(self::IMAGES_DIR); } catch (\Error $e) { - $this->logger->error('NCbotwebhooks: get threw Error on images dir: ' . $e->getMessage(), [ + $this->logger->error('nc_bot_webhooks: get threw Error on images dir: ' . $e->getMessage(), [ 'app' => self::APP_ID, 'path' => self::IMAGES_DIR, 'exception' => get_class($e), @@ -994,12 +994,12 @@ class TalkService { $roomDir = null; try { $roomDir = $imagesDir->get($roomToken); - $this->logger->info('NCbotwebhooks: room dir already exists', [ + $this->logger->info('nc_bot_webhooks: room dir already exists', [ 'app' => self::APP_ID, 'path' => $roomToken, ]); } catch (\OCP\Files\NotFoundException $e) { - $this->logger->info('NCbotwebhooks: creating room dir', [ + $this->logger->info('nc_bot_webhooks: creating room dir', [ 'app' => self::APP_ID, 'parent' => self::IMAGES_DIR, 'path' => $roomToken, @@ -1007,7 +1007,7 @@ class TalkService { $imagesDir->newFolder($roomToken); $roomDir = $imagesDir->get($roomToken); } catch (\Error $e) { - $this->logger->error('NCbotwebhooks: get threw Error on room dir: ' . $e->getMessage(), [ + $this->logger->error('nc_bot_webhooks: get threw Error on room dir: ' . $e->getMessage(), [ 'app' => self::APP_ID, 'parent' => self::IMAGES_DIR, 'path' => $roomToken, @@ -1023,13 +1023,13 @@ class TalkService { $timestamp = date('Y-m-d H.i.s') . '.' . sprintf('%06d', (int)(microtime(true) * 1000) % 1000000); $relativePath = 'talk-bot ' . $timestamp . '_' . $base . '.' . $ext; - $this->logger->info('NCbotwebhooks: writing file', [ + $this->logger->info('nc_bot_webhooks: writing file', [ 'app' => self::APP_ID, 'original' => $safeFilename, 'path' => $relativePath, ]); $roomDir->newFile($relativePath, $data); - $this->logger->info('NCbotwebhooks: file written successfully', [ + $this->logger->info('nc_bot_webhooks: file written successfully', [ 'app' => self::APP_ID, 'path' => self::IMAGES_DIR . '/' . $roomToken . '/' . $relativePath, ]); @@ -1048,21 +1048,21 @@ class TalkService { $stmtFc->execute([self::IMAGES_DIR . '/' . $roomToken . '/' . $relativePath]); $fcRow = $stmtFc->fetchAll(\PDO::FETCH_ASSOC); $stmtFc->closeCursor(); - $this->logger->info('NCbotwebhooks: uploadImage filecache check', [ + $this->logger->info('nc_bot_webhooks: uploadImage filecache check', [ 'app' => self::APP_ID, 'found' => count($fcRow) > 0, 'entries' => $fcRow, ]); } catch (\Throwable $e) { - $this->logger->warning('NCbotwebhooks: uploadImage filecache check failed: ' . $e->getMessage(), ['app' => self::APP_ID]); + $this->logger->warning('nc_bot_webhooks: uploadImage filecache check failed: ' . $e->getMessage(), ['app' => self::APP_ID]); } return self::IMAGES_DIR . '/' . $roomToken . '/' . $relativePath; } catch (\Error $e) { - $this->logger->error('NCbotwebhooks: uploadImage Error: ' . $e->getMessage() . ' at ' . $e->getFile() . ':' . $e->getLine(), ['app' => self::APP_ID]); + $this->logger->error('nc_bot_webhooks: uploadImage Error: ' . $e->getMessage() . ' at ' . $e->getFile() . ':' . $e->getLine(), ['app' => self::APP_ID]); return null; } catch (\Exception $e) { - $this->logger->error('NCbotwebhooks: Failed to upload image: ' . $e->getMessage(), ['app' => self::APP_ID]); + $this->logger->error('nc_bot_webhooks: Failed to upload image: ' . $e->getMessage(), ['app' => self::APP_ID]); return null; } } @@ -1080,25 +1080,25 @@ class TalkService { * Creates a public link share so Talk can resolve the rich object. */ public function buildRichObject(string $filePath, string $mimeType, string $roomToken): ?array { - $this->logger->info('NCbotwebhooks: buildRichObject ENTER', ['app' => self::APP_ID, 'filePath' => $filePath, 'roomToken' => $roomToken]); + $this->logger->info('nc_bot_webhooks: buildRichObject ENTER', ['app' => self::APP_ID, 'filePath' => $filePath, 'roomToken' => $roomToken]); $bot = $this->userManager->get('talk-bot'); if (!$bot) { - $this->logger->info('NCbotwebhooks: buildRichObject EXIT noBot', ['app' => self::APP_ID]); + $this->logger->info('nc_bot_webhooks: buildRichObject EXIT noBot', ['app' => self::APP_ID]); return null; } try { $safeFilename = basename($filePath); - $this->logger->info('NCbotwebhooks: richObject step=basename', ['app' => self::APP_ID]); + $this->logger->info('nc_bot_webhooks: richObject step=basename', ['app' => self::APP_ID]); // filePath is the full filecache path returned by uploadImage (e.g. nc_bot_webhooks-images/abc123/talk-bot 2026-06-13 01.35.19.123456_filename.png). $fileCachePath = $filePath; - $this->logger->info('NCbotwebhooks: richObject step=buildPath', ['app' => self::APP_ID, 'path' => $fileCachePath]); + $this->logger->info('nc_bot_webhooks: richObject step=buildPath', ['app' => self::APP_ID, 'path' => $fileCachePath]); // Use PDO directly to avoid any DBConnection method that could trigger lazy init. - $this->logger->info('NCbotwebhooks: richObject step=getPdo', ['app' => self::APP_ID]); + $this->logger->info('nc_bot_webhooks: richObject step=getPdo', ['app' => self::APP_ID]); $pdo = $this->db->getInner()->getNativeConnection(); - $this->logger->info('NCbotwebhooks: richObject step=pdoOk', ['app' => self::APP_ID]); + $this->logger->info('nc_bot_webhooks: richObject step=pdoOk', ['app' => self::APP_ID]); // Get table prefix from system config (safe — no DB abstraction layer). $prefix = $this->config->getSystemValueString('dbtableprefix', 'oc_'); @@ -1113,7 +1113,7 @@ class TalkService { $fileCacheTable = $prefix . 'filecache'; $shareTable = $prefix . 'share'; - $this->logger->info('NCbotwebhooks: richObject step=tables', ['app' => self::APP_ID, 'filecache' => $fileCacheTable, 'share' => $shareTable]); + $this->logger->info('nc_bot_webhooks: richObject step=tables', ['app' => self::APP_ID, 'filecache' => $fileCacheTable, 'share' => $shareTable]); // Resolve the bot user's home storage ID from the storages table. // Storage IDs are instance-specific; hardcoding '1' breaks on many setups. @@ -1124,29 +1124,29 @@ class TalkService { $stmt->execute(['home::' . $bot->getUID()]); $storageId = (int)$stmt->fetch(\PDO::FETCH_COLUMN); $stmt->closeCursor(); - $this->logger->info('NCbotwebhooks: richObject step=storageId', ['app' => self::APP_ID, 'storageId' => $storageId]); + $this->logger->info('nc_bot_webhooks: richObject step=storageId', ['app' => self::APP_ID, 'storageId' => $storageId]); } catch (\Throwable $e) { - $this->logger->warning('NCbotwebhooks: richObject step=storageIdFail', ['app' => self::APP_ID, 'error' => $e->getMessage()]); + $this->logger->warning('nc_bot_webhooks: richObject step=storageIdFail', ['app' => self::APP_ID, 'error' => $e->getMessage()]); } - $this->logger->info('NCbotwebhooks: richObject step=prepareSelect', ['app' => self::APP_ID]); + $this->logger->info('nc_bot_webhooks: richObject step=prepareSelect', ['app' => self::APP_ID]); $stmt = $pdo->prepare( 'SELECT fileid, path, mimetype, permissions, size, storage' . ' FROM "' . $fileCacheTable . '"' . ' WHERE "path_hash" = ?', ); $pathHash = md5($fileCachePath); - $this->logger->info('NCbotwebhooks: richObject step=executeSelect', ['app' => self::APP_ID, 'pathHash' => $pathHash, 'path' => $fileCachePath]); + $this->logger->info('nc_bot_webhooks: richObject step=executeSelect', ['app' => self::APP_ID, 'pathHash' => $pathHash, 'path' => $fileCachePath]); $stmt->execute([$pathHash]); - $this->logger->info('NCbotwebhooks: richObject step=fetch', ['app' => self::APP_ID]); + $this->logger->info('nc_bot_webhooks: richObject step=fetch', ['app' => self::APP_ID]); $row = $stmt->fetch(\PDO::FETCH_ASSOC); $stmt->closeCursor(); - $this->logger->info('NCbotwebhooks: richObject step=rowFetched', ['app' => self::APP_ID, 'found' => $row !== false, 'columns' => array_keys($row ?: []), 'data' => $row]); + $this->logger->info('nc_bot_webhooks: richObject step=rowFetched', ['app' => self::APP_ID, 'found' => $row !== false, 'columns' => array_keys($row ?: []), 'data' => $row]); // Path-based fallback: if path_hash lookup found nothing, try LIKE match on path column. // This catches cases where the filecache entry exists but path_hash didn't match. if (!$row) { - $this->logger->info('NCbotwebhooks: richObject step=pathFallback', ['app' => self::APP_ID, 'path' => $fileCachePath]); + $this->logger->info('nc_bot_webhooks: richObject step=pathFallback', ['app' => self::APP_ID, 'path' => $fileCachePath]); $stmt2 = $pdo->prepare( 'SELECT fileid, path, mimetype, permissions, size, storage' . ' FROM "' . $fileCacheTable . '"' @@ -1155,11 +1155,11 @@ class TalkService { $stmt2->execute([self::IMAGES_DIR . '/%']); $rows = $stmt2->fetchAll(\PDO::FETCH_ASSOC); $stmt2->closeCursor(); - $this->logger->info('NCbotwebhooks: richObject step=pathFallbackRows', ['app' => self::APP_ID, 'count' => count($rows)]); + $this->logger->info('nc_bot_webhooks: richObject step=pathFallbackRows', ['app' => self::APP_ID, 'count' => count($rows)]); foreach ($rows as $r) { if ($r['path'] === $fileCachePath) { $row = $r; - $this->logger->info('NCbotwebhooks: richObject step=pathFallbackMatch', ['app' => self::APP_ID, 'fileId' => $r['fileid']]); + $this->logger->info('nc_bot_webhooks: richObject step=pathFallbackMatch', ['app' => self::APP_ID, 'fileId' => $r['fileid']]); break; } } @@ -1168,7 +1168,7 @@ class TalkService { if (!$row) { // Manual filecache insertion — the file exists on disk but the entry is missing. // This can happen if the scanner didn't run or the entry was deleted. - $this->logger->warning('NCbotwebhooks: richObject step=insertFc', ['app' => self::APP_ID, 'path' => $fileCachePath, 'storageId' => $storageId]); + $this->logger->warning('nc_bot_webhooks: richObject step=insertFc', ['app' => self::APP_ID, 'path' => $fileCachePath, 'storageId' => $storageId]); try { // Look up mimetype ID from the mimetype lookup table. // In NC33, mimetype is a bigint (ID), not a string. @@ -1228,9 +1228,9 @@ class TalkService { \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE, ]); $fileId = (int)$pdo->lastInsertId($prefix . 'filecache_fileid_seq'); - $this->logger->info('NCbotwebhooks: richObject step=fcInserted', ['app' => self::APP_ID, 'fileId' => $fileId]); + $this->logger->info('nc_bot_webhooks: richObject step=fcInserted', ['app' => self::APP_ID, 'fileId' => $fileId]); } catch (\Throwable $e) { - $this->logger->error('NCbotwebhooks: richObject step=fcInsertFail', ['app' => self::APP_ID, 'error' => $e->getMessage()]); + $this->logger->error('nc_bot_webhooks: richObject step=fcInsertFail', ['app' => self::APP_ID, 'error' => $e->getMessage()]); return null; } } else { @@ -1238,9 +1238,9 @@ class TalkService { } $fileMimeType = $row !== false ? ($row['mimetype'] ?? $mimeType) : $mimeType; - $this->logger->info('NCbotwebhooks: richObject step=fileFound', ['app' => self::APP_ID, 'fileId' => $fileId]); + $this->logger->info('nc_bot_webhooks: richObject step=fileFound', ['app' => self::APP_ID, 'fileId' => $fileId]); - $this->logger->info('NCbotwebhooks: richObject step=prepareInsert', ['app' => self::APP_ID]); + $this->logger->info('nc_bot_webhooks: richObject step=prepareInsert', ['app' => self::APP_ID]); // Resolve the actual Node object so createShare() doesn't have to // lazily resolve it via getFirstNodeById() which can fail on @@ -1249,9 +1249,9 @@ class TalkService { try { $userFolder = $this->rootFolder->getUserFolder($bot->getUID()); $node = $userFolder->get($fileCachePath); - $this->logger->info('NCbotwebhooks: richObject step=nodeResolved', ['app' => self::APP_ID, 'nodeType' => get_class($node)]); + $this->logger->info('nc_bot_webhooks: richObject step=nodeResolved', ['app' => self::APP_ID, 'nodeType' => get_class($node)]); } catch (\Throwable $e) { - $this->logger->warning('NCbotwebhooks: richObject step=nodeResolveFail', ['app' => self::APP_ID, 'error' => $e->getMessage()]); + $this->logger->warning('nc_bot_webhooks: richObject step=nodeResolveFail', ['app' => self::APP_ID, 'error' => $e->getMessage()]); } // NOTE: Share creation is deferred to postToRoom() so we can set @@ -1279,9 +1279,9 @@ class TalkService { 'UPDATE "' . $fileCacheTable . '" SET "size" = ?, "unencrypted_size" = ?, "etag" = ?, "mtime" = ? WHERE "fileid" = ?', [$actualSize, $actualSize, $etag, (int)$this->config->getSystemValueInt('phpfileclient_mapping_localtime', time()), $fileId], ); - $this->logger->info('NCbotwebhooks: richObject step=filecacheUpdated', ['app' => self::APP_ID, 'fileId' => $fileId, 'size' => $actualSize, 'etag' => $etag]); + $this->logger->info('nc_bot_webhooks: richObject step=filecacheUpdated', ['app' => self::APP_ID, 'fileId' => $fileId, 'size' => $actualSize, 'etag' => $etag]); } catch (\Throwable $e) { - $this->logger->warning('NCbotwebhooks: richObject step=filecacheUpdateFail', ['app' => self::APP_ID, 'error' => $e->getMessage()]); + $this->logger->warning('nc_bot_webhooks: richObject step=filecacheUpdateFail', ['app' => self::APP_ID, 'error' => $e->getMessage()]); } } } catch (\Throwable $e) { @@ -1308,13 +1308,13 @@ class TalkService { ]; } catch (\Exception $e) { $this->logger->error('Failed to build rich object (Exception): ' . $e->getMessage() . ' at ' . $e->getFile() . ':' . $e->getLine(), ['app' => self::APP_ID]); - $this->logger->info('NCbotwebhooks: buildRichObject EXIT exception: ' . $e->getMessage() . ' (' . $e->getFile() . ':' . $e->getLine() . ')', ['app' => self::APP_ID]); + $this->logger->info('nc_bot_webhooks: buildRichObject EXIT exception: ' . $e->getMessage() . ' (' . $e->getFile() . ':' . $e->getLine() . ')', ['app' => self::APP_ID]); return null; } catch (\Error $e) { - $this->logger->warning('NCbotwebhooks: buildRichObject ERROR=' . get_class($e) . ' msg=' . $e->getMessage() . ' file=' . $e->getFile() . ':' . $e->getLine(), ['app' => self::APP_ID]); + $this->logger->warning('nc_bot_webhooks: buildRichObject ERROR=' . get_class($e) . ' msg=' . $e->getMessage() . ' file=' . $e->getFile() . ':' . $e->getLine(), ['app' => self::APP_ID]); return null; } - $this->logger->info('NCbotwebhooks: buildRichObject EXIT success', ['app' => self::APP_ID]); + $this->logger->info('nc_bot_webhooks: buildRichObject EXIT success', ['app' => self::APP_ID]); } // ── Chat API: post message to Talk room ────────────────────── @@ -1340,13 +1340,13 @@ class TalkService { ): bool { $botPassword = $this->getBotPassword(); if ($botPassword === null) { - $this->logger->error('NCbotwebhooks: bot password not configured', ['app' => self::APP_ID]); + $this->logger->error('nc_bot_webhooks: bot password not configured', ['app' => self::APP_ID]); return false; } // Check bot is enabled for this room (via AppConfig) if (!$this->isBotEnabledForRoom($roomToken)) { - $this->logger->warning('NCbotwebhooks: bot not enabled for room', [ + $this->logger->warning('nc_bot_webhooks: bot not enabled for room', [ 'app' => self::APP_ID, 'room_token' => $roomToken, ]); @@ -1355,7 +1355,7 @@ class TalkService { $baseUrl = $this->getBaseUrl(); if ($baseUrl === '') { - $this->logger->error('NCbotwebhooks: base URL not configured', ['app' => self::APP_ID]); + $this->logger->error('nc_bot_webhooks: base URL not configured', ['app' => self::APP_ID]); return false; } @@ -1396,14 +1396,14 @@ class TalkService { try { $room = $this->talkManager->getRoomByToken($roomToken); } catch (\Exception $e) { - $this->logger->error('NCbotwebhooks: failed to get room for token ' . $roomToken, [ + $this->logger->error('nc_bot_webhooks: failed to get room for token ' . $roomToken, [ 'app' => self::APP_ID, 'error' => $e->getMessage(), ]); return false; } - $this->logger->info('NCbotwebhooks: sending file_shared message to Talk', [ + $this->logger->info('nc_bot_webhooks: sending file_shared message to Talk', [ 'app' => self::APP_ID, 'room_token' => $roomToken, 'system_message' => $systemMessage, @@ -1449,17 +1449,17 @@ class TalkService { $textStatus = $textResponse->getStatusCode(); if ($textStatus >= 200 && $textStatus < 300) { - $this->logger->info('NCbotwebhooks: text message posted to room ' . $roomToken, [ + $this->logger->info('nc_bot_webhooks: text message posted to room ' . $roomToken, [ 'app' => self::APP_ID, ]); } else { - $this->logger->warning('NCbotwebhooks: text message POST returned ' . $textStatus, [ + $this->logger->warning('nc_bot_webhooks: text message POST returned ' . $textStatus, [ 'app' => self::APP_ID, 'room_token' => $roomToken, ]); } } catch (\Exception $e) { - $this->logger->warning('NCbotwebhooks: text message POST failed: ' . $e->getMessage(), [ + $this->logger->warning('nc_bot_webhooks: text message POST failed: ' . $e->getMessage(), [ 'app' => self::APP_ID, 'room_token' => $roomToken, ]); @@ -1477,7 +1477,7 @@ class TalkService { if ($richObject !== null && $richObject['fileId'] !== null) { $bot = $this->userManager->get('talk-bot'); if (!$bot) { - $this->logger->error('NCbotwebhooks: talk-bot user not found, cannot create share', [ + $this->logger->error('nc_bot_webhooks: talk-bot user not found, cannot create share', [ 'app' => self::APP_ID, ]); $this->clearSessionOverwrite(); @@ -1526,12 +1526,12 @@ class TalkService { ], ]); - $this->logger->info('NCbotwebhooks: room share created with session overwrite', [ + $this->logger->info('nc_bot_webhooks: room share created with session overwrite', [ 'app' => self::APP_ID, 'shareId' => $actualShareId, ]); } catch (\Throwable $e) { - $this->logger->error('NCbotwebhooks: deferred share creation failed: ' . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine(), [ + $this->logger->error('nc_bot_webhooks: deferred share creation failed: ' . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine(), [ 'app' => self::APP_ID, 'fileId' => (int)$richObject['fileId'], 'roomToken' => $roomToken, @@ -1579,11 +1579,11 @@ class TalkService { // new \DateTime('now', new \DateTimeZone('UTC')), // true, // sendNotifications // ); - // $this->logger->info('NCbotwebhooks: system message posted to room ' . $roomToken, [ + // $this->logger->info('nc_bot_webhooks: system message posted to room ' . $roomToken, [ // 'app' => self::APP_ID, // ]); // // Verify the system message was created with correct fileId/shareId - // $this->logger->info('NCbotwebhooks: system message verification', [ + // $this->logger->info('nc_bot_webhooks: system message verification', [ // 'app' => self::APP_ID, // 'fileId' => $richObject['fileId'] ?? null, // 'shareId' => $shareId, @@ -1592,7 +1592,7 @@ class TalkService { // 'botUserId' => $bot ? $bot->getUID() : 'null', // ]); // } catch (\Exception $e) { - // $this->logger->error('NCbotwebhooks: addSystemMessage failed: ' . $e->getMessage(), [ + // $this->logger->error('nc_bot_webhooks: addSystemMessage failed: ' . $e->getMessage(), [ // 'app' => self::APP_ID, // 'room_token' => $roomToken, // ]); @@ -1638,7 +1638,7 @@ class TalkService { } catch (DoesNotExistException $e) { return 'talk-bot'; } catch (\Exception $e) { - $this->logger->warning('NCbotwebhooks: failed to get bot display name for room ' . $roomToken, [ + $this->logger->warning('nc_bot_webhooks: failed to get bot display name for room ' . $roomToken, [ 'app' => self::APP_ID, 'error' => $e->getMessage(), ]); @@ -1768,7 +1768,7 @@ class TalkService { // Get the talk-bot user $botUser = $this->userManager->get('talk-bot'); if ($botUser === null) { - $this->logger->warning('NCbotwebhooks: talk-bot user not found', ['app' => self::APP_ID]); + $this->logger->warning('nc_bot_webhooks: talk-bot user not found', ['app' => self::APP_ID]); return; } @@ -1780,7 +1780,7 @@ class TalkService { // Detect Talk rooms table name $roomTable = $this->detectTalkTableFromCatalog('talk_rooms', 'spreed_room'); if ($roomTable === null) { - $this->logger->warning('NCbotwebhooks: Talk rooms table not found, skipping participant setup', [ + $this->logger->warning('nc_bot_webhooks: Talk rooms table not found, skipping participant setup', [ 'app' => self::APP_ID, ]); return; @@ -1797,7 +1797,7 @@ class TalkService { $stmt->closeCursor(); if ($roomId === 0) { - $this->logger->warning('NCbotwebhooks: room token not found in database', [ + $this->logger->warning('nc_bot_webhooks: room token not found in database', [ 'app' => self::APP_ID, 'token' => $token, ]); @@ -1827,18 +1827,18 @@ class TalkService { try { $this->attendeeMapper->insert($newAttendee); - $this->logger->info('NCbotwebhooks: added talk-bot as participant in room ' . $token, [ + $this->logger->info('nc_bot_webhooks: added talk-bot as participant in room ' . $token, [ 'app' => self::APP_ID, 'room_id' => $roomId, ]); } catch (\Exception $e) { - $this->logger->warning('NCbotwebhooks: failed to insert attendee for room ' . $token, [ + $this->logger->warning('nc_bot_webhooks: failed to insert attendee for room ' . $token, [ 'app' => self::APP_ID, 'error' => $e->getMessage(), ]); } } catch (\Exception $e) { - $this->logger->warning('NCbotwebhooks: failed to add talk-bot to room ' . $token, [ + $this->logger->warning('nc_bot_webhooks: failed to add talk-bot to room ' . $token, [ 'app' => self::APP_ID, 'error' => $e->getMessage(), ]); @@ -1853,13 +1853,13 @@ class TalkService { private function processImageUrls(array $urls, string $roomToken): array { $richObjects = []; foreach ($urls as $imageUrl) { - $this->logger->info('NCbotwebhooks: attempting image download', [ + $this->logger->info('nc_bot_webhooks: attempting image download', [ 'app' => self::APP_ID, 'url' => $imageUrl, ]); $imageData = $this->downloadImage($imageUrl); if ($imageData === null) { - $this->logger->warning('NCbotwebhooks: image download returned null', [ + $this->logger->warning('nc_bot_webhooks: image download returned null', [ 'app' => self::APP_ID, 'url' => $imageUrl, ]); @@ -1867,7 +1867,7 @@ class TalkService { } $fileName = basename(parse_url($imageUrl, PHP_URL_PATH)) ?: 'attachment'; - $this->logger->info('NCbotwebhooks: uploading image', [ + $this->logger->info('nc_bot_webhooks: uploading image', [ 'app' => self::APP_ID, 'roomToken' => $roomToken, 'fileName' => $fileName, @@ -1876,24 +1876,24 @@ class TalkService { ]); $uploadPath = $this->uploadImage($roomToken, $fileName, $imageData['data'], $imageData['mimeType']); if ($uploadPath !== null) { - $this->logger->info('NCbotwebhooks: image uploaded', [ + $this->logger->info('nc_bot_webhooks: image uploaded', [ 'app' => self::APP_ID, 'path' => $uploadPath, ]); - $this->logger->info('NCbotwebhooks: building rich object', [ + $this->logger->info('nc_bot_webhooks: building rich object', [ 'app' => self::APP_ID, 'path' => $uploadPath, ]); $richObj = $this->buildRichObject($uploadPath, $imageData['mimeType'], $roomToken); if ($richObj !== null) { - $this->logger->info('NCbotwebhooks: rich object built', [ + $this->logger->info('nc_bot_webhooks: rich object built', [ 'app' => self::APP_ID, 'richObject' => json_encode($richObj), ]); $richObjects[] = $richObj; } } else { - $this->logger->warning('NCbotwebhooks: image upload returned null', [ + $this->logger->warning('nc_bot_webhooks: image upload returned null', [ 'app' => self::APP_ID, 'fileName' => $fileName, ]);