Add ability to control Deluge's upload and download speeds based on Jellyfin streams.

This commit is contained in:
2026-04-20 20:30:43 +10:00
parent 758e4ea9a4
commit bc46a8f179
4 changed files with 250 additions and 0 deletions

147
controllers/deluge.php Normal file
View File

@@ -0,0 +1,147 @@
<?php
/**
* Copyright 2026, Dreytac <dreytac@hobbyhome.net>
*
* This file is part of Kirby Deluge.
*
* Kirby Deluge is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
*
* Kirby Deluge is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with Kirby Deluge. If not, see <https://www.gnu.org/licenses/>.
*/
return function ($page) {
$currentStreams = $page->currentStreams()->toInt();
$lastSeen = $page->lastSeen()->toInt();
$curl = curl_init($page->delugeUrl());
$curlOptions = [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_HTTPHEADER => ["Accept: application/json", "Content-Type: application/json"],
CURLOPT_ENCODING => "",
CURLOPT_COOKIEJAR => "",
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => true,
CURLINFO_HEADER_OUT => true,
];
curl_setopt_array($curl, $curlOptions);
$reqId = 0;
$response = site()->makeRequest($curl, $reqId, "auth.login", [$page->delugePassword()->toString()]);
$reqId++;
if (get("s") == "inc") {
// Increment number of streams and ensure speeds are set to minimums.
$currentStreams++;
$lastSeen = time();
site()->makeRequest($curl, $reqId, "core.set_config", [["max_download_speed" => $page->minDownSpeed()->toInt()]]);
$reqId++;
site()->makeRequest($curl, $reqId, "core.set_config", [["max_upload_speed" => $page->minUpSpeed()->toInt()]]);
} elseif (get("s") == "dec") {
// Decrement number of streams and, if 0 active streams, ensure speeds are set to maximum.
$currentStreams--;
if ($lastSeen > 0) {
if ($lastSeen < time() - ($page->maxTimeAtMin()->toInt() * 60)) {
// Assume the sessions have finished and clear them.
$currentStreams = 0;
$lastSeen = 0;
}
}
if ($currentStreams <= 0) {
site()->makeRequest($curl, $reqId, "core.set_config", [["max_download_speed" => $page->maxDownSpeed()->toInt()]]);
$reqId++;
site()->makeRequest($curl, $reqId, "core.set_config", [["max_upload_speed" => $page->maxUpSpeed()->toInt()]]);
}
} elseif (get("s") == "reset") {
// Reset streams and speeds back to 0 and maximum respectively.
$currentStreams = 0;
$lastSeen = 0;
site()->makeRequest($curl, $reqId, "core.set_config", [["max_download_speed" => $page->maxDownSpeed()->toInt()]]);
$reqId++;
site()->makeRequest($curl, $reqId, "core.set_config", [["max_upload_speed" => $page->maxUpSpeed()->toInt()]]);
} elseif (get("s") == "update") {
// Forceably get a list of active sessions from Jellyfin and update Deluge accordingly.
$jfCurl = curl_init($page->jellyfinUrl()->toString() . "/Sessions");
$jfCurlOptions = [
CURLOPT_RETURNTRANSFER => true,
// CURLOPT_HEADER => true,
CURLOPT_HTTPHEADER => ["Accept: application/json", "Content-Type: application/json", "Authorization: MediaBrowser Token=\"{$page->jellyfinApiKey()->toString()}\""],
CURLOPT_ENCODING => "",
CURLOPT_COOKIEJAR => "",
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => true,
CURLINFO_HEADER_OUT => true,
CURLOPT_VERBOSE => true,
];
curl_setopt_array($jfCurl, $jfCurlOptions);
$sessions = site()->makeRequest($jfCurl, $reqId, "get");
$reqId++;
curl_close($jfCurl);
$sessionsActive = 0;
if (!is_null($sessions)) {
foreach ($sessions as $session) {
if (isset($session["NowPlayingItem"])) {
if ($session["NowPlayingItem"]["Type"] !== "Audio") {
$sessionsActive++;
}
}
}
if ($sessionsActive == 0) {
// There are no sessions active. Set to maximum speed.
$currentStreams = 0;
$lastSeen = 0;
site()->makeRequest($curl, $reqId, "core.set_config", [["max_download_speed" => $page->maxDownSpeed()->toInt()]]);
$reqId++;
site()->makeRequest($curl, $reqId, "core.set_config", [["max_upload_speed" => $page->maxUpSpeed()->toInt()]]);
} else {
// There are sessions active. Set to minimum speed.
$currentStreams = $sessionsActive;
$lastSeen = time();
site()->makeRequest($curl, $reqId, "core.set_config", [["max_download_speed" => $page->minDownSpeed()->toInt()]]);
$reqId++;
site()->makeRequest($curl, $reqId, "core.set_config", [["max_upload_speed" => $page->minUpSpeed()->toInt()]]);
}
} else {
// We couldn't access Jellyfin. Assume there's something wrong and that no sessions are active.
$currentStreams = 0;
$lastSeen = 0;
site()->makeRequest($curl, $reqId, "core.set_config", [["max_download_speed" => $page->maxDownSpeed()->toInt()]]);
$reqId++;
site()->makeRequest($curl, $reqId, "core.set_config", [["max_upload_speed" => $page->maxUpSpeed()->toInt()]]);
}
}
// We should never have less than 0 streams active.
$currentStreams = $currentStreams < 0 ? 0 : $currentStreams;
$page = kirby()->impersonate("kirby", function () use ($page, $currentStreams, $lastSeen) {
return $page->update([
"currentStreams" => $currentStreams,
"lastSeen" => $lastSeen,
]);
});
curl_close($curl);
if (!($user = kirby()->user() and $user->role()->isAdmin())) {
// Limit access to page to administrators only.
echo new Response(Data::encode(["currentStreams" => $currentStreams, "lastSeen" => $lastSeen], "json"), "text/json");
exit();
}
return compact("page");
};