汎用プラグイン開発¶
このページでは、Sikiの通信や起動時の処理を拡張する「汎用プラグイン」の作り方を説明します。
対応バージョン
内容はSiki 0.43.6の実装を基準にしています。汎用プラグインのAPIは現在正式な互換性保証がないため、配布時は対応するSikiのバージョンを明記してください。
このページの対象
ここで扱うのは request-hook、startup、shutdown のプラグインです。掲示板サイトを追加する gpbc-plugin-*(サイトインタプリタ)は別の仕組みなので、このページの対象外です。
プラグインの仕組み¶
プラグインは、Sikiのプロファイルにある plugins フォルダの下に、プラグインごとのフォルダを作って配置します。デフォルトのプロファイルは次の場所です。
| OS | プロファイル |
|---|---|
| Windows | C:\Users\{ユーザー名}\AppData\Roaming\siki\profile |
| macOS | /Users/{ユーザー名}/Library/Application Support/siki/profile |
| Linux | /home/{ユーザー名}/.config/siki/profile |
プラグインの場所を変更している場合は、設定の「Plugin Directory」を確認してください。
plugins/
└─ hello-plugin/
├─ package.json
└─ index.js
最小の構成¶
通常は package.json の main で指定したJavaScriptファイルが読み込まれます。
{
"name": "hello-plugin",
"version": "1.0.0",
"description": "Siki用のサンプルプラグイン",
"main": "index.js"
}
module.exports.type = 'startup'
module.exports.meta = {
name: 'hello-plugin',
description: '起動時に一度だけ実行するサンプル',
version: '1.0.0',
needVersion: '0.43.6'
}
module.exports.mainScript = async (settings, tools) => {
tools.emitter.emit('plugin:hello-plugin:ready')
}
プラグインを配置したら、設定のプラグイン一覧で有効にしてSikiを再起動します。プラグインのコードや package.json を変更した場合も、まず再起動して読み込み直してください。
フォルダ名、package.json の name、meta.name は同じ名前にすることを推奨します。表示名と有効化判定に使われる名前が異なると、設定画面で有効状態を正しく表示できない場合があります。
プラグインの種類¶
type |
実行される処理 | 主な用途 |
|---|---|---|
request-hook |
beforeRequest、afterRequest |
通信のURL・ヘッダー・本文の変更、通信結果の保存や補正 |
startup |
mainScript |
起動時の初期化、イベント購読、外部サービスの準備 |
shutdown |
mainScript |
Siki終了時の保存や後片付け |
meta¶
モジュールの meta は、設定画面やログに表示する情報です。
| プロパティ | 内容 |
|---|---|
name |
プラグイン名。フォルダ名と一致させることを推奨 |
description |
設定画面に表示する説明 |
version |
プラグインのバージョン |
needVersion |
動作確認したSikiの最低バージョン。互換性チェックを自動で行う値ではありません |
type はモジュールのトップレベルに指定します。
module.exports.type = 'request-hook'
module.exports.meta = {
name: 'example-hook',
description: '通信を補正する例',
version: '1.0.0',
needVersion: '0.43.6'
}
request-hook¶
beforeRequest¶
通信を送信する前に呼び出されます。変更したい値を返してください。返さない場合は元の通信内容が使われます。
module.exports.beforeRequest = async (tools, url, method, headers, payload, query) => {
if (url.includes('example.com')) {
headers['user-agent'] = 'my-siki-plugin/1.0'
return { url, method, headers, payload }
}
}
| 引数 | 内容 |
|---|---|
tools |
プラグイン用の補助オブジェクト |
url |
リクエストURL |
method |
GET、HEAD、POST、PUT、DELETE |
headers |
リクエストヘッダー。キーは小文字 |
payload |
パーセントエンコード済みの本文 |
query |
URLクエリ。エンコード前の値 |
戻り値には url、method、headers、payload のうち変更したものだけを含められます。
afterRequest¶
通信が完了した後に呼び出されます。レスポンスの本文やステータスを補正できます。
module.exports.afterRequest = async (tools, url, statusCode, response_headers, response_body) => {
if (url.endsWith('/subject.txt')) {
response_body = response_body.replaceAll('古い表記', '新しい表記')
}
return { statusCode, response_headers, response_body }
}
| 引数 | 内容 |
|---|---|
tools |
プラグイン用の補助オブジェクト |
url |
リクエストに使ったURL |
statusCode |
HTTPステータスコード |
response_headers |
レスポンスヘッダー。キーは小文字 |
response_body |
Unicode文字列に変換済みのレスポンス本文 |
戻り値には statusCode、response_headers、response_body を指定できます。複数のフックを有効にしている場合は、有効化された順に実行され、前のフックの変更結果が次のフックへ渡されます。
request-hook のツール¶
beforeRequest と afterRequest の第1引数に渡されます。
| プロパティ | 内容 |
|---|---|
conf |
request_hook_conf に保存する設定。get、set、delete が使えます |
simplefetch |
Sikiの通信処理を使って別のURLを取得する関数 |
log |
error、warn、info、verbose、debug のログ関数 |
siki_values |
workspaceid、user_dir、log_dir、plugin_dir などの値 |
get_res |
URLからSikiのスレッドデータを取得する非同期関数 |
設定キーにはプラグイン名を含め、他のプラグインと衝突しない名前を使ってください。
const key = 'example-hook.lastValue'
const previous = tools.conf.get(key)
tools.conf.set(key, 'saved value')
通信フックはワークスペース単位で無効化できる場合があります。対象ワークスペースでフックが無効になっていると、関数は呼ばれません。
startup¶
mainScript(settings, tools) はSiki起動時に一度だけ実行されます。
module.exports.type = 'startup'
module.exports.meta = {
name: 'startup-example',
description: '起動時のイベントを監視する例',
version: '1.0.0'
}
module.exports.mainScript = async (settings, tools) => {
const { config, userSettings } = settings
tools.emitter.on('ThreadFetchSuccess', (urlObject) => {
console.log('thread fetched', urlObject.location)
})
}
settings¶
| プロパティ | 内容 |
|---|---|
config |
Sikiのシステム設定。config.js 相当 |
userSettings |
ユーザー設定。user.js 相当 |
startup のツール¶
| プロパティ | 内容 |
|---|---|
emitter |
Siki内部イベントを購読・発火するイベントエミッター |
syncplay |
Syncplay機能のインスタンス |
iconv |
文字コード変換ライブラリ |
イベント名やイベントデータは内部実装に依存します。利用するイベントは、対応するSikiバージョンで確認してください。
shutdown¶
shutdown はSikiの終了処理で mainScript(settings) が一度だけ呼ばれます。設定の保存や一時ファイルの後片付けに利用できます。
module.exports.type = 'shutdown'
module.exports.meta = {
name: 'shutdown-example',
description: '終了時に処理する例',
version: '1.0.0'
}
module.exports.mainScript = async (settings) => {
// 終了前に必要な保存処理を行う
}
終了処理は短時間で完了するようにし、失敗してもSikiの終了を妨げない設計にしてください。
エラーとデバッグ¶
package.jsonのversionまたはmainがないと、通常のプラグインとして読み込まれません。- モジュールの読み込みに失敗した場合は、Sikiのログにプラグイン名とエラー内容が記録されます。
startup、shutdown、通信フックで発生した例外はSiki側で捕捉され、ログに記録されます。- 通信フックで例外が発生した場合は、Siki側で捕捉してログに記録し、処理を継続します。フック内で途中まで値を書き換えていた場合の結果は保証されません。
- 変更後に反映されない場合は、フォルダ名、有効化状態、
package.jsonのmain、構文エラー、Sikiの再起動を順に確認してください。
プラグインはNode.jsの機能を利用できるため、外部から入手したプラグインは内容を確認してから有効にしてください。特に、認証情報、Cookie、通信本文、プロファイル内のファイルを扱うプラグインには注意が必要です。
配布時の確認項目¶
- 対応するSikiのバージョンを
needVersionとREADMEに記載する package.jsonのname、version、mainを確認する- プラグインフォルダをそのままZIPにする
- 必要な依存パッケージとライセンスを明記する
- 認証情報や個人のプロファイルファイルをZIPに含めない
- エラー時にSikiを停止させない
現在の配布プラグイン一覧はプラグインを参照してください。