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

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

MyDC.ru _ Программирование на Lua _ Вопросы Разработчикам Скриптов

Автор: Wariner 8.7.2008, 19:59

Вот тут сижу сам кое как ковыряю скрипты и в некоторых моментах нужна помощь!!!!!
Так как Николя временно отсутствует хотелось бы найти знающего человека!!!!!!!!!!!!!
ОТЗОВИТЕСЬ still_dreaming.gif

Автор: Jaska 9.7.2008, 20:26

Чем тебе помочь друг мой? Я конечо не имею таких обширных знаний как Nickolya но кое что могу подсказать =) все-таки его ученик.

Автор: Wariner 10.7.2008, 14:15

Цитата(Jaska @ 9.7.2008, 21:26) *
Чем тебе помочь друг мой? Я конечо не имею таких обширных знаний как Nickolya но кое что могу подсказать =) все-таки его ученик.


да ничего глобального))) вопрос как опустить строку в нижний регистр?
msg=string.lower(msg) -- не помогает(((( точнее вроде работает как то не так(((
я видел как это используется например в антимате, но мне это не помогло...
например скрипт задаёт вопросы, ответы на них привязанны к "да"\"нет", но на "ДА"\"НЕТ" он уже не реагирует

Автор: Setuper 10.7.2008, 19:39

Код
function String2Lower( sText )
    local sReturn, iByte = ""
    if sText then
        sText = string.lower( sText )
        for i = 1, string.len( sText ) do
            iByte = string.byte( sText, i )
            if iByte > 191 and iByte < 224 then
                iByte = iByte + 32
            elseif iByte == 168 or iByte == 184 then
                iByte = 229
            end
            sReturn = sReturn..string.char( iByte )
        end
    end
    return sReturn
end

Автор: Wariner 10.7.2008, 20:13

Setuper, спасидо всё работает))) а почему не помогала просто надпись sText = string.lower( sText )
в некоторых скриптах при поиске мата например хватило только этой строчки!!!

Автор: Setuper 10.7.2008, 20:38

Wariner: вероятно вы не просекли фишку написанного мною тут скрипта!
Если бы вы просекли, то не задавали бы такой вопрос.

Объясняю:

функция string.lower - приводит строку символов с кодом от 0 до 128 к нижнему регистру;
в эти коды входят только латинские буквы и цифры, ну и некоторые спец-символы;
коды с 192 до 223 включительно отвечают заглавным русским буквам (не включая букву "Ё");
коды с 224 до 255 включительно отвечают соответствующим прописным русским буквам (не включая букву "ё");
смещение букв составляет 32;
код буквы "Ё" - 168;
код буквы "ё" - 184;
229 - это код буквы "е";
Как видно из кода (кому видно, а кому и нет), данная функция приводит буквы к нижнему регистру и убирает проблемы с буквой "Ё" и "ё", заменяя её на букву "е".

Думаю, что достаточно подробно объяснил работу функции)))

Автор: Wariner 10.7.2008, 21:31

Спс ответ исчерпывающий))) просто я ещё нуб и мне многое надо обэяснять очень подробно)))
Да и честно говоря не успел толком посмотреть что делает твой скрипт... просто впихнул его целеком в свой и всё заработало)))

PS:Впредь буду внимательнее

Автор: Wariner 10.7.2008, 21:40

и ещё вопросик local _,_,To,From,Message = string.find(data,"$To:%s+(%S+)%s+From:%s+%S+%s+$<(%S+)>%s+(.*)|")
Что значат выделенные символы ?!

Автор: Setuper 10.7.2008, 21:44

захват из строки

Автор: Wariner 11.7.2008, 7:52

Цитата(Setuper @ 10.7.2008, 22:44) *
захват из строки


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

Автор: Setuper 11.7.2008, 19:03

хочешь узнать ответ - читай мануал по lua.
я переписывать сюда мануал не собираюсь

Автор: fixx 7.8.2008, 12:38

API 2
Вот бьюсь над автозаменой:

Код
if     string.find(sData, "[dD][cC][hH][uU][bB][:][/][/]")
            then
            sData = string.gsub(sData , "[dD][cC][hH][uU][bB][:][/][/]", "АБРАКАДАБРА")

Это заменяет dchub:// на АБРАКАДАБРУ
А как мне заменить всю строку , в которой имеется dchub://, на АБРАКАДАБРУ?
чОй-то невыходит... =(
Это еще и поможет мне с АнтиВинампом..

оффтоп:
О, я уже учаснеГ =)

Автор: Setuper 7.8.2008, 14:19

все очень просто))))

Код
if     string.find(sData, "[dD][cC][hH][uU][bB][:][/][/]") then
            sData = string.gsub(sData , "[dD][cC][hH][uU][bB][:][/][/].*", "АБРАКАДАБРА")


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

Автор: fixx 7.8.2008, 15:31

Дело ТОЛЬКО в точке и звездочке?
Хм.. =)))))) да... я про это незнал, чесно )))
Спасибо!!!
Но так все, что написано ДО dchub:// будет отображаться..
Где ещё звездочку надо? =)
И, кстати, когда я что-то переделываю, я всегда пишу коменты (в тех строках, где понимаю), самые подробные, это помогает не забыть скрипт, а также помогает тем, кто еще хуже, чем я знает ЛУА =)
Предлагаю скриптописателям, коментировать каждую строку, тогда вопросов будет все меньше и меньше, а скриптов все больше =) Например:

Код
if not user.bOperator then -- Если не админ, то...
for i = 1,#trigs do -- фильтруем базар в соответствии со списком запретных слов

=)

Автор: Setuper 7.8.2008, 16:00

2fixx: http://mydc.ru/topic266.html?view=findpost&p=1526 думаю что после такого подробного объяснения все должны подружится с регулярными выражениями.

А ответ на твой вопрос еще легче)))))))

Код
if string.find(sData, "[dD][cC][hH][uU][bB][:][/][/]") then
            sData = "АБРАКАДАБРА"
end


и не надо ничего придумывать big_smile.gif

Автор: Wariner 8.8.2008, 17:24

Цитата(Setuper @ 11.7.2008, 20:03) *
хочешь узнать ответ - читай мануал по lua.
я переписывать сюда мануал не собираюсь


Хехе, всё таки пришлось написать still_dreaming.gif

Люди помогите пожалуйста, все мануалы которые нашёл на русском очень сложны для меня(во всяком случае не получается делать то что в них написанно beat_brick.gif ) Своё обучени бросил уже как пару недель назад, ибо просто бесит собственная тупость((( Помогите может есть у кого русский мануальчик с примерами... ОЧЕНЬ НАДО!!!

ps заранее благодарен

Автор: ustas 9.8.2008, 14:45

http://mydc.ru/r/?http://forum.proc.ru/index.php?showtopic=37035 подробно и с примерами

Автор: Wariner 18.8.2008, 12:18

Создание меню вроде очень простое дело но возник вопросик...
а как сделать так чтоб слово закрыть было самым нижним?

Автор: Setuper 18.8.2008, 12:42

Никак! Меню закрыть - это меню клиента, а не хаба, настраивается при написании клиента. Хочешь исправить? - бери исходники и правь сам.

Автор: Wariner 18.8.2008, 13:39

Цитата(Setuper @ 18.8.2008, 13:42) *
Никак! Меню закрыть - это меню клиента, а не хаба, настраивается при написании клиента. Хочешь исправить? - бери исходники и правь сам.


Хм... странно. Я пользуюсь токо флаем и точно на одном из хабов я видел эту фишку(там спросить не могу ибо не помню что за хаб)

Автор: Setuper 18.8.2008, 14:14

Хаха эта менюшка наверняка не закрывает окно, а просто разъединяет пользователя - такое сделать можно!
Вот код:

Код
bNewApi=true
function Main()
    bNewApi=false
end

function SendToUser(tUser,sMsg)
    if bNewApi then
        Core.SendToUser(tUser,sMsg)
    else
        tUser:SendData(sMsg)
    end
end

function UserConnected(tUser)
    SendToUser(tUser,"$UserCommand 1 3 Закрыть соединение$&# 36;Quit %[mynick]&# 124;")
end

NewUserConnected=UserConnected
OpConnected=UserConnected
RegConnected=UserConnected

В функции UserConnected не забудь убрать пробелы после "&#" (перед "36;" и перед "124;")!!!!!!!!

Для того, чтобы менюшка была последней, необходимо скрипт поставить последним в списке скриптов!

Автор: Wariner 18.8.2008, 19:05

Точно помню что менюшка закрывало окно... но тогда скриптами я не интересовался и не спросил(((

Автор: Setuper 18.8.2008, 22:16

средствами хаба никак нельзя закрыть окно клиента!!!

Автор: Wariner 18.8.2008, 22:34

Цитата(Setuper @ 18.8.2008, 23:16) *
средствами хаба никак нельзя закрыть окно клиента!!!


не, ты меня не понимаешь, просто меню которое посылает хаб вставлялось выше кнопки "закрыть" дц клиента

Автор: Setuper 18.8.2008, 22:52

Такого тоже не может быть. Контекстное меню устроено так, что в него добавляются менюшки ни сверху а снизу. Так устроено любое контекстное меню. Поэтому никак не получиться.

Автор: Wariner 19.8.2008, 11:36

Помогите написать функцию!!! Смысл её вот в чём:
Когда скрипт выводит ник юзера он должен быть определённой длинны. Т.е на хабе есть ограничение на длину ника(скажем 20 символов), при выводе ника скрипт считает колличество символов в нике и если оно меньше 20 добавляет в конце него нужное пробелов.

Автор: Setuper 19.8.2008, 11:45

Зачем это? Тупость какая то!
Программно этого сделать нельзя, то есть нельзя сделать так, чтобы сама программа PtokaX хранила в своей памяти список модифицированных ников. Можно только это сделать внутри скрипта, переопределяя вначале каждой функции поле sNick таблицы пользователя.

Автор: Wariner 19.8.2008, 16:41

Цитата(Setuper @ 19.8.2008, 12:45) *
Зачем это? Тупость какая то!


Смысл в том чтоб в таблицах со статистикой выводимых скриптами чатранкс и топхаберс ники сделать в первом столбце и при этом чтобы хоть чуть чуть уровнять столбцы

вот что то я сделал токо не работает(((
CODE
function getLenght(Name)
local Nick = Name
sLength = string.len(Nick)
if sLength < 20 then
tLength = 20 - sLength
end
for i =1, tLength do
Nick = Nick.." "
end
return Nick
end

что не так?

Автор: Setuper 19.8.2008, 20:15

Все верно сделал, но есть метод лучше.
Для выравнивания можно использовать табуляцию.

Автор: Wariner 19.8.2008, 20:22

Блин не работает(((( Я ставлю вывод с этой функцией и пусто((((

Прошу прощения сам разобрался))))

Автор: Wariner 20.8.2008, 10:52

вот есть это

Код
function ChatArrival(sUser,sData)
       sData = string.sub(sData,1,-2)
       local _,_,cmd =string.find(sData, "%b<>%s+(%S+)")
       if cmd == "!topranks" then
                     Core.SendToNick(sUser.sNick,"<"..gBot.."> "..ShowRanks(tRankingTable, 2))
                     return true
    end
end

и это
CODE
function ShowRanks(tQWERTY, number)
local tTemp = {}
for i,v in pairs(tQWERTY) do
table.insert(tTemp,{i,v})
end
table.sort(tTemp,function(a,b) return (a[2] > b[2]) end)
if number == 1 then
local disp = " ¤ Текущий Toп ранжирования ¤\r\n\r\n"
disp = disp.."\t№:\tНик:\t\t\tШара\r\n"
disp = disp.."\t»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«» «»«»«»«»«\r\n"
for i = 1,MaxShowed do
if tTemp[i] then
disp = disp..i..getLenght(tTemp[i][1])..getNormalShare(tTemp[i][2]).."\r\n"
end
end
disp = disp.."\t»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«» «»«»«»«»«\r\n"
end
if number == 1 then
local disp = " ¤ Текущий Toп ранжирования ¤\r\n\r\n"
disp = disp.."\t№:\tНик:\tОчки:\tРанг:\t\r\n"
disp = disp.."\t»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«» «»«»«»«»«\r\n"
for i = 1,MaxShowed do
if tTemp[i] then
disp = disp..i..getLenght(tTemp[i][1])..tTemp[i][2]..tFunctions.GetRankName(tTemp[i][2]).."\r\n"
end
end
disp = disp.."\t»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«» «»«»«»«»«\r\n"
end
return disp
end

выдаёт ошибку [11:43] Синтаксис Копия MyBoT.lua:xx: attempt to concatenate a nil value
где я ошибся?

Автор: Nickolya 20.8.2008, 11:04

Ошибка во 2 части кода, а именно:
1) два раза одно условие "if number == 1 then", исправь во втором на двойку big_smile.gif
2) конструкция

Код
if number == 1 then
    local disp = "текст"
end
return disp
вернет nil в свзяи с правилами видимости локальных переменных. Почитать можно про это тут: http://mydc.ru/r/?http://www.lua.ru/doc/2.6.html. А правильный код будет таким:

Код
local disp
if number == 1 then
    disp = "текст"
end
return disp

Автор: Wariner 24.8.2008, 18:29

Вот выкладываю кусок скрипта. Он должен при команде сохранять данные в таблицу, но есть какой то глюк... Толи есть какая то задержка сохранения толи не всегда срабатывает, так как я жму на менюшку, потом проверяю таблицу а в ней пусто((( что делать?

 Скрипт.lua ( 3.25 килобайт ) : 16
 

Автор: Setuper 24.8.2008, 18:54

Код
function AddFriends(Name, Friend)
    if not tFriends[Name] then
        tFriends[Name] = {}
    end
    if tFriends[Name][Friend] then
        Core.SendToNick(Friend, "<"..gBot.."> Вы уже являетесь другом "..Name)
    else
        tFriends[Name][Friend] = 1
        WriteFile(tFriends, "tFriends",gFriends)
    end
end

Автор: Wariner 24.8.2008, 20:33

Как можно забрать ник юзера вводящего команду(в функции ChatArrival) и запихнуть его в ToArrival... Не знаю насколько понятно написал, попробую ещё раз... Первый юзер вводит команду(ChatArrival) и второму отправляется запрос о подтверждении, если он подтверждает(ToArrival), ники заносятся в таблицу. Ник подтверждающего не проблема а того кто вводит команду... не понимаю как это сделать(((

Автор: Setuper 25.8.2008, 0:47

Вот своял под апи2, но на работоспособность не проверял!

CODE
function OnStartup()
sBot=SetMan.GetString(21)
iTime=60 --Время в минутах, в течение которого нужно отправить подтверждение
tTmp={}
tFriends={} --база друзей
TmrMan.AddTimer(60000,"ClearRequests")
end

function ChatArrival(tUser,sData)
sData=sData:sub(string.len(tUser.sNick)+4,-2)
local _,_,sCmd,sNick=string.find(sData,"[+!/](%S+)%s+(%S+).*")
if sCmd and sNick and sCmd=="friend" then
if sNick==tUser.sNick then
Core.SendToUser(tUser,"*** О боже... Что я вижу... Вы хотите подружиться с собой! Перед тем как подружиться с собой навестите психиатора.")
end
local tUs=Core.GetUser(sNick)
if tUs then
for i,v in pairs(tFriends) do
if v[1]==tUser.sNick and v[2]==sNick or v[2]==tUser.sNick and v[1]==sNick then
Core.SendToUser(tUser,"*** Вы с '"..sNick.."' уже являетесь друзьями!")
return true
end
end
if not tTmp[tUser.sNick] then
tTmp[tUser.sNick]={}
tTmp[tUser.sNick].sNick=sNick
tTmp[tUser.sNick].iTime=os.time()+iTime*60
if tTmp[sNick] and tTmp[sNick].sNick==tUser.sNick then
tTmp[sNick]=nil
tTmp[tUser.sNick]=nil
table.insert(tFriends,{tUser.sNick,sNick}
Core.SendToUser(tUser,"$To: "..tUser.sNick.." From: "..sBot.." $<"..sBot.."> "..
"Запрос подтвержден! Вы с '"..sNick.."' с данного момента являетесь друзьями")
Core.SendToUser(tUs,"$To: "..sNick.." From: "..sBot.." $<"..sBot.."> "..
"Запрос подтвержден! Вы с '"..tUser.sNick.."' с данного момента являетесь друзьями")
else
Core.SendToUser(tUser,"*** Запрос на поддержание дружбы с пользователем '"..sNick..
"' успешно отправлен. Ждите подтверждения!")
end
else
Core.SendToUser(tUser,"*** Запрос на поддержание дружбы уже был отправлен пользователю '"..sNick.."'")
end
Core.SendToUser(tUs,"$To: "..sNick.." From: "..sBot.." $<"..tUser.sNick.."> "..
"Поступил запрос на подтверждение дружбы. Для подтверждения отправьте в чат +friend "..tUser.sNick)
else
Core.SendToUser(tUser,"*** Пользователь '"..sNick.."' оффлайн!")
end
return true
end
end

function ClearRequests()
for i,v in pairs(tTmp) do
if os.time()>v.iTime then
tTmp[i]=nil
end
end
end

Автор: Wariner 25.8.2008, 9:31

Появились две ошибки:
[10:09] Синтаксис test.lua:6: bad argument #2 to 'AddTimer' (string expected, got function)
[10:10] Синтаксис test.lua:25: attempt to index field '?' (a nil value)
Честно говоря полностью так и не смог разобраться в работе скрипта... Он здесь полностью?

Автор: Setuper 25.8.2008, 11:50

Ошибки исправил.
Скрипт не полный. Я думаю, что тебе хватит знаний, чтобы дописать к нему менюшку, а также загрузку и сохранение таблицы tFriends

Автор: Wariner 25.8.2008, 15:00

[15:51] Синтаксис test.lua:27: attempt to call global 'time' (a nil value)
[15:51] Синтаксис test.lua:53: attempt to call global 'time' (a nil value)

time() - вроде это вызов функции, но такой функции в скрипте нет. Я правильно понял?

Автор: Setuper 25.8.2008, 16:44

os.time()

з.ы. писал на скорую руку и не тестил, так как мне такой скрипт не нужен))))

Автор: Wariner 26.8.2008, 11:25

Вот тут в одной теме просили написать скрипт статистики.... Написал... вроде всё правильно, но есть ошибка:не сохраняются данные в файл(не таблица), а ещё как наилучшим способом реализовать чтоб шара удалялась из таблицы если пользователь не был какое то время или поменял её.

 Statistics.lua ( 7.73 килобайт ) : 16
 

Автор: Setuper 26.8.2008, 12:07

папку Statistics создай!
что касается изменения шары, то это можно взять из хуббабота, там при входе сканируется и изменяется таблица топа шары и устанавливается время очистки

Автор: Wariner 26.8.2008, 15:09

Папка была!!! При первом запуске скрипта создаётся два нужных файла. В файл с таблицей запись идёт а в во второй нет(((

Автор: Setuper 26.8.2008, 15:37

во-первых, думаю, что следует написать так:

Код
local sSettings = "MaxUser = 0\r\nMaxUsersTime = 0\r\nMaxShara = 0\r\nMaxSharaTime = 0"
MaxUser,MaxUsersTime,MaxShara,MaxSharaTime = 0,0,0,0
local sHandle = io.open(gStat, "w+")
sHandle:write(sSettings)
sHandle:flush()
sHandle:close()

P.S. переменные MaxUser,MaxUsersTime,MaxShara и MaxSharaTime останутся в стеке скрипта.

во-вторых:
запись в этот файл производится по таймеру (каждые 30 секунд)
Код
TmrMan.AddTimer(30*1000,"UpdateHubStats")

Автор: Wariner 10.9.2008, 13:08

давненько уже сам ничего не делал вот тут нашли ещё один баг в вышеприведённом скрипте статистики!

CODE

gPath = Core.GetPtokaXPath():gsub("/", "\\").."scripts\\Statistics\\" -- основная папка скрипта
gStat = gPath.."Statistics.tbl" -- таблица max статистики
gShara = gPath.."Sharatop.tbl" -- таблица шары пользователей

tShara = {}

function OnStartup() -- функции которые выполняются при загрузке скрипта
if loadfile(gStat) ~= nil then
dofile(gStat)
Core.SendToAll("Файл найден")
else
local sSettings = "MaxUser = 0\r\nMaxUsersTime = 0\r\nMaxShara = 0\r\nMaxSharaTime = 0"
MaxUser,MaxUsersTime,MaxShara,MaxSharaTime = 0,0,0,0
local sHandle = io.open(gStat, "w+")
sHandle:write(sSettings)
sHandle:flush()
sHandle:close()
Core.SendToAll("Файл не найден")
end
end

Он всегда не находит файл(хотя он там есть) и при перезагрузке обнуляет всю стату((( в чём проблема

Автор: Setuper 10.9.2008, 15:00

попробуй так:

Код
gPath = "scripts\\Statistics\\"

Автор: Wariner 11.9.2008, 15:16

не помогло((( попробовал и так:gPath = "scripts\\Statistics\\" и так: gPath = "Statistics\\" Собственно у меня птока 0400 поэтому первый вариант и так не подходит! Когда файла нет, он пишет файл не найден и создаёт его, но когда в него вносятся какие то изменения при перезагрузке скрипта он опять пишет файл не найден и воссоздаёт его в первоначальном виде(((

Автор: Wariner 15.9.2008, 21:05

как создать папку если она прописана как

Код
gPath = Core.GetPtokaXPath():gsub("/", "\\").."scripts\\Hub files\\"

вроде это просто... черещ вот этот код
Код
        if os.execute("dir "..gPath) ~= 0 then
            os.execute("md "..gPath)    
        end

Автор: Setuper 15.9.2008, 21:07

не совсем верно

есть 3 ошибки:
1). Нафига использовать полный путь? Незачем выполнять лишние действия и писать Core.GetPtokaXPath():gsub("/", "\\")
Функция os.execute вызывает командную строку (командная строка вызывается из папки, где лежит файл PtokaX.exe), поэтому ошибочным будет загонять полный путь.
2). В аргументе команды md недопустимы пробелы.
3). Действие os.execute("md "..gPath) создает папку, если она еще не была создана до этого, поэтому действие if os.execute("dir "..gPath) ~= 0 then также бессмысленно.

В итоге надо написать так:

Код
local gPath = "scripts\\Hub_files"
os.execute("md "..gPath)

Автор: Wariner 16.9.2008, 22:34

А можно ли получить IP юзера по нику? Вот например когда делаем вот так:

CODE
function ChatArrival(sUser, sData)
sData = string.sub(sData,1,-2)
local _,_,cmd =string.find(sData, "%b<>%s+(%S+)")
if cmd == "!gagmainnick" then
local _,_,Nick = string.find(sData, "%b<>%s+%S+%s+(%S+)")
local IP = ???
end
end

если я напишу local IP = sUser.sIP, то IP будет присвоенно значение моего ип, а как сделать чтоб IP было равно айпишнику юзера с ником Nick?

И ещё вопросец, видемо к Setuper`у(ибо остальные куда то пропали) Ты был прав в скрипте гага я ошибся... Посмотри пожалуйста где я напортачил:
CODE
function ChatArrival...
if cmd == "!showgagmain" then
showgag(sUser, Main)
return true
end
if cmd == "!showgagpm" then
showgag(sUser, Pm)
return true
end

function showgag(sUser, tip)
local qwerty = nil
tNick = {}
tIP = {}
if tip == Main then
qwerty = "главном чате"
tNick = tGag.Main["Nick"]
tIP = tGag.Main["Ip"]
end
qwerty = "привате"
tNick = tGag.Pm["Nick"]
tIP = tGag.Pm["Ip"]
end
...
end

Почемуто когда нажиимаешь посмотреть заглушенных в мейне он всё равно показывает заглушенных в PM

Автор: Setuper 16.9.2008, 22:57

Код
function ChatArrival(sUser, sData)
    sData = string.sub(sData,1,-2)
    local _,_,cmd =string.find(sData, "%b<>%s+(%S+)")
    if cmd == "!gagmainnick" then
        local _,_,Nick = string.find(sData, "%b<>%s+%S+%s+(%S+)")
        local tUs=Core.GetUser(Nick)
        if tUs then
            local IP = tUs.sIP
        end
    end
end


Код
function ChatArrival...
    if cmd == "!showgagmain" then
        showgag(sUser, "Main")
        return true
    elseif cmd == "!showgagpm" then
        showgag(sUser, "Pm")
        return true
    end


function showgag(sUser, tip)
    local qwerty = nil
    tNick = {}
    tIP = {}
    if tip == "Main" then
        qwerty = "главном чате"
        tNick = tGag.Main["Nick"]
        tIP = tGag.Main["Ip"]
    elseif tip == "Pm" then
        qwerty = "привате"
        tNick = tGag.Pm["Nick"]
        tIP = tGag.Pm["Ip"]
    end
...
end

Автор: Wariner 17.9.2008, 20:06

Цитата(Setuper @ 15.9.2008, 22:07) *
3). Действие os.execute("md "..gPath) создает папку, если она еще не была создана до этого, поэтому действие if os.execute("dir "..gPath) ~= 0 then также бессмысленно.

не понимаю почему это действие бессмыслено, ведь dir это команда просмотра содержимого папки, поэтому если os.execute("dir "..gPath) ~= 0 (просмотр папки не удался), значит надо применять os.execute("md "..gPath). Или я не правильно понимаю?

А ещё
CODE
function ChatArrival(sUser, sData)
sData = string.sub(sData,1,-2)
local _,_,cmd =string.find(sData, "%b<>%s+(%S+)")
if cmd == "!gagmainnick" then
local _,_,Nick = string.find(sData, "%b<>%s+%S+%s+(%S+)")
local tUs=Core.GetUser(Nick)
if tUs then
local IP = tUs.sIP
end
end
end

не работает. Пишет что tUs равно nil(((

И ещё вопрос как сделать так чтоб изменение в скрипте применялись без перезагрузки. Т.е. если сделать переименование бота из меню чтобы после введения нового имении сразу становился с таким именем а не ждал перезагрузки скрипта

Автор: Setuper 18.9.2008, 11:52

Цитата(Wariner @ 17.9.2008, 21:06) *
не понимаю почему это действие бессмыслено, ведь dir это команда просмотра содержимого папки, поэтому если os.execute("dir "..gPath) ~= 0 (просмотр папки не удался), значит надо применять os.execute("md "..gPath). Или я не правильно понимаю?

Зачем просматривать содержимое папки, если команда os.execute("md "..gPath) создаёт папку в случае если она ещё не создана (в случае если папка уже создана команда ничего не делает). Просмотр содержимого папки - лишнее действие.

Цитата(Wariner @ 17.9.2008, 21:06) *
не работает. Пишет что tUs равно nil(((

Если пользователя с указанным ником не существует или он оффлайн, то будет nil. Данное действие применимо только к онлайн пользователям.

Цитата(Wariner @ 17.9.2008, 21:06) *
И ещё вопрос как сделать так чтоб изменение в скрипте применялись без перезагрузки. Т.е. если сделать переименование бота из меню чтобы после введения нового имении сразу становился с таким именем а не ждал перезагрузки скрипта

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

Автор: Wariner 18.9.2008, 18:23

Цитата(Setuper @ 18.9.2008, 12:52) *
Если пользователя с указанным ником не существует или он оффлайн, то будет nil. Данное действие применимо только к онлайн пользователям.

Это я понимаю и пробовал я на себе так что юзер по любому онлайн)))

Автор: Setuper 18.9.2008, 20:42

незнаю почему у тебя не пашет. может быть api1 у тя?

Автор: Wariner 18.9.2008, 21:25

Ну блин я же не совсем нуБ(ну во всяком случае не до такой степени)!!! still_dreaming.gif Все тесты провожу на птоке 0.4.0.0

Автор: Setuper 18.9.2008, 21:46

возможно ты нарушаешь правило локализации переменных

Код
function ChatArrival(sUser, sData)
    sData = string.sub(sData,1,-2)
    local _,_,cmd =string.find(sData, "%b<>%s+(%S+)")
    if cmd == "!gagmainnick" then
        local _,_,Nick = string.find(sData, "%b<>%s+%S+%s+(%S+)")
        local tUs=Core.GetUser(Nick)
        if tUs then
            local IP = tUs.sIP
//Тут IP ~= nil !!!
        end
//А тут уже IP == nil !!!
    end
end


Можно написать вот так:
Код
function ChatArrival(sUser, sData)
    sData = string.sub(sData,1,-2)
    local _,_,cmd =string.find(sData, "%b<>%s+(%S+)")
    if cmd == "!gagmainnick" then
        local _,_,Nick = string.find(sData, "%b<>%s+%S+%s+(%S+)")
        local tUs,IP=Core.GetUser(Nick)
        if tUs then
            IP = tUs.sIP
        end
    end
end

Автор: Wariner 18.9.2008, 22:12

да с локальной переменной IP я ошибся, но всё дело в том что до этого места кода реализация не доходит!

CODE

function ChatArrival(sUser, sData)
sData = string.sub(sData,1,-2)
local _,_,msg =string.find(sData, "(.*)")
local _,_,cmd =string.find(sData, "%b<>%s+(%S+)")
if cmd == "!gagmainfull" then
local _,_,Nick = string.find(sData, "%b<>%s+%S+%s+(%S+)")
if Nick ~= nil then
Core.SendToAll("="..Nick.."=") -- ВОТ ТУТ ПРОВЕРИЛ, NICK = НИК БЕЗ ПРОБЕЛОВ И ЛИШНИХ СИМВОЛОВ
local tUs = Core.GetUser(Nick) -- ЗДЕСЬ ОШИБКИ НЕТ(так как если ника нет то возвращает nil), ПОЭТОМУ
Core.SendToAll(tUs) -- ВОТ ТУТ ПИШЕТ СТРИНГ ЭКСПЕКТИД ГОТ НИЛ(извини что по русски) собственно дальнейший код в данной ситуации не важен
if tUs then
local IP = tUs.sIP
Core.SendToAll(IP)
if (tGag.Main.Nick[Nick] ~= 1) and (tGag.Main.Ip[IP] ~= 1) then
tGag.Main.Nick[Nick] = 1
tGag.Main.Ip[IP] = 1
WriteFile(tGag, "tGag", gGag)
Core.SendPmToNick(Nick, gBot, "Вы были заглушены и теперь не можете общаться в главном чате!")
Core.SendToAll("<"..gBot.."> Юзер с ником "..Nick.." и ip "..IP.." был заглушен и теперь не может общаться в главном чате! Наказал: "..sUser.sNick)
...

Автор: Setuper 18.9.2008, 22:23

Core.SendToAll(tUs) --так нельзя писать

tUs является таблицей.

Если хочешь проверить тип переменной, то надо написать так: Core.SendToAll(type(tUs))
Если хочешь проверить значение переменной, то напиши лучше так: Core.SendToAll(tostring(tUs))
В последнем случае в чат отправится адрес памяти, в котором хранится данная таблица.
Если тебе известен язык си или с++, то там существуют структуры или класса - это аналоги таблиц.

Автор: Wariner 19.9.2008, 9:29

Спасибо, разобрался))) Заработало)))

PS: других языков фактически не знаю... в школе проходили бейсик, сам пробовал изучать паскаль, в универе один семестр было "C". В итоге везде нахватал верхушек.... бывает же still_dreaming.gif

А вот ещё вопросец: а может ли быть в скрипте несколько функций OnTaimer() или как сделать так чтобы в одной этой функции выполнялось несколько действий с разным интервалом времени?

Автор: Setuper 19.9.2008, 10:36

в новом апи такая возможность есть. Делается так:

Код
nTimerInterval1=60000 -- 1 мин
nTimerInterval2=72000 -- 1.2 мин
nTimerInterval3=90000 -- 1.5 мин

TmrMan.AddTimer(nTimerInterval1, "func1")
TmrMan.AddTimer(nTimerInterval2, "func2")
TmrMan.AddTimer(nTimerInterval3, "func3")

function func1()
    SendToAll("timer 1")
end

function func2()
    SendToAll("timer 2")
end

function func3()
    SendToAll("timer 3")
end


для старого апи такую функцию надо писать самому)))

Автор: Wariner 3.10.2008, 21:29

думаю переходить обратно я не буду, dllку скомпилить тоже врядли смогу(во всяком случае на данном жизненом этапе) значит остаётся два варианта искать глюки в существующей либе и обходить их либо ждать чего то нового. Кстати над этим работы какие нибудь ведутся?

CODE
if ( cmd=="!profile" and user.iProfile ~= nil ) then
_,_,usernme = string.find( data, "%b<>%s+%S+%s+(%S+)" )
if usernme ~= nil then
if Core.GetUser(usernme,true) then
nme = Core.GetUser(usernme)
if usernme.iProfile ~= -1 then
nme = (ProfMan.GetProfile(Core.GetUser(nme.sNick)) and ProfMan.GetProfile(Core.GetUser(nme.sNick).sProfileName).iProfile) -- ошибка тут
Core.SendToNick(user.sNick,"*** Пользователь <"..bnick.."> имеет профиль "..nme)
return true
else
Core.SendToNick(user.sNick,"*** Пользователь <"..usernme.."> не зарегистрирован")
return true
end
else
Core.SendToNick(user.sNick,"*** Пользователь <"..usernme.."> оффлайн!")
return true
end
else
Core.SendToNick(user.sNick,"*** Ошибка! Вы не указали ник!")
return true
end
end


как должно быть правильно?
[22:28] Синтаксис thunder_newapi.lua:253: bad argument #1 to 'GetProfile' (string or number expected, got 3552855)

Автор: Setuper 3.10.2008, 21:45

Вроде вот так:

Код
if (cmd=="!profile" and user.iProfile) then
    local _,_,usernme=string.find(data,"%b<>%s+%S+%s+(%S+)")
    if usernme then
        local nme=Core.GetUser(usernme)
        if nme then
            if nme.iProfile~=-1 then
                Core.SendToNick(user.sNick,"*** Пользователь <"..usernme.."> имеет профиль "..
                ProfMan.GetProfile(nme.iProfile).sProfileName)
            else
                Core.SendToNick(user.sNick,"*** Пользователь <"..usernme.."> не зарегистрирован")
            end
        else
            Core.SendToNick(user.sNick,"*** Пользователь <"..usernme.."> оффлайн!")
        end
    else
        Core.SendToNick(user.sNick,"*** Ошибка! Вы не указали ник!")
    end
    return true
end

Автор: Wariner 6.10.2008, 15:40

Код
        sMsg = sMsg:gsub("<!\[CDATA\[", " ")
        sMsg = sMsg:gsub("\]\]>", " ")


пишет [16:38] Синтаксис Bash_API2.lua:94: malformed pattern (missing ']')
я понимаю что это квадратные скобки но вроде я посттавил перед ними "\" Что не так?

Автор: Nickolya 6.10.2008, 15:42

Читай про магические символы, неужели забыл что перед ними не \ а % ставится?)
Мой открытый вариант скрипта ковырял?? http://mydc.ru/topic396.html?view=findpost&p=2828

Автор: Wariner 6.10.2008, 15:48

Цитата(Nickolya @ 6.10.2008, 16:42) *
Читай про магические символы, неужели забыл что перед ними не \ а % ставится?)

да с этим я что то тупанул...
Цитата(Nickolya @ 6.10.2008, 16:42) *
Мой открытый вариант скрипта ковырял?? http://mydc.ru/topic396.html?view=findpost&p=2828

я его посмотрел... во первых там в папке два файла с закрытым кодом, во вторых не дорос я ещё до таких скриптов... наверно

Автор: Nickolya 6.10.2008, 15:50

Файл Core.lua - с открытым кодом! Вроде не так уж и сложно всё там...
Строка 87:

Код
            local _,_, sData = string.find(sDescription, "<!%[CDATA%[(.*)%]%]")

Автор: Wariner 6.10.2008, 15:52

ладно может покапаюсь, а щас побежал на тренировку)))))

Автор: Wariner 13.10.2008, 19:38

2Setuper: Илюх, ты где то писал про сиистему(начальных букв у переменных), помоему венгерскую, но я что то потерял темку в которой ты это отписывал((( Можешь продублировать ещё раз?(поис мне не помог beat_brick.gif )

Автор: Nickolya 13.10.2008, 19:59

Странно, но я нашел в поиске: http://mydc.ru/ipb.html?s=&showtopic=315&view=findpost&p=2068

Автор: Setuper 13.10.2008, 20:04

Называется венгерская нотация)))))

Код
s - string
i - integer
n - number
l - long
b - boolean
p - pointer
h - handle
C - class
T - type
t - table
mt - metatable


В lua можно использовать следующие:
Код
s - string
i - integer
b - boolean
h - handle
t - table
mt - metatable


(iShareSize, bConnected, hFile, tTable, mtTable)

http://mydc.ru/ipb.html?s=&showtopic=315&view=findpost&p=2068

Автор: Wariner 14.10.2008, 18:53

в чём тут ошибка?

Код
function UserDisconnected(tUser)
    tUser[tUser.sIP].OffData = os.date("%d.%m.%Y %H:%M:%S")
    WriteTable(tUsers, "tUsers", sUser)
end


Синтаксис ххх.lua:46: attempt to index field '?' (a nil value)

Автор: Nickolya 14.10.2008, 19:31

В таблице tUser нет таблицы равной его ip: tUser[tUser.sIP] = nil, а ты пытаешься в такой таблице создать поле OffData, надо сначала объявить таблицу: tUser[tUser.sIP] = {}, или сразу поле в ней: tUser[tUser.sIP] = {OffData = os.date("%d.%m.%Y %H:%M:%S"),}

Автор: Wariner 14.10.2008, 20:20

таблица создаётся в функции юзерконнектед, выглядит так

CODE
tUsers = {
["10.2.100.240"] = {
["Nick"] = "-=Wariner=-",
["Shara"] = 12100841835,
["Msg"] = 0,
["OffData"] = 0,
["Downloads"] = 0,
["BanTop"] = 0,
["Ban"] = 0,
["OpBanTop"] = 0,
["GagTop"] = 0,
["Seach"] = 0,
["OpGagTop"] = 0,
["OldNick"] = {
},
["IP"] = "10.2.100.240",
},
}


после чего идёт описаный выше код, но дальше ошибка

Автор: Sephiroth_Lukaw 14.10.2008, 21:22

Цитата(Wariner @ 14.10.2008, 18:53) *
tUser[tUser.sIP].OffData = os.date("%d.%m.%Y %H:%M:%S")
Может ты тут tUsers имеешь в виду...?

Цитата
WriteTable(tUsers, "tUsers", sUser)
А переменная sUser откудо?...
Да и в WriteTable ты tUser никак не используешь...

Автор: Wariner 14.10.2008, 21:30

2Sephiroth_Lukaw: вот код

CODE
sBot = "Protector"

function OnStartup()
sPath = Core.GetPtokaXPath():gsub("/", "\\").."scripts\\Protector\\"
sData = sPath.."Data\\"
sText = sPath.."Text\\"
sUser = sData.."User.tbl"
...

function UserConnected(tUser)
Core.GetUserAllData(tUser)
local Shara = tUser.iShareSize or 0
if tUsers[tUser.sIP] == nil then
tUsers[tUser.sIP] = {}
...
tUsers[tUser.sIP].OffData = 0
WriteTable(tUsers, "tUsers", sUser)
end
end

OpConnected = UserConnected
RegConnected = UserConnected

function UserDisconnected(tUser)
tUser[tUser.sIP].OffData = os.date("%d.%m.%Y %H:%M:%S") -- вот тут ошибка
WriteTable(tUsers, "tUsers", sUser)
end

OpDisconnected = UserDisconnected
RegDisconnected = UserDisconnected

function WriteTable(tTable, tablename, file)
local handle = io.open(file, "w")
Serialize(tTable, tablename, handle)
handle:close()
end

function Serialize(tTable, sTableName, hFile, sTab)
sTab = sTab or "";
hFile:write(sTab..sTableName.." = {\n" );
for key, value in pairs(tTable) do
local sKey = (type(key) == "string") and string.format("[%q]",key) or string.format("[%d]",key);
if(type(value) == "table") then
Serialize(value, sKey, hFile, sTab.."\t");
else
local sValue = (type(value) == "string") and string.format("%q",value) or tostring(value);
hFile:write(sTab.."\t"..sKey.." = "..sValue);
end
hFile:write(",\n");
end
hFile:write(sTab.."}");
end


если не всё ещё понятно объясню подробнее

Автор: Sephiroth_Lukaw 14.10.2008, 21:47

Ну, если ты сделаешь как сказал Nickolya, то ошибка в той строчке биться не должна...хотя не вижу в ней никакого смысла если честно) т.к. tUser всё-равно локальна и ты её больше нигде не используешь в данной функции..

Автор: Setuper 14.10.2008, 22:10

Код
function UserDisconnected(tUser)
  if tUsers[tUser.sIP] then
    tUsers[tUser.sIP].OffData = os.date("%d.%m.%Y %H:%M:%S")
  end
  WriteTable(tUsers, "tUsers", sUser)
end

Автор: Wariner 14.10.2008, 22:17

2Sephiroth_Lukaw я тебя не понимать.... still_dreaming.gif
2Setuper спасибо

Автор: Nickolya 14.10.2008, 22:27

Цитата
tUser[tUser.sIP].OffData = os.date("%d.%m.%Y %H:%M:%S") -- вот тут ошибка

Да, тут ошибка big_smile.gif и ошибка как всегда глупая, подумай сам:
Код
tUsers[tUser.sIP].OffData = 0
tUser[tUser.sIP].OffData = os.date("%d.%m.%Y %H:%M:%S")

Думаю разница теперь заметна big_smile.gif

ЗЫ: я тормоз laughing.gif

ЗЗЫ: слишком сложно и накладно для самого человека показать человеку как надо делать, легче и полезнее заставить его думать big_smile.gif

Автор: Setuper 14.10.2008, 22:40

Думаю тут и думать не над чем. Просто невнимательность и описка)))
Скорее всего это часть скрипта автора, поэтому всё уже продумано было)))

Автор: Wariner 15.10.2008, 11:18

просто сначала сделал таблицу tUser но из-за Core.GetUserAllData(tUser) в неё заносилось много лишнего, поэтому исправил везде на tUsers. А в том месте не обратил внимание beat_brick.gif

Автор: Wariner 16.10.2008, 19:41

опять же тот же самый код

CODE
function OnStartup()
sPath = Core.GetPtokaXPath():gsub("/", "\\").."scripts\\Protector\\"
sData = sPath.."Data\\"
sText = sPath.."Text\\"
sUser = sData.."User.tbl"
if loadfile(sUser) then
dofile(sUser)
end
tUsers = {}
end
function UserConnected(tUser)
Core.GetUserAllData(tUser)
local Shara = tUser.iShareSize or 0
if tUsers[tUser.sIP] == nil then
tUsers[tUser.sIP] = {}
tUsers[tUser.sIP].Nick = tUser.sNick
...
WriteTable(tUsers, "tUsers", sUser)
Core.SendToUser(tUser, "Запись добавлена")
else
Core.SendToUser(tUser, "Ты уже есть в таблице")
end
end

Так вот при первом коннекте добавляется запись в файл, потом всё впорядке вплоть до перезагрузки скрипта. При этом при перезаходе он опять пишет Запись добавлена ну вообще не понимаю почему так(((

Вопрос снят сам понял свою глупость

Автор: Wariner 22.10.2008, 21:40

Вот тут возникла проблема с поисковыми запросами:

Цитата(Setuper @ 23.8.2008, 13:59) *
1. Клиент отправляет серверу запрос на поиск ("$Search ip:порт строка_поиска|").

а у меня получается
Цитата
$Search ip:порт фигня строка_поиска


вот в одном из поисков фигня равна = F?T?0?1?

это код скрипта
Код
function SearchArrival(tUser, sData)
    sData = string.sub(sData,1,-2)
    local _,_,seach = string.find(sData, "$Search %d*%.%d*%.%d*%.%d*:%d*(.*)")
    Core.SendToUser(tUser, "<"..sBot.."> "..seach)    
end


как мне от этого избавится?

проверил на двух хабах 0.4.0.0 и 0.4.1.1 и везде появляется F?T?0?1? может это стандартная надпись?

Автор: Nickolya 22.10.2008, 22:36

http://mydc.ru/Direct%20Connect%20Protocol%20Documentation.htm#SearchActiveclients. Вот, выложил, думаю это поможет. Спрашивай если что, но думаю разберешься. big_smile.gif

ЗЫ: подпись реально не в тему...
ЗЗЫ: используй codebox'ы только когда надо показать много кода, чтобы он не загромождал пространство, при маленьком коде это как-то стремно смотрится (я про бб-код codebox, вместо него пользуй просто code)

Автор: Setuper 22.10.2008, 23:42

Согласно протоколу dc на сегодняшний день существует следующая конфигурация запроса клиента на поиск:

A?B?C?D

где A и B могут принимать следующие значения: F или T
C и D - это числа. C это размер в байтах, D - это тип файла

выражение A?B? может принимать одно из следующих значений:

F?T? - поиск точного размера файла (в качестве размера выступает параметр C);
T?F? - поиск файла размером не менее, чем параметр C;
T?T? - поиск файла размером не более, чем параметр C.

параметр D (тип файла) может принимать одно из следующих значений:

1 - любой файл;
2 - аудио файл;
3 - архив;
4 - документ;
5 - испольняемый файл;
6 - картинка;
7 - видео;
8 - папка;
9 - TTH;
10 - CD/DVD образы.

Примеры:

$Search 10.10.10.10:6789 F?T?0?1?qwerty| - поиск qwerty среди всех файлов любого размера;
$Search 10.10.10.10:6789 F?T?0?2?qwerty| - поиск qwerty среди аудио файлов любого размера;
$Search 10.10.10.10:6789 F?T?0?9?TTH:ZELTUPSSMY56CSJGYNCVABGTGDKHP6DHCVNXS6| - поиск по хешу TTH файлов любого размера;
$Search 10.10.10.10:6789 T?F?4194304?1?qwerty| - поиск qwerty среди всех файлов размером не менее 4 Мб;
$Search 10.10.10.10:6789 T?T?1048576?1?qwerty| - поиск qwerty среди всех файлов размером не более 1 Мб;
$Search 10.10.10.10:6789 F?T?1048576?8?qwerty| - поиск qwerty среди папок размером в точности 1 Мб.

Кстате говоря $Search ip:port - так будет только в случае активного поиска, в случае же пассивного поиска будет немного иначе, а именно $Search Hub:nick
big_smile.gif

Автор: Wariner 24.10.2008, 20:57

а что в этом коде не так?

Код
function SearchArrival(tUser, sData)
    sData = string.sub(sData,1,-2)
    local _,_,seach = string.find(sData, "$Search %d*%.%d*%.%d*%.%d*:%d*%s%u%p%u%p%d%p%d%p(.*)")
    seach = string.gsub(seach, "%p", " ")
    seach = tSys:String2Lower(seach)


Цитата
[21:51] Синтаксис TopSeach.lua:25: bad argument #1 to 'gsub' (string expected, got nil)


я понимаю что значит эта ошибка, но не понимаю в какой момент она возникает((( точнее она возникает почти каждую секунду(не влияя на работу скрипта).

ЗЫ опять я где то накасячил

Автор: Setuper 24.10.2008, 21:50

хм... странно у меня работает данный код

Автор: Sephiroth_Lukaw 25.10.2008, 1:01

Цитата
[03:59] Sephiroth_Lukaw (**.**.**.**) > $Search Hub:Sephiroth_Lukaw F?T?0?1?ж|
Пассивный режим - [03:59] Синтаксис D:\Установленное\Test Ptokax\scripts\l.lua:4: bad argument #1 to 'gsub' (string expected, got nil)


Цитата
[04:00] Sephiroth_Lukaw (**.**.**.**) > $Search **.**.**.**:32128 F?T?0?1?ьь|
Активный режим - Нет синтаксических ошибок в файле скрипта l.lua

Автор: Setuper 25.10.2008, 6:46

Код
function SearchArrival(tUser, sData)
  sData = string.sub(sData,1,-2)
  local _,_,seach = string.find(sData, "$Search .-%s%u%p%u%p%d%p%d%p(.*)")
  seach = string.gsub(seach, "%p", " ")
  seach = tSys:String2Lower(seach)
  ...
end

юзаем CMD отладчик))))))

Автор: Wariner 25.10.2008, 11:27

Пардон, чего юзаем? beat_brick.gif
а ещё вот тут была проблема

Цитата
local _,_,seach = string.find(sData, "$Search .-%s%u%p%u%p%d%p%d%p(.*)")

изменил на
Цитата
local _,_,seach = string.find(sData, "$Search .-%s%u%p%u%p%d%p%d+%p(.*)")

Автор: Setuper 25.10.2008, 14:31

В любом dc клиенте есть так называемый CMD отладчик. Для просмотра команд, которые отсылает и принимает клиент. Это я к слову о пассивных и активных поисках - как узнать какая команда была отослана на хаб.

Автор: Wariner 26.10.2008, 20:54

есть таблица

Код
tUsers = {
    ["10.2.100.240"] = {
        ["OldNick"] = {
            [1] = "ыыыы",
            [2] = "ыыыы2",
        },
    },
}


есть код
Код
                for i = 1, table.maxn(tUsers[sIP].OldNick) do
                    local tTable = tUsers[tUser.sIP].OldNick
                    Nicks = tTable[i]..", "
                end
                local Niki = Niks or "Пользователь не использовал других ников"
                msg = msg.."\tСтарые ники: "..Niki.."\r\n"..


всегда пишет "Пользователь не использовал других ников" Что то совсем запарился не понимаю как сделать(((
после проверки оказалось table.maxn(tUsers[sIP].OldNick) = nil !!!
пробовал также через for i,v in pairs(tTable) do тоже не помогло(((

Автор: Sephiroth_Lukaw 26.10.2008, 21:14

Может так надо?

Код
for i = 1, table.maxn(tUsers[tUser.sIP].OldNick) do

Автор: Wariner 26.10.2008, 21:20

нет это часть функции выводящей инфу о пользователе IP вводится с чата! поэтому именно sIP

Автор: Sephiroth_Lukaw 26.10.2008, 21:33

Значение sIP проверял?
upd.

Код
>>>Nicks<<< = tTable[i]..", "
Код
local Niki = >>>Niks<<< or "Пользователь не использовал других ников"
Очепятка?-)

Автор: Setuper 26.10.2008, 21:49

я бы написал так:

Код
  msg = msg.."\tСтарые ники: "..(tUsers[tUser.sIP].OldNick and table.concat(tUsers[tUser.sIP].OldNick,", ") or "Пользователь не использовал других ников").."\r\n"..
этот код выполняется быстрее.

кстате, лучше использовать
Код
for i,v in pairs(tTable) do
чем
Код
for i = 1, table.maxn(tTable) do

Автор: Wariner 26.10.2008, 21:50

Цитата(Sephiroth_Lukaw @ 26.10.2008, 21:33) *
Очепятка?-)

Вот это лажа час с этим капался а опять всё дело в опечатке((((

2Setuper: можешь объяснить код который ты написал?

у меня есть вот такое описание
Цитата
table.concat (table [, sep [, i [, j]]])

Задан массив в котором все элементы – строки или числа, возвращает table[i]..sep..table[i+1] ··· sep..table[j]. Значение по умолчанию для sep – пустая строка, значение по умолчанию для i – 1, а для j – длина таблицы. Если i больше j, функция возвращает пустую строку.

но я его не понял(((

Автор: Sephiroth_Lukaw 26.10.2008, 22:33

ммм...Возвращает весь массив(table[i+1]) разделяя каждый элементом - sep(separation) - Разделителем
i - С какого элемента начинать(по умолчанию 1)
j - До куда(по умолчанию - длина таблицы)
Всё, кроме table - не обязательные параметры.
Т.к. table[i+1] - то, нельзя, что бы ключи в таблице были не числовые, так же, нельзя, что бы какой-нибудь элемент был опущен, т.е.

Код
tTable =
{
[1] = "Слово 1",
[3] = "Слово 2" ,
[4] = "Слово 3",
}
return table.concat (tTable,">_<") -- Не прокатит, нету индекса с номером 2
return table.concat (tTable,">_<", 3, 4) -- Вернёт: "Слово 2>_<Слово 3"
return table.concat (tTable,">_<", 4, 4) -- Вернёт: "Слово 3"



table.concat (table [, sep [, i [, j]]])
Код
tTable =
{
"Слово 1",
"Слово 2" ,
"Слово 3",
}
return table.concat (tTable,">_<") -- Вернёт: "Слово 1>_<Слово 2>_<Слово 3"
return table.concat (tTable,">_<", 2) -- Вернёт: "Слово 2>_<Слово 3"
return table.concat (tTable,">_<", 2, 2) -- Вернёт: "Слово 2"

блин...я плохо объясняю(((

Автор: Setuper 26.10.2008, 22:47

concat - конкатенация. Переводится как склеивание (сложение) строк.
table.concat - конкатенация элементов таблицы
первый параметр - сама таблица (обязательный)
второй параметр - разделитель между складываемыми элементами (не обязательный, по умолчанию пустая строка)
третий параметр - индекс таблицы начального элемента конкатенации (не обязательный, по умолчанию 1)
четвёртый параметр - индекс таблицы элемента конца конкатенации (не обязательный, по умолчанию равен наивысшему индексу таблицы)

2Sephiroth_Lukaw: все хорошо объясняешь))))

Автор: Wariner 26.10.2008, 23:07

Вот а ещё тут ломаю голову вот над каким вопросом:
есть две таблицы которые сводятся в одну временную после чего сортируется и выводится в чат(скрипт топпоисков)
так вот получается что во временной таблице некоторые поля дублируются!!! Например в одной ["фильмы"] = 5 а в другой ["фильмы"] = 10. Как перетрехнуть временную таблицу чтобы при нахождении дублирующие поля удалялись а их значения складывались?

Автор: Nickolya 27.10.2008, 0:05

У тебя вот такая конструкция:

Код
    if num == "1" then
        for j,q in pairs(v) do     
            table.insert(tTemp,{j,q})
        end
    else
Думаю можно сделать так:
Код
    if num == "1" then
        local tTemp2 = {}
        for j,q in pairs(v) do
            tTemp2[j] = q + (tTemp2[j] or 0)
        end
        for k, l in pairs(tTemp2) do
            table.insert(tTemp,{k,l})
        end
    else

Думаю суть ясна, если код "1", тогда мы создаем доп. временнную талицу, в которой суммируются данные при проходе по всей таблице tSeachTop, затем они добавляются в исходную таблицу tTemp

Автор: Wariner 30.10.2008, 19:53

Проверил... этот код не работает...

Автор: Setuper 30.10.2008, 22:27

тогда уж наверное так:

Код
local tTemp,tTemp2={},{}
for i,v in pairs(tTable) do
  if num=="1" then
    for j,q in pairs(v) do
      tTemp2[j]=q+(tTemp2[j] or 0)
    end
  else
    table.insert(tTemp,{i,v})
  end
end
if num=="1" then
  for i,v in pairs(tTemp2) do
    table.insert(tTemp,{i,v})
  end
end
table.sort(tTemp,function(a,b) return (a[2] > b[2]) end)
...

Автор: Setuper 8.11.2008, 16:07

Переименовал тему в Вопросы разработчикам скриптов. Так название лучше отражает суть темы

Автор: Wariner 8.11.2008, 17:09

Цитата(Setuper @ 8.11.2008, 16:07) *
Переименовал тему в Вопросы разработчикам скриптов. Так название лучше отражает суть темы

+1

Есть такое дело пишу функцию бана, чтоб можно было вводить время. Я отталкивался от "сегодняшней" даты, т.е. если какманда бана на 1h то из сегодняшней даты выделяются часы к ним плюсуется единица и впихивается обратно. Плюс идёт проверка на то что если оказывается больше 24 часов то идёт плюс к дням и т.д а вот с месяцами возникли проблемы... там же не стандартное число дней(30 31 или вообще 29) Как решить эту проблему?!

Автор: Setuper 8.11.2008, 17:26

привязку следует делать не к сегодняшнему дню, а к "началу эры юникс" 1.1.1970
для этого существует функция os.time(), которая выдаёт текущее время в секундах начиная с начала эры юникса.

Например функция установки временного бана по ip выглядит так:

Код
tTempBan={}
iMinutes=5
function TempBan(sIP)
  tTempBan[sIP]=os.time()+60*iMinutes
end


Функция проверки бана при входе выглядит так:
Код
function UserConnected(tUser)
  if os.time()<tTempBan[tUser.sIP] then
    Core.SendToUser(tUser,"*** Вы временно забанены. Вам осталось ждать "..(tTempBan[tUser.sIP]-os.time()).." сек.")
    Core.Disconnect(tUser)
  end
end


Если временный бан в несколько минут или даже часов, то для того, чтобы не было такого сообщения: "*** Вы временно забанены. Вам осталось ждать 16759 сек.", нужно предусмотреть перевод секунд в нормальный вид. Если надо, то могу предоставить такую функцию.

Автор: Wariner 8.11.2008, 19:27

Ок, спасибо, по поводу перевода из секунд в другие величины думаю разберусь))))


что то опять ступор...
60*5 - минуты
60*60*5 -часы
24*60*60*5 - дни
а как будут месяцы?! я в упор этого не понимаю. Надо писать блок который будет определять какой месяц или как то проще можно сделать?

Автор: Setuper 8.11.2008, 19:35

просто положи, что в месяце 30 дней и всё))))))

Автор: Wariner 8.11.2008, 21:24

Код
function GetNormalTime(s)
    s=tonumber(s)
    if s>=31104000 then
        Y = math.floor(s/31104000)        
        M = math.floor((s-31104000*Y)/2592000)
        d = math.floor((s-31104000*Y-2592000*M)/86400)
        h = math.floor((s-31104000*Y-2592000*M-86400*d)/3600)
        m = math.floor((s-31104000*Y-2592000*M-86400*d-3600*h)/60)
        s = math.floor(s-31104000*Y-2592000*M-86400*d-3600*h-60*m)
        return Y.." г. "..M.." мес. "..d.." д. "..h.." ч. "..m.." мин. "..s.." сек."
    elseif s>=2592000 then  
        M = math.floor(s/2592000)
        d = math.floor((s-2592000*M)/86400)
        h = math.floor((s-2592000*M-86400*d)/3600)
        m = math.floor((s-2592000*M-86400*d-3600*h)/60)
        s = math.floor(s-2592000*M-86400*d-3600*h-60*m)
        return M.." мес. "..d.." д. "..h.." ч. "..m.." мин. "..s.." сек."        
    elseif s>=86400 then  
        d = math.floor(s/86400)
        h = math.floor((s-86400*d)/3600)
        m = math.floor((s-86400*d-3600*h)/60)
        s = math.floor(s-86400*d-3600*h-60*m)
        return d.." д. "..h.." ч. "..m.." мин. "..s.." сек."        
    elseif s>=3600 then
        h = math.floor(s/3600)
        m = math.floor((s-3600*h)/60)
        s = math.floor(s-3600*h-60*m)
        return h.." ч. "..m.." мин. "..s.." сек."
    elseif s>=60 then
        m = math.floor(s/60)
        s = (s-60*m)
        return m.." мин. "..s.." сек. "
    else return s.." сек."
    end
end


вот такая функция получилась. как вам?

Автор: Setuper 8.11.2008, 21:52

я бы немного упростил и оптимизировал)))

Код
function GetNormalTime(s)
    s=tonumber(s) or 0
    local r=""
    if s>=31104000 then r=math.floor(s/31104000).." г. " s=math.fmod(s,31104000) end
    if s>=2592000 then r=r..math.floor(s/2592000).." мес. " s=math.fmod(s,2592000) end
    if s>=86400 then r=r..math.floor(s/86400).." д. " s=math.fmod(s,86400) end
    if s>=3600 then r=r..math.floor(s/3600).." ч. " s=math.fmod(s,3600) end
    if s>=60 then r=r..math.floor(s/60).." мин. " s=math.fmod(s,60) end
    return r..s.." сек."
end


или ещё более оптимизированный вариант (используя стандартные средства lua):
Код
function GetNormalTime(s)
    s=tonumber(s) or 0
    local r,t="",os.date("!*t",s)
    t.year,t.month,t.day=t.year-1970,t.month-1,t.day-1
    if t.year~=0 then r=t.year.." г. " end
    if t.month~=0 then r=r..t.month.." мес. " end
    if t.day~=0 then r=r..t.day.." д. " end
    if t.hour~=0 then r=r..t.hour.." ч. " end
    if t.min~=0 then r=r..t.min.." мин. " end
    if t.sec~=0 then r=r..t.sec.." сек. " end
    return r
end

Автор: Wariner 9.11.2008, 19:53

Написал я тут скриптик статистики поисковых запросов... никогда не интересовался сколько памяти жрёт скрипт, а тут вдруг промахнулся и попал в эту статистику, так оказалось хубба при 110 пользователях жрёт 5000 кб, но это не столь важно... Больше всего поразило что мой скрипт этих поисковых запросов жрёт 2000 кб. Можно ли как то это исправить? Может добавить или что то убрать из скрипта?

PS кажется это всё из за уже довольно большой базы...

Автор: Wariner 11.11.2008, 23:09

Вопрос почему не работает код?

Код
        if (sType ~= "main") or (sType ~= "pm") or (sType ~= "full") then
            Core.SendToUser(tUser,"<"..sBot.."> Вы неправильно ввели тип гага! (main, pm или full)")
            return true
        end

если оставить одно условие то всё пашет если нет то глухо... всегда пишет вы не правильно ввели!

Автор: Nickolya 12.11.2008, 0:04

По поводу памяти ничего не могу сказать, может просто слишком большая захламленность лишними переменными, но если данных много, то естественно это займет много памяти...

А про код могу вполне уверенно объяснить что он не логичен нихрена big_smile1.gif
Допустим, i = 10, а условие такое: если i не равно 1 то код такой-то, тут всё работает прекрасно, но при твоём усложнении ты допустил ошибку в духе юнной гениальности: если i не равно 1 ИЛИ i не равно 2 ИЛИ i не равно 3, то... этот код выполнится при любом i: даже если i равно 1, то оно не равно 2 и 3, и так далее, это как бы взаимоисключение группой условий друг друга big_smile.gif Используй И (and) и будет тебе счастье, так как тебе надо одновременное выполнение всех условий! Надеюсь доступно объяснил, спрашивай, если что-то непонятно.

Автор: district 21.11.2008, 1:04

Дабы не плодить новых топиков, решил коротенький вопрос изложить ТУТ.
(Собственно сабж ждет своего часа для освоения, пока не готов морально, набираюсь знаний и опыта big_smile.gif )
Вот какая из этих функций оптимальнее? И чем они по сути различаются?
(Задача - запретить определенные сочетания символов в никах на стадии валидации)

Есть допустим таблица:
(Таблица может быть большой и развесистой, поэтому, думаю, вариант с проверкой ников самой Птокой тут непригоден)

Код
tFbdNick = { -- символы и сочетания, запрещенные в НИКАХ
")))",
"(((",
"-=",
"=-",
"!",
"=",
}


И есть две функции. Обе вроде работают, но хотелось бы понимать разницу.

Код
function NickCheck(user)
local tmp = string.lower(user.sName)
        for i = 1,table.maxn(tFbdNick) do
            if string.find( tmp , tFbdNick[i] , 1 , true ) then ...


и

Код
function NickCheck(user)
for i,v in pairs(tFbdNick) do
  if (string.find(user.sName, v, 1, true)) then ...

Автор: Setuper 21.11.2008, 1:30

именно для такой таблице оптимальнее использовать следующий код:

Код
function NickCheck(user)
  for i,v in ipairs(tFbdNick) do
    if (string.find(user.sName:lower(),v,1,true)) then ...

Функция lower приводит латинские буквы ника к нижнему регистру.

Обрати внимание вместо pairs написано ipairs - это связано со структурой таблицы tFbdNick, так как индексы таблицы целочисленные (если индексы не указаны, то по умолчанию они целочисленны), то оптимальнее использовать функцию для целочисленных индексов ipairs.

Любые конструкции ipairs или pairs работают в цикле быстрее, из-за того, что перебор индексов происходит в порядке их хранения в памяти, а не в порядке возрастания целых чисел, как в случае цикла for i = 1,#tFbdNick do

По поводу порядка следования индексов в цикле можешь сам провести тест и сравнить порядки в обоих случаях big_smile.gif
Код
local sMsg=""
for i,v in ipairs(tFbdNick) do
  sMsg=i..", "
end
SendToAll("Порядок индексов данных в памяти: "..sMsg)

sMsg=""
for i=1,#tFbdNick do
  sMsg=i..", "
end
SendToAll("Заданный, возрастающий порядок индексов: "..sMsg)

Автор: district 21.11.2008, 3:23

Охохо... осмыслим на свежую голову.

Последний вопрос на сегодня.
Допустим, хочу я сделать ряд функций, подчиненных NewUserConnected'у

Код
function NewUserConnected(user)
Check(user)
RepeatCheck(user)
Fuck(user)
end

Например, проверка на то, проверка на это...
Удобно: если функция не нужна, ее можно просто закомментировать и т. обр. отключить двумя дефисами...

А вопрос такой. Сильно ли это ужасно с точки зрения производительности?

Автор: Setuper 21.11.2008, 7:32

Комментарии? Они никак не влияют на производительность. Интерпретатор просто игнорирует их при чтении кода.

Автор: Nickolya 21.11.2008, 9:45

Скорее вопрос в передаче одного локального параметра в функцию. На сколько я понимаю (везде лишь мои предположения и наблюдения, если не прав - поправьте), при получении параметра функцией, он будет локальным, .т.е. создается еще нное количество локальных переменных. Потом, луа работает быстрее с локальными данными. Отсюда появляется 2 варианта: тот что выше и вариант с глобальной переменной конфигурации, что чуть удобнее в плане использования:

Код
tCfg = {}
tCfg.bCheck = true
tCfg.bRepCheck = true
tCfg.bFuck = true

function NewUserConnected(user)
    if tCfg.bCheck then
        Check(user)
    end
    if tCfg.bRepCheck then
        RepeatCheck(user)
    end
    if tCfg.bFuck then
        Fuck(user)
    end
end

Этот вариант, конечно, чуть медленне, чем просто закомментировать функцию, но более понятней в настройке.

Потом, у меня давно была такая идея: что если исходя из настройки скрипта, он сам будет писать функцию в файл и загружать ее без всех лишних вещей, создавая как бы самого себя?! Это довольно сложно, хотя еще не полное извращение, видал я и хуже...

Автор: district 21.11.2008, 10:25

Пардон, вопрос был неверно сформулирован big_smile.gif

Вопрос заключался, конечно же, не в том, "будет ли интерпретатор пребывать в тягостных раздумьях, увидев закомментированное имя функции", и даже не в том, какой вариант удобнее для подключения/отключения функции. big_smile.gif
А вопрос заключался в следующем. Допустим, есть NewUserConnected в том виде, в котором привел ее я выше (с тремя подфункциями) и есть функция-монстр NewUserConnected, в которой все эти три уже встроены и априори последовательно исполняется. Вынося за скобки вопрос об удобстве подключения/отключения, насколько будет первый вариант тормознее второго, если вообще будет? (Имея в виду, что

Цитата
луа работает быстрее с локальными данными
?)

И еще один вопрос.
Возможно ли создать ряд типичных наборов условий (по русски напишу, и от балды, только для примера) например:
"если юзер не оператор
если юзер был хабтопером
если юзер был хабтопером но никогда не был VIPом" , что бы каждый такой набор условий был "вещью в себе"? Если не ошибаюсь, такая конструкция называется "макрос"?

тогда мы бы имели оговоренные в самом начале скрипта
макрос 1 = тыдыдыдыды -- комментарии
макрос2 = тыдыдыды --комментарии

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

Автор: Setuper 21.11.2008, 10:45

Быстрота выполнения в обоих вариантах одинакова, однако, первый вариант (с тремя функциями) лучше с точки зрения хорошего стиля программирования. Если есть отдельное действие, то лучше это действие выделять в отдельную функцию.

По поводу второго вопроса. Да, так можно сделать, но только в данном языке это будут глобальные переменные а не макросы. Макросов в языке lua нет, они есть в языке с/с++. Макросы работают как инструкции препроцессора и встраиваются прямо в код. В отличии от макросов языка с/с++, глобальные переменные языка LUA не обладают таким замечательным свойством, как встраиваемость в код, и поэтому несут некоторую нагрузку. Поэтому программисты lua в целях оптимизации стараются по возможности избегать использование глобальных переменных, в отличии от программистов c/с++, которые для оптимизации всегда используют макросы.

Автор: district 21.11.2008, 12:30

Цитата
однако, первый вариант (с тремя функциями) лучше с точки зрения хорошего стиля программирования.


Йес! Не зря не спим две недели, кое-что, значит, получается big_smile.gif :dance:

Цитата
В отличии от макросов языка с/с++, глобальные переменные языка LUA не обладают таким замечательным свойством, как встраиваемость в код, и поэтому несут некоторую нагрузку. Поэтому программисты lua в целях оптимизации стараются по возможности избегать использование глобальных переменных,

Примерно так и думал, чисто интуитивно ))



Уф.. опять вопрос назрел. Понимаю, что по-хорошему надо бы освоить все стринг.файнды, но слишком обширная тема, с наскоку не разберешься.
Вот есть таблица
Код
tFbdClient = {    
"XZDC++", -- тип клиента
}

есть например функция

Код
function MyINFOArrival(user,data)
for i,v in ipairs(tFbdClient) do
    if (string.find(user.sMyInfoString:lower(),v,1,true)) then
    client = string.find(???)
    
    msg = "*** Вы пользуетесь типом клиента, запрещенным на этом хабе.\r\n Ваш клиент: "..client.." ...

Что нужно указать в
Код
string.find(???)
, чтобы в сообщении было не UNKNOWN TAG, а тот самый XZDC++ ? Или как-то по другому поступить нужно?

Автор: Setuper 21.11.2008, 13:28

Во-первых, зачем приводить MyINFO строку к нижнему регистру? user.sMyInfoString:lower() - этого делать не надо.

Во-вторых, по поводу захватов и регулярных выражений можешь почитать тут: http://mydc.ru/topic266.html

В-третьих, никаких string.find-ов тут не нужно, а код будет таким:

Код
function MyINFOArrival(tUser)
  for i,v in ipairs(tFbdClient) do
    if v==tUser.sClient then
      msg = "*** Вы пользуетесь типом клиента, запрещенным на этом хабе.\r\n Ваш клиент: "..v.."
      break --для оптимизации
    end
  end
  ...

Автор: district 21.11.2008, 16:05

Окей, оно и правильно что вопросы сюда перенесены.
Но приведенный код - без захвата - вообще не работает, хоть sClient, хоть sClientVersion.

Автор: Setuper 21.11.2008, 16:20

Просто поле sClient берёт названия клиентов из файла cfg/ClientTags.xml и если в этом файле тега нет, то клиент помечается как неизвестный)))

С захватами не разобрался? Может сам напишешь?

Автор: district 21.11.2008, 19:40

Разберусь и напишу обязательно.
Что sClient актуально только тогда, когда тэг учтен в клиент ClientTags, еще вчера понял ))
Там просто хитрая конструкция хочу сделать, запрещенными могут быть не только клиенты, но и их отдельные версии (ну какому амину что от сердца дальше), из майинфо стринга вытаскиваться должны и клиент, и версия, если таковые есть в запретном списке.
..а пока провел небольшой эксперимент.
сама функция MyInfoArrival отдает, как выяснилось, SClient , но не sClientVersion

Код
Bot = frmHub:GetHubBotName()
function MyINFOArrival(user,data)
nick = "(ник админа)"
rpt = ""..user.sName.." "..user.sClient..""
SendPmToNick(nick, Bot, rpt)
end
- работает

Код
Bot = frmHub:GetHubBotName()
function MyINFOArrival(user,data)
nick = "(ник админа)"
rpt = ""..user.sName.." "..user.sClient.." "..user.sClientVersion..""
SendPmToNick(nick, Bot, rpt)
end
- attempt to call field 'sClientVersion' (a string value)

а вот NewUserConnected отдает и версию тоже
Код
Bot = frmHub:GetHubBotName()
function NewUserConnected(user)
nick = "[INT]district"
rpt = ""..user.sName.." "..user.sClient..""..user.sClientVersion..""
SendPmToNick(nick, Bot, rpt)
end

Автор: Setuper 21.11.2008, 20:05

Это всё верно, он только зачем пустые строки вставляешь?

Код
rpt = ""..user.sName.." "..user.sClient..""..user.sClientVersion..""
не проще ли написать так:
Код
rpt = user.sName.." "..user.sClient..user.sClientVersion
Лишняя конкатенация ни к чему.

И ещё второй раз уже пишу, что для того чтобы не забивать стек лучше не писать неиспользуемые параметры в функции. То есть вместо:
Код
function MyINFOArrival(user,data)
лучше писать
Код
function MyINFOArrival(user)


И ещё совет: писать переменные в венгерской нотации, так намного понятнее становится что содержит та или иная переменная (какого она типа), да и разработчики PtokaX в функциях апи также используют венгерскую нотацию (sClient, sClientVersion)
Поэтому вместо user советую писать tUser big_smile.gif

Автор: district 21.11.2008, 23:01

Setuper Будь друг, погоди с нюансами, "нотациями" big_smile.gif Ну зевнул я data, ну user а не tUser (к слову, лично у меня t ассоциируется с таблицами). Дойдем и до этого, сейчас вопросы посерьезнее на повестке дня.

Решить задачку с вычленением имени клиента и версии клиента хоть из какого угодно тега (в т ч не прописанного в ClientTags) пока удалось в два этапа, на более хитрое тяму пока не хватает.

Код
Bot = frmHub:GetHubBotName()

function MyINFOArrival(user)
nick = "[INT]district"
local _,_,xTag=string.find(user.sMyInfoString,"(%b<>)")
local_,_,cln,ver=string.find(xTag,"%S(%S+)%s(%S+),M")
rpt = "Клиент: "..cln..", Версия: "..ver..""
SendPmToNick(nick, Bot, rpt)
end

Замечена отдна странность: отсечь лишний "хвост", там где M:A.. и т д просто запятой или %p - не получается.
(Это самостоятельный тестовый ботик под АПИ1)

Автор: Wariner 21.11.2008, 23:34

Цитата(district @ 21.11.2008, 23:01) *
Setuper Будь друг, погоди с нюансами, "нотациями" big_smile.gif Ну зевнул я data, ну user а не tUser (к слову, лично у меня t ассоциируется с таблицами).


Может я опять щас ляпну не в тему но с таблицами у тебя ассоцииируется правильно ибо tUser - это таблица пользователей

Автор: Setuper 22.11.2008, 0:13

Код
local sBot = frmHub:GetHubBotName()
function MyINFOArrival(tUser)
  local _,_,sClient,sClientVersion=tUser.sMyInfoString:find("<(.-)%sV?:?(%S+),")
  local sNick,sMsg="[INT]district","Клиент: "..sClient..", Версия: "..sClientVersion
  SendPmToNick(sNick,sBot,sMsg)
end

Автор: district 22.11.2008, 0:44

Цитата
Ваш клиент: XZDC++, Версия: 1.1.0,M:A,H:1/0/0

Я же говорю, простой запятой лишний хвост "M:A,H:1/0/0" не отсекается. (Почему?)
А какой смысл тут в знаках "?" ? То, что это "магический символ", понятно, а подробнее? В обзоре захватов по ссылке про то не написано.

Цитата
Магические символы: ( ) . % + - * ? [ ] ^ $
Перед всеми магическими символами нужно ставить %

и вот с этим как-то не клеится. (?)

Автор: Wariner 22.11.2008, 0:54

Цитата
%s? - 0 или 1 символ пробела

я правильно понял?;)

PS прошу прощения что я всё время влезаю просто пытаюсь учится вместе с вами still_dreaming.gif

Автор: Setuper 22.11.2008, 0:56

Да уж... немного неправильно написал... Вот так:

Код
local sBot = frmHub:GetHubBotName()
function MyINFOArrival(tUser)
  local _,_,sClient,sClientVersion=tUser.sMyInfoString:find("<(.-)%sV?:?(.-),")
  local sNick,sMsg="[INT]district","Клиент: "..sClient..", Версия: "..sClientVersion
  SendPmToNick(sNick,sBot,sMsg)
end

По поводу вопросика: там в мануале надо смотреть не магические символы, а следующее:
Цитата
%s - 1 символ пробела
%s+ - 1 или более символов пробела
%s- - 0 или более символов пробела
%s* - 0 или более символов пробела
%s? - 0 или 1 символ пробела

Соответственно: V? - 0 или 1 символ V, :? - 0 или 1 символ :

Из-за чего я именно так сделал? Потому что существуют "левые клиенты", у которых отсутствует спецификатор V:, например, <AvaLink 1.3,M:A,H:0/2/0,S:8>

Автор: district 22.11.2008, 3:41

Имея в виду как раз тот пресловутый АваЛинк, попробовал соорудить доп.проверку для случая, когда в Птоке выбрано "Принимать клиентов без действительного тэга", и когда заходят на том же АваЛинке и им по боку например правило MaxHubs.

Где-то накосячил.. код то пачками шлет лички, то вылетает. Прошу за мелочи не пенять, сейчас главное усвоить как правильно тут должен выглядеть стринг, и почему вылетает суммирование a+b+c и как это искоренить. (

Цитата
attempt to perform arithmetic on local 'a' (a nil value)
)
Код
sBot = frmHub:GetHubBotName()
function MyINFOArrival(user)
local nick = "[INT]district"
local _,_,a,b,c,slots,share=user.sMyInfoString:find("H:(%d*)/(%d*)/(%d*)%S+S:(%d*)>%$%s%$.-%$%$(%d*)")
hubs = a+b+c
rpt = "Юзер: "..user.sName.." Хабы: "..hubs..", Слоты: "..slots.." Шара: "..share..""
SendPmToNick(nick,sBot,rpt)
end


Иногда эта зараза все-таки работает:
Цитата
[06:29:37] <БотПрощайМолодость> Юзер: Audion Хабы: 30, Слоты: 30 Шара: 2302216999857
[06:29:37] <БотПрощайМолодость> Юзер: BiNet Хабы: 40, Слоты: 15 Шара: 90021819095
[06:29:44] <БотПрощайМолодость> Юзер: Vetalmax Хабы: 22, Слоты: 15 Шара: 167860596055
[06:29:52] <БотПрощайМолодость> Юзер: [dn+]_karkysha17 Хабы: 22, Слоты: 44 Шара: 23508549985
[06:30:02] <БотПрощайМолодость> Юзер: Marry_Hacker Хабы: 15, Слоты: 10 Шара: 46313775246
[06:31:29] <БотПрощайМолодость> Юзер: Preta Хабы: 22, Слоты: 66 Шара: 158188566610
[06:31:34] <БотПрощайМолодость> Юзер: Vetalmax Хабы: 21, Слоты: 15 Шара: 167860596055
[06:31:39] <БотПрощайМолодость> Юзер: BiNet Хабы: 39, Слоты: 15 Шара: 90021819095

big_smile.gif

Автор: Sephiroth_Lukaw 22.11.2008, 5:51

ммм...а зачем мучать sMyInfoString, если шара, слоты - всё это есть в tUser?>,..,<
P.S.

Цитата("district")
Шара: 90021819095
http://mydc.ru/topic334.html?view=findpost&p=2490

Автор: district 22.11.2008, 10:34

Sephiroth_Lukaw
Да не обращай внимания, это просто обычная админская паранойя big_smile.gif
Кстати! Кто такой tUser?? Сколько раз ко мне нах хаб заходил? Сколько правил нарушил??? Под какими никами?? С каких IP?? С какой шарой? Какие читы использовал, подлец??? ПОЧЕМУ Я НЕ В КУРСЕ?????
big_smile1.gif big_smile1.gif big_smile1.gif
За ссылку по форматированию шары спасибо, на будущее учту. Только в данном конкретном случае, думаю, вряд ли пригодится: идея была в простом сравнении с frmHub:GetMinShare()
Причем - с точностью до байта! Чтоб не фулюганили ...))) А то знаю я этих tUserов, кот за дверь - мыши в пляс, глаз да глаз нужен big_smile1.gif

Setuper
А это вот для тебя персонально, вот так работает инспектор логов, который ты написал по моей просьбе.

Цитата
[2008-11-21 17:49] 172.17.137.174:Локалка <-_-> pt
[2008-11-21 17:49] 172.17.137.174:Локалка <-_-> :-O

[2008-11-21 17:52] :?? <БотПрощайМолодость> *** Юзер -_- был отключен. Отключил: Master [INT]district.
[2008-11-21 17:52] :?? *** Ушёл: -_-
[2008-11-21 17:52] :?? <Таможня> *** Пресечена попытка входа на хаб юзеру с запрещенными символами либо буквосочетаниями в нике. Юзер: -_-, IP: [ 172.17.137.174 ].

[2008-11-21 17:53] :?? *** Пришёл: }I{bI}I{A
[2008-11-21 17:55] 172.17.137.174:Локалка <}I{bI}I{A> пт

[2008-11-21 17:55] 172.17.137.174:Локалка <}I{bI}I{A> не понялза что кикнули с хаба -_-
[2008-11-21 17:56] 80.64.95.38:Новотелеком Нск <[INT]district> }I{bI}I{A: ты что, меня тренируешь?
[2008-11-21 17:56] 172.17.137.174:Локалка <}I{bI}I{A> [INT]district: ?

[2008-11-21 17:56] 80.64.95.38:Новотелеком Нск <[INT]district> посмотри какие у нормальных людей нормальные ники
[2008-11-21 17:56] 80.64.95.38:Новотелеком Нск <[INT]district> а с такими - пожалуйста, на иной хаб
[2008-11-21 17:56] 172.17.137.174:Локалка <}I{bI}I{A> я не могу придумать еще... фантазии мало
[2008-11-21 17:56] 172.17.137.174:Локалка <}I{bI}I{A> тем более мата нет в нике
[2008-11-21 17:57] 80.64.95.38:Новотелеком Нск <[INT]district> тогда сделай либо префикс нанки
[2008-11-21 17:58] 172.17.137.174:Локалка <}I{bI}I{A> я не разбираюст в нумерах нанок ваще:'-(
[2008-11-21 17:58] 80.64.95.38:Новотелеком Нск <[INT]district> либо я за себя не отвечаю ]:->
[2008-11-21 17:58] 172.17.137.174:Локалка <}I{bI}I{A> ок
[2008-11-21 17:59] :?? *** Ушёл: }I{bI}I{A
[2008-11-21 17:59] :?? *** Пришёл: [313]_WOWIR_500
[2008-11-21 17:59] 172.17.137.174:Локалка <[313]_WOWIR_500> сменил опять

[2008-11-21 17:59] :?? *** Пришёл: ConnectionsInspector
[2008-11-21 17:59] :?? <ConnectionsInspector> *** Ники, под которыми входил пользователь с IP адресом 172.17.137.174
-_- - 1 раз(а) с этого IP
}I{bI}I{A - 1 раз(а) с этого IP
[131]L1nk - 1 раз(а) с этого IP

[313]_WOWIR_500 - 1 раз(а) с этого IP


[2008-11-21 18:00] 80.64.95.38:Новотелеком Нск <[INT]district> [313]_WOWIR_500: [131]L1nk твой ник и хватит придуриваться


(ТУТ НЕМАЯ ПАУЗА big_smile1.gif)
[2008-11-21 18:00] 172.17.137.174:Локалка <[313]_WOWIR_500> [INT]district: а как ты узнаёшь ники, которые были на других хабах и давным давно?


а вот вопрос про a+b+c по-прежнему животрепещущ..
Добавив пять строчек в код
Код
function MyINFOArrival(user)
local nick = "[INT]district"
local _,_,a,b,c,slots,share=user.sMyInfoString:find(".-H:(%d*)/(%d*)/(%d*)%S+S:(%d*).-%$%$(%d*)")
a = a or 0
b = b or 0
c = c or 0
slots = slots or 0
share = share or 0
iHubs = a+b+c
rpt = "Юзер: "..user.sName.." Хабы: "..iHubs..", Слоты: "..slots.." Шара: "..share..""
SendPmToNick(nick,sBot,rpt)
end

получил такую картину:
Цитата
[15:11:32] <БотПрощайМолодость> Юзер: Gsera(INT) Хабы: 54, Слоты: 54 Шара: 20748169326
[15:11:32] <БотПрощайМолодость> Юзер: KOMMUNIST Хабы: 0, Слоты: 0 Шара: 0
[15:11:34] <БотПрощайМолодость> Юзер: Vetalmax Хабы: 22, Слоты: 15 Шара: 173292041223

Тут юзер KOMMUNIST вполне добропорядочный, но параметры не извлекаются. Это как следует понимать? Что string.find попросту отрабатывать не успевает, или в другом причина?

Автор: Setuper 22.11.2008, 13:04

Код
local _,_,a,b,c,iSlots,iShareSize=tUser.sMyInfoString:find("H:(%d+)/(%d+)/(%d+),S:(%d+).-%$%$(%d+)")
a,b,c,iSlots,iShareSize=a or 0,b or 0,c or 0,iSlots or 0,iShareSize or 0
local iHubs=a+b+c

Автор: Nickolya 22.11.2008, 14:39

Может вот этот скрипт чем-то поможет, поковыряйте...

 BadTag_1.1.lua ( 4.64 килобайт ) : 15
 

Автор: district 22.11.2008, 16:26

Setuper По поводу последнего кода: разница я понял только в плюсиках вместо звездочек? В таком варианте - то же самое, порядочных юзеров код принимает за халявщиков.

И еще одна проблема. Хвосты толком не отрабатываются и в такой вот конструкции:

Цитата
local _,_,a,b,c,d=user.sName:find(".*+?(%S)(%S)(%S)(%S)???")
if a and b and c and d then
a,b,c,d = a or 0,b or 0,c or 0, d or 0
if a==b and a==c and a==d then


Задача - определить наличие в нике четырех и более одинаковых символов подряд.
Если ник ass1111 или asss0000 - все нормально. Если допустим asss1111s - все, перестает работать.
Если приписать в конце стринга только %S - отрабатывает, но только при наличии ОДНОГО символа в нике после вычленяемых четырех. Если будет asss1111sss - не работает, даже если приписать %S+, %S+? (практически все перепробовал). Как тут быть?

Nickolya
Спасибо, посмотрим чем там можно поживиться)

Автор: Sephiroth_Lukaw 22.11.2008, 16:44

Цитата(" district ")
четырех и более одинаковых символов подряд.
Код
(.)%1%1%1
как-то так.

Автор: district 22.11.2008, 17:08

Да.. "как-то так". Но ведь не будешь на все возможные сочетания символов свои захваты городить? Поэтому в примере и используются (%S) - работает, ты ж сам видел. Но вот с окончанием захвата (а может, и с началом?) - проблема.

Автор: Sephiroth_Lukaw 22.11.2008, 17:22

Цитата("district")
Задача - определить наличие в нике четырех и более одинаковых символов подряд.
Код
...
local _,_,Test=string.find("AAAzzzzddd", "(.)%1%1%1")
    if not Test then
    SendToAll("Нету") //Ну и ладно..
    else
    SendToAll("Есть - " . Test) //4 одинаковых символа, тут дисконнект юзера, бан, etc.
    end
...

Автор: Setuper 22.11.2008, 18:29

хм... странно... а тэги этих самых юзеров можешь написать сюда? Надо разобраться из-за чего не происходит захвата.

по поводу повторений в нике думаю, что можно сделать так:

Код
function CheckRepeat(sStr)
  local sNewChar,sOldChar,iC,iRepeat="","",1,4
  for i=1,sStr:len() do
    sNewChar=sStr:sub(i,i)
    if sNewChar==sOldChar then
      iC=iC+1
    else
      iC=1
    end
    if iC>=iRepeat then
      return true
    end
    sOldChar=sNewChar
  end
end

function CheckNick(tUser)
  if CheckRepeat(tUser.sName) then
    tUser:SendData("Bad Nick.")
    tUser:Disconnect()
  end
end

Автор: district 22.11.2008, 18:39

Sephiroth_Lukaw
Ну не знаю, что имел в виду уважаемый докладчик.. Или у меня лыжи совсем уже не едут..))
Запустил в таком виде:

Код
sBot = frmHub:GetHubBotName()
function MyINFOArrival(user)
local _,_,Test=string.find("AAAzzzzddd", "(.)%1%1%1")
if Test then
SendPmToNick("[INT]district",sBot, ""..user.sName.."")
end
end

Ну код мне и выдал каждый ник каждого юзера, при каждом входящем майинфо. В чем тут прикол? Что-то не догоняю :(

Автор: Sephiroth_Lukaw 22.11.2008, 18:42

ну, по идее, регулярки вроде бы всегда медленнее...
P.S.
local _,_,Test=string.find(user.sName, "(.)%1%1%1")
P.P.S.
И вправду, ты всегда, зачем то лишние "" вставляешь
""..user.sName.."" -> user.sName

Автор: Setuper 22.11.2008, 18:55

Действительно, наверное всё же оптимальнее использовать регулярное выражение:

Код
(.)%1%1%1



Код
function ValidateNickArrival(tUser)
  if tUser.sName:find("(.)%1%1%1") then
    tUser:SendData("Bad nick")
    tUser:Disconnect()
  end
end

Автор: district 22.11.2008, 19:26

Setuper
Думаешь, дело может быть в тэге?
Мы ж не весь майинфо стринг исследуем, а конкретный юзерский объект...

Код
$MyINFO $ALL asss0000 сотона<StrgDC++ V:2.2,M:A,H:1/0/0,S:3>$ $100$$140742256829$|

-есть захват

Код
$MyINFO $ALL asss00001 сотона<StrgDC++ V:2.2,M:A,H:1/0/0,S:3>$ $100$$140742256829$|

нет захвата
Кстати, этот захват я попробовал и в ValidateNickArrival, и в NewUserConnected, на всякий случай. Результат тот же.

==============================================================
Ай ребята, ну где ж вы раньше были с таким элегантным и эффективным регулярным выражением ))) Целый день убил, пытаясь захват сделать.

Работает! Может, еще какие-нибудь хитрые выражения есть? (Хабик небольшой, народу немного, нагрузка на ресурсы не бешеная)

Автор: Setuper 22.11.2008, 20:40

Если имя клиента является неизвестным, то тег клиента приклеивается к описанию!!!

Функция коррекции данных пользователя:

Код
function GetNormalValue(tUser)
  if not tUser.sTag then
    local _,_,sDescription,sTag,sClient,sClientVersion,sMode,iNormalHubs,iRegHubs,iOpHubs,iSlots,iLlimit=tUser
.sDescription:find("(.*)(<(.+)%sV:(.-),M:(.-),H:(%d+)/(%d+)/(%d+),S:(%d+)>)$")
    if not sDescription then
    _,_,sDescription,sTag,sClient,sClientVersion,sMode,iNormalHubs,iRegHubs,iOpHubs,iSlots,iLlimit=
tUser.sDescription:find("(.*)(<(.+)%sV:(.-),M:(.-),H:(%d+)/(%d+)/(%d+),S:(%d+),L:(%d+)>)$")
    end
    if not sDescription then
    _,_,sDescription,sTag,sClient,sClientVersion,sMode,iNormalHubs,iRegHubs,iOpHubs,iSlots,iLlimit=
tUser.sDescription:find("(.*)(<(.+)%sV:(.-),M:(.-),H:(%d+)/(%d+)/(%d+),S:(%d+),B:(%d+)>)$")
    end
    tUser.sDescription=sDescription
    tUser.sTag=sTag
    tUser.sClient=sClient
    tUser.sClientVersion=sClientVersion
    tUser.sMode=sMode
    tUser.iNormalHubs=iNormalHubs
    tUser.iRegHubs=iRegHubs
    tUser.iOpHubs=iOpHubs
    tUser.iHubs=iNormalHubs+iRegHubs+iOpHubs
    tUser.iSlots=iSlots
    tUser.iLlimit=iLlimit
  end
  return tUser
end


Использование коррекции:
Код
function MyINFOArrival(tUser)
  tUser=GetNormalValue(tUser)
  tUser:SendData("sName = "..tostring(tUser.sName).."\n"..
  "sClient = "..tostring(tUser.sClient).."\n"..
  "sClientVersion = "..tostring(tUser.sClientVersion).."\n"..
  "sMode = "..tostring(tUser.sMode).."\n"..
  "sMyInfoString = "..tostring(tUser.sMyInfoString:sub(1,-2)).."\n"..
  "iShareSize = "..tostring(tUser.iShareSize).."\n"..
  "iHubs = "..tostring(tUser.iHubs).."\n"..
  "iSlots = "..tostring(tUser.iSlots).."\n"..
  "sTag = "..tostring(tUser.sTag).."\n"..
  "sDescription = "..tostring(tUser.sDescription).."\n"..
  "sConnection = "..tostring(tUser.sConnection).."\n"..
  "sEmail = "..tostring(tUser.sEmail).."\n"..
  "iNormalHubs = "..tostring(tUser.iNormalHubs).."\n"..
  "iRegHubs = "..tostring(tUser.iRegHubs).."\n"..
  "iOpHubs = "..tostring(tUser.iOpHubs))
end

Автор: Wariner 22.11.2008, 22:49

А как захватить несколько сообщений юзера? Т.е. если он пишет

Цитата
<user>10.
<user>2.
<user>100.
<user>240

его кикало. В моём представлении это можно сделать только конкатацией. Есть ещё какие то варианты и как будет реагировать если между сообщениями этого юзера вклинится сообщения ещё кого то?

Автор: Nickolya 22.11.2008, 23:06

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

Автор: mariner 23.11.2008, 0:46

Wariner, я вот что посоветую... Ковыряй настройки хаба =) Там есть антифлуд. настрой его как надо и все.

Автор: Nickolya 23.11.2008, 1:44

Ну хватит говорить лишь бы о чем-то! Речь идет о сообщениях не повторяющихся, но в сумме дающих адрес.
Идеальной антирекламы сделать не получится, т.к. не будет конца извращениям, генерируемым мозгом человека...
В птоке АНТИФЛУД, а это отностится к антирекламе, которую туда еще не влепили. big_smile1.gif
P.S. удалите сами весь этот "базар"

Автор: district 23.11.2008, 6:37

В свете промелькнувшего "регулярного выражения" хотелось бы снова поднять эту тему. Может, мой вопрос и не затрагивает те самые регулярки? Попытаюсь изложить предметно.

Пока что, в тестовом варианте, проверка юзера идет на трех этапах:
ValidateNickArrival
MyInfoArrival
NewUserConnected

(Насколько я понял, именно в такой последовательности нужно делать, на каждом этапе используя информацию, доступную именно на этом этапе)
Вот есть условие:

Код
if not (user.bOperator or tPNicks[user.sName] or tPIps[user.sIP] or tPProfile[(GetProfileName(GetUserProfile(user.sName)))]) then

которое используется как отменяющее проверку (приписано в начале каждой из трех функций)
Хотелось бы сделать применение условий более гибким, т е создать локальные группы,
а условие, отменяющее проверку и отсылающее к сопоставлению с "членством" в локальной группе, перенести в начало каждой из кучи прикладных функций: NoProxy, OneIP4OneClient, CheckNick, CheckDesc, CheckEmail, и т д, которые, как я где-то писал об этой идее, подключаются по мере необходимости простым раскомментированием имени функции.
например как-то так
локальная группа А = принадлежность к таблицам х, у и/или профилю такому-то...
Что-то мудревато пока получается, в голове не складывается. Может, есть наработки, чтобы не изобретать велосипед?

Setuper
Почему ж все-таки захваты не работают? Я посмотрел крайний захват МайИнфо, который ты привел. В сравнении с моим первый "блином комом", там нет лишнего %S+ , которое я по ошибке поставил между перечислением хабов и слотами. Но все равно работает от раза к разу, то все выдает, то все по нулям. С чем тут еще может быть связано? Речь-то пока ни о каких не левых юзерах, теги всех присутствующих учтены в ClientTags, хотя, стоит крыжик "Принимать тэг от неизвестного клиента за действительный". Может, это баг Птоки такой, забыть и не мучиться? Птока - 0360 LUA 5.1.2
doubt.gif

Автор: Setuper 23.11.2008, 13:21

Ты идёшь по моим стопам. Именно такую фишку я реализовал в моём боте, но немного более сложную чем ты предполагаешь сделать, а именно, в базе данных существует таблица с действиями. Таблица состоит из следующих столбцов (строк может быть любое количество): он_офф, Тип_действия, действие, номер_профиля_s, номер_профиля_e, номер_текущего_профиля_s, номер_текущего_профиля_e, ip_s, ip_e, ник.
В таблице указаны действия и их применимость или не применимость к определённой группе. Например, тип_действия=оповещение, действие=вход_с_запрещённых_ip, номер_профиля_s=5, номер_профиля_e=12, номер_текущего_профиля_s=1, номер_текущего_профиля_e=nil, ip_s=nil, ip_e=nil, ник=nil. Таким образом, оповещение о входе пользователя с запрещённым ip поступит профилям, начиная с номера 5, до номера 12, если текущий профиль меньше пятого, однако, если текущий профиль пользователя больше, либо равен пятому, то параметр номер_текущего_профиля_s говорить сколько надо прибавить к текущему профилю, чтобы отсылать оповещений. В данном случае надо прибавить 1, а так как номер_текущего_профиля_e=nil, то последний профиль не изменяется, таким образом, если текущий профиль меньше пятого, то оповещение отправится всем профилям от 5 до 12, иначе оповещение отправится профилям от (текущий_профиль + 1) до 12. Кроме этого, если параметры ip_s, ip_e и ник не указаны, то оповещение отправляется только профилям, если же, например, ip_s=0, ip_e=167772160, то оповещение прийдёт только тем профилям, которым разрешено плюс ip этих пользователей должны будут лежать в диапазоне 0.0.0.0 (=0) - 10.0.0.0 (=167772160), а если ещё указывается и ник, то оповещение отправляется указанному нику, но при условии, что профилю с этим ником разрешена отсылка, и ip адрес этого ника лежит в разрешённом диапазоне.

Конечно это очень сложный механизм со сложной реализацией, который использует хранение в базе данных, но этот механизм очень универсальный. Любой действие или антидействие в нём прописано, от отсылки оповещений и менюшек до собственных параметров каждого пользователя.

Что касается захватов, то последняя моя функция коррекции должна работать всегда. Как её использовать я тоже прописал.

Автор: district 23.11.2008, 18:15

Setuper
Ясно.. что ничего не ясно big_smile.gif
Ну да ладно. Вот есть небольшой вопрос: как организовать разделители в менюшках, если в коде использованы вот такие конструкции?

Код
tRC = {{"Дать иммунитет", " add %[line:Ник]" }, { "Забрать иммунитет", " remove %[line:Ник]" } }

Сверху этого пункта в меню получается еще три, хотелось бы их отделить, по типу
$UserCommand 0 3

Автор: Setuper 23.11.2008, 18:19

зачем все эти навороты с разделениями, которые потом всё равно собираются в один код отправки, тем более, что эти разделения только для разработчика.

Просто пиши уже готовые коды без разделений

Автор: district 23.11.2008, 18:54

Я вот что имел в виду (на картинке)
Тут приведен пример правда из обычного оформления юзерской команды, через сенд дата.
Сверху и снизу меню скрипта погоды обставлено "разделителями" - снизу есть, сверху не получается. (красная линия)
Даже в обычном варианте трудности.
Как тут быть? И тем более, как быть в первом вопросе?

 

Автор: Setuper 23.11.2008, 19:12

Разделитель нельзя поставить снизу менюшки со стрелочкой. Если ты немного задумаешься как отправляются менюшки, то думаю, что ты сможешь понять почему.

Например в твоём случае:
есть менюшка: Объявления, Релизы, Запросы\\Подменю
Если после этой менюшки ставить разделитель, то он появится после "Подменю" а не после "Объявления, Релизы, Запросы", потому что разделитель нельзя вставить между ними, так как они отправляются как единое целое.

Надеюсь ясно изложил?

Автор: district 23.11.2008, 20:38

Setuper

Цитата
Разделитель нельзя поставить снизу менюшки со стрелочкой.

примерно так и думал, спасибо.
Насчет разделителей, когда пункты меню создаются как
Код
tRC = {{"Дать иммунитет", " add %[line:Ник]" }, { "Забрать иммунитет", " remove %[line:Ник]" } }
вопрос остался открытым..

Автор: Wariner 23.11.2008, 20:39

2Setuper: если не сложно можешь сказать несколько слов о метатаблицах. Я как всегда несколько не понял описания на http://mydc.ru/r/?http://lua.ru

Автор: Setuper 23.11.2008, 20:47

2district: говорю же отправляй готовые пункты меню, не разделяй на несколько частей команды
2Wariner: метатаблицы - это таже таблицы, но только с определёнными методами - это несколько расширенная возможность, например, можно предусмотреть, что будет делаться с данными при вставке в такую таблицу, или, например, при сложении данных ну и тд.

Автор: Wariner 28.11.2008, 23:45

Не смог перевести скрипт((( Переводил без конвертера...

Цитата
[23:43] Синтаксис ...okaX 0.4.1.1\scripts\Hang-Man.v1.1.LUA5.X-PtokaX.lua:1183: attempt to index field '_GAME_STATISTICS' (a nil value)


Что не так?

 Hang_Man.v1.1.LUA5.X_PtokaX.rar ( 45.29 килобайт ) : 7
 

Автор: Setuper 29.11.2008, 0:10

Бегло просмотрев код, я сразу заметил, что всё привязано к конкретным цифрам, поэтому, сменив бота скрипт оказывается нерабочим.
Смотри строку:

Код
if string.sub(data,6,5+(string.len(tVar.sBot))) == tVar.sBot then

Автор: Nickolya 29.11.2008, 1:04

Это если бегло, это случай остылки в приват, так что чтобы не искать в строке, она обрезается, вспомни "$To: ", и поймешь откуда конкретные цифры, кстати, хороший метод работы с приватом, чтобы не закрывать код. big_smile.gif
А вообще, ошибка в том что нет таблицы _GAME_STATISTICS в таблице tPoint: tPoint["_GAME_STATISTICS"]
Хотя в начале скипта есть вот такое, таблицы все-таки нет:

Код
tPoint = {}
tPoint["_GAME_STATISTICS"] = {}
tPoint["_GAME_TOTALS"] = 0
Скорее всего проблема исправится если удалить этот файл со статистикой, при выключенном скрипте естественно, т.к. в сохраненном файле таблица только с твоим ником, а должны быть еще и эти служебные. Надеюсь растолковал, но это тоже беглый просмотр и лишь теория. Пробуй, будем разбираться.

Автор: Setuper 29.11.2008, 1:39

Да, точно, не подумал. Нестандартное отсечение меня заблудило))))

Скрипт большой, поэтому не стал разбираться подробно.

Автор: *FoxMalder* 29.11.2008, 18:05

можно ли определять с какого порта заходят на хаб? и сделать типо
с такого то порта сидят стока то % юзеров
а с такого то стока то %

м??

Автор: Setuper 29.11.2008, 18:40

Такой возможности в PtokaX нет

Автор: Wariner 1.12.2008, 16:05

Цитата(Nickolya @ 29.11.2008, 1:04) *
Скорее всего проблема исправится если удалить этот файл со статистикой


+1 )))
Просто он в готовых уже так выложен вот я и не обратил внимание

Автор: Wariner 2.12.2008, 18:22

Можно ли заменить одну команду другой? Т.е юзер вводит !ban а выполняется !banuser?

Автор: Setuper 2.12.2008, 20:06

А зачем огород городить?

Код
function ChatArrival(tUser,sData)
  sData=sData:sub(tUser.sNick:len()+4,-2)
  local _,_,sPrefix,sCmd,sArg=sData:find"%s*(%p)(%S+)(.*)"
  if sCmd and sPrefix=="!" and sCmd=="ban" then
    --выполняем те действия, которые выполняются при команде !banuser
    return true
  end
end

Вторая команда не является встроенной командой PtokaX, если бы она таковой была бы, то ничего сделать нельзя было бы, так как встроенную команду нельзя вызвать скриптом.
Если вторая команда - это команда какого-то другого скрипта, то тоже ничего не выйдет.

Автор: Wariner 10.12.2008, 22:22

Как лучше(оптимальнее) работать с текстовыми файлами? Просто вписывать туда текст или таблицей?

Автор: Setuper 10.12.2008, 23:12

что понимается под словом текстовый файл?
просто файл с набором текста? или это файл с какой-то определённой структурой?

Автор: Wariner 11.12.2008, 16:38

прошу прощения что некорректно выразился...
я имею ввиду файлы типа .dat .txt .tbl в общем все вспомогательные файлы которые используются скриптами для хранения информации.
как лучше? (На примере викторины) так

Код
вопрос1*ответ1
вопрос2*ответ2

или так
Код
TrivEx._Config = {
    ["trivhint"] = 0,
    ["trivskip"] = 0,
    ["mode"] = "pm",
    ["showquesmode"] = 1,
    ["sequentialnum"] = 96,
}


или в каком случае лучше одно а в каком другое?

Автор: Setuper 11.12.2008, 17:48

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

Поэтому в разных случаях по разному. Всё зависит от того, что конкретно надо реализовать.

Автор: Sephiroth_Lukaw 12.12.2008, 21:13

Код
function UserConnected(tUser)
local sBuffer = ''
  for i = 1, #tActionTable do
  sBuffer = sBuffer.."$UserCommand 1 2 Действия\\"..tActionTable[i][1].."$<%[mynick]> !"..sActionCmd.." "..i.." %[nick]||"
  end
Core.SendToNick(tUser.sNick, sBuffer)
end


Код
function OnStartup()
sBuffer = ''
  for i = 1, #tActionTable do
  sBuffer = sBuffer.."$UserCommand 1 2 Действия\\"..tActionTable[i][1].."$<%[mynick]> !"..sActionCmd.." "..i.." %[nick]||"
  end
end

function UserConnected(tUser)
Core.SendToNick(tUser.sNick, sBuffer)
end

Какой из вариантов, по идее, лучше(в смысле, оптимизации), учитывая, что таблица очень большая? Интересно, просто. Я, думаю, что 2-ой вариант(просто, он больше памяти будет есть, но работать быстрее).

Автор: Setuper 12.12.2008, 21:23

Безусловно лучше второй вариант.
В первом варианте всё загоняется в глобальную переменную и это означает, что вся информация будет храниться в оперативке.
Во втором варианте из-за локальности переменной в памяти оставаться инфа не будет, но этот вариант плох тем, что он значительно нагружает процессор. Любой цикл нагружает процессор, а тут он будет нагружаться при каждом входе юзера.

Автор: *FoxMalder* 13.12.2008, 20:24

а можно с помошью скрипта как нибуть "спросить" у клиена его ratio?

Автор: Setuper 13.12.2008, 21:53

нет, нельзя

Автор: Wariner 28.12.2008, 22:40

Цитата(ustas @ 28.12.2008, 22:16) *
это не скрипт, а отдельный бот

Вот интересно, а бот это не скрипт?!

Автор: Setuper 28.12.2008, 22:42

тут скрипт, а вообще бывают боты и не скриптами реализованные)))

Автор: Wariner 28.12.2008, 22:51

не я имел ввиду что когда говорят на скрипт бот что под этим подразумевают?
Про отдельных ботов я знаю

Автор: Setuper 28.12.2008, 22:58

Скрипт - это программа (код), которой для выполнения необходим интерпретатор.
Бот - это некий робот, который выполняет некий набор инструкций по некому алгоритму и написанный на каком-то языке, в частности на скриптовом.
Поэтому бот-скрипт - это сприптовая программа, выполняющая набор действий.

Автор: Wariner 28.12.2008, 23:44

эмммм..... ну тогда любой скрипт - это бот surrender.gif

Автор: Setuper 28.12.2008, 23:45

Ну в принципе да. Хотя ботом я думаю называют сложные скрипты, которые используют сложные алгоритмы и сопрограммы.

Автор: *FoxMalder* 9.1.2009, 17:57

а можно узнать какой пароль вводит юзер заходя на хаб несмотря в регистр?

Автор: Wariner 9.1.2009, 18:01

Цитата
PasswordArrival(tUser, sData) - Поступившее от пользователя сообщение с паролем.
Аналог API 1: PasswordArrival(tUser, sData)

Автор: Setuper 9.1.2009, 18:15

Код
sOwner="Админ"
function PasswordArrival(tUser, sData)
  Core.SendToNick(sOwner,"Nick="..tUser.sNick.." Pass="..sData:sub(9,-2))
end
big_smile.gif
http://mydc.ru/ipb.html?s=&showtopic=915&view=findpost&p=6733

Автор: *FoxMalder* 9.1.2009, 18:24

можно переделать чтоб отправлялось тока в том случаи если пароль неверный?

Автор: *FoxMalder* 9.1.2009, 20:56

что то админу не отсылает

Автор: Setuper 9.1.2009, 21:42

хехе, а данная функция PasswordArrival вызывается только в случае правильной отсылки пароля))) поэтому бес толку писать такой скрипт.

Именно из-за подобного рода проблем в ptokax я и хочу написать свой хаб)))

Автор: Wariner 9.1.2009, 21:50

Цитата(Setuper @ 9.1.2009, 21:42) *
Именно из-за подобного рода проблем в ptokax я и хочу написать свой хаб)))

и как успехи? кстати хотел спросить ты сам всё это учишь или кто то помогает/курсы/ещё что то(просто в голову не лезет)?

Автор: Setuper 9.1.2009, 22:07

хаха. Какие ещё курсы? Курсы DC++ hub? Смешно.
Просто я dc-помешанный, у меня так и написано в профиле)))
Кстате говоря, вот и перевалили мои сообщения за тысячу big_smile.gif

Автор: Wariner 9.1.2009, 22:51

Ладно чушь спросил, ещё одна : этьо просто развлечение или приносит какой то доход?

Автор: Setuper 9.1.2009, 22:57

Это стремление быть экспертом в этой области, а доход не обязателен, хотя я не против, и не стану стесняться предложений уже было много.
Стремление познать каждую мелочь, стремление написать нечто универсальное и кросс-платформенное, стремление изобрести новые алгоритмы, стремление к красоте кода.

Автор: Wariner 11.1.2009, 0:10

Почему когда некоторые настройки включаешь в функции OnStartup скрипт их не видит?

Автор: Setuper 11.1.2009, 0:22

что именно?

Автор: Wariner 11.1.2009, 0:27

посмотри вот это http://mydc.ru/topic1091.html вынес настройки в файл и пришлось писать dofile до фукции OnStartup

Автор: Setuper 11.1.2009, 0:40

всё работает. Не понимаю в чём у тебя проблема?

Автор: Wariner 11.1.2009, 1:00

вот смотри. в той версии которая выложена подключение настроек идёт до функции OnStartup и всё работает, а когда я переносил эти же строчки в саму функцию скрипт отключается сразу после включения не выдавая ошибок.видел такое уже в паре скриптов и не ожидал такое от собственноручно написанного скрипта(((
А так как есть оставлять не хочу ибо Core.GetPtokaXPath() при выключенном хабе будет выдавать ошибку.

Автор: Setuper 11.1.2009, 1:10

Я помещю загрузку из файла в функцию OnStartup, всё по прежнему работает. Не понимаю почему у тебя не работает, может PtokaX левая

Автор: Sephiroth_Lukaw 11.1.2009, 4:05

В начало функции ставь, а не в конец.
У тебя там переменная "sType" используется из фаила настроек.
Так что, либо в начале функции, либо за её пределами.

Цитата
function OnStartup()
...
if (sType ~= "sIP" and sType ~= "sNick") or not sType then
Core.SendToOpChat("<"..SetMan.GetString(21).."> В скрипте KarmaBot обнаружена ошибка!!! Проверьте параметр sType!!! Его значени должно быть равно sIP или sNick")
ScriptMan.StopScript("KarmaBot.lua")
end
...
end
Вот оно и отключение, сразу после запуска, при запущенной PtokaX, без вывода ошибок(хотя, должно в оп-чат отсылаться).

Автор: Wariner 11.1.2009, 17:06

эх как всегда я на ровном месте.... beat_brick.gif Спасибо

Автор: lOKO1 11.1.2009, 17:22

Подскажите, если кто знает php, как будет выелядеть код ниже в LUA с использованием библиотек PXLuaSocket?

Код
$file = file("http://mysite.org/$QUERY_STRING");
$file = @implode("", $file);
echo "$file";


Спасибо!

Автор: Sephiroth_Lukaw 11.1.2009, 17:37

Код
http = require("socket.http")
file = http.request("http://mysite.org/"..QUERY_STRING) // функция file - возвращяет результат в виде массива, http.request - получает в виде строки, так что использовать альтернативу функции implode в lua - не нужно. QUERY_STRING - Нужно определить.
Core.SendToAll(file) //Отправит в чат(просто SendToAll- если API 1, либо использовать print - если речь идёт не о PtokaX)

Автор: Wariner 12.1.2009, 20:05

наткнулся тут на старые скрипты во всех есть DataArrival(user, data) Я так понимаю это сегодняшняя ChatArrival()?

Автор: Setuper 12.1.2009, 21:00

Правильно думаешь

Автор: Al-j® 14.1.2009, 0:02

А интересует напосредственно пропуск команды в чат... Как этого НЕ допустить? Я когда-то пробовал на API1 и у меня получилось исключить пропуск команды +radio для G-Bot в чат, на API2 не смог, да и не помню как на первую прописывал, думаю эта информация пригодится многим

Автор: Setuper 14.1.2009, 0:06

для api1: return 1
для api2: return true

Автор: Wariner 15.1.2009, 19:56

где ошибка в следующем коде. Глаз замылился не могу понять...

Код
local _,_,RateNumber,One,Two,Three,Four,Five,Six = string.find(Rate, "%s*(%d+)%(%s*(%S+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)")

Автор: Setuper 15.1.2009, 20:58

вроде всё верно, смотря что надо захватывать)))

пример строки для захвата:

Код
"  473(   word    7634   3847   3478  5365 998"

Автор: Wariner 15.1.2009, 21:07

вот так работает

Код
        local _,_,RateNumber = string.find(Rate, "%s*(%d+)")
        local _,_,One = string.find(Rate, "%s*%d+%(%s*(%S+)")
        local _,_,Two = string.find(Rate, "%s*%d+%(%s*%S+%s+(%d+)")
        local _,_,Three = string.find(Rate, "%s*%d+%(%s*%S+%s+%d+%s+(%d+)")
        local _,_,Four = string.find(Rate, "%s*%d+%(%s*%S+%s+%d+%s+%d+%s+(%d+)%")
        local _,_,Five = string.find(Rate, "%s*%d+%(%s*%S+%s+%d+%s+%d+%s+%d+%s+(%d+)")
        local _,_,Six = string.find(Rate, "%s*%d+%(%s*%S+%s+%d+%s+%d+%s+%d+%s+%d+%s+(%d+)")

вот так нет
Код
        local _,_,RateNumber,One,Two,Three,Four,Five,Six = string.find(Rate, "%s*(%d+)%(%s*(%S+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)")

в последнем варианте все параметры равны nil

Автор: Setuper 15.1.2009, 21:18

Не может такого быть! Всё работает и тот и другой код:

Код
local Rate="  473(   word    7634   3847   3478  5365 998"
function OnStartup()
  local _,_,RateNumber = string.find(Rate, "%s*(%d+)")
  local _,_,One = string.find(Rate, "%s*%d+%(%s*(%S+)")
  local _,_,Two = string.find(Rate, "%s*%d+%(%s*%S+%s+(%d+)")
  local _,_,Three = string.find(Rate, "%s*%d+%(%s*%S+%s+%d+%s+(%d+)")
  local _,_,Four = string.find(Rate, "%s*%d+%(%s*%S+%s+%d+%s+%d+%s+(%d+)")
  local _,_,Five = string.find(Rate, "%s*%d+%(%s*%S+%s+%d+%s+%d+%s+%d+%s+(%d+)")
  local _,_,Six = string.find(Rate, "%s*%d+%(%s*%S+%s+%d+%s+%d+%s+%d+%s+%d+%s+(%d+)")
  Core.SendToAll(tostring(RateNumber).." "..tostring(One).." "..tostring(Two).." "..tostring(Three).." "..tostring(Four).." "..tostring(Five).." "..tostring(Six))
end


Код
local Rate="  473(   word    7634   3847   3478  5365 998"
function OnStartup()
  local _,_,RateNumber,One,Two,Three,Four,Five,Six = string.find(Rate, "%s*(%d+)%(%s*(%S+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)")
  Core.SendToAll(tostring(RateNumber).." "..tostring(One).." "..tostring(Two).." "..tostring(Three).." "..tostring(Four).." "..tostring(Five).." "..tostring(Six))
end

Автор: Wariner 15.1.2009, 22:02

А что значат буквы RC в версиях программ(скриптов)? shame.gif

Автор: Setuper 15.1.2009, 22:17

RC - сокращение от Release Candidate. Дословно переводится как релиз-кандидат, по русски говорять предварительная версия

В предыдущем вопросе разобрался? Что не так у тебя было?

Автор: Wariner 15.1.2009, 23:03

Нет пока не разобрался.... Почему то когда начинаю писать скрипты работающие с приватом начинаются проблемы((((

Код
    if tStatAR[tUser.sNick].Type == "ReceRates" then
        local _,_,RateMoney = string.find(sData, "$To:%s%S+%sFrom:%s%S+%s$%S+%s+(%d+)")
        local _,_,Rate = string.find(sData, "$To:%s%S+%sFrom:%s%S+%s$%S+%s+%d+%s+(.*)")
        Core.SendPmToUser(tUser, sBot, "sss: "..Rate)
        local _,_,RateNumber,One,Two,Three,Four,Five,Six = string.find(Rate, "%s*(%d+)%s+%(%s*(%S+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)")
        if ((To == sBot) and (Rate) and (RateMoney)) then
        Core.SendPmToUser(tUser, sBot, RateNumber)
...

ввожу
Цитата
100 2(10 11)


до последнего часа думал что я понимаю захваты и рег выражения.....
Код
local _,_,a,b,c,d = string.find(msg,"(%d+)%s*%S+%s*(%d+)%s*%S+%s*(%d+)%s*%S+%s*(%d+)")

ввожу
Цитата
10.2.101

результат
Цитата
a=10 b=2 c=1 d=1

Что я опять делаю не так?

PS: видать последние мозги сессия выбила xD)))))))))))))))

Автор: Setuper 15.1.2009, 23:21

Всё верно. Не вижу ничего удивительного:

Код
(%d+)%s*%S+%s*(%d+)%s*%S+%s*(%d+)%s*%S+%s*(%d+)
(10)%s*.%s*(2)%s*.%s*(1)%s*0%s*(1)
надеюсь так понятнее?

я так понимаю, что ты хочешь сделать антирекламу?

Автор: Wariner 16.1.2009, 15:53

да я пока не хочу делать готовый скрипт, токо подбираю варианты....
по поводу цифр в скобках я и так понял, непонятно почему %d+ он находит только одну цифру а не "один или более символов" Или он стремится всем переменным присвоить значение?

Автор: Setuper 16.1.2009, 16:32

Так как это функция find, то название говорит само за себя. Эта функция пытается найти совпадения в строке с указанным регулярным выражением. %d+ означает 1 или более цифр. Функция перебирает все возможные варианты до тех пор, пока не найдёт какое-то совпадение. Сначала функция проверяет конечно же такой вариант: (10)%s*.%s*(2)%s*.%s*(101)%s*%S+%s*(%d+). Но в данном варианте в строке не найдётся совпадений из-за "хвоста": %S+%s*(%d+). Поэтому продолжается дальнейший перебор вариантов, подходящих под это регулярное выражение.

Автор: Wariner 16.1.2009, 22:29

решил проблему так:

Код
local _,_,a,b,c,d = string.find(msg,"(%d+)%s*%D+%s*(%d+)%s*%D+%s*(%d+)%s*%D+%s*(%d+)")

Setuper, а ты бы какой код посоветовал?

Автор: Setuper 17.1.2009, 0:37

Такой код не пойдет по следующей причине:

Допустим кто-то пишет так:

Цитата
1) какое-то педложение
2) ещё какое-то преложение
3) снова какое-то предложение
4) и ещё предложение


или вот так:
Цитата
сколько будет 2+2? вы думаете 4, а я думаю 3!


В данном случае любые 4 числа в предложении будут ловиться. Единственное условие - это наличие между этими числами хотя бы одного не пробельного символа! Поэтому твой вариант является наихудшим.


Предлагаю лучше сделать так:
Код
local _,_,a,b,c,d = msg:find"(%d+)%s*%p*[%p*%s*]%s*(%d+)%s*%p*[%p*%s*]%s*(%d+)%s*%p*[%p*%s*]%s*(%d+)"
в данном случае будут ловиться только числа, разделённые знаками пунктуации и/или пробелами.
К данному захвату нужно добавить ещё один из распространённых методов:
Код
local _,_,a,b,c,d = msg:find"(%d+)%s*ю%s*(%d+)%s*ю%s*(%d+)%s*ю%s*(%d+)"

Автор: Wariner 19.1.2009, 21:35

зачем мы объявляем таблицы в начале скрипта(извиняюсь если не так выразился). Я это делаю лишь для того чтоб если нет файла в который сохраняется таблица не было ошибок. А какие ещё функции несёт на себе эта операция(если вообще несёт)
Если непонятно написал то я об этом:

Код
sBot = "Protector"
tUsers = {}
tCfg = {}        <=== я вот об этом

function OnStartup()
    sPath = Core.GetPtokaXPath().."scripts/Protector/"

Автор: Setuper 19.1.2009, 21:52

Таблица - сложная структура. Объявление таблицы - это выделение под неё памяти. Под обычные переменные память выделяется автоматически, а под таблицу нужно ручное выделение, так как таблица может содержать поля.
Возможно не очень понятно объяснил big_smile.gif

Автор: Wariner 19.1.2009, 22:01

в общих чертах понятно. А можно ли это делать в функции OnStartup по средствам dofile из файла с таблицами? Точнее я пробовал можно, но нет ли каких нюансов?

Автор: Setuper 19.1.2009, 22:12

не понимаю что ты имеешь ввиду?
без разницы в каком файле объявлять, если таблица является глобальной - главное объявить))

Автор: Wariner 19.1.2009, 22:27

ок спасибо всё понял)))))

и ещё у меня две просьбы:
1) Setuper, если можешь расскажи( или покажи) как у тебя в sBot`e реализована раздача команд
2) Опять же если можешь дай(вышли на почту) открытый код скрипта Regme.(думаю мне можно ибо скрипт чтения личек напишу с закрытыми глазами.) Просто не могу работать с командами из привата((( Очень надо посмотреть что то стоящее.

Заранее спасибо!!! почта Wariner[тут_сабака]mail.ru

Автор: Wariner 20.1.2009, 21:09

если не можешь то ответь не могу)))))))))))

Автор: Setuper 20.1.2009, 21:47

1) Из бота вынуть очень сложно, тем более через бд всё.
2) Не понимаю, что тебя интересует?

Автор: ustas 20.1.2009, 23:31

не подскажете функцию для округления до нужного разряда
round (x, r) где x - само число, r - до какого разряда округлить
например round(192.168, 2) = 192.17

Автор: Setuper 21.1.2009, 0:23

Код
function round(x, r)
  return tonumber(string.format("%."..r.."f", x))
end

Автор: ustas 21.1.2009, 8:48

Блогодарю. Так все просто )

Автор: *FoxMalder* 21.1.2009, 17:00

простите что сюда) но можите написать маленький скрипт под 0360 который будет на команды +regme pass и !regme pass идти в ptokax\text и показывать в приват файл reghelp.txt ?

Автор: Wariner 21.1.2009, 19:12

Цитата(Setuper @ 20.1.2009, 21:47) *
1) Из бота вынуть очень сложно, тем более через бд всё.
2) Не понимаю, что тебя интересует?

1)мне не нужен код как таковой, мне нужен так скажем алгоритм...Какая то наводящая на правильный ход мыслей подсказка)))))
2)все скрипты работающие в привате получаются кривыми. либо на одно слово реагируют кучей команд либо молчат, либо работают но получаются очень огромными!!!

Автор: Setuper 21.1.2009, 19:37

1) Не знаю чем тебе это поможет...
Реализовано всё следующим образом: существует таблица с правами. Перечислять все столбы не буду, скажу только, что в этой таблице раздаются права на то или иное действие (раздача по ключу): будь это разрешение (или наоборот запрет) на использование той или иной команды, или на отсылку той или иной менюшки, или допустим настройки на рассылки массовых сообщений, или настройки входа, настройки отображения в списке и тд. и тп. Абсолютно все права раздаются через данную таблицу. Например, для проверки на право использовать ту или иную команду в бд отсылается запрос, и если в указанной таблице не найдено правила для данного пользователя, то действует правило по умолчанию (которое либо запрещает, либо разрешает использование). Правило по умолчанию находится в отдельной таблице всех правил по умолчанию. Правило для пользователя может искаться по разным параметрам. Вот некоторые параметры поиска правила: поиск по ip, поиск по нику, поиск по тегу, поиск по описанию, поиск по слотам, поиск по шаре и так далее...

Не уверен, что ты понял всю мощь, и не уверен, что это тебе поможет))) Тем и интересны мультиботы, из-за того, что возможности очень широкие.

2) Команды в приват ничем не отличаются от команд в чат!

Автор: Wariner 21.1.2009, 19:43

Спасибо. Понимаю то я многое, но пока не знаю как это реализовать так чтоб и раздавалось всё правильно и профили сво можно было легко поставить.

Автор: Setuper 21.1.2009, 20:04

2*FoxMalder*:

Код
function ChatArrival(tUser,sData)
  if sData:find"[!+/][Rr][Ee][Gg][Mm][Ee]%s+.*|" then
    local f=io.open((Core and Core.GetPtokaXPath() or frmHub:GetPtokaXLocation()).."texts/reghelp.txt")
    if f then
      if Core then Core.SendPmToUser(tUser,SetMan.GetString(21),f:read("*all")) else tUser:SendPM(frmHub:GetHubBotName(),f:read("*all")) end
      f:flush()
      f:close()
      return Core and true or 1
    end
  end
end



Чем больше пытаешься сделать, тем больше понимаешь недостатки PtokaX. Поэтому уже пишу свой хаб, который будет поддерживать lua, и в котором я устраню те недостатки, которые есть в PtokaX))))

Очевидные недостатки:
1) Неверно работает функция MyINFOArrival. На мой взгляд она должна срабатывать до отсылки строки MyINFO, и в случае, если данная функция возвращает true, MyINFO строка не должна отсылаться, в противном случае строка должна отправляться ОДИН раз!
2) Неверно работает функция PasswordArrival. Функция должна срабатывать не только в случае ввода правильного пароля. Функция должна возвращать значение: true - пароль не проверяется, false - пароль проверяется.
3) Неверно работает частичная отсылка строки MyINFO.
4) Неверно отправляется пользователю информация о главном боте хаба. Информация должна отправляться в функции GetNickListArrival.
5) Неверное хранение базы пользователей в xml файле обусловлено тормозами при большой базе.

Автор: *FoxMalder* 21.1.2009, 20:14

Setuper
lua:5: '=' expected near 'and'

насчет "pass" я имел в виду любой пароль который вводит юзер)

Автор: Setuper 21.1.2009, 20:31

Код
sData:find"[!+/][Rr][Ee][Gg][Mm[Ee]%s+.*|"
- интересно как в данном случае у тебя будут пользователи регаться если по данной команде будет выдаваться файл?

это я просто универсальный скрипт пишу под оба API
Код
if Core then Core.SendToUser(tUser,f:read("*all")) else tUser:SendData(f:read("*all")) end


Исправил недочёты. Смотри полный код.

Автор: *FoxMalder* 21.1.2009, 20:37

команда к регистрации другая

и над чтоб это сообщение отсылалось в пм юзеру)

Автор: Setuper 21.1.2009, 20:46

Зачем регистрироваться другой командой, когда все уже привыкли юзать эту? Не понятен смысл

Обновил код для отправки в пм

Автор: *FoxMalder* 21.1.2009, 20:53

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

Автор: serrrios 9.2.2009, 16:56

Только начал пробывать писать, накидал тут пару строк под апи2:

Код
function Core.OnStartup()
    TmrMan.AddTimer(60000, " Func1")
end

function Func1()
  ScriptMan.RestartScript(scripts/123.lua)
end


Сам 123.lua
Код
Core.SendToAll("тест")


Выдает: \restart.lua:6: malformed number near '123.lua'
Почему может не работать?

Автор: Setuper 9.2.2009, 16:59

Пишется так

Код
ScriptMan.RestartScript("123.lua")
но этот скрипт правильно работать не будет)))

Автор: serrrios 9.2.2009, 18:55

Цитата(Setuper @ 9.2.2009, 16:59) *
Пишется так
Код
ScriptMan.RestartScript("123.lua")

Спасибо, в документациях не заметил чет / А абсолютный путь не нужно указывать? Просто видел много скриптов которые ругались на это.
Цитата(Setuper @ 9.2.2009, 16:59) *
но этот скрипт правильно работать не будет)))

Соответственно вопрос почему? И как реализовать правильно? big_smile.gif

Автор: Setuper 9.2.2009, 19:27

Вот так работать будет, и только на API1

Код
dofile(frmHub:GetPtokaXLocation().."scripts/old_api.lu")
function Core.OnStartup()
    TmrMan.AddTimer(60000, "Func1")
end

function Func1()
  Core.SendToAll("тест")
end


Соответственно для API2 вот так:
Код
function OnStartup()
    TmrMan.AddTimer(60000, "Func1")
end

function Func1()
  Core.SendToAll("тест")
end


Вообще говоря скажи в чём задача состоит и знаешь ли ты, что используешь метод быстрого перевода под api1?

Автор: *FoxMalder* 12.2.2009, 22:54

какое кол-во строк может быть максимально в действиях (чтоб не сильно нагружать хаб\клиент)?? (О>,<О)
и вообще затрудняют ли они (действия) когда их много)) вход на хаб?

Автор: Setuper 12.2.2009, 23:12

Если уж на то пошло, то любой скрипт грузит хаб. Не парься с количеством действий.

Автор: *FoxMalder* 19.2.2009, 1:03

ну ладно.. просто существует некая проблема с входом на хаб... да и замечал пару раз что менюшки не все грузились

и вот такой еще вопросец

можно ли поставить разделитель сразу после 1 менюшки тоесть..

1 менюшка -> 2 менюшка
---------------- разделитель
1 менюшка -> 2 менюшка
---------------- разделитель

надеюсь понятно обьяснил shocked.gif

Автор: Setuper 19.2.2009, 1:15

Универсального способа подо все клиенты нету, однако на некоторых клиентах (на большинстве) проходит следующий код:

Код
Core.SendToUser(tUser,"$UserCommand 1 3 Меню\\Команда$<%[mynick]> !cmd&#*124;|"..
"$UserCommand 1 3 $<%[mynick]>&#*124;|$UserCommand 0 3&#*124;")
* - удалить

Автор: *FoxMalder* 19.2.2009, 1:22

Ну раз под все клиенты не подходит то поставим старое доброе _ )

спасиб =)

Автор: Setuper 19.2.2009, 1:27

В смысле старое доброе?

Под основные клиенты подходит (DC++, Strong, Apex, Pelink, Greylink, Flylink). Под другие не тестировал, однако помнится, что на каком-то клиенте разделитель не появлялся (не помню что за клиент был).

Автор: *FoxMalder* 19.2.2009, 2:44

в смысле старое доброе "нижнее подчеркивание" _____ ;)
мне так даже больше нравится =)

Автор: *FoxMalder* 21.2.2009, 20:53

Цитата(Setuper @ 12.2.2009, 23:12) *
Если уж на то пошло, то любой скрипт грузит хаб. Не парься с количеством действий.


кстате ты не прав когда онлайн подбирается к 2к народу из-за действий и инфо_в_меню на хаб становится невозможно зайти..
он заходит тока через 1-10 минут после того как появится "PtokaX DC Hub 0.3.6.0" ...

над с этой менюшкой делать что то beat_plaster.gif

p.s. может можно сделать что бы действия загружались после того как юзер зашел на хаб? или частично (в смысле не все сразу, а по частям)

Автор: Wariner 21.2.2009, 21:05

почитай вот это: http://mydc.ru/ipb.html?s=&showtopic=639&view=findpost&p=4763 там есть про меню!

Автор: Setuper 21.2.2009, 21:09

1) Просто надо оптимизировать отправку. Наверняка в твоём скрипте действий происходит многократный вызов функции отправки, что сильно нагружает. Например, можно отправлять так:

Код
Core.SendToUser(tUser,"$UserCommand 1 3 Меню\\Команда1$<%[mynick]> !cmd1&#*124;")
Core.SendToUser(tUser,"$UserCommand 1 3 Меню\\Команда2$<%[mynick]> !cmd2&#*124;")
Core.SendToUser(tUser,"$UserCommand 1 3 Меню\\Команда3$<%[mynick]> !cmd3&#*124;")
Core.SendToUser(tUser,"$UserCommand 1 3 Меню\\Команда4$<%[mynick]> !cmd4&#*124;")
...
Core.SendToUser(tUser,"$UserCommand 1 3 Меню\\КомандаN$<%[mynick]> !cmdN&#*124;")
* - удалить.

Но намного оптимизированнее отправлять так:
Код
Core.SendToUser(tUser,"$UserCommand 1 3 Меню\\Команда1$<%[mynick]> !cmd1&#*124;|"..
"$UserCommand 1 3 Меню\\Команда2$<%[mynick]> !cmd2&#*124;|"..
"$UserCommand 1 3 Меню\\Команда3$<%[mynick]> !cmd3&#*124;|"..
"$UserCommand 1 3 Меню\\Команда4$<%[mynick]> !cmd4&#*124;|"..
...
"$UserCommand 1 3 Меню\\КомандаN$<%[mynick]> !cmdN&#*124;")
* - удалить.
Во втором случае функция отправки вызывается всего 1 раз, а клиент уже сам разберётся и разделит отправленную строку на несколько менюшек.
2) Скрипт действий лучше ставить последним в списке всех скриптов, так как менюшки можно отослать и после того как вошёл на хаб.
3) Не советую использовать скрипт действий, в котором для разных пользователей показывается разный текст действий, так как этот скрипт в отличии от обычного скрипта действий в разы больше потребляет ресурсов из-за наличия обработки действий.

Автор: *FoxMalder* 21.2.2009, 22:29

вот так я и сделаю =) правдо переделывать весь скрип я буду дооолго(

на 1 апи это будет выглядеть так? big_smile.gif

Код
user:SendData("$UserCommand 1 3 Меню\\Команда1$<%[mynick]> !cmd1&#*124;|"..
"$UserCommand 1 3 Меню\\Команда2$<%[mynick]> !cmd2&#*124;|"..
"$UserCommand 1 3 Меню\\Команда3$<%[mynick]> !cmd3&#*124;|"..
"$UserCommand 1 3 Меню\\Команда4$<%[mynick]> !cmd4&#*124;|"..
"$UserCommand 1 3 Меню\\КомандаN$<%[mynick]> !cmdN&#*124;")

Автор: Wariner 21.2.2009, 22:31

естественно)))

Автор: *FoxMalder* 21.2.2009, 22:35

и еще можно сделать так чтоб те ники которые есть в этом скрипте при использование /me писали [Время] *** nick2 text?

Код
tNames = {
  ["nick1"] = "nick2",
}
    
function ChatArrival(curUser,data)
  if tNames[curUser.sName] then
    SendToAll(tNames[curUser.sName],data:sub(curUser.sName:len()+4,-2))
    return 1
  end
end

Автор: *FoxMalder* 24.2.2009, 20:22

*** яидиот... оказывается лагало не из-за действий, а из-за "ограничение входа N юзеров за 10 сек". Теперь вход на хаб отличный и наконец-то лагать перестало) нагрузка цп не больше 20% в пик юзеров big_smile.gif *счастлив за хаб*

Автор: IIPu3PAK 20.3.2009, 1:50

1) вопрос -- есть строчка SendToAll("blablabla") почему она выводится ПОСЛЕ следующей за этой строчкой строкой?

CODE
local c = string.char
local sDatagram = c(0xFF)..c(0xFF)..c(0xFF)..c(0xFF)..c(0x54)..c(0x53)..c(0x6F)..c(0x75)..
c(0x72)..c(0x63)..c(0x65)..c(0x20)..c(0x45)..c(0x6E)..c(0x67)..c(0x69)..c(0x6E)..
c(0x65)..c(0x20)..c(0x51)..c(0x75)..c(0x65)..c(0x72)..c(0x79)..c(0x00) ---это основной запрос всем source и goldscr серверам
local sServerIp = {"81.9.25.202","tf.csmania.ru",} -- суда вписываем айпи своего сервера
local sServerPort = {"27013","27016",} -- суда вписываем порт своего сервера
local iTimeOut = 1 -- таймаут соединения на получение
local iBuferSize = nil -- размер буфера (nil - стандартный)
BotName = "Курильщик" -- имя бота
BotDesc = "Закуривай;)" -- описание бота
BotEmail = "hub@mail.ru" -- email бота
----------------------------------------------------------------------------
-- loads the socket module
socket = require("socket")

myudp = socket.udp()

myudp:settimeout(iTimeOut)

function Main()
SetTimer(1000)
frmHub:RegBot(BotName, 1, BotDesc, BotEmail) --регистрируем бота на хабе
end

function CorrectData(sData, sReplace)
local sStr, iSmb = ''
for i = 1, sData:len() do
iSmb = sData:byte(i)
if iSmb > 243 and iSmb < 256 then
sStr = sStr..sReplace
elseif iSmb > 31 then
sStr = sStr..string.char(iSmb)
elseif iSmb < 1 then
sStr = sStr..sReplace
elseif iSmb >= 1 then
sStr = sStr..iSmb
end
end
return sStr
end


function ChatArrival(tUser, sData)
local sCmd = sData:match"%b<> !л4д"
if sCmd then
for i = 1,table.getn(sServerIp) do
myudp:setpeername(sServerIp[i], sServerPort[i])
local _, sError = myudp:send(sDatagram, sServerIp[i], sServerPort[i])
local bData, sError = ReceiveData()
if not sError and bData then
local z = CorrectData(bData,'?'):sub(7)
local sName, sMap, sTyp, sType, ilen, iTotal, sVersion = z:match"(.-)?(.-)?(.-)?(.-)?(.+)"
if sName then
if sName==sName:match"(%d*%p%d+%p%d+%p%d+:%d+)" then
k=sMap
sMap=sTyp
l=sType
sType=k
sName=k
end
iPlayers, iTotal, sVersion = ilen:sub(3):match"(%d*)(%d)(.+)"
if iPlayers:len() >1 then
iPlayers, iTotal, sVersion = ilen:sub(3):match"(%d*)(%d%d)(.+)"
end
if zlen then
iTotal="32"
iPlayers=ilen:sub(3):match"(%d*).+"
end
sVersion = sVersion:match"(%d%p%d+%p%d+%p%d+)"
iPlayers = iPlayers~='' and iPlayers or 0
SendToAll("blablabla") --написано до следующих строчек а выводится после них
tUser:SendData("Курильщик"," Айпи адрес сервера---> "..sServerIp[i]..":"..sServerPort[i]..""..
"|<Курильщик> Название сервера---> "..tostring(sName)..
"|<Курильщик> Карта на сервере---> "..tostring(sMap)..
"|<Курильщик> Тип и сложность игры---> "..tostring(sType)..
"|<Курильщик> Игроков на сервере---> "..tostring(iPlayers).."/"..tostring(iTotal)..
"|<Курильщик> Версия сервера---> "..tostring(sVersion)..
"|<Курильщик> =======================================")
end
end
end
return 1
end
end

function OnExit()
myudp:close()
end
OnError = OnExit

function ReceiveData()
local sData, sError = myudp:receive(iBuferSize)
if sError then
-- ошибка!
return nil, sError
end
return sData
end



function NewUserConnected(tUser)
tUser:SendData("$UserCommand 1 3 Left4Dead\\Мониторинг наших серверов$<%[mynick]> !л4д||")
end
OpConnected=NewUserConnected


2)если я пишу Unban("172.25.188.23") или Unban(172.25.188.23) то в 1 случае мне пишут что невозоможно вызвать функцию со значением НИЛ , а во 2 случае неправильный синтаксис... и даже если я вместо айпи пишу ник Ошибки теже самые (забанил через Пкм в птохе где Юзер/чат)

оба вопроса относятся к Апи1 , в 1 вопросе даны рабочие интернет-сервера для проверки

Автор: Setuper 20.3.2009, 2:29

1) Так устроена функция SendToAll. Вызывая её, мы помещаем данные в "глобальную очередь". Это связано с производительностью. Сначала отсылаем то, что можно быстро отослать, а потом уже всё, что находится в "глобальной очереди". Считается, что это ускоряет процесс отсылки нескольких сообщений подряд, однако на практики разницы никогда не ощутишь))

Если не нравится то, что сообщения помещаются в глобальную очередь, то можно отсылать всем юзерам по отдельности:

Код
for _,v in pairs(frmHub:GetOnlineUsers()) do
  v:SendData(sData)
end


2) Первый вариант должен работать. Это может быть баг ptokax, у меня на 0.3.5.2f эта функция работает.


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

Автор: IIPu3PAK 20.3.2009, 13:06

1)

Цитата
Сначала отсылаем то, что можно быстро отослать

Фактически если смотреть мониторинг сервера то данные могут приходить с запозданием в секунду и причем SendToAll тот который написан(он фактически у мну пишется 2 раза т.к. забито 2 айпи) но всеравно все 2 раза приходят в чат скопом после ВСЕГО мониторинга а не его части
2)под птоха 3.6.0 ну вообще нивкакую

function ChatArrival(tUser,sData)
Unban("172.25.188.23")
end

Должна работать?

Автор: Setuper 20.3.2009, 13:49

Ну я же говорю, что данное сообщение ставится в "глобальную очередь", и оно не будет отсылаться, пока не бетед отослана вся "локальная очередь". Что тут не понятно? Не нравится, - я предложил альтернативный вариант.

Автор: IIPu3PAK 20.3.2009, 14:56

Цитата(Setuper @ 20.3.2009, 14:49) *
Ну я же говорю, что данное сообщение ставится в "глобальную очередь", и оно не будет отсылаться, пока не бетед отослана вся "локальная очередь". Что тут не понятно? Не нравится, - я предложил альтернативный вариант.

вот теперь все понятно....
остался вопрос №2

Автор: Setuper 20.3.2009, 15:30

0.3.6.0:  PtokaX.rar ( 729.03 килобайт ) : 1


Работает.

Автор: vicious 31.3.2009, 13:00

Core.GetUserData(tUser, nValueId) - Добавляет или обновляет данные с указанным идентификатором в таблице пользователя. Возвращает nil в случае неудачи (пользователь оффлайн) или true в случае успеха.

Подскажите, как добавить то?
Вообщем нужно следущее:
При подключении изера идет проверка Core.GetUserValue(tUser,5). Если проверку не проходит, то надо чтобы эта строка (строка Email) у него отображалась пустой на хабе. Как это сделать?

Автор: Setuper 31.3.2009, 13:25

В том-то и дело, что никак.

Функция GetUserData добавляет в таблицу tUser поле, которому отвечает идентификатор nValueId, если это поле не добавлялось ранее в эту таблицу. Если поле было добавлено ранее, то данная функция обновляет данные в этом поле.

Внесение изменений самому в это поле невозможно. Единственный выход - это установка отправки полной строки MyINFO по таймеру.

То, что ты хочешь реализовать легко реализуется в скриптах HexHub, так как там можно заблокировать действие любой команды со стороны клиента, в том числе и команды $MyINFO.

Это можно было бы реализовать в PtokaX, если бы получаемые данные MyINFO от пользователя можно было бы блокировать в функции MyINFOArrival, допустим путём возвращения этой функцией значения true (как это делает, например, функция ChatArrival).

К сожалению функционал ptokax не столь разнообразен, и это явный недостаток.

Автор: vicious 31.3.2009, 13:39

Суть ,как ты наверное догадалася уже, была в том чтобы скрывать поля nValueId (к примеру если там реклама какая-нибудь), т.е. все что можно сделать это только отключать (ну и т.д.) юзеров, которые не прошли проверку?

Цитата
Единственный выход - это установка отправки полной строки MyINFO по таймеру.


Вот это не понял, поясни пожалуйста!

З.Ы.:
Есть хаб dchub://exclusive.maryno.net он на Птоке 0.4.1.1
на нем это как-то реализовано. Чем бы я не заполнял поля Description , на хабе оно пустое отображается (и так у всех)

Автор: Setuper 31.3.2009, 14:04

Нет. Я же сказал, что реализовать можно, но только по средствам таймера отсылки.

То есть смысл вот в чём.
Описание, email, шара, тэг и тд. - все эти параметры хаб получает от пользователя через отправку на хаб пользователем команды $MyINFO.
В PtokaX есть функция, которая перехватывает эту команду. Это функция MyINFOArrival. Эта функция выполняется каждый раз, когда пользователь отсылает на хаб команду $MyINFO.

Команда $MyINFO отсылается клиентом пользователя на хаб автоматически, например, после обновления шары или после установки режима away, или после обновления любого другого параметра, который входит в команду $MyINFO.

После отправки пользователем на хаб этой команды, команда поступает в функцию MyINFOArrival, но так как эта функция не блокирует эту команду, то после выполнения этой функции (MyINFOArrival), эта команда будет транслирована хабом всем пользователям хаба.

Ну так вот, например, пользователь Вася отправляет эту команду:

Код
$MyINFO $ALL Вася Описание<StrgDC++ V:2.22,M:A,H:1/2/0,S:5>$ $Modem$email$26937284354$|

Команда поступает в функцию MyINFOArrival в качестве параметра sData:
Код
$MyINFO $ALL Вася Описание<StrgDC++ V:2.22,M:A,H:1/2/0,S:5>$ $Modem$email$26937284354$|

В этой функции мы пытаемся отправить всем пользователям другие данные, например, заменив email на 123:
Код
function MyINFOArrival(tUser, sData)
  sData = sData:gsub(sData:match"%$(.-)%$.-%$|$", "123")
  Core.SendToAll(sData)
end


Но после окончания выполнения этой функции, так как функция не блокирует пересылку этой команды всем пользователям, всем пользователям отправятся те самые данные, которые мы так тщательно пытались заменить.


Поэтому выход из этой ситуации таков: переждать пока функция MyINFOArrival перешлёт эту команду всем пользователям и только после этого отсылать свои подкорректированные данные:
Код
local tTimers = {}
local iInterval = ???

function MyINFOArrival(tUser, sData)
  local iIdTimer = TmrMan.AddTimer(iInterval, "Timer")
  tTimers[iIdTimer] = sData
end

function Timer()
  for i,w in pairs(tTimers) do
    Core.SendToAll(w:gsub(w:match"%$(.-)%$.-%$|$", "123"))
    tTimers[i] = nil
    TmrMan.RemoveTimer(i)
  end
end


При всём сказанном, колоссальное значение имеет выбор параметра iInterval, так как при большом количестве народа за это время (iInterval), если оно мало, данные команды $MyINFO могут ещё не быть разостланы всем пользователям. Поэтому данный параметр должен подстраиваться под количество народу на хабе и под производительность сервера. Поэтому реализовать можно, но сложно и геморно.

Автор: vicious 31.3.2009, 14:11

Я там изменил свое сообщение, не поглядишь тот хаб который я указал, думаешь у них именно так реализовано?
Спасибо за ответ!!!!

Автор: Setuper 31.3.2009, 14:19

Ну это просто сделать: входишь в настройки -> Моя информация -> убираешь галочку со строки описания.
Убрать полностью - это не значит заменить big_smile.gif

Автор: vicious 31.3.2009, 14:39

не не не! Как раз информацию то я вводил, как и многие другие там....но на хабе поля эти пустые когда подключаюсь)
Т.е. перед подключением я заполняю поле у себя Description, подключаюсь на хаб...а оно отображается пустым там.

Вот именно так нужно...т.е. чтобы ни писали юзеры у себя в описании и в емайле...на хабе оно отображается пустым, как у них.

Автор: Setuper 31.3.2009, 14:59

Ну да. Это в настройках хаба ставиться. Именно там, где я и сказал. И чтобы ты не написал - оно отображаться ни для кого не будет.

Автор: vicious 31.3.2009, 15:07

Еще 1 вопрос:
При определенном событии (условии) нику посылается сообщение.
К примеру Core.SendPmToNick(tUser.sNick, "Тест PM", "<"..tUser.sNick.."> "..whoTo..": "..chat.."" )
Ника такого, конечно не существует. Когда юзер отвечает ему в (в PM ессно) то его отключает от хаба. Не подскажите почему такое может происходить?




Цитата(Setuper @ 31.3.2009, 14:59) *
Ну да. Это в настройках хаба ставиться. Именно там, где я и сказал. И чтобы ты не написал - оно отображаться ни для кого не будет.


Спасибо, вот это я нуб!)))

Автор: Setuper 31.3.2009, 15:34

С личкой шутки плохи))
Все операции с личными сообщениями пользователей не нужно производить!

Автор: vicious 31.3.2009, 15:47

Я знаю что здесь запрещенны скрипты в которых это может быть использовано, однако скрипт я уже написал, выкладывать ессно не буду. Да и у себя не использую, но суть не в этом...я хочу понять почему при ответе этому не существующему нику, юзера отключает. Если например от ССкрипта написать - то при ответе не отключит, а здесь отключает...хочу понять почему, чисто для себя, ибо мне и не нужно впринципе чтобы туда кто-нить отвечал!!! Но понять хочется.

Автор: alex82 31.3.2009, 19:22

Цитата
К примеру Core.SendPmToNick(tUser.sNick, "Тест PM", "<"..tUser.sNick.."> "..whoTo..": "..chat.."" )

Ник юзера не может содержать пробелов - это нарушение протокола NMDC. А отключает, видимо, за неизвестную команду.

Автор: *FoxMalder* 3.4.2009, 18:11

из-за чего могут вылетать все скрипты с ошибкой "No space left on device"? помогает включить их обратно тока перезагрузка хаба

Автор: vicious 3.4.2009, 18:59

Подскажите как из string - число получить.
Суть в следующем. к примеру - временный бан. Меню - временно забанить. Щелкаем - вводим ник, время, причину.
Время у нас получается string и поэтому когда я захватываю его и использую в BanMan.Ban мне ессно выдается ошибка.
Как правильно делать? Заранее пасиба за ответ!.
Вот необходимые части кода чтобы понять в чем проблема:

Код
Core.SendToUser(tUser, ""..hMenu.."\Временно забанить юзера$<%[mynick]> !ptban %[line:Введите ник] %[line:Введите время бана в минутах] %[line:Введите причину]|")

function ChatArrival(tUser, sData)
sData = string.sub(sData,1,-2)
local _,_,data = string.find(sData, "%b<>(.*)")
local _,_,cmd = string.find(sData, "%b<>%s+(%S+)")

if cmd == "!ptban" then
    local _,_,nick,sTime,sReason = string.find(sData, "%b<>%s+%S+%s+(%S+)%s+(%S+)%s+(.*)")
    local nick = Core.GetUser(nick)
    BanMan.TempBan(nick,sTime,sReason,sBot,false)
    return true
end
end

Автор: alex82 3.4.2009, 19:20

Цитата(vicious @ 3.4.2009, 18:59) *
Подскажите как из string - число получить.
tonumber(<строка>)

Автор: Setuper 3.4.2009, 19:22

Код
if cmd == "!ptban" then
  local nick,sTime,sReason = sData:match"%b<>%s+%S+%s+(%S+)%s+(%d+)%s+(.*)"
  if nick then
    local nick = Core.GetUser(nick)
    BanMan.TempBan(nick,tonumber(sTime),sReason,sBot,false)
    return true
  end
end

Автор: vicious 3.4.2009, 19:23

Цитата(alex82 @ 3.4.2009, 19:20) *
tonumber(<строка>)

Спасибо!

Автор: Setuper 3.4.2009, 19:37

Обрати внимания и на другие изменения

Автор: Master-Grow 3.4.2009, 23:25

Народ и какже из птоки 0.3.6.0 переконвертировать скрипы на 0.4.1.1 ??

Автор: Setuper 3.4.2009, 23:32

Руками или кнвертером

Автор: vicious 4.4.2009, 16:15

Цитата(Setuper @ 3.4.2009, 19:37) *
Обрати внимания и на другие изменения

Видел, это понятно, я просто для примера показывал.

У меня опять вопрос!!!
Как получить кол-во строк в текстовом файле, и как к примеру выводить (в чат) определенные строки.
к примеру у меня текстовый файл с кучей строк...а мне нуно вывести только последние 3...как это реализовать?

И еще одно...дайте пожалуйста прямую ссылку(если таковая есть) на описание (желательно понятное и полное) функции
"Serialize". Хочу разобрать ее. Или если кому не сложно опишите ее, как например описали "о захватах"!
Заранее СПАСИБО!

Автор: Setuper 4.4.2009, 16:39

Код
local h = io.open(Core.GetPtokaXPath().."scripts/test.txt")
if h then
  local iCount = 0
  while h:read() do
    iCount = iCount + 1
  end
  h:seek"set"
  local sData = h:read()
  while sData  do
    iCount = iCount - 1
    if iCount < 3 then
      Core.SendToAll(tostring(sData))
    end
    sData = h:read()
  end
end


Функцию понимать не нужно, её нужно использовать. Ты сам поймёшь как она работает, когда наберёшься достаточного опыта.

Автор: vicious 4.4.2009, 18:34

Цитата(Setuper @ 4.4.2009, 16:39) *
Код
local h = io.open(Core.GetPtokaXPath().."scripts/test.txt")
if h then
  local iCount = 0
  while h:read() do
    iCount = iCount + 1
  end
  h:seek"set"
  local sData = h:read()
  while sData  do
    iCount = iCount - 1
    if iCount < 3 then
      Core.SendToAll(tostring(sData))
    end
    sData = h:read()
  end
end


Функцию понимать не нужно, её нужно использовать. Ты сам поймёшь как она работает, когда наберёшься достаточного опыта.


Спасибо..все разобрал функцию. По поводу строк тоже спасибо, щас попробую.

Автор: vicious 6.4.2009, 16:08

ScriptMan.GetScript() - Возвращает таблицу этого скрипта с полями sName, bEnabled, iMemUsage.
Аналог API 1: нету

ScriptMan.GetScripts() - Возвращает таблицу всех скриптов с полями sName, bEnabled, iMemUsage.
Аналог API 1: нету

Вопрос! А как получить таблицу конкретного скрипта? к примеру у меня есть скрипт "abc" в птоке...мне надо узнать другим скриптом, запущен он или нет? Подскажите плз!

Автор: vicious 6.4.2009, 18:08

спасибо, я ужо сам догнал....просто не успел отписаться что уже не надо)

Я тут просто вот что решил написать...написал скриптик, который позваляет писать код прям в чат...и этот код будет выполняться! т.е. пишу код, автоматические создается скрипт с этим кодом и запускается...(плюч немного функциональности добавил)...но посути получилось что теперь можно использовать в качестве команд - функции ...не знаю делал кто-нить подобное или нет, то чет захотелось сделать этот скрипт посерьезней..буду грейдить дальше)

пока сделал так:..пишу команду в AM !conf мне приходит личка, в которой уже предалагается выбрать необходимую функцию и вписать в нее код. На данное время выбор 3 функций : OnStartup() - позволяет выполнить моментально любой код, ChatArrival - ну тут можно пофантазировать, ToArrival() -и тут тоже. После выбора функции предлагается ввести нужный код. и автоматически создается луа файлик с выбранной функцией и написанным кодом в ней, запускается и ессно выполняется...

Автор: Wariner 6.4.2009, 18:14

мне кажется надо быть аккуратным с такого рода скриптами! Мало ли кто и какой код может написать!

Автор: Setuper 6.4.2009, 18:16

Хм... Это же элементарно делается. Только вот не знаю что в этом хорошего.
Я всегда стараюсь избежать несанкционированного выполнения кода. Инкапсуляция - один из принципов ООП.

Когда выйдет в свет SBot, то ты сможешь увидеть действительную работу инкапсуляции - практически всё защищено, и практически ничего нельзя использовать "глобально". Все переменные исключительно локальные, или как принято в с++ - privat data. Кстати говоря, быстрее всего lua работает именно с локальными переменными. Это в частности связанно с уровнями lua стека. Доступ к переменным на том же уровне является наибыстрейшим.

Автор: vicious 6.4.2009, 18:27

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

Цитата(Setuper @ 6.4.2009, 18:16) *
Когда выйдет в свет SBot, то ты сможешь увидеть действительную работу инкапсуляции - практически всё защищено, и практически ничего нельзя использовать "глобально". Все переменные исключительно локальные, или как принято в с++ - privat data. Кстати говоря, быстрее всего lua работает именно с локальными переменными. Это в частности связанно с уровнями lua стека. Доступ к переменным на том же уровне является наибыстрейшим.


Вот это вот непонял...и про какой SBot тоже не понял! Если не сложно расскажи...

Автор: Wariner 6.4.2009, 18:45

См подпись и вот это http://mydc.ru/topic285s0.html?start=0 .

Автор: vicious 7.4.2009, 19:46

Добрый вечер! Очередной вопрос:
Есть к примеру таблица:

Data = {
["Index"] = "8",
["vicious"] = "test",
}

Как мне из нее удалить из нее ["vicious"] = "test" ???

Пробую table.remove(Data["vicious"]) - "bad argument #1 to 'remove' (table expected, got string)"...не понимаю какая разница десятичные индексы или стринговые...че не удаляется то?

Автор: Wariner 7.4.2009, 20:01

Код
Data["vicious"] = nil

table.remove работает только с числовыми индексами
кстати как сказал бы Setuper таблички лучше обозначать с буквочкой t т.е. tData)))

Автор: vicious 7.4.2009, 20:09

Спасибо...насчет буковок согласен с ним...я везде их добавляю, это я здесь только для примера...это же не цитата моего кода была)))

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

Автор: Setuper 7.4.2009, 20:10

Хехе. t можно и не писать, но если пишешь t, то придерживаешься венгерской нотации big_smile.gif Это для удобства. Так как в lua нет конкретизации в типах, то с помощью венгерской нотации мы следим за тем, какой тип имеет переменная big_smile.gif

Автор: Wariner 7.4.2009, 20:12

но ведь не обязательно полностью придерживаться.....

Автор: vicious 7.4.2009, 20:15

Цитата(Setuper @ 7.4.2009, 21:10) *
Хехе. t можно и не писать, но если пишешь t, то придерживаешься венгерской нотации big_smile.gif Это для удобства. Так как в lua нет конкретизации в типах, то с помощью венгерской нотации мы следим за тем, какой тип имеет переменная big_smile.gif

знаю знаю...просто учился в основном на ваших скриптах каких-нибудь...поэтому ессно перенимаю ваши привычки. Тоже добавляю буковки...tTable sDate tUser и т.д..

подскажите все-таки по поводу сравнивания времени. Т.е. выполнилась команда, запомнилось текущее время в переменную...и чтобы юзер больше не мог выполнять эту команду пока к примеру не пройдет 30 минут (тупо для примера). Как все это реализовать...подскажите плз...

Автор: Setuper 7.4.2009, 20:32

Код
if tData[sNick].iTime then
  if tData[sNick].iTime < os.time() then
    tData[sNick].iTime = os.time() + 1800
    --выполнение
  else
    --блокировка выполнения
  end
end