Compare commits
53 Commits
Author | SHA1 | Date | |
---|---|---|---|
f968d05ea0 | |||
d6e5dc2167 | |||
460147fea2 | |||
cea44834bb | |||
1af50fd7b8 | |||
b18013025f | |||
399eb60809 | |||
ed67e3506b | |||
d8ff37fc45 | |||
2fcc3bb1ea | |||
2e680c3d1e | |||
af0a0ef41b | |||
bbfccb0bbf | |||
c89eb5d69f | |||
ebde84214e | |||
03fbae7b6d | |||
f90e9596d4 | |||
944f9524e2 | |||
c61050244e | |||
90337adbbc | |||
7b67e41c5b | |||
91db24fcfc | |||
bb53db905f | |||
0e9a1efe46 | |||
289cd3e200 | |||
e0f847e539 | |||
c2842b486e | |||
7235ade42f | |||
850be2df1d | |||
d504501440 | |||
208392f12c | |||
0fe036c640 | |||
a40c41f0b0 | |||
4affa5b710 | |||
4eb574d991 | |||
2c1577ea24 | |||
b87e7e50b6 | |||
36215d50bd | |||
5ff1245d0c | |||
ebd189fb27 | |||
6f724827bd | |||
b6a0982012 | |||
c3e375e8a5 | |||
302409fd83 | |||
a2046461c1 | |||
6660c34120 | |||
b88ccf0ddd | |||
b898bbf94c | |||
787e89eb95 | |||
1022c2c438 | |||
ba21c62ed4 | |||
bfe66c919b | |||
3dacf7f661 |
@ -70,6 +70,7 @@ common:
|
||||
donation: "Spenden"
|
||||
nav: "Navigation"
|
||||
tips: "Tipps"
|
||||
hashtags: "ハッシュタグ"
|
||||
deck:
|
||||
widgets: "Widget hinzufügen:"
|
||||
home: "Startseite"
|
||||
@ -226,6 +227,7 @@ common/views/widgets/posts-monitor.vue:
|
||||
toggle: "表示を切り替え"
|
||||
common/views/widgets/hashtags.vue:
|
||||
title: "ハッシュタグ"
|
||||
count: "{}人が投稿"
|
||||
common/views/widgets/server.vue:
|
||||
title: "Serverinformationen"
|
||||
toggle: "Sicht umschalten"
|
||||
|
@ -70,6 +70,7 @@ common:
|
||||
donation: "Donation"
|
||||
nav: "Navigation"
|
||||
tips: "Tips"
|
||||
hashtags: "Hashtags"
|
||||
deck:
|
||||
widgets: "Widgets"
|
||||
home: "Home"
|
||||
@ -226,6 +227,7 @@ common/views/widgets/posts-monitor.vue:
|
||||
toggle: "Toggle views"
|
||||
common/views/widgets/hashtags.vue:
|
||||
title: "Hashtags"
|
||||
count: "{} users mentioned"
|
||||
common/views/widgets/server.vue:
|
||||
title: "Server info"
|
||||
toggle: "Toggle views"
|
||||
|
@ -70,6 +70,7 @@ common:
|
||||
donation: "寄付のお願い"
|
||||
nav: "ナビゲーション"
|
||||
tips: "ヒント"
|
||||
hashtags: "ハッシュタグ"
|
||||
deck:
|
||||
widgets: "ウィジェット"
|
||||
home: "ホーム"
|
||||
@ -226,6 +227,7 @@ common/views/widgets/posts-monitor.vue:
|
||||
toggle: "表示を切り替え"
|
||||
common/views/widgets/hashtags.vue:
|
||||
title: "ハッシュタグ"
|
||||
count: "{}人が投稿"
|
||||
common/views/widgets/server.vue:
|
||||
title: "サーバー情報"
|
||||
toggle: "表示を切り替え"
|
||||
|
@ -70,6 +70,7 @@ common:
|
||||
donation: "Dons"
|
||||
nav: "Navigation"
|
||||
tips: "Conseils"
|
||||
hashtags: "ハッシュタグ"
|
||||
deck:
|
||||
widgets: "Widgets"
|
||||
home: "Accueil"
|
||||
@ -226,6 +227,7 @@ common/views/widgets/posts-monitor.vue:
|
||||
toggle: "表示を切り替え"
|
||||
common/views/widgets/hashtags.vue:
|
||||
title: "ハッシュタグ"
|
||||
count: "{}人が投稿"
|
||||
common/views/widgets/server.vue:
|
||||
title: "Info sur le serveur"
|
||||
toggle: "Afficher les vues"
|
||||
|
@ -70,6 +70,7 @@ common:
|
||||
donation: "寄付のお願い"
|
||||
nav: "ナビゲーション"
|
||||
tips: "ヒント"
|
||||
hashtags: "ハッシュタグ"
|
||||
deck:
|
||||
widgets: "ウィジェット"
|
||||
home: "ホーム"
|
||||
@ -226,6 +227,7 @@ common/views/widgets/posts-monitor.vue:
|
||||
toggle: "表示を切り替え"
|
||||
common/views/widgets/hashtags.vue:
|
||||
title: "ハッシュタグ"
|
||||
count: "{}人が投稿"
|
||||
common/views/widgets/server.vue:
|
||||
title: "サーバー情報"
|
||||
toggle: "表示を切り替え"
|
||||
|
@ -257,6 +257,8 @@ common/views/widgets/posts-monitor.vue:
|
||||
|
||||
common/views/widgets/hashtags.vue:
|
||||
title: "ハッシュタグ"
|
||||
count: "{}人が投稿"
|
||||
empty: "トレンドなし"
|
||||
|
||||
common/views/widgets/server.vue:
|
||||
title: "サーバー情報"
|
||||
|
@ -70,6 +70,7 @@ common:
|
||||
donation: "寄付のお願い"
|
||||
nav: "ナビゲーション"
|
||||
tips: "ヒント"
|
||||
hashtags: "ハッシュタグ"
|
||||
deck:
|
||||
widgets: "ウィジェット"
|
||||
home: "ホーム"
|
||||
@ -226,6 +227,7 @@ common/views/widgets/posts-monitor.vue:
|
||||
toggle: "表示を切り替え"
|
||||
common/views/widgets/hashtags.vue:
|
||||
title: "ハッシュタグ"
|
||||
count: "{}人が投稿"
|
||||
common/views/widgets/server.vue:
|
||||
title: "サーバー情報"
|
||||
toggle: "表示を切り替え"
|
||||
|
@ -70,6 +70,7 @@ common:
|
||||
donation: "Dotacje"
|
||||
nav: "Nawigacja"
|
||||
tips: "Wskazówki"
|
||||
hashtags: "Hashtagi"
|
||||
deck:
|
||||
widgets: "Widżety"
|
||||
home: "Strona główna"
|
||||
@ -225,7 +226,8 @@ common/views/widgets/posts-monitor.vue:
|
||||
title: "Wykres wpisów"
|
||||
toggle: "Przełącz widok"
|
||||
common/views/widgets/hashtags.vue:
|
||||
title: "ハッシュタグ"
|
||||
title: "Hashtagi"
|
||||
count: "Wspomniany przez {} użytkowników"
|
||||
common/views/widgets/server.vue:
|
||||
title: "Informacje o serwerze"
|
||||
toggle: "Przełącz widok"
|
||||
|
@ -70,6 +70,7 @@ common:
|
||||
donation: "寄付のお願い"
|
||||
nav: "ナビゲーション"
|
||||
tips: "ヒント"
|
||||
hashtags: "ハッシュタグ"
|
||||
deck:
|
||||
widgets: "ウィジェット"
|
||||
home: "ホーム"
|
||||
@ -226,6 +227,7 @@ common/views/widgets/posts-monitor.vue:
|
||||
toggle: "表示を切り替え"
|
||||
common/views/widgets/hashtags.vue:
|
||||
title: "ハッシュタグ"
|
||||
count: "{}人が投稿"
|
||||
common/views/widgets/server.vue:
|
||||
title: "サーバー情報"
|
||||
toggle: "表示を切り替え"
|
||||
|
@ -70,6 +70,7 @@ common:
|
||||
donation: "寄付のお願い"
|
||||
nav: "ナビゲーション"
|
||||
tips: "ヒント"
|
||||
hashtags: "ハッシュタグ"
|
||||
deck:
|
||||
widgets: "ウィジェット"
|
||||
home: "ホーム"
|
||||
@ -226,6 +227,7 @@ common/views/widgets/posts-monitor.vue:
|
||||
toggle: "表示を切り替え"
|
||||
common/views/widgets/hashtags.vue:
|
||||
title: "ハッシュタグ"
|
||||
count: "{}人が投稿"
|
||||
common/views/widgets/server.vue:
|
||||
title: "サーバー情報"
|
||||
toggle: "表示を切り替え"
|
||||
|
@ -70,6 +70,7 @@ common:
|
||||
donation: "寄付のお願い"
|
||||
nav: "ナビゲーション"
|
||||
tips: "ヒント"
|
||||
hashtags: "ハッシュタグ"
|
||||
deck:
|
||||
widgets: "ウィジェット"
|
||||
home: "ホーム"
|
||||
@ -226,6 +227,7 @@ common/views/widgets/posts-monitor.vue:
|
||||
toggle: "表示を切り替え"
|
||||
common/views/widgets/hashtags.vue:
|
||||
title: "ハッシュタグ"
|
||||
count: "{}人が投稿"
|
||||
common/views/widgets/server.vue:
|
||||
title: "サーバー情報"
|
||||
toggle: "表示を切り替え"
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <i@syuilo.com>",
|
||||
"version": "2.37.1",
|
||||
"clientVersion": "1.0.6419",
|
||||
"version": "2.37.7",
|
||||
"clientVersion": "1.0.6474",
|
||||
"codename": "nighthike",
|
||||
"main": "./built/index.js",
|
||||
"private": true,
|
||||
|
@ -40,6 +40,17 @@ export default Vue.component('mk-note-html', {
|
||||
ast = this.ast;
|
||||
}
|
||||
|
||||
if (ast.filter(x => x.type != 'hashtag').length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (
|
||||
ast[ast.length - 1].type == 'hashtag' ||
|
||||
(ast[ast.length - 1].type == 'text' && ast[ast.length - 1].content == ' ') ||
|
||||
(ast[ast.length - 1].type == 'text' && ast[ast.length - 1].content == '\n')) {
|
||||
ast.pop();
|
||||
}
|
||||
|
||||
// Parse ast to DOM
|
||||
const els = flatten(ast.map(token => {
|
||||
switch (token.type) {
|
||||
@ -92,7 +103,7 @@ export default Vue.component('mk-note-html', {
|
||||
case 'hashtag':
|
||||
return createElement('a', {
|
||||
attrs: {
|
||||
href: `${url}/search?q=${token.content}`,
|
||||
href: `${url}/tags/${token.content}`,
|
||||
target: '_blank'
|
||||
}
|
||||
}, token.content);
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
|
||||
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`" style="overflow:visible">
|
||||
<defs>
|
||||
<linearGradient :id="gradientId" x1="0" x2="0" y1="1" y2="0">
|
||||
<stop offset="0%" stop-color="hsl(200, 80%, 70%)"></stop>
|
||||
@ -14,17 +14,17 @@
|
||||
:points="polylinePoints"
|
||||
fill="none"
|
||||
stroke="#fff"
|
||||
stroke-width="0.7"/>
|
||||
stroke-width="2"/>
|
||||
<circle
|
||||
:cx="headX"
|
||||
:cy="headY"
|
||||
r="1.2"
|
||||
r="3"
|
||||
fill="#fff"/>
|
||||
</mask>
|
||||
</defs>
|
||||
<rect
|
||||
x="-2" y="-2"
|
||||
:width="viewBoxX + 4" :height="viewBoxY + 4"
|
||||
x="-10" y="-10"
|
||||
:width="viewBoxX + 20" :height="viewBoxY + 20"
|
||||
:style="`stroke: none; fill: url(#${ gradientId }); mask: url(#${ maskId })`"/>
|
||||
</svg>
|
||||
</template>
|
||||
@ -49,7 +49,8 @@ export default Vue.extend({
|
||||
polylinePoints: '',
|
||||
polygonPoints: '',
|
||||
headX: null,
|
||||
headY: null
|
||||
headY: null,
|
||||
clock: null
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@ -59,16 +60,26 @@ export default Vue.extend({
|
||||
},
|
||||
created() {
|
||||
this.draw();
|
||||
|
||||
// Vueが何故かWatchを発動させない場合があるので
|
||||
this.clock = setInterval(this.draw, 1000);
|
||||
},
|
||||
beforeDestroy() {
|
||||
clearInterval(this.clock);
|
||||
},
|
||||
methods: {
|
||||
draw() {
|
||||
const stats = this.src.slice().reverse();
|
||||
const peak = Math.max.apply(null, stats) || 1;
|
||||
|
||||
const polylinePoints = stats.map((x, i) => [this.viewBoxX - ((stats.length - 1) - i), (1 - (x / peak)) * this.viewBoxY]);
|
||||
const polylinePoints = stats.map((n, i) => [
|
||||
i * (this.viewBoxX / (stats.length - 1)),
|
||||
(1 - (n / peak)) * this.viewBoxY
|
||||
]);
|
||||
|
||||
this.polylinePoints = polylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' ');
|
||||
|
||||
this.polygonPoints = `${this.viewBoxX - (stats.length - 1)},${ this.viewBoxY } ${ this.polylinePoints } ${ this.viewBoxX },${ this.viewBoxY }`;
|
||||
this.polygonPoints = `0,${ this.viewBoxY } ${ this.polylinePoints } ${ this.viewBoxX },${ this.viewBoxY }`;
|
||||
|
||||
this.headX = polylinePoints[polylinePoints.length - 1][0];
|
||||
this.headY = polylinePoints[polylinePoints.length - 1][1];
|
||||
|
@ -5,14 +5,16 @@
|
||||
|
||||
<div class="mkw-hashtags--body" :data-mobile="platform == 'mobile'">
|
||||
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
|
||||
<div v-else>
|
||||
<p class="empty" v-else-if="stats.length == 0">%fa:exclamation-circle%%i18n:@empty%</p>
|
||||
<transition-group v-else tag="div" name="chart">
|
||||
<div v-for="stat in stats" :key="stat.tag">
|
||||
<div class="tag">
|
||||
<router-link :to="`/tags/${ stat.tag }`">#{{ stat.tag }}</router-link>
|
||||
<router-link :to="`/tags/${ stat.tag }`" :title="stat.tag">#{{ stat.tag }}</router-link>
|
||||
<p>{{ '%i18n:@count%'.replace('{}', stat.usersCount) }}</p>
|
||||
</div>
|
||||
<x-chart class="chart" :src="stat.chart"/>
|
||||
</div>
|
||||
</div>
|
||||
</transition-group>
|
||||
</div>
|
||||
</mk-widget-container>
|
||||
</div>
|
||||
@ -40,7 +42,7 @@ export default define({
|
||||
},
|
||||
mounted() {
|
||||
this.fetch();
|
||||
this.clock = setInterval(this.fetch, 1000 * 60 * 10);
|
||||
this.clock = setInterval(this.fetch, 1000 * 60);
|
||||
},
|
||||
beforeDestroy() {
|
||||
clearInterval(this.clock);
|
||||
@ -64,6 +66,7 @@ export default define({
|
||||
root(isDark)
|
||||
.mkw-hashtags--body
|
||||
> .fetching
|
||||
> .empty
|
||||
margin 0
|
||||
padding 16px
|
||||
text-align center
|
||||
@ -73,22 +76,42 @@ root(isDark)
|
||||
margin-right 4px
|
||||
|
||||
> div
|
||||
.chart-enter
|
||||
.chart-leave-to
|
||||
opacity 0
|
||||
transform translateY(-30px)
|
||||
|
||||
> *
|
||||
transition transform .3s ease, opacity .3s ease
|
||||
|
||||
> div
|
||||
display flex
|
||||
align-items center
|
||||
padding 16px
|
||||
padding 14px 16px
|
||||
|
||||
&:not(:last-child)
|
||||
border-bottom solid 1px #393f4f
|
||||
border-bottom solid 1px isDark ? #393f4f : #eee
|
||||
|
||||
> .tag
|
||||
flex 1
|
||||
overflow hidden
|
||||
font-size 14px
|
||||
color isDark ? #9baec8 : #65727b
|
||||
|
||||
> a
|
||||
color #9baec8
|
||||
display block
|
||||
width 100%
|
||||
white-space nowrap
|
||||
overflow hidden
|
||||
text-overflow ellipsis
|
||||
color inherit
|
||||
|
||||
> p
|
||||
margin 0
|
||||
font-size 75%
|
||||
opacity 0.7
|
||||
|
||||
> .chart
|
||||
width 50px
|
||||
height 30px
|
||||
|
||||
.mkw-hashtags[data-darkmode]
|
||||
|
@ -5,7 +5,7 @@
|
||||
<div class="gqpwvtwtprsbmnssnbicggtwqhmylhnq">
|
||||
<template v-if="edit">
|
||||
<header>
|
||||
<select v-model="widgetAdderSelected">
|
||||
<select v-model="widgetAdderSelected" @change="addWidget">
|
||||
<option value="profile">%i18n:common.widgets.profile%</option>
|
||||
<option value="analog-clock">%i18n:common.widgets.analog-clock%</option>
|
||||
<option value="calendar">%i18n:common.widgets.calendar%</option>
|
||||
@ -30,20 +30,15 @@
|
||||
<option value="nav">%i18n:common.widgets.nav%</option>
|
||||
<option value="tips">%i18n:common.widgets.tips%</option>
|
||||
</select>
|
||||
<button @click="addWidget">%i18n:@add%</button>
|
||||
</header>
|
||||
<x-draggable
|
||||
:list="column.widgets"
|
||||
:options="{ handle: '.handle', animation: 150 }"
|
||||
:options="{ animation: 150 }"
|
||||
@sort="onWidgetSort"
|
||||
>
|
||||
<div v-for="widget in column.widgets" class="customize-container" :key="widget.id">
|
||||
<header>
|
||||
<span class="handle">%fa:bars%</span>{{ widget.name }}<button class="remove" @click="removeWidget(widget)">%fa:times%</button>
|
||||
</header>
|
||||
<div @click="widgetFunc(widget.id)">
|
||||
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="deck"/>
|
||||
</div>
|
||||
<div v-for="widget in column.widgets" class="customize-container" :key="widget.id" @contextmenu.stop.prevent="widgetFunc(widget.id)">
|
||||
<button class="remove" @click="removeWidget(widget)">%fa:times%</button>
|
||||
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="deck"/>
|
||||
</div>
|
||||
</x-draggable>
|
||||
</template>
|
||||
@ -142,6 +137,13 @@ export default Vue.extend({
|
||||
|
||||
root(isDark)
|
||||
.gqpwvtwtprsbmnssnbicggtwqhmylhnq
|
||||
> header
|
||||
padding 16px
|
||||
|
||||
> *
|
||||
width 100%
|
||||
padding 4px
|
||||
|
||||
.widget, .customize-container
|
||||
margin 8px
|
||||
|
||||
@ -149,7 +151,21 @@ root(isDark)
|
||||
margin-top 0
|
||||
|
||||
.customize-container
|
||||
background #fff
|
||||
cursor move
|
||||
|
||||
> *:not(.remove)
|
||||
pointer-events none
|
||||
|
||||
> .remove
|
||||
position absolute
|
||||
z-index 1
|
||||
top 8px
|
||||
right 8px
|
||||
width 32px
|
||||
height 32px
|
||||
color #fff
|
||||
background rgba(#000, 0.7)
|
||||
border-radius 4px
|
||||
|
||||
> header
|
||||
color isDark ? #fff : #000
|
||||
|
@ -1,13 +1,26 @@
|
||||
import Note from '../../../../models/note';
|
||||
|
||||
/*
|
||||
トレンドに載るためには「『直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上』のハッシュタグの上位5位以内に入る」ことが必要
|
||||
ユニーク投稿数とはそのハッシュタグと投稿ユーザーのペアのカウントで、例えば同じユーザーが複数回同じハッシュタグを投稿してもそのハッシュタグのユニーク投稿数は1とカウントされる
|
||||
*/
|
||||
|
||||
const rangeA = 1000 * 60 * 30; // 30分
|
||||
const rangeB = 1000 * 60 * 120; // 2時間
|
||||
const coefficient = 1.5; // 「n倍」の部分
|
||||
const requiredUsers = 3; // 最低何人がそのタグを投稿している必要があるか
|
||||
|
||||
const max = 5;
|
||||
|
||||
/**
|
||||
* Get trends of hashtags
|
||||
*/
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
module.exports = () => new Promise(async (res, rej) => {
|
||||
//#region 1. 直近Aの内に投稿されたハッシュタグ(とユーザーのペア)を集計
|
||||
const data = await Note.aggregate([{
|
||||
$match: {
|
||||
createdAt: {
|
||||
$gt: new Date(Date.now() - 1000 * 60 * 60)
|
||||
$gt: new Date(Date.now() - rangeA)
|
||||
},
|
||||
tags: {
|
||||
$exists: true,
|
||||
@ -18,49 +31,83 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
$unwind: '$tags'
|
||||
}, {
|
||||
$group: {
|
||||
_id: '$tags',
|
||||
count: {
|
||||
$sum: 1
|
||||
}
|
||||
}
|
||||
}, {
|
||||
$group: {
|
||||
_id: null,
|
||||
tags: {
|
||||
$push: {
|
||||
tag: '$_id',
|
||||
count: '$count'
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
$project: {
|
||||
_id: false,
|
||||
tags: true
|
||||
_id: { tags: '$tags', userId: '$userId' }
|
||||
}
|
||||
}]) as Array<{
|
||||
tags: Array<{
|
||||
tag: string;
|
||||
count: number;
|
||||
}>
|
||||
_id: {
|
||||
tags: string;
|
||||
userId: any;
|
||||
}
|
||||
}>;
|
||||
//#endregion
|
||||
|
||||
if (data.length == 0) {
|
||||
return res([]);
|
||||
}
|
||||
|
||||
const hots = data[0].tags
|
||||
const tags = [];
|
||||
|
||||
// カウント
|
||||
data.map(x => x._id).forEach(x => {
|
||||
const i = tags.findIndex(tag => tag.name == x.tags);
|
||||
if (i != -1) {
|
||||
tags[i].count++;
|
||||
} else {
|
||||
tags.push({
|
||||
name: x.tags,
|
||||
count: 1
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 最低要求投稿者数を下回るならカットする
|
||||
const limitedTags = tags.filter(tag => tag.count >= requiredUsers);
|
||||
|
||||
//#region 2. 1で取得したそれぞれのタグについて、「直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上」かどうかを判定する
|
||||
const hotsPromises = limitedTags.map(async tag => {
|
||||
const passedCount = (await Note.distinct('userId', {
|
||||
tags: tag.name,
|
||||
createdAt: {
|
||||
$lt: new Date(Date.now() - rangeA),
|
||||
$gt: new Date(Date.now() - rangeB)
|
||||
}
|
||||
}) as any).length;
|
||||
|
||||
if (tag.count >= (passedCount * coefficient)) {
|
||||
return tag;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
//#endregion
|
||||
|
||||
// タグを人気順に並べ替え
|
||||
let hots = (await Promise.all(hotsPromises))
|
||||
.filter(x => x != null)
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.map(tag => tag.tag)
|
||||
.slice(0, 10);
|
||||
.map(tag => tag.name)
|
||||
.slice(0, max);
|
||||
|
||||
const countPromises: Array<Promise<number[]>> = [];
|
||||
//#region 3. もし上記の方法でのトレンド抽出の結果、求められているタグ数に達しなければ「ただ単に現在投稿数が多いハッシュタグ」に切り替える
|
||||
if (hots.length < max) {
|
||||
hots = hots.concat(tags
|
||||
.filter(tag => hots.indexOf(tag.name) == -1)
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.map(tag => tag.name)
|
||||
.slice(0, max - hots.length));
|
||||
}
|
||||
//#endregion
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
// 10分
|
||||
const interval = 1000 * 60 * 10;
|
||||
//#region 2(または3)で話題と判定されたタグそれぞれについて過去の投稿数グラフを取得する
|
||||
const countPromises: Array<Promise<any[]>> = [];
|
||||
|
||||
countPromises.push(Promise.all(hots.map(tag => Note.count({
|
||||
const range = 20;
|
||||
|
||||
// 10分
|
||||
const interval = 1000 * 60 * 10;
|
||||
|
||||
for (let i = 0; i < range; i++) {
|
||||
countPromises.push(Promise.all(hots.map(tag => Note.distinct('userId', {
|
||||
tags: tag,
|
||||
createdAt: {
|
||||
$lt: new Date(Date.now() - (interval * i)),
|
||||
@ -71,9 +118,18 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
|
||||
const countsLog = await Promise.all(countPromises);
|
||||
|
||||
const totalCounts: any = await Promise.all(hots.map(tag => Note.distinct('userId', {
|
||||
tags: tag,
|
||||
createdAt: {
|
||||
$gt: new Date(Date.now() - (interval * range))
|
||||
}
|
||||
})));
|
||||
//#endregion
|
||||
|
||||
const stats = hots.map((tag, i) => ({
|
||||
tag,
|
||||
chart: countsLog.map(counts => counts[i])
|
||||
chart: countsLog.map(counts => counts[i].length),
|
||||
usersCount: totalCounts[i].length
|
||||
}));
|
||||
|
||||
res(stats);
|
||||
|
Reference in New Issue
Block a user