Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

MyDC.ru _ Технические вопросы по RusHub'у _ Запрос помощи или особенности плагиностроения для хаба

Автор: hjet 26.10.2012, 2:16

Я много и долго писал, но... устал, объясните, пожалуйста что не так со скриптом?

Код
sBot = Config.sHubBot
sHubTopic = "Добро пожаловать!"

function table.multiinsert(tTableLink, ...)
    for _, sWhat in ipairs({...}) do
        table.insert(tTableLink, sWhat)
    end
end

function OnStartup()
    sThisScriptDir = Core.sScriptsDir.."motd/"
    sHelloMsg = LoadText(sThisScriptDir.."connect.txt")
end

function OnUserEnter(UID)
    local tUser = UID
    local tToSend = {}
    local sHelloMsg = sHelloMsg:gsub("%[(%S+)%]", {
        nick = tUser.sNick,
        ip = tUser.sIP,
    })
    table.multiinsert(tToSend, "<", sBot, "> ", sHelloMsg, "|", "$HubTopic ", sHubTopic, "|")
    Core.SendToUser(UID, table.concat(tToSend))
end


test.lua:12: attempt to call global 'LoadText' (a nil value)

Код скопипастин из FirstRusHubBot.lua - изменения только в имени папки и имени файла. Путь к файлу connect.txt верен, файл с кодировкой ANSII, что не так? Собственно, все началось с желания показать текст из файла при OnUserConnected, а не после входа, но не удалось - скопипастил логику - nil, поставил вместо OnUserConnected обратно OnUserEnter, как в FirstRusHubBot.lua - все равно nil - на этом желание исчезло.

Заранее спасибо за помощь.

p.s. содержимое connect.txt - ПРЕВЕД [nick] [ip]!

Автор: Alexey 26.10.2012, 4:18

В скрипте происходит попытка вызвать функцию LoadText(), которой в нём нет. В FirstRusHubBot.lua эта функция подгружается из файла functions.lua. Либо подгружай этот файл и ты, либо просто скопируй её оттуда.

Автор: hjet 26.10.2012, 9:38

всё, спасибо! я разобрался откуда у меня изначально ошибки были, я после require "files" в теле функции писал LoadText вместо Files.LoadText... и тут понеслось extreme_sexy_girl.gif

Автор: hjet 2.11.2012, 13:51

Всем снова привет кхе.. кхе..
Выдалось у меня пару свободных часов и решил я, на старости лет, сделать покоряющий своей гениальностью, восхваляющий мое имя в века, в усладу миллионов страждущих скромный скрипт, идея которого сводится к простому... но, скачала предыстория:

Щавель со спиртом - русский вариант Махито

Введение
или как старый дед придумал, как убить пару вечерних часов

Есть у меня список дружественных хабов, туда входят хабы моего города + несколько хабов из пиринга (кто не в курсе что это или живет не в москве/подмосковье, то кратко - это локальная сеть между разными провайдерами - не играет роли где они находятся, в твоем городе или в соседнем, имеющими договоренность по обмену внутрисетевым трафиком, а еще короче для обывателя - халява). Итак, уже давно была у меня идея по автоматизации этого списка ну или хоть как то этот список обрабатывать или еще что-то - в те времена я еще не сформулировал свое желание (и трава была зеленее). Как вы могли понять по моим предыдущим сообщениям и темам, я очень краток в написании текстов и далек от какого-либо программирования, но, как говорится в русской народной пословице - глаза бояться, в лес не ходить. Поэтому я решил начать что-то делать и начал я опять с потрошения чужих скриптов и вылепливания некоего мутанта...

Часть 1
или как старый дед луну лепил и отвечал на свои же вопросы

Где мы будем хранить список хабов? Ну конечно не в Вологде, а в файле friendlyhubs.dat лежащему в папке data в папке скриптов (а то каждый скрипт пихает свои файлы dat куда попало, надо же порядок навести?). Что мы будем там хранить? Все что угодно (адрес сайта, имя админа, включен ли хаб, скольк юзеров на хабе, описание в свободном стиле и т.д. и т.п.), но для начала я добавил то, что необходимо - название, адрес, порт и статус:
Код
dFH = {
    [1] = {
        ['hName'] = 'Супер Хаб Деда Пердеда',
        ['hAddr'] = 'localhost',
        ['hPort'] = '411',
        ['hOnline'] = true,
    },
    [2] = {
        ['hName'] = 'Ахтун! 100500 бабок продакшн',
        ['hAddr'] = '127.0.0.1',
        ['hIp'] = '127.0.0.1',
        ['hPort'] = '412',
        ['hOnline'] = false,
    },
}

