diff options
author | Evan Steinkerchner <esteinkerchner@gmail.com> | 2022-04-19 20:18:39 -0400 |
---|---|---|
committer | Evan Steinkerchner <esteinkerchner@gmail.com> | 2022-04-19 20:18:39 -0400 |
commit | 33f75a798a204e2e7fbecb42571ed007092718c2 (patch) | |
tree | af016abba286ca1a0b3fb90aaaf349df0a04c24b | |
parent | a2dfffab6892c6976fc8b880f75c314506259675 (diff) | |
parent | 9c370d3c5e25d1a5e3e04f6e146e35883e4ac2e3 (diff) | |
download | homer-33f75a798a204e2e7fbecb42571ed007092718c2.tar.gz homer-33f75a798a204e2e7fbecb42571ed007092718c2.tar.zst homer-33f75a798a204e2e7fbecb42571ed007092718c2.zip |
Merge branch 'main' into proxy-api
-rw-r--r-- | docs/customservices.md | 40 | ||||
-rw-r--r-- | src/components/services/Emby.vue | 118 | ||||
-rw-r--r-- | src/components/services/Portainer.vue | 6 | ||||
-rw-r--r-- | yarn.lock | 6 |
4 files changed, 166 insertions, 4 deletions
diff --git a/docs/customservices.md b/docs/customservices.md index cb68e1d..509278f 100644 --- a/docs/customservices.md +++ b/docs/customservices.md | |||
@@ -6,7 +6,17 @@ apikey included in the configuration file is exposed to anyone who can access th | |||
6 | if your homer instance is secured behind some form of authentication or access restriction. | 6 | if your homer instance is secured behind some form of authentication or access restriction. |
7 | 7 | ||
8 | Available services are in `src/components/`. Here is an overview of all custom services that are available | 8 | Available services are in `src/components/`. Here is an overview of all custom services that are available |
9 | within Homer. | 9 | within Homer: |
10 | + [PiHole](#pihole) | ||
11 | + [OpenWeatherMap](#openweathermap) | ||
12 | + [Medusa](#medusa) | ||
13 | + [Lidarr, Prowlarr, Sonarr and Radarr](#lidarr-prowlarr-sonarr-and-radarr) | ||
14 | + [PaperlessNG](#paperlessng) | ||
15 | + [Ping](#ping) | ||
16 | + [Prometheus](#prometheus) | ||
17 | + [AdGuard Home](#adguard-home) | ||
18 | + [Portainer](#portainer) | ||
19 | + [Emby](#emby) | ||
10 | 20 | ||
11 | If you experiencing any issue, please have a look to the [troubleshooting](troubleshooting.md) page. | 21 | If you experiencing any issue, please have a look to the [troubleshooting](troubleshooting.md) page. |
12 | 22 | ||
@@ -126,11 +136,23 @@ For Prometheus you need to set the type to Prometheus and provide a url. | |||
126 | # subtitle: "Monitor data server" | 136 | # subtitle: "Monitor data server" |
127 | ``` | 137 | ``` |
128 | 138 | ||
139 | ## AdGuard Home | ||
140 | For AdGuard Home you need to set the type to AdGuard, if you have somes issues as 403 responses on requests you need to provide authentification in headers for locations needed as below. | ||
141 | |||
142 | ```yaml | ||
143 | - name: "Adguard" | ||
144 | logo: "assets/tools/adguardhome.png" | ||
145 | url: "https://adguard.exemple.com" | ||
146 | target: "_blank" | ||
147 | type: "AdGuardHome" | ||
148 | ``` | ||
149 | |||
129 | ## Portainer | 150 | ## Portainer |
130 | 151 | ||
131 | This service displays info about the total number of containers managed by your Portainer instance. | 152 | This service displays info about the total number of containers managed by your Portainer instance. |
132 | In order to use it, you must be using Portainer version 1.11 or later. Generate an access token from the UI and pass | 153 | In order to use it, you must be using Portainer version 1.11 or later. Generate an access token from the UI and pass |
133 | it to the apikey field. | 154 | it to the apikey field. |
155 | By default, every connected environments will be checked. To select specific ones,add an "environments" entry which can be a simple string or an array containing all the selected environments name. | ||
134 | 156 | ||
135 | See https://docs.portainer.io/v/ce-2.11/user/account-settings#access-tokens | 157 | See https://docs.portainer.io/v/ce-2.11/user/account-settings#access-tokens |
136 | 158 | ||
@@ -140,4 +162,20 @@ See https://docs.portainer.io/v/ce-2.11/user/account-settings#access-tokens | |||
140 | url: "http://192.168.0.151/" | 162 | url: "http://192.168.0.151/" |
141 | type: "Portainer" | 163 | type: "Portainer" |
142 | apikey: "MY-SUPER-SECRET-API-KEY" | 164 | apikey: "MY-SUPER-SECRET-API-KEY" |
165 | # environments: | ||
166 | # - "raspberry" | ||
167 | # - "local" | ||
168 | ``` | ||
169 | |||
170 | ## Emby | ||
171 | |||
172 | You need to set the type to Emby, provide an api key and choose which stats to show if the subtitle is disabled. | ||
173 | |||
174 | ```yaml | ||
175 | - name: "Emby" | ||
176 | logo: "assets/tools/sample.png" | ||
177 | url: "http://192.168.0.151/" | ||
178 | type: "Emby" | ||
179 | apikey: "MY-SUPER-SECRET-API-KEY" | ||
180 | libraryType: "music" #Choose which stats to show. Can be one of: music, series or movies. | ||
143 | ``` | 181 | ``` |
diff --git a/src/components/services/Emby.vue b/src/components/services/Emby.vue new file mode 100644 index 0000000..25a2612 --- /dev/null +++ b/src/components/services/Emby.vue | |||
@@ -0,0 +1,118 @@ | |||
1 | <template> | ||
2 | <Generic :item="item"> | ||
3 | <template #content> | ||
4 | <p class="title is-4">{{ item.name }}</p> | ||
5 | <p class="subtitle is-6"> | ||
6 | <template v-if="item.subtitle"> | ||
7 | {{ item.subtitle }} | ||
8 | </template> | ||
9 | <template v-else> | ||
10 | {{ embyCount }} | ||
11 | </template> | ||
12 | </p> | ||
13 | </template> | ||
14 | <template #indicator> | ||
15 | <div v-if="status" class="status" :class="status"> | ||
16 | {{ status }} | ||
17 | </div> | ||
18 | </template> | ||
19 | </Generic> | ||
20 | </template> | ||
21 | |||
22 | <script> | ||
23 | import service from "@/mixins/service.js"; | ||
24 | import Generic from "./Generic.vue"; | ||
25 | |||
26 | export default { | ||
27 | name: "Emby", | ||
28 | mixins: [service], | ||
29 | props: { | ||
30 | item: Object, | ||
31 | }, | ||
32 | components: { | ||
33 | Generic, | ||
34 | }, | ||
35 | data: () => ({ | ||
36 | status: "", | ||
37 | albumCount: 0, | ||
38 | songCount: 0, | ||
39 | movieCount: 0, | ||
40 | seriesCount: 0, | ||
41 | episodeCount: 0, | ||
42 | }), | ||
43 | computed: { | ||
44 | embyCount: function () { | ||
45 | if (this.item.libraryType === "music") | ||
46 | return `${this.songCount} songs, ${this.albumCount} albums`; | ||
47 | else if (this.item.libraryType === "movies") | ||
48 | return `${this.movieCount} movies`; | ||
49 | else if (this.item.libraryType === "series") | ||
50 | return `${this.episodeCount} eps, ${this.seriesCount} series`; | ||
51 | else return `wrong library type 💀`; | ||
52 | }, | ||
53 | }, | ||
54 | created() { | ||
55 | this.fetchServerStatus(); | ||
56 | |||
57 | if (!this.item.subtitle && this.status !== "dead") | ||
58 | this.fetchServerMediaStats(); | ||
59 | }, | ||
60 | methods: { | ||
61 | fetchServerStatus: async function () { | ||
62 | this.fetch("/System/info/public") | ||
63 | .then((response) => { | ||
64 | if (response.Id) this.status = "running"; | ||
65 | else throw new Error(); | ||
66 | }) | ||
67 | .catch((e) => { | ||
68 | console.log(e); | ||
69 | this.status = "dead"; | ||
70 | }); | ||
71 | }, | ||
72 | fetchServerMediaStats: async function () { | ||
73 | const headers = { | ||
74 | "X-Emby-Token": this.item.apikey, | ||
75 | }; | ||
76 | |||
77 | var data = await this.fetch("/items/counts", { headers }).catch((e) => { | ||
78 | console.log(e); | ||
79 | }); | ||
80 | |||
81 | this.albumCount = data.AlbumCount; | ||
82 | this.songCount = data.SongCount; | ||
83 | this.movieCount = data.MovieCount; | ||
84 | this.seriesCount = data.SeriesCount; | ||
85 | this.episodeCount = data.EpisodeCount; | ||
86 | }, | ||
87 | }, | ||
88 | }; | ||
89 | </script> | ||
90 | |||
91 | <style scoped lang="scss"> | ||
92 | .status { | ||
93 | font-size: 0.8rem; | ||
94 | color: var(--text-title); | ||
95 | |||
96 | &.running:before { | ||
97 | background-color: #94e185; | ||
98 | border-color: #78d965; | ||
99 | box-shadow: 0 0 5px 1px #94e185; | ||
100 | } | ||
101 | |||
102 | &.dead:before { | ||
103 | background-color: #c9404d; | ||
104 | border-color: #c42c3b; | ||
105 | box-shadow: 0 0 5px 1px #c9404d; | ||
106 | } | ||
107 | |||
108 | &:before { | ||
109 | content: " "; | ||
110 | display: inline-block; | ||
111 | width: 7px; | ||
112 | height: 7px; | ||
113 | margin-right: 10px; | ||
114 | border: 1px solid #000; | ||
115 | border-radius: 7px; | ||
116 | } | ||
117 | } | ||
118 | </style> | ||
diff --git a/src/components/services/Portainer.vue b/src/components/services/Portainer.vue index 5f3954f..d101ecc 100644 --- a/src/components/services/Portainer.vue +++ b/src/components/services/Portainer.vue | |||
@@ -83,6 +83,12 @@ export default { | |||
83 | 83 | ||
84 | let containers = []; | 84 | let containers = []; |
85 | for (let endpoint of this.endpoints) { | 85 | for (let endpoint of this.endpoints) { |
86 | if ( | ||
87 | this.item.environments && | ||
88 | !this.item.environments.includes(endpoint.Name) | ||
89 | ) { | ||
90 | continue; | ||
91 | } | ||
86 | const uri = `/api/endpoints/${endpoint.Id}/docker/containers/json?all=1`; | 92 | const uri = `/api/endpoints/${endpoint.Id}/docker/containers/json?all=1`; |
87 | const endpointContainers = await this.fetch(uri, { headers }).catch( | 93 | const endpointContainers = await this.fetch(uri, { headers }).catch( |
88 | (e) => { | 94 | (e) => { |
@@ -5590,9 +5590,9 @@ minimatch@^3.0.4: | |||
5590 | brace-expansion "^1.1.7" | 5590 | brace-expansion "^1.1.7" |
5591 | 5591 | ||
5592 | minimist@^1.2.0, minimist@^1.2.5: | 5592 | minimist@^1.2.0, minimist@^1.2.5: |
5593 | version "1.2.5" | 5593 | version "1.2.6" |
5594 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" | 5594 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" |
5595 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== | 5595 | integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== |
5596 | 5596 | ||
5597 | minipass@^3.1.1: | 5597 | minipass@^3.1.1: |
5598 | version "3.1.3" | 5598 | version "3.1.3" |