mirror of
https://github.com/bastienwirtz/homer.git
synced 2025-03-13 06:49:32 +01:00
parent
7edcfe0705
commit
51ba5ff503
@ -25,6 +25,7 @@ within Homer:
|
|||||||
- [Mealie](#mealie)
|
- [Mealie](#mealie)
|
||||||
- [Healthchecks](#healthchecks)
|
- [Healthchecks](#healthchecks)
|
||||||
- [Proxmox](#proxmox)
|
- [Proxmox](#proxmox)
|
||||||
|
- [rTorrent](#rtorrent)
|
||||||
- [qBittorrent](#qbittorrent)
|
- [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.
|
||||||
@ -249,6 +250,27 @@ Two lines are needed in the config.yml :
|
|||||||
The url must be the root url of the Healthchecks application.
|
The url must be the root url of the Healthchecks application.
|
||||||
The Healthchecks API key can be found in Settings > API Access > API key (read-only). The key is needed to access Healthchecks API.
|
The Healthchecks API key can be found in Settings > API Access > API key (read-only). The key is needed to access Healthchecks API.
|
||||||
|
|
||||||
|
## rTorrent
|
||||||
|
|
||||||
|
This service displays the global upload and download rates, as well as the number of torrents
|
||||||
|
listed in rTorrent. The service communicates with the rTorrent XML-RPC interface which needs
|
||||||
|
to be accessible from the browser. Please consult
|
||||||
|
[the instructions](https://github.com/rakshasa/rtorrent-doc/blob/master/RPC-Setup-XMLRPC.md)
|
||||||
|
for setting up rTorrent and make sure the correct CORS-settings are applied. Examples for various
|
||||||
|
servers can be found at https://enable-cors.org/server.html.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: "rTorrent"
|
||||||
|
logo: "assets/tools/sample.png"
|
||||||
|
url: "http://192.168.0.151" # Your rTorrent web UI, f.e. ruTorrent or Flood.
|
||||||
|
xmlrpc: "http://192.168.0.151:8081" # Reverse proxy for rTorrent's XML-RPC.
|
||||||
|
type: "Rtorrent"
|
||||||
|
rateInterval: 5000 # Interval for updating the download and upload rates.
|
||||||
|
torrentInterval: 60000 # Interval for updating the torrent count.
|
||||||
|
username: "username" # Username for logging into rTorrent (if applicable).
|
||||||
|
password: "password" # Password for logging into rTorrent (if applicable).
|
||||||
|
|
||||||
|
|
||||||
## Proxmox
|
## Proxmox
|
||||||
|
|
||||||
This service displays status information of a Proxmox node (VMs running and disk, memory and cpu used). It uses the proxmox API and [API Tokens](https://pve.proxmox.com/pve-docs/pveum-plain.html) for authorization so you need to generate one to set in the yaml config. You can set it up in Proxmox under Permissions > API Tokens. You also need to know the realm the user of the API Token is assigned to (by default pam).
|
This service displays status information of a Proxmox node (VMs running and disk, memory and cpu used). It uses the proxmox API and [API Tokens](https://pve.proxmox.com/pve-docs/pveum-plain.html) for authorization so you need to generate one to set in the yaml config. You can set it up in Proxmox under Permissions > API Tokens. You also need to know the realm the user of the API Token is assigned to (by default pam).
|
||||||
|
10
dummy-data/rtorrent/download_list
Normal file
10
dummy-data/rtorrent/download_list
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<methodResponse>
|
||||||
|
<params>
|
||||||
|
<param><value><array><data>
|
||||||
|
<value><string>2BAC78C9E10D82415142E57D24601F2FD8927816</string></value>
|
||||||
|
<value><string>8BB10DB9EA239106D4907601C342ABBA29BE4391</string></value>
|
||||||
|
<value><string>2790CE71493BE7083929D5A1CE9CFD6B8394F224</string></value>
|
||||||
|
</data></array></value></param>
|
||||||
|
</params>
|
||||||
|
</methodResponse>
|
6
dummy-data/rtorrent/global_down
Normal file
6
dummy-data/rtorrent/global_down
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<methodResponse>
|
||||||
|
<params>
|
||||||
|
<param><value><i8>149279</i8></value></param>
|
||||||
|
</params>
|
||||||
|
</methodResponse>
|
6
dummy-data/rtorrent/global_up
Normal file
6
dummy-data/rtorrent/global_up
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<methodResponse>
|
||||||
|
<params>
|
||||||
|
<param><value><i8>45616</i8></value></param>
|
||||||
|
</params>
|
||||||
|
</methodResponse>
|
153
src/components/services/Rtorrent.vue
Normal file
153
src/components/services/Rtorrent.vue
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
<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">
|
||||||
|
<i class="fas fa-download"></i> {{ downRate }}
|
||||||
|
</span>
|
||||||
|
<span class="up">
|
||||||
|
<i class="fas fa-upload"></i> {{ 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 Generic from './Generic.vue';
|
||||||
|
|
||||||
|
// Units to add to download and upload rates.
|
||||||
|
const units = ['B', 'kiB', 'MiB', 'GiB'];
|
||||||
|
|
||||||
|
// 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: 'rTorrent',
|
||||||
|
props: {item: Object},
|
||||||
|
components: {Generic},
|
||||||
|
// Properties for download, upload, torrent count and errors.
|
||||||
|
data: () => ({dl: null, ul: null, count: null, error: null}),
|
||||||
|
// Computed properties for the rate labels.
|
||||||
|
computed: {
|
||||||
|
downRate: function() {
|
||||||
|
return displayRate(this.dl);
|
||||||
|
},
|
||||||
|
upRate: function() {
|
||||||
|
return displayRate(this.ul);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// Set intervals if configured so the rates and/or torrent count
|
||||||
|
// will be updated.
|
||||||
|
const rateInterval = parseInt(this.item.rateInterval, 10) || 0;
|
||||||
|
const torrentInterval = parseInt(this.item.torrentInterval, 10) || 0;
|
||||||
|
|
||||||
|
if (rateInterval > 0) {
|
||||||
|
setInterval(() => this.fetchRates(), rateInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (torrentInterval > 0) {
|
||||||
|
setInterval(() => this.fetchCount(), torrentInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the initial values.
|
||||||
|
this.fetchRates();
|
||||||
|
this.fetchCount();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// Perform two calls to the XML-RPC service and fetch download
|
||||||
|
// and upload rates. Values are saved to the `ul` and `dl`
|
||||||
|
// properties.
|
||||||
|
fetchRates: async function() {
|
||||||
|
this.getRate('throttle.global_up.rate')
|
||||||
|
.then((ul) => this.ul = ul)
|
||||||
|
.catch(() => this.error = true);
|
||||||
|
|
||||||
|
this.getRate('throttle.global_down.rate')
|
||||||
|
.then((dl) => this.dl = dl)
|
||||||
|
.catch(() => this.error = true);
|
||||||
|
},
|
||||||
|
// Perform a call to the XML-RPC service to fetch the number of
|
||||||
|
// torrents.
|
||||||
|
fetchCount: async function() {
|
||||||
|
this.getCount().catch(() => this.error = true);
|
||||||
|
},
|
||||||
|
// Fetch a numeric value from the XML-RPC service by requesting
|
||||||
|
// the specified method name and parsing the XML. The response
|
||||||
|
// is expected to adhere to the structure of a single numeric
|
||||||
|
// value.
|
||||||
|
getRate: async function(methodName) {
|
||||||
|
return this.getXml(methodName)
|
||||||
|
.then((xml) => parseInt(xml.getElementsByTagName('value')[0].firstChild.textContent, 10));
|
||||||
|
},
|
||||||
|
// Fetch the numer of torrents by requesting the download list
|
||||||
|
// and counting the number of entries therein.
|
||||||
|
getCount: async function() {
|
||||||
|
return this.getXml('download_list')
|
||||||
|
.then((xml) => {
|
||||||
|
const arrayEl = xml.getElementsByTagName('array');
|
||||||
|
this.count = arrayEl ? arrayEl[0].getElementsByTagName('value').length : 0;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// Perform a call to the XML-RPC service and parse the response
|
||||||
|
// as XML, which is then returned.
|
||||||
|
getXml: async function(methodName) {
|
||||||
|
const headers = {'Content-Type': 'text/xml'};
|
||||||
|
|
||||||
|
if (this.item.username && this.item.password) {
|
||||||
|
headers['Authorization'] = `${this.item.username}:${this.item.password}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch(`${this.item.xmlrpc.replace(/\/$/, '')}/RPC2`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers,
|
||||||
|
body: `<methodCall><methodName>${methodName}</methodName></methodCall>`
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw Error(response.statusText);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.text();
|
||||||
|
})
|
||||||
|
.then((text) => Promise.resolve(new DOMParser().parseFromString(text, 'text/xml')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.error {
|
||||||
|
color: #e51111 !important;
|
||||||
|
}
|
||||||
|
.down {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
.count {
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue
Block a user