diff options
Diffstat (limited to 'src/components/services/Rtorrent.vue')
-rw-r--r-- | src/components/services/Rtorrent.vue | 115 |
1 files changed, 63 insertions, 52 deletions
diff --git a/src/components/services/Rtorrent.vue b/src/components/services/Rtorrent.vue index 75efb7b..ed8e7a6 100644 --- a/src/components/services/Rtorrent.vue +++ b/src/components/services/Rtorrent.vue | |||
@@ -8,14 +8,13 @@ | |||
8 | <span class="down"> | 8 | <span class="down"> |
9 | <i class="fas fa-download"></i> {{ downRate }} | 9 | <i class="fas fa-download"></i> {{ downRate }} |
10 | </span> | 10 | </span> |
11 | <span class="up"> | 11 | <span class="up"> <i class="fas fa-upload"></i> {{ upRate }} </span> |
12 | <i class="fas fa-upload"></i> {{ upRate }} | ||
13 | </span> | ||
14 | </template> | 12 | </template> |
15 | </p> | 13 | </p> |
16 | </template> | 14 | </template> |
17 | <template #indicator> | 15 | <template #indicator> |
18 | <span v-if="!error" class="count">{{ count }} | 16 | <span v-if="!error" class="count" |
17 | >{{ count }} | ||
19 | <template v-if="count === 1">torrent</template> | 18 | <template v-if="count === 1">torrent</template> |
20 | <template v-else>torrents</template> | 19 | <template v-else>torrents</template> |
21 | </span> | 20 | </span> |
@@ -24,38 +23,41 @@ | |||
24 | </template> | 23 | </template> |
25 | 24 | ||
26 | <script> | 25 | <script> |
27 | import Generic from './Generic.vue'; | 26 | import Generic from "./Generic.vue"; |
28 | 27 | ||
29 | // Units to add to download and upload rates. | 28 | // Units to add to download and upload rates. |
30 | const units = ['B', 'kiB', 'MiB', 'GiB']; | 29 | const units = ["B", "kiB", "MiB", "GiB"]; |
31 | 30 | ||
32 | // Take the rate in bytes and keep dividing it by 1k until the lowest | 31 | // Take the rate in bytes and keep dividing it by 1k until the lowest |
33 | // value for which we have a unit is determined. Return the value with | 32 | // value for which we have a unit is determined. Return the value with |
34 | // up to two decimals as a string and unit/s appended. | 33 | // up to two decimals as a string and unit/s appended. |
35 | const displayRate = (rate) => { | 34 | const displayRate = (rate) => { |
36 | let i = 0; | 35 | let i = 0; |
37 | 36 | ||
38 | while (rate > 1000 && i < units.length) { | 37 | while (rate > 1000 && i < units.length) { |
39 | rate /= 1000; | 38 | rate /= 1000; |
40 | i++; | 39 | i++; |
41 | } | 40 | } |
42 | 41 | ||
43 | return Intl.NumberFormat(undefined, {maximumFractionDigits: 2}) | 42 | return ( |
44 | .format(rate || 0) + ` ${units[i]}/s`; | 43 | Intl.NumberFormat(undefined, { maximumFractionDigits: 2 }).format( |
45 | } | 44 | rate || 0 |
45 | ) + ` ${units[i]}/s` | ||
46 | ); | ||
47 | }; | ||
46 | 48 | ||
47 | export default { | 49 | export default { |
48 | name: 'rTorrent', | 50 | name: "rTorrent", |
49 | props: {item: Object}, | 51 | props: { item: Object }, |
50 | components: {Generic}, | 52 | components: { Generic }, |
51 | // Properties for download, upload, torrent count and errors. | 53 | // Properties for download, upload, torrent count and errors. |
52 | data: () => ({dl: null, ul: null, count: null, error: null}), | 54 | data: () => ({ dl: null, ul: null, count: null, error: null }), |
53 | // Computed properties for the rate labels. | 55 | // Computed properties for the rate labels. |
54 | computed: { | 56 | computed: { |
55 | downRate: function() { | 57 | downRate: function () { |
56 | return displayRate(this.dl); | 58 | return displayRate(this.dl); |
57 | }, | 59 | }, |
58 | upRate: function() { | 60 | upRate: function () { |
59 | return displayRate(this.ul); | 61 | return displayRate(this.ul); |
60 | }, | 62 | }, |
61 | }, | 63 | }, |
@@ -72,7 +74,7 @@ export default { | |||
72 | if (torrentInterval > 0) { | 74 | if (torrentInterval > 0) { |
73 | setInterval(() => this.fetchCount(), torrentInterval); | 75 | setInterval(() => this.fetchCount(), torrentInterval); |
74 | } | 76 | } |
75 | 77 | ||
76 | // Fetch the initial values. | 78 | // Fetch the initial values. |
77 | this.fetchRates(); | 79 | this.fetchRates(); |
78 | this.fetchCount(); | 80 | this.fetchCount(); |
@@ -81,62 +83,71 @@ export default { | |||
81 | // Perform two calls to the XML-RPC service and fetch download | 83 | // Perform two calls to the XML-RPC service and fetch download |
82 | // and upload rates. Values are saved to the `ul` and `dl` | 84 | // and upload rates. Values are saved to the `ul` and `dl` |
83 | // properties. | 85 | // properties. |
84 | fetchRates: async function() { | 86 | fetchRates: async function () { |
85 | this.getRate('throttle.global_up.rate') | 87 | this.getRate("throttle.global_up.rate") |
86 | .then((ul) => this.ul = ul) | 88 | .then((ul) => (this.ul = ul)) |
87 | .catch(() => this.error = true); | 89 | .catch(() => (this.error = true)); |
88 | 90 | ||
89 | this.getRate('throttle.global_down.rate') | 91 | this.getRate("throttle.global_down.rate") |
90 | .then((dl) => this.dl = dl) | 92 | .then((dl) => (this.dl = dl)) |
91 | .catch(() => this.error = true); | 93 | .catch(() => (this.error = true)); |
92 | }, | 94 | }, |
93 | // Perform a call to the XML-RPC service to fetch the number of | 95 | // Perform a call to the XML-RPC service to fetch the number of |
94 | // torrents. | 96 | // torrents. |
95 | fetchCount: async function() { | 97 | fetchCount: async function () { |
96 | this.getCount().catch(() => this.error = true); | 98 | this.getCount().catch(() => (this.error = true)); |
97 | }, | 99 | }, |
98 | // Fetch a numeric value from the XML-RPC service by requesting | 100 | // Fetch a numeric value from the XML-RPC service by requesting |
99 | // the specified method name and parsing the XML. The response | 101 | // the specified method name and parsing the XML. The response |
100 | // is expected to adhere to the structure of a single numeric | 102 | // is expected to adhere to the structure of a single numeric |
101 | // value. | 103 | // value. |
102 | getRate: async function(methodName) { | 104 | getRate: async function (methodName) { |
103 | return this.getXml(methodName) | 105 | return this.getXml(methodName).then((xml) => |
104 | .then((xml) => parseInt(xml.getElementsByTagName('value')[0].firstChild.textContent, 10)); | 106 | parseInt( |
107 | xml.getElementsByTagName("value")[0].firstChild.textContent, | ||
108 | 10 | ||
109 | ) | ||
110 | ); | ||
105 | }, | 111 | }, |
106 | // Fetch the numer of torrents by requesting the download list | 112 | // Fetch the numer of torrents by requesting the download list |
107 | // and counting the number of entries therein. | 113 | // and counting the number of entries therein. |
108 | getCount: async function() { | 114 | getCount: async function () { |
109 | return this.getXml('download_list') | 115 | return this.getXml("download_list").then((xml) => { |
110 | .then((xml) => { | 116 | const arrayEl = xml.getElementsByTagName("array"); |
111 | const arrayEl = xml.getElementsByTagName('array'); | 117 | this.count = arrayEl |
112 | this.count = arrayEl ? arrayEl[0].getElementsByTagName('value').length : 0; | 118 | ? arrayEl[0].getElementsByTagName("value").length |
113 | }); | 119 | : 0; |
120 | }); | ||
114 | }, | 121 | }, |
115 | // Perform a call to the XML-RPC service and parse the response | 122 | // Perform a call to the XML-RPC service and parse the response |
116 | // as XML, which is then returned. | 123 | // as XML, which is then returned. |
117 | getXml: async function(methodName) { | 124 | getXml: async function (methodName) { |
118 | const headers = {'Content-Type': 'text/xml'}; | 125 | const headers = { "Content-Type": "text/xml" }; |
119 | 126 | ||
120 | if (this.item.username && this.item.password) { | 127 | if (this.item.username && this.item.password) { |
121 | headers['Authorization'] = `${this.item.username}:${this.item.password}`; | 128 | headers[ |
129 | "Authorization" | ||
130 | ] = `${this.item.username}:${this.item.password}`; | ||
122 | } | 131 | } |
123 | 132 | ||
124 | return fetch(`${this.item.xmlrpc.replace(/\/$/, '')}/RPC2`, { | 133 | return fetch(`${this.item.xmlrpc.replace(/\/$/, "")}/RPC2`, { |
125 | method: 'POST', | 134 | method: "POST", |
126 | headers, | 135 | headers, |
127 | body: `<methodCall><methodName>${methodName}</methodName></methodCall>` | 136 | body: `<methodCall><methodName>${methodName}</methodName></methodCall>`, |
128 | }) | 137 | }) |
129 | .then((response) => { | 138 | .then((response) => { |
130 | if (!response.ok) { | 139 | if (!response.ok) { |
131 | throw Error(response.statusText); | 140 | throw Error(response.statusText); |
132 | } | 141 | } |
133 | 142 | ||
134 | return response.text(); | 143 | return response.text(); |
135 | }) | 144 | }) |
136 | .then((text) => Promise.resolve(new DOMParser().parseFromString(text, 'text/xml'))); | 145 | .then((text) => |
137 | } | 146 | Promise.resolve(new DOMParser().parseFromString(text, "text/xml")) |
138 | } | 147 | ); |
139 | } | 148 | }, |
149 | }, | ||
150 | }; | ||
140 | </script> | 151 | </script> |
141 | 152 | ||
142 | <style scoped lang="scss"> | 153 | <style scoped lang="scss"> |
@@ -150,4 +161,4 @@ export default { | |||
150 | color: var(--text); | 161 | color: var(--text); |
151 | font-size: 0.8em; | 162 | font-size: 0.8em; |
152 | } | 163 | } |
153 | </style> \ No newline at end of file | 164 | </style> |