- Timestamp:
- 07/26/07 01:54:10 (18 months ago)
- Location:
- trunk/awkbot
- Files:
-
- 3 added
- 2 removed
- 7 modified
-
awkbot.sql (modified) (1 diff)
-
bin/awkbot (added)
-
bin/awkpp (deleted)
-
bin/awkpp.awk (deleted)
-
etc/awkbot.conf (modified) (2 diffs)
-
lib/awkbot-boot.awk (added)
-
lib/awkbot.awk (modified) (8 diffs)
-
lib/awkbot_db_mysql.awk (modified) (2 diffs)
-
lib/awkpaste.awk (modified) (1 diff)
-
lib/cgi-lib.awk (modified) (1 diff)
-
lib/irc.awk (modified) (3 diffs)
-
lib/socket.awk (added)
Legend:
- Unmodified
- Added
- Removed
-
trunk/awkbot/awkbot.sql
r8 r47 46 46 INSERT INTO `qna` VALUES ('mysql.awk','http://www.blisted.org/svn/modules/mysql.awk/ until tag writes documentation'); 47 47 48 49 CREATE TABLE `status` ( 50 `running` boolean not null default false, 51 `livefeed` varchar(120) default null 52 ); 53 54 INSERT INTO `status` (running, livefeed) VALUES (FALSE, NULL); 55 56 -- Make status a table with only one record, always 57 -- Mysql is ghetto like that... we can't raise errors, we have to actually just 58 -- create one with an invalid statement... 59 60 DELIMITER / 61 62 CREATE TRIGGER t_status_final BEFORE INSERT ON status 63 FOR EACH ROW 64 BEGIN 65 DECLARE temp integer; 66 SELECT `INSERT is not allowed` INTO temp FROM status; 67 END; 68 / 69 70 CREATE TRIGGER t_status_final_d BEFORE DELETE ON status 71 FOR EACH ROW 72 BEGIN 73 DECLARE temp integer; 74 SELECT `DELETE is not allowed` INTO temp FROM status; 75 END; 76 / 77 78 DELIMITER ; -
trunk/awkbot/etc/awkbot.conf
r44 r47 2 2 # IRC Stuff 3 3 <irc> 4 nickname awk bot-test5 altnick awk bot_test4 nickname awktest 5 altnick awk_test 6 6 username awkbot 7 7 realname AWK IRC bot … … 22 22 23 23 <mysql> 24 username tag25 password darwin24 username scott 25 password scott 26 26 database awkbot 27 27 </mysql> -
trunk/awkbot/lib/awkbot.awk
r44 r47 7 7 # ----------------------------------------------------------------------------- 8 8 9 #i nclude<assert.awk>10 #i nclude<config.awk>11 #i nclude<awkbot_db_mysql.awk>12 #i nclude<irc.awk>13 #i nclude<awkdoc.awk>14 #i nclude<join.awk>15 #i nclude<queue.awk>9 #import <assert.awk> 10 #import <config.awk> 11 #import <awkbot_db_mysql.awk> 12 #import <irc.awk> 13 #import <awkdoc.awk> 14 #import <join.awk> 15 #import <queue.awk> 16 16 17 17 #define TEST 1 … … 29 29 30 30 BEGIN { 31 # assert(irc, "Awkbot depends on irc.awk")32 # assert(awkbot_config, "Awkbot depends on config.awk")33 34 31 VERSION = "awkbot $Revision: 412 $" 35 32 … … 41 38 assert(config("irc.server"), "server not specified in config") 42 39 40 awkbot_db_init() 41 43 42 irc_set("debug", config("irc.debug")) 44 43 … … 50 49 irc_register("privmsg") 51 50 irc_register("ctcp") 52 51 irc_register("error") 52 53 print "Using", awkbot_db_status_livefeed(), "as live feed from awkbot" 54 55 # XXX Nasty hack, make this not need direct access to the irc array! 56 irc["tempfile"] = awkbot_db_status_livefeed() 57 irc_connect(config("irc.server")) 58 } 59 60 END { 61 awkbot_db_status_connected(0) 62 } 63 64 # Nasty hack to clean up every few records 65 NR % 3 == 0 { 66 print "DEBUG: Truncating file.." 67 printf "" > irc["tempfile"] 68 fflush(irc["tempfile"]) 69 close(irc["tempfile"]) 70 } 71 $1 == "say" { 72 _msg = $3 73 for (i = 4; i < NF; i++) { 74 _msg = _msg " " $i 75 } 76 print "Saying " _msg " to " $2 77 irc_privmsg($2, _msg) 78 } 79 80 function irc_handler_error () { 53 81 irc_connect(config("irc.server")) 54 82 } … … 61 89 62 90 if (msg) irc_sockwrite(msg "\r\n") 91 92 awkbot_db_status_connected(1) 63 93 } 64 94 … … 76 106 } 77 107 108 func calc (expr ,result,bc) { 109 bc = "bc -q" 110 print "scale=10" |& bc 111 print expr |& bc 112 print "quit" |& bc 113 bc |& getline result 114 close(bc) 115 116 # coerce to number 117 return result + 0 118 } 119 78 120 function irc_handler_privmsg (nick, host, recipient, message, arg \ 79 121 ,direct,target,address,action,c_msg,argc,t,q,a) { … … 118 160 # It's only numbers and stuff 119 161 else if (c_msg ~ /^[0-9^.*+\/() -]*$/) { 120 action = "bc -q" 121 print "scale=10" |& action 122 print c_msg |& action 123 print "quit" |& action 124 action |& getline a 125 close(action) 126 irc_privmsg(target, address (a + 0)) 127 # Coerce the result into an array 162 irc_privmsg(target, address calc(c_msg)) 128 163 } 129 164 else { … … 161 196 } 162 197 } 198 else if (arg[1] == nick) { 199 irc_privmsg(target, address "Talking about yourself, are we?") 200 } 163 201 } 164 202 -
trunk/awkbot/lib/awkbot_db_mysql.awk
r44 r47 7 7 # deps: assert.awk mysql.awk 8 8 9 #include <assert.awk> 10 #include <mysql.awk> 9 #import <assert.awk> 10 #import <config.awk> 11 #import <mysql.awk> 11 12 12 BEGIN { 13 # Config wont get parsed until awkbot's BEGIN {} block 14 irc_register("initialize") 15 } 16 17 function irc_handler_initialize () { 13 function awkbot_db_init () { 18 14 mysql_login(config("mysql.username"), config("mysql.password")) 19 15 mysql_db(config("mysql.database")) … … 78 74 } 79 75 76 function awkbot_db_status_running (running) { 77 mysql_finish(mysql_query("UPDATE status SET running = " \ 78 running ? 1 : 0)) 79 80 if (! running) 81 mysql_finish(mysql_query("UPDATE status SET livefeed = null")) 82 } 83 84 function awkbot_db_status_connected (connected) { 85 mysql_finish(mysql_query("UPDATE status SET connected = " \ 86 connected ? 1 : 0)) 87 } 88 89 function awkbot_db_status_livefeed (filename ,rv,row) { 90 if (filename) { 91 mysql_finish(mysql_query("UPDATE status SET livefeed = " \ 92 mysql_quote(filename))) 93 } 94 else { 95 rv = mysql_query("SELECT livefeed FROM status") 96 97 mysql_fetch_row(rv, row) 98 filename = row[1] 99 100 mysql_finish(rv) 101 } 102 103 return filename 104 } 105 80 106 function awkbot_db_info (keyword ,result,rv,row) { 81 107 rv = mysql_query("select keyword, text from info where keyword like " \ -
trunk/awkbot/lib/awkpaste.awk
r44 r47 1 1 #!/usr/bin/awk -f 2 2 3 #i nclude<cgi-lib.awk>3 #import <cgi-lib.awk> 4 4 5 5 BEGIN { -
trunk/awkbot/lib/cgi-lib.awk
r44 r47 7 7 # Set this globally so we don't have to ensure it happens anywhere else... 8 8 ORS = "\r\n" 9 10 # Handle uploads... 11 12 # gawk only 13 match(HEADER["Content-Disposition"], / filename="([^;]*)"/, r) 14 filename = r[1] ? r[1] : "multipart/mixed" 15 16 if (filename && multipart) { 17 tempfilename = tempfile("cgi-awk") 18 } 19 20 # When it's multipart, save headers and body together 21 if (multipart) { 22 for (key in HEADER) print key ":", HEADER[key] >> tempfilename 23 print "\r\n" >> tempfilename 24 } 25 26 while (buffersize < length(input)) { 27 getline i 28 print i >> tempfile 29 } 30 31 print cgi_read_buffer() >> tempfilename 9 32 } 10 33 -
trunk/awkbot/lib/irc.awk
r8 r47 10 10 # ----------------------------------------------------------------------------- 11 11 12 # Init 12 # This library implements the IRC protocol only. An example of how to make it 13 # work with gawk's /inet/tcp is provided below. 13 14 14 BEGIN { 15 if (!irc["tempfile"]) irc["tempfile"] = irc_allocate_tempfile() 16 17 print "INIT" > irc["tempfile"] 18 close(irc["tempfile"]) 19 20 ARGV[ARGC++] = irc["tempfile"] 21 } 22 23 END { 24 system(sprintf("rm %s", irc["tempfile"])) 25 } 26 15 #import <socket.awk> 27 16 28 17 # ----------------------------------------------------------------------------- … … 84 73 # Connection API 85 74 function irc_privmsg (target, message) { 86 irc_sockwrite(sprintf("PRIVMSG %s :%s \r\n", target, message))75 irc_sockwrite(sprintf("PRIVMSG %s :%s", target, message)) 87 76 } 88 77 89 78 function irc_ctcp (target, type, arg) { 90 irc_sockwrite(sprintf("PRIVMSG %s :\x01%s %s\x01 \r\n", target, type, arg))79 irc_sockwrite(sprintf("PRIVMSG %s :\x01%s %s\x01", target, type, arg)) 91 80 } 92 81 93 82 function irc_ctcp_reply (target, type, arg) { 94 irc_sockwrite(sprintf("NOTICE %s :\x01%s %s\x01 \r\n", target, type, arg))83 irc_sockwrite(sprintf("NOTICE %s :\x01%s %s\x01", target, type, arg)) 95 84 } 96 85 97 86 function irc_join (channel) { 98 irc_sockwrite(sprintf("JOIN %s \r\n", channel))87 irc_sockwrite(sprintf("JOIN %s", channel)) 99 88 } 100 89 101 90 function irc_part (channel, message) { 102 irc_sockwrite(sprintf("PART %s :%s \r\n", channel, message))91 irc_sockwrite(sprintf("PART %s :%s", channel, message)) 103 92 } 104 93 105 94 function irc_quit (message) { 106 irc_sockwrite(sprintf("QUIT :%s \r\n", message))95 irc_sockwrite(sprintf("QUIT :%s", message)) 107 96 } 108 97 109 function irc_connect (host, port) { 110 irc_sockopen(host, port) 111 irc_sockwrite("NICK " irc["nickname"] "\n") 112 irc_sockwrite("USER " irc["username"] " a a :" irc["realname"] "\r\n") 98 function irc_connect (server ,t,host,port) { 99 # Pull host and port from host:port string 100 split(server, t, /:/) 101 102 host = t[1] 103 port = t[2] ? t[2] : 6667 104 105 socket_init(irc_socket, irc["tempfile"], !irc["tailpipe"]) 106 socket_connect(irc_socket, host, port) 107 108 irc_sockwrite("NICK " irc["nickname"]) 109 irc_sockwrite("USER " irc["username"] " a a :" irc["realname"]) 113 110 } 114 111 … … 118 115 # Raw internals 119 116 120 function irc_allocate_tempfile ( mktemp,tempfile) { 121 if (! irc["command", "mktemp"]) mktemp = "mktemp /tmp/irc.awk.XXXXXX" 122 else mktemp = irc["command", "mktemp"] 123 124 mktemp | getline tempfile 125 close(mktemp) 126 127 return tempfile 117 # Now just wraps socket_write 118 function irc_sockwrite (data) { 119 socket_write(irc_socket, data "\r\n") 128 120 } 129 121 130 function irc_sockwrite (data) { 131 if (irc["socket"]) printf data |& irc["socket"] 132 else irc_error("Attempt to write" data " to closed socket") 122 # Just wraps socket_close 123 function irc_sockclose () { 124 if (irc_socket) { 125 socket_close(irc_socket) 126 } 133 127 134 if (irc["debug"]) printf "> %s\n", data135 }136 137 function irc_sockopen (host,port ,t) {138 if (! irc["socket"]) {139 if (! port) {140 if (host !~ /:/) {141 irc_error("irc_sockopen called without port number")142 }143 144 split(host,t,/:/)145 host = t[1]146 port = t[2]147 }148 149 irc["socket"] = "/inet/tcp/0/" host "/" port150 }151 }152 153 function irc_sockclose () {154 if (irc["socket"]) {155 close(irc["socket"])156 delete irc["socket"]157 }158 128 else irc_error("irc_sockclose called with no open socket") 159 129 } 160 130 161 131 # ----------------------------------------------------------------------------- 162 # Main loop 163 164 { 165 if (irc["socket"]) { 166 # Get next line from socket and put in file for parsing 167 irc["socket"] |& getline 168 169 # Cycle Tempfile every 1000th line. 170 if (FNR == 1000) { 171 print > irc["tempfile"] 172 ARGV[ARGC++] = FILENAME 173 delete ARGV[ARGC - 2] 174 } 175 176 # Write to tempfile for next iteration 177 else print >> irc["tempfile"] 178 close(irc["tempfile"]) 179 180 if (irc["debug"]) print 181 } 182 } 132 # This is an example main loop, awkbot used to use it. I keep it in this 133 # source file only as an example, and will some day soon move it out into a 134 # test suite or some other bit of code. This code is well tested, and works 135 # like a charm, without flooding the filesystem with too much data. 136 # 137 # # Initialization 138 # 139 # BEGIN { 140 # if (!irc["tempfile"]) irc["tempfile"] = irc_allocate_tempfile() 141 # 142 # print "INIT" > irc["tempfile"] 143 # close(irc["tempfile"]) 144 # 145 # ARGV[ARGC++] = irc["tempfile"] 146 # } 147 # 148 # # Cleanup 149 # 150 # END { 151 # system(sprintf("rm %s", irc["tempfile"])) 152 # } 153 # 154 # # Main loop 155 # 156 # { 157 # 158 # if (irc["using_inet_tcp"] && irc["socket"]) { 159 # # Get next line from socket and put in file for parsing 160 # irc["socket"] |& getline 161 # 162 # # Cycle Tempfile every 1000th line. 163 # if (FNR == 1000) { 164 # print > irc["tempfile"] 165 # ARGV[ARGC++] = FILENAME 166 # delete ARGV[ARGC - 2] 167 # } 168 # 169 # # Write to tempfile for next iteration 170 # else print >> irc["tempfile"] 171 # close(irc["tempfile"]) 172 # 173 # if (irc["debug"]) print 174 # } 175 # } 183 176 184 177 END { if (irc["socket"]) close(irc["socket"]) }