Создать - создали, теперь подключаем:

Код
dirData = Core.sScriptsDir.."data/" --папка с данными
dataFriendHub = dirData.."friendlyhubs.dat" --список хабов

Выводить мне этот список надо внутри файла motd после захода бабко-юзверя на мой деревенский хаб (мотды у меня специфические с уникальной разметкой в боевом стиле "вырви глаз"):

Код
»»    Дружественные хабы:
    [FriendHubsList]

»»    Мы рекомендуем вам добавить эти хабы в избранное. Хабы из этого списка проверены
    временем, одобрены другими пользователями, имеют схожие правила с нашим хабом и
    находятся под контролем адекватных и отзывчивых администраторов. Чтобы увидеть весь
    список хабов, наберите в чате !ВсеХабы или выберите в меню хаба
        » Помощь » Список хабов
    
»»    Вашего хаба нет в списке? Узнайте как сюда попасть набрав в чате !КакПопастьВСписокХабов
    или через меню хаба
        » Помощь » Как попасть в список хабов?

«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»

Как видите - вместо FriendHubsList будет список хабов + долгоиграющие планы по прикручиванию команд и меню... Продолжаем разговор... Подключаем этот мотд:

Код
dirMotd = Core.sScriptsDir.."motd/" --папка мотдов
motdEnter = Files.LoadText(dirMotd.."enter.txt") --мотд при входе на хаб

Теперь делаем вывод на экран от имени бота:

Код
require"files" -- подключем модуль работы с файлами
sBot = Config.sHubBot -- имя бота

-- делаем что-то при входе юзера на хаб (как видите у меня некая функция ReplaceTag с непонятным никому названием - о в следующей главе)
function OnUserEnter(UID)
    Core.SendToUser(UID, ReplaceTag(motdFriendHub, UID), sBot)
end


Самое легкое осталось позади...

Часть 2
или как старый дед велосипед придумывал

Функция ReplaceTag очень простая она подменяет по регулярке что мы ей напихаем:

Код
-- функция подстановки значений в текст
function ReplaceTag(inpute, UID)
    local message = inpute:gsub("%[(%S+)%]", {
        -- Инфо о юзере
        nick = UID.sNick, -- ник
        ip = UID.sIP, -- ip
        port = UID.iPortConn, -- порт
        realport = UID.iPort, -- реальный порт
        mac = UID.sMacAddress, -- мак-адрес
        
        -- Инфо о хабе
        hubname = Config.sHubName, -- имя хаба
        hubtopic = Config.sTopic, -- топик хаба
        onlineusers = Core.GetUsersCount(), -- юзеров онлайн
        
        -- Хаб лист
        FriendHubsList = FriendlyHubs(), -- список хабов
    })
    return message
end

Да чтож такое! Опять какая то функция FriendlyHubs! Что же она у меня делает (знатоки лунного языка, приготовьтесь - есть шанс пустить себе кровь из глаз):

Код
-- Список дружественных хабов
function FriendlyHubs()
    local result = ''
    local port = ''
    local link = ''

    if loadfile(dataFriendHub) then
        dofile(dataFriendHub)
        for key, value in pairs(dFH) do
            
            -- если порт не 411 - добавляем к ссылке порт
            if value['hPort'] ~= '411' then
                port = ':'..value['hPort']
            end
            
            -- если хаб онлайн - добавляем ссылку, а если нет - пошел нахрен
            if value['hOnline'] == true then
                link = 'dchub://'
            end

            result = result.."\n".."\t["..value['hName'].."]\t\t-\t"..link..value['hAddr']..port
        end
    end
    return result
end


Эпилог
или как старый дед вникал

Собираем это все в правильно последовательности и проверяем результат - все работает прекрасно. На этом моя плодотворная деятельность закончилась (но будет продолжена).

Зачем мне статус хаба? В силу своей необъятной любви к себе и своей врожденной скромности, я хотел бы еще скрипт, который можно было бы повесить в крон и 1 раз в час проверять статус хаба и обновлял файл friendlyhubs.dat... Вот такая вот еще идея...

Есть предложения по улучшению/оптимизации/доработке кода?

Автор: Saymon21 2.11.2012, 13:57

Цитата
friendlyhubs.dat

Но зачем? При наличии кучи баз данных.
Цитата
скрипт, который можно было бы повесить в крон и 1 раз в час проверять статус хаба

http://mydc.ru/topic4787.html
Предложения по улучшению кода:
Я бы не делал кучу конкатенаций, это раз.

Автор: hjet 2.11.2012, 14:15

Цитата(Saymon21 @ 2.11.2012, 13:57) *
Но зачем? При наличии кучи баз данных.

http://mydc.ru/topic4787.html
Предложения по улучшению кода:
Я бы не делал кучу конкатенаций, это раз.


кучи баз данных, это предложение перевести список хабов, например в мускуль?

кучу конкатенаций не делать, а как сформировать список при обходе таблицы в нужном мне виде? с табуляциями, переводами строк и вообще как обойти склейку из разных кусков в одну строку, а если строк много то как же их всех вывести без склеек? =)

з.ы. за ссыль на пингер спасибо, полез изучать как его прикрутить =)

Автор: Saymon21 2.11.2012, 14:28

Цитата
кучи баз данных, это предложение перевести список хабов, например в мускуль?

По желанию. Кроме мускла есть ещё дофига чего.

Цитата
кучу конкатенаций не делать, а как сформировать список при обходе таблицы в нужном мне виде? с табуляциями, переводами строк и вообще как обойти склейку из разных кусков в одну строку, а если строк много то как же их всех вывести без склеек? =)

Вместо
Код
result = result.."\n".."\t["..value['hName'].."]\t\t-\t"..link..value['hAddr']..port

Например так:
Код
result = result..("\n\t[%s]\t\t-\t%s%s%s"):format(value['hName'], link, value['hAddr'], port)

Автор: hjet 2.11.2012, 14:32

Цитата(Saymon21 @ 2.11.2012, 14:28) *
По желанию. Кроме мускла есть ещё дофига чего.


Вместо
Код
result = result.."\n".."\t["..value['hName'].."]\t\t-\t"..link..value['hAddr']..port

Например так:
Код
result = result..("\n\t[%s]\t\t-\t%s%s%s"):format(value['hName'], link, value['hAddr'], port)


ааа регулярки, как я вас люблю и почти понимаю =) спасибо! у меня мускуль есть и монгодб, видел где то лунный скрипт с мускулем связанный, найду, покопаюсь, авось разберусь =)
з.ы. а не, это вроде просто подмена в строке, надо погугли что за команда =)

Автор: hjet 3.11.2012, 20:51

Всем привет!

Мне на днях захотелось красоты и я решил немного доработать скрипт, выдающий "сейчас на хабе 100500 пользователей". Собственно вопрос - как правильно просклонять числительные?

Код
    -- склоняем пользователей к греху
    if Core.GetUsersCount() == 1 and Core.GetUsersCount() ~= 11 or string.sub(Core.GetUsersCount(), -1) == 1 then
        UserOnlineText = 'пользователь'
    else
        UserOnlineText = 'пользователей'
    end

Вроде работает корректно или не стоит так гемороиться и просто написать 'человек'? =))

з.ы. не продумал как обойти "22 пользователя" или 23 или 123 пользователя, а то не красиво 123 пользователей... красиво когда '1 пользователь', '123 пользователя', '78 пользователей' =)

Автор: Ksan 4.11.2012, 5:42

Пиши число последним в предложении:

Цитата
Сейчас на хабе пользователей - 123.
Сейчас на хабе пользователей - 121.
Сейчас на хабе пользователей - 22.
Сейчас на хабе пользователей - 78.
Сейчас на хабе пользователей - 100500.

Автор: Alexey 4.11.2012, 5:51

Код
local tForms    = {" пользователь", " пользователя", " пользователей"}
local tRule    = {1,2,2,2,3,3,3,3,3,[0]=3}

function GetForm(n)
    n = tostring(n)
    if tonumber(n:sub(-2,-2)) ~= 1 then
        return n..tForms[tRule[tonumber(n:sub(-1,-1))]]
    else
        return n..tForms[3]
    end
end

-- демонстрация
function OnStartup()
    for i=0,30 do
        Core.SendToAll(GetForm(i))
    end
end

Автор: hjet 4.11.2012, 11:46

Цитата(Ksan @ 4.11.2012, 5:42) *
Пиши число последним в предложении:

Сейчас на хабе пользователей - 123.
Сейчас на хабе пользователей - 121.
Сейчас на хабе пользователей - 22.
Сейчас на хабе пользователей - 78.
Сейчас на хабе пользователей - 100500.

собственно так оно везде и есть - скучно, серо и однообразно =)

Цитата(Alexey @ 4.11.2012, 5:51) *
Код
local tForms    = {" пользователь", " пользователя", " пользователей"}
local tRule    = {1,2,2,2,3,3,3,3,3,[0]=3}

function GetForm(n)
    if tonumber(tostring(n):sub(-2,-2)) ~= 1 then
        return n..tForms[tRule[tonumber(tostring(n):sub(-1,-1))]]
    else
        return n..tForms[3]
    end
end

-- демонстрация
function OnStartup()
    local sMsg = "\n"
    for i=0,30 do
        sMsg = sMsg..GetForm(i).."\n"
    end
    Core.SendToAll(sMsg)
end


Гениально! осталось только разобраться почему это работает =)))

Автор: hjet 11.11.2012, 16:38

Всем привет!

У меня на хабе отключены описание и теги у юзверей, т.е. описание пустое, а вот тег выглядит так - <V:,M:A,H:0/0/1,S:10> можно ли вообще не показывать тэг из списка юзверей, а инфо перенести в описание типо так:

Код
[Актив][1 Хаб][10 Слотов]
видел подобное на каком-то хабе

Автор: Alexey 12.11.2012, 1:45

Цитата(hjet @ 11.11.2012, 16:38) *
можно ли вообще не показывать тэг из списка юзверей, а инфо перенести в описание типо так:
Код
[Актив][1 Хаб][10 Слотов]

Сделать то можно, но какой в этом смысл?

Цитата(hjet @ 11.11.2012, 16:38) *
видел подобное на каком-то хабе

А я не видел, покажешь?

PS: Спасибо, Тём.

Автор: Артём 12.11.2012, 1:47

Alexey, ошибся ты, это тема RusHub ;)

Автор: hjet 11.12.2012, 3:46

Всем привет!
Поставил себе скрипт антимата и столкнулся с проблемой, связанной со скриптом истории чата - если антимат стоит после истории чата, то мат попадает в историю (что логично, но не приемлемо), но если его поставить перед историей чата (чтоб сначала обрабатывалось, а уж потом записывалось), то в историю чата вообще никакие сообщения не попадают =)

антимат (немного изменил в силу своих кривых рук, но и без изменения та же петрушка)

Раскрывающийся текст
Код
-------------------------------------------------
-- Название: Фильтр чата / ChatFilter.
-- Версия: 1.0
-- Автор версии для PtokaX 0.4.*.*: KoYoT.
-- Перевод под RusHub: Setuper.
-- Описание: Простой скрипт замены рекламы, мата и т. п.
-------------------------------------------------

-- Фразы замены.
Phrases = {
"*ой*", "*ай*", "*эй*", "*эх*", "*хммм*", "*уф*", "*бррр*", "*хо-хо*", "*опа*", "*ага*",
}

-- Что запрещаем.
Filter = {
"таблица с кучей всякого мата",
}
PhrasLen = #Phrases
FilterLen = #Filter

