1
0
mirror of https://github.com/irssi/irssi.git synced 2024-06-09 06:20:45 +00:00

Merge tag '0.8.18'

master now on 0.8.19-head
This commit is contained in:
ailin-nemui 2016-02-29 22:45:54 +01:00
commit 9174ec584f
7 changed files with 772 additions and 1953 deletions

6
NEWS
View File

@ -1,4 +1,10 @@
v0.8.18-head 2016-xx-xx The Irssi team <staff@irssi.org>
* Removed --disable-ipv6
+ irssiproxy can now forward all tags through a single port.
+ send channel -botcmds immediately when no mask is specified (#175).
- Correctly store te layout of SAFE channels (#183).
v0.8.18 2016-02-13 The Irssi team <staff@irssi.org>
* Modules will now require to define a
void MODULENAME ## _abicheck(int *version)
method to ensure that they are compiled against the correct Irssi

View File

@ -32,7 +32,7 @@ cat docs/help/Makefile.am.gen|sed "s/@HELPFILES@/$files/g"|sed 's/?/\\?/g'|tr '!
# .html -> .txt with lynx or elinks
echo "Documentation: html -> txt..."
if type lynx >/dev/null 2>&1 ; then
LC_ALL=C lynx -dump docs/faq.html|perl -pe 's/^ *//; if ($_ eq "\n" && $state eq "Q") { $_ = ""; } elsif (/^([QA]):/) { $state = $1 } elsif ($_ ne "\n") { $_ = " $_"; };' > docs/faq.txt
LC_ALL=en_IE.utf8 lynx -dump docs/faq.html|perl -pe 's/^ *//; if ($_ eq "\n" && $state eq "Q") { $_ = ""; } elsif (/^([QA]):/) { $state = $1 } elsif ($_ ne "\n") { $_ = " $_"; };' > docs/faq.txt
elif type elinks >/dev/null 2>&1 ; then
elinks -dump docs/faq.html|perl -pe 's/^ *//; if ($_ eq "\n" && $state eq "Q") { $_ = ""; } elsif (/^([QA]):/) { $state = $1 } elsif ($_ ne "\n") { $_ = " $_"; };' > docs/faq.txt
elif type links >/dev/null 2>&1 ; then

View File

@ -1,4 +1,4 @@
AC_INIT(irssi, 0.8.18-head)
AC_INIT(irssi, 0.8.19-head)
AC_CONFIG_SRCDIR([src])
AC_CONFIG_AUX_DIR(build-aux)
AC_PREREQ(2.50)

View File

@ -1,152 +1,80 @@
<h2>FAQ</h2>
<h1>Frequently Asked Questions</h1>
<h3 id="q-why-doesnt-irssi-display-colors-even-when-ircii-etc-displays-them">Q: Why doesnt irssi display colors even when ircii etc. displays them?</h3>
<h3>Q: Why doesn't irssi display colors even when ircii etc. displays them?</h3>
<p>A: They force ANSI colors even if terminal doesnt support them. By default, irssi uses colors only if terminfo/termcap so says. The correct way to fix this would be to change your TERM environment to a value where colors work, like xterm-color or color_xterm (eg. <code>TERM=xterm-color irssi</code>). If this doesnt help, then use the evil way of <code>/SET term_force_colors ON</code>.</p>
<p>A: They force ANSI colors even if terminal doesn't support them. By
default, irssi uses colors only if terminfo/termcap so says. The correct
way to fix this would be to change your TERM environment to a value where
colors work, like xterm-color or color_xterm (eg. <code>TERM=xterm-color
irssi</code>). If this doesn't help, then use the evil way of <code>/SET
term_force_colors ON</code>.</p>
<h3>Q: How do I easily write text to channel that starts with '/' character?</h3>
<h3 id="q-how-do-i-easily-write-text-to-channel-that-starts-with--character">Q: How do I easily write text to channel that starts with / character?</h3>
<p>A: <code>/ /text</code></p>
<h3 id="q-why-doesnt-irssi-update-my-realname-or-whatever-after-i-change-it-with-set-realname-and-reconnect-with-reconnect-or-server">Q: Why doesnt irssi update my realname (or whatever) after I change it with <code>/SET realname</code> and reconnect with <code>/RECONNECT</code> or <code>/SERVER</code>?</h3>
<h3>Q: Why doesn't irssi update my realname (or whatever) after I change it
with <code>/SET realname</code> and reconnect with <code>/RECONNECT</code>
or <code>/SERVER</code>?</h3>
<p>A: Irssi is trying to be too smart. This will be fixed in future, but for now you should use <code>/DISCONNECT</code> and <code>/CONNECT</code>.</p>
<p>A: Irssi is trying to be too smart. This will be fixed in future, but for
now you should use <code>/DISCONNECT</code> and <code>/CONNECT</code>.</p>
<h3 id="q-i-connected-to-some-server-which-isnt-responding-but-now-irssi-tries-to-connect-back-to-it-all-the-time-how-can-i-stop-it">Q: I connected to some server which isnt responding but now irssi tries to connect back to it all the time! How can I stop it?</h3>
<p>A: Two ways. The “good way” to do it is with <code>/DISCONNECT</code>. Check the server tags first with <code>/SERVER</code> without giving it any parameters, reconnections are those that have tag starting with “recon” text. So most probably youre going to do <code>/DISCONNECT recon-1</code>. The other way is to remove all the reconnections with <code>/RMRECONNS</code>, easier but may remove some connections you actually wanted to reconnect (if you used multiple servers..).</p>
<h3>Q: I connected to some server which isn't responding but now irssi tries
to connect back to it all the time! How can I stop it?</h3>
<h3 id="q-how-do-i-add-seconds-to-timestamp">Q: How do I add seconds to timestamp?</h3>
<p>A: Two ways. The "good way" to do it is with <code>/DISCONNECT</code>.
Check the server tags first with <code>/SERVER</code> without giving it any
parameters, reconnections are those that have tag starting with "recon"
text. So most probably you're going to do <code>/DISCONNECT recon-1</code>.
The other way is to remove all the reconnections with
<code>/RMRECONNS</code>, easier but may remove some connections you actually
wanted to reconnect (if you used multiple servers..).</p>
<p>A: <code>/FORMAT timestamp {timestamp %%H:%%M:%%S}</code> - and remember to add the trailing space :)</p>
<h3 id="q-why-does-irssi-say-irssi-channel-not-fully-synchronized-yet-try-again-after-a-while-when-i-try-to-use-ban-etc">Q: Why does irssi say “Irssi: Channel not fully synchronized yet, try again after a while” when I try to use /BAN etc?</h3>
<h3>Q: How do I add seconds to timestamp?</h3>
<p>A: Possibly a bug in irssi, or ircd youre using does something that irssi didnt really notice. The new code should make this happen far less often than before, but one known reason for this is when irssi doesnt notice that you were unable to join some channel. Currently however I dont know of any such events irssi doesnt know about.</p>
<p>A: <code>/FORMAT timestamp {timestamp %%H:%%M:%%S}</code> - and remember
to add the trailing space :)</p>
<h3>Q: Why does irssi say "Irssi: Channel not fully synchronized yet, try
again after a while" when I try to use /BAN etc?</h3>
<p>A: Possibly a bug in irssi, or ircd you're using does something that
irssi didn't really notice. The new code should make this happen far less
often than before, but one known reason for this is when irssi doesn't
notice that you were unable to join some channel. Currently however I don't
know of any such events irssi doesn't know about.</p>
<p>Anyway, if this does happen, do <code>/RAWLOG SAVE ~/rawlog</code> soon
after joining to channel, and either try to figure out yourself why irssi
didn't get reply to WHO request, or send the whole log to cras@irssi.org. Note
that the rawlog is by default only 200 lines and it may not be enough to
show all needed information, so you might want to do <code>/SET rawlog_lines
1000</code> or so.</p>
<p>Anyway, if this does happen, do <code>/RAWLOG SAVE ~/rawlog</code> soon after joining to channel, and either try to figure out yourself why irssi didnt get reply to WHO request, or open a Github issue with the full log included. Note that the rawlog is by default only 200 lines and it may not be enough to show all needed information, so you might want to do <code>/SET rawlog_lines 1000</code> or so.</p>
<p><code>MODE +b</code> still works fine though.</p>
<h3 id="q-wheres-the-gui-version">Q: Wheres the GUI version?</h3>
<h3>Q: Where's the GUI version?</h3>
<p>A: There was one on <a href="https://github.com/irssi-import/xirssi">irssi-import/xirssi</a> but it has not been maintained for a long time.</p>
<p>A: Read
<a href="http://www.irssi.org/about">http://www.irssi.org/about</a></p>
<h3 id="q-how-do-i-autorejoin-channels-after-being-kicked">Q: How do I autorejoin channels after being kicked?</h3>
<p>A: Thats evil and you shouldnt do it. If you get kicked, you should stay out, at least until the channel forgot you existed :) Most channels Ive joined just ban you if you autorejoin after kick. If youre joined to channels who kick people for fun, try changing channels or something.</p>
<h3>Q: How do I autorejoin channels after being kicked?</h3>
<p>Anyway, if you REALLY want to do that, and you understand that youre doing evilness, you can use the autorejoin.pl script that comes with irssi. Youll still need to specify the channels you wish to rejoin with <code>/SET autorejoin_channels #chan1 #chan2 ...</code></p>
<p>A: That's evil and you shouldn't do it. If you get kicked, you should stay
out, at least until the channel forgot you existed :) Most channels I've
joined just ban you if you autorejoin after kick. If you're joined to
channels who kick people for fun, try changing channels or something.</p>
<h3 id="q-how-do-i-announce-that-im-awayback-in-all-channels-ive-joined-or-how-do-i-change-my-nick-when-setting-myself-awayback">Q: How do I announce that Im away/back in all channels Ive joined? Or how do I change my nick when setting myself away/back?</h3>
<p>Anyway, if you REALLY want to do that, and you understand that you're doing
evilness, you can use the autorejoin.pl script that comes with irssi. You'll
still need to specify the channels you wish to rejoin with <code>/SET
autorejoin_channels #chan1 #chan2 ...</code></p>
<p>A: Thats even worse than autorejoin. Who could possibly care every time you come and go? Many channels will kick you for using this, and I for example have added several ignores so Id never need to see these messages. Learn to use <code>/AWAY</code> command properly and tell its existence to people who dont know about it. <code>/WII yournick</code> shows your away reason much better for people who actually want to know if youre there or not.</p>
<h3 id="q-why-does-irssi-autojoin-on-invite-by-default">Q: Why does irssi autojoin on invite by default?</h3>
<h3>Q: How do I announce that I'm away/back in all channels I've joined? Or
how do I change my nick when setting myself away/back?</h3>
<p>A: The setting is /SET join_auto_chans_on_invite - its not the same as regular autojoin-on-invite, which irssi doesnt even have. The only channels that are joined on invite, are the ones youve added to config with /CHANNEL ADD -auto. This is very useful with +i channels when you need to first send an invite request to bot, or if you get accidentally kicked from channel, the kicker can invite you back immediately.</p>
<p>A: That's even worse than autorejoin. Who could possibly care every time
you come and go? Many channels will kick you for using this, and I for example
have added several ignores so I'd never need to see these messages. Learn to
use <code>/AWAY</code> command properly and tell its existence to people
who don't know about it. <code>/WII yournick</code> shows your away reason
much better for people who actually want to know if you're there or not.</p>
<p>I dont see any bad side effects with this feature, so its ON by default. I guess someone could start kicking/inviting you all the time but server connection shouldnt drop because of that, and you shouldnt join channels whose operators are that evil.</p>
<h3 id="q-how-to-make-utf-8-support-work-with-irssi">Q: How to make UTF-8 support work with irssi?</h3>
<h3>Q: Why does irssi autojoin on invite by default?</h3>
<p>A: Make sure your terminal supports UTF-8 (for example, <code>xterm -u8</code>). If you use screen, you may have to do <code>screen -U</code>. And in Irssi do <code>/SET term_charset utf-8</code>. (for 0.8.9 and older: <code>/SET term_type utf-8</code>)</p>
<p>A: The setting is /SET join_auto_chans_on_invite - it's not the same
as regular autojoin-on-invite, which irssi doesn't even have. The only
channels that are joined on invite, are the ones you've added to config
with /CHANNEL ADD -auto. This is very useful with +i channels when you
need to first send an invite request to bot, or if you get accidentally
kicked from channel, the kicker can invite you back immediately.</p>
<h3 id="q-will-there-be-detach-like-feature">Q: Will there be /DETACH-like feature?</h3>
<p>I don't see any bad side effects with this feature, so it's ON by
default. I guess someone could start kicking/inviting you all the time
but server connection shouldn't drop because of that, and you shouldn't
join channels whose operators are that evil.</p>
<p>A: <a href="http://tmux.github.io/">tmux</a>, <a href="http://www.gnu.org/software/screen/screen.html">screen</a> and <a href="http://dtach.sf.net/">dtach</a> can be used to do it just fine.</p>
<h3 id="q-how-do-i-run-scripts-automatically-at-startup">Q: How do I run scripts automatically at startup?</h3>
<h3>Q: How to make UTF-8 support work with irssi?</h3>
<p>A: Put them into <code>~/.irssi/scripts/autorun/</code> directory. Or better would be if you placed them in <code>~/.irssi/scripts/</code> and created symlinks to autorun directory (eg. <code>cd ~/.irssi/scripts/autorun/ ; ln -s ../script.pl .</code>)</p>
<p>A: Make sure your terminal supports UTF-8 (for example, <code>xterm -u8</code>).
If you use screen, you may have to do <code>screen -U</code>. And in Irssi do
<code>/SET term_charset utf-8</code>. (for 0.8.9 and older: <code>/SET term_type utf-8</code>)</p>
<h3 id="q-how-do-i-execute-commands-automatically-at-startup">Q: How do I execute commands automatically at startup?</h3>
<p>A: Put them into <code>~/.irssi/startup</code> file, each command on its own line. The preceding slash (/) is not necessary.</p>
<h3>Q: Will there be /DETACH-like feature?</h3>
<h3 id="q-how-do-i-easily-edit-existing-topic">Q: How do I easily edit existing topic?</h3>
<p>A: Maybe. Detach code already is there, attach is just missing :) But I
don't have much interest in coding it,
<a href="http://www.gnu.org/software/screen/screen.html">screen</a> and
<a href="http://dtach.sf.net/">dtach</a> can be used to do it just fine.</p>
<p>A: <code>/TOPIC &lt;tab&gt;</code></p>
<h3 id="q-how-can-i-have-whois-replies-to-active-window">Q: How can I have /WHOIS replies to active window?</h3>
<h3>Q: How do I run scripts automatically at startup?</h3>
<p>A: You can disable the status window, or do <code>/WINDOW LEVEL -CRAP</code> in it which would also make several other messages show up in active window. You can also use a <a href="http://dgl.cx/irssi/hack-whois-in-current-window.pl">script</a>.</p>
<p>A: Put them into <code>~/.irssi/scripts/autorun/</code> directory. Or
better would be if you placed them in <code>~/.irssi/scripts/</code> and
created symlinks to autorun directory (eg. <code>cd
~/.irssi/scripts/autorun/ ; ln -s ../script.pl .</code>)</p>
<h3 id="q-how-do-i-add-the-active-network-to-the-statusbar">Q: How do I add the active network to the statusbar</h3>
<p>A: Modify the window-line in statusbar section in config file to <code>window = "{sb $winref:$tag/$T{sbmode $M}}";</code></p>
<h3>Q: How do I execute commands automatically at startup?</h3>
<p>A: Put them into <code>~/.irssi/startup</code> file, each command on its
own line. The preceding slash (/) is not necessary.</p>
<h3>Q: How do I easily edit existing topic?</h3>
<p>A: /TOPIC &lt;tab&gt;</p>
<h3>Q: How can I have /WHOIS replies to active window?</h3>
<p>A: You can disable the status window, or do <code>/WINDOW LEVEL
-CRAP</code> in it which would also make several other messages show up in
active window. You can also use a
<a href="http://dgl.cx/irssi/hack-whois-in-current-window.pl">script</a>.</p>
<h3>Q: How do I add the active network to the statusbar</h3>
<p>A: Modify the window-line in statusbar section in config file to
<code>window = "{sb $winref:$tag/$T{sbmode $M}}";</code></p>
<h3 id="q-how-to-pronounce-irssi">Q: How to pronounce Irssi?</h3>
<p>A: Check <a href="https://irssi.org/assets/irssi.wav">here</a></p>

