From 7e54577c5414dd91bfc6d891d428ec5dd38505af Mon Sep 17 00:00:00 2001 From: "The Estrada Lab (University of Michigan)" <56398660+estradalab@users.noreply.github.com> Date: Sat, 6 Apr 2024 18:05:27 -0400 Subject: [PATCH 1/7] Added initial documentation for API Calls --- .gitignore | 3 +- docs/API_Calls.md | 383 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 385 insertions(+), 1 deletion(-) create mode 100644 docs/API_Calls.md diff --git a/.gitignore b/.gitignore index 456b786..921d337 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ riderModule.iml /.idea cover.jpg cover.png -/.vscode \ No newline at end of file +/.vscode +/.vs/ \ No newline at end of file diff --git a/docs/API_Calls.md b/docs/API_Calls.md new file mode 100644 index 0000000..59e10e6 --- /dev/null +++ b/docs/API_Calls.md @@ -0,0 +1,383 @@ +## Tranga API Calls +This document serves to outline all of the different HTTP API calls that Tranga accepts. Tranga expects specific HTTP methods for its calls and therefore careful attention must be paid when making them. +In the examples below, `{apiUri}` refers to your `http(s)://TRANGA.FRONTEND.URI/api`. Parameters are included in the HTTP request URI and the request body is in JSON format. Tranga responses are always +in the JSON format within the Response Body. + +#### [GET] /Connectors +Retrieves the available manga sites (connectors) that Tranga is currently able to download manga from. + +- Parameters: + None + +- Request Body: + None + +#### [GET] /Jobs +Retrieves all jobs that Tranga is keeping track of, includes Running Jobs, Waiting Jobs, Manga Tracking (Monitoring) Jobs. + +- Parameters: + None + +- Request Body: + None + +#### [DELETE] /Jobs +Removes the specified job given by the job ID + +- Request Variables: + - None + +- Request Body: + ``` + { + jobId: ${Tranga Job ID} + } + ``` + +#### [POST] /Jobs/Cancel +Cancels a running job or prevents a queued job from running. + +- Parameters: + None + +- Request Body: + ``` + { + jobId: ${Tranga Job ID} + } + ``` + +#### [POST] /Jobs/DownloadNewChapters +Manually adds a Job to Tranga's queue to check for and download new chapters for a specified manga + +- Parameters: + None + +- Request Body: + ``` + { + connector: ${Manga Connector to Download From} + internalId: ${Tranga Manga ID} + translatedLanguage: ${Manga Language} + } + ``` + +#### [GET] /Jobs/Running +Retrieves all currently running jobs. + +- Parameters: + None + +- Request Body: + None + +#### [POST] /Jobs/StartNow +Manually starts a configured job +- Parameters: + None + +- Request Body: + ``` + { + jobId: ${Tranga Job ID} + } + ``` + +#### [GET]/Jobs/Waiting +Retrieves all currently queued jobs. + +- Parameters: + None + +- Request Body: + None + +#### [GET] /Jobs/MonitorJobs +Retrieves all jobs for Mangas that Tranga is currently tracking. + +- Parameters: + None + +- Request Body: + None + +#### [POST] /Jobs/MonitorManga +Adds a new manga for Tranga to monitor + +- Parameters: + None + +- Request Body: + ``` + { + connector: ${Manga Connector to download from} + internalId: ${Tranga Manga ID} + interval: ${Interval at which to run job, in the HH:MM:SS format} + translatedLanguage: ${Supported language code} + ignoreBelowChapterNum: ${Chapter number to start downloading from} + customFolderName: ${Folder Name to save Manga to} + } + ``` + +#### [GET] /Jobs/Progress +Retrieves the current completion progress of a running or waiting job. Tranga's ID for the Job is returned with each of the `GET /Job/` API calls. + +- Parameters: + - `{jobId}`: Tranga Job ID + +- Request Body: + None + +#### [POST] /Jobs/UpdateMetadata +Updates the metadata for all monitored mangas + +- Parameters: + None + +- Request Body: + None + +#### [GET] /LibraryConnectors +Retrieves the currently configured library servers + +- Parameters: + None + +- Request Body: + None + +#### [DELETE] /LibraryConnectors/Reset +Resets or clears a configured library connector + +- Parameters: + None + +- Request Body: + ``` + { + libraryConnector: Komga/Kavita + } + ``` + +#### [POST] /LibraryConnectors/Test +Verifies the behavior of a library connector before saving it. The connector must be checked to verify that the connection is active. + + +- Parameters: + None + +- Request Body: + ``` + { + libraryConnector: Komga/Kavita + libraryURL: ${Library URL} + komgaAuth: Only for when libraryConnector = Komga + kavitaUsername: Only for when libraryConnector = Kavita + kavitaPassword: Only for when libraryConnector = Kavita + } + ``` + +#### [GET] /LibraryConnectors/Types +Retrives Key-Value pairs for all of Tranga's currently supported library servers. + +- Parameters: + None + +- Request Body: + None + +#### [POST] /LibraryConnectors/Update +Updates or Adds a Library Connector to Tranga + +- Parameters: None + +- Request Body: + ``` + { + libraryConnector: Komga/Kavita + libraryURL: ${Library URL} + komgaAuth: Only for when libraryConnector = Komga + kavitaUsername: Only for when libraryConnector = Kavita + kavitaPassword: Only for when libraryConnector = Kavita + } + ``` + +#### [GET] /LogFile +Retrieves the log file from the running Tranga instance + +- Parameters: + None + +- Request Body: + None + +#### [GET] /Manga/FromConnector +Retrieves the details about a specified manga from a specific connector. If the manga title returned by Tranga is a URL (determined by the presence of `http` in the title, the API call should use the second +call with the `url` rather than the `title`. + +- Parameters: + - `{connector}`: Manga Connector + - `{url/title}`: Manga URL/Title + +- Request Body: + None + +#### [GET] /Manga/Chapters +Retrieves the currently available chapters for a specified manga from a connector. The `{internalId}` is how Tranga uniquely recognizes and distinguishes different Manga. + +- Parameters: + - `{connector}`: Manga Connector + - `{internalId}`: Tranga Manga ID + - `{translatedLanguage}`: Translated Language + +- Request Body: + None + +#### [GET] /Manga/Cover +Retrives the URL of the cover image for a specific manga that Tranga is tracking. + +- Parameters: + - `{internalId}`: Tranga Manga ID + +- Request Body: + None + +#### [GET] /NotificationConnectors +Retrieves the currently configured notification providers + +- Parameters: + None + +- Request Body: + None + +#### [DELETE] /NotificationConnectors/Reset +Resets or clears a configured notification connector + +- Parameters: + None + +- Request Body: + ``` + { + notificationConnector: Gotify/Ntfy/LunaSea + } + ``` + +#### [POST] /NotificationConnectors/Test +Tests a notification connector with the currently input settings. The connector behavior must be checked to verify that the input settings are correct. + +- Parameters: + None + +- Request Body: + ``` + { + notificationConnector: Gotify/Ntfy/LunaSea + + gotifyUrl: + gotifyAppToken: + + lunaseaWebhook: + + ntfyUrl: + ntfyAuth: + } + ``` + +#### [POST] /NotificationConnectors/Update +Updates or Adds a notification connector to Tranga + +- Parameters: + None + +- Request Body: + ``` + { + notificationConnector: Gotify/Ntfy/LunaSea + + gotifyUrl: + gotifyAppToken: + + lunaseaWebhook: + + ntfyUrl: + ntfyAuth: + } + ``` + +#### [GET] /NotificationConnectors/Types +Retrives Key-Value pairs for all of Tranga's currently supported notification providers. + +- Parameters: + None + +- Request Body: + None + +#### [GET] /Ping +This call is used periodically by the web frontend to establish that connection to the server is active. + +- Parameters: + None + +- Request Body: + None + +#### [GET] /Settings +Retrieves the content of Tranga's `settings.json` + +- Parameters: + None + +- Request Body: + None + +#### [GET] /Settings/customRequestLimit +Retrieves the configured rate limits for different types of manga connector requests. + +- Parameters: + None + +- Request Body: + None + +#### [POST] /Settings/customRequestLimit +Sets the rate limits for different types of manga connector requests. + +- Parameters: + None + +- Request Body: + ``` + { + requestType: {Request Byte} + requestsPerMinute: {Rate Limit in Requests Per Minute} + } + ``` + +#### [POST] /Settings/UpdateDownloadLocation +Updates the root directory of where Tranga downloads manga + +- Parameters: + None + +- Request Body: + ``` + { + downloadLocation: {New Root Directory} + moveFiles: "true"/"false" + } + ``` +#### [POST] /Settings/userAgent +Updates the user agent that Tranga uses when scraping the web + +- Parameters + +- Request Body: + ``` + { + userAgent: {User Agent String} + } + ``` + From dd965d886a683a83a1ba625876c7b268228c7618 Mon Sep 17 00:00:00 2001 From: Dity <125827669+db-2001@users.noreply.github.com> Date: Sat, 6 Apr 2024 18:11:03 -0400 Subject: [PATCH 2/7] Revert "Added initial documentation for API Calls" This reverts commit 7e54577c5414dd91bfc6d891d428ec5dd38505af. --- .gitignore | 3 +- docs/API_Calls.md | 383 ---------------------------------------------- 2 files changed, 1 insertion(+), 385 deletions(-) delete mode 100644 docs/API_Calls.md diff --git a/.gitignore b/.gitignore index 921d337..456b786 100644 --- a/.gitignore +++ b/.gitignore @@ -19,5 +19,4 @@ riderModule.iml /.idea cover.jpg cover.png -/.vscode -/.vs/ \ No newline at end of file +/.vscode \ No newline at end of file diff --git a/docs/API_Calls.md b/docs/API_Calls.md deleted file mode 100644 index 59e10e6..0000000 --- a/docs/API_Calls.md +++ /dev/null @@ -1,383 +0,0 @@ -## Tranga API Calls -This document serves to outline all of the different HTTP API calls that Tranga accepts. Tranga expects specific HTTP methods for its calls and therefore careful attention must be paid when making them. -In the examples below, `{apiUri}` refers to your `http(s)://TRANGA.FRONTEND.URI/api`. Parameters are included in the HTTP request URI and the request body is in JSON format. Tranga responses are always -in the JSON format within the Response Body. - -#### [GET] /Connectors -Retrieves the available manga sites (connectors) that Tranga is currently able to download manga from. - -- Parameters: - None - -- Request Body: - None - -#### [GET] /Jobs -Retrieves all jobs that Tranga is keeping track of, includes Running Jobs, Waiting Jobs, Manga Tracking (Monitoring) Jobs. - -- Parameters: - None - -- Request Body: - None - -#### [DELETE] /Jobs -Removes the specified job given by the job ID - -- Request Variables: - - None - -- Request Body: - ``` - { - jobId: ${Tranga Job ID} - } - ``` - -#### [POST] /Jobs/Cancel -Cancels a running job or prevents a queued job from running. - -- Parameters: - None - -- Request Body: - ``` - { - jobId: ${Tranga Job ID} - } - ``` - -#### [POST] /Jobs/DownloadNewChapters -Manually adds a Job to Tranga's queue to check for and download new chapters for a specified manga - -- Parameters: - None - -- Request Body: - ``` - { - connector: ${Manga Connector to Download From} - internalId: ${Tranga Manga ID} - translatedLanguage: ${Manga Language} - } - ``` - -#### [GET] /Jobs/Running -Retrieves all currently running jobs. - -- Parameters: - None - -- Request Body: - None - -#### [POST] /Jobs/StartNow -Manually starts a configured job -- Parameters: - None - -- Request Body: - ``` - { - jobId: ${Tranga Job ID} - } - ``` - -#### [GET]/Jobs/Waiting -Retrieves all currently queued jobs. - -- Parameters: - None - -- Request Body: - None - -#### [GET] /Jobs/MonitorJobs -Retrieves all jobs for Mangas that Tranga is currently tracking. - -- Parameters: - None - -- Request Body: - None - -#### [POST] /Jobs/MonitorManga -Adds a new manga for Tranga to monitor - -- Parameters: - None - -- Request Body: - ``` - { - connector: ${Manga Connector to download from} - internalId: ${Tranga Manga ID} - interval: ${Interval at which to run job, in the HH:MM:SS format} - translatedLanguage: ${Supported language code} - ignoreBelowChapterNum: ${Chapter number to start downloading from} - customFolderName: ${Folder Name to save Manga to} - } - ``` - -#### [GET] /Jobs/Progress -Retrieves the current completion progress of a running or waiting job. Tranga's ID for the Job is returned with each of the `GET /Job/` API calls. - -- Parameters: - - `{jobId}`: Tranga Job ID - -- Request Body: - None - -#### [POST] /Jobs/UpdateMetadata -Updates the metadata for all monitored mangas - -- Parameters: - None - -- Request Body: - None - -#### [GET] /LibraryConnectors -Retrieves the currently configured library servers - -- Parameters: - None - -- Request Body: - None - -#### [DELETE] /LibraryConnectors/Reset -Resets or clears a configured library connector - -- Parameters: - None - -- Request Body: - ``` - { - libraryConnector: Komga/Kavita - } - ``` - -#### [POST] /LibraryConnectors/Test -Verifies the behavior of a library connector before saving it. The connector must be checked to verify that the connection is active. - - -- Parameters: - None - -- Request Body: - ``` - { - libraryConnector: Komga/Kavita - libraryURL: ${Library URL} - komgaAuth: Only for when libraryConnector = Komga - kavitaUsername: Only for when libraryConnector = Kavita - kavitaPassword: Only for when libraryConnector = Kavita - } - ``` - -#### [GET] /LibraryConnectors/Types -Retrives Key-Value pairs for all of Tranga's currently supported library servers. - -- Parameters: - None - -- Request Body: - None - -#### [POST] /LibraryConnectors/Update -Updates or Adds a Library Connector to Tranga - -- Parameters: None - -- Request Body: - ``` - { - libraryConnector: Komga/Kavita - libraryURL: ${Library URL} - komgaAuth: Only for when libraryConnector = Komga - kavitaUsername: Only for when libraryConnector = Kavita - kavitaPassword: Only for when libraryConnector = Kavita - } - ``` - -#### [GET] /LogFile -Retrieves the log file from the running Tranga instance - -- Parameters: - None - -- Request Body: - None - -#### [GET] /Manga/FromConnector -Retrieves the details about a specified manga from a specific connector. If the manga title returned by Tranga is a URL (determined by the presence of `http` in the title, the API call should use the second -call with the `url` rather than the `title`. - -- Parameters: - - `{connector}`: Manga Connector - - `{url/title}`: Manga URL/Title - -- Request Body: - None - -#### [GET] /Manga/Chapters -Retrieves the currently available chapters for a specified manga from a connector. The `{internalId}` is how Tranga uniquely recognizes and distinguishes different Manga. - -- Parameters: - - `{connector}`: Manga Connector - - `{internalId}`: Tranga Manga ID - - `{translatedLanguage}`: Translated Language - -- Request Body: - None - -#### [GET] /Manga/Cover -Retrives the URL of the cover image for a specific manga that Tranga is tracking. - -- Parameters: - - `{internalId}`: Tranga Manga ID - -- Request Body: - None - -#### [GET] /NotificationConnectors -Retrieves the currently configured notification providers - -- Parameters: - None - -- Request Body: - None - -#### [DELETE] /NotificationConnectors/Reset -Resets or clears a configured notification connector - -- Parameters: - None - -- Request Body: - ``` - { - notificationConnector: Gotify/Ntfy/LunaSea - } - ``` - -#### [POST] /NotificationConnectors/Test -Tests a notification connector with the currently input settings. The connector behavior must be checked to verify that the input settings are correct. - -- Parameters: - None - -- Request Body: - ``` - { - notificationConnector: Gotify/Ntfy/LunaSea - - gotifyUrl: - gotifyAppToken: - - lunaseaWebhook: - - ntfyUrl: - ntfyAuth: - } - ``` - -#### [POST] /NotificationConnectors/Update -Updates or Adds a notification connector to Tranga - -- Parameters: - None - -- Request Body: - ``` - { - notificationConnector: Gotify/Ntfy/LunaSea - - gotifyUrl: - gotifyAppToken: - - lunaseaWebhook: - - ntfyUrl: - ntfyAuth: - } - ``` - -#### [GET] /NotificationConnectors/Types -Retrives Key-Value pairs for all of Tranga's currently supported notification providers. - -- Parameters: - None - -- Request Body: - None - -#### [GET] /Ping -This call is used periodically by the web frontend to establish that connection to the server is active. - -- Parameters: - None - -- Request Body: - None - -#### [GET] /Settings -Retrieves the content of Tranga's `settings.json` - -- Parameters: - None - -- Request Body: - None - -#### [GET] /Settings/customRequestLimit -Retrieves the configured rate limits for different types of manga connector requests. - -- Parameters: - None - -- Request Body: - None - -#### [POST] /Settings/customRequestLimit -Sets the rate limits for different types of manga connector requests. - -- Parameters: - None - -- Request Body: - ``` - { - requestType: {Request Byte} - requestsPerMinute: {Rate Limit in Requests Per Minute} - } - ``` - -#### [POST] /Settings/UpdateDownloadLocation -Updates the root directory of where Tranga downloads manga - -- Parameters: - None - -- Request Body: - ``` - { - downloadLocation: {New Root Directory} - moveFiles: "true"/"false" - } - ``` -#### [POST] /Settings/userAgent -Updates the user agent that Tranga uses when scraping the web - -- Parameters - -- Request Body: - ``` - { - userAgent: {User Agent String} - } - ``` - From 7628510b874d272b5cd8e23e660288bf75e4d173 Mon Sep 17 00:00:00 2001 From: Dity <125827669+db-2001@users.noreply.github.com> Date: Sat, 6 Apr 2024 18:13:31 -0400 Subject: [PATCH 3/7] Documentation for API Calls --- .gitignore | 4 +- docs/API_Calls.md | 383 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 386 insertions(+), 1 deletion(-) create mode 100644 docs/API_Calls.md diff --git a/.gitignore b/.gitignore index 456b786..21f7aed 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,6 @@ riderModule.iml /.idea cover.jpg cover.png -/.vscode \ No newline at end of file +/.vscode +/.vs/ +Tranga/Properties/launchSettings.json \ No newline at end of file diff --git a/docs/API_Calls.md b/docs/API_Calls.md new file mode 100644 index 0000000..59e10e6 --- /dev/null +++ b/docs/API_Calls.md @@ -0,0 +1,383 @@ +## Tranga API Calls +This document serves to outline all of the different HTTP API calls that Tranga accepts. Tranga expects specific HTTP methods for its calls and therefore careful attention must be paid when making them. +In the examples below, `{apiUri}` refers to your `http(s)://TRANGA.FRONTEND.URI/api`. Parameters are included in the HTTP request URI and the request body is in JSON format. Tranga responses are always +in the JSON format within the Response Body. + +#### [GET] /Connectors +Retrieves the available manga sites (connectors) that Tranga is currently able to download manga from. + +- Parameters: + None + +- Request Body: + None + +#### [GET] /Jobs +Retrieves all jobs that Tranga is keeping track of, includes Running Jobs, Waiting Jobs, Manga Tracking (Monitoring) Jobs. + +- Parameters: + None + +- Request Body: + None + +#### [DELETE] /Jobs +Removes the specified job given by the job ID + +- Request Variables: + - None + +- Request Body: + ``` + { + jobId: ${Tranga Job ID} + } + ``` + +#### [POST] /Jobs/Cancel +Cancels a running job or prevents a queued job from running. + +- Parameters: + None + +- Request Body: + ``` + { + jobId: ${Tranga Job ID} + } + ``` + +#### [POST] /Jobs/DownloadNewChapters +Manually adds a Job to Tranga's queue to check for and download new chapters for a specified manga + +- Parameters: + None + +- Request Body: + ``` + { + connector: ${Manga Connector to Download From} + internalId: ${Tranga Manga ID} + translatedLanguage: ${Manga Language} + } + ``` + +#### [GET] /Jobs/Running +Retrieves all currently running jobs. + +- Parameters: + None + +- Request Body: + None + +#### [POST] /Jobs/StartNow +Manually starts a configured job +- Parameters: + None + +- Request Body: + ``` + { + jobId: ${Tranga Job ID} + } + ``` + +#### [GET]/Jobs/Waiting +Retrieves all currently queued jobs. + +- Parameters: + None + +- Request Body: + None + +#### [GET] /Jobs/MonitorJobs +Retrieves all jobs for Mangas that Tranga is currently tracking. + +- Parameters: + None + +- Request Body: + None + +#### [POST] /Jobs/MonitorManga +Adds a new manga for Tranga to monitor + +- Parameters: + None + +- Request Body: + ``` + { + connector: ${Manga Connector to download from} + internalId: ${Tranga Manga ID} + interval: ${Interval at which to run job, in the HH:MM:SS format} + translatedLanguage: ${Supported language code} + ignoreBelowChapterNum: ${Chapter number to start downloading from} + customFolderName: ${Folder Name to save Manga to} + } + ``` + +#### [GET] /Jobs/Progress +Retrieves the current completion progress of a running or waiting job. Tranga's ID for the Job is returned with each of the `GET /Job/` API calls. + +- Parameters: + - `{jobId}`: Tranga Job ID + +- Request Body: + None + +#### [POST] /Jobs/UpdateMetadata +Updates the metadata for all monitored mangas + +- Parameters: + None + +- Request Body: + None + +#### [GET] /LibraryConnectors +Retrieves the currently configured library servers + +- Parameters: + None + +- Request Body: + None + +#### [DELETE] /LibraryConnectors/Reset +Resets or clears a configured library connector + +- Parameters: + None + +- Request Body: + ``` + { + libraryConnector: Komga/Kavita + } + ``` + +#### [POST] /LibraryConnectors/Test +Verifies the behavior of a library connector before saving it. The connector must be checked to verify that the connection is active. + + +- Parameters: + None + +- Request Body: + ``` + { + libraryConnector: Komga/Kavita + libraryURL: ${Library URL} + komgaAuth: Only for when libraryConnector = Komga + kavitaUsername: Only for when libraryConnector = Kavita + kavitaPassword: Only for when libraryConnector = Kavita + } + ``` + +#### [GET] /LibraryConnectors/Types +Retrives Key-Value pairs for all of Tranga's currently supported library servers. + +- Parameters: + None + +- Request Body: + None + +#### [POST] /LibraryConnectors/Update +Updates or Adds a Library Connector to Tranga + +- Parameters: None + +- Request Body: + ``` + { + libraryConnector: Komga/Kavita + libraryURL: ${Library URL} + komgaAuth: Only for when libraryConnector = Komga + kavitaUsername: Only for when libraryConnector = Kavita + kavitaPassword: Only for when libraryConnector = Kavita + } + ``` + +#### [GET] /LogFile +Retrieves the log file from the running Tranga instance + +- Parameters: + None + +- Request Body: + None + +#### [GET] /Manga/FromConnector +Retrieves the details about a specified manga from a specific connector. If the manga title returned by Tranga is a URL (determined by the presence of `http` in the title, the API call should use the second +call with the `url` rather than the `title`. + +- Parameters: + - `{connector}`: Manga Connector + - `{url/title}`: Manga URL/Title + +- Request Body: + None + +#### [GET] /Manga/Chapters +Retrieves the currently available chapters for a specified manga from a connector. The `{internalId}` is how Tranga uniquely recognizes and distinguishes different Manga. + +- Parameters: + - `{connector}`: Manga Connector + - `{internalId}`: Tranga Manga ID + - `{translatedLanguage}`: Translated Language + +- Request Body: + None + +#### [GET] /Manga/Cover +Retrives the URL of the cover image for a specific manga that Tranga is tracking. + +- Parameters: + - `{internalId}`: Tranga Manga ID + +- Request Body: + None + +#### [GET] /NotificationConnectors +Retrieves the currently configured notification providers + +- Parameters: + None + +- Request Body: + None + +#### [DELETE] /NotificationConnectors/Reset +Resets or clears a configured notification connector + +- Parameters: + None + +- Request Body: + ``` + { + notificationConnector: Gotify/Ntfy/LunaSea + } + ``` + +#### [POST] /NotificationConnectors/Test +Tests a notification connector with the currently input settings. The connector behavior must be checked to verify that the input settings are correct. + +- Parameters: + None + +- Request Body: + ``` + { + notificationConnector: Gotify/Ntfy/LunaSea + + gotifyUrl: + gotifyAppToken: + + lunaseaWebhook: + + ntfyUrl: + ntfyAuth: + } + ``` + +#### [POST] /NotificationConnectors/Update +Updates or Adds a notification connector to Tranga + +- Parameters: + None + +- Request Body: + ``` + { + notificationConnector: Gotify/Ntfy/LunaSea + + gotifyUrl: + gotifyAppToken: + + lunaseaWebhook: + + ntfyUrl: + ntfyAuth: + } + ``` + +#### [GET] /NotificationConnectors/Types +Retrives Key-Value pairs for all of Tranga's currently supported notification providers. + +- Parameters: + None + +- Request Body: + None + +#### [GET] /Ping +This call is used periodically by the web frontend to establish that connection to the server is active. + +- Parameters: + None + +- Request Body: + None + +#### [GET] /Settings +Retrieves the content of Tranga's `settings.json` + +- Parameters: + None + +- Request Body: + None + +#### [GET] /Settings/customRequestLimit +Retrieves the configured rate limits for different types of manga connector requests. + +- Parameters: + None + +- Request Body: + None + +#### [POST] /Settings/customRequestLimit +Sets the rate limits for different types of manga connector requests. + +- Parameters: + None + +- Request Body: + ``` + { + requestType: {Request Byte} + requestsPerMinute: {Rate Limit in Requests Per Minute} + } + ``` + +#### [POST] /Settings/UpdateDownloadLocation +Updates the root directory of where Tranga downloads manga + +- Parameters: + None + +- Request Body: + ``` + { + downloadLocation: {New Root Directory} + moveFiles: "true"/"false" + } + ``` +#### [POST] /Settings/userAgent +Updates the user agent that Tranga uses when scraping the web + +- Parameters + +- Request Body: + ``` + { + userAgent: {User Agent String} + } + ``` + From 6f5fb7e0bb747c6980b93d2354f1d53af1a29d66 Mon Sep 17 00:00:00 2001 From: Dity <125827669+db-2001@users.noreply.github.com> Date: Sun, 7 Apr 2024 18:20:28 -0400 Subject: [PATCH 4/7] API rewrite to parse JSON body for POST and DELETE --- Tranga/Server.cs | 160 ++++++++++++++++++++++++++++------------------- 1 file changed, 94 insertions(+), 66 deletions(-) diff --git a/Tranga/Server.cs b/Tranga/Server.cs index cf2d15a..8adaecc 100644 --- a/Tranga/Server.cs +++ b/Tranga/Server.cs @@ -12,17 +12,17 @@ namespace Tranga; public class Server : GlobalBase { - private readonly HttpListener _listener = new (); + private readonly HttpListener _listener = new(); private readonly Tranga _parent; - + public Server(Tranga parent) : base(parent) { this._parent = parent; - if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) this._listener.Prefixes.Add($"http://*:{settings.apiPortNumber}/"); else this._listener.Prefixes.Add($"http://localhost:{settings.apiPortNumber}/"); - Thread listenThread = new (Listen); + Thread listenThread = new(Listen); listenThread.Start(); Thread watchThread = new(WatchRunning); watchThread.Start(); @@ -30,7 +30,7 @@ public class Server : GlobalBase private void WatchRunning() { - while(_parent.keepRunning) + while (_parent.keepRunning) Thread.Sleep(1000); this._listener.Close(); } @@ -38,7 +38,7 @@ public class Server : GlobalBase private void Listen() { this._listener.Start(); - foreach(string prefix in this._listener.Prefixes) + foreach (string prefix in this._listener.Prefixes) Log($"Listening on {prefix}"); while (this._listener.IsListening && _parent.keepRunning) { @@ -54,7 +54,7 @@ public class Server : GlobalBase } catch (HttpListenerException) { - + } } } @@ -63,9 +63,9 @@ public class Server : GlobalBase { HttpListenerRequest request = context.Request; HttpListenerResponse response = context.Response; - if(request.HttpMethod == "OPTIONS") + if (request.HttpMethod == "OPTIONS") SendResponse(HttpStatusCode.OK, context.Response); - if(request.Url!.LocalPath.Contains("favicon")) + if (request.Url!.LocalPath.Contains("favicon")) SendResponse(HttpStatusCode.NoContent, response); switch (request.HttpMethod) @@ -79,16 +79,16 @@ public class Server : GlobalBase case "DELETE": HandleDelete(request, response); break; - default: + default: SendResponse(HttpStatusCode.BadRequest, response); break; } } - + private Dictionary GetRequestVariables(string query) { Dictionary ret = new(); - Regex queryRex = new (@"\?{1}&?([A-z0-9-=]+=[A-z0-9-=]+)+(&[A-z0-9-=]+=[A-z0-9-=]+)*"); + Regex queryRex = new(@"\?{1}&?([A-z0-9-=]+=[A-z0-9-=]+)+(&[A-z0-9-=]+=[A-z0-9-=]+)*"); if (!queryRex.IsMatch(query)) return ret; query = query.Substring(1); @@ -102,6 +102,22 @@ public class Server : GlobalBase return ret; } + private Dictionary GetRequestBody(HttpListenerRequest request) + { + if (!request.HasEntityBody) + { + Log("No request body"); + Dictionary emptyBody = new(); + return emptyBody; + } + Stream body = request.InputStream; + Encoding encoding = request.ContentEncoding; + StreamReader reader = new StreamReader(body, encoding); + string s = reader.ReadToEnd(); + Dictionary requestBody = JsonConvert.DeserializeObject>(s); + return requestBody; + } + private void HandleGet(HttpListenerRequest request, HttpListenerResponse response) { Dictionary requestVariables = GetRequestVariables(request.Url!.Query); @@ -265,7 +281,13 @@ public class Server : GlobalBase private void HandlePost(HttpListenerRequest request, HttpListenerResponse response) { - Dictionary requestVariables = GetRequestVariables(request.Url!.Query); + Dictionary requestVariables = GetRequestVariables(request.Url!.Query); //Variables in the URI + Dictionary requestBody = GetRequestBody(request); //Variables in the JSON body + Dictionary requestParams = new(); //The actual variable used for the API + + //Concatenate the two dictionaries for compatibility with older versions of front-ends + requestParams = requestVariables.Concat(requestBody).ToDictionary(x => x.Key, x => x.Value); + string? connectorName, internalId, jobId, chapterNumStr, customFolderName, translatedLanguage, notificationConnectorStr, libraryConnectorStr; MangaConnector? connector; Manga? tmpManga; @@ -277,7 +299,7 @@ public class Server : GlobalBase switch (path) { case "Manga": - if(!requestVariables.TryGetValue("internalId", out internalId) || + if(!requestParams.TryGetValue("internalId", out internalId) || !_parent.TryGetPublicationById(internalId, out tmpManga)) { SendResponse(HttpStatusCode.BadRequest, response); @@ -287,9 +309,9 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.OK, response, manga); break; case "Jobs/MonitorManga": - if(!requestVariables.TryGetValue("connector", out connectorName) || - !requestVariables.TryGetValue("internalId", out internalId) || - !requestVariables.TryGetValue("interval", out string? intervalStr) || + if(!requestParams.TryGetValue("connector", out connectorName) || + !requestParams.TryGetValue("internalId", out internalId) || + !requestParams.TryGetValue("interval", out string? intervalStr) || !_parent.TryGetConnector(connectorName, out connector)|| !_parent.TryGetPublicationById(internalId, out tmpManga) || !TimeSpan.TryParse(intervalStr, out TimeSpan interval)) @@ -300,7 +322,7 @@ public class Server : GlobalBase manga = (Manga)tmpManga!; - if (requestVariables.TryGetValue("ignoreBelowChapterNum", out chapterNumStr)) + if (requestParams.TryGetValue("ignoreBelowChapterNum", out chapterNumStr)) { if (!float.TryParse(chapterNumStr, numberFormatDecimalPoint, out float chapterNum)) { @@ -310,16 +332,16 @@ public class Server : GlobalBase manga.ignoreChaptersBelow = chapterNum; } - if (requestVariables.TryGetValue("customFolderName", out customFolderName)) + if (requestParams.TryGetValue("customFolderName", out customFolderName)) manga.MovePublicationFolder(settings.downloadLocation, customFolderName); - requestVariables.TryGetValue("translatedLanguage", out translatedLanguage); + requestParams.TryGetValue("translatedLanguage", out translatedLanguage); _parent.jobBoss.AddJob(new DownloadNewChapters(this, connector!, manga, true, interval, translatedLanguage: translatedLanguage??"en")); SendResponse(HttpStatusCode.Accepted, response); break; case "Jobs/DownloadNewChapters": - if(!requestVariables.TryGetValue("connector", out connectorName) || - !requestVariables.TryGetValue("internalId", out internalId) || + if(!requestParams.TryGetValue("connector", out connectorName) || + !requestParams.TryGetValue("internalId", out internalId) || !_parent.TryGetConnector(connectorName, out connector)|| !_parent.TryGetPublicationById(internalId, out tmpManga)) { @@ -329,7 +351,7 @@ public class Server : GlobalBase manga = (Manga)tmpManga!; - if (requestVariables.TryGetValue("ignoreBelowChapterNum", out chapterNumStr)) + if (requestParams.TryGetValue("ignoreBelowChapterNum", out chapterNumStr)) { if (!float.TryParse(chapterNumStr, numberFormatDecimalPoint, out float chapterNum)) { @@ -339,15 +361,15 @@ public class Server : GlobalBase manga.ignoreChaptersBelow = chapterNum; } - if (requestVariables.TryGetValue("customFolderName", out customFolderName)) + if (requestParams.TryGetValue("customFolderName", out customFolderName)) manga.MovePublicationFolder(settings.downloadLocation, customFolderName); - requestVariables.TryGetValue("translatedLanguage", out translatedLanguage); + requestParams.TryGetValue("translatedLanguage", out translatedLanguage); _parent.jobBoss.AddJob(new DownloadNewChapters(this, connector!, manga, false, translatedLanguage: translatedLanguage??"en")); SendResponse(HttpStatusCode.Accepted, response); break; case "Jobs/UpdateMetadata": - if (!requestVariables.TryGetValue("internalId", out internalId)) + if (!requestParams.TryGetValue("internalId", out internalId)) { foreach (Job pJob in _parent.jobBoss.jobs.Where(possibleDncJob => possibleDncJob.jobType is Job.JobType.DownloadNewChaptersJob).ToArray())//ToArray to avoid modyifying while adding new jobs @@ -375,7 +397,7 @@ public class Server : GlobalBase } break; case "Jobs/StartNow": - if (!requestVariables.TryGetValue("jobId", out jobId) || + if (!requestParams.TryGetValue("jobId", out jobId) || !_parent.jobBoss.TryGetJobById(jobId, out job)) { SendResponse(HttpStatusCode.BadRequest, response); @@ -385,7 +407,7 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); break; case "Jobs/Cancel": - if (!requestVariables.TryGetValue("jobId", out jobId) || + if (!requestParams.TryGetValue("jobId", out jobId) || !_parent.jobBoss.TryGetJobById(jobId, out job)) { SendResponse(HttpStatusCode.BadRequest, response); @@ -395,8 +417,8 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); break; case "Settings/UpdateDownloadLocation": - if (!requestVariables.TryGetValue("downloadLocation", out string? downloadLocation) || - !requestVariables.TryGetValue("moveFiles", out string? moveFilesStr) || + if (!requestParams.TryGetValue("downloadLocation", out string? downloadLocation) || + !requestParams.TryGetValue("moveFiles", out string? moveFilesStr) || !Boolean.TryParse(moveFilesStr, out bool moveFiles)) { SendResponse(HttpStatusCode.BadRequest, response); @@ -406,7 +428,7 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); break; /*case "Settings/UpdateWorkingDirectory": - if (!requestVariables.TryGetValue("workingDirectory", out string? workingDirectory)) + if (!requestParams.TryGetValue("workingDirectory", out string? workingDirectory)) { SendResponse(HttpStatusCode.BadRequest, response); break; @@ -415,7 +437,7 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); break;*/ case "Settings/userAgent": - if(!requestVariables.TryGetValue("userAgent", out string? customUserAgent)) + if(!requestParams.TryGetValue("userAgent", out string? customUserAgent)) { SendResponse(HttpStatusCode.BadRequest, response); break; @@ -428,8 +450,8 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); break; case "Settings/customRequestLimit": - if (!requestVariables.TryGetValue("requestType", out string? requestTypeStr) || - !requestVariables.TryGetValue("requestsPerMinute", out string? requestsPerMinuteStr) || + if (!requestParams.TryGetValue("requestType", out string? requestTypeStr) || + !requestParams.TryGetValue("requestsPerMinute", out string? requestsPerMinuteStr) || !Enum.TryParse(requestTypeStr, out RequestType requestType) || !int.TryParse(requestsPerMinuteStr, out int requestsPerMinute)) { @@ -450,7 +472,7 @@ public class Server : GlobalBase settings.ExportSettings(); break; case "NotificationConnectors/Update": - if (!requestVariables.TryGetValue("notificationConnector", out notificationConnectorStr) || + if (!requestParams.TryGetValue("notificationConnector", out notificationConnectorStr) || !Enum.TryParse(notificationConnectorStr, out notificationConnectorType)) { SendResponse(HttpStatusCode.BadRequest, response); @@ -459,8 +481,8 @@ public class Server : GlobalBase if (notificationConnectorType is NotificationConnector.NotificationConnectorType.Gotify) { - if (!requestVariables.TryGetValue("gotifyUrl", out string? gotifyUrl) || - !requestVariables.TryGetValue("gotifyAppToken", out string? gotifyAppToken)) + if (!requestParams.TryGetValue("gotifyUrl", out string? gotifyUrl) || + !requestParams.TryGetValue("gotifyAppToken", out string? gotifyAppToken)) { SendResponse(HttpStatusCode.BadRequest, response); break; @@ -469,7 +491,7 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); }else if (notificationConnectorType is NotificationConnector.NotificationConnectorType.LunaSea) { - if (!requestVariables.TryGetValue("lunaseaWebhook", out string? lunaseaWebhook)) + if (!requestParams.TryGetValue("lunaseaWebhook", out string? lunaseaWebhook)) { SendResponse(HttpStatusCode.BadRequest, response); break; @@ -478,8 +500,8 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); }else if (notificationConnectorType is NotificationConnector.NotificationConnectorType.Ntfy) { - if (!requestVariables.TryGetValue("ntfyUrl", out string? ntfyUrl) || - !requestVariables.TryGetValue("ntfyAuth", out string? ntfyAuth)) + if (!requestParams.TryGetValue("ntfyUrl", out string? ntfyUrl) || + !requestParams.TryGetValue("ntfyAuth", out string? ntfyAuth)) { SendResponse(HttpStatusCode.BadRequest, response); break; @@ -494,7 +516,7 @@ public class Server : GlobalBase break; case "NotificationConnectors/Test": NotificationConnector notificationConnector; - if (!requestVariables.TryGetValue("notificationConnector", out notificationConnectorStr) || + if (!requestParams.TryGetValue("notificationConnector", out notificationConnectorStr) || !Enum.TryParse(notificationConnectorStr, out notificationConnectorType)) { SendResponse(HttpStatusCode.BadRequest, response); @@ -503,8 +525,8 @@ public class Server : GlobalBase if (notificationConnectorType is NotificationConnector.NotificationConnectorType.Gotify) { - if (!requestVariables.TryGetValue("gotifyUrl", out string? gotifyUrl) || - !requestVariables.TryGetValue("gotifyAppToken", out string? gotifyAppToken)) + if (!requestParams.TryGetValue("gotifyUrl", out string? gotifyUrl) || + !requestParams.TryGetValue("gotifyAppToken", out string? gotifyAppToken)) { SendResponse(HttpStatusCode.BadRequest, response); break; @@ -512,7 +534,7 @@ public class Server : GlobalBase notificationConnector = new Gotify(this, gotifyUrl, gotifyAppToken); }else if (notificationConnectorType is NotificationConnector.NotificationConnectorType.LunaSea) { - if (!requestVariables.TryGetValue("lunaseaWebhook", out string? lunaseaWebhook)) + if (!requestParams.TryGetValue("lunaseaWebhook", out string? lunaseaWebhook)) { SendResponse(HttpStatusCode.BadRequest, response); break; @@ -520,8 +542,8 @@ public class Server : GlobalBase notificationConnector = new LunaSea(this, lunaseaWebhook); }else if (notificationConnectorType is NotificationConnector.NotificationConnectorType.Ntfy) { - if (!requestVariables.TryGetValue("ntfyUrl", out string? ntfyUrl) || - !requestVariables.TryGetValue("ntfyAuth", out string? ntfyAuth)) + if (!requestParams.TryGetValue("ntfyUrl", out string? ntfyUrl) || + !requestParams.TryGetValue("ntfyAuth", out string? ntfyAuth)) { SendResponse(HttpStatusCode.BadRequest, response); break; @@ -538,7 +560,7 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); break; case "NotificationConnectors/Reset": - if (!requestVariables.TryGetValue("notificationConnector", out notificationConnectorStr) || + if (!requestParams.TryGetValue("notificationConnector", out notificationConnectorStr) || !Enum.TryParse(notificationConnectorStr, out notificationConnectorType)) { SendResponse(HttpStatusCode.BadRequest, response); @@ -548,7 +570,7 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); break; case "LibraryConnectors/Update": - if (!requestVariables.TryGetValue("libraryConnector", out libraryConnectorStr) || + if (!requestParams.TryGetValue("libraryConnector", out libraryConnectorStr) || !Enum.TryParse(libraryConnectorStr, out libraryConnectorType)) { SendResponse(HttpStatusCode.BadRequest, response); @@ -557,9 +579,9 @@ public class Server : GlobalBase if (libraryConnectorType is LibraryConnector.LibraryType.Kavita) { - if (!requestVariables.TryGetValue("kavitaUrl", out string? kavitaUrl) || - !requestVariables.TryGetValue("kavitaUsername", out string? kavitaUsername) || - !requestVariables.TryGetValue("kavitaPassword", out string? kavitaPassword)) + if (!requestParams.TryGetValue("kavitaUrl", out string? kavitaUrl) || + !requestParams.TryGetValue("kavitaUsername", out string? kavitaUsername) || + !requestParams.TryGetValue("kavitaPassword", out string? kavitaPassword)) { SendResponse(HttpStatusCode.BadRequest, response); break; @@ -568,8 +590,8 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); }else if (libraryConnectorType is LibraryConnector.LibraryType.Komga) { - if (!requestVariables.TryGetValue("komgaUrl", out string? komgaUrl) || - !requestVariables.TryGetValue("komgaAuth", out string? komgaAuth)) + if (!requestParams.TryGetValue("komgaUrl", out string? komgaUrl) || + !requestParams.TryGetValue("komgaAuth", out string? komgaAuth)) { SendResponse(HttpStatusCode.BadRequest, response); break; @@ -584,7 +606,7 @@ public class Server : GlobalBase break; case "LibraryConnectors/Test": LibraryConnector libraryConnector; - if (!requestVariables.TryGetValue("libraryConnector", out libraryConnectorStr) || + if (!requestParams.TryGetValue("libraryConnector", out libraryConnectorStr) || !Enum.TryParse(libraryConnectorStr, out libraryConnectorType)) { SendResponse(HttpStatusCode.BadRequest, response); @@ -593,9 +615,9 @@ public class Server : GlobalBase if (libraryConnectorType is LibraryConnector.LibraryType.Kavita) { - if (!requestVariables.TryGetValue("kavitaUrl", out string? kavitaUrl) || - !requestVariables.TryGetValue("kavitaUsername", out string? kavitaUsername) || - !requestVariables.TryGetValue("kavitaPassword", out string? kavitaPassword)) + if (!requestParams.TryGetValue("kavitaUrl", out string? kavitaUrl) || + !requestParams.TryGetValue("kavitaUsername", out string? kavitaUsername) || + !requestParams.TryGetValue("kavitaPassword", out string? kavitaPassword)) { SendResponse(HttpStatusCode.BadRequest, response); break; @@ -603,8 +625,8 @@ public class Server : GlobalBase libraryConnector = new Kavita(this, kavitaUrl, kavitaUsername, kavitaPassword); }else if (libraryConnectorType is LibraryConnector.LibraryType.Komga) { - if (!requestVariables.TryGetValue("komgaUrl", out string? komgaUrl) || - !requestVariables.TryGetValue("komgaAuth", out string? komgaAuth)) + if (!requestParams.TryGetValue("komgaUrl", out string? komgaUrl) || + !requestParams.TryGetValue("komgaAuth", out string? komgaAuth)) { SendResponse(HttpStatusCode.BadRequest, response); break; @@ -620,7 +642,7 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); break; case "LibraryConnectors/Reset": - if (!requestVariables.TryGetValue("libraryConnector", out libraryConnectorStr) || + if (!requestParams.TryGetValue("libraryConnector", out libraryConnectorStr) || !Enum.TryParse(libraryConnectorStr, out libraryConnectorType)) { SendResponse(HttpStatusCode.BadRequest, response); @@ -637,7 +659,13 @@ public class Server : GlobalBase private void HandleDelete(HttpListenerRequest request, HttpListenerResponse response) { - Dictionary requestVariables = GetRequestVariables(request.Url!.Query); + Dictionary requestVariables = GetRequestVariables(request.Url!.Query); //Variables in the URI + Dictionary requestBody = GetRequestBody(request); //Variables in the JSON body + Dictionary requestParams = new(); //The actual variable used for the API + + //Concatenate the two dictionaries for compatibility with older versions of front-ends + requestParams = requestVariables.Concat(requestBody).ToDictionary(x => x.Key, x => x.Value); + string? connectorName, internalId; MangaConnector connector; Manga manga; @@ -645,7 +673,7 @@ public class Server : GlobalBase switch (path) { case "Jobs": - if (!requestVariables.TryGetValue("jobId", out string? jobId) || + if (!requestParams.TryGetValue("jobId", out string? jobId) || !_parent.jobBoss.TryGetJobById(jobId, out Job? job)) { SendResponse(HttpStatusCode.BadRequest, response); @@ -655,8 +683,8 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); break; case "Jobs/DownloadNewChapters": - if(!requestVariables.TryGetValue("connector", out connectorName) || - !requestVariables.TryGetValue("internalId", out internalId) || + if(!requestParams.TryGetValue("connector", out connectorName) || + !requestParams.TryGetValue("internalId", out internalId) || _parent.GetConnector(connectorName) is null || _parent.GetPublicationById(internalId) is null) { @@ -669,7 +697,7 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); break; case "NotificationConnectors": - if (!requestVariables.TryGetValue("notificationConnector", out string? notificationConnectorStr) || + if (!requestParams.TryGetValue("notificationConnector", out string? notificationConnectorStr) || !Enum.TryParse(notificationConnectorStr, out NotificationConnector.NotificationConnectorType notificationConnectorType)) { SendResponse(HttpStatusCode.BadRequest, response); @@ -679,7 +707,7 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); break; case "LibraryConnectors": - if (!requestVariables.TryGetValue("libraryConnectors", out string? libraryConnectorStr) || + if (!requestParams.TryGetValue("libraryConnector", out string? libraryConnectorStr) || !Enum.TryParse(libraryConnectorStr, out LibraryConnector.LibraryType libraryConnectoryType)) { From 33b8ede4927c4008d3724bc9f574c0e9f6f1118b Mon Sep 17 00:00:00 2001 From: db-2001 Date: Thu, 18 Apr 2024 17:58:23 -0400 Subject: [PATCH 5/7] Use new requestParams variable for AprilFoolsMode setting --- Tranga/Server.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tranga/Server.cs b/Tranga/Server.cs index 0aa2ca9..e7e55c8 100644 --- a/Tranga/Server.cs +++ b/Tranga/Server.cs @@ -431,7 +431,7 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); break; case "Settings/AprilFoolsMode": - if (!requestVariables.TryGetValue("enabled", out string? aprilFoolsModeEnabledStr) || + if (!requestParams.TryGetValue("enabled", out string? aprilFoolsModeEnabledStr) || bool.TryParse(aprilFoolsModeEnabledStr, out bool aprilFoolsModeEnabled)) { SendResponse(HttpStatusCode.BadRequest, response); From 01bab621905a5115045ce49fccd15f7548090010 Mon Sep 17 00:00:00 2001 From: db-2001 Date: Thu, 18 Apr 2024 18:32:49 -0400 Subject: [PATCH 6/7] Log request if unknown --- Tranga/Server.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tranga/Server.cs b/Tranga/Server.cs index e7e55c8..e7c0d41 100644 --- a/Tranga/Server.cs +++ b/Tranga/Server.cs @@ -731,6 +731,9 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.Accepted, response); break; default: + Log("Invalid Request:"); + Log(request.Url!.Query); + Log(requestParams); SendResponse(HttpStatusCode.BadRequest, response); break; } From a8aa7d33707eacc55e2f4b9e31563d6514c4ead8 Mon Sep 17 00:00:00 2001 From: db-2001 Date: Thu, 18 Apr 2024 18:45:19 -0400 Subject: [PATCH 7/7] Okay, actually write request variables to log. --- Tranga/Server.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Tranga/Server.cs b/Tranga/Server.cs index e7c0d41..923680c 100644 --- a/Tranga/Server.cs +++ b/Tranga/Server.cs @@ -733,7 +733,10 @@ public class Server : GlobalBase default: Log("Invalid Request:"); Log(request.Url!.Query); - Log(requestParams); + foreach (KeyValuePair kvp in requestParams) + { + Log("Request variable = {0}, Variable Value = {1}", kvp.Key, kvp.Value); + } SendResponse(HttpStatusCode.BadRequest, response); break; }