вторник, 14 октября 2008 г.

Linux. Чат-бот Рубик в виде LUA скрипта

Ура! Наконец-то! Я это сделал.
Мой чат-бот для DBhub'a был переписан с Perl'a на язык скриптов LUA. Отдельное спасибо за это форуму сайта www.lua.ru

За основу был взят чат-бот Кубик, которого я сначала хотел "проапгрейдить". В итоге это практически вышло, но влекло много минусов, вроде того, что база хранилась бы лишь в ОЗУ, что совершенно не интересно.

В итоге я реализовал его как и в Perl'e - может немного и коряво, но он работает, а это главное =)
Остальное можно поправить в процессе.

Итак, если у вас есть поддержка LUA-скриптов (например стоит PtokaX-хаб, хотя я так понял они где только не используются) - вы можете поставить себе "Рубика".
Копируете код в файл, сохраняете как "Rubik.lua" и вуаля! =)


***** Код *****

--[[
Rubik bot 0.5 для LUA
основан на коде полностью измененного Кубика
модифицировал TrenAr

История версий бота:
0.1 - Первый релиз! =)
0.2 - Теперь он "А?"кает и введена защита от пустых фраз
0.3 - Рубик перестал принимать фразы в базу, если они записаны в 2 и более строки. Иначе база слетала
0.4 - Из анализируемой фразы было выкинуто имя самого Рубика, что приводило к заеданию бота на какую-то фразу
0.5 - Повышен искуственный интеллект. Фразы с большим совпадением имеют приоритет при выборе ответа.

Версия для LUA 5.0.2 / 5.1.1 by NRJ

Сконвертировано под Lua 5.1.3 неизвестно кем :) Конвертер, отзовись ;)

Таблица trigs взята из одноименного скрипта перевода romiros'a
Поддержка русских букв взята из NOYELL script от NoNick'a

]]--

BotName = "Рубик" -- имя бота
BotDesc = "Обучаемый бот" -- описание бота
BotEmail = "" -- email бота

------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------

-- Таблица ников-исключений,чьи фразы бот не будет комментировоть (примеры ниже)
-- Фигня, она не работает, но нужна для работоспособности бота
TableName = {
["Админ"] = 1,
}

------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------

Rus={["А"]="а",["Б"]="б",["В"]="в",["Г"]="г",["Д"]="д",["Е"]="е",["Ё"]="ё",["Ж"]="ж",["З"]="з",["И"]="и",["Й"]="й",["К"]="к",["Л"]="л",["М"]="м",["Н"]="н",["О"]="о",["П"]="п",["Р"]="р",["С"]="с",["Т"]="т",["У"]="у",["Ф"]="ф",["Х"]="х",["Ц"]="ц",["Ч"]="ч",["Ш"]="ш",["Щ"]="щ",["Ъ"]="ъ",["Ы"]="ы",["Ь"]="ь",["Э"]="э",["Ю"]="ю",["Я"]="я"}

function OnStartup()
if (_VERSION == "Lua 5.1.1") or (_VERSION == "Lua 5.1") then
TableMaxSize = table.maxn
elseif (_VERSION == "Lua 5.0.2") then
TableMaxSize = table.getn
end

Core.RegBot(BotName,BotDesc,BotEmail,true)
end

function ChatArrival(curUser,data)
Core.GetUserAllData(curUser)

if TableName[curUser.sNick] ~=1 then if string.sub(data, 1, 1) then
data=string.sub(data,1,string.len(data)-1)
s,e,cmd,RestOfText = string.find( data, "%b<>%s+(%S+)%s+(.*)" )
if RestOfText == nil then
RestOfText = ""
s,e,cmd = string.find( data, "%b<>%s+(%S+)" )
end
end


s,e,mess = string.find(data, "^%b<>%s(.*)$")

-- Моё - проверка на наличие имени Рубика.
-- А также вероятность написать в чат, даже если ему ниче не пишут
-- It's work!
--
-- rndsay = math.random(1,35)
-- if (string.find( mess, "Рубик")) or (rndsay == 3) then
-- Сам пока писать не будет. Дабы не было глюков

if (string.find( mess, "Рубик")) then

-- Убираем имя Рубика
rubname = string.find( mess, "Рубик")
mymess=string.sub(mess , rubname + 6, string.len(mess))
-- Если имя написано с двоеточием
if (string.find( mess, "Рубик:")) then mymess=string.sub(mess , rubname + 7, string.len(mess)) end

-- Читаем базу на наличие вхождений фраз из неё в тексте пришедшего сообщения от юзера
-- Считаем кол-во вхождений
kol = 0
maxlen = 0
maxlensum = 0
maxlenansw = ""

local handle = io.open("RubikBase.txt","r")
if handle then
str1 = handle:read(65)
while str1 do
str2 = handle:read(129)
-- Отрезаем у строк "хвосты"
hvost1=string.find( str1, "%-%-%-")
str1=string.sub(str1 , 1, hvost1-1)
hvost2=string.find( str2, "%-%-%-")
str2=string.sub(str2 , 1, hvost2-1)
-- Если нашли str1 - плюсуем кол-во, ну и условия по макс.длине
if (string.find( mymess, str1)) then
kol = kol+1
if (string.len(str1) >= maxlen) then
maxlen = string.len(str1)
maxlenansw = str2
end
maxlensum = maxlensum + string.len(str1)
end
str1 = handle:read(65)
end
handle:close()
end

-- Второй проход по файлу. Выбираем рандомно ответ и задаём ответ по-умолчанию
answer = "А?"
-- Пробегаем 2 раз, только если kol>0
if (kol > 0) then
local handle = io.open("RubikBase.txt","r")
if handle then
str1 = handle:read(65)
while str1 do
str2 = handle:read(129)
-- Отрезаем у строк "хвосты"
hvost1=string.find( str1, "%-%-%-")
str1=string.sub(str1 , 1, hvost1-1)
hvost2=string.find( str2, "%-%-%-")
str2=string.sub(str2 , 1, hvost2-1)
-- Итак, выбор ответа
if (string.find( mymess, str1)) then
rnd = math.random(1,maxlensum)
if (rnd < answer =" str2" str1 =" handle:read(65)" answer ="="" answer =" maxlenansw" st =" string.find(" line1="string.sub(mymess" line2="string.sub(mymess"> 2 ) and ( string.len(line1) <> 2 ) and ( string.len(line2) < line1 =" line1.." line2 =" line2.." handle =" io.open("> Отделяем в фразе часть ДО " - " и ПОСЛЕ - строки line и line2 соответственно
-- Т.е. если нашли " - "
end


-- Ответ бота =)
Core.SendToAll("<"..curUser.sNick.."> "..cmd.." "..RestOfText)
Core.SendToAll("<"..BotName.."> "..curUser.sNick.." ".. answer )
return true

-- end к проверке на имя Бота в сообщении (которая It's work)
end

-- Дальше оригинальный код
-- Нда... очень оригинальный =)

end
end

***** Конец кода *****



* ВНИМАНИЕ *
Код, будучи выложен в общий доступ, заинтересовал одного замечательного товарища, с ником SCALOlaz. Ему понравилась идея и он стал её дорабатывать (после версии 0.5). И прикрутил к боту очень много всяких полезных дополнительных фич. Код, правда, выкладывать ему лень, но выложу я, ибо такое добро пропадать не должно. Поэтмоу настоятельно рекомендую использовать его код, а не мой.



***** Начало кода *****

--[[
Rubik bot для LUA
основан на коде полностью измененного Кубика
модифицировал TrenAr
после версии 0.5 модифицировал SCALOlaz

История версий бота:
0.1 - Первый релиз! =)
0.2 - Теперь он "А?"кает и введена защита от пустых фраз
0.3 - Рубик перестал принимать фразы в базу, если они записаны в 2 и более строки. Иначе база слетала
0.4 - Из анализируемой фразы было выкинуто имя самого Рубика, что приводило к заеданию бота на какую-то фразу
0.5 - Повышен искуственный интеллект. Фразы с большим совпадением имеют приоритет при выборе ответа.

Версия для LUA 5.0.2 / 5.1.1 by NRJ

Сконвертировано под Lua 5.1.3 неизвестно кем :) Конвертер, отзовись ;)

Таблица trigs взята из одноименного скрипта перевода romiros'a
Поддержка русских букв взята из NOYELL script от NoNick'a

0.6 [16/11/2008]
- Теперь бот выводит имя собеседника не постоянно
- База сохраняется четко в папке RUBIK скриптов
- Вместо "А?" всегда разные ответы на пустые фразы ( массив и переменная DefAnswers (Cat) )

0.9 [10/1/2009]
- Теперь бот настраивается операторами и админом (Имя, Описание, Автофлуд, Частота)
- Выводит фразы в чат самостоятельно
- ТеПеРь НеЗаВиСиМо от РеГиСтРа, отвечает сохраненными фразами
- Добавлен просмотр Базы (выдает в личку)

+- Возможность поиска по слову
+- Возможность удаления первого вхождения по слову

]]--

RubikBotName = "Зина" -- имя бота
-- RubikBotName = SetMan.GetString(21)
RubikBotDesc = "..." -- описание бота
RubikBotEmail = "" -- email бота
RubikBotKey = true -- Бот с ключом или без
RubikPatch = Core.GetPtokaXPath().."scripts/RUBIK/RubikBase.txt" -- added for highest API2

BotAutoAnswer = true -- Включить автоговорилку
BotStupid = 79 -- Генерация автоговорилки (не менее 2)
------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------
-- Таблица ответов по умолчанию, например на пустую фразу
DefAnswersCnt = 15 -- Всего ответов
DefAnswers = {
"Чиво?",
"К чему это все?..",
"Тебе это надо?",
"Ну и?",
"Непонимаю...",
"Пафтари",
"Эй! Убери грабли!",
"А?",
"Ась ?",
"Харош жмакать мой ник!",
":спряталсо:",
"Чо хател?",
"Хто тут?!!",
"Игнор",
"Слыш, выбери кого-нить другого и спрашивай"
}


-- Таблица ников-исключений,чьи фразы бот не будет комментировоть (примеры ниже)
-- Фигня, она не работает, но нужна для работоспособности бота
--TableName = {
-- ["Админ"] = 1,
--}
-- БОЛЬШЕ НЕ НУЖНА

--Rus={["А"]="а",["Б"]="б",["В"]="в",["Г"]="г",["Д"]="д",["Е"]="е",["Ё"]="ё",["Ж"]="ж",["З"]="з",["И"]="и",["Й"]="й",["К"]="к",["Л"]="л",["М"]="м",["Н"]="н",["О"]="о",["П"]="п",["Р"]="р",["С"]="с",["Т"]="т",["У"]="у",["Ф"]="ф",["Х"]="х",["Ц"]="ц",["Ч"]="ч",["Ш"]="ш",["Щ"]="щ",["Ъ"]="ъ",["Ы"]="ы",["Ь"]="ь",["Э"]="э",["Ю"]="ю",["Я"]="я"}
------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------

function OnStartup()
-- if (_VERSION == "Lua 5.1.1") or (_VERSION == "Lua 5.1") then
-- TableMaxSize = table.maxn
-- elseif (_VERSION == "Lua 5.0.2") then
-- TableMaxSize = table.getn
-- end

Core.RegBot(RubikBotName,RubikBotDesc,RubikBotEmail,RubikBotKey)
Core.SendToAll("<"..SetMan.GetString(21).."> --=============[ Скрипт "..RubikBotName.." был перезапущен: "..os.date("%d/%m/%y в %H:%M:%S").."! ]=============--")
end

function OpDisconnected(user) end
function UserDisconnected(user) end

function UserConnected(user)
Core.GetUserAllData(user)
RubikUserRightclicker(user,data)
end

function OpConnected(user)
Core.GetUserAllData(user)
RubikOpRightclicker(user,data)
end

function RubikUserRightclicker(user,data)
-- Core.SendToNick(user.sNick,"$UserCommand 1 3 Боты\\Информация по ботам$<%[mynick]> !botshelp||")
end

function RubikOpRightclicker(user,data)

Core.SendToNick(user.sNick,"$UserCommand 1 3 Боты\\"..RubikBotName.."\\Включить автофлуд$<%[mynick]> !rubickgoflood||")
Core.SendToNick(user.sNick,"$UserCommand 1 3 Боты\\"..RubikBotName.."\\Выключить автофлуд бота$<%[mynick]> !rubickstopflood||")
Core.SendToNick(user.sNick,"$UserCommand 0 3 Боты\\"..RubikBotName.."\\|")
Core.SendToNick(user.sNick,"$UserCommand 1 3 Боты\\"..RubikBotName.."\\Сводная информация$<%[mynick]> !rubickinfo||")
Core.SendToNick(user.sNick,"$UserCommand 1 3 Боты\\"..RubikBotName.."\\Посмотреть список фраз$<%[mynick]> !rubicklistbase||")

-- Core.SendToNick(user.sNick,"$UserCommand 1 3 Боты\\"..RubikBotName.."\\Удалить фразу$<%[mynick]> !rubdel %[line:Укажите номер строки]||")

if user.iProfile==0 or user.iProfile==1 then
-- if user.iProfile==0 then --тупо скроем менюшку от операторов и юзверей
Core.SendToNick(user.sNick,"$UserCommand 0 3 Боты\\"..RubikBotName.."\\|")
Core.SendToNick(user.sNick,"$UserCommand 1 3 Боты\\"..RubikBotName.."\\Изменить Имя$<%[mynick]> !rubickname %[line:Введите Новый Ник]||")
Core.SendToNick(user.sNick,"$UserCommand 1 3 Боты\\"..RubikBotName.."\\Изменить Описание$<%[mynick]> !rubickdesc %[line:Введите Новое Описание]||")
end

if user.iProfile==0 then
Core.SendToNick(user.sNick,"$UserCommand 1 3 Боты\\"..RubikBotName.."\\Частота флуда$<%[mynick]> !rubickrankingflood %[line:Укажите частоту флуда !ЧИСЛО (3-80)!]||")
end
end

function ChatArrival(curUser,data)
Core.GetUserAllData(curUser)
data=string.sub(data,1,string.len(data)-1)
local s,e,cmd=string.find(data,"%b<>%s+(%S+)")
cmd=string.sub(cmd,2)

if cmd=="rubicklistbase" and (curUser.iProfile==0 or curUser.iProfile==1) then

RubickBaseList = "Список фраз Базы:\r\n"
local RubickBaseLenght = 0
-- local handle = io.open("scripts/RUBIK/RubikBase.txt","r") --RubikPatch
local handle = io.open(RubikPatch,"r") --RubikPatch
-- local count = 0
if handle then
str1 = handle:read(65)
while str1 do
str2 = handle:read(129)
-- Отрезаем у строк "хвосты"
hvost1=string.find( str1, "%-%-%-")
str1=string.sub(str1 , 1, hvost1-1)
hvost2=string.find( str2, "%-%-%-")
str2=string.sub(str2 , 1, hvost2-1)
RubickBaseList=RubickBaseList.."\t"..RubickBaseLenght..":\t"..str1.." - "..str2.."\r\n"
RubickBaseLenght = RubickBaseLenght +1
str1 = handle:read(65)
end
handle:close()
end
Core.SendPmToNick(curUser.sNick,RubikBotName,RubickBaseList)
Core.SendPmToNick(curUser.sNick,RubikBotName,"Всего в Базе: "..RubickBaseLenght.." записей")
return true

--[[
elseif cmd=="rubdel" and (curUser.iProfile==0 or curUser.iProfile==1) then
local _,_,delnum=string.find(data,"(%d+)")
local delnumber = tonumber(delnum)

local handle = io.open(RubikPatch,"r")
local count = 0
local massive = ""
if handle then
str1 = handle:read(65)
while str1 do
str2 = handle:read(129)
if count ~= delnumber then
massive = massive..str1..str2
end
-- Отрезаем у строк "хвосты"
hvost1=string.find( str1, "%-%-%-")
str1=string.sub(str1 , 1, hvost1-1)
hvost2=string.find( str2, "%-%-%-")
str2=string.sub(str2 , 1, hvost2-1)
if count == delnumber then
Core.SendToNick(curUser.sNick,"<"..RubikBotName.."> Будет удалена фраза №"..count..": "..str1.." - "..str2.."")
end
count = count + 1
str1 = handle:read(65)
end
handle:close()
end
Core.SendPmToNick(curUser.sNick,RubikBotName,massive)
local handle = io.open("scripts/RUBIK/RubikBase2.txt","w+")
handle:write(massive)
handle:close()
return true
]]--

elseif cmd=="rubickgoflood" and (curUser.iProfile==0 or curUser.iProfile==1) then
BotAutoAnswer = true
Core.SendToNick(curUser.sNick,"*** Вы включили автофлуд бота. Теперь он будет говорить даже когда не просят.")
Core.SendToOps("<"..SetMan.GetString(21).."> <"..curUser.sNick.."> включил автофлуд бота <"..RubikBotName..">")

Core.SendToAll("<"..RubikBotName.."> *** Теперь я, бот '"..RubikBotName.."', буду общаться с вами даже если меня не просят!")

return true
elseif cmd=="rubickstopflood" and (curUser.iProfile==0 or curUser.iProfile==1) then
BotAutoAnswer = false
Core.SendToNick(curUser.sNick,"*** Вы отключили автофлуд бота. Он будет только отвечать на вопросы.")
Core.SendToOps("<"..SetMan.GetString(21).."> <"..curUser.sNick.."> выключил автофлуд бота <"..RubikBotName..">")

Core.SendToAll("<"..RubikBotName.."> *** Все, я молчу. Пока не спросите - ничего не скажу")



return true

elseif cmd=="rubickname" and (curUser.iProfile==0 or curUser.iProfile==1) then
local _,_,RubikNewName=string.find(data, "^%b<>%s(.*)$")
if RubikNewName ~= nil then
Core.UnregBot(RubikBotName)
Core.SendToNick(curUser.sNick,"*** Вы сменили Ник бота на '"..RubikNewName.."'")
Core.SendToOps("<"..SetMan.GetString(21).."> <"..curUser.sNick.."> сменил Ник бота <"..RubikBotName..">")

Core.SendToAll("<"..RubikBotName.."> *** Теперь меня зовут '"..RubikNewName.."'... Странно, в паспорте никаких отметок. ")
RubikBotName=RubikNewName
Core.RegBot(RubikBotName,RubikBotDesc,RubikBotEmail,RubikBotKey)
end
if RubikNewName == nil then
Core.SendToNick(curUser.sNick,"*** Ошибка! Вы не указали ник!")
end
return true

elseif cmd=="rubickdesc" and (curUser.iProfile==0 or curUser.iProfile==1) then
-- local _,_,RubikNewDesc=string.find(data,"%b<>%s+%S+%s+(%S+)")
local _,_,RubikNewDesc=string.find(data, "^%b<>%s(.*)$")
RubikNewDesc=string.sub(RubikNewDesc , 13, string.len(RubikNewDesc)) --13 - длина команды

if RubikNewDesc ~= nil then
Core.UnregBot(RubikBotName)
Core.SendToNick(curUser.sNick,"*** Вы сменили Описание бота на '"..RubikNewDesc.."'")
Core.SendToOps("<"..SetMan.GetString(21).."> <"..curUser.sNick.."> сменил описание бота <"..RubikBotName..">")

Core.SendToAll("<"..RubikBotName.."> *** Мое описание '"..RubikNewDesc.."'... Не поверите, я тоже в шоке от такого хамства!")
RubikBotDesc=RubikNewDesc
Core.RegBot(RubikBotName,RubikNewDesc,RubikBotEmail,RubikBotKey)
end
if RubikNewDesc == nil then
Core.SendToNick(curUser.sNick,"*** Ошибка! Вы не указали ник!")
end
return true

elseif cmd=="rubickrankingflood" and curUser.iProfile==0 then
local _,_,RubikRank=string.find(data,"(%d+)")
RubikRanking=tonumber(RubikRank)
-- Тут сука надо заставить его различать текст введен или число! Иначе сука крэшится

if (RubikRank ~= nil) then
if ((RubikRanking > 2) and (RubikRanking < 81)) then
Core.SendToNick(curUser.sNick,"*** Вы сменили относительную частоту флуда бота на '"..RubikRanking.."'")
Core.SendToOps("<"..SetMan.GetString(21).."> <"..curUser.sNick.."> сменил частоту флуда бота <"..RubikBotName.."> на '"..RubikRanking.."'")
BotStupid=RubikRanking
else
Core.SendToNick(curUser.sNick,"*** Ошибка! Неверный интервал! Укажите ЧИСЛО от 3 до 50-ти!")
end
else
Core.SendToNick(curUser.sNick,"*** Ошибка! Указан неверный параметр или параметр пропущен!")
end
return true

elseif cmd=="rubickinfo" then
RubikInfo = "<"..RubikBotName.."> Сводная информация о скрипте: \r\n"
RubikInfo=RubikInfo.."\t=========================================\r\n"
RubikInfo = RubikInfo.."\t- Имя бота: '"..RubikBotName.."'\r\n\t- Описание: '"..RubikBotDesc.."'\r\n"
if BotAutoAnswer == true then
RubikInfo=RubikInfo.."\t- Автофлуд: Включен\r\n"
else RubikInfo=RubikInfo.."\t- Автофлуд: Выключен\r\n"
end
if curUser.iProfile==0 then
RubikInfo=RubikInfo.."\t- Частота флуда: "..BotStupid.."\r\n\r\n"
RubikInfo=RubikInfo.."* Внимание! Частота указывается в относительной величине! В процессе опроса введённой строки рандомно выбирается число в интервале от 1 до Этого числа! При совпадении в районе +1 бот автоматически выдает фразу.\r\n"
-- RubikInfo=RubikInfo.."* Внимание! На данный момент в скрипте нет проверки на число или слово!!! Вводите ТОЛЬКО ЧИСЛАМИ, иначе скрипт упадет\r\n"
RubikInfo=RubikInfo.."\t=========================================\r\n"
Core.SendToNick(curUser.sNick,RubikInfo)
end
return true
end


-- if TableName[curUser.sNick] ~=1 then
if string.sub(data, 1, 1) then
-- data=string.sub(data,1,string.len(data)-1)
s,e,cmd,RestOfText = string.find( data, "%b<>%s+(%S+)%s+(.*)" )
if RestOfText == nil then
RestOfText = ""
s,e,cmd = string.find( data, "%b<>%s+(%S+)" )
end
-- end





s,e,mess = string.find(data, "^%b<>%s(.*)$")

-- Моё - проверка на наличие имени Рубика.
-- А также вероятность написать в чат, даже если ему ниче не пишут
-- It's work!


-- С этого момента он сам отвечает в чат
BotQuest = 0
if (string.find( mess, RubikBotName)) then BotQuest = 1 end

if (BotQuest == 0) and (BotAutoAnswer == true) then
rndsay = math.random(1,BotStupid)
if (rndsay > (BotStupid-1)) then
mess = RubikBotName..":"..mess
end
end
-- до этого момента


-- if (string.find( mess, "Рубик")) or (rndsay > (BotStupid-1)) then
-- Сам пока писать не будет. Дабы не было глюков


if (string.find( mess, RubikBotName)) then
mess = string.gsub(mess, "%%", "+" )
-- Убираем имя Рубика
rubname = string.find( mess, RubikBotName.."")
mymess=string.sub(mess , rubname + string.len(RubikBotName), string.len(mess))
-- Если имя написано с двоеточием
if (string.find( mess, RubikBotName..":")) then mymess=string.sub(mess , rubname + (string.len(RubikBotName)+1), string.len(mess)) end

-- Читаем базу на наличие вхождений фраз из неё в тексте пришедшего сообщения от юзера
-- Считаем кол-во вхождений
kol = 0
maxlen = 0
maxlensum = 0
maxlenansw = ""

-- local handle = io.open("scripts/RUBIK/RubikBase.txt","r")
local handle = io.open(RubikPatch,"r")

if handle then
str1 = handle:read(65)
while str1 do
str2 = handle:read(129)
-- Отрезаем у строк "хвосты"
hvost1=string.find( str1, "%-%-%-")
str1=string.sub(str1 , 1, hvost1-1)
hvost2=string.find( str2, "%-%-%-")
str2=string.sub(str2 , 1, hvost2-1)

--mymess - Сабж от юзверя
--str1 - Сабж в базе
mymess22=LowString(mymess)
str12=LowString(str1)

-- Если нашли str1 - плюсуем кол-во, ну и условия по макс.длине
if (string.find( mymess22, str12)) then
kol = kol+1
-- Core.SendToAll("<"..RubikBotName.."> Заявлено: " ..mymess22.." Найдено: ".. str1.. "." )

if (string.len(str1) >= maxlen) then
maxlen = string.len(str1)
maxlenansw = str2
end
maxlensum = maxlensum + string.len(str1)
end
str1 = handle:read(65)
end
handle:close()
end

-- Второй проход по файлу. Выбираем рандомно ответ и задаём ответ по-умолчанию
answreg = DefAnswers[math.random(1,DefAnswersCnt)]
answer = answreg
-- Пробегаем 2 раз, только если kol>0
if (kol > 0) then
-- local handle = io.open("scripts/RUBIK/RubikBase.txt","r")
local handle = io.open(RubikPatch,"r")

if handle then
str1 = handle:read(65)
while str1 do
str2 = handle:read(129)
-- Отрезаем у строк "хвосты"
hvost1=string.find( str1, "%-%-%-")
str1=string.sub(str1 , 1, hvost1-1)
hvost2=string.find( str2, "%-%-%-")
str2=string.sub(str2 , 1, hvost2-1)
-- Итак, выбор ответа

--mymess - Сабж от юзверя
--str1 - Сабж в базе
mymess22=LowString(mymess)
str12=LowString(str1)

if (string.find( mymess22, str12)) then
rnd = math.random(1,maxlensum)
if (rnd < string.len(str1)) then answer = str2 end
end
str1 = handle:read(65)
end
handle:close()
end
-- Если ни один ответ не выпал - берем тот, что самый длинный
if (answer == answreg) then answer = maxlenansw end
end

-----------
-- Тут пополнение базы. Если найдена фраза типа "Рубик: Молоко - Это не рыба", нужно добавить в файл с базой 2 строки: "Молоко" и "Это не рыба". Тогда Рубик в след.раз, увидив слово Молоко, скажет "Это не рыба".
-----------

-- Блок записи в файл.

-- Отделяем в фразе часть ДО " - " и ПОСЛЕ - строки line и line2 соответственно
if (string.find( mymess, " %- ")) then
st = string.find( mymess, " %- ")

line1=string.sub(mymess , 1, st-1)

line2=string.sub(mymess , st+3, string.len(mymess))

-- Если сообщения нормальной длины и в них нет символов \n и \r (перенос строки и возврат каретки), то фраза принимается
if ( string.len(line1) > 2 ) and ( string.len(line1) < 60) then
if ( string.len(line2) > 2 ) and ( string.len(line2) < 120 ) then
if not (( string.find( line1, "\n") ) or ( string.find( line1, "\r") )) then
if not (( string.find( line2, "\n") ) or ( string.find( line2, "\r") )) then

-- Пишем строки в файл.
-- Предварительно раздуем длину
while (string.len(line1)<64) do line1 = line1.."-" end
while (string.len(line2)<128) do line2 = line2.."-" end
--local handle = io.open("scripts/RUBIK/RubikBase.txt","a+")
local handle = io.open(RubikPatch,"a+")

handle:write(line1.."\n")
handle:write(line2.."\n")
handle:close()

end
end
end
end

-- End of -> Отделяем в фразе часть ДО " - " и ПОСЛЕ - строки line и line2 соответственно
-- Т.е. если нашли " - "
end


-- Ответ бота =)
Core.SendToAll("<"..curUser.sNick.."> "..cmd.." "..RestOfText)

rndanswnick = math.random(1,2)
if (rndanswnick == 2) then
Core.SendToAll("<"..RubikBotName.."> "..curUser.sNick..": "..answer )
else
Core.SendToAll("<"..RubikBotName.."> ".. answer )
end
return true

-- end к проверке на имя Бота в сообщении (которая It's work)
end

-- Дальше оригинальный код
-- Нда... очень оригинальный =)

end
end

function LowString(sData)
sData = sData:gsub("(.)", function ( s )
local iByte = s:byte()
if iByte >= 192 and iByte <= 223 then
iByte = iByte + 32
elseif iByte == 168 or iByte == 184 then --приведем Ё и ё к букве е
-- iByte = 184
iByte = 229
end
return string.char(iByte)
end)
return sData:lower()
end

***** Конец кода *****


Если вам помогла эта статья - оставьте комментарий! Они доступны даже не зарегистрированным пользователям.

За помощь в вопросе спасибо XNut.

Комментариев нет: