統計で無視するハッシュタグを設定できるように
This commit is contained in:
parent
106d4cc0d6
commit
7343e6e2e8
6 changed files with 74 additions and 6 deletions
41
src/client/app/desktop/views/pages/admin/admin.hashtags.vue
Normal file
41
src/client/app/desktop/views/pages/admin/admin.hashtags.vue
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<template>
|
||||||
|
<div class="jdnqwkzlnxcfftthoybjxrebyolvoucw mk-admin-card">
|
||||||
|
<header>%i18n:@hided-tags%</header>
|
||||||
|
<textarea v-model="hidedTags"></textarea>
|
||||||
|
<button class="ui" @click="save">%i18n:@save%</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from "vue";
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
hidedTags: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
(this as any).os.getMeta().then(meta => {
|
||||||
|
this.hidedTags = meta.hidedTags.join('\n');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
save() {
|
||||||
|
(this as any).api('admin/update-meta', {
|
||||||
|
hidedTags: this.hidedTags.split('\n')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
@import '~const.styl'
|
||||||
|
|
||||||
|
.jdnqwkzlnxcfftthoybjxrebyolvoucw
|
||||||
|
textarea
|
||||||
|
width 100%
|
||||||
|
min-height 300px
|
||||||
|
|
||||||
|
</style>
|
|
@ -5,6 +5,8 @@
|
||||||
<li @click="nav('dashboard')" :class="{ active: page == 'dashboard' }">%fa:chalkboard .fw%%i18n:@dashboard%</li>
|
<li @click="nav('dashboard')" :class="{ active: page == 'dashboard' }">%fa:chalkboard .fw%%i18n:@dashboard%</li>
|
||||||
<li @click="nav('users')" :class="{ active: page == 'users' }">%fa:users .fw%%i18n:@users%</li>
|
<li @click="nav('users')" :class="{ active: page == 'users' }">%fa:users .fw%%i18n:@users%</li>
|
||||||
<li @click="nav('announcements')" :class="{ active: page == 'announcements' }">%fa:broadcast-tower .fw%%i18n:@announcements%</li>
|
<li @click="nav('announcements')" :class="{ active: page == 'announcements' }">%fa:broadcast-tower .fw%%i18n:@announcements%</li>
|
||||||
|
<li @click="nav('hashtags')" :class="{ active: page == 'hashtags' }">%fa:hashtag .fw%%i18n:@hashtags%</li>
|
||||||
|
|
||||||
<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }">%fa:cloud .fw%%i18n:@drive%</li> -->
|
<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }">%fa:cloud .fw%%i18n:@drive%</li> -->
|
||||||
<!-- <li @click="nav('update')" :class="{ active: page == 'update' }">%i18n:@update%</li> -->
|
<!-- <li @click="nav('update')" :class="{ active: page == 'update' }">%i18n:@update%</li> -->
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -17,6 +19,9 @@
|
||||||
<div v-show="page == 'announcements'">
|
<div v-show="page == 'announcements'">
|
||||||
<x-announcements/>
|
<x-announcements/>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-show="page == 'hashtags'">
|
||||||
|
<x-hashtags/>
|
||||||
|
</div>
|
||||||
<div v-if="page == 'users'">
|
<div v-if="page == 'users'">
|
||||||
<x-suspend-user/>
|
<x-suspend-user/>
|
||||||
<x-unsuspend-user/>
|
<x-unsuspend-user/>
|
||||||
|
@ -33,6 +38,7 @@
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import XDashboard from "./admin.dashboard.vue";
|
import XDashboard from "./admin.dashboard.vue";
|
||||||
import XAnnouncements from "./admin.announcements.vue";
|
import XAnnouncements from "./admin.announcements.vue";
|
||||||
|
import XHashtags from "./admin.hashtags.vue";
|
||||||
import XSuspendUser from "./admin.suspend-user.vue";
|
import XSuspendUser from "./admin.suspend-user.vue";
|
||||||
import XUnsuspendUser from "./admin.unsuspend-user.vue";
|
import XUnsuspendUser from "./admin.unsuspend-user.vue";
|
||||||
import XVerifyUser from "./admin.verify-user.vue";
|
import XVerifyUser from "./admin.verify-user.vue";
|
||||||
|
@ -43,6 +49,7 @@ export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
XDashboard,
|
XDashboard,
|
||||||
XAnnouncements,
|
XAnnouncements,
|
||||||
|
XHashtags,
|
||||||
XSuspendUser,
|
XSuspendUser,
|
||||||
XUnsuspendUser,
|
XUnsuspendUser,
|
||||||
XVerifyUser,
|
XVerifyUser,
|
||||||
|
|
|
@ -4,12 +4,13 @@ const Meta = db.get<IMeta>('meta');
|
||||||
export default Meta;
|
export default Meta;
|
||||||
|
|
||||||
export type IMeta = {
|
export type IMeta = {
|
||||||
broadcasts: any[];
|
broadcasts?: any[];
|
||||||
stats: {
|
stats?: {
|
||||||
notesCount: number;
|
notesCount: number;
|
||||||
originalNotesCount: number;
|
originalNotesCount: number;
|
||||||
usersCount: number;
|
usersCount: number;
|
||||||
originalUsersCount: number;
|
originalUsersCount: number;
|
||||||
};
|
};
|
||||||
disableRegistration: boolean;
|
disableRegistration?: boolean;
|
||||||
|
hidedTags?: string[];
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,7 +21,13 @@ export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '招待制か否か'
|
'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;
|
set.disableRegistration = ps.disableRegistration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(ps.hidedTags)) {
|
||||||
|
set.hidedTags = ps.hidedTags;
|
||||||
|
}
|
||||||
|
|
||||||
await Meta.update({}, {
|
await Meta.update({}, {
|
||||||
$set: set
|
$set: set
|
||||||
}, { upsert: true });
|
}, { upsert: true });
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import Note from '../../../../models/note';
|
import Note from '../../../../models/note';
|
||||||
import { erase } from '../../../../prelude/array';
|
import { erase } from '../../../../prelude/array';
|
||||||
|
import Meta from '../../../../models/meta';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
トレンドに載るためには「『直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上』のハッシュタグの上位5位以内に入る」ことが必要
|
トレンドに載るためには「『直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上』のハッシュタグの上位5位以内に入る」ことが必要
|
||||||
|
@ -17,6 +18,9 @@ const max = 5;
|
||||||
* Get trends of hashtags
|
* Get trends of hashtags
|
||||||
*/
|
*/
|
||||||
export default () => new Promise(async (res, rej) => {
|
export default () => new Promise(async (res, rej) => {
|
||||||
|
const meta = await Meta.findOne({});
|
||||||
|
const hidedTags = (meta.hidedTags || []).map(t => t.toLowerCase());
|
||||||
|
|
||||||
//#region 1. 直近Aの内に投稿されたハッシュタグ(とユーザーのペア)を集計
|
//#region 1. 直近Aの内に投稿されたハッシュタグ(とユーザーのペア)を集計
|
||||||
const data = await Note.aggregate([{
|
const data = await Note.aggregate([{
|
||||||
$match: {
|
$match: {
|
||||||
|
@ -53,6 +57,9 @@ export default () => new Promise(async (res, rej) => {
|
||||||
|
|
||||||
// カウント
|
// カウント
|
||||||
data.map(x => x._id).forEach(x => {
|
data.map(x => x._id).forEach(x => {
|
||||||
|
// ブラックリストに登録されているタグなら弾く
|
||||||
|
if (hidedTags.includes(x.tag)) return;
|
||||||
|
|
||||||
const i = tags.findIndex(tag => tag.name == x.tag);
|
const i = tags.findIndex(tag => tag.name == x.tag);
|
||||||
if (i != -1) {
|
if (i != -1) {
|
||||||
tags[i].count++;
|
tags[i].count++;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import config from '../../../config';
|
import config from '../../../config';
|
||||||
import Meta from '../../../models/meta';
|
import Meta from '../../../models/meta';
|
||||||
|
import { ILocalUser } from '../../../models/user';
|
||||||
|
|
||||||
const pkg = require('../../../../package.json');
|
const pkg = require('../../../../package.json');
|
||||||
const client = require('../../../../built/client/meta.json');
|
const client = require('../../../../built/client/meta.json');
|
||||||
|
@ -11,7 +12,7 @@ const client = require('../../../../built/client/meta.json');
|
||||||
/**
|
/**
|
||||||
* Show core info
|
* 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()) || {};
|
const meta: any = (await Meta.findOne()) || {};
|
||||||
|
|
||||||
res({
|
res({
|
||||||
|
@ -35,6 +36,7 @@ export default () => new Promise(async (res, rej) => {
|
||||||
disableRegistration: meta.disableRegistration,
|
disableRegistration: meta.disableRegistration,
|
||||||
driveCapacityPerLocalUserMb: config.localDriveCapacityMb,
|
driveCapacityPerLocalUserMb: config.localDriveCapacityMb,
|
||||||
recaptchaSitekey: config.recaptcha ? config.recaptcha.site_key : null,
|
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
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue