✨ Adds Mullvad and IP blacklist check widgets
This commit is contained in:
@@ -58,7 +58,6 @@ export default {
|
||||
border-radius: var(--curve-factor);
|
||||
text-decoration: none;
|
||||
transition: all 0.2s ease-in-out 0s;
|
||||
color: var(--item-text-color);
|
||||
p.sub-item-group-title {
|
||||
margin: 0 auto;
|
||||
cursor: default;
|
||||
|
||||
137
src/components/Widgets/BlacklistCheck.vue
Normal file
137
src/components/Widgets/BlacklistCheck.vue
Normal file
@@ -0,0 +1,137 @@
|
||||
<template>
|
||||
<div class="blacklist-check-wrapper" v-if="blacklisted">
|
||||
<p v-if="message" class="summary-msg">{{ message }}</p>
|
||||
<template v-if="showAll || (blacklisted && blacklistFiltered.length > 0)">
|
||||
<div v-for="blacklist in blacklistFiltered" :key="blacklist.id" class="blacklist-row">
|
||||
<span v-if="blacklist.detected" class="status detected">✘</span>
|
||||
<span v-else class="status not-detected">✔</span>
|
||||
<span>{{ blacklist.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else class="all-clear">
|
||||
<p>No Detections Found</p>
|
||||
<span class="tick">✔</span>
|
||||
</div>
|
||||
<p class="toggle-view-all" @click="showAll = !showAll">
|
||||
{{ showAll ? $t('widgets.general.show-less') : $t('widgets.general.show-more') }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetMixin from '@/mixins/WidgetMixin';
|
||||
import { widgetApiEndpoints } from '@/utils/defaults';
|
||||
|
||||
export default {
|
||||
mixins: [WidgetMixin],
|
||||
computed: {
|
||||
version() {
|
||||
return this.options.version || 'v2';
|
||||
},
|
||||
ipAddress() {
|
||||
if (this.autoIp) return this.autoIp;
|
||||
if (!this.options.apiKey) this.error('Missing IP Address');
|
||||
return this.options.ipAddress;
|
||||
},
|
||||
apiKey() {
|
||||
if (!this.options.apiKey) this.error('Missing API Key');
|
||||
return this.options.apiKey;
|
||||
},
|
||||
endpoint() {
|
||||
return `${widgetApiEndpoints.blacklistCheck}/${this.ipAddress}`;
|
||||
},
|
||||
blacklistFiltered() {
|
||||
return this.showAll ? this.blacklisted : this.blacklisted.filter(bl => (bl.detected));
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
blacklisted: null,
|
||||
message: '',
|
||||
showAll: false,
|
||||
autoIp: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/* Make GET request to CoinGecko API endpoint */
|
||||
fetchData() {
|
||||
if (!this.ipAddress) {
|
||||
this.getUsersIpAddress(); return;
|
||||
}
|
||||
this.defaultTimeout = 20000;
|
||||
const options = { Authorization: `Basic ${this.apiKey}` };
|
||||
this.makeRequest(this.endpoint, options).then(this.processData);
|
||||
},
|
||||
/* Assign data variables to the returned data */
|
||||
processData(blResponse) {
|
||||
this.message = `${blResponse.detections} detections found for ${blResponse.ip_address}`;
|
||||
this.blacklisted = blResponse.blacklists;
|
||||
},
|
||||
getUsersIpAddress() {
|
||||
this.makeRequest(widgetApiEndpoints.publicIp)
|
||||
.then((ipInfo) => {
|
||||
this.autoIp = ipInfo.ip;
|
||||
this.fetchData();
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.blacklist-check-wrapper {
|
||||
color: var(--widget-text-color);
|
||||
padding: 0.25rem;
|
||||
cursor: default;
|
||||
max-height: 2800px;
|
||||
overflow: auto;
|
||||
.blacklist-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.status {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
padding: 0 0.25rem 0.5rem 0.25rem;
|
||||
margin: 0.1rem 0.5rem 0.1rem 0.1rem;
|
||||
border: 1px solid var(--widget-text-color);
|
||||
border-radius: 1rem;
|
||||
text-align: center;
|
||||
&.detected { color: var(--danger); border-color: var(--danger); }
|
||||
&.not-detected { color: var(--success); border-color: var(--success); }
|
||||
}
|
||||
&:not(:last-child) { border-bottom: 1px dashed var(--widget-text-color); }
|
||||
}
|
||||
p.summary-msg {
|
||||
font-size: 0.85rem;
|
||||
margin: 0.2rem auto;
|
||||
font-style: italic;
|
||||
opacity: var(--dimming-factor);
|
||||
color: var(--widget-text-color);
|
||||
}
|
||||
p.toggle-view-all {
|
||||
text-align: center;
|
||||
margin: 0.5rem auto;
|
||||
padding: 0.5rem;
|
||||
border-radius: var(--curve-factor);
|
||||
border: 1px dashed transparent;
|
||||
background: var(--widget-accent-color);
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
border-color: var(--widget-text-color);
|
||||
}
|
||||
}
|
||||
.all-clear {
|
||||
color: var(--success);
|
||||
text-align: center;
|
||||
.tick {
|
||||
font-size: 2rem;
|
||||
margin: 0 auto;
|
||||
border-radius: 1.5rem;
|
||||
padding: 0.3rem 0.8rem;
|
||||
background: var(--success);
|
||||
color: var(--white);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
111
src/components/Widgets/MullvadStatus.vue
Normal file
111
src/components/Widgets/MullvadStatus.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<div class="mullvad-wrapper" v-if="mullvadInfo">
|
||||
<p v-if="mullvadInfo.isMullvad" class="status connected"><span>✔</span> Connected</p>
|
||||
<p v-else class="status not-connected"><span>✘</span> Not Connected</p>
|
||||
<div class="connection-info">
|
||||
<p><span class="lbl">IP</span><span class="val">{{ mullvadInfo.ip }}</span></p>
|
||||
<p v-if="mullvadInfo.host">
|
||||
<span class="lbl">Host</span><span class="val">{{ mullvadInfo.host }}</span>
|
||||
</p>
|
||||
<p><span class="lbl">Owner</span><span class="val">{{ mullvadInfo.ownedBy }}</span></p>
|
||||
<p v-if="mullvadInfo.serverType">
|
||||
<span class="lbl">Type</span><span class="val">{{ mullvadInfo.serverType }}</span>
|
||||
</p>
|
||||
<p><span class="lbl">Location</span><span class="val">{{ mullvadInfo.location }}</span></p>
|
||||
<p>
|
||||
<span class="lbl">Blacklisted?</span>
|
||||
<span class="val">{{ mullvadInfo.isBlacklisted ? '✘ Yes' : '✔ No' }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetMixin from '@/mixins/WidgetMixin';
|
||||
import { widgetApiEndpoints } from '@/utils/defaults';
|
||||
|
||||
export default {
|
||||
mixins: [WidgetMixin],
|
||||
computed: {
|
||||
endpoint() {
|
||||
return widgetApiEndpoints.mullvad;
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
mullvadInfo: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/* Make GET request to Mullvad API endpoint */
|
||||
fetchData() {
|
||||
this.makeRequest(this.endpoint).then(this.processData);
|
||||
},
|
||||
/* Assign data variables to the returned data */
|
||||
processData(mullvad) {
|
||||
this.mullvadInfo = {
|
||||
ip: mullvad.ip,
|
||||
isMullvad: mullvad.mullvad_exit_ip,
|
||||
host: mullvad.mullvad_exit_ip_hostname,
|
||||
serverType: mullvad.mullvad_server_type,
|
||||
ownedBy: mullvad.organization,
|
||||
location: `${mullvad.city}, ${mullvad.country}`,
|
||||
isBlacklisted: mullvad.blacklisted.blacklisted,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mullvad-wrapper {
|
||||
color: var(--widget-text-color);
|
||||
cursor: default;
|
||||
|
||||
.status {
|
||||
display: flex;
|
||||
max-width: 250px;
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
align-items: center;
|
||||
margin: 0.25rem auto;
|
||||
justify-content: space-evenly;
|
||||
span {
|
||||
font-size: 1.5rem;
|
||||
border-radius: 1.5rem;
|
||||
padding: 0.3rem 0.7rem;
|
||||
border: 1px solid;
|
||||
color: var(--background);
|
||||
}
|
||||
&.not-connected {
|
||||
color: var(--danger);
|
||||
span { background: var(--danger); }
|
||||
}
|
||||
&.connected {
|
||||
color: var(--success);
|
||||
span { background: var(--success); }
|
||||
}
|
||||
}
|
||||
.connection-info {
|
||||
p {
|
||||
display: flex;
|
||||
max-width: 250px;
|
||||
font-size: 0.9rem;
|
||||
padding: 0.2rem;
|
||||
margin: 0.2rem auto;
|
||||
justify-content: space-between;
|
||||
opacity: var(--dimming-factor);
|
||||
span {
|
||||
&.lbl {
|
||||
font-weight: bold;
|
||||
}
|
||||
&.val {
|
||||
font-family: monospace;
|
||||
}
|
||||
}
|
||||
&:not(:last-child) { border-bottom: 1px dashed var(--widget-text-color); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -34,6 +34,13 @@
|
||||
@error="handleError"
|
||||
:ref="widgetRef"
|
||||
/>
|
||||
<BlacklistCheck
|
||||
v-else-if="widgetType === 'blacklist-check'"
|
||||
:options="widgetOptions"
|
||||
@loading="setLoaderState"
|
||||
@error="handleError"
|
||||
:ref="widgetRef"
|
||||
/>
|
||||
<Clock
|
||||
v-else-if="widgetType === 'clock'"
|
||||
:options="widgetOptions"
|
||||
@@ -244,6 +251,13 @@
|
||||
@error="handleError"
|
||||
:ref="widgetRef"
|
||||
/>
|
||||
<MullvadStatus
|
||||
v-else-if="widgetType === 'mullvad-status'"
|
||||
:options="widgetOptions"
|
||||
@loading="setLoaderState"
|
||||
@error="handleError"
|
||||
:ref="widgetRef"
|
||||
/>
|
||||
<NdCpuHistory
|
||||
v-else-if="widgetType === 'nd-cpu-history'"
|
||||
:options="widgetOptions"
|
||||
@@ -402,6 +416,7 @@ export default {
|
||||
// Register widget components
|
||||
AnonAddy: () => import('@/components/Widgets/AnonAddy.vue'),
|
||||
Apod: () => import('@/components/Widgets/Apod.vue'),
|
||||
BlacklistCheck: () => import('@/components/Widgets/BlacklistCheck.vue'),
|
||||
Clock: () => import('@/components/Widgets/Clock.vue'),
|
||||
CodeStats: () => import('@/components/Widgets/CodeStats.vue'),
|
||||
CovidStats: () => import('@/components/Widgets/CovidStats.vue'),
|
||||
@@ -432,6 +447,7 @@ export default {
|
||||
IframeWidget: () => import('@/components/Widgets/IframeWidget.vue'),
|
||||
ImageWidget: () => import('@/components/Widgets/ImageWidget.vue'),
|
||||
Jokes: () => import('@/components/Widgets/Jokes.vue'),
|
||||
MullvadStatus: () => import('@/components/Widgets/MullvadStatus.vue'),
|
||||
NdCpuHistory: () => import('@/components/Widgets/NdCpuHistory.vue'),
|
||||
NdLoadHistory: () => import('@/components/Widgets/NdLoadHistory.vue'),
|
||||
NdRamHistory: () => import('@/components/Widgets/NdRamHistory.vue'),
|
||||
@@ -476,7 +492,7 @@ export default {
|
||||
/* Returns users specified widget options, or empty object */
|
||||
widgetOptions() {
|
||||
const options = this.widget.options || {};
|
||||
const timeout = this.widget.timeout || 2500;
|
||||
const timeout = this.widget.timeout || null;
|
||||
const useProxy = this.appConfig.widgetsAlwaysUseProxy || !!this.widget.useProxy;
|
||||
const updateInterval = this.widget.updateInterval !== undefined
|
||||
? this.widget.updateInterval : null;
|
||||
|
||||
Reference in New Issue
Block a user