diff --git a/src/client/app/desktop/views/pages/admin/admin.hashtags.vue b/src/client/app/desktop/views/pages/admin/admin.hashtags.vue
new file mode 100644
index 0000000000..c6bf20361f
--- /dev/null
+++ b/src/client/app/desktop/views/pages/admin/admin.hashtags.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/client/app/desktop/views/pages/admin/admin.vue b/src/client/app/desktop/views/pages/admin/admin.vue
index a71059c378..510252b447 100644
--- a/src/client/app/desktop/views/pages/admin/admin.vue
+++ b/src/client/app/desktop/views/pages/admin/admin.vue
@@ -5,6 +5,8 @@
%fa:chalkboard .fw%%i18n:@dashboard%
%fa:users .fw%%i18n:@users%
%fa:broadcast-tower .fw%%i18n:@announcements%
+ %fa:hashtag .fw%%i18n:@hashtags%
+
@@ -17,6 +19,9 @@
+
+
+
@@ -33,6 +38,7 @@
import Vue from "vue";
import XDashboard from "./admin.dashboard.vue";
import XAnnouncements from "./admin.announcements.vue";
+import XHashtags from "./admin.hashtags.vue";
import XSuspendUser from "./admin.suspend-user.vue";
import XUnsuspendUser from "./admin.unsuspend-user.vue";
import XVerifyUser from "./admin.verify-user.vue";
@@ -43,6 +49,7 @@ export default Vue.extend({
components: {
XDashboard,
XAnnouncements,
+ XHashtags,
XSuspendUser,
XUnsuspendUser,
XVerifyUser,
diff --git a/src/models/meta.ts b/src/models/meta.ts
index aef0163dfe..4f1977f3b5 100644
--- a/src/models/meta.ts
+++ b/src/models/meta.ts
@@ -4,12 +4,13 @@ const Meta = db.get('meta');
export default Meta;
export type IMeta = {
- broadcasts: any[];
- stats: {
+ broadcasts?: any[];
+ stats?: {
notesCount: number;
originalNotesCount: number;
usersCount: number;
originalUsersCount: number;
};
- disableRegistration: boolean;
+ disableRegistration?: boolean;
+ hidedTags?: string[];
};
diff --git a/src/server/api/endpoints/admin/update-meta.ts b/src/server/api/endpoints/admin/update-meta.ts
index 10ca15d329..f903628774 100644
--- a/src/server/api/endpoints/admin/update-meta.ts
+++ b/src/server/api/endpoints/admin/update-meta.ts
@@ -21,7 +21,13 @@ export const meta = {
desc: {
'ja-JP': '招待制か否か'
}
- })
+ }),
+
+ hidedTags: $.arr($.str).optional.nullable.note({
+ desc: {
+ 'ja-JP': '統計などで無視するハッシュタグ'
+ }
+ }),
}
};
@@ -39,6 +45,10 @@ export default (params: any) => new Promise(async (res, rej) => {
set.disableRegistration = ps.disableRegistration;
}
+ if (Array.isArray(ps.hidedTags)) {
+ set.hidedTags = ps.hidedTags;
+ }
+
await Meta.update({}, {
$set: set
}, { upsert: true });
diff --git a/src/server/api/endpoints/hashtags/trend.ts b/src/server/api/endpoints/hashtags/trend.ts
index e7c08ca9f0..bfa475619c 100644
--- a/src/server/api/endpoints/hashtags/trend.ts
+++ b/src/server/api/endpoints/hashtags/trend.ts
@@ -1,5 +1,6 @@
import Note from '../../../../models/note';
import { erase } from '../../../../prelude/array';
+import Meta from '../../../../models/meta';
/*
トレンドに載るためには「『直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上』のハッシュタグの上位5位以内に入る」ことが必要
@@ -17,6 +18,9 @@ const max = 5;
* Get trends of hashtags
*/
export default () => new Promise(async (res, rej) => {
+ const meta = await Meta.findOne({});
+ const hidedTags = (meta.hidedTags || []).map(t => t.toLowerCase());
+
//#region 1. 直近Aの内に投稿されたハッシュタグ(とユーザーのペア)を集計
const data = await Note.aggregate([{
$match: {
@@ -53,6 +57,9 @@ export default () => new Promise(async (res, rej) => {
// カウント
data.map(x => x._id).forEach(x => {
+ // ブラックリストに登録されているタグなら弾く
+ if (hidedTags.includes(x.tag)) return;
+
const i = tags.findIndex(tag => tag.name == x.tag);
if (i != -1) {
tags[i].count++;
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index b0876eaafd..4472d8d779 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -4,6 +4,7 @@
import * as os from 'os';
import config from '../../../config';
import Meta from '../../../models/meta';
+import { ILocalUser } from '../../../models/user';
const pkg = require('../../../../package.json');
const client = require('../../../../built/client/meta.json');
@@ -11,7 +12,7 @@ const client = require('../../../../built/client/meta.json');
/**
* Show core info
*/
-export default () => new Promise(async (res, rej) => {
+export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
const meta: any = (await Meta.findOne()) || {};
res({
@@ -35,6 +36,7 @@ export default () => new Promise(async (res, rej) => {
disableRegistration: meta.disableRegistration,
driveCapacityPerLocalUserMb: config.localDriveCapacityMb,
recaptchaSitekey: config.recaptcha ? config.recaptcha.site_key : null,
- swPublickey: config.sw ? config.sw.public_key : null
+ swPublickey: config.sw ? config.sw.public_key : null,
+ hidedTags: (me && me.isAdmin) ? meta.hidedTags : undefined
});
});