userdefinedscheduler_ja - noonworks/Nursery GitHub Wiki
UserDefinedSchedulerプラグイン
UserDefinedSchedulerプラグインは、ユーザーが自分で定義したスケジュールで、Botからのメッセージ送信および音声読み上げを行えるプラグインです。
1. プラグインの有効化
標準で有効化されています。特に操作は必要ありません。
2. ユーザー定義スケジュールを追加する
2-1. ユーザー定義スケジュールを作成する
標準では、Nurseryのフォルダ内のschedules
以下に、ユーザー定義スケジュールの設定を保存します。フォルダがない場合は作成してください。
その後、schedules\three_minutes.json
として、以下のファイルを保存します。
{
"name": "three_minutes",
"conditions": [
{
"type": "interval",
"interval_minutes": 3,
"interval_start_option": "run_next"
}
],
"processes": [
{
"type": "send_message",
"values": [
"3分が経過しました。 ${count} / ${total_count} [${HH}:${mm}]"
]
}
]
}
2-2. ユーザー定義スケジュールを実行する
ファイルを追加した後、Nurseryを起動し、入室させます。その後3分が経過すると、botが以下のような発言をします。
3分が経過しました。 1 / 1 [06:35]
- その後も、3分経過するたびに同様の発言をします。
- botを
bye
などで退室させると、3分が経過しても、発言をしません。 1 / 1
は実行回数 / 合計実行回数
です。実行のたびに増えていきます。実行回数
は、入室してから実行した回数です。一度退室すると、0にリセットされます。合計実行回数
は、スケジュール設定が読み込まれてから実行した合計回数です。
[06:35]
は現在時刻です。botはPCのローカル時刻を参照しているため、Discordのサーバー時刻とはずれる可能性があります。
3. コマンド
@nursery-bot udsreload
3-1. ユーザー定義スケジュールを再読み込みするコマンドです。
通常、ユーザー定義スケジュールはNursery起動時に自動で読み込まれるので、このコマンドを使用する必要はありません。ただし、Nursery起動中に設定を変更した場合、変更した分は自動で再読み込みされません。その場合にこのコマンドを使って再読み込みします。
4. ユーザー定義スケジュール設定詳細
- 設定ファイルはJSON形式です。
- 必要に応じて
"
や\
などはJSON形式のエスケープをしてください。
4-1. スケジュールの設定
{
"name": "name_of_this_schedule",
"conditions": [],
"processes": []
}
name
: このスケジュールの名前を指定します。任意の名前を付けます。conditions
: スケジュールが実行される条件を、配列で指定します。どれかひとつの条件が成立した場合、スケジュールが実行されます。processes
: スケジュールの実行内容を、配列で指定します。すべてが実行されます。
4-2. 実行条件
4-2-1. 間隔条件(インターバル条件)
- 「指定した時間ごとに、定期的に起動する」という条件です。
- 分単位での設定が可能です。
- Botがボイスチャットに入室している間のみ起動します。
{
"type": "interval",
"interval_minutes": 3,
"interval_start_option": "run_next",
"interval_start_at": ""
}
type
:"interval"
を指定します。interval_minutes
: 間隔(分)を数値で指定します。interval_start_option
: 間隔の計算開始タイミングを指定します。"run_on_join"
: Botが入室したときに、すぐ1回目を実行します。"run_next"
: Botが入室したときには実行せず、次から実行します。"not_start"
: Botが入室しても、間隔の計算を開始しません。(他の条件と組み合わせるときに使います。)"start_at"
:interval_start_at
で指定した日時から間隔の計算をします。
interval_start_at
: 間隔の計算を開始する日時を指定します。interval_start_option
が"start_at"
のときのみ有効です。- 日時は
yyyy.MM.dd-HH:mm
形式で指定します。(例:2018年8月14日21時3分は2018.08.14-21:03
)
4-2-2. 時間範囲条件
- 「指定した範囲の時間に該当した場合、起動する」という条件です。
- 分単位での設定が可能です。
- Botがボイスチャットに入室している間のみ起動します。
- 時間範囲に該当した最初の1回のみ、スケジュールが実行されます。
- 例:「9:00から12:00まで」という範囲の場合
- 9:00にスケジュールが実行された場合、9:01や10:00、11:30などにはスケジュールは実行されません。
- 9:00にはBotが入室しておらず、9:45に入室した場合、入室時にスケジュールが実行されます。
- 9:00にスケジュールが実行された場合、次にスケジュールが実行されるのは、以下のタイミングです。
- 12:00までの間に、Botが一度退室して再入室したとき
- 12:00までの間に、ユーザー定義スケジュール設定の再読み込みコマンドが実行されたとき
- 翌日の9:00
- 例:「9:00から12:00まで」という範囲の場合
{
"type": "time_range",
"time_range_start": 900,
"time_range_end": 1200,
"time_range_date_pattern": "",
"time_range_use_previous_day": false
}
type
:"time_range"
を指定します。time_range_start
、time_range_end
: 時間範囲の開始と終了を数値で指定します。- 時刻を最大4桁の数字で指定します。9:30は
930
、22:53は2253
、0:03は3
、0:00は0
になります。 - ここで指定した数値の時刻自体は範囲に含まれます。
開始 > 終了
の場合、日をまたいだ設定とみなします。- 開始が
2100
で終了が100
の場合、21:00から翌日の1:00までとみなす。
- 開始が
- 時刻を最大4桁の数字で指定します。9:30は
time_range_date_pattern
: 日付の条件を指定します。- DateTimeMatcherの書式で指定します。
- デフォルトは空(指定なし)です。
- 例えば「火曜日の21時から23時」といった範囲を指定可能です。
time_range_use_previous_day
: 日付をまたいた設定の場合で、基準の日を前日にするオプションです。- 通常、日付をまたいだ設定では、「当日から翌日にかけて」の設定とみなします。「当日」が
time_range_date_pattern
の判定に使われる基準の日になります。 time_range_use_previous_day
をtrue
にすると、日付をまたいだ設定を「前日から当日にかけて」とみなします。「当日」がtime_range_date_pattern
の判定に使われる基準の日になります。- 使用例は後述のサンプルを確認してください。
- 通常、日付をまたいだ設定では、「当日から翌日にかけて」の設定とみなします。「当日」が
4-2-2-1. 時間範囲条件サンプル① 毎日21:00~22:30
{
"type": "time_range",
"time_range_start": 2100,
"time_range_end": 2230
}
time_range_date_pattern
がないので、毎日条件に一致します。
4-2-2-2. 時間範囲条件サンプル② 毎週火曜22:30~翌日1:00
{
"type": "time_range",
"time_range_start": 2230,
"time_range_end": 100,
"time_range_date_pattern": "****.**.**-*2-**:**"
}
time_range_date_pattern
の*2
が火曜を表します。(DateTimeMatcherの書式)開始(2230) > 終了(100)
なので、日をまたいだ設定とみなされます。- 「当日から翌日にかけて」の設定とみなされます。(当日=
time_range_date_pattern
の基準になる日=火曜)
4-2-2-3. 時間範囲条件サンプル③ 毎月、前日~最終日曜の深夜
{
"type": "time_range",
"time_range_start": 2300,
"time_range_end": 100,
"time_range_date_pattern": "****.**.**-L0-**:**",
"time_range_use_previous_day": true
}
time_range_date_pattern
のL0
が最終日曜日を表します。(DateTimeMatcherの書式)- 「最終日曜の前日」は最終土曜とは限らない(月末が土曜の場合は月が変わる)ので、
time_range_use_previous_day
を使って「前日から当日」(当日=time_range_date_pattern
の基準になる日=最終日曜)に設定しています。
4-2-3. 日時条件
- 「指定した日時に該当した場合、起動する」という条件です。
- Botがボイスチャットに入室している間のみ起動します。
- 指定日時に該当した最初の1回のみ、スケジュールが実行されます。
- 詳細は後述のサンプルを参照してください。
{
"type": "date_time",
"date_time_pattern": ""
}
type
:"time_range"
を指定します。time_range_date_pattern
: 日時条件をDateTimeMatcherの書式で指定します。
4-2-3-1. 日時条件サンプル① 毎時10分(1)
{
"type": "date_time",
"date_time_pattern": "****.**.**-**-**:10"
}
- 分以外の条件がないので、毎時
10
分に起動します。- 10分にBotが入室しておらず、15分に入室した場合、次の10分に起動します。
4-2-3-2. 日時条件サンプル② 毎時10分(2)
{
"type": "date_time",
"date_time_pattern": "****.**.**-**-**:1*"
}
- 分以外の条件がないので、毎時
1*
分に起動します。- 基本的には10分に起動します。
- 10分にBotが入室しておらず、例えば15分に入室した場合、15分に起動します。
4-2-3-3. 日時条件サンプル③ 12時台
{
"type": "date_time",
"date_time_pattern": "****.**.**-**-12:**"
}
- 時以外の条件がないので、毎日
12
時に起動します。- 基本的には12時に起動します。
- 12時にBotが入室しておらず、例えば12:40に入室した場合、12:40に起動します。
4-2-4. 関数条件
- JavaScriptの関数を使って条件を記述します。
- Botがボイスチャットに入室している間のみ起動します。
- 関数は
function_str
もしくはfunction_file
のどちらかで指定します。 - 関数が長い場合、
function_file
を使った方が管理が楽になります。
{
"type": "function",
"function_str": "",
"function_file": "",
"function_name": ""
}
type
:"function"
を指定します。function_str
: JavaScriptコードを文字列で指定します。エスケープを忘れないよう注意してください。関数の仕様は後述します。function_file
が指定されていた場合、function_str
は無視されます。function_file
: JavaScriptコードの記述されたファイルのパスを文字列で指定します。関数の仕様は後述します。function_name
: 関数名を文字列で指定します。function_str
もしくはfunction_file
で指定したJavaScriptコードのうち、ここで指定した関数が呼ばれます。
function function_name(obj) {
// ...
return true;
}
- 関数は、
JSScheduleArgument
型の引数1つを受け取り、bool
型の結果を返します。true
を返した場合、条件が成立したとみなします。false
をを返した場合、条件が成立しなかったとみなします。
JSScheduleArgument
型およびそのメンバの型についてはJavaScriptから使用可能なインターフェースを参照してください。
4-2-4-1. JavaScript関数の例
設定ファイルと関数ファイルのセットをschedules
フォルダに保存します。
- 設定ファイル
sec30.json
{
"name": "sec30",
"conditions": [
{
"type": "function",
"function_name": "sec30_condition",
"function_file": "sec30_condition.js"
}
],
"processes": [
// 以下の内容についてはセクション4.3.3で解説
{
"type": "function",
"function_name": "sec30_process",
"function_file": "sec30_process.js"
}
]
}
- 関数ファイル
sec30_condition.js
// 秒針が0秒か30秒のときにスケジュールを実行するよう設定する条件関数
function sec30_condition(obj) {
var now = new Date();
// 現在日時を文字列化する。
var now_str = '' + now.getFullYear() + '/' +
('00' + (now.getMonth() + 1)).slice(-2) + '/' +
('00' + now.getDate()).slice(-2) + ' ' +
('00' + now.getHours()).slice(-2) + ':' +
('00' + now.getMinutes()).slice(-2) + ':' +
('00' + now.getSeconds()).slice(-2);
// obj.Scheduler.AdditionalData は、各スケジュールが持つ変数で、
// JS関数が任意の文字列を保存・参照してよい。
// ここでは「前回の実行日時」を保存する。
// 前回の実行日時が現在日時と同一の場合、重複して実行しないようにする。
if (obj.Scheduler.AdditionalData == now_str) { return false; }
// 実行するか判定する。(秒針が0か30)
var run = (now.getSeconds() % 30 == 0);
// 実行する場合、現在日時を「前回の実行日時」として
// obj.Scheduler.AdditionalData に保存する。
if (run) { obj.Scheduler.AdditionalData = now_str; }
return run;
}
4-3. 実行内容
4-3-1. メッセージの送信
- BotからDiscordにメッセージを送信します。
{
"type": "send_message",
"values": [],
"send_to_type": "default",
"send_to": [],
"cut_if_too_long": true
}
type
:"send_message"
を指定します。values
: 送信するメッセージを文字列の配列で指定します。- メッセージには特殊書式が使用できます。
send_to_type
: 送信先の種類を指定します。default
: デフォルトのテキストチャンネル(Botを呼ぶときに使ったテキストチャンネル)に送信します。all
: Botが参加しているすべてのテキストチャンネルに送信します。- ただし、
${announce}
と${speak}
のラベルは1つ目のチャンネルにしか送信されません。
- ただし、
channels
:send_to
で指定したテキストチャンネル(複数可)に送信します。- ただし、
${announce}
と${speak}
のラベルは1つ目のチャンネルにしか送信されません。
- ただし、
send_to
: メッセージを送信するテキストチャンネルのIDを、文字列の配列で指定します。send_to_type
がchannels
のときのみ有効です。
4-3-2. 文章の読み上げ
- 棒読みちゃんでの文章読み上げを行います。
- Discordにはメッセージを送信しません。
{
"type": "talk",
"values": []
}
type
:"talk"
を指定します。values
: 読み上げる文章を文字列の配列で指定します。- メッセージには特殊書式が使用できます。
4-3-3. 関数の実行
- JavaScriptの関数を実行します。
- 関数は
function_str
もしくはfunction_file
のどちらかで指定します。 - 関数が長い場合、
function_file
を使った方が管理が楽になります。
{
"type": "function",
"function_str": "",
"function_file": "",
"function_name": ""
}
type
:"function"
を指定します。function_str
: JavaScriptコードを文字列で指定します。エスケープを忘れないよう注意してください。関数の仕様は後述します。function_file
が指定されていた場合、function_str
は無視されます。function_file
: JavaScriptコードの記述されたファイルのパスを文字列で指定します。関数の仕様は後述します。function_name
: 関数名を文字列で指定します。function_str
もしくはfunction_file
で指定したJavaScriptコードのうち、ここで指定した関数が呼ばれます。
function function_name(obj) {
// ...
return [];
}
- 関数は、
JSScheduleArgument
型の引数1つを受け取り、ScheduledMessage[]
型の結果を返します。- 結果の
ScheduledMessage[]
すべてについて、メッセージの送信もしくは文章の読み上げが行われます。 null
を返した場合、メッセージの送信および文章の読み上げは行われません。
- 結果の
JSScheduleArgument
型、ScheduledMessage
型およびそのメンバの型についてはJavaScriptから使用可能なインターフェースを参照してください。
4-3-3-1. JavaScript関数の例
設定ファイルと関数ファイルのセットをschedules
フォルダに保存します。
- 設定ファイル
sec30.json
セクション4.2.4で例示したsec30.json
ファイルを参照してください。
- 関数ファイル
sec30_process.js
// sec30_conditionに対応する処理関数
function sec30_process(obj) {
// obj.Scheduler.AdditionalData から実行日時を取得する。
var add_data = obj.Scheduler.AdditionalData;
// 結果用変数を生成する。
var msg = new ScheduledMessage();
// 結果の本文を設定する。
if (add_data == null || add_data.length == 0) {
// 実行日時が取得できなかった場合は「エラー」を本文とする。
msg.Content = 'エラー';
} else {
// 実行日時が取得できた場合はそれを本文とする。
msg.Content = add_data;
}
// 結果用変数のクローンを作成
var msg2 = msg.Clone();
// 結果用変数をメッセージ送信として設定
msg.Type = ScheduledMessageType.SendMessage;
// クローンを文章読み上げとして設定
msg2.Type = ScheduledMessageType.Talk;
// 2つを配列で返す。
// →同じ内容で、Discordへのメッセージ送信と棒読みちゃんでの文章読み上げが両方行われる。
return [msg, msg2];
}
5. プラグインの無効化
plugins\plugins.json
をメモ帳などで開きます。Nursery.UserDefinedSchedulerPlugin.
で始まる行を削除します。- 上書き保存してメモ帳を閉じます。
- 次回の起動時から、UserDefinedSchedulerプラグインが無効になります。