mysqlquote.tcl 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #
  2. # 16/08/2010
  3. # by horgh
  4. #
  5. # MySQL quote script
  6. #
  7. # Setup:
  8. # The table must be called "quote" and have the following schema:
  9. # CREATE TABLE quote (
  10. # qid SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
  11. # uid SMALLINT UNSIGNED NOT NULL,
  12. # quote TEXT NOT NULL,
  13. # PRIMARY KEY (qid)
  14. # );
  15. # Other keys are possible but not required
  16. #
  17. # aq (addquote) usage:
  18. # - \n starts a new line for the quote
  19. # - e.g.: aq <user> hi there!\n<user2> hey
  20. # becomes the quote:
  21. # <user> hi there
  22. # <user2> hey
  23. #
  24. package require mysqltcl
  25. namespace eval sqlquote {
  26. variable output_cmd putserv
  27. # MySQL settings
  28. variable host localhost
  29. variable user quote
  30. variable pass quote
  31. variable db quote
  32. # mysql connection handler
  33. variable conn []
  34. # search results stored in this dict
  35. variable results []
  36. bind pub -|- latest sqlquote::latest
  37. bind pub -|- quotestats sqlquote::stats
  38. bind pub -|- quote sqlquote::quote
  39. bind pub -|- aq sqlquote::addquote
  40. bind pub m|- delquote sqlquote::delquote
  41. setudef flag quote
  42. }
  43. proc sqlquote::connect {} {
  44. # If connection not initialised or has disconnected
  45. if {![mysql::state $sqlquote::conn -numeric] || ![mysql::ping $sqlquote::conn]} {
  46. set sqlquote::conn [mysql::connect -host $sqlquote::host -user $sqlquote::user -password $sqlquote::pass -db $sqlquote::db]
  47. putlog "Connecting to db..."
  48. }
  49. }
  50. # fetch a single quote row with given statement
  51. proc sqlquote::fetch_single {stmt} {
  52. mysql::sel $sqlquote::conn $stmt
  53. mysql::map $sqlquote::conn {qid quote} {
  54. set q [list qid $qid quote $quote]
  55. }
  56. return $q
  57. }
  58. proc sqlquote::fetch_search {terms} {
  59. putlog "Retrieving new quotes for $terms..."
  60. set terms [mysql::escape $sqlquote::conn $terms]
  61. set stmt "SELECT qid, quote FROM quote WHERE quote LIKE \"%${terms}%\" LIMIT 20"
  62. set count [mysql::sel $sqlquote::conn $stmt]
  63. if {$count <= 0} {
  64. return []
  65. }
  66. mysql::map $sqlquote::conn {qid quote} {
  67. lappend quotes [list qid $qid quote $quote]
  68. }
  69. return $quotes
  70. }
  71. proc sqlquote::stats {nick host hand chan argv} {
  72. if {![channel get $chan quote]} { return }
  73. sqlquote::connect
  74. set stmt "SELECT COUNT(qid) FROM quote"
  75. mysql::sel $sqlquote::conn $stmt
  76. mysql::map $sqlquote::conn {c} {
  77. set count $c
  78. }
  79. $sqlquote::output_cmd "PRIVMSG $chan :There are $count quotes in the database."
  80. }
  81. proc sqlquote::latest {nick host hand chan argv} {
  82. if {![channel get $chan quote]} { return }
  83. sqlquote::connect
  84. set stmt "SELECT qid, quote FROM quote ORDER BY qid DESC LIMIT 1"
  85. sqlquote::output $chan [sqlquote::fetch_single $stmt]
  86. }
  87. proc sqlquote::random {} {
  88. set stmt "SELECT qid, quote FROM quote ORDER BY RAND() LIMIT 1"
  89. return [sqlquote::fetch_single $stmt]
  90. }
  91. proc sqlquote::quote_by_id {id} {
  92. set stmt "SELECT qid, quote FROM quote WHERE qid = ${id}"
  93. return [sqlquote::fetch_single $stmt]
  94. }
  95. proc sqlquote::quote {nick host hand chan argv} {
  96. if {![channel get $chan quote]} { return }
  97. sqlquote::connect
  98. if {$argv == ""} {
  99. sqlquote::output $chan [sqlquote::random]
  100. } elseif {[string is integer $argv]} {
  101. sqlquote::output $chan [sqlquote::quote_by_id $argv]
  102. } else {
  103. sqlquote::output $chan {*}[sqlquote::search $argv]
  104. }
  105. }
  106. proc sqlquote::search {terms} {
  107. set terms [regsub -all -- {\*} $terms "%"]
  108. if {![dict exists $sqlquote::results $terms]} {
  109. dict set sqlquote::results $terms [sqlquote::fetch_search $terms]
  110. }
  111. # Extract one quote from results
  112. set quotes [dict get $sqlquote::results $terms]
  113. set quote [lindex $quotes 0]
  114. set quotes [lreplace $quotes 0 0]
  115. # Remove key if no quotes after removal of one, else update quotes
  116. if {![llength $quotes]} {
  117. dict unset sqlquote::results $terms
  118. } else {
  119. dict set sqlquote::results $terms $quotes
  120. }
  121. return [list $quote [llength $quotes]]
  122. }
  123. proc sqlquote::addquote {nick host hand chan argv} {
  124. if {![channel get $chan quote]} { return }
  125. if {$argv == ""} {
  126. $sqlquote::output_cmd "PRIVMSG $chan :Usage: aq <text...>"
  127. return
  128. }
  129. sqlquote::connect
  130. set argv [regsub -all -- {\\n} $argv \n]
  131. set quote [mysql::escape $sqlquote::conn $argv]
  132. set stmt "INSERT INTO quote (uid, quote) VALUES(1, \"${quote}\")"
  133. set count [mysql::exec $sqlquote::conn $stmt]
  134. $sqlquote::output_cmd "PRIVMSG $chan :${count} quote added."
  135. }
  136. proc sqlquote::delquote {nick host hand chan argv} {
  137. if {$argv == "" || ![string is integer $argv]} {
  138. $sqlquote::output_cmd "PRIVMSG $chan :Usage: delquote <#>"
  139. return
  140. }
  141. sqlquote::connect
  142. set stmt "DELETE FROM quote WHERE qid = ${argv}"
  143. set count [mysql::exec $sqlquote::conn $stmt]
  144. $sqlquote::output_cmd "PRIVMSG $chan :#${argv} deleted. ($count quotes affected.)"
  145. }
  146. # quote is dict of form {qid ID quote TEXT}
  147. proc sqlquote::output {chan quote {left {}}} {
  148. if {$quote == ""} {
  149. $sqlquote::output_cmd "PRIVMSG $chan :No quotes found."
  150. return
  151. }
  152. set qid [dict get $quote qid]
  153. set text [dict get $quote quote]
  154. set head "Quote #\002$qid\002"
  155. if {$left ne ""} {
  156. set head "${head} ($left left)"
  157. }
  158. $sqlquote::output_cmd "PRIVMSG $chan :$head"
  159. foreach l [split $text \n] {
  160. $sqlquote::output_cmd "PRIVMSG $chan : $l"
  161. }
  162. }
  163. sqlquote::connect
  164. putlog "sqlquote.tcl loaded"