Feature / user recommendation config in admin ui (#3357)
* add config for external user recommendation into admin ui * debug * correct admin ui * switch external user recommendation to admin ui config * debug * debug * debug * Revert "debug" This reverts commit f4a0460e5bde21cd1f39a735f496a2d74233ef3f. * explicit parseInt radix * add Japanese message * change default engine to https * remove unused settings * debug * nullable externalUserRecommendationTimeout
This commit is contained in:
		
							parent
							
								
									562a5f66fc
								
							
						
					
					
						commit
						ac14adfd3e
					
				
					 8 changed files with 94 additions and 14 deletions
				
			
		| 
						 | 
					@ -121,9 +121,3 @@ autoAdmin: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Summaly proxy
 | 
					# Summaly proxy
 | 
				
			||||||
#summalyProxy: "http://example.com"
 | 
					#summalyProxy: "http://example.com"
 | 
				
			||||||
 | 
					 | 
				
			||||||
# User recommendation
 | 
					 | 
				
			||||||
#user_recommendation:
 | 
					 | 
				
			||||||
#  external: true
 | 
					 | 
				
			||||||
#  engine: http://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}
 | 
					 | 
				
			||||||
#  timeout: 300000
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1117,6 +1117,12 @@ admin/views/instance.vue:
 | 
				
			||||||
  invite: "招待"
 | 
					  invite: "招待"
 | 
				
			||||||
  save: "保存"
 | 
					  save: "保存"
 | 
				
			||||||
  saved: "保存しました"
 | 
					  saved: "保存しました"
 | 
				
			||||||
 | 
					  user-recommendation-config: "おすすめユーザー"
 | 
				
			||||||
 | 
					  enable-external-user-recommendation: "外部ユーザーレコメンデーションを有効にする"
 | 
				
			||||||
 | 
					  external-user-recommendation-engine: "エンジン"
 | 
				
			||||||
 | 
					  external-user-recommendation-engine-desc: "例: https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}"
 | 
				
			||||||
 | 
					  external-user-recommendation-timeout: "タイムアウト"
 | 
				
			||||||
 | 
					  external-user-recommendation-timeout-desc: "ミリ秒単位 (例: 300000)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
admin/views/charts.vue:
 | 
					admin/views/charts.vue:
 | 
				
			||||||
  title: "チャート"
 | 
					  title: "チャート"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,6 +42,12 @@
 | 
				
			||||||
		<section>
 | 
							<section>
 | 
				
			||||||
			<ui-switch v-model="disableLocalTimeline">{{ $t('disable-local-timeline') }}</ui-switch>
 | 
								<ui-switch v-model="disableLocalTimeline">{{ $t('disable-local-timeline') }}</ui-switch>
 | 
				
			||||||
		</section>
 | 
							</section>
 | 
				
			||||||
 | 
							<section>
 | 
				
			||||||
 | 
								<header><fa :icon="faUserPlus"/> {{ $t('user-recommendation-config') }}</header>
 | 
				
			||||||
 | 
								<ui-switch v-model="enableExternalUserRecommendation">{{ $t('enable-external-user-recommendation') }}</ui-switch>
 | 
				
			||||||
 | 
								<ui-input v-model="externalUserRecommendationEngine" :disabled="!enableExternalUserRecommendation">{{ $t('external-user-recommendation-engine') }}<span slot="desc">{{ $t('external-user-recommendation-engine-desc') }}</span></ui-input>
 | 
				
			||||||
 | 
								<ui-input v-model="externalUserRecommendationTimeout" type="number" :disabled="!enableExternalUserRecommendation">{{ $t('external-user-recommendation-timeout') }}<span slot="suffix">ms</span><span slot="desc">{{ $t('external-user-recommendation-timeout-desc') }}</span></ui-input>
 | 
				
			||||||
 | 
							</section>
 | 
				
			||||||
		<section>
 | 
							<section>
 | 
				
			||||||
			<ui-button @click="updateMeta">{{ $t('save') }}</ui-button>
 | 
								<ui-button @click="updateMeta">{{ $t('save') }}</ui-button>
 | 
				
			||||||
		</section>
 | 
							</section>
 | 
				
			||||||
| 
						 | 
					@ -95,7 +101,7 @@ import Vue from 'vue';
 | 
				
			||||||
import i18n from '../../i18n';
 | 
					import i18n from '../../i18n';
 | 
				
			||||||
import { host } from '../../config';
 | 
					import { host } from '../../config';
 | 
				
			||||||
import { toUnicode } from 'punycode';
 | 
					import { toUnicode } from 'punycode';
 | 
				
			||||||
import { faHeadset, faShieldAlt, faGhost } from '@fortawesome/free-solid-svg-icons';
 | 
					import { faHeadset, faShieldAlt, faGhost, faUserPlus } from '@fortawesome/free-solid-svg-icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Vue.extend({
 | 
					export default Vue.extend({
 | 
				
			||||||
	i18n: i18n('admin/views/instance.vue'),
 | 
						i18n: i18n('admin/views/instance.vue'),
 | 
				
			||||||
| 
						 | 
					@ -129,7 +135,10 @@ export default Vue.extend({
 | 
				
			||||||
			discordClientSecret: null,
 | 
								discordClientSecret: null,
 | 
				
			||||||
			proxyAccount: null,
 | 
								proxyAccount: null,
 | 
				
			||||||
			inviteCode: null,
 | 
								inviteCode: null,
 | 
				
			||||||
			faHeadset, faShieldAlt, faGhost
 | 
								enableExternalUserRecommendation: false,
 | 
				
			||||||
 | 
								externalUserRecommendationEngine: null,
 | 
				
			||||||
 | 
								externalUserRecommendationTimeout: null,
 | 
				
			||||||
 | 
								faHeadset, faShieldAlt, faGhost, faUserPlus
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -158,6 +167,9 @@ export default Vue.extend({
 | 
				
			||||||
			this.enableDiscordIntegration = meta.enableDiscordIntegration;
 | 
								this.enableDiscordIntegration = meta.enableDiscordIntegration;
 | 
				
			||||||
			this.discordClientId = meta.discordClientId;
 | 
								this.discordClientId = meta.discordClientId;
 | 
				
			||||||
			this.discordClientSecret = meta.discordClientSecret;
 | 
								this.discordClientSecret = meta.discordClientSecret;
 | 
				
			||||||
 | 
								this.enableExternalUserRecommendation = meta.enableExternalUserRecommendation;
 | 
				
			||||||
 | 
								this.externalUserRecommendationEngine = meta.externalUserRecommendationEngine;
 | 
				
			||||||
 | 
								this.externalUserRecommendationTimeout = meta.externalUserRecommendationTimeout;
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -199,7 +211,10 @@ export default Vue.extend({
 | 
				
			||||||
				githubClientSecret: this.githubClientSecret,
 | 
									githubClientSecret: this.githubClientSecret,
 | 
				
			||||||
				enableDiscordIntegration: this.enableDiscordIntegration,
 | 
									enableDiscordIntegration: this.enableDiscordIntegration,
 | 
				
			||||||
				discordClientId: this.discordClientId,
 | 
									discordClientId: this.discordClientId,
 | 
				
			||||||
				discordClientSecret: this.discordClientSecret
 | 
									discordClientSecret: this.discordClientSecret,
 | 
				
			||||||
 | 
									enableExternalUserRecommendation: this.enableExternalUserRecommendation,
 | 
				
			||||||
 | 
									externalUserRecommendationEngine: this.externalUserRecommendationEngine,
 | 
				
			||||||
 | 
									externalUserRecommendationTimeout: parseInt(this.externalUserRecommendationTimeout, 10)
 | 
				
			||||||
			}).then(() => {
 | 
								}).then(() => {
 | 
				
			||||||
				this.$root.alert({
 | 
									this.$root.alert({
 | 
				
			||||||
					type: 'success',
 | 
										type: 'success',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,10 @@ const defaultMeta: any = {
 | 
				
			||||||
	maxNoteTextLength: 1000,
 | 
						maxNoteTextLength: 1000,
 | 
				
			||||||
	enableTwitterIntegration: false,
 | 
						enableTwitterIntegration: false,
 | 
				
			||||||
	enableGithubIntegration: false,
 | 
						enableGithubIntegration: false,
 | 
				
			||||||
	enableDiscordIntegration: false
 | 
						enableDiscordIntegration: false,
 | 
				
			||||||
 | 
						enableExternalUserRecommendation: false,
 | 
				
			||||||
 | 
						externalUserRecommendationEngine: "https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}",
 | 
				
			||||||
 | 
						externalUserRecommendationTimeout: 300000
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default async function(): Promise<IMeta> {
 | 
					export default async function(): Promise<IMeta> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -125,6 +125,19 @@ if ((config as any).github) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					if ((config as any).user_recommendation) {
 | 
				
			||||||
 | 
						Meta.findOne({}).then(m => {
 | 
				
			||||||
 | 
							if (m != null && m.enableExternalUserRecommendation == null) {
 | 
				
			||||||
 | 
								Meta.update({}, {
 | 
				
			||||||
 | 
									$set: {
 | 
				
			||||||
 | 
										enableExternalUserRecommendation: true,
 | 
				
			||||||
 | 
										externalUserRecommendationEngine: (config as any).user_recommendation.engine,
 | 
				
			||||||
 | 
										externalUserRecommendationTimeout: (config as any).user_recommendation.timeout
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type IMeta = {
 | 
					export type IMeta = {
 | 
				
			||||||
	name?: string;
 | 
						name?: string;
 | 
				
			||||||
| 
						 | 
					@ -195,4 +208,8 @@ export type IMeta = {
 | 
				
			||||||
	enableDiscordIntegration?: boolean;
 | 
						enableDiscordIntegration?: boolean;
 | 
				
			||||||
	discordClientId?: string;
 | 
						discordClientId?: string;
 | 
				
			||||||
	discordClientSecret?: string;
 | 
						discordClientSecret?: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enableExternalUserRecommendation?: boolean;
 | 
				
			||||||
 | 
						externalUserRecommendationEngine?: string;
 | 
				
			||||||
 | 
						externalUserRecommendationTimeout?: number;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,6 +200,27 @@ export const meta = {
 | 
				
			||||||
			desc: {
 | 
								desc: {
 | 
				
			||||||
				'ja-JP': 'DiscordアプリのClient Secret'
 | 
									'ja-JP': 'DiscordアプリのClient Secret'
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							enableExternalUserRecommendation: {
 | 
				
			||||||
 | 
								validator: $.bool.optional,
 | 
				
			||||||
 | 
								desc: {
 | 
				
			||||||
 | 
									'ja-JP': '外部ユーザーレコメンデーションを有効にする'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							externalUserRecommendationEngine: {
 | 
				
			||||||
 | 
								validator: $.str.optional.nullable,
 | 
				
			||||||
 | 
								desc: {
 | 
				
			||||||
 | 
									'ja-JP': '外部ユーザーレコメンデーションのサードパーティエンジン'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							externalUserRecommendationTimeout: {
 | 
				
			||||||
 | 
								validator: $.num.optional.nullable.min(0),
 | 
				
			||||||
 | 
								desc: {
 | 
				
			||||||
 | 
									'ja-JP': '外部ユーザーレコメンデーションのタイムアウト (ミリ秒)'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -315,6 +336,18 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
 | 
				
			||||||
		set.discordClientSecret = ps.discordClientSecret;
 | 
							set.discordClientSecret = ps.discordClientSecret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ps.enableExternalUserRecommendation !== undefined) {
 | 
				
			||||||
 | 
							set.enableExternalUserRecommendation = ps.enableExternalUserRecommendation;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ps.externalUserRecommendationEngine !== undefined) {
 | 
				
			||||||
 | 
							set.externalUserRecommendationEngine = ps.externalUserRecommendationEngine;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ps.externalUserRecommendationTimeout !== undefined) {
 | 
				
			||||||
 | 
							set.externalUserRecommendationTimeout = ps.externalUserRecommendationTimeout;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	await Meta.update({}, {
 | 
						await Meta.update({}, {
 | 
				
			||||||
		$set: set
 | 
							$set: set
 | 
				
			||||||
	}, { upsert: true });
 | 
						}, { upsert: true });
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,6 +72,10 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
 | 
				
			||||||
		enableTwitterIntegration: instance.enableTwitterIntegration,
 | 
							enableTwitterIntegration: instance.enableTwitterIntegration,
 | 
				
			||||||
		enableGithubIntegration: instance.enableGithubIntegration,
 | 
							enableGithubIntegration: instance.enableGithubIntegration,
 | 
				
			||||||
		enableDiscordIntegration: instance.enableDiscordIntegration,
 | 
							enableDiscordIntegration: instance.enableDiscordIntegration,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							enableExternalUserRecommendation: instance.enableExternalUserRecommendation,
 | 
				
			||||||
 | 
							externalUserRecommendationEngine: instance.externalUserRecommendationEngine,
 | 
				
			||||||
 | 
							externalUserRecommendationTimeout: instance.externalUserRecommendationTimeout
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ps.detail) {
 | 
						if (ps.detail) {
 | 
				
			||||||
| 
						 | 
					@ -85,7 +89,11 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
 | 
				
			||||||
			github: instance.enableGithubIntegration,
 | 
								github: instance.enableGithubIntegration,
 | 
				
			||||||
			discord: instance.enableDiscordIntegration,
 | 
								discord: instance.enableDiscordIntegration,
 | 
				
			||||||
			serviceWorker: config.sw ? true : false,
 | 
								serviceWorker: config.sw ? true : false,
 | 
				
			||||||
			userRecommendation: config.user_recommendation ? config.user_recommendation : {}
 | 
								userRecommendation: {
 | 
				
			||||||
 | 
									external: instance.enableExternalUserRecommendation,
 | 
				
			||||||
 | 
									engine: instance.externalUserRecommendationEngine,
 | 
				
			||||||
 | 
									timeout: instance.externalUserRecommendationTimeout
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,8 @@ import Mute from '../../../../models/mute';
 | 
				
			||||||
import * as request from 'request';
 | 
					import * as request from 'request';
 | 
				
			||||||
import config from '../../../../config';
 | 
					import config from '../../../../config';
 | 
				
			||||||
import define from '../../define';
 | 
					import define from '../../define';
 | 
				
			||||||
 | 
					import fetchMeta from '../../../../misc/fetch-meta';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const meta = {
 | 
					export const meta = {
 | 
				
			||||||
	desc: {
 | 
						desc: {
 | 
				
			||||||
| 
						 | 
					@ -30,13 +32,15 @@ export const meta = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default define(meta, (ps, me) => new Promise(async (res, rej) => {
 | 
					export default define(meta, (ps, me) => new Promise(async (res, rej) => {
 | 
				
			||||||
	if (config.user_recommendation && config.user_recommendation.external) {
 | 
						const instance = await fetchMeta();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (instance.enableExternalUserRecommendation) {
 | 
				
			||||||
		const userName = me.username;
 | 
							const userName = me.username;
 | 
				
			||||||
		const hostName = config.hostname;
 | 
							const hostName = config.hostname;
 | 
				
			||||||
		const limit = ps.limit;
 | 
							const limit = ps.limit;
 | 
				
			||||||
		const offset = ps.offset;
 | 
							const offset = ps.offset;
 | 
				
			||||||
		const timeout = config.user_recommendation.timeout;
 | 
							const timeout = instance.externalUserRecommendationTimeout;
 | 
				
			||||||
		const engine = config.user_recommendation.engine;
 | 
							const engine = instance.externalUserRecommendationEngine;
 | 
				
			||||||
		const url = engine
 | 
							const url = engine
 | 
				
			||||||
			.replace('{{host}}', hostName)
 | 
								.replace('{{host}}', hostName)
 | 
				
			||||||
			.replace('{{user}}', userName)
 | 
								.replace('{{user}}', userName)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue