## sBNC-Tools.Tcl
#
## Описание:
#	Данный скрипт позволяет Eggdrop'у работать с sbnc сервером, что позволяет:
#		- вести лог привата sbnc на указанный в настройках канал, а не читать флуд в привате ;)
#		- полноценно управлять сервером sBNC через публичные команды;
#		- выполнять долгие и рутинные действия "в два клика";
#	Движок скрипта продуман таким образом, чтобы любой мог добавить неограниченное кол-во своих уникальных команд или наборов команд.
#
## Полный список команд скрипта
## Все команды вводятся через префикс, указанный в переменной $sbnc(cmd.pref)
## Например: !bnc -rehash
#	-help (-h) - Помощь по командам скрипта.
#	-stats (-stat -s) - Статистика по пользователям BNC сервера.
#	-version (-vers -v) - Информация о версии скрипта.
#	-rehash (-r) - Отправить команду REHASH BNC серверу.
#	-add (-a) - Добавить пользователя на BNC сервер.
#	-del (-d) - Удалить пользователя с BNC сервера.
#	-uset - Установить настройки указанного пользователя.
#	-ujump - Реконнект указанного пользователя к IRC серверу.
#	-ujoin - Завести пользователя на указаный канал.
#	-upart - Закрыть указанный канал у пользователя.
#	-set - Установить настройки собственного аккаунта.
#	-jump - Реконнект к IRC серверу.
#	-global (-g) - Послать сообщение всем пользователям BNC сервера.
#	-motd (-m) - Установить MOTD на сервере.
#	-lock - Блокировка пользовательских опций.
#	-unlock - Разблокировка пользовательских опций.
#	-suspend - Блокировка аккаунта указанного пользователя.
#	-unsuspend - Разблокировка аккаунта указанного пользователя.
#	-pesetpass - Отсоединение пользователя от BNC.
#	-kill - Отсоединение пользователя от BNC.
#	-disconnect - Отсоединение аккаунта пользователя от IRC сервера.
#	-vuser - Просмотр списка пользователей, использующих определенный vhost.
#
## Обязательные требования к установке скрипта:
#	Eggdrop: 1.6.18-20;
#	TCL: 8.5.x;
#	sBNC: 1.2;
#	Скрипты для sbnc:
#		vhost.tcl, showusers.tcl, lock.tcl, vuser.tcl (http://files.chaters.ru/lumian/tcl/sbnc-tools/sbnc-scripts/)
#	Статус администратора на sBNC сервере;
#
## История версий:
#	0.1-0.6.5 by lumian
#		Не публичные девелоперские версии.
#
#	0.6.6 by lumian [16.05.2010]
#		Первая публичная версия.
#		Реализовано:
#			Вывод логов bnc сервера на специальный канал.
#			Возможность указывать префикс перед сообщениями в канал (полезно, если на канал идут логи с нескольких серверов).
#			Вывод статистики bnc сервера на канал по запросу.
#			Вывод помощи по командам скрипта.
#
#	0.6.7 by lumian [17.05.2010]
#		Добавлено:
#			Возможность делать rehash bnc серверу.
#			Возможность устанавливать настройки собственного аккаунта (!bncset).
#			Добавленние новых пользователей (с установкой realname и vhost).
#			Удаление пользователей.
#
#	0.6.8 by lumian [13.06.2010]
#		Изменено:
#			Небольшие фиксы по выдаваемому ботом тексту.
#			Стиль команд скрипта изменен на shell-like (!pref --<cmd> <arg>)
#		Добавлено:
#			Возможность указывать дефолтный реалнейм при создании нового юзера.
#			Возможность указывать дефолтный виртуальный хост при создании нового юзера.
#			Возможность переподключения к IRC серверу своего аккаунта.
#			Возможность устанавливать awaynick боту (было забыто в версии 0.6.7)
#			Возможность изменять настройки пользователей BNC сервера.
#			Возможность переподключения указанного пользователя.
#			Подробная помощь по командам: --add, --del, --set, --uset, --ujump.
#
#	0.7 by lumian [11.08.2010]
#		Изменения:
#			Полностью переписан движок обработки команд, в следствии чего стало намного удобнее добавлять обработку новых команд.
#			Убрана возможность указания RealName за ненадобностью (можно указать в настройках sbnc).
#			
#			Исправлена ошибка при логировании действия "Wrong password".
#			Добавлена возможность указывать IRC сервер при добавлении пользователя.
#			Добавлен default vhost (параметр "def" вместо <vhost>) при добавлении пользователя.
#			Добавлена генерация случайного цифрового пароля ботом и установка его на аккаунт пользователя.
#			Добавлен нотис от бота по завершению добавления пользователя с предоставлением информации о проделанной работе и пароле аккаунта.
#			Исправлена работа процедуры "userjump".
#
#	0.7.1 by lumian [20.08.2010]
#		Изменения:
#			Оптимизирован движок обработки входящих данных.
#			Добавлена возможность посылать глобальные сообщения.
#			Добавлена возможность устанавливать MOTD на сервере.
#			Добавлена разблокировка опций vhost и server перед их сменой администратором и блокировка после.
#			Добавлена возможность блокировки определенных опций пользователя администратором.
#			Добавлена возможность разблокировки определенных опций пользователя администратором.
#			Добавлено немного информативности при выполнении таких команд как: userjump,userjoin,userpart,adduser,deluser.
#			Добавлена обработка сообщения от -sBNC "G/K-line reason for user <user>:<reason>".
#			добавлена обработка сообщения от -sBNC "Blocked login attempt from <host> for user <user>".
#			Добавлена автоматическая очистка логов при их обнаружении.
#
#	0.7.2 by lumian [09.02.2011]
#		Изменения:
#			Добавлена возможность заморозки аккаунта.
#			Добавлена возможность разморозки аккаунта.
#			Добавлена возможность сбрасывать пароль аккаунта с автогенерацией нового пароля (посылается нотисом).
#			Добавлена возможность отсоединения пользователя от BNC сервера.
#			Добавлена возможность отсоединения аккаунта от IRC сервера.
#			Добавлена возможность включения/выключения поддержки IPv6 у пользователя и аккаунта бота.
#			Добавлена возможность устанавливать временную зону у пользователя и аккаунта бота.
#			Добавлена возможность просмотра пользователей с определенным vhost. (требуется sbnc скрипт vuser.tcl)
#
#			Добавлена обработка события "Error received for user <ident>:<reason>"
#			Добавлена обработка события "User <ident> has been suspended."
#			Добавлена обработка события "User <ident> has been unsuspended."
#			
#			Генерации пароля для команд resetpass и adduser вынесена в отдельную процедуру(::sbnc::genpass).
#			Все simul команды, теперь посылаются в приват к -sBNC ("simul <ident> :privmsg -sbnc :<cmd>", вместо "simul <ident> :sbnc <cmd>").
#			Исправлена ошибка "Неверный аргумент ()" при наборе команды без параметров. Теперь выводится предложение для просмотра помощи по скрипту.
#			Исправлена ошибка при выполненении команды unlock.
#			Общие косметические правки.
#
## Информация об авторе скрипта:
#	Ник:		lumian
#	IRC:		LifeNet: irc.chaters.ru (#chaters)
#				RusNet: irc.run.net (#eggdrop)
#	Email:		lumian@chaters.ru
#	Сайт:		www.chaters.ru
#
#	Так же, принимали участие в создании скрипта:
#		Идеи: Alex-@RusNet & Trusty@RusNet & Soldier@IrcCity
#		Помощь в написании скрипта: Vertigo@RusNet
#
#	>> Предложения по функционалу скрипта слать на email <<
#
##

namespace eval sbnc {}
foreach k [array names sbnc *] { catch {unset sbnc($k) } }

##
# Настройки скрипта:
##

## Настройки логирования:
# Канал для логирования сообщений.
# На данный канал будут валится ВСЕ логи sbnc, а так же управление sbnc через бота может быть осуществимо только на этом канале.
# В следствии вышенаписанного советую данный канал скрыть от публики.
set sbnc(chan)			"#services-bnc"
## Префикс сообщений на канале.
# Выводится в самом начале информационных сообщений скрипта на канал.
# Не используется при обращении к пользователю на канале.
set sbnc(chan.pref)		"\0037* De-2 *\017"

## Общие настройки:
# Публичная команда для работы скрипта (вместе с префиксом)
set sbnc(cmd.pref)		"*bnc"

## Настройка дефолтных значений:
## Дефолтный ip(vhost).
# Используется при выборе параметра 'def' как vhost при добавлении пользователя.
set sbnc(default.vhost)		"88.198.15.51"

## Команды скрипта:
# Принцип построения массива с командами скрипта.
#  Каждая новая группа - это новая команда. Внутри группы присутствует 3 или 4 блока в зависимости от команды.
# Описание блоков внутри группы:
#  1: Внутренний (системный) бинд на команду. Используется при передаче между процедурами и в поиске данных.
#  2: Список команд через пробел. Первая команда основные, 2я и более алиасы.
#  3: Описание команды. Используется в общем хелпе, а так же в краткой помощи при наборе команды без параметров.
#  4: Синтаксис команды. используется только в помощи по команде.
#
set sbnc(binds) {
	{ "help" "-help -h" "Помощь по командам скрипта." }
	{ "stat" "-stats -stat -s" "Статистика по пользователям BNC сервера." }
	{ "vers" "-version -vers -v" "Информация о версии скрипта." }
	{ "rehash" "-rehash -r" "Отправить команду REHASH BNC серверу." }
	{ "adduser" "-add -a" "Добавить пользователя на BNC сервер." "<ident> <vhost> <irc.server.net:6667>" }
	{ "deluser" "-del -d" "Удалить пользователя с BNC сервера." "<ident>"}
	{ "userset" "-uset" "Установить настройки указанного пользователя." "<ident> <setting> <arguments>" }
	{ "userjump" "-ujump" "Реконнект указанного пользователя к IRC серверу." }
	{ "userjoin" "-ujoin" "Завести пользователя на указаный канал." "<ident> <#chan>"}
	{ "userpart" "-upart" "Закрыть указанный канал у пользователя." "<ident> <#chan>"}
	{ "set" "-set" "Установить настройки собственного аккаунта." "<setting> <arguments>" }
	{ "jump" "-jump" "Реконнект к IRC серверу." }
	{ "glob" "-global -g" "Послать сообщение всем пользователям BNC сервера." "<message>"}
	{ "motd" "-motd -m" "Установить MOTD на сервере." "<motd>"}
	{ "lock" "-lock" "Блокировка пользовательских опций." "<ident> <option>"}
	{ "unlock" "-unlock" "Разблокировка пользовательских опций." "<ident> <option>"}
	{ "suspend" "-suspend" "Блокировка аккаунта указанного пользователя." "<ident> <reason>"}
	{ "unsuspend" "-unsuspend" "Разблокировка аккаунта указанного пользователя." "<ident>"}
	{ "resetpass" "-pesetpass -rsp" "Сброс пароля аккаунта указанного пользователя." "<ident>"}
	{ "kill" "-kill" "Отсоединение пользователя от BNC." "<ident>"}
	{ "disconnect" "-disconnect -dc" "Отсоединение аккаунта пользователя от IRC сервера." "<ident>"}
	{ "vuser" "-vuser" "Просмотр списка пользователей, использующих определенный vhost." "<ip>"}
}

##
# Основная часть скрипта.
#
# ДАЛЕЕ НИЧЕГО НЕ ТРОГАЙТЕ, ЕСЛИ НЕ ПОНИМАЕТЕ ЧТО ДЕЛАЕТЕ.
##

## Установка копирайтов:
set sbnc(inf)	{"sBNC-Tools" "0.7.2" "09.02.2011" "lumian" "www.chaters.ru/blog/eggdrop" }

## bind's
# - на все приватные сообщения
# - на команду, указанную в настройках
bind msgm - "*" ::sbnc::msgcheck
bind pub -|n $sbnc(cmd.pref) ::sbnc::pubcmd

## Процедура "препарирования" логов от sbnc
proc ::sbnc::msgcheck { nick host hand text } {
		global sbnc
		if ([string match "-sBNC" $nick]) {
			## Входы/выходы:
			if ([string match "*User*?*logged on*" $text]) { 
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) 3Вход: \002[lindex $text 1] ([lindex $text 5]\002"
				return 
			}
			if ([string match "*User*?*logged off*" $text]) { 
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) 4Выход: \002[lindex $text 1]\002. Подключений осталось: [lindex $text 4]"
				return 
			}
			## Создание/удаление/редактирование пользователей:
			if ([string match "*New user created:*?*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Пользователь [lindex $text 3] \037добавлен на сервер\037."
				return
			}
			if ([string match "*User removed:*?*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Пользователь [lindex $text 2] \037удален с сервера\037."
				return
			}
			if {[string match "*User *?* has been suspended.*" $text]} {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Аккаунт пользователя [lindex $text 1] \037заморожен\037."
				return
			}
			if {[string match "*User *?* has been unsuspended.*" $text]} {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Аккаунт пользователя [lindex $text 1] \037разморожен\037."
				return
			}
			## Ошибки:
			if ([string match "Wrong password for user *?*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Неверно введен пароль! \002Логин:\002 [lindex $text 4] (Хост: [lindex $text 6]"
				return 
			}
			if ([string match "*Login attempt for unknown user*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Неверный логин! \002Логин\002 [lindex $text 5] (Хост: [lindex $text 9])"
				return
			}
			if ([string match "*Blocked login attempt from *?*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Перебор паролей! \002Логин\002 [lindex $text 7] (Хост: [lindex $text 4]) Доступ заблокирован!"
				return
			}
			if ([string match "*Time*warp*detected*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Обнаружена деформация времени: [lindex $text 3] секунд."
				return
			}
			## IRC сервер (подключение/отключение/переподключение/ping timeout):
			if ([string match "*User*?*connected to an IRC server*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Пользователь [lindex $text 1] \037подключился\037 к IRC серверу."
				return
			}
			if ([string match "*User*?*disconnected from the server*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Пользователь [lindex $text 1] \037отключился\037 от IRC сервера."
				return
			}
			if ([string match "*Trying to reconnect to*?*for user*?*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Попытка соединения с IRC. Пользователь: [lindex $text 7]; Сервер: [lindex $text 4]"
				return
			}
			if ([string match "*An error occurred while connecting for user*?*: Connection timed out*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Пользователь [lindex $text 7] отключен от сервера: Ping Timeout"
				return
			}
			if ([string match "*G/K-line reason for user *?*:*?*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) G/K-Line ([lindex $text 4]): [lrange $text 5 end]"
				return
			}
			if ([string match "Error received for user *?*:*?*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Ошибка подключения пользователя [lindex $text 4] [lrange $text 5 end]"
				return
			}
			## Всякая хрень:
			if ([string match "*Rehashing TCL module*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Обновление конфигурации sBNC сервера: успешно!"
				return
			}
			if ([string match "Users using *?* as VHOST = *?*" $text]) {
				putserv "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Пользователи с VHOST [lindex $text 2]: [lrange $text 6 end]"
				return
			}
			## Статистика:
			if ([string match "*Total user count:*?*, logged on:*?*, connected to IRC: *?*, suspended:*?*" $text]) {
				putquick "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Статистика sBNC сервера:"
				putquick "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) Всего пользователей: [lindex $text 3] Соединены с IRC сервером: [lindex $text 10]"
				putquick "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) На связи: [lindex $text 6] Заблокировано: [lindex $text 12]"
				return
			}
			if ([string match "*You have new messages.*" $text]) {
				putquick "PRIVMSG -sBNC :erase"
				return
			}
		}
	}

## Процедура реакции на публичные команды и фильтрации их на существование.
# Если команда существует, то процесс направляется в процедуру ::sbnc::proccmds, которая начинает обработку данных.
# Если же команда не найдена, то юзир шлется куда подальше.
# Команды ищутся в массиве sbnc(binds)
proc ::sbnc::pubcmd { nick host hand chan text} {
		global sbnc
		if {$chan == $sbnc(chan)} {
			if {$text == ""} {
				putquick "NOTICE $nick :Центр управления sBNC."
				putquick "NOTICE $nick :Помощь по командам: $sbnc(cmd.pref) [lindex $sbnc(binds) 0 1 0]"
				return
			}
			set find [lindex $text 0]
			set sbnc(tmp.cmd.fnd) "0"
			foreach x $sbnc(binds) {
				if {[set y [lsearch [lindex $x 1] $find]] != -1} {
					set sbnc(tmp.cmd.fnd) "1"
					# Что-то вроде отладки :)
					#putserv "PRIVMSG $chan :$sbnc(chan.pref) Command found! \[Cmd: [lindex $text 0] | SysCmd: [lindex $x 0] \]. Go to procedure..."
					::sbnc::proccmds [lindex $x 0] $nick $host $hand $text
					break
				}
			}
			if {$sbnc(tmp.cmd.fnd) == "0"} {
				putserv "NOTICE $nick :\002$nick\002: Неверный аргумент (\002[lindex $text 0]\002)"
			}
		}
	}

## Процедура разбора полученных данных от пользователя.
# Тут происходит фильтрация полученных данных и их обработка (посыл в другую процеду или же моментальная обработка)
proc ::sbnc::proccmds { cmd nick host hand text } {
		global sbnc
		if {$cmd == "help"} {
			putserv "PRIVMSG $nick :\0035Помощь по командам центра управления sBNC\017"
			putserv "PRIVMSG $nick :\0035Префикс сообщений на канале:\017 $sbnc(chan.pref)"
			putserv "PRIVMSG $nick :\0035Синтаксис: \0034$sbnc(cmd.pref) <command>\017"
			foreach x $sbnc(binds) {
				if {[lrange [lindex $x 1] 1 end] != ""} {
					putserv "PRIVMSG $nick :  \0034[lindex $x 1 0] ([lrange [lindex $x 1] 1 end]) - \0035[lrange [lindex $x 2] 0 end]"
				} else {
					putserv "PRIVMSG $nick :  \0034[lindex $x 1 0] - \0035[lrange [lindex $x 2] 0 end]"
				}
			}
			putserv "PRIVMSG $nick :\0035Конец помощи.\017"
		}
		if {$cmd == "stat"} {
			putquick "PRIVMSG -sBNC :showusers"
		}
		if {$cmd == "vers"} {
			putquick "PRIVMSG $sbnc(chan) :$sbnc(chan.pref) [lindex $sbnc(inf) 0] Версия: [lindex $sbnc(inf) 1] | Дата последних изменений: [lindex $sbnc(inf) 2] | Автор: [lindex $sbnc(inf) 3]"
		}
		if {$cmd == "rehash"} {
			putquick "PRIVMSG -sBNC :tcl rehash"
			return
		}
		if {$cmd == "adduser"} {
			set ident "[lindex $text 1]"
			set vhost "[lindex $text 2]"
			set ircserv "[lindex $text 3]"
			if {$ident == "" || $vhost == "" || $ircserv == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG $sbnc(chan) :$nick: Начинаю добавление пользователя..."
			::sbnc::adduser $nick $ident $vhost $ircserv
			return
		}
		if {$cmd == "deluser"} {
			set ident "[lindex $text 1]"
			if {$ident == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG $sbnc(chan) :$nick: Выполняю удаление пользователя $ident с сервера..."
			::sbnc::deluser $ident
		}
		if {$cmd == "userset"} {
			set ident "[lindex $text 1]"
			set set "[lindex $text 2]"
			set arg "[lrange $text 3 end]"
			if {$ident == "" || $set == "" || $arg == "" } { ::sbnc::syntax $nick $cmd; return; }
			::sbnc::accuset $nick $ident $set $arg
			return
		}
		if {$cmd == "userjump"} {
			set ident "[lindex $text 1]"
			if {$ident == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG $sbnc(chan) :$nick: Переподключаю пользователя $ident к IRC серверу..."
			putquick "PRIVMSG -sBNC :simul $ident :privmsg -sbnc :jump"
			return
		}
		if {$cmd == "userjoin"} {
			set ident "[lindex $text 1]"
			set joinchan "[lindex $text 2]"
			if {$ident == "" || $joinchan == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG $sbnc(chan) :$nick: Команда отослана на сервер..."
			putquick "PRIVMSG -sBNC :simul $ident :join $joinchan"
		}
		if {$cmd == "userpart"} {
			set ident "[lindex $text 1]"
			set partchan "[lindex $text 2]"
			if {$ident == "" || $partchan == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG $sbnc(chan) :$nick: Команда отослана на сервер..."
			putquick "PRIVMSG -sBNC :simul $ident :part $partchan Request from BNC admin"
		}
		if {$cmd == "set"} {
			set set "[lindex $text 1]"
			set arg "[lrange $text 2 end]"
			if {$set == "" || $arg == "" } { ::sbnc::syntax $nick $cmd; return; }
			::sbnc::accset $nick $set $arg
			return
		}
		if {$cmd == "jump"} {
			putquick "PRIVMSG $sbnc(chan) :$nick: Выполняю переподключение к серверу."
			putserv "PRIVMSG -sBNC :jump"
			return
		}
		if {$cmd == "glob"} {
			set msg "[lrange $text 1 end]"
			if {$msg == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG $sbnc(chan) :$nick: Выполняю рассылку сообщения..."
			putquick "PRIVMSG -sBNC :global :\00312*** $msg\017"
			return
		}
		if {$cmd == "motd"} {
			set motd "[lrange $text 1 end]"
			if {$motd == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG $sbnc(chan) :$nick: Выполняю установку MOTD сообщения..."
			putquick "PRIVMSG -sBNC :motd $motd"
			return
		}
		if {$cmd == "lock"} {
			set ident "[lindex $text 1]"
			set option "[lindex $text 2]"
			if {$ident == "" | $option == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG $sbnc(chan) :$nick: Блокирую опцию \"$option\" у пользователя $ident"
			putquick "PRIVMSG -sBNC :lock $ident $option"
			return
		}
		if {$cmd == "unlock"} {
			set ident "[lindex $text 1]"
			set option "[lindex $text 2]"
			if {$ident == "" | $option == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG $sbnc(chan) :$nick: Снимаю блокировку с опции \"$option\" у пользователя $ident"
			putquick "PRIVMSG -sBNC :unlock $ident $option"
			return
		}
		if {$cmd == "suspend"} {
			set ident "[lindex $text 1]"
			set reason "[lrange $text 2 end]"
			if {$ident == "" | $reason == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG $sbnc(chan) :$nick: Выполняю заморозку аккаунта пользователя $ident..."
			putquick "PRIVMSG -sBNC :suspend $ident :$reason"
			return
		}
		if {$cmd == "unsuspend"} {
			set ident "[lindex $text 1]"
			if {$ident == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG $sbnc(chan) :$nick: Выполняю разморозку аккаунта пользователя $ident..."
			putquick "PRIVMSG -sBNC :unsuspend $ident"
			return
		}
		if {$cmd == "resetpass"} {
			set ident "[lindex $text 1]"
			if {$ident == ""} { ::sbnc::syntax $nick $cmd; return; }
			set pass [::sbnc::genpass]
			putquick "PRIVMSG $sbnc(chan) :$nick: Выполняю смену пароля пользователя $ident..."
			putquick "PRIVMSG -sBNC :resetpass $ident $pass"
			putquick "NOTICE $nick :Пароль для аккаунта $ident изменен на \"$pass\""
			return
		}
		if {$cmd == "kill"} {
			set ident "[lindex $text 1]"
			if {$ident == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG $sbnc(chan) :$nick: Выполняю отсоединение пользователя $ident от BNC сервера..."
			putquick "PRIVMSG -sBNC :kill $ident"
			return
		}
		if {$cmd == "disconnect"} {
			set ident "[lindex $text 1]"
			if {$ident == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG $sbnc(chan) :$nick: Выполняю отсоединение пользователя $ident от IRC сервера..."
			putquick "PRIVMSG -sBNC :disconnect $ident"
			return
		}
		if {$cmd == "vuser"} {
			set ip "[lindex $text 1]"
			if {$ip == ""} { ::sbnc::syntax $nick $cmd; return; }
			putquick "PRIVMSG -sBNC :vuser $ip"
			return
		}
	}

## Процедура выдачи информационного нотиса с описанием команды и ее синтаксисом.
# Используется процедурой ::sbnc::proccmds
# Что тут происходит:
#  на основе полученных данных от вышеупомянутой процедуры происходит поиск группы с командой в массиве sbnc(binds)
#  далее происходит "препарирование" и "окутывание" данных в удобочитаемый вид и выдача их пользователю.
proc ::sbnc::syntax { nick find } {
		global sbnc
		set a [lsearch -index 0 -all $sbnc(binds) $find]
		putquick "NOTICE $nick :[lrange [lindex $sbnc(binds) $a 2] 0 end]"
		putquick "NOTICE $nick :Синтаксис: $sbnc(cmd.pref) [lindex $sbnc(binds) $a 1 0] [lrange [lindex $sbnc(binds) $a 3] 0 end]"
	}

## Процедура генерации пароля. 
# Используется в командах adduser и resetpass.
# Описание: Генерация пароля и возвращение его обратно.
proc ::sbnc::genpass { } {
	global sbnc
	set sbnc(tmp.pass) [expr { int(10000000 * rand()) }]
	return $sbnc(tmp.pass)
}

## Процедура добавления пользователя.
# Тут происходит добавление нового пользователя на sbnc, а так же предварительная настройка аккаунта.
# Выдача администратору данных аккаунта.
proc ::sbnc::adduser {nick ident vhost ircserv} {
		global sbnc
		set pass [::sbnc::genpass]
		putquick "PRIVMSG -sBNC :adduser $ident $pass"
		if {$vhost == "def"} {
			putquick "PRIVMSG -sBNC :simul $ident :privmsg -sBNC :set vhost $sbnc(default.vhost)"
			set vhost $sbnc(default.vhost)
		} else {
			putquick "PRIVMSG -sBNC :simul $ident :privmsg -sBNC :set vhost $vhost"
		}
		putquick "PRIVMSG -sBNC :simul $ident :privmsg -sBNC :set awaynick $ident\[bnc\]"
		putquick "PRIVMSG -sBNC :simul $ident :privmsg -sBNC :set server $ircserv"
		
		putquick "PRIVMSG -sBNC :lock $ident server"
		putquick "PRIVMSG -sBNC :lock $ident vhost"
		putserv "NOTICE $nick :Аккаунт $ident создан. Пароль: \"$sbnc(tmp.pass)\". Установлен vhost: $vhost. Заблокированы опции: server, vhost."
	}

## Удаление пользователя.
# Вынесено в отдельную процедуру, т.к. 
# в будущем планируется выполнять еще несколько действий перед или после удаления аккаунта.
proc ::sbnc::deluser { ident } {
		global sbnc
		putquick "PRIVMSG -sBNC :deluser $ident"
	}

## Настройка пользовательских аккаунтов через бота.
# Что тут:
# Установка списка разрешенных настроек, выборка по полученным данным и изменение необходимых настроек.
proc ::sbnc::accuset {nick ident set arg} {
		global sbnc
		set sbnc(list.uset.cmd) { vhost server realname awaynick away awaymessage ipv6 timezone }
		if {[lsearch -inline $sbnc(list.uset.cmd) $set] != $set} { 
			putserv "NOTICE $nick :Указанной настройки ($set) не существует, либо ее модификация невозможна."
			putserv "NOTICE $nick :Возможные настройки: [lrange $sbnc(list.uset.cmd) 0 end]."
			return
		}
		if {$set == "vhost"} { 
			putserv "PRIVMSG -sBNC :unlock $ident vhost"
			putserv "PRIVMSG -sBNC :simul $ident :privmsg -sBNC :set vhost $arg"
			putserv "PRIVMSG -sBNC :lock $ident vhost"
		}
		if {$set == "server" } {
			putserv "PRIVMSG -sBNC :unlock $ident server"
			putserv "PRIVMSG -sBNC :simul $ident :privmsg -sBNC :set server $arg"
			putserv "PRIVMSG -sBNC :lock $ident server"
		}
		if {$set == "ipv6" } {
			if {$arg == "on" || $arg == "off" } {
				putserv "PRIVMSG -sBNC :simul $ident :privmsg -sBNC :set ipv6 $arg"
			} else {
				putserv "NOTICE $nick :Ошибка! Возможные параметры: on|off"
				return
			}
		}
		if {$set == "realname" }	{ putserv "PRIVMSG -sBNC :simul $ident :privmsg -sBNC :set realname $arg"		}
		if {$set == "awaynick" }	{ putserv "PRIVMSG -sBNC :simul $ident :privmsg -sBNC :set awaynick $arg"		}
		if {$set == "away" }		{ putserv "PRIVMSG -sBNC :simul $ident :privmsg -sBNC :set away $arg"			}
		if {$set == "awaymessage" }	{ putserv "PRIVMSG -sBNC :simul $ident :privmsg -sBNC :set awaymessage $arg"	}
		if {$set == "timezone" }	{ putserv "PRIVMSG -sBNC :simul $ident :privmsg -sBNC :set timezone $arg"		}
		putquick "PRIVMSG $sbnc(chan) :\002$nick\002: Настройка '$set $arg' для пользователя $ident установлена."
	}

## Настройка аккаунта бота.
# Что тут:
# Установка списка разрешенных настроек, выборка по полученным данным и изменение необходимых настроек.
proc ::sbnc::accset {nick set arg} {
		global sbnc
		set sbnc(list.set.cmd) { vhost server realname serverpass awaynick away awaymessage ipv6 timezone }
		if {[lsearch -inline $sbnc(list.set.cmd) $set] != $set} { putserv "PRIVMSG $sbnc(chan) :$nick: Указанной настройки ($set) не существует, либо ее модификация невозможна."; return; }
		if {$set == "vhost"}			{ putserv "PRIVMSG -sBNC :set vhost $arg" }
		if {$set == "server" }			{ putserv "PRIVMSG -sBNC :set server $arg" }
		if {$set == "realname" }		{ putserv "PRIVMSG -sBNC :set realname $arg" }
		if {$set == "serverpass" }		{ putserv "PRIVMSG -sBNC :set serverpass $arg" }
		if {$set == "awaynick" }		{ putserv "PRIVMSG -sBNC :set awaynick $arg" }
		if {$set == "away" }			{ putserv "PRIVMSG -sBNC :set away $arg" }
		if {$set == "awaymessage" }		{ putserv "PRIVMSG -sBNC :set awaymessage $arg" }
		if {$set == "timezone" }		{ putserv "PRIVMSG -sBNC :set timezone $arg" }
		if {$set == "ipv6" } {
			if {$arg == "on" || $arg == "off" } {
				putserv "PRIVMSG -sBNC :set ipv6 $arg"
			} else {
				putserv "NOTICE $nick :Ошибка! Возможные параметры: on|off"
				return
			}
		}
		putquick "PRIVMSG $sbnc(chan) :\002$nick\002: Настройка '$set $arg' установлена."
	}

## Вывод в лог
putlog "[lindex $sbnc(inf) 0] v.[lindex $sbnc(inf) 1]([lindex $sbnc(inf) 2]) by [lindex $sbnc(inf) 3] ([lindex $sbnc(inf) 4])"

