-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
339 lines (291 loc) · 11.7 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
/* eslint-disable camelcase */
import * as Misskey from 'misskey-js';
import axios from 'axios';
import schedule from 'node-schedule';
import * as dotenv from 'dotenv';
// eslint-disable-next-line import/extensions
import MessageMaker from './message-maker.js';
// 設定項目読み込み
dotenv.config();
const { BOT_TOKEN, MISSKEY_URL, JSON_URL, npm_package_version, BTM_JSON_URL } = process.env;
process.title = 'Grizzco Misskey Bot';
// Misskeyへ接続
/**
* Misskey Client
* @since v1.0.0
* @type {Misskey}
* @instance
*/
const cli = new Misskey.api.APIClient(
{
origin: MISSKEY_URL,
credential: BOT_TOKEN
});
// 追加用のスケジューラーを空で用意
/**
* Blank variable for scheduler.
* @since v1.0.0
* @type {schedule}
*/
let salmonjobExtra;
// 現在時刻を取得する
/**
* Get UNIX Time now.
* @since v1.0.0
* @return {string} - UNIX time now.
*/
const getNowUnixTime = () => {
const now = Date.now() / 1000;
return now;
}
// メッセージ送信用function
/**
* Send message to Misskey.
* @since v1.0.0
* @param {string} msg - Message to send.
* @param {boolean} visibility - Flag of visibility.
* @param {boolean} cw - Flag of CW.
* @param {string} replyId - User ID to reply.
* @returns {void}
*/
const sendMessage = async (msg, visibility = null, cw = null, replyId = null) => {
console.log('func: sendMessage');
const args = { text: msg };
if (visibility) {
args.visibility = visibility;
}
if (cw) {
args.cw = cw;
}
if (replyId) {
args.replyId = replyId;
}
await cli.request('notes/create', args).catch(e => { console.error(e) });
}
// サーモンランルール
/**
* Make and send message to Misskey.
* @since v1.0.0
* @returns {void}
*/
const salmonrun = async () => {
try {
const res = await axios.get(JSON_URL);
// スケジュールを分類
const regular = res.data.results.filter((shift) => shift.is_big_run === false);
const bigrun = res.data.results.filter((shift) => shift.is_big_run === true);
// 現在時刻を取得
const nowUnix = getNowUnixTime();
// もしビッグランのスケジュールがなければ
if (bigrun.length === 0) {
// 終了時刻を取得
let end = new Date(regular[0].end_time);
let endUnix = end.getTime() / 1000;
// 残り時間を計算
let restOfHours = Math.ceil((endUnix - nowUnix) / (60 * 60));
// もし残り時間が0時間なら次のシフトを基準にしたい
let i = 0;
if (restOfHours === 0) {
i = 1;
// 対象で計算し直し
end = new Date(regular[i].end_time);
endUnix = end.getTime() / 1000;
restOfHours = Math.ceil((endUnix - nowUnix) / (60 * 60));
}
const now = new MessageMaker(regular[i], restOfHours);
let msg = now.maker();
// もし残りが2時間なら次のシフトのお知らせを追加
if (restOfHours === 2) {
const next = new MessageMaker(regular[i + 1], 40, false, true);
msg += "\n---\n";
msg += next.maker();
// 一回だけ1時間おきにしたいので、追加する
const extraDate = new Date(regular[i].end_time);
const extraNoteDate = ((extraDate.getTime() / 1000) - 60 * 60) * 1000;
console.log(extraNoteDate.toLocaleString());
// eslint-disable-next-line no-use-before-define
salmonjobExtra = schedule.scheduleJob(extraNoteDate, () => { salmonrunextra() });
console.log(`set: salmonrunextra at ${extraNoteDate}`);
}
console.log(msg);
sendMessage(msg);
}
// ビッグランのシフトがあったら
// 今がビッグランのシフトだったら
else if (Date(bigrun[0].start_time).getTime() / 1000 < getNowUnixTime()) {
// 終了時刻を取得
const end = new Date(bigrun[0].end_time);
const endUnix = end.getTime() / 1000;
// 残り時間を計算
const restOfHours = Math.ceil((endUnix - nowUnix) / (60 * 60));
// もし残り時間が0時間なら次のシフトを基準にしたい
let i = 0;
if (restOfHours === 0) {
i = 1;
}
const now = new MessageMaker(bigrun[i], restOfHours, false, false, true);
let msg = now.maker();
// もし残りが2時間なら次のシフトのお知らせを追加
if (restOfHours === 2) {
const next = new MessageMaker(regular[0], 40, false, true);
msg += "\n---\n";
msg += next.maker();
// 一回だけ1時間おきにしたいので、追加する
const extraDate = new Date(regular[0].end_time);
const extraNoteDate = ((extraDate.getTime() / 1000) - 60 * 60) * 1000;
console.log(extraNoteDate.toLocaleString());
// eslint-disable-next-line no-use-before-define
salmonjobExtra = schedule.scheduleJob(extraNoteDate, () => { salmonrunextra() });
console.log(`set: salmonrunextra at ${extraNoteDate}`);
}
sendMessage(msg);
}
// この先ビッグランの予定があるときは
else {
// 終了時刻を取得
let end = new Date(bigrun[0].end_time);
let endUnix = end.getTime() / 1000;
// 残り時間を計算
let restOfHours = Math.ceil((endUnix - nowUnix) / (60 * 60));
// もし残り時間が0時間なら次のシフトを基準にしたい
let i = 0;
if (restOfHours === 0) {
i = 1;
// 対象で計算し直し
end = new Date(bigrun[i].end_time);
endUnix = end.getTime() / 1000;
restOfHours = Math.ceil((endUnix - nowUnix) / (60 * 60));
}
const now = new MessageMaker(regular[i], restOfHours);
let msg = now.maker();
// もし残りが2時間なら次のシフトのお知らせを追加
if (restOfHours === 2) {
// ビッグランよりも通常シフトが先なら次のシフトの情報を挟む
if (Date(regular[i + 1].start_time) < DataView(bigrun[0].start_time)) {
const next = new MessageMaker(regular[i + 1], 40, false, true);
const nextbigrun = new MessageMaker(bigrun[0], 48, false, false, true, false, true);
msg += "\n---\n";
msg += next.maker();
msg += "\n---\n";
msg += nextbigrun.maker();
}
// 次がビッグランだったら次の情報として繋ぐ
else {
const nextbigrun = new MessageMaker(bigrun[0], 48, false, true, true, false, true);
msg += "\n---\n";
msg += nextbigrun.maker();
}
// 一回だけ1時間おきにしたいので、追加する
const extraDate = new Date(regular[0].end_time);
const extraNoteDate = ((extraDate.getTime() / 1000) - 60 * 60) * 1000;
console.log(extraNoteDate.toLocaleString());
// eslint-disable-next-line no-use-before-define
salmonjobExtra = schedule.scheduleJob(extraNoteDate, () => { salmonrunextra() });
console.log(`set: salmonrunextra at ${extraNoteDate}`);
}
// ビッグランの情報を付ける
else {
const nextbigrun = new MessageMaker(bigrun[0], 48, false, false, true, false, true);
msg += "\n---\n";
msg += nextbigrun.maker();
}
sendMessage(msg);
}
const teamcontestRes = await axios.get(BTM_JSON_URL);
const teamcontest = teamcontestRes.data.results;
if (teamcontest.length > 0) {
if (Date(teamcontest[0].start_time).getTime() / 1000 > nowUnix) {
const nextteamcontest = new MessageMaker(teamcontest[0], 48, false, true, false, true, false);
sendMessage(nextteamcontest.maker());
} else {
// 残り時間を計算
const restOfHours = Math.ceil(((Date(teamcontest[0].end_time).getTime() / 1000) - nowUnix) / (60 * 60));
const nextteamcontest = new MessageMaker(teamcontest[0], restOfHours, false, false, false, true, false);
sendMessage(nextteamcontest.maker());
}
}
} catch (e) {
console.error(e);
sendMessage('$[x2 :error:]\nAPIのデータに問題があるため、定時のシフトのお知らせができませんでした。');
}
}
// 追加で1時間分流す時の分
/**
* Send the last hour message to Misskey
* @since v1.0.0
* @returns {void}
*/
const salmonrunextra = async () => {
const res = await axios.get(JSON_URL);
// 現在時刻を取得
const nowUnix = getNowUnixTime();
// スケジュールを分類
const regular = res.data.results.filter((shift) => shift.is_big_run === false);
const bigrun = res.data.results.filter((shift) => shift.is_big_run === true);
// const { regular, bigrun } = res.data;
let msg = ''
// レギュラーが時間内だったら、レギュラーを対象にする。それ以外はビッグラン扱い。
if ((Date(regular[0].start_time).getTime() / 1000) < nowUnix && (Date(regular[0].end_time).getTime() / 1000) > nowUnix) {
const now = new MessageMaker(regular[0], 1, true);
let nextShift;
if (bigrun.length === 0 || Date(regular[1].start_time) < Date(bigrun[0].start_time)) {
[, nextShift] = regular;
} else {
[nextShift] = bigrun;
}
const next = new MessageMaker(nextShift, 40, false, true);
msg += now.maker();
msg += "\n---\n";
msg += next.maker();
} else {
const now = new MessageMaker(bigrun[0], 1, true, false, true);
const next = new MessageMaker(regular[0], 40, false, true);
msg += now.maker();
msg += "\n---\n";
msg += next.maker();
}
console.log(msg);
sendMessage(msg);
salmonjobExtra.cancel();
console.log('cancel: salmonrunextra');
}
// スケジュール。奇数時間の正時に実行。
/**
* Regular schedule.
* @since v1.0.0
* @type {schedule}
*/
// eslint-disable-next-line no-unused-vars
const salmonjob = schedule.scheduleJob('0 0 1-23/2 * * *', () => { salmonrun() });
/**
* Return time.
* @since v1.0.1
* @param {int} restOfHours - Rest of hours of the shift.
* @param {Object} data - Shift object.
* @param {int} nowUnix - Unix Time of now.
* @returns {Object} - New end time and new rest of hours.
*/
// const returnTime = (restOfHours, data, nowUnix) => {
// let newEndUnix;
// let newRestOfHours;
// if (restOfHours === 0) {
// newEndUnix = data[1].endunix;
// newRestOfHours = Math.ceil((newEndUnix - nowUnix) / (60 * 60));
// } else {
// newEndUnix = data[0].endunix;
// newRestOfHours = Math.ceil((newEndUnix - nowUnix) / (60 * 60));
// }
// return { newEndUnix, newRestOfHours };
// }
// salmonrun();
// 起動時メッセージ
/**
* Send up message to misskey
* @since v1.0.0
* @returns {void}
*/
const upNotice = () => {
console.log('[upNotice] Misskey bot up!');
sendMessage(`【Bot再起動通知】v${npm_package_version} で起動しました。`);
}
upNotice();