diff --git a/src/config.js b/src/config.js index cf4e8cd..5e092b8 100644 --- a/src/config.js +++ b/src/config.js @@ -38,6 +38,9 @@ module.exports.LANG = process.env.LANG || 'en'; module.exports.UI_TRAFFIC_STATS = process.env.UI_TRAFFIC_STATS || 'false'; module.exports.UI_CHART_TYPE = process.env.UI_CHART_TYPE || 0; +module.exports.DICEBEAR_TYPE = process.env.DICEBEAR_TYPE || false; +module.exports.USE_GRAVATAR = process.env.USE_GRAVATAR || false; + const getRandomInt = (min, max) => min + Math.floor(Math.random() * (max - min)); const getRandomJunkSize = () => getRandomInt(15, 150); const getRandomHeader = () => getRandomInt(1, 2_147_483_647); diff --git a/src/lib/Server.js b/src/lib/Server.js index d1510d2..55e6a72 100644 --- a/src/lib/Server.js +++ b/src/lib/Server.js @@ -32,6 +32,8 @@ const { LANG, UI_TRAFFIC_STATS, UI_CHART_TYPE, + DICEBEAR_TYPE, + USE_GRAVATAR, } = require('../config'); const requiresPassword = !!PASSWORD_HASH; @@ -92,6 +94,14 @@ module.exports = class Server { return `"${UI_CHART_TYPE}"`; })) + .get('/api/ui-avatar-settings', defineEventHandler((event) => { + setHeader(event, 'Content-Type', 'application/json'); + return { + dicebear: DICEBEAR_TYPE, + gravatar: USE_GRAVATAR, + } + })) + // Authentication .get('/api/session', defineEventHandler((event) => { const authenticated = requiresPassword diff --git a/src/www/js/api.js b/src/www/js/api.js index 9006f5a..a4239d2 100644 --- a/src/www/js/api.js +++ b/src/www/js/api.js @@ -57,6 +57,13 @@ class API { }); } + async getAvatarSettings() { + return this.call({ + method: 'get', + path: '/ui-avatar-settings', + }); + } + async getSession() { return this.call({ method: 'get', diff --git a/src/www/js/app.js b/src/www/js/app.js index 6058ac1..9d0e048 100644 --- a/src/www/js/app.js +++ b/src/www/js/app.js @@ -71,6 +71,10 @@ new Vue({ uiTrafficStats: false, uiChartType: 0, + avatarSettings: { + 'dicebear': null, + 'gravatar': false, + }, uiShowCharts: localStorage.getItem('uiShowCharts') === '1', uiTheme: localStorage.theme || 'auto', prefersDarkScheme: window.matchMedia('(prefers-color-scheme: dark)'), @@ -173,10 +177,10 @@ new Vue({ const clients = await this.api.getClients(); this.clients = clients.map((client) => { - if (client.name.includes('@') && client.name.includes('.')) { + if (client.name.includes('@') && client.name.includes('.') && this.avatarSettings.gravatar) { client.avatar = `https://gravatar.com/avatar/${sha256(client.name.toLowerCase().trim())}.jpg`; - } else { - client.avatar = `https://api.dicebear.com/9.x/bottts/svg?seed=${sha256(client.name.toLowerCase().trim())}` + } else if (this.avatarSettings.dicebear) { + client.avatar = `https://api.dicebear.com/9.x/${this.avatarSettings.dicebear}/svg?seed=${sha256(client.name.toLowerCase().trim())}` } if (!this.clientsPersist[client.id]) { @@ -386,6 +390,17 @@ new Vue({ this.uiChartType = 0; }); + this.api.getAvatarSettings() + .then((res) => { + this.avatarSettings = res; + }) + .catch(() => { + this.avatarSettings = { + 'dicebear': null, + 'gravatar': false, + }; + }); + Promise.resolve().then(async () => { const lang = await this.api.getLang(); if (lang !== localStorage.getItem('lang') && i18n.availableLocales.includes(lang)) {