qBittorrent service (#540)

qBittorrent service
This commit is contained in:
Shagon94 2022-10-30 18:32:51 +01:00 committed by GitHub
parent ac5f04f058
commit cfd31b86b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 229 additions and 23 deletions

View File

@ -7,25 +7,28 @@ if your homer instance is secured behind some form of authentication or access r
Available services are in `src/components/`. Here is an overview of all custom services that are available Available services are in `src/components/`. Here is an overview of all custom services that are available
within Homer: within Homer:
+ [PiHole](#pihole)
+ [OpenWeatherMap](#openweathermap) - [Custom Services](#custom-services)
+ [Medusa](#medusa) - [Common options](#common-options)
+ [Lidarr, Prowlarr, Sonarr and Radarr](#lidarr-prowlarr-sonarr-and-radarr) - [PiHole](#pihole)
+ [PaperlessNG](#paperlessng) - [OpenWeatherMap](#openweathermap)
+ [Ping](#ping) - [Medusa](#medusa)
+ [Prometheus](#prometheus) - [Lidarr, Prowlarr, Sonarr and Radarr](#lidarr-prowlarr-sonarr-and-radarr)
+ [AdGuard Home](#adguard-home) - [PaperlessNG](#paperlessng)
+ [Portainer](#portainer) - [Ping](#ping)
+ [Emby / Jellyfin](#emby--jellyfin) - [Prometheus](#prometheus)
+ [Uptime Kuma](#uptime-kuma) - [AdGuard Home](#adguard-home)
+ [Tautulli](#tautulli) - [Portainer](#portainer)
+ [Mealie](#mealie) - [Emby / Jellyfin](#emby--jellyfin)
+ [Healthchecks](#healthchecks) - [Uptime Kuma](#uptime-kuma)
+ [Proxmox](#proxmox) - [Tautulli](#tautulli)
- [Mealie](#mealie)
- [Healthchecks](#healthchecks)
- [Proxmox](#proxmox)
- [qBittorrent](#qbittorrent)
If you experiencing any issue, please have a look to the [troubleshooting](troubleshooting.md) page. If you experiencing any issue, please have a look to the [troubleshooting](troubleshooting.md) page.
## Common options ## Common options
```yaml ```yaml
@ -272,4 +275,23 @@ Configuration example:
warning_value: 50 warning_value: 50
danger_value: 80 danger_value: 80
api_token: "PVEAPIToken=root@pam!your-api-token-name=your-api-token-key" api_token: "PVEAPIToken=root@pam!your-api-token-name=your-api-token-key"
``` ```
## qBittorrent
This service displays the global upload and download rates, as well as the number of torrents
listed. The service communicates with the qBittorrent API interface which needs
to be accessible from the browser. Please consult
[the instructions](https://github.com/qbittorrent/qBittorrent/pull/12579)
for setting up qBittorrent and make sure the correct CORS-settings are applied. Examples for various
servers can be found at [enable-cors.org](https://enable-cors.org/server.html).
```yaml
- name: "qBittorrent"
logo: "assets/tools/sample.png"
url: "http://192.168.1.2:8080" # Your rTorrent web UI, f.e. ruTorrent or Flood.
type: "qBittorrent"
rateInterval: 2000 # Interval for updating the download and upload rates.
torrentInterval: 5000 # Interval for updating the torrent count.
target: "_blank" # optional html a tag target attribute
```

View File

@ -1,15 +1,16 @@
# Dummy data # Dummy data
This directory content makes possible to test custom services cards or create a demo without actually running the service. This directory content makes possible to test custom services cards or create a demo without actually running the service.
The principle is simple: save a sample output of the API used in the service in a static file in this directory. The path must be identical as the service endpoint to be used seamlessly. The principle is simple: save a sample output of the API used in the service in a static file in this directory. The path must be identical as the service endpoint to be used seamlessly.
## How to add a new services sample: ## How to add a new services sample
- create a directory for your service, and any sub-folder existing in the service api path. - create a directory for your service, and any sub-folder existing in the service api path.
- save the api output in a file named after the service endpoint. - save the api output in a file named after the service endpoint.
Example: Example:
```
```sh
mkdir pihole mkdir pihole
curl http://my-pihole.me/admin/api.php -o pihole/api.php # /admin is omited because for PiHole, the implementation expect it to be in the base url (`url` or `enpoint` property) curl http://my-pihole.me/admin/api.php -o pihole/api.php # /admin is omited because for PiHole, the implementation expect it to be in the base url (`url` or `endpoint` property)
``` ```

View File

@ -0,0 +1,53 @@
[
{
"added_on": 1666985518,
"amount_left": 0,
"auto_tmm": false,
"availability": -1,
"category": "",
"completed": 1474873344,
"completion_on": 1666985584,
"content_path": "/downloads/ubuntu-22.04.1-live-server-amd64.iso",
"dl_limit": -1,
"dlspeed": 0,
"download_path": "",
"downloaded": 1513976240,
"downloaded_session": 0,
"eta": 8640000,
"f_l_piece_prio": false,
"force_start": false,
"hash": "cf3ea75e2ebbd30e0da6e6e215e2226bf35f2e33",
"infohash_v1": "cf3ea75e2ebbd30e0da6e6e215e2226bf35f2e33",
"infohash_v2": "",
"last_activity": 1666985588,
"magnet_uri": "magnet:?xt=urn:btih:cf3ea75e2ebbd30e0da6e6e215e2226bf35f2e33&dn=ubuntu-22.04.1-live-server-amd64.iso&tr=https%3a%2f%2ftorrent.ubuntu.com%2fannounce&tr=https%3a%2f%2fipv6.torrent.ubuntu.com%2fannounce",
"max_ratio": 0,
"max_seeding_time": -1,
"name": "ubuntu-22.04.1-live-server-amd64.iso",
"num_complete": 0,
"num_incomplete": 583,
"num_leechs": 0,
"num_seeds": 0,
"priority": 0,
"progress": 1,
"ratio": 1.7163413343924075e-05,
"ratio_limit": -2,
"save_path": "/downloads/",
"seeding_time": 4,
"seeding_time_limit": -2,
"seen_complete": 1666985584,
"seq_dl": false,
"size": 1474873344,
"state": "pausedUP",
"super_seeding": false,
"tags": "",
"time_active": 69,
"total_size": 1474873344,
"tracker": "",
"trackers_count": 2,
"up_limit": -1,
"uploaded": 25985,
"uploaded_session": 0,
"upspeed": 0
}
]

View File

@ -0,0 +1,10 @@
{
"connection_status": "connected",
"dht_nodes": 318,
"dl_info_data": 23481469329,
"dl_info_speed": 1234567,
"dl_rate_limit": 40960000,
"up_info_data": 1788370216,
"up_info_speed": 765432,
"up_rate_limit": 10547200
}

View File

@ -0,0 +1,120 @@
<template>
<Generic :item="item">
<template #content>
<p class="title is-4">{{ item.name }}</p>
<p class="subtitle is-6">
<span v-if="error" class="error">An error has occurred.</span>
<template v-else>
<span class="down monospace">
<p class="fas fa-download "></p> {{ downRate }}
</span>
<span class="up monospace">
<p class="fas fa-upload"></p> {{ upRate }}
</span>
</template>
</p>
</template>
<template #indicator>
<span v-if="!error" class="count">{{ count }}
<template v-if="count === 1">torrent</template>
<template v-else>torrents</template>
</span>
</template>
</Generic>
</template>
<script>
import service from "@/mixins/service.js";
import Generic from "./Generic.vue";
const units = ["B", "KB", "MB", "GB"];
// Take the rate in bytes and keep dividing it by 1k until the lowest
// value for which we have a unit is determined. Return the value with
// up to two decimals as a string and unit/s appended.
const displayRate = (rate) => {
let i = 0;
while (rate > 1000 && i < units.length) {
rate /= 1000;
i++;
}
return (
Intl.NumberFormat(undefined, { maximumFractionDigits: 2 }).format(
rate || 0
) + ` ${units[i]}/s`
);
};
export default {
name: "qBittorrent",
mixins: [service],
props: { item: Object },
components: { Generic },
data: () => ({ dl: null, ul: null, count: null, error: null }),
computed: {
downRate: function () {
return displayRate(this.dl);
},
upRate: function () {
return displayRate(this.ul);
},
},
created() {
const rateInterval = parseInt(this.item.rateInterval, 10) || 0;
const torrentInterval = parseInt(this.item.torrentInterval, 10) || 0;
if (rateInterval > 0) {
setInterval(() => this.getRate(), rateInterval);
}
if (torrentInterval > 0) {
setInterval(() => this.fetchCount(), torrentInterval);
}
this.getRate();
this.fetchCount();
},
methods: {
fetchCount: async function () {
try {
const body = await this.fetch('/api/v2/torrents/info');
this.error = false;
this.count = body.length;
} catch (e) {
this.error = true;
console.error(e);
}
},
getRate: async function () {
try {
const body = await this.fetch('/api/v2/transfer/info');
this.error = false;
this.dl = body.dl_info_speed;
this.ul = body.up_info_speed;
} catch (e) {
this.error = true;
console.error(e);
}
},
},
};
</script>
<style scoped lang="scss">
.error {
color: #e51111 !important;
}
.down {
margin-right: 1em;
}
.count {
color: var(--text);
font-size: 0.8em;
}
.monospace {
font-weight: 300;
font-family: monospace;
}
</style>