View File

@ -1,846 +0,0 @@
<h2>Startup HOWTO</h2>
<h3>Новичкам в Irssi (а не IRC ..)</h3>
<p>&copy; 2000-2002 by Timo Sirainen, распространяется под лицензией
<a href="http://www.gnu.org/licenses/fdl.html">GNU FDL</a> 1.1.<br/>
На русский язык переведено NiXoiD'ом (#xakep @ irc.wenet.ru)
</p>
<p>Оглавление с некоторыми вопросами из FAQ, на которые дается ответ в параграфах:</p>
<ol>
<li><a href="#c1">Для ленивых</a>
<ul>
<li>Управление окнами, аналогичное ircII</li>
</ul></li>
<li><a href="#c2">Основы пользовательского интерфейса</a>
<ul>
<li>Работа с "разделенными" окнами (я так перевёл "split windows")</li>
<li>Как я могу легко переключаться между окнами?</li>
<li>Но alt-1 и.т.д. не работает!</li>
</ul></li>
<li><a href="#c3">Автозаход на каналы и серверы</a>
<ul>
<li>Как автоматически подключаться к серверам при запуске?</li>
<li>Как автоматически заходить на каналы?</li>
<li>Как автоматически выполнять команды при подключении?</li>
</ul></li>
<li><a href="#c4">Настройка окон и автоматическое восстановление их при запуске</a></li>
<li><a href="#c5">Окна status и msgs &amp; уровни сообщений</a>
<ul>
<li>Я хочу чтобы ответ на /WHOIS выводился в текущее окно</li>
<li>Я хочу чтобы все сообщения выводились в одном окне</li>
</ul></li>
<li><a href="#c6">Как в irssi работает многосерверная поддержка</a>
<ul>
<li>Я подключился к серверу, который не отвечает и теперь irssi пытается подключиться к нему снова и снова. Как мне остановить это??</li>
<li>Я хочу отдельное окно статуса и сообщений для каждого сервера</li>
</ul></li>
<li><a href="#c7">Команда /LASTLOG и прокрутка окон</a>
<ul>
<li>Как сохранить весь текст из окна в файл?</li>
</ul></li>
<li><a href="#c8">Ведение логов</a></li>
<li><a href="#c9">Изменение клавиатурных Сочетаний</a>
<ul>
<li>Как я могу заставить F1 делать что-то?</li>
</ul></li>
<li><a href="#c10">Прокси и боунсеры</a>
<ul>
<li>Что такое irssi-proxy?</li>
</ul></li>
<li><a href="#c11">Настройки Irssi</a></li>
<li><a href="#c12">Статусбар</a>
<ul>
<li>Я загрузил скрипт для статусбара, но его нигде не видно!</li>
</ul></li>
</ol>
<h3><a id="c1">1. Для ленивых</a></h3>
<p>Несколько полезных настроек по умолчанию:</p>
<p>Если не работают цвета и вы не собираетесь использовать VT-несовместимый терминал, то просто введите:</p>
<pre>
/SET term_force_colors ON
</pre>
<p>Если вы хотите чтобы все сообщения выводились в одном окне:</p>
<pre>
/SET autocreate_own_query OFF
/SET autocreate_query_level DCCMSGS
/SET use_status_window OFF
/SET use_msgs_window ON
</pre>
<p>Чтобы окна автоматически не закрывались когда вы покидаете канал(<code>/PART</code>)или приват
(<code>/UNQUERY</code>):</p>
<pre>
/SET autoclose_windows OFF
/SET reuse_unused_windows ON
</pre>
<p>Чтобы управление окнами в irssi было похоже на ircII введите эти команды:</p>
<pre>
/SET autocreate_own_query OFF
/SET autocreate_query_level NONE
/SET use_status_window OFF
/SET use_msgs_window OFF
/SET reuse_unused_windows ON
/SET windows_auto_renumber OFF
/SET autostick_split_windows OFF
/SET autoclose_windows OFF
/SET print_active_channel ON
</pre>
<p>Вот пример добавления серверов:</p>
<p>(сеть OFTC, идентифицироваться через nickserv и ждать 2 секунды перед заходом на каналы)</p>
<pre>
/IRCNET ADD -autosendcmd "/^msg nickserv identify pass;wait 2000" OFTC
</pre>
<p>Теперь добавление нескольких серверов к разным сетям (IRC-сеть для них уже установлена),
irc.kpnqwest.fi используется по дефолту для IRCNet но если он не доступен, то irssi будет пытаться подключиться к
irc.funet.fi:</p>
<pre>
/SERVER ADD -auto -ircnet ircnet irc.kpnqwest.fi 6667
/SERVER ADD -ircnet ircnet irc.funet.fi 6667
/SERVER ADD -auto -ircnet efnet efnet.cs.hut.fi 6667
</pre>
<p>Автозаход на каналы при подключении к серверу и оп-запрос бота при заходе на efnet/#irssi:</p>
<pre>
/CHANNEL ADD -auto #irssi ircnet
/CHANNEL ADD -auto -bots *!*bot@host.org -botcmd "/^msg $0 op pass" #irssi efnet
</pre>
Чтобы строки, содержащие Ваш ник подсвечивались:
<pre>
/HILIGHT ваш_ник
</pre>
<h3><a id="c2">2. Основы пользовательского интерфейса</a></h3>
<p>Для скроллинга содержимого окон используйте PgUp и PgDown. Если они не работают, используйте кнопки Meta-p и Meta-n.
Чтобы перескочить в начало или конец буфера используйте команды <code>/SB HOME</code> и <code>/SB END</code>.</p>
<p>По умолчанию irssi использует для всего "скрытые окна". Скрытое окно создается каждый раз когда вы заходите(<code>/JOIN</code>) на канал или создаете приват(<code>/QUERY</code>)
с кем-то. Есть несколько способов переключения между этими окнами:</p>
<pre>
Meta-1, Meta-2, .. Meta-0 - Переключение между окнами 1-10
Meta-q .. Meta-o - Переключение между окнами 11-19
/WINDOW &lt;номер&gt; - Переключение на окно с заданным номером
Ctrl-P, Ctrl-N - Переключение к предыдущему/следующему окну
</pre>
<p>Простейший способ переключения - это Meta-номер. Что такое Meta?
Для некоторых терминалов это ALT. Если у вас windows-совместимая клавиатура, то это так-же может быть левая кнопка windows. Если они не работают, то вам придется настроить некоторые X-ресурсы
(это работает как в xterm так и в rxvt):</p>
<pre>
XTerm*eightBitInput: false
XTerm*metaSendsEscape: true
</pre>
<p>В rxvt вы так-же можете указать какая кнопка соответствует кнопке meta, так что если вы хотите использовать Alt вместо Win допишите это в файл с ресурсами:</p>
<pre>
rxvt*modifier: alt
</pre>
<p>Вы так-же можете сделать это при помощи xmodmap:</p>
<pre>
xmodmap -e "keysym Alt_L = Meta_L Alt_L"
</pre>
<p>Так как-же установить эти X-ресурсы? Для Debian'а, это файл
<code>/etc/X11/Xresources/xterm</code>, в который вы можете их засунуть и они будут автоматически читаться при старте иксов. Файлы <code>~/.Xresources</code> и
<code>~/.Xdefaults</code> так-же должны работать. Если ничего из вышеперечисленного не работает, то просто скопируйте их в <code>~/.Xresources</code>
и загрузите командой <code>xrdb -merge ~/.Xresources</code>.
Изменения начинают действовать только в заново запущенном терминале.</p>
<p>Многие SSH клиенты под Windows так же не разрешают использовать кнопку ALT. Прекрасный клиент, который позволяет делать это - putty, вы можете скачать его с
<a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/">
http://www.chiark.greenend.org.uk/~sgtatham/putty/</a>.</p>
<p>Так-же поддерживает разделение окон. Вот команды, которые позволяют это сделать:</p>
<pre>
/WINDOW NEW - Создать новое разделенное окно
/WINDOW NEW HIDE - Создать новое скрытое окно
/WINDOW CLOSE - Закрыть разделенное или скрытое окно
/WINDOW HIDE [&lt;number&gt;|&lt;name&gt;] - Сделать разделенное окно скрытым
/WINDOW SHOW &lt;number&gt;|&lt;name&gt; - Сделать скрытое окно разделенным
/WINDOW SHRINK [&lt;lines&gt;] - Уменьшить активное окно
/WINDOW GROW [&lt;lines&gt;] - Увеличить активное окно
/WINDOW BALANCE - Сбалансировать размеры всех разделенных окон
</pre>
<p>По умолчанию Irssi использует "приклеивание окон". Это подразумевает, что окно, созданное внутри разделенного окна не может быть перемещено без некоторого гемора :). Например у вас может быть следующее расположение окон:</p>
<pre>
Split window 1: win#1 - Status window, win#2 - Окно сообщений
Split window 2: win#3 - ircnet/#channel1, win#4 - ircnet/#channel2
Split window 3: win#5 - efnet/#channel1, win#6 - efnet/#channel2
</pre>
<p>Когда вы в окне win#1 нажимаете ALT-6, irssi переключается на разделенное окно
#3 и перемещает канал efnet/#channel2 в активное окно.</p>
<p>При "незакреплённом" варианте окна не имеют никакой связи с разделенными окнами
и нажатие ALT-6 в окне win#1 перемещает окно win#6 в разделенное окно 1
и делает его активным, исключение может быть когда окно win#6 уже видимо в каком-то другом
разделенном окне, irssi просто переключается к этому разделенному окну. Такой метод переключения между окнами применяется в ircII и если он вам понравился то вы можете активизировать его при помощи команды</p>
<pre>
/SET autostick_split_windows OFF
</pre>
<p>Каждое окно внутри себя может содержать много каналов, приватов и других "вещей". Если вы вообще не любите окна, то вы можете отменить их командой</p>
<pre>
/SET autocreate_windows OFF [format c: надёжнее ;) - прим. перев.]
</pre>
<p>И если вы держите все каналы в одном окне, то вам наверное захочется чтобы имя канала выводилось в каждом сообщении:</p>
<pre>
/SET print_active_channel ON
</pre>
<p>Если вы хотите сгруппировать в какое-то окно только некоторые каналы или приваты, то используйте эти команды:</p>
<pre>
/JOIN -window #channel
/QUERY -window nick
</pre>
<h3><a id="c3">3. Автозаход на каналы и серверы</a></h3>
<p>В Irssi многосерверная поддержка ИМХО очень хорошая :). Даже если вы хотите общаться только в одной сети, то очень удобно сгруппировать все серверы этой сети в одну группу т.к. это помогает в случае невозможности соединения с главным сервером и в некоторых других случаях :).
Дополнительную информацию об эффективном использовании многосерверной поддержки смотрите в главе 6.</p>
<p>Для начала вам нужно установить свою IRC-сеть, для этого используйте команду <code>/IRCNET</code>,
чтобы убедится, что она ещё не установлена. Если она не установлена, то введите <code>/IRCNET ADD
имя_сети</code>. Если вы хотите, чтобы какие-то команды автоматически выполнялись при подключении к этой сети, то воспользуйтесь опцией <code>-autosendcmd</code>.
Вот некоторые примеры:</p>
<pre>
/IRCNET ADD -autosendcmd '^msg bot invite' ircnet
/IRCNET ADD -autosendcmd "/^msg nickserv identify pass;wait 2000" OFTC
</pre>
<p>После этого вы должны добавить к этой сети серверы. Например:</p>
<pre>
/SERVER ADD -auto -ircnet ircnet irc.kpnqwest.fi 6667
/SERVER ADD -auto -ircnet worknet irc.mycompany.com 6667 пароль
</pre>
<p>Опция <code>-auto</code> указывает, что к этому серверу нужно автоматически подключаться при запуске.
Вы не должны помечать другие серверы той-же сети опцией <code>-auto</code> - Irssi автоматически к ним подключится, если сервер помеченный <code>-auto</code> недоступен.</p>
<p>И наконец каналы:</p>
<pre>
/CHANNEL ADD -auto -bots *!*bot@host.org -botcmd "/^msg $0 op pass" #irssi efnet
/CHANNEL ADD -auto #secret ircnet password
</pre>
<p>Опции <code>-bots</code> и <code>-botcmd</code> требуют небольшого пояснения.
Они используются для того, чтобы автоматически давать команды боту при заходе на канал,
обычно для автоматического получения опа. Вы можете задать много масок ботов при помощи опции
<code>-bots</code>, разделенной пробелами (не забудьте взять эту строку в кавычек). Переменная $0 в опции
<code>-botcmd</code> указывает на первого бота в списке найденных. Если вы не хотите использовать маски для ботов (например если бот всегда сидит под одним ником)
вы можете указать только опцию <code>-botcmd</code> и команду.</p>
<h3><a id="c4">4. Настройка окон и автоматическое восстановление при запуске</a></h3>
<p>Для начала создайте нужные окна(подключитесь к нужным серверам, каналам и.т.д.).
Для перемещения окон используйте следующие команды:</p>
<pre>
/WINDOW MOVE LEFT/RIGHT/номер - переместить окно влево, вправо или на указанный номер
/WINDOW ITEM MOVE &lt;номер&gt;|&lt;имя&gt; - переместить канал или приват в другое окно
</pre>
<p>Когда всё выглядит так, как вы хотите, используйте команду <code>/LAYOUT SAVE</code>
<code>/SAVE</code>, если не включено автосохранение) и когда вы в следующий раз запустите irssi, то он вспомнит позиции сохраненных окон.
Это "запоминание" не означает, что использование команды <code>/LAYOUT SAVE</code> будет приводить к автоматическому подключению к серверам и заходу на каналы,
для этого вы должны использовать команды <code>/SERVER ADD -auto</code> и <code>/CHANNEL ADD -auto</code>.</p>
<p>Чтобы изменить сохраненные настройки окон, расставьте их в нужные позиции и заново введите команду <code>/LAYOUT SAVE</code>.
Чтобы обнулить настройки используйте команду <code>/LAYOUT RESET.</code></p>
<h3><a id="c5">5. Окна status и msgs &amp; уровни сообщений</a></h3>
<p>По умолчанию "дополнительные сообщения" выводятся в окно статуса. Под дополнительными подразумеваются сообщения, которые не принадлежат ни к одному каналу или привату(например ctcp-запросы).
Некоторых людей они раздражают, так что если вы хотите их скрыть, то введите</p>
<pre>
/SET use_status_window OFF
</pre>
<p>Этот параметр заработает только после перезапуска irssi. Если вы хотите удалить их немедленно, то просто закройте окно(<code>/WINDOW CLOSE</code>).</p>
<p>Другое основное окно - это "окно сообщений", куда идут все сообщения привата.
По умолчанию оно отключено и вместо этого для каждого привата создается новое окно. Чтобы все сообщения привата шли в одно окно используйте команду:</p>
<pre>
/SET use_msgs_window ON
/SET autocreate_query_level DCCMSGS (или если вы так-же не хотите
создавать новые окна для DCC-чата напишите NONE)
</pre>
<p>Этот параметр так-же не будет задействован до перезапуска irssi. Чтобы применить его немедленно введите:</p>
<pre>
/WINDOW NEW HIDE - создать окно
/WINDOW NAME (msgs) - переименовать его в "(msgs)"
/WINDOW LEVEL MSGS - перенаправить все приватные сообщения в это окно
/WINDOW MOVE 1 - сделать это окно первым в списке
</pre>
<p>Учтите, что ни use_msgs_window, ни use_status_window не будут работать если использована команда <code>/LAYOUT SAVE</code>.</p>
<p>Теперь мы подошли к уровням сообщений.. Что это? Все сообщения, которые выводит irssi имеют один или больше
"уровень сообщений". Вот основные уровни: PUBLIC - для сообщений на каналах,
MSGS - для приватных сообщений и CRAP для остальных сообщений, которые нельзя классифицировать. Вы можете получить полный список уровней при помощи команды</p>
<pre>
/HELP levels
</pre>
<p>Окну статуса присвоен уровень <code>ALL -MSGS</code>, который подразумевает, что все сообщения,
исключая приватные, для которых не назначено другое место идут в это окно. Благодаря опции <code>-MSGS</code> оно не конфликтует с окном сообщений.</p>
<h3><a id="c6">6. Как в irssi работает многосерверная поддержка</a></h3>
<p>В ircII и некоторых других IRC-клиентах многосерверная поддержка реализована в виде помещения вкладки с сервером в список окон
. В IRSSI НЕТ. Нет никакой связи между окном и сервером. Вы можете подключиться к десяти серверам одновременно и управлять ими всеми из одного окна, или заходить на каналы на каждом из них
в одном окне, если вы действительно этого хотите. Как было сказано вы можете подключиться к новому серверу, не закрывая текущего соединения:</p>
<pre>
/CONNECT irc.server.org
</pre>
<p>Вместо команды <code>/SERVER</code>, которая закрывает существующее
соединение. Чтобы посмотреть список осуществленных соединений используйте команду <code>/SERVER</code>
без параметров. Вы увидите примерно следующее:</p>
<pre>
-!- IRCNet: irc.song.fi:6667 (IRCNet)
-!- OFTC: irc.oftc.net:6667 (OFTC)
-!- RECON-1: 192.168.0.1:6667 () (02:59 left before reconnecting)
</pre>
<p>Здесь видно, что мы подключены к сетям IRCNet и OFTC.
Надпись IRCNet в начале является "меткой сервера" а
(IRCnet) в конце показывает соответствующую IRC-сеть. Метка сервера соответствует уникальному имени, которое обычно совпадает с названием сети.
Когда IRC-сеть не известна это какая-то часть имени сервера.
Когда осуществлены несколько соединений с одной сетью или сервером, irssi
добавляет цифру после метки, так что это может быть ircnet, ircnet2, ircnet3
и.т.д.</p>
<p>Метка сервера, начинающаяся с <code>RECON-</code> обозначает переподключение.
В вышеприведенном примере мы видим, что подключение к серверу 192.168.0.1 было неудачным и
irssi попробует подключиться заново через 3 минуты.</p>
<p>Чтобы отключиться от сервера используйте следующие команды:</p>
<pre>
/DISCONNECT ircnet - отключиться от сервера с меткой "ircnet"
/DISCONNECT recon-1 - остановить попытки переподключения к серверу RECON-1
/RMRECONNS - остановить все попытки переподключения
/RECONNECT recon-1 - немедленно попробовать переподключиться к RECON-1
/RECONNECT ALL - немедленно попробовать переподключиться ко всем серверам
в очереди на подключение
</pre>
<p>Теперь, когда вы подключены ко всем серверам вы должны знать как указать какой из них вы хотите использовать.
Единственный способ - это иметь пустое окно наподобе окна статуса. В нем вы можете выбрать какой сервер хотите сделать активным</p>
<pre>
/WINDOW SERVER tag - сделать сервер с меткой "tag" активным
Ctrl-X - Сделать следующий в списке сервер активным
</pre>
<p>Когда сервер активный вы можете нормально его использовать. Когда вы подключены к нескольким серверам, irssi добавляет префикс [метка_сервера]
ко всем сообщениям, не относящимся к каналу или привату так что вы можете знать с какого сервера оно пришло.</p>
<p>Некоторые команды так-же позволяют использовать опцию <code>етка_сервера</code>
чтобы указать для какого сервера вы хотите её использовать:</p>
<pre>
/MSG -метка ник сообщение
/JOIN -метка #канал
/QUERY -метка ник
</pre>
<p>Автодополнение команды <code>/MSG</code> так-же автоматически добавляет метку сервера
когда ник не на активном сервере.</p>
<p>Окно сервера можно сделать закреплённым. Когда оно закреплено, то оно никогда автоматически не переключится на какое-то другое, и если произошло отключение от сервера,
то оно не будет иметь активного сервера. Когда к серверу снова произведено подключение,
то он автоматически становится активным в этом окне. Чтобы закрепить окно сервера используйте следующую команду:</p>
<pre>
/WINDOW SERVER -sticky tag
</pre>
<p>Это полезно если вы хотите иметь отдельные окна статуса и сообщений для каждого сервера. Вот как это можно сделать (повторите для каждого сервера):</p>
<pre>
/WINDOW NEW HIDE
/WINDOW NAME (status)
/WINDOW LEVEL ALL -MSGS
/WINDOW SERVER -sticky ircnet
/WINDOW NEW HIDE
/WINDOW NAME (msgs)
/WINDOW LEVEL MSGS
/WINDOW SERVER -sticky ircnet
</pre>
<h3><a id="c7">7. Команда /LASTLOG и прокрутка окон</a></h3>
<p>Команда <code>/LASTLOG</code> может быть использована для поиска текста в буфере окна. Вот простейшие примеры её использования:</p>
<pre>
/LASTLOG слово - вывести все строки, содержащие "слово"
/LASTLOG word 10 - вывести последние 10 строк, содержащих "word"
/LASTLOG -topics - вывести все изменения топика
</pre>
<p>Если результатом вывода должны стать более 1000 строк, то irssi предположит, что вы допустили ошибку и выведет их только с опцией <code>-force</code>.
Чтобы сохранить содержимое буфера окна в файл, используйте следующую команду:</p>
<pre>
/LASTLOG -file ~/irc.log
</pre>
<p>При использовании опции <code>-file</code> опция <code>-force</code>
не требуется. У команды <code>/LASTLOG</code> есть много других опций. Чтобы получить более подробную справку по ней используйте <code>/HELP lastlog</code>.</p>
<p>Когда вы нашли интересовавшие вас строки, вам скорее всего захочется посмотреть другие прилегающие к ним сообщения. В Irssi есть команда <code>/SCROLLBACK</code> (или
её синоним - <code>/SB</code>) для перемещения по буферу окна.
Команда <code>/LASTLOG</code> выводит оригинальное время сообщения
и вы можете использовать команду <code>/SB GOTO чч:мм</code> чтобы "перепрыгнуть" к этому фрагменту дискуссии.
Чтобы переместиться обратно вниз используйте команду <code>/SB
END</code>.</p>
<h3><a id="c8">8. Ведение логов</a></h3>
<p>Irssi может автоматически вести лог всех важных сообщений когда вы в эвее
(<code>/AWAY причина</code>). когда вы вышли из эвея
(ещё раз введите <code>/AWAY</code>), новые сообщения в эвей-логе выводятся на экран.
Вы можете настроить его при помощи следующих команд:</p>
<pre>
/SET awaylog_level MSGS HILIGHT - Выбирает какое сообщения надо записывать в лог
/SET awaylog_file ~/.irssi/away.log - Выбирает файл для лога
</pre>
<p>Простейший способ ведения логов при помощи Irssi - включение автолога.
Irssi будет вести логи всех сообщений в заданный каталог.
Вы можете включить его при помощи следующей команды:</p>
<pre>
/SET autolog ON
</pre>
<p>По умолчанию в логи записывается почти всё кроме уровней CTCPS или CRAP
(<code>/WHOIS</code>-запросы и.т.д.). Вы можете задать уровни сообщений, которые надо писать в логи следующей командой:</p>
<pre>
/SET autolog_level ALL -CRAP -CLIENTCRAP -CTCPS (this is the default)
</pre>
<p>По умолчанию irssi пишет лог в ~/irclogs/&lt;метка_сервера&gt;/&lt;цель&gt;.log.
Это настраивается следующей командой:</p>
<pre>
/SET autolog_path ~/irclogs/$tag/$0.log (вариант "по умолчанию")
</pre>
<p>Если заданный каталог не существует, то он автоматически создается. В переменной $0
содержится цель(канал или ник). Вы можете настроить Irssi так, чтобы он автоматически добавлял дату/время к имени файла с логом.
Вормат даты - "man strftime" :). Вот пример:</p>
<pre>
/SET autolog_path ~/irclogs/%Y/$tag/$0.%m-%d.log
</pre>
<p>Чтобы вести логи только по каким-то отдельным каналам или никам смотрите <code>/HELP
log</code></p>
<h3><a id="c9">9. Изменение клавиатурных сочетаний</a></h3>
<p>Вы можете изменить любое клавиатурное сочетание, о котором терминал даёт знать irssi.
То есть irssi "видит" не все клавиатурные сочетания, например он не будет реагировать на
shift-backspace если вы как-то не отредактируете соответствующие X-ресурсы.</p>
<p>Команда <code>/HELP bind</code> даёт намного больше информации о клавиатурных сочетаниях, чем приведено здесь.
Обычно проблеммой является "забивание" каких-то не стандартных клавиш.
Они немного различны для каждого терминала, так что вы должны будете узнать что именно даёт нажатие этой клавиши.
Простейший путь узнать это - выполнить в консоли <code>cat</code> и посмотреть что будет выводится при нажатии этой клавиши.
Вот пример нажатия клавиши F1:</p>
<pre>
[cras@hurina] ~% cat
^[OP
</pre>
<p>Так что в irssi чтобы "забить" что-то на F1 вы должны будете использовать команду <code>/BIND ^[OP /ECHO нажата клавиша F1</code>.
Если вы используете разные терминалы, которые по разному распознают нажатие одной и той-же клавиши, то вам лучше использовать что-то вроде этого:</p>
<pre>
/BIND ^[OP key F1
/BIND ^[11~ key F1
/BIND F1 /ECHO нажата клавиша F1.
</pre>
<h3><a id="c10">10. Прокси и боунсеры</a></h3>
<p>Irssi поддерживает подключение к IRC-серверам через прокси. Если вы всё правильно сделаете, то все подключения будут осуществляться через него и вам не надо будет вводить никаких дополнительных команд.</p>
<p>Вот пример: У вас есть боунсер, висящий на
irc.bouncer.org 5000. Вы хотите использовать его для подключения к серверам irc.dal.net и irc.efnet.org. Для начала вы должны будете настроить боунсер:</p>
<pre>
/SET use_proxy ON (включить использование прокси)
/SET proxy_address irc.bouncer.org
/SET proxy_port 5000
/SET proxy_password ВАШ_ПАРОЛЬ
/SET -clear proxy_string
/SET proxy_string_after conn %s %d
</pre>
<p>Потом вам нужно будет добавить нужные серверы. Это делается точно так-же, как если бы вы хотели подключиться к ним напрямую:</p>
<pre>
/SERVER ADD -auto -ircnet dalnet irc.dal.net
/SERVER ADD -auto -ircnet efnet irc.efnet.org
</pre>
<p>После того, как вы сделали вышеперечисленные настройки все соединения irssi будет производить через проксю.</p>
<p>Если вы не хотите использовать проксю для какого-то сервера, то при его добавлении укажите опцию
<code>-noproxy</code>.</p>
<p><strong>Специфичные настройки для разных типов прокси:</strong></p>
<p>Обычные настройки:</p>
<pre>
/SET use_proxy ON
/SET proxy_address &lt;Адрес прокси&gt;
/SET proxy_port &lt;Порт&gt;
</pre>
<p><strong>HTTP proxy</strong></p>
<p>Используйте эти настройки для HTTP-прокси:</p>
<pre>
/SET -clear proxy_password
/EVAL SET proxy_string CONNECT %s:%d\n\n
</pre>
<p><strong>BNC</strong></p>
<pre>
/SET proxy_password ваш_пароль
/SET -clear proxy_string
/SET proxy_string_after conn %s %d
</pre>
<p><strong>dircproxy</strong></p>
<p>dircproxy производит подключения к серверам по паролям. Так что если например вы хотите подключиться к серверу ircnet с паролем ircpass
и к OFTC с паролем oftcpass, вы должны сделать примерно следующее:</p>
<pre>
/SET -clear proxy_password
/SET -clear proxy_string
/SERVER ADD -auto -ircnet ircnet fake.ircnet 6667 ircpass
/SERVER ADD -auto -ircnet OFTC fake.oftc 6667 oftcpass
</pre>
<p>Имя сервера и порт, которые вы вводите нигде не используются, так что вы можете писать сюда всё что угодно.</p>
<p><strong>psyBNC</strong></p>
<p>psyBNC имеет внутреннюю многосерверную поддержку.
Это может доставлять небольшие неудобства и некоторые люди просто используют разные логины для подключения к нескольким серверам.
Вы очень просто можете делать это средствами Irssi:</p>
<pre>
/SET -clear proxy_password
/SET -clear proxy_string
/IRCNET ADD -user ircnetuser ircnet
/SERVER ADD -auto -ircnet ircnet fake.ircnet 6667 ircpass
/IRCNET ADD -user oftcuser OFTC
/SERVER ADD -auto -ircnet OFTC fake.oftc 6667 oftcpass
</pre>
<p>Здесь при помощи команды <code>/IRCNET ADD</code> вы задаете имена пользователей
и пароли при помощи <code>/SERVER ADD</code>.</p>
<p><strong>Irssi proxy</strong></p>
<p>Irssi включает свою собственную проксю, которую вы можете собрать при помощи опции configure
<code>--with-proxy</code>. Чтобы её использовать вы должны оставлять irssi запущенным.</p>
<p>Irssi-прокся немного отличается от остальных прокси-серверов, нормальные прокси создают новые соединения с IRC-сервером когда вы хотите к нему подключиться, а
<strong>irssi-прокся использует уже существующее соединение(я) для всех клиентов</strong>. Или ещё понятнее: <strong>Вы можете использовать только одно соединение с IRC-сервером для неограниченного числа клиентов</strong>.</p>
<p>Irssi-прокся может распределять несколько соединений с серверами на разные порты, например на 2777-ом порту у вас может быть соединение с ircnet, а на 2778 с efnet.</p>
<p>Использование на стороне прокси:</p>
<pre>
/LOAD proxy
/SET irssiproxy_password &lt;пароль&gt;
/SET irssiproxy_ports &lt;IRC_сеть&gt;=&lt;порт&gt; ... (например ircnet=2777 efnet=2778)
</pre>
<p>Вы <strong>должны</strong> добавить все серверы, которые вы используете в списки серверов и сетей
при помощи команд <code>/SERVER ADD</code> и
<code>/IRCNET ADD</code>. ..разве что если вы хотите использовать только одно соединение, то вы можете указать:</p>
<pre>
/SET irssiproxy_ports *=2777
</pre>
<p>Использование на стороне клиента:</p>
<p>Просто подключитесь к проксе как к нормальному серверу с паролем, заданным командой <code>/SET irssiproxy_password</code>. Пример:</p>
<pre>
/SERVER ADD -ircnet ircnet my.irssi-proxy.org 2777 secret
/SERVER ADD -ircnet efnet my.irssi-proxy.org 2778 secret
</pre>
<p>Irssi-прокся так-же нормально работает с другими irc-клиентами.</p>
<p><strong>SOCKS</strong></p>
Irssi может быть собран с поддержкой socks-прокси (опция configure <code>--with-socks</code>),
но я на самом деле не знаю как оно работает. Настройки <code>/SET
proxy</code> на эти прокси никак не действуют.
<p><strong>Другие прокси</strong></p>
<p>IRC-боунсеры обычно работают точно так-же как и IRC-серверы, но просят пароль. Вы можете дать им его при помощи следующей команды:</p>
<pre>
/SET proxy_password &lt;пароль&gt;
</pre>
<p>CONNECT-строки по умолчанию:</p>
<pre>
/SET proxy_string CONNECT %s %d
/SET proxy_string_after
</pre>
<p>proxy_string отправляются перед командами NICK/USER, а
proxy_string_after отправляется после них. %s and %d can be used with both
of them.</p>
<h3><a id="c11">11. Настройки Irssi</a></h3>
<p>Вам могут не понравится настройки Irssi по умолчанию.
Вот некоторые из них, которые вы скорее всего захотите изменить(в примерах приведены "умолчальные" значения):</p>
<p><strong>Окна приватов</strong></p>
<dl>
<dt>/SET autocreate_own_query ON</dt>
<dd>Автоматически создавать окно привата когда вы отправляете кому-то сообщение при помощи команды <code>/MSG</code>.</dd>
<dt>/SET autocreate_query_level MSGS</dt>
<dd>При получении сообщений окно привата создается с этим уровнем сообщений. Сейчас работают только MSGS, DCCMSGS и NOTICES.
Вы можете отменить это при помощи команды <code>/SET -clear autocreate_query_level</code>.</dd>
<dt>/SET autoclose_query 0</dt>
<dd>Окна приватов могут быть автоматически закрыты после заданного "простоя". Активное окно и окна с непрочитанными сообщениями не закрываются. Значение задается в секундах.</dd>
</dl>
<p><strong>Окна</strong></p>
<dl>
<dt>/SET use_msgs_window OFF</dt>
<dd>Создавать окно сообщений при запуске. Все приватные сообщения будут направляться в это окно.
Это имеет смысл только если вы отменили автосоздание окон приватов.
Это окно так-же может быть создано вручную при помощи команды /WINDOW LEVEL
MSGS, /WINDOW NAME (msgs).</dd>
<dt>/SET use_status_window ON</dt>
<dd>Создавать окно статуса при запуске. Все сообщения, которые больше некуда отправить идут сюда, включая /WHOIS и.т.д.
Окно статуса тоже может быть создано вручную при помощи команд <code>/WINDOW LEVEL ALL -MSGS</code>,
<code>/WINDOW NAME (status)</code>.</dd>
<dt>/SET autocreate_windows ON</dt>
<dd>Если вы это отключите, то все сообщения будут помещаться в одно окно</dd>
<dt>/SET autoclose_windows ON</dt>
<dd>Автозакрытие окон (например при выходе с каналов(<code>/PART</code>)).</dd>
<dt>/SET reuse_unused_windows OFF</dt>
<dd>Когда ищется место для создания нового окна (канала или привата) Irssi
сначала пытается использовать уже существующие пустые окна. Если эта опция включена, то всегда будут создаваться новые окна.
Эта настройка игнорируется если autoclose_windows включен.</dd>
<dt>/SET window_auto_change OFF</dt>
<dd>Автоматически переключаться в автоматически созданные окна.</dd>
<dt>/SET print_active_channel OFF</dt>
<dd>Когда вы держите в одном окне больше чем один канал, Irssi выводит сообщения, приходящие на активный канал в форме <code>&lt;ник&gt; текст</code>
а те, что приходят на другие каналы так: <code>&lt;ник:канал&gt; текст</code>. Если эта опция включена, то сообщения, приходящие на активный канал будут так-же выводиться во втором варианте.</dd>
<dt>/SET window_history OFF</dt>
<dd>Хранить отдельную историю команд для каждого окна.</dd>
</dl>
<p><strong>Информация о пользователе</strong></p>
<dl>
<dt>/SET nick</dt>
<dd>Ваш ник</dd>
<dt>/SET alternate_nick</dt>
<dd>Ваш альтернативный ник.</dd>
<dt>/SET user_name</dt>
<dd>Ваше имя пользователя. Если у вас включен ident, то оно ничего не даёт.</dd>
<dt>/SET real_name</dt>
<dd>Ваше настоящее имя.</dd>
</dl>
<p><strong>Информация о сервере</strong></p>
<dl>
<dt>/SET skip_motd OFF</dt>
<dd>Пропускать motd при подключении к серверу.</dd>
<dt>/SET server_reconnect_time 300</dt>
<dd>Сколько секунд надо ждать перед повторной попыткой подключения к серверу.</dd>
<dt>/SET lag_max_before_disconnect 300</dt>
<dd>При каком лаге(в секундах) надо отключаться от сервера и предпринимать попытку переподключения.</dd>
</dl>
<p><strong>Внешний вид</strong></p>
<dl>
<dt>/SET timestamps ON</dt>
<dd>Показывать время перед каждым сообщением.</dd>
<dt>/SET hide_text_style OFF</dt>
<dd>Скрыть оформление текста(жирный шрифт, цвета и.т.д.).</dd>
<dt>/SET show_nickmode ON</dt>
<dd>Показывать "режим ника" на каналах, например
<code>&lt;@nick&gt;</code> у опов, <code>&lt;+nick&gt;</code> у войсов и.т.д.</dd>
<dt>/SET show_nickmode_empty ON</dt>
<dd>Если у ника нет режима - выводить пробел на месте "символа режима".</dd>
<dt>/SET show_quit_once OFF</dt>
<dd>Показывать quit-сообщение только в одном окне, если человек вышел с нескольких каналов, на которых вы сидите.</dd>
<dt>/SET lag_min_show 100</dt>
<dd>Показывать в статус-баре лаг если он превышает заданное число юнитов. В одной секунде 100 юнитов.</dd>
<dt>/SET indent 10</dt>
<dd>Если строка, которую надо вывести не вмещается в одну строку, то она разбивается и выводится на следующих строках. Этот параметр показывает сколько места надо отступить перед началом вывода текста на следующих строках.
Это может быть переопределено в настройках форматирования текста при помощи формата <code>%|</code>.</dd>
<dt>/SET activity_hide_targets</dt>
<dd>Если вы не хотите видеть активность на каких-то каналах или приватах, то перечислите их здесь. Например <code>#boringchannel =bot1
=bot2</code>. Эта настройка игнорируется если встречается текст или сообщение, для которого вы настроили подсветку(highlight).</dd>
</dl>
<p><strong>Автодополнение ников</strong></p>
<dl>
<dt>/SET completion_auto OFF</dt>
<dd>Автоматически дополнять ник если строка начинается с первых букв ника и "символа автодополнения".
Лучше всего использовать автодополнение табом.</dd>
<dt>/SET completion_char :</dt>
<dd>"Символ автодополнения".</dd>
</dl>
<h3><a id="c12">12. Панель статуса</a></h3>
<p>Команда <code>/STATUSBAR</code> выводит список панелей статуса:</p>
<pre>
Name Type Placement Position Visible
window window bottom 0 always
window_inact window bottom 1 inactive
prompt root bottom 100 always
topic root top 1 always
</pre>
<p><code>/STATUSBAR &lt;имя&gt;</code> выводит настройки панели статуса и её компоненты.
<code>/STATUSBAR &lt;имя&gt; ENABLE|DISABLE</code>
включает или отключает панель. <code>/STATUSBAR &lt;имя&gt; RESET</code>
устанавливает для панели статуса настройки по умолчанию, или если она была создана вами, то удаляет её.</p>
<p>Панель может иметь два типа: windows и root - это подразумевает, что она может быть видна для всех окон или только для одного.
Placement - это расположение панели: top - сверху, bottom - снизу.
Position - это число, чем больше значение которого, тем ниже на экране располагается панель.
Параметр Visible может принимать 3 значения: always, active и inactive. Режимы active/inactive полезны только для разделенных окон.
Эти настройки могут быть изменены следующими командами:</p>
<pre>
/STATUSBAR &lt;имя&gt; TYPE window|root
/STATUSBAR &lt;имя&gt; PLACEMENT top|bottom
/STATUSBAR &lt;имя&gt; POSITION &lt;num&gt;
/STATUSBAR &lt;имя&gt; VISIBLE always|active|inactive
</pre>
<p>Когда вы загружаете новые скрипты для панелей статуса вам скорее всего придется выбрать где вы хотите их расположить.
Компоненты панелей могут быть изменены следующими командами:</p>
<pre>
/STATUSBAR &lt;имя&gt; ADD [-before | -after &lt;item&gt;] [-priority #] [-alignment left|right] &lt;компонента(item)&gt;
/STATUSBAR &lt;имя&gt; REMOVE &lt;компонента(item)&gt;
</pre>
<p>Обычно для имя компоненты в скрипте для панели соответствует имени скрипта.
Об этом должно быть написано в документации к скрипту. Так что чтобы добавить скрипт mail.pl
перед списком активных окон (смотрите
<code>/STATUSBAR</code>), введите эту команду: <code>/STATUSBAR window ADD -before
act mail</code>.</p>

File diff suppressed because it is too large Load Diff

View File

@ -5,21 +5,19 @@
use strict;
use vars qw($VERSION %IRSSI);
$VERSION = '2003020803';
%IRSSI = (
our $VERSION = '2003020804';
our %IRSSI = (
authors => 'Stefan \'tommie\' Tomanek',
contact => 'stefan@pico.ruhr.de',
name => 'scriptassist',
description => 'keeps your scripts on the cutting edge',
license => 'GPLv2',
url => 'http://irssi.org/scripts/',
changed => $VERSION,
modules => 'Data::Dumper LWP::UserAgent (GnuPG)',
commands => "scriptassist"
);
use vars qw($forked %remote_db $have_gpg);
our ($forked, %remote_db, $have_gpg, @complist);
use Irssi 20020324;
use Data::Dumper;
@ -27,12 +25,11 @@ use LWP::UserAgent;
use POSIX;
# GnuPG is not always needed
use vars qw($have_gpg @complist);
$have_gpg = 0;
eval "use GnuPG qw(:algo :trust);";
$have_gpg = 1 if not ($@);
sub show_help() {
sub show_help {
my $help = "scriptassist $VERSION
/scriptassist check
Check all loaded scripts for new available versions
@ -42,15 +39,15 @@ sub show_help() {
Search the script database
/scriptassist info <scripts>
Display information about <scripts>
/scriptassist ratings <scripts>
Retrieve the average ratings of the the scripts
/scriptassist top <num>
Retrieve the first <num> top rated scripts
/scriptassist new <num>
".#/scriptassist ratings <scripts>
# Retrieve the average ratings of the the scripts
#/scriptassist top <num>
# Retrieve the first <num> top rated scripts
"/scriptassist new <num>
Display the newest <num> scripts
/scriptassist rate <script> <stars>
Rate the script with a number of stars ranging from 0-5
/scriptassist contact <script>
".#/scriptassist rate <script> <stars>
# Rate the script with a number of stars ranging from 0-5
"/scriptassist contact <script>
Write an email to the author of the script
(Requires OpenURL)
/scriptassist cpan <module>
@ -70,7 +67,7 @@ sub show_help() {
#theme_box("ScriptAssist", $text, "scriptassist help", 1);
}
sub theme_box ($$$$) {
sub theme_box {
my ($title, $text, $footer, $colour) = @_;
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'box_header', $title);
foreach (split(/\n/, $text)) {
@ -79,31 +76,30 @@ sub theme_box ($$$$) {
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'box_footer', $footer);
}
sub draw_box ($$$$) {
sub draw_box {
my ($title, $text, $footer, $colour) = @_;
my $box = '';
$box .= '%R,--[%n%9%U'.$title.'%U%9%R]%n'."\n";
foreach (split(/\n/, $text)) {
$box .= '%R|%n '.$_."\n";
} $box .= '%R`--<%n'.$footer.'%R>->%n';
}
$box .= '%R`--<%n'.$footer.'%R>->%n';
$box =~ s/%.//g unless $colour;
return $box;
}
sub call_openurl ($) {
sub call_openurl {
my ($url) = @_;
no strict "refs";
# check for a loaded openurl
if ( %{ "Irssi::Script::openurl::" }) {
&{ "Irssi::Script::openurl::launch_url" }($url);
if (my $code = Irssi::Script::openurl::->can('launch_url')) {
$code->($url);
} else {
print CLIENTCRAP "%R>>%n Please install openurl.pl";
}
use strict;
}
sub bg_do ($) {
my ($func) = @_;
sub bg_do {
my ($func) = @_;
my ($rh, $wh);
pipe($rh, $wh);
if ($forked) {
@ -137,7 +133,6 @@ sub bg_do ($) {
$result{data}{update} = update_scripts(\@items, $xml);
} elsif ($items[0] eq 'search') {
shift(@items);
#$result{data}{search}{-foo} = 0;
foreach (@items) {
$result{data}{search}{$_} = search_scripts($_, $xml);
}
@ -150,14 +145,12 @@ sub bg_do ($) {
} elsif ($items[0] eq 'ratings') {
shift(@items);
@items = @{ loaded_scripts() } if $items[0] eq "all";
#$result{data}{rating}{-foo} = 1;
my %ratings = %{ get_ratings(\@items, '') };
foreach (keys %ratings) {
$result{data}{rating}{$_}{rating} = $ratings{$_}->[0];
$result{data}{rating}{$_}{votes} = $ratings{$_}->[1];
}
} elsif ($items[0] eq 'rate') {
#$result{data}{rate}{-foo} = 1;
$result{data}{rate}{$items[1]} = rate_script($items[1], $items[2]);
} elsif ($items[0] eq 'info') {
shift(@items);
@ -182,12 +175,16 @@ sub bg_do ($) {
my $data = $dumper->Dump;
print($wh $data);
};
if ($@) {
print($wh Data::Dumper->new([+{data=>+{error=>$@}}])
->Purity(1)->Deepcopy(1)->Indent(0)->Dump);
}
close($wh);
POSIX::_exit(1);
}
}
sub get_unknown ($$) {
sub get_unknown {
my ($cmd, $db) = @_;
foreach (keys %$db) {
next unless defined $db->{$_}{commands};
@ -198,56 +195,90 @@ sub get_unknown ($$) {
return undef;
}
sub script_info ($) {
sub get_names {
my ($sname, $db) = shift;
$sname =~ s/\s+$//;
$sname =~ s/\.pl$//;
my $plname = "$sname.pl";
$sname =~ s/^.*\///;
my $xname = $sname;
$xname =~ s/\W/_/g;
my $pname = "${xname}::";
if ($xname ne $sname || $sname =~ /_/) {
my $dir = Irssi::get_irssi_dir()."/scripts/";
if ($db && exists $db->{"$sname.pl"}) {
# $found = 1;
} elsif (-e $dir.$plname || -e $dir."$sname.pl" || -e $dir."autorun/$sname.pl") {
# $found = 1;
} else {
# not found
my $pat = $xname; $pat =~ y/_/?/;
my $re = "\Q$xname"; $re =~ s/\Q_/./g;
if ($db) {
my ($cand) = grep /^$re\.pl$/, sort keys %$db;
if ($cand) {
return get_names($cand, $db);
}
}
my ($cand) = glob "'$dir$pat.pl' '${dir}autorun/$pat.pl'";
if ($cand) {
$cand =~ s/^.*\///;
return get_names($cand, $db);
}
}
}
($sname, $plname, $pname, $xname)
}
sub script_info {
my ($scripts) = @_;
no strict "refs";
my %result;
my $xml = get_scripts();
foreach (@{$scripts}) {
next unless (defined $xml->{$_.".pl"} || ( %{ 'Irssi::Script::'.$_.'::' } && %{ 'Irssi::Script::'.$_.'::IRSSI' }));
$result{$_}{version} = get_remote_version($_, $xml);
my ($sname, $plname, $pname) = get_names($_, $xml);
next unless (defined $xml->{$plname} || ( exists $Irssi::Script::{$pname} && exists $Irssi::Script::{$pname}{IRSSI} ));
$result{$sname}{version} = get_remote_version($sname, $xml);
my @headers = ('authors', 'contact', 'description', 'license', 'source');
foreach my $entry (@headers) {
$result{$_}{$entry} = ${ 'Irssi::Script::'.$_.'::IRSSI' }{$entry};
if (defined $xml->{$_.".pl"}{$entry}) {
$result{$_}{$entry} = $xml->{$_.".pl"}{$entry};
$result{$sname}{$entry} = $Irssi::Script::{$pname}{IRSSI}{$entry};
if (defined $xml->{$plname}{$entry}) {
$result{$sname}{$entry} = $xml->{$plname}{$entry};
}
}
if ($xml->{$_.".pl"}{signature_available}) {
$result{$_}{signature_available} = 1;
if ($xml->{$plname}{signature_available}) {
$result{$sname}{signature_available} = 1;
}
if (defined $xml->{$_.".pl"}{modules}) {
my $modules = $xml->{$_.".pl"}{modules};
#$result{$_}{modules}{-foo} = 1;
if (defined $xml->{$plname}{modules}) {
my $modules = $xml->{$plname}{modules};
foreach my $mod (split(/ /, $modules)) {
my $opt = ($mod =~ /\((.*)\)/)? 1 : 0;
$mod = $1 if $1;
$result{$_}{modules}{$mod}{optional} = $opt;
$result{$_}{modules}{$mod}{installed} = module_exist($mod);
$result{$sname}{modules}{$mod}{optional} = $opt;
$result{$sname}{modules}{$mod}{installed} = module_exist($mod);
}
} elsif (defined ${ 'Irssi::Script::'.$_.'::IRSSI' }{modules}) {
my $modules = ${ 'Irssi::Script::'.$_.'::IRSSI' }{modules};
} elsif (defined $Irssi::Script::{$pname}{IRSSI}{modules}) {
my $modules = $Irssi::Script::{$pname}{IRSSI}{modules};
foreach my $mod (split(/ /, $modules)) {
my $opt = ($mod =~ /\((.*)\)/)? 1 : 0;
$mod = $1 if $1;
$result{$_}{modules}{$mod}{optional} = $opt;
$result{$_}{modules}{$mod}{installed} = module_exist($mod);
$result{$sname}{modules}{$mod}{optional} = $opt;
$result{$sname}{modules}{$mod}{installed} = module_exist($mod);
}
}
if (defined $xml->{$_.".pl"}{depends}) {
my $depends = $xml->{$_.".pl"}{depends};
if (defined $xml->{$plname}{depends}) {
my $depends = $xml->{$plname}{depends};
foreach my $dep (split(/ /, $depends)) {
$result{$_}{depends}{$dep}{installed} = 1; #(defined ${ 'Irssi::Script::'.$dep });
$result{$sname}{depends}{$dep}{installed} = 1;
}
}
}
return \%result;
}
sub rate_script ($$) {
sub rate_script {
my ($script, $stars) = @_;
my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30);
$ua->agent('ScriptAssist/'.$VERSION);
$ua->agent('ScriptAssist/'.2003020803);
my $request = HTTP::Request->new('GET', 'http://ratings.irssi.de/irssirate.pl?&stars='.$stars.'&mode=rate&script='.$script);
my $response = $ua->request($request);
unless ($response->is_success() && $response->content() =~ /You already rated this script/) {
@ -257,10 +288,10 @@ sub rate_script ($$) {
}
}
sub get_ratings ($$) {
sub get_ratings {
my ($scripts, $limit) = @_;
my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30);
$ua->agent('ScriptAssist/'.$VERSION);
$ua->agent('ScriptAssist/'.2003020803);
my $script = join(',', @{$scripts});
my $request = HTTP::Request->new('GET', 'http://ratings.irssi.de/irssirate.pl?script='.$script.'&sort=rating&limit='.$limit);
my $response = $ua->request($request);
@ -278,7 +309,7 @@ sub get_ratings ($$) {
return \%result;
}
sub get_new ($) {
sub get_new {
my ($num) = @_;
my $result;
my $xml = get_scripts();
@ -290,7 +321,7 @@ sub get_new ($) {
}
return $result;
}
sub module_exist ($) {
sub module_exist {
my ($module) = @_;
$module =~ s/::/\//g;
foreach (@INC) {
@ -299,63 +330,64 @@ sub module_exist ($) {
return 0;
}
sub debug_scripts ($) {
sub debug_scripts {
my ($scripts) = @_;
my %result;
my $xml = get_scripts();
foreach (@{$scripts}) {
my $xml = get_scripts();
if (defined $xml->{$_.".pl"}{modules}) {
my $modules = $xml->{$_.".pl"}{modules};
my ($sname, $plname) = get_names($_, $xml);
if (defined $xml->{$plname}{modules}) {
my $modules = $xml->{$plname}{modules};
foreach my $mod (split(/ /, $modules)) {
my $opt = ($mod =~ /\((.*)\)/)? 1 : 0;
$mod = $1 if $1;
$result{$_}{$mod}{optional} = $opt;
$result{$_}{$mod}{installed} = module_exist($mod);
$result{$sname}{$mod}{optional} = $opt;
$result{$sname}{$mod}{installed} = module_exist($mod);
}
}
}
return(\%result);
}
sub install_scripts ($$) {
sub install_scripts {
my ($scripts, $xml) = @_;
my %success;
#$success{-foo} = 1;
my $dir = Irssi::get_irssi_dir()."/scripts/";
foreach (@{$scripts}) {
if (get_local_version($_) && (-e $dir.$_.".pl")) {
$success{$_}{installed} = -2;
my ($sname, $plname, $pname) = get_names($_, $xml);
if (get_local_version($sname) && (-e $dir.$plname)) {
$success{$sname}{installed} = -2;
} else {
$success{$_} = download_script($_, $xml);
$success{$sname} = download_script($sname, $xml);
}
}
return \%success;
}
sub update_scripts ($$) {
sub update_scripts {
my ($list, $database) = @_;
$list = loaded_scripts() if ($list->[0] eq "all" || scalar(@$list) == 0);
my %status;
#$status{-foo} = 1;
foreach (@{$list}) {
my $local = get_local_version($_);
my $remote = get_remote_version($_, $database);
my ($sname) = get_names($_, $database);
my $local = get_local_version($sname);
my $remote = get_remote_version($sname, $database);
next if $local eq '' || $remote eq '';
if (compare_versions($local, $remote) eq "older") {
$status{$_} = download_script($_, $database);
$status{$sname} = download_script($sname, $database);
} else {
$status{$_}{installed} = -2;
$status{$sname}{installed} = -2;
}
$status{$_}{remote} = $remote;
$status{$_}{local} = $local;
$status{$sname}{remote} = $remote;
$status{$sname}{local} = $local;
}
return \%status;
}
sub search_scripts ($$) {
sub search_scripts {
my ($query, $database) = @_;
$query =~ s/\.pl\Z//;
my %result;
#$result{-foo} = " ";
foreach (sort keys %{$database}) {
my %entry = %{$database->{$_}};
my $string = $_." ";
@ -385,23 +417,22 @@ sub search_scripts ($$) {
sub pipe_input {
my ($rh, $pipetag) = @{$_[0]};
my @lines = <$rh>;
my $text = do { local $/; <$rh>; };
close($rh);
Irssi::input_remove($$pipetag);
$forked = 0;
my $text = join("", @lines);
unless ($text) {
print CLIENTCRAP "%R<<%n Something weird happend";
print CLIENTCRAP "%R<<%n Something weird happend (no text)";
return();
}
no strict "vars";
my $incoming = eval("$text");
local our $VAR1;
my $incoming = eval($text);
if ($incoming->{db} && $incoming->{timestamp}) {
$remote_db{db} = $incoming->{db};
$remote_db{timestamp} = $incoming->{timestamp};
}
unless (defined $incoming->{data}) {
print CLIENTCRAP "%R<<%n Something weird happend";
print CLIENTCRAP "%R<<%n Something weird happend (no data)";
return;
}
my %result = %{ $incoming->{data} };
@ -447,10 +478,14 @@ sub pipe_input {
if ($result{unknown}) {
print_unknown($result{unknown});
}
if (defined $result{error}) {
print CLIENTCRAP "%R<<%n There was an error in background processing:"; chomp($result{error});
print CLIENTERROR $result{error};
}
}
sub print_unknown ($) {
sub print_unknown {
my ($data) = @_;
foreach my $cmd (keys %$data) {
print CLIENTCRAP "%R<<%n No script provides '/$cmd'" unless $data->{$cmd};
@ -458,7 +493,7 @@ sub print_unknown ($) {
my $text .= "The command '/".$cmd."' is provided by the script '".$data->{$cmd}{$_}{name}."'.\n";
$text .= "This script is currently not installed on your system.\n";
$text .= "If you want to install the script, enter\n";
my ($name) = /(.*?)\.pl$/;
my ($name) = get_names($_);
$text .= " %U/script install ".$name."%U ";
my $output = draw_box("ScriptAssist", $text, "'".$_."' missing", 1);
print CLIENTCRAP $output;
@ -466,11 +501,12 @@ sub print_unknown ($) {
}
}
sub check_autorun ($) {
sub check_autorun {
my ($script) = @_;
my (undef, $plname) = get_names($script);
my $dir = Irssi::get_irssi_dir()."/scripts/";
if (-e $dir."/autorun/".$script.".pl") {
if (readlink($dir."/autorun/".$script.".pl") eq "../".$script.".pl") {
if (-e $dir."/autorun/".$plname) {
if (readlink($dir."/autorun/".$plname) eq "../".$plname) {
return 1;
}
}
@ -487,7 +523,7 @@ sub array2table {
$l =~ s/%%/%/g;
$width[$_] = length($l) if $width[$_]<length($l);
}
}
}
my $text;
foreach my $line (@array) {
for (0..scalar(@$line)-1) {
@ -503,7 +539,7 @@ sub array2table {
}
sub print_info (%) {
sub print_info {
my (%data) = @_;
my $line;
foreach my $script (sort keys(%data)) {
@ -543,7 +579,6 @@ sub print_info (%) {
$line .= " <optional>" if $data{$script}{modules}{$_}{optional};
$line .= "\n";
}
#$line .= " Needed Irssi scripts:\n";
$line .= " Needed Irssi Scripts:\n" if $data{$script}{depends};
foreach (sort keys %{$data{$script}{depends}}) {
if ( $data{$script}{depends}{$_}{installed} == 1 ) {
@ -551,14 +586,13 @@ sub print_info (%) {
} else {
$line .= " %r->%n ".$_." (not loaded)";
}
#$line .= " <optional>" if $data{$script}{depends}{$_}{optional};
$line .= "\n";
}
}
print CLIENTCRAP draw_box('ScriptAssist', $line, 'info', 1) ;
}
sub print_rate (%) {
sub print_rate {
my (%data) = @_;
my $line;
foreach my $script (sort keys(%data)) {
@ -571,7 +605,7 @@ sub print_rate (%) {
print CLIENTCRAP draw_box('ScriptAssist', $line, 'rating', 1) ;
}
sub print_ratings (%) {
sub print_ratings {
my (%data) = @_;
my @table;
foreach my $script (sort {$data{$b}{rating}<=>$data{$a}{rating}} keys(%data)) {
@ -589,12 +623,12 @@ sub print_ratings (%) {
print CLIENTCRAP draw_box('ScriptAssist', array2table(@table), 'ratings', 1) ;
}
sub print_new ($) {
sub print_new {
my ($list) = @_;
my @table;
foreach (sort {$list->{$b}{last_modified} cmp $list->{$a}{last_modified}} keys %$list) {
my @line;
my ($name) = /^(.*?)\.pl$/;
my ($name) = get_names($_);
if (get_local_version($name)) {
push @line, "%go%n";
} else {
@ -607,7 +641,7 @@ sub print_new ($) {
print CLIENTCRAP draw_box('ScriptAssist', array2table(@table), 'new scripts', 1) ;
}
sub print_debug (%) {
sub print_debug {
my (%data) = @_;
my $line;
foreach my $script (sort keys %data) {
@ -627,12 +661,12 @@ sub print_debug (%) {
}
}
sub load_script ($) {
sub load_script {
my ($script) = @_;
Irssi::command('script load '.$script);
}
sub print_install (%) {
sub print_install {
my (%data) = @_;
my $text;
my ($crashed, @installed);
@ -681,17 +715,16 @@ sub print_install (%) {
list_sbitems(\@installed);
}
sub list_sbitems ($) {
sub list_sbitems {
my ($scripts) = @_;
my $text;
foreach (@$scripts) {
no strict 'refs';
next unless %{ "Irssi::Script::${_}::" };
next unless %{ "Irssi::Script::${_}::IRSSI" };
my %header = %{ "Irssi::Script::${_}::IRSSI" };
next unless $header{sbitems};
next unless exists $Irssi::Script::{"${_}::"};
next unless exists $Irssi::Script::{"${_}::"}{IRSSI};
my $header = $Irssi::Script::{"${_}::"}{IRSSI};
next unless $header->{sbitems};
$text .= '%9"'.$_.'"%9 provides the following statusbar item(s):'."\n";
$text .= ' ->'.$_."\n" foreach (split / /, $header{sbitems});
$text .= ' ->'.$_."\n" foreach (split / /, $header->{sbitems});
}
return unless $text;
$text .= "\n";
@ -699,7 +732,7 @@ sub list_sbitems ($) {
print CLIENTCRAP draw_box('ScriptAssist', $text, 'sbitems', 1);
}
sub check_sig ($) {
sub check_sig {
my ($sig) = @_;
my $line;
my %trust = ( -1 => 'undefined',
@ -722,7 +755,7 @@ sub check_sig ($) {
return $line;
}
sub print_search ($%) {
sub print_search {
my ($query, %data) = @_;
my $text;
foreach (sort keys %data) {
@ -738,7 +771,7 @@ sub print_search ($%) {
print CLIENTCRAP draw_box('ScriptAssist', $text, 'search: '.$query, 1) ;
}
sub print_update (%) {
sub print_update {
my (%data) = @_;
my $text;
my @table;
@ -761,7 +794,7 @@ sub print_update (%) {
push @table, ['%yo%n', '%9'.$_.'%9', 'not upgraded'];
foreach (split /\n/, check_sig($data{$_})) {
push @table, ['', '', $_];
}
}
} elsif ($data{$_}{installed} == -2 && $verbose) {
my $local = $data{$_}{local};
push @table, ['%go%n', '%9'.$_.'%9', 'already at the latest version ('.$local.')'];
@ -771,35 +804,44 @@ sub print_update (%) {
print CLIENTCRAP draw_box('ScriptAssist', $text, 'update', 1) ;
}
sub contact_author ($) {
sub contact_author {
my ($script) = @_;
no strict 'refs';
return unless %{ "Irssi::Script::${script}::" };
my %header = %{ "Irssi::Script::${script}::IRSSI" };
if (defined $header{contact}) {
my @ads = split(/ |,/, $header{contact});
my ($sname, $plname, $pname) = get_names($script);
return unless exists $Irssi::Script::{$pname};
my $header = $Irssi::Script::{$pname}{IRSSI};
if ($header && defined $header->{contact}) {
my @ads = split(/ |,/, $header->{contact});
my $address = $ads[0];
$address .= '?subject='.$script;
$address .= '_'.get_local_version($script) if defined get_local_version($script);
call_openurl($address);
call_openurl($address) if $address =~ /[\@:]/;
}
}
sub get_scripts {
my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30);
$ua->agent('ScriptAssist/'.$VERSION);
$ua->agent('ScriptAssist/'.2003020803);
$ua->env_proxy();
my @mirrors = split(/ /, Irssi::settings_get_str('scriptassist_script_sources'));
my %sites_db;
my $not_modified = 0;
my $fetched = 0;
my @sources;
my $error;
foreach my $site (@mirrors) {
my $request = HTTP::Request->new('GET', $site);
if ($remote_db{timestamp}) {
$request->if_modified_since($remote_db{timestamp});
}
my $response = $ua->request($request);
next unless $response->is_success;
if ($response->code == 304) { # HTTP_NOT_MODIFIED
$not_modified = 1;
next;
}
unless ($response->is_success) {
$error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), '';
next;
}
$fetched = 1;
my $data = $response->content();
my ($src, $type);
@ -826,9 +868,8 @@ sub get_scripts {
$sites_db{$_}{source} = $src;
}
} else {
## FIXME Panic?!
die("Unknown script database type ($type).\n");
}
}
if ($fetched) {
# Clean database
@ -842,32 +883,40 @@ sub get_scripts {
}
$remote_db{db}{$_} = $sites_db{$_} foreach (keys %sites_db);
$remote_db{timestamp} = time();
} elsif ($not_modified) {
# nothing to do
} else {
die("No script database sources defined in /set scriptassist_script_sources\n") unless @mirrors;
die("Fetching script database failed: $error") if $error;
die("Unknown error while fetching script database\n");
}
return $remote_db{db};
}
sub get_remote_version ($$) {
sub get_remote_version {
my ($script, $database) = @_;
return $database->{$script.".pl"}{version};
my $plname = (get_names($script, $database))[1];
return $database->{$plname}{version};
}
sub get_local_version ($) {
sub get_local_version {
my ($script) = @_;
no strict 'refs';
return unless %{ "Irssi::Script::${script}::" };
my $version = ${ "Irssi::Script::${script}::VERSION" };
return $version;
my $pname = (get_names($script))[2];
return unless exists $Irssi::Script::{$pname};
my $vref = $Irssi::Script::{$pname}{VERSION};
return $vref ? $$vref : undef;
}
sub compare_versions ($$) {
sub compare_versions {
my ($ver1, $ver2) = @_;
my @ver1 = split /\./, $ver1;
my @ver2 = split /\./, $ver2;
#if (scalar(@ver2) != scalar(@ver1)) {
# return 0;
#}
for ($ver1, $ver2) {
$_ = "0:$_" unless /:/;
}
my @ver1 = split /[.:]/, $ver1;
my @ver2 = split /[.:]/, $ver2;
my $cmp = 0;
### Special thanks to Clemens Heidinger
no warnings 'uninitialized';
$cmp ||= $ver1[$_] <=> $ver2[$_] || $ver1[$_] cmp $ver2[$_] for 0..scalar(@ver2);
return 'newer' if $cmp == 1;
return 'older' if $cmp == -1;
@ -875,24 +924,20 @@ sub compare_versions ($$) {
}
sub loaded_scripts {
no strict 'refs';
my @modules;
foreach (sort grep(s/::$//, keys %Irssi::Script::)) {
#my $name = ${ "Irssi::Script::${_}::IRSSI" }{name};
#my $version = ${ "Irssi::Script::${_}::VERSION" };
push @modules, $_;# if $name && $version;
push @modules, $_;
}
return \@modules;
}
sub check_scripts {
my ($data) = @_;
my %versions;
#$versions{-foo} = 1;
foreach (@{loaded_scripts()}) {
my $remote = get_remote_version($_, $data);
my $local = get_local_version($_);
my ($sname) = get_names($_, $data);
my $remote = get_remote_version($sname, $data);
my $local = get_local_version($sname);
my $state;
if ($local && $remote) {
$state = compare_versions($local, $remote);
@ -905,51 +950,50 @@ sub check_scripts {
$remote = '/';
}
if ($state) {
$versions{$_}{state} = $state;
$versions{$_}{remote} = $remote;
$versions{$_}{local} = $local;
$versions{$sname}{state} = $state;
$versions{$sname}{remote} = $remote;
$versions{$sname}{local} = $local;
}
}
return \%versions;
}
sub download_script ($$) {
sub download_script {
my ($script, $xml) = @_;
my ($sname, $plname) = get_names($script, $xml);
my %result;
my $site = $xml->{$script.".pl"}{source};
my $site = $xml->{$plname}{source};
$result{installed} = 0;
$result{signed} = 0;
my $dir = Irssi::get_irssi_dir();
my $ua = LWP::UserAgent->new(env_proxy => 1,keep_alive => 1,timeout => 30);
$ua->agent('ScriptAssist/'.$VERSION);
$ua->agent('ScriptAssist/'.2003020803);
my $request = HTTP::Request->new('GET', $site.'/scripts/'.$script.'.pl');
my $response = $ua->request($request);
if ($response->is_success()) {
my $file = $response->content();
mkdir $dir.'/scripts/' unless (-e $dir.'/scripts/');
local *F;
open(F, '>'.$dir.'/scripts/'.$script.'.pl.new');
print F $file;
close(F);
open(my $F, '>', $dir.'/scripts/'.$plname.'.new');
print $F $file;
close($F);
if ($have_gpg && Irssi::settings_get_bool('scriptassist_use_gpg')) {
my $ua2 = LWP::UserAgent->new(env_proxy => 1,keep_alive => 1,timeout => 30);
$ua->agent('ScriptAssist/'.$VERSION);
my $request2 = HTTP::Request->new('GET', $site.'/signatures/'.$script.'.pl.asc');
$ua->agent('ScriptAssist/'.2003020803);
my $request2 = HTTP::Request->new('GET', $site.'/signatures/'.$plname.'.asc');
my $response2 = $ua->request($request2);
if ($response2->is_success()) {
local *S;
my $sig_dir = $dir.'/scripts/signatures/';
mkdir $sig_dir unless (-e $sig_dir);
open(S, '>'.$sig_dir.$script.'.pl.asc');
open(my $S, '>', $sig_dir.$plname.'.asc');
my $file2 = $response2->content();
print S $file2;
close(S);
print $S $file2;
close($S);
my $sig;
foreach (1..2) {
# FIXME gpg needs two rounds to load the key
my $gpg = new GnuPG();
eval {
$sig = $gpg->verify( file => $dir.'/scripts/'.$script.'.pl.new', signature => $sig_dir.$script.'.pl.asc' );
$sig = $gpg->verify( file => $dir.'/scripts/'.$plname.'.new', signature => $sig_dir.$plname.'.asc' );
};
}
if (defined $sig->{user}) {
@ -975,13 +1019,13 @@ sub download_script ($$) {
if ($result{installed}) {
my $old_dir = "$dir/scripts/old/";
mkdir $old_dir unless (-e $old_dir);
rename "$dir/scripts/$script.pl", "$old_dir/$script.pl.old" if -e "$dir/scripts/$script.pl";
rename "$dir/scripts/$script.pl.new", "$dir/scripts/$script.pl";
rename "$dir/scripts/$plname", "$old_dir/$plname.old" if -e "$dir/scripts/$plname";
rename "$dir/scripts/$plname.new", "$dir/scripts/$plname";
}
return \%result;
}
sub print_check (%) {
sub print_check {
my (%data) = @_;
my $text;
my @table;
@ -1001,28 +1045,29 @@ sub print_check (%) {
print CLIENTCRAP draw_box('ScriptAssist', $text, 'check', 1) ;
}
sub toggle_autorun ($) {
sub toggle_autorun {
my ($script) = @_;
my ($sname, $plname) = get_names($script);
my $dir = Irssi::get_irssi_dir()."/scripts/";
mkdir $dir."autorun/" unless (-e $dir."autorun/");
return unless (-e $dir.$script.".pl");
if (check_autorun($script)) {
if (readlink($dir."/autorun/".$script.".pl") eq "../".$script.".pl") {
if (unlink($dir."/autorun/".$script.".pl")) {
print CLIENTCRAP "%R>>%n Autorun of ".$script." disabled";
return unless (-e $dir.$plname);
if (check_autorun($sname)) {
if (readlink($dir."/autorun/".$plname) eq "../".$plname) {
if (unlink($dir."/autorun/".$plname)) {
print CLIENTCRAP "%R>>%n Autorun of ".$sname." disabled";
} else {
print CLIENTCRAP "%R>>%n Unable to delete link";
}
} else {
print CLIENTCRAP "%R>>%n ".$dir."/autorun/".$script.".pl is not a correct link";
print CLIENTCRAP "%R>>%n ".$dir."/autorun/".$plname." is not a correct link";
}
} else {
symlink("../".$script.".pl", $dir."/autorun/".$script.".pl");
print CLIENTCRAP "%R>>%n Autorun of ".$script." enabled";
symlink("../".$plname, $dir."/autorun/".$plname);
print CLIENTCRAP "%R>>%n Autorun of ".$sname." enabled";
}
}
sub sig_script_error ($$) {
sub sig_script_error {
my ($script, $msg) = @_;
return unless Irssi::settings_get_bool('scriptassist_catch_script_errors');
if ($msg =~ /Can't locate (.*?)\.pm in \@INC \(\@INC contains:(.*?) at/) {
@ -1032,7 +1077,7 @@ sub sig_script_error ($$) {
}
}
sub missing_module ($$) {
sub missing_module {
my ($module) = @_;
my $text;
$text .= "The perl module %9".$module."%9 is missing on your system.\n";
@ -1041,7 +1086,7 @@ sub missing_module ($$) {
print CLIENTCRAP &draw_box('ScriptAssist', $text, $module, 1);
}
sub cmd_scripassist ($$$) {
sub cmd_scripassist {
my ($arg, $server, $witem) = @_;
my @args = split(/ /, $arg);
if ($args[0] eq 'help' || $args[0] eq '-h') {
@ -1083,27 +1128,34 @@ sub cmd_scripassist ($$$) {
}
}
sub sig_command_script_load ($$$) {
sub cmd_help {
my ($arg, $server, $witem) = @_;
$arg =~ s/\s+$//;
if ($arg =~ /^scriptassist/i) {
show_help();
}
}
sub sig_command_script_load {
my ($script, $server, $witem) = @_;
no strict;
$script = $2 if $script =~ /(.*\/)?(.*?)\.pl$/;
if ( %{ "Irssi::Script::${script}::" }) {
if (defined &{ "Irssi::Script::${script}::pre_unload" }) {
my ($sname, $plname, $pname, $xname) = get_names($script);
if ( exists $Irssi::Script::{$pname} ) {
if (my $code = "Irssi::Script::${pname}"->can('pre_unload')) {
print CLIENTCRAP "%R>>%n Triggering pre_unload function of $script...";
&{ "Irssi::Script::${script}::pre_unload" }();
$code->();
}
}
}
sub sig_default_command ($$) {
sub sig_default_command {
my ($cmd, $server) = @_;
return unless Irssi::settings_get_bool("scriptassist_check_unknown_commands");
bg_do('unknown '.$cmd);
}
sub sig_complete ($$$$$) {
sub sig_complete {
my ($list, $window, $word, $linestart, $want_space) = @_;
return unless $linestart =~ /^.script(assist)? (install|rate|ratings|update|check|contact|info|autorun)/;
return unless $linestart =~ /^.script(assist)? (install|rate|ratings|update|check|contact|info|autorun)/i;
my @newlist;
my $str = $word;
foreach (@complist) {
@ -1114,13 +1166,12 @@ sub sig_complete ($$$$$) {
foreach (@{loaded_scripts()}) {
push @newlist, $_ if /^(\Q$str\E.*)?$/;
}
$want_space = 0;
push @$list, $_ foreach @newlist;
Irssi::signal_stop();
}
Irssi::settings_add_str($IRSSI{name}, 'scriptassist_script_sources', 'http://scripts.irssi.org/scripts.dmp');
Irssi::settings_add_str($IRSSI{name}, 'scriptassist_script_sources', 'https://scripts.irssi.org/scripts.dmp');
Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_cache_sources', 1);
Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_update_verbose', 1);
Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_check_verbose', 1);
@ -1131,24 +1182,37 @@ Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_use_gpg', 1);
Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_integrate', 1);
Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_check_unknown_commands', 1);
Irssi::signal_add_first("default command", \&sig_default_command);
Irssi::signal_add_first('complete word', \&sig_complete);
Irssi::signal_add_first('command script load', \&sig_command_script_load);
Irssi::signal_add_first('command script unload', \&sig_command_script_load);
Irssi::signal_add_first("default command", 'sig_default_command');
Irssi::signal_add_first('complete word', 'sig_complete');
Irssi::signal_add_first('command script load', 'sig_command_script_load');
Irssi::signal_add_first('command script unload', 'sig_command_script_load');
if (defined &Irssi::signal_register) {
Irssi::signal_register({ 'script error' => [ 'Irssi::Script', 'string' ] });
Irssi::signal_add_last('script error', \&sig_script_error);
}
Irssi::signal_register({ 'script error' => [ 'Irssi::Script', 'string' ] });
Irssi::signal_add_last('script error', 'sig_script_error');
Irssi::command_bind('scriptassist', \&cmd_scripassist);
Irssi::command_bind('scriptassist', 'cmd_scripassist');
Irssi::command_bind('help', 'cmd_help');
Irssi::theme_register(['box_header', '%R,--[%n$*%R]%n',
'box_inside', '%R|%n $*',
'box_footer', '%R`--<%n$*%R>->%n',
]);
foreach my $cmd ( ( 'check', 'install', 'update', 'contact', 'search', '-h', 'help', 'ratings', 'rate', 'info', 'echo', 'top', 'cpan', 'autorun', 'new') ) {
foreach my $cmd ( ( 'check',
'install',
'update',
'contact',
'search',
# '-h',
'help',
# 'ratings',
# 'rate',
'info',
# 'echo',
# 'top',
'cpan',
'autorun',
'new' ) ) {
Irssi::command_bind('scriptassist '.$cmd => sub {
cmd_scripassist("$cmd ".$_[0], $_[1], $_[2]); });
if (Irssi::settings_get_bool('scriptassist_integrate')) {