0
0
Fork 0
This commit is contained in:
Xeltica 2021-01-30 01:48:00 +09:00
parent 2e253f52bc
commit 2b71549feb
7 changed files with 90 additions and 44 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "misshaialert", "name": "misshaialert",
"version": "1.5.0", "version": "1.5.1",
"description": "", "description": "",
"main": "built/app.js", "main": "built/app.js",
"author": "Xeltica", "author": "Xeltica",

View file

@ -1,9 +1,7 @@
export default { export default {
version: '1.5.0', version: '1.5.1',
changelog: [ changelog: [
'UIを全般的にスタイリッシュに刷新', 'インスタンスの接続エラーにより後続処理が行えなくなる重大な不具合を修正',
'自動投稿のテンプレートをカスタマイズできる機能を追加', '全員分の算出が終わるまで、ランキングを非表示に',
'自動投稿の公開範囲を設定できるように',
'新機能 みす廃ランキング および、みす廃レートを追加',
], ],
}; };

View file

@ -15,6 +15,7 @@ import { send } from '../services/send';
import { visibilities, Visibility } from '../types/Visibility'; import { visibilities, Visibility } from '../types/Visibility';
import { defaultTemplate, variables } from '../functions/format'; import { defaultTemplate, variables } from '../functions/format';
import { getRanking } from '../functions/ranking'; import { getRanking } from '../functions/ranking';
import { getState } from '../store';
export const router = new Router<DefaultState, Context>(); export const router = new Router<DefaultState, Context>();
@ -65,23 +66,28 @@ router.get('/', async ctx => {
const usersCount = await getUserCount(); const usersCount = await getUserCount();
const ranking = await getRanking(10); const ranking = await getRanking(10);
const commonLocals = {
usersCount, ranking,
state: getState(),
from: ctx.query.from,
};
if (user && isAvailable) { if (user && isAvailable) {
const meta = await api<{ version: string }>(user?.host, 'meta', {}); const meta = await api<{ version: string }>(user?.host, 'meta', {});
await ctx.render('mypage', { await ctx.render('mypage', {
user, usersCount, ranking, ...commonLocals,
user,
// To Activate Groundpolis Mode // To Activate Groundpolis Mode
isGroundpolis: meta.version.includes('gp'), isGroundpolis: meta.version.includes('gp'),
defaultTemplate, defaultTemplate,
templateVariables: variables, templateVariables: variables,
score: await getScores(user), score: await getScores(user),
from: ctx.query.from,
}); });
} else { } else {
// 非ログイン // 非ログイン
await ctx.render('welcome', { await ctx.render('welcome', {
usersCount, ranking, ...commonLocals,
welcomeMessage: welcomeMessage[Math.floor(Math.random() * welcomeMessage.length)], welcomeMessage: welcomeMessage[Math.floor(Math.random() * welcomeMessage.length)],
from: ctx.query.from,
}); });
} }
}); });
@ -148,6 +154,7 @@ router.get('/teapot', async ctx => {
router.get('/ranking', async ctx => { router.get('/ranking', async ctx => {
await ctx.render('ranking', { await ctx.render('ranking', {
state: getState(),
ranking: await getRanking(null), ranking: await getRanking(null),
}); });
}); });

View file

@ -9,32 +9,44 @@ import { AlertMode } from '../types/AlertMode';
import { Users } from '../models'; import { Users } from '../models';
import { send } from './send'; import { send } from './send';
import { api } from './misskey'; import { api } from './misskey';
import * as Store from '../store';
export default (): void => { export default (): void => {
cron.schedule('0 0 0 * * *', async () => { cron.schedule('0 0 0 * * *', async () => {
Store.dispatch({
nowCalculating: true,
});
const users = await Users.find({ const users = await Users.find({
alertMode: Not<AlertMode>('nothing'), alertMode: Not<AlertMode>('nothing'),
}); });
for (const user of users) { for (const user of users) {
const miUser = await api<MiUser & { error: unknown }>(user.host, 'users/show', { username: user.username }, user.token);
try { try {
const miUser = await api<MiUser & { error: unknown }>(user.host, 'users/show', { username: user.username }, user.token);
if (miUser.error) throw miUser.error; if (miUser.error) throw miUser.error;
await updateRating(user, miUser); await updateRating(user, miUser);
await send(user); await send(user);
} catch (e) {
if (e.code === 'NO_SUCH_USER' || e.code === 'AUTHENTICATION_FAILED') { await updateScore(user, miUser);
// ユーザーが削除されている場合、レコードからも消してとりやめ
console.info(`${user.username}@${user.host} is deleted, so delete this user from the system`);
await deleteUser(user.username, user.host);
} else {
console.error(`${e.name}: ${e.message}`);
}
} finally {
if (user.alertMode === 'note') if (user.alertMode === 'note')
await delay(3000); await delay(3000);
await updateScore(user, miUser); } catch (e) {
if (e.code) {
if (e.code === 'NO_SUCH_USER' || e.code === 'AUTHENTICATION_FAILED') {
// ユーザーが削除されている場合、レコードからも消してとりやめ
console.info(`${user.username}@${user.host} is deleted, so delete this user from the system`);
await deleteUser(user.username, user.host);
} else {
console.error(`Misskey Error: ${JSON.stringify(e)}`);
}
} else {
// おそらく通信エラー
console.error(`Unknown error: ${e.name} ${e.message}`);
}
} }
} }
Store.dispatch({
nowCalculating: false,
});
}); });
}; };

22
src/store.ts Normal file
View file

@ -0,0 +1,22 @@
// Fluxもどき簡易Store
// getStateを介してステートを取得し、dispatchによって更新する
// stateを直接編集できないようになっている
const defaultState: State = {
nowCalculating: false,
};
let _state: Readonly<State> = defaultState;
export type State = {
nowCalculating: boolean,
};
export const getState = () => Object.freeze({..._state});
export const dispatch = (mutation: Partial<State>) => {
_state = {
..._state,
...mutation,
};
};

View file

@ -10,27 +10,31 @@ mixin ranking()
p p
i.fas.fa-users i.fas.fa-users
strong 登録者数: !{usersCount}人 strong 登録者数: !{usersCount}人
+rankingTable() if state && state.nowCalculating
p: a(href="/ranking") 全員分見る p 現在計算中です。後ほどご確認ください
else
+rankingTable()
p: a(href="/ranking") 全員分見る
mixin rankingTable() mixin rankingTable()
table table
thead: tr thead: tr
th 順位 th 順位
th ユーザー th ユーザー
th レート th レート
tbody tbody
-
let rank = 1;
let lastRating = '';
each rec in ranking
- const rating = rec.rating.toFixed(2);
tr
td=rank
td: +exta(href="https://" + rec.host + "/@" + rec.username) @!{rec.username}@!{rec.host}
td=rating
- -
if (lastRating !== rating) { let rank = 1;
rank++; let lastRating = '';
} each rec in ranking
lastRating = rating - const rating = rec.rating.toFixed(2);
tr
td=rank
td: +exta(href="https://" + rec.host + "/@" + rec.username) @!{rec.username}<wbr/>@!{rec.host}
td=rating
-
if (lastRating !== rating) {
rank++;
}
lastRating = rating

View file

@ -9,4 +9,7 @@ block content
summary これは何? summary これは何?
p みす廃ランキングは、独自に算出された「<strong>みす廃レート</strong>」の高い順ランキングです。毎日みす廃あらーとが発行される度に更新されます。 p みす廃ランキングは、独自に算出された「<strong>みす廃レート</strong>」の高い順ランキングです。毎日みす廃あらーとが発行される度に更新されます。
p みす廃レートは、登録日からの経過日数およびノート数から算出されます。 p みす廃レートは、登録日からの経過日数およびノート数から算出されます。
+rankingTable if state.nowCalculating
p 現在計算中です。後ほどご確認ください
else
+rankingTable