-------------------------------------------------
function OnChat(curUser,data)
    local _,_,sdata = string.find( data, "^%b<>%s(.*)$")
    local mat = nil
    if sdata then
        sdata2 = StringLower(sdata)
        for i = 1, FilterLen do
            if string.find( sdata2, Filter[i] ) then
                sdata2 = string.gsub(sdata2, Filter[i], Phrases[math.random(PhrasLen)])
                mat = true;
            end
        end
        if mat then
            Core.SendToAll("<"..curUser.sNick.."> ".. sdata2)
        else
            Core.SendToAll("<"..curUser.sNick.."> ".. sdata)
        end
        return true
    end
end

-------------------------------------------------
function StringLower(arg) -- Приводим текстовую строку в нижний регистр
    local res = ""
    local Byte, Len = nil, string.len(arg)
    arg = string.lower(arg)
    for i = 1, Len do
    Byte = string.byte(arg, i)
    if (Byte >= 192) and (Byte < 224) then
        Byte = Byte + 32
    end
    if (Byte == 168) or (Byte == 184) then Byte = 229 end -- убираем проблему с Ё
        res = res..string.char(Byte)
    end
    return res
end


история чата

Раскрывающийся текст
Код
--[[ Название: История чата
      Автор: STRELOK
      Версия: 2.1a (08.01.2011)
      Обсуждение скрипта: http://mydc.ru/topic2919.html
      Описание: Выводит последние n сообщений в чате при подключении пользователя к хабу
    Изменения:
        Версия 2.1a:
            * Поправка в регулярном выражении (команды для хаба при вводе заносились в лог)
        Версия 2.1:
            * Возможность включения логирования команд /+!me
            * Попралена ошибка, когда при кике с хаба пользователя последние сообщения выводились в статусную строку клиента
        Версия 2.0:
            * Лог чата сохраняется в файл (c) STRELOK
            * Изменён стиль вывода лога чата (c) STRELOK ]]--

sBot = Config.sHubBot    -- Имя бота
MSG_COUNT = 10        -- Кол-во вывода сообщений при входе
iMe = true            -- логирование команд /+!me

File = "Chat.dat"
Chat = {}
require "files"

sPath = Core.sScriptsDir.."ChatLog/"
sFile = sPath..File

function OnStartup()
    if loadfile(sFile) then
        dofile(sFile)
    end
end    

function OnChat(UID, sData)
    local sCmd = sData:match"%b<>%s+([!+/*]%S+)"
    if ((not sCmd or ((iMe) and (sCmd == "!me" or sCmd == "+me" or sCmd == "/me"))) or (sCmd == "[!+/]me")) and (not (sData:match("is kicking"))) then
        local HData = {
        os.date("[%H:%M:%S]"),
        sData,
        }
        table.insert(Chat, HData)
        if #Chat > MSG_COUNT then
        table.remove(Chat,1)
        end
    end
    Files.SaveTable(sFile, Chat, "Chat")
end

function GetChat(lines)
    local x = lines
    if lines > #Chat then
        x,lines = #Chat,#Chat
    end
    x = #Chat - x
    local okon = 'ие'
    if( lines == 1 ) then
        okon = 'яя фраза в чате'
    elseif(( lines >= 5 )) then
        okon = 'ие '..lines..' фраз в чате'
    elseif(( lines <= 4 )and( lines >= 2 )) then
        okon = 'ие '..lines..' фразы в чате'
    end
    local str = ""..string.rep(" ",0).."Последн"..okon
    for i,v in ipairs(Chat) do
        if i > x then
            str = str.."\r\n --- "..v[1].." "..v[2]
        end
    end
    if ( lines > 0 ) then
        return str.."\r\n"
    end
    return '';
end

function OnUserEnter(UID)
    if ( MSG_COUNT >= 1 ) then
        Core.SendToUser(UID, GetChat(MSG_COUNT), sBot)
    end
end


как быть? заранее спасибо =)

Автор: Alexey 11.12.2012, 13:30

Убрать из скрипта антимата блокировку всех сообщений.

Цитата(hjet @ 11.12.2012, 3:46) *
антимат (немного изменил в силу своих кривых рук, но и без изменения та же петрушка)

Нет такой петрушки с оригинальным скриптом.

Автор: Setuper 11.12.2012, 18:13

http://mydc.ru/r/?http://wiki.mydc.ru/%D0%A1%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D1%8F_Lua_API_%D0%B2_RusHub#OnChat