Subscribed unsubscribe Subscribe Subscribe

ZNCでチャンネル情報を保存する方法を調べた

IRC

ZNCではconfigファイルにchannel情報を書いておくことで、サーバ接続時にそこに自動でjoinできたりするのだけど、その設定を(手で直接confファイルを書き換える以外に)変更する方法が分からなかった。普通にjoinしてからSaveConfigコマンドを叩いてもそれは反映されない。

結論としては以下の通り。変更をconfファイルに自動で反映してくれるmodule、chansaverが標準で入っているので、それをloadするだけ。
zncでjoinした部屋をconfigにも反映する - soh335 memo
https://github.com/znc/znc/blob/master/modules/chansaver.cpp

chansaverを見つけるまで

何故、普通にjoinした後にSaveConfigを叩いてもchannel情報が保存されないのか、を調べてみた。
ClientCommand.cpp

...
	} else if (m_pUser->IsAdmin() && sCommand.Equals("SaveConfig")) {
		if (CZNC::Get().WriteConfig()) {
			PutStatus("Wrote config to [" + CZNC::Get().GetConfigFile() + "]");
		} else {
			PutStatus("Error while trying to write config.");
		}
	} else if (...) {
...

clientからSaveConfigコマンドを叩いた場合、CZNC::Get().GetConfigFile()が呼ばれているようだ。

ここではグローバル設定が書き込まれた後、各ユーザごとの設定が書きだされる。
znc.cpp

bool CZNC::WriteConfig() {
...
	for (map<CString,CUser*>::iterator it = m_msUsers.begin(); it != m_msUsers.end(); ++it) {
		CString sErr;

		if (!it->second->IsValid(sErr)) {
			DEBUG("** Error writing config for user [" << it->first << "] [" << sErr << "]");
			continue;
		}

		pFile->Write("\n");

		if (!it->second->WriteConfig(*pFile)) {
			DEBUG("** Error writing config for user [" << it->first << "]");
		}
	}
...

で、CUser::WriteConfigで、channel情報を取得して書き込むようになっている。
User.cpp

bool CUser::WriteConfig(CFile& File) {
...
	// Chans
	for (unsigned int c = 0; c < m_vChans.size(); c++) {
		CChan* pChan = m_vChans[c];
		if (pChan->InConfig()) {
			File.Write("\n");
			if (!pChan->WriteConfig(File)) {
				return false;
			}
		}
	}
...

ここで、取得された各channelはif (pChan->InConfig())が真でないと書き込まれずにスキップされてしまう。これが、後でjoinしたchannelが保存されない理由のようだ。
ではどうすればInConfig()が真になるのか、検索してみる

$ ack SetInConfig
Chan.h
113:    void SetInConfig(bool b) { m_bInConfig = b; }

modules/admin.cpp
404:                    pChan->SetInConfig(b);

modules/chansaver.cpp
28:                             pChan->SetInConfig(true);
59:                     Channel.SetInConfig(true);
66:                     Channel.SetInConfig(false);

modules/webadmin.cpp
562:            pChan->SetInConfig(WebSock.GetParam("save").ToBool());

User.cpp
648:                    pChan->SetInConfig(pNewChan->InConfig());
659:                    pChan->SetInConfig(false);

なるほど、chansaverというモジュールがあるんだ、とココで初めて知って、これの説明を読んで、コレをLoadするだけで勝手に反映してもらえることに気づいた。