quote.tcl

Решение вопросов при работе с TCL скриптами.

Модератор: Модераторы

quote.tcl

Сообщение lzman » 23 июн 2013 22:55

Имеется скрипт цитат:
Код: Выделить всё
######################################################
# Windrop © Vladislav
# Автор: Stream mod Vladislav
# Версия: 1.4
# Описание: Скрипт канальных цитат.                           
# Команды:         !addquote <цитата> - добавить цитату в базу;         
#         !delquote <номер> - удалить цитату с указанным номером;   
#         !quote - вывод произвольной цитаты;                  
#         !quote <номер> - вывод цитаты с указанным номером         
#         !quote <строка> - вывод цитаты, в которой есть указанная "строка"                             
#####################################################################################

namespace eval quote {}

setudef flag noquote
setudef flag auto-quote

#################################################

bind pub   -   $::gprefix(1)quote   ::quote::pub_quote
bind pub   -   $::gprefix(1)цитата   ::quote::pub_quote
bind pub   -   $::gprefix(1)q      ::quote::pub_quote
bind pub   -   $::gprefix(1)ц      ::quote::pub_quote
bind pub   -   $::gprefix(1)addquote   ::quote::pub_addquote
bind pub   -   $::gprefix(1)+цитата   ::quote::pub_addquote
bind pub   -   $::gprefix(1)aq      ::quote::pub_addquote
bind pub   -   $::gprefix(1)+ц      ::quote::pub_addquote
bind pub   o|o   $::gprefix(1)delquote   ::quote::pub_delquote
bind pub   o|o   $::gprefix(1)-цитата   ::quote::pub_delquote
bind pub   o|o   $::gprefix(1)dq      ::quote::pub_delquote
bind pub   o|o   $::gprefix(1)-ц      ::quote::pub_delquote

#################################################

foreach p [array names quote *] {catch {unset quote($p)}}

#################################################

set quote(announcetime)   45
set quote(datafile)   "data/quote.data"
set quote(data)      ""

#################################################

proc ::quote::readdata {} {
   global quote
   set quote(data) ""
   if {![catch {set fid [open $quote(datafile) "r"]}]} {
   while {![eof $fid]} {
      set data [split [string trim [gets $fid]] "|"]
   if {[llength $data] == 4} {lappend quote(data) $data}
   }
   close $fid
   }
}

proc ::quote::writedata {} {
   global quote
   set fid [open "$quote(datafile)" "w+"]
   foreach data $quote(data) {
   set sdata [join $data "|"]
   puts $fid "$sdata  "
   }
   close $fid
}

proc ::quote::init {} {
   global quote
   foreach tmr [timers] {if {[lindex $tmr 1] == "::quote::announce"} {killtimer [lindex $tmr 2]}}
   ::quote::readdata
   timer $quote(announcetime) ::quote::announce
}

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

proc ::quote::out {nick chan text} {
   global botnick
   if {$nick != $botnick} {
   if {[validchan $chan]} {putserv "PRIVMSG $chan :$text"
   } else {putserv "NOTICE $nick :$text"}
   } else {putserv "PRIVMSG $chan :$text"}
}

#################################################

proc ::quote::pub_quote {nick uhost hand chan args} {
   if {![validchan $chan]} {return}
      if {[channel get $chan noquote]} { return }
   regsub -all -- {\\} [join $args] "" args
   ::quote::quote $nick $uhost $hand $chan $chan [string trim $args]
}

proc ::quote::pub_addquote {nick uhost hand chan args} {
   if {![validchan $chan]} {return}
   if {[channel get $chan noquote]} { return }
   regsub -all -- {\\} [join $args] "" args
   ::quote::addquote $nick $uhost $hand $chan [string trim $args]
}

proc ::quote::pub_delquote {nick uhost hand chan args} {
   if {![validchan $chan]} {return}
   if {[channel get $chan noquote]} { return }
   regsub -all -- {\\} [join $args] "" args
   ::quote::delquote $nick $uhost $hand $chan [string trim $args]
}

#################################################

proc ::quote::total {chan} {
   global quote
   set total 0
   foreach q $quote(data) {if {![validchan $chan] || [string equal [lindex $q 0] $chan]} {incr total}}
   return $total
}

proc ::quote::addquote {nick uhost hand chan args} {
   global quote
   set args [join $args]
   if {[string length $args] < 1} {::quote::out $nick $nick "Формат: $::gprefix(1)+цитата <цитата>"; return}
   set largs [::quote::tolower $args]
   set num 0
   foreach q $quote(data) {
      if {![string equal [lindex $q 0] $chan]} {continue}
      incr num
      if {[string equal [::quote::tolower [lindex $q 2]] $largs]} {
      ::quote::out $nick $nick "Такая цитата уже добавлена (номер $num)."
      return
      }
   }
   lappend quote(data) [list $chan $nick $args [unixtime]]
   incr num
   ::quote::out $nick $nick "Цитата добавлена (номер $num)."
   ::quote::writedata
}

proc ::quote::delquote {nick uhost hand chan args} {
   global quote
   set args [join $args]
   if {[string length $args] < 1} {::quote::out $nick $nick "Формат: $::gprefix(1)-цитата <номер>"; return}
   if {[::quote::total $chan] == 0} {::quote::out $nick $nick "В базе нет ни одной цитаты..."; return}
   if {![regexp -nocase -- {^([0-9]{1,5})$} $args]} {::quote::out $nick $nick "Некорректный номер цитаты."; return}
   set num 0
   set res ""
   foreach q $quote(data) {
      if {![string equal [lindex $q 0] $chan]} {lappend res $q; continue}
      incr num
      if {$num != $args} {lappend res $q} else {::quote::out $nick $nick "Удалена цитата номер $num."}
   }
   if {[llength $res] < [llength $quote(data)]} {
      set quote(data) $res
      ::quote::writedata
   } else {::quote::out $nick $nick "Цитата под номером $args не найдена."}
}

proc ::quote::randomquote {nick chan dchan} {
   global quote botnick
   set total [::quote::total $chan]
   if {$total == 0} {return}
   set rnum [rand $total]
   set num 0
   set res ""
   foreach q $quote(data) {
      if {[validchan $chan] && ![string equal [lindex $q 0] $chan]} {continue}
      if {$num == $rnum} {set res $q}
      incr num
   }
   if {$res != ""} {
      if {[validchan $chan]} {::quote::out $botnick $dchan "$::gcolor(14)\[$::gcolor(6)[expr {$rnum + 1}]$::gcolor(14)/$num\]\003 [lindex $res 2]\017 $::gcolor(14)\[$::gcolor(5)[lindex $res 1]$::gcolor(14) [clock format [lindex $res 3] -format {%d-%m-%Y %H:%M:%S}]\]"
      } else {::quote::out $nick $dchan "$::gcolor(14)\[$::gcolor(6)[expr {$rnum + 1}]$::gcolor(14)/$num\]\003 [lindex $res 2]\017 $::gcolor(14)\[$::gcolor(5)[lindex $res 1]$::gcolor(14) [clock format [lindex $res 3] -format {%d-%m-%Y %H:%M:%S}]\]"}
   }
   
}

proc ::quote::quotebynum {nick chan dchan args} {
   global quote botnick
   set args [join $args]
   set num 0
   set res ""
   foreach q $quote(data) {
      if {[validchan $chan] && ![string equal [lindex $q 0] $chan]} {continue}
      incr num
      if {$num == $args} {set res $q}
   }
   if {$res != ""} {
      if {[validchan $chan]} {::quote::out $botnick $dchan "$::gcolor(14)\[$::gcolor(6)$args$::gcolor(14)/$num\]\003 [lindex $res 2]\017 $::gcolor(14)\[$::gcolor(5)[lindex $res 1]$::gcolor(14) [clock format [lindex $res 3] -format {%d-%m-%Y %H:%M:%S}]\]"
      } else {::quote::out $nick $dchan "$::gcolor(14)\[$::gcolor(6)$args$::gcolor(14)/$num\]\003 [lindex $res 2]\017 $::gcolor(14)\[$::gcolor(5)[lindex $res 1]$::gcolor(14) [clock format [lindex $res 3] -format {%d-%m-%Y %H:%M:%S}]\]"}
   } else {::quote::out $nick $nick "Цитата под номером $args не найдена."}
}

proc ::quote::quotebycontent {nick chan dchan args} {
   global quote botnick
   set args [join $args]
   set num 0
   set res ""
   set rnum 0
   foreach q $quote(data) {
      if {[validchan $chan] && ![string equal [lindex $q 0] $chan]} {continue}
      incr num
      if {$res == ""} {
         if {[string match "*$args*" "[lindex $q 2] \[[lindex $q 1]\]"]} {
            set res $q
            set rnum $num
         }
      }
   }
   if {$res != ""} {
      if {[validchan $chan]} {::quote::out $botnick $dchan "$::gcolor(14)\[$::gcolor(6)$rnum$::gcolor(14)/$num\]\003 [lindex $res 2]\017 $::gcolor(14)\[$::gcolor(5)[lindex $res 1]$::gcolor(14) [clock format [lindex $res 3] -format {%d-%m-%Y %H:%M:%S}]\]"
      } else {::quote::out $nick $dchan "$::gcolor(14)\[$::gcolor(6)$rnum$::gcolor(14)/$num\]\003 [lindex $res 2]\017 $::gcolor(14)\[$::gcolor(5)[lindex $res 1]$::gcolor(14) [clock format [lindex $res 3] -format {%d-%m-%Y %H:%M:%S}]\]"}
   } else {::quote::out $nick $nick "Цитата не найдена."}
}

proc ::quote::quote {nick uhost hand chan dchan args} {
   global quote
   if {[::quote::total $chan] == 0} {::quote::out $nick $nick "В базе нет ни одной цитаты..."; return}
   set args [join $args]
   if {[string length $args] == 0} {::quote::randomquote $nick $chan $dchan
   } elseif {[regexp -nocase -- {^([0-9]{1,5})$} $args]} {::quote::quotebynum $nick $chan $dchan $args
   } else {::quote::quotebycontent $nick $chan $dchan $args}
}

proc ::quote::announce {} {
   global quote botnick
   if {[llength $quote(data)] == 0} {return}
   foreach chan [channels] {
      if {[channel get $chan auto-quote]} {::quote::randomquote $botnick $chan $chan}
   }
   timer $quote(announcetime) ::quote::announce
}

::quote::init

Скрипт работает замечательно, но есть одно НО.
Команда !цитата <строка_для поиска> - ищет цитату в базе цитат, в которой есть строка <строка_для поиска>. Но проблема в том, что этот скрипт ищет первую в списке цитату с вхождением <строка_для поиска>. Если в базе есть несколько цитат со строкой <строка_для поиска>, то команда всё равно всегда ищет и показывает первую в списке цитату в базе.

Приведу пример.
Пример базы quote.data:
Код: Выделить всё
#channel|MyNick|<Vegas> Цитата номер один|1371710485 
#channel|MyNick|<Vegas> Цитата номер два|1371710485 
#channel|MyNick|<Vegas> Цитата номер три|1371710485 
#channel|MyNick|<Vegas> Цитата номер четыре|1371710485

Если я напишу в ирке команду "!цитата Vegas", то он мне будет всегда показывать "<Vegas> Цитата номер один", сколько бы я раз не повторял команду "!цитата Vegas".

Так вот задача вроде бы простая, как мне поправить скрипт, чтобы он мне выдавал поиском цитаты не первое совпадение по базе, а случайное (рандомную цитату с указанным вхождением/совпадением)?
Иначе говоря, чтобы когда я писал команду "!цитата Vegas", он мне выдавал случайную цитату из 4 совпадений, указанных выше в базе, а не всегда первую в списке по базе от автора Vegas.

P.S. В TCL пока достаточно плохо разбираюсь, поэтому буду очень благодарен за помощь в исправлении скрипта. Спасибо.
lzman
 
Сообщения: 10
Зарегистрирован: 23 июн 2013 22:31
Благодарил (а): 4 раз.
Поблагодарили: 0 раз.

Re: quote.tcl

Сообщение tvrsh » 23 июн 2013 23:57

Может быть стоит начать использовать нормальных ботов и нормальные скрипты, а не какие-то "сборки", качество которых оставляет желать лучшего?

Открывай скрипт quote.tcl
В процедуре quotebycontent строки
                                        set res $q
                                        set rnum $num

заменяй на строку
                    lappend qnum $q|$num

Далее, перед строкой
                if {![string is space $res]} {

добавь строки
                set qn [lindex $qnum [rand [llength $qnum]]]
                set res [lindex [split $qn "|"] 0]
                set rnum [lindex [split $qn "|"] 1]

Сохрани скрипт, рехашни бота и пробуй.
Не тестировал, но должно работать.
Have fun.
-
Получить помощь можно на каналах #egghelp в сети IrcNet.ru и #eggdrop в сети RusNet(Ключ канала eggdrop).
Перед созданием новой темы внимательно читайте Правила оформления топиков.
Аватара пользователя
tvrsh
 
Сообщения: 1230
Зарегистрирован: 19 авг 2008 16:55
Откуда: Russian Federation, Podolsk
Благодарил (а): 6 раз.
Поблагодарили: 130 раз.
Версия бота: Eggdrop 1.6.20+suzi

Re: quote.tcl

Сообщение lzman » 24 июн 2013 04:20

tvrsh, спасибо большое! Это почти работает, но есть одна ошибка.
Например, у меня в базе добавлено 3 цитаты
Код: Выделить всё
#channel nick!~nick@тут_IP 24-06-2013 02:23:05 тест
#channel nick!~nick@тут_IP 24-06-2013 02:30:22 тест2
#channel nick!~nick@тут_IP 24-06-2013 03:18:48 тест3

Если я пишу "!quote тест", то он успешно перебирает рандомно все 3 цитаты. Но если я напишу, например "!quote тест555", то скрипт выдает ошибку:
Код: Выделить всё
Tcl error [::quote::quote]: can't read "qnum": no such variable

Хотя, по идее должно в чате писать "Цитата, содержащая $text не найдена."

P.S. И заодно сразу спрошу, как сделать в этом скрипте включение/отключение подписи [added by Nickname 24-06-2013 on 02:30:22] опциональным? Чтобы была возможность отключить/включить отображение кем и когда добавлена цитата.
lzman
 
Сообщения: 10
Зарегистрирован: 23 июн 2013 22:31
Благодарил (а): 4 раз.
Поблагодарили: 0 раз.

Re: quote.tcl

Сообщение tvrsh » 24 июн 2013 18:05

В разделе настроек после
# канальный флаг
variable chflag                 $unamespace
добавь новую переменную которая будет отвечать за показ информации о цитате
# показывать автора и дату цитаты или нет (1/0)
variable showqinfo 0

Далее надо объявить эту переменную. В процедуре randomquote строку с объявлением переменных приведи к такому виду
variable quotedir; variable quotedata; variable debug; variable msgspeed; variable showqinfo


Теперь надо весь вывод сделать через условие, если переменная 1, то показывать инфу, а если 0, то не показывать. Строку
output $chan [subst {\00313\[\00312[expr {$rnum + 1}]\00313/\00306$num\00313\] \00312::\00314 [join [lrange [split $res] 4 end]]\00313 \[\00312added by \00305[lindex [split [lindex [split $res] 1] {!}] 0] [lindex [split $res] 2]\00312 on\00305 [lindex [split $res] 3]\00313\]\003}] -speed $msgspeed -type msg
замени на
TCL: [ Скачать ] [ Скрыть ]
if {$showqinfo} {
    output $chan [subst {\00313\[\00312$rnum\00313/\00306$num\00313\] \00312::\00314 [join [lrange [split $res] 4 end]]\00313 \[\00312added by \00305[lindex [split [lindex [split $res] 1] {!}] 0] [lindex [split $res] 2]\00312 on\00305 [lindex [split $res] 3]\00313\]\003}] -speed $msgspeed -type msg
} else {
    output $chan [subst {\00313\[\00312$rnum\00313/\00306$num\00313\] \00312::\00314 [join [lrange [split $res] 4 end]]\003}]  -speed $msgspeed -type msg
}

И так надо сделать в каждой из процедур где присутствует вывод в канал.
В quotebynum делай так
variable quotedir; variable quotedata; variable debug; variable msgspeed; variable showqinfo

и меняй
output $chan [subst {\00313\[\00312$text\00313/\00306$num\00313\] \00312::\00314 [join [lrange [split $res] 4 end]]\00313 \[\00312added by \00305[lindex [split [lindex [split $res] 1] {!}] 0] [lindex [split $res] 2]\00312 on\00305 [lindex [split $res] 3]\00313\]\003}] -speed $msgspeed -type msg
на
TCL: [ Скачать ] [ Скрыть ]
if {$showqinfo} {
    output $chan [subst {\00313\[\00312$text\00313/\00306$num\00313\] \00312::\00314 [join [lrange [split $res] 4 end]]\00313 \[\00312added by \00305[lindex [split [lindex [split $res] 1] {!}] 0] [lindex [split $res] 2]\00312 on\00305 [lindex [split $res] 3]\00313\]\003}] -speed $msgspeed -type msg
} else {
    output $chan [subst {\00313\[\00312$text\00313/\00306$num\00313\] \00312::\00314 [join [lrange [split $res] 4 end]]\003}] -speed $msgspeed -type msg
}

В randomquote делай
variable quotedir; variable quotedata; variable debug; variable msgspeed; variable showqinfo

и меняй
output $chan [subst {\00313\[\00312[expr {$rnum + 1}]\00313/\00306$num\00313\] \00312::\00314 [join [lrange [split $res] 4 end]]\00313 \[\00312added by \00305[lindex [split [lindex [split $res] 1] {!}] 0] [lindex [split $res] 2]\00312 on\00305 [lindex [split $res] 3]\00313\]\003}] -speed $msgspeed -type msg
на
TCL: [ Скачать ] [ Скрыть ]
if {$showqinfo} {
    output $chan [subst {\00313\[\00312[expr {$rnum + 1}]\00313/\00306$num\00313\] \00312::\00314 [join [lrange [split $res] 4 end]]\00313 \[\00312added by \00305[lindex [split [lindex [split $res] 1] {!}] 0] [lindex [split $res] 2]\00312 on\00305 [lindex [split $res] 3]\00313\]\003}] -speed $msgspeed -type msg
} else {
    output $chan [subst {\00313\[\00312[expr {$rnum + 1}]\00313/\00306$num\00313\] \00312::\00314 [join [lrange [split $res] 4 end]]\003}] -speed $msgspeed -type msg
}


А чтобы не было ошибки замени процедуру quotebycontent на эту
TCL: [ Скачать ] [ Скрыть ]
        proc quotebycontent {nick uhost chan text} {
                set text [lindex [string range $text 0 end] 0]
                set num 0
                set qnum [list]
                set rnum 0
                variable quotedir; variable quotedata; variable debug; variable msgspeed; variable showqinfo
                set qdata [readdata "$quotedir/$quotedata"]
                foreach q $qdata {
                        if {![string match -nocase [lindex [split $q] 0] $chan]} { continue }
                        incr num
                        if {[string is space $qnum]} {
                                if {[string match -nocase "*$text" [lrange [split $q] 4 end]] || [string match -nocase "$text*" [lrange [split $q] 4 end]] || [string match -nocase "*$text*" [lrange [split $q] 4 end]] || [string match -nocase "$text" [lrange [split $q] 4 end]]} {
                    lappend qnum $q|$num
                                }
                        }
                }
                if {![string is space $qnum]} {
                    set qn [lindex $qnum [rand [llength $qnum]]]
                set res [lindex [split $qn "|"] 0]
                set rnum [lindex [split $qn "|"] 1]
                        if {$debug} { debug [subst {Get quote ($rnum/$num) matched '$text' (requested by $nick!$uhost on channel $chan)}] [namespace tail [lindex [info lev 0] 0]] -type msg }
            if {$showqinfo} {
                output $chan [subst {\00313\[\00312$rnum\00313/\00306$num\00313\] \00312::\00314 [join [lrange [split $res] 4 end]]\00313 \[\00312added by \00305[lindex [split [lindex [split $res] 1] {!}] 0] [lindex [split $res] 2]\00312 on\00305 [lindex [split $res] 3]\00313\]\003}] -speed $msgspeed -type msg
                        } else {
                    output $chan [subst {\00313\[\00312$rnum\00313/\00306$num\00313\] \00312::\00314 [join [lrange [split $res] 4 end]]\003}]  -speed $msgspeed -type msg
                        }
                        return 0
                } else {
                        if {$debug} { debug [subst {Can not get quote matched '$text' (requested by $nick!$uhost on channel $chan) :: not found}] [namespace tail [lindex [info lev 0] 0]] -type msg }
                        output $chan [subst {\00314Цитата, содержащая \00312'\00306$text\00312'\00314 не найдена.\003}] -speed $msgspeed -type msg
                        return 0
                }
        }
 
Have fun.
-
Получить помощь можно на каналах #egghelp в сети IrcNet.ru и #eggdrop в сети RusNet(Ключ канала eggdrop).
Перед созданием новой темы внимательно читайте Правила оформления топиков.

За это сообщение автора tvrsh поблагодарил:
lzman (24 июн 2013 20:05)
Аватара пользователя
tvrsh
 
Сообщения: 1230
Зарегистрирован: 19 авг 2008 16:55
Откуда: Russian Federation, Podolsk
Благодарил (а): 6 раз.
Поблагодарили: 130 раз.
Версия бота: Eggdrop 1.6.20+suzi

Re: quote.tcl

Сообщение lzman » 24 июн 2013 20:00

Вы написали
tvrsh писал(а):В процедуре randomquote строку с объявлением переменных приведи к такому виду

а потом ниже
tvrsh писал(а):В randomquote делай

Где указали почти тоже самое, только уже с небольшим отличием от первого варианта. В первом варианте, например, вырезается вхождение {$rnum + 1}, а ниже оно снова появляется. Какой же из вариантов верный?
Или же это ошибка копипаста или во второй раз вы имели в виду не randomquote, а процедуру quotebycontent.
Я посчитал, что вы всё-таки во второй раз имели в виду процедуру quotebycontent и полностью заменил её на ту, что написали вы.
Скрипт работает, дата добавления убирается, но опять перестали работать рандомные цитаты. То есть после того, как я заменил процедуру quotebycontent на вашу, у меня опять перестали работать рандомные цитаты. Вновь выдает только первое совпадение по базе.
lzman
 
Сообщения: 10
Зарегистрирован: 23 июн 2013 22:31
Благодарил (а): 4 раз.
Поблагодарили: 0 раз.

Re: quote.tcl

Сообщение tvrsh » 24 июн 2013 22:15

Как-то ты все слишком сложно и непонятно написал.
На.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Have fun.
-
Получить помощь можно на каналах #egghelp в сети IrcNet.ru и #eggdrop в сети RusNet(Ключ канала eggdrop).
Перед созданием новой темы внимательно читайте Правила оформления топиков.

За это сообщение автора tvrsh поблагодарил:
lzman (25 июн 2013 00:24)
Аватара пользователя
tvrsh
 
Сообщения: 1230
Зарегистрирован: 19 авг 2008 16:55
Откуда: Russian Federation, Podolsk
Благодарил (а): 6 раз.
Поблагодарили: 130 раз.
Версия бота: Eggdrop 1.6.20+suzi

Re: quote.tcl

Сообщение lzman » 25 июн 2013 00:23

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

Первый способ воспроизвести баг.
Добавляем в базу цитаты, пишем в чате:
Код: Выделить всё
!+цитата тест1
!+цитата тест2
!+цитата тест3

А теперь пишем в этом же порядке цитаты с кавычками:
Код: Выделить всё
!+цитата ""тест"
!+цитата ""тест""

После того как мы добавим вторую цитату с кавычками, у нас полностью очистится база данных цитат и получим ошибку:
Tcl error [::quote::addquote]: list element in quotes followed by "тест"" instead of space


Второй способ воспроизвести баг.
Этим способом я и поймал баг. В моей базе есть очень много цитат с использованием кавычек.
Открываем базу цитат quote.dat и пишем туда и сохраняем
Код: Выделить всё
#channel bot!~bot@наш_.IP 25-06-2013 00:01:31 тест1
#channel bot!~bot@наш_.IP 25-06-2013 00:01:37 "тест3"
#channel bot!~bot@наш_.IP 25-06-2013 00:01:39 ""тест2""

После этого в чате пишем команду добавления новой цитаты:
Код: Выделить всё
!+цитата тест

После этого у нас так же очищается вся база цитат и получаем ошибку:
Tcl error [::quote::addquote]: list element in quotes followed by "тест3""" instead of space

Как можно исправить этот баг, конечно чтобы без потери безопасности? Ведь не использовать кавычки в цитатах с прямой речью - это абсурд :shock: К тому же всё равно можно легко добавить цитаты с кавычками и автоматически убить всю базу цитат.
lzman
 
Сообщения: 10
Зарегистрирован: 23 июн 2013 22:31
Благодарил (а): 4 раз.
Поблагодарили: 0 раз.

Re: quote.tcl

Сообщение lzman » 26 июн 2013 00:14

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

Как ни странно, но скрипт который я выложил в первом сообщении темы, такой критической ошибки не имеет. Возможно потому, что имеет базу данных с разделениями не пробелом, а чертой |.
В формате:
Код: Выделить всё
#channel|Nick|цитата|1372190217

Но в этом скрипте не работает отображение рандомных цитат по маске !цитата <слово>, выдает всегда первое совпадение по списку в базе.
А значит нужен способ как-нибудь починить, предложенный вами скрипт, либо как-то добавить возможность показывать случайные цитаты в мой первый скрипт.
Помогите :cry:
lzman
 
Сообщения: 10
Зарегистрирован: 23 июн 2013 22:31
Благодарил (а): 4 раз.
Поблагодарили: 0 раз.

Re: quote.tcl

Сообщение Vertigo » 26 июн 2013 06:53

lzman писал(а):Открываем базу цитат quote.dat и пишем туда и сохраняем
Код: Выделить всё
#channel bot!~bot@наш_.IP 25-06-2013 00:01:31 тест1
#channel bot!~bot@наш_.IP 25-06-2013 00:01:37 "тест3"
#channel bot!~bot@наш_.IP 25-06-2013 00:01:39 ""тест2""

Так делать нельзя. Писать руками в базу с неэкранированными кавычками. Надо их эскейпить - \" как и фигурные/квадратные скобки. Обычно это делается при корректном использовании функций тикля, или же можно принудительно заескейпить их, например следующим образом.
set text [string map [list \" \\\" \[ \\\[ \] \\\] \{ \\\{ \} \\\} \$ \\\$ \\ \\\\] $text]

Где $text - переменная с текстом цитаты.
Аватара пользователя
Vertigo
 
Сообщения: 107
Зарегистрирован: 20 авг 2008 23:49
Откуда: Москва
Благодарил (а): 0 раз.
Поблагодарили: 37 раз.
Версия бота: Eggdrop 1.8

Re: quote.tcl

Сообщение lzman » 26 июн 2013 07:31

Vertigo, а как это применить к скрипту из этого сообщения? post2990.html#p2990
Дело в том, что когда пишем !addquote ""цитата"" (с кавычками прямо в ирк чате), то в базу quote.dat оно добавляется прямо в таком же виде (не экранируется):
Код: Выделить всё
#channel bot!~bot@наш_.IP 25-06-2013 00:01:39 ""цитата""

Причем когда я добавляю (через команду в ирк чате) несколько таких цитат с использованием разного количества кавычек, то происходит ошибка и вся база цитат очищается.
P.S. Не знаю в экранировании кавычек тут дело или нет, но проблема явно связана с неправильной обработкой кавычек самим скриптом цитат.
lzman
 
Сообщения: 10
Зарегистрирован: 23 июн 2013 22:31
Благодарил (а): 4 раз.
Поблагодарили: 0 раз.

Re: quote.tcl

Сообщение Vertigo » 26 июн 2013 09:30

Попробуй такой вариант скрипта. Работоспособность проверял, пробежавшись по коду скрипта, обнаружил много мест с неправильной работой со строками/списками.
---
UPD: последняя версия во вложении последнего сообщения.
Последний раз редактировалось Vertigo 26 июн 2013 16:27, всего редактировалось 1 раз.
Аватара пользователя
Vertigo
 
Сообщения: 107
Зарегистрирован: 20 авг 2008 23:49
Откуда: Москва
Благодарил (а): 0 раз.
Поблагодарили: 37 раз.
Версия бота: Eggdrop 1.8

Re: quote.tcl

Сообщение lzman » 26 июн 2013 12:00

Vertigo , не сработало.

1. Пишу в ирк чате !addquote ""тест""
В базе появляется запись:
Код: Выделить всё
#channel nick!~nick@мой.IP 26-06-2013 11:43:29 \"\"тест\"\"

2. Ещё раз пишу в ирк чате !addquote ""тест""
База начинает выглядеть так:
Код: Выделить всё
#channel nick!~nick@мой.IP 26-06-2013 11:43:29 ""тест""
#channel nick!~nick@мой.IP 26-06-2013 11:46:34 \"\"тест\"\"

3. Ещё раз пишу в ирк чате !addquote ""тест""
База данных quote.dat полностью очищается (файл становится пустой) и появляется ошибка:
Код: Выделить всё
Tcl error [::quote::addquote]: list element in quotes followed by "тест""" instead of space
lzman
 
Сообщения: 10
Зарегистрирован: 23 июн 2013 22:31
Благодарил (а): 4 раз.
Поблагодарили: 0 раз.

Re: quote.tcl

Сообщение Vertigo » 26 июн 2013 12:07

|26.06.2013 / 12:02:57| <Sergio> !addquote ""тест""
|26.06.2013 / 12:03:02| <Sergio> ^addquote ""тест""
|26.06.2013 / 12:03:03| <Juliana> Sergio, Цитата добавлена. (номер: 6)
|26.06.2013 / 12:03:06| <Sergio> ^addquote ""тест""
|26.06.2013 / 12:03:07| <Juliana> Sergio, Цитата добавлена. (номер: 7)
|26.06.2013 / 12:03:09| <Sergio> ^addquote ""тест""
|26.06.2013 / 12:03:10| <Juliana> Sergio, Цитата добавлена. (номер: 8)
|26.06.2013 / 12:03:12| <Sergio> ^addquote ""тест""
|26.06.2013 / 12:03:13| <Juliana> Sergio, Цитата добавлена. (номер: 9)
|26.06.2013 / 12:03:31| <Sergio> ^quote ""test""
|26.06.2013 / 12:03:33| <Juliana> Цитата, содержащая '{""test""}' не найдена.
|26.06.2013 / 12:03:40| <Sergio> ^quote test
|26.06.2013 / 12:03:41| <Juliana> [5/9] :: test тест
|26.06.2013 / 12:03:45| <Sergio> ^quote -2 test
|26.06.2013 / 12:03:46| <Juliana> Цитата, содержащая '-2' не найдена.
|26.06.2013 / 12:03:52| <Sergio> ^quote 2 test
|26.06.2013 / 12:03:53| <Juliana> Цитата, содержащая '2' не найдена.
|26.06.2013 / 12:03:56| <Sergio> ^quote test
|26.06.2013 / 12:03:57| <Juliana> [5/9] :: test тест
|26.06.2013 / 12:03:58| <Sergio> ^quote test
|26.06.2013 / 12:04:00| <Juliana> [5/9] :: test тест
|26.06.2013 / 12:04:01| <Sergio> ^quote test
|26.06.2013 / 12:04:03| <Juliana> [5/9] :: test тест
|26.06.2013 / 12:04:07| <Sergio> ^quote test
|26.06.2013 / 12:04:09| <Juliana> [5/9] :: test тест
|26.06.2013 / 12:04:17| <Sergio> ^quote 9
|26.06.2013 / 12:04:18| <Juliana> [9/9] :: {\"\"тест\"\"}
|26.06.2013 / 12:04:23| <Sergio> ^quote 8
|26.06.2013 / 12:04:24| <Juliana> [8/9] :: {\"\"тест\"\"}

Не так гладко, как хотелось, но мне тема подобных скриптов не слишком интересна, так что флаг в руки, поправить скрипт можно вполне. Я аттач обновлял позже, ты, видать, скачал первую версию, когда я не проверил. Попробуй перекачать, а остальные ошибки уж сам как-нибудь ;)
Аватара пользователя
Vertigo
 
Сообщения: 107
Зарегистрирован: 20 авг 2008 23:49
Откуда: Москва
Благодарил (а): 0 раз.
Поблагодарили: 37 раз.
Версия бота: Eggdrop 1.8

Re: quote.tcl

Сообщение lzman » 26 июн 2013 13:02

Vertigo, перескачал ваш скрипт. Действительно стал работать, но осталась в нём одна странность.
Пишем в чат !addquote ""цитата"" - цитата успешно добавлена.
Пишем в чат ещё раз !addquote ""цитата"" - пишет, что цитата тоже добавлена. Хотя должен говорить, что такая цитата уже существует. :shock:
lzman
 
Сообщения: 10
Зарегистрирован: 23 июн 2013 22:31
Благодарил (а): 4 раз.
Поблагодарили: 0 раз.

Re: quote.tcl

Сообщение Vertigo » 26 июн 2013 13:32

Ну на работе делать в принципе особо нечего - пофиксил, то, что ты обнаружил.
Тесты:
|26.06.2013 / 13:23:55| <Sergio> .tcl exec rm data/quotes.db
|26.06.2013 / 13:23:56| <Juliana> Tcl (25.43ms): [no error]
|26.06.2013 / 13:23:59| <Sergio> .load tests/quote.tcl
|26.06.2013 / 13:24:01| <Juliana> Sergio: файл "quote.tcl" (21.09 KB, 465 строк) загружен успешно.
|26.06.2013 / 13:24:09| <Sergio> ^addquote ""тест""
|26.06.2013 / 13:24:10| <Juliana> Sergio, Цитата добавлена. (номер: 1)
|26.06.2013 / 13:24:13| <Sergio> ^addquote ""тест""
|26.06.2013 / 13:24:14| <Juliana> Sergio, Такая цитата уже есть в базе. Её добавил Sergio в 26-06-2013 13:24:10.
|26.06.2013 / 13:24:45| <Sergio> ^+quote тест цитаты со {скобк"""ами[ и кавыч\ ка\{ми "
|26.06.2013 / 13:24:46| <Juliana> Sergio, Цитата добавлена. (номер: 2)
|26.06.2013 / 13:24:51| <Sergio> ^addquote ""тест""
|26.06.2013 / 13:24:52| <Juliana> Sergio, Такая цитата уже есть в базе. Её добавил Sergio в 26-06-2013 13:24:10.
|26.06.2013 / 13:24:54| <Sergio> ^+quote тест цитаты со {скобк"""ами[ и кавыч\ ка\{ми "
|26.06.2013 / 13:24:54| <Juliana> Sergio, Такая цитата уже есть в базе. Её добавил Sergio в 26-06-2013 13:24:46.
|26.06.2013 / 13:26:13| <Sergio> ^quote 2
|26.06.2013 / 13:26:14| <Juliana> [2/2] :: тест цитаты со {скобк"""ами[ и кавыч\ ка\{ми " [added by Sergio on 26-06-2013 13:24:46]
|26.06.2013 / 13:26:17| <Sergio> ^quote 1
|26.06.2013 / 13:26:17| <Juliana> [1/2] :: ""тест"" [added by Sergio on 26-06-2013 13:24:10]
У вас нет необходимых прав для просмотра вложений в этом сообщении.

За это сообщение автора Vertigo поблагодарил:
lzman (26 июн 2013 16:37)
Аватара пользователя
Vertigo
 
Сообщения: 107
Зарегистрирован: 20 авг 2008 23:49
Откуда: Москва
Благодарил (а): 0 раз.
Поблагодарили: 37 раз.
Версия бота: Eggdrop 1.8

Re: quote.tcl

Сообщение lzman » 26 июн 2013 14:02

Осталась ещё одна странность.
Когда пишу !addquote тест - в базу записывает цитату без фигурных скобок так:
Код: Выделить всё
{26-06-2013 13:43:09} тест5

А когда пишу !addquote тест два - т.е. цитата из 2-х и более слов, то в базу записывает цитату в фигурных скобках так:
Код: Выделить всё
{26-06-2013 13:43:09} {тест два}


P.S. Ещё а базе цитаты записываются через строчку, вот так:
Код: Выделить всё
{#channel} nick!~nick@мой.IP {26-06-2013 11:43:29} тест

{#channel} nick!~nick@мой.IP {26-06-2013 11:46:34} тест2

{#channel} nick!~nick@мой.IP {26-06-2013 11:43:29} тест3

Так и должно быть?
lzman
 
Сообщения: 10
Зарегистрирован: 23 июн 2013 22:31
Благодарил (а): 4 раз.
Поблагодарили: 0 раз.

Re: quote.tcl

Сообщение Vertigo » 26 июн 2013 14:08

Насчет скобок - в базу пишется правильный tcl-список. Когда список состоит из элемента без пробелов, фигурные скобки опускаются, если же есть пробелы, то добавляются фигурные скобки. По поводу черезстрочности - хз. Наверно надо поправить место где цитаты читаются из базы. Попробуй заменить
set data [split [read $fileio] \n]
в процедуре readdata на
set data [lrange [split [read $fileio] \n] 0 end-1]

Базу придется очистить для вступления изменений в силу.

За это сообщение автора Vertigo поблагодарил:
lzman (26 июн 2013 16:36)
Аватара пользователя
Vertigo
 
Сообщения: 107
Зарегистрирован: 20 авг 2008 23:49
Откуда: Москва
Благодарил (а): 0 раз.
Поблагодарили: 37 раз.
Версия бота: Eggdrop 1.8

Re: quote.tcl

Сообщение lzman » 26 июн 2013 16:39

Vertigo, спасибо, помогло! Вроде бы теперь всё работает как я и хотел. Пока никаких новых проблем не обнаружилось. :)
Спасибо вам ещё раз за помощь в исправлении скрипта.
lzman
 
Сообщения: 10
Зарегистрирован: 23 июн 2013 22:31
Благодарил (а): 4 раз.
Поблагодарили: 0 раз.


Вернуться в TCL скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8

cron