]> Pileus Git - ~andy/rhawk/blob - irc.awk
Save game after flipping the table
[~andy/rhawk] / irc.awk
1 # Connect with:
2 #   socat 'TCP:localhost:12345' 'EXEC:awk -f $0'
3 #
4 # Pre-defined variables:
5 #
6 # When connected:
7 #   SERVER:  IRC Server that is connected to
8 #   NICK:    Nickname given by the bot
9 #   CHANNEL: Channel the bot is currently in
10 #
11 # When a messages is recieved:
12 #   CMD:     Message, e.g. PRIVMSG
13 #   SRC:     Source of the message
14 #   DST:     Destination of the message, e.g. the channel
15 #   TO:      Nickname the message was addressed to
16 #   FROM:    Nickname of the user who sent the message
17 #   MSG:     Message sent
18 #   $0:      Message sans TO
19
20 # Debugging
21 function send(msg) {
22         print "  > " msg > "/dev/stderr"
23         print msg
24         fflush()
25 }
26
27 // {
28         #print ""         > "/dev/stderr"
29         print "  < " $0  > "/dev/stderr"
30 }
31
32 function debug(msg) {
33         print "  # " msg > "/dev/stderr"
34         fflush()
35 }
36
37 function set(i) {
38         debug("CMD:  [" CMD  "]")
39         debug("SRC:  [" SRC  "]")
40         debug("DST:  [" DST  "]")
41         debug("FROM: [" FROM "]")
42         debug("TO:   [" TO   "]")
43         debug("MSG:  [" MSG  "]")
44         debug("$0:   [" $0   "]")
45         for (i in ARG)
46                 debug("ARG"i": [" ARG[i] "]")
47 }
48
49 # Functions
50 function connect(server, nick, channel, auth, pass) {
51         SERVER  = server
52         NICK    = nick
53         CHANNEL = channel
54         if (FIRST) {
55                 "whoami"   | getline _name
56                 "hostname" | getline _host
57                 send("USER " _name " " _host " " server " :" nick)
58                 send("NICK " nick)
59                 send("CAP REQ :account-notify")
60                 send("CAP REQ :extended-join")
61                 send("CAP END")
62                 say("NickServ", "IDENTIFY " pass)
63         } else {
64                 send("WHOIS " nick)
65         }
66 }
67
68 function say(to, msg) {
69         if (msg == "") {
70                 msg = to
71                 if (DST ~ "^#")
72                         to = DST
73                 else if (DST == NICK && FROM)
74                         to = FROM
75                 else
76                         to = CHANNEL
77         }
78         send("PRIVMSG " to " :" msg)
79         if (!DEBUG && NR > 1)
80                 system("sleep 1")
81 }
82
83 function action(to, msg)
84 {
85         if (msg)
86                 say(to, "\001ACTION " msg "\001")
87         else
88                 say("\001ACTION " to "\001")
89 }
90
91 function reply(msg) {
92         say(FROM ": " msg)
93 }
94
95 function join(chan) {
96         send("JOIN " chan)
97         send("TOPIC " chan)
98         send("WHO " chan " %uhnar")
99 }
100
101 function part(chan) {
102         send("PART " chan)
103 }
104
105 function topic(chan, msg) {
106         send("TOPIC " chan " :" msg)
107 }
108
109 # Reloading
110 BEGIN {
111         if (CHILD == "") {
112                 debug("Starting server");
113                 cmd = "awk -f rhawk" \
114                       " -v CHILD=1" \
115                       " -v START=" systime() \
116                       " -v DEBUG=" !!DEBUG
117                 status = system(cmd " -v FIRST=1");
118                 while (status)
119                         status = system(cmd);
120                 exit(0);
121         } else {
122                 debug("Starting child:" \
123                       " DEBUG=" DEBUG   \
124                       " CHILD=" CHILD   \
125                       " START=" START   \
126                       " FIRST=" FIRST);
127         }
128 }
129
130 function quit() {
131         exit(0)
132 }
133
134 function reload() {
135         exit(1)
136 }
137
138 # Input parsing
139 // {
140         gsub(/\s+/, " ")
141         gsub(/^ | $/, "")
142         gsub(/[\2\11\17\23\25\26\37]/, "")
143         gsub(/[\3\13](1[0-5]|0?[0-9])?(,(1[0-5]|0?[0-9]))?/, "")
144         match($0, /(:([^ ]+) )?([A-Z0-9]+)(( [^:][^ ]*)*)( :(.*))?/, arr);
145         sub(/^ /, "", arr[4])
146         SRC = arr[2]
147         CMD = arr[3]
148         MSG = arr[7]
149
150         split(arr[4], ARG)
151         DST = ARG[1]
152
153         match(SRC, /([^! ]+)!([^@ ]+)@([^ ]+\/[^ ]+)?/, arr);
154         FROM = arr[1]
155         USER = arr[2]
156         HOST = arr[3]
157
158         match(MSG, /(([^ :,]*)[:,] *)?(.*)/, arr);
159         TO  = arr[2]
160         $0  = TO ? arr[3] : MSG
161
162         if (CMD == "PRIVMSG" && DST == NICK && FROM && !TO)
163                 TO = DST
164
165         if (FROM in USERS)
166                 AUTH = USERS[FROM]["auth"]
167         else
168                 AUTH = ""
169
170         #set()
171 }
172
173 # IRC client
174 CMD == "001" && MSG ~ /Welcome/ {
175         join(CHANNEL)
176 }
177
178 CMD == "PING" {
179         send("PING " MSG)
180 }
181
182 CMD == "332" {
183         TOPICS[ARG[2]] = MSG
184 }
185
186 CMD == "TOPIC" {
187         TOPICS[ARG[1]] = MSG
188 }
189
190 # Authentication
191 # todo - netsplits
192 CMD == "319" {
193         gsub(/[@+]/, "")
194         for (i=1; i<=NF; i++)
195                 send("WHO " $i " %uhnar")
196         for (i=1; i<=NF; i++)
197                 send("TOPIC " $i)
198 }
199
200 CMD == "ACCOUNT" {
201         _auth = ARG[1] == "*" ? 0 : ARG[1]
202         USERS[FROM]["auth"] = _auth
203 }
204
205 CMD == "354" {
206         _auth = ARG[5] == "*" ? 0 : ARG[5]
207         USERS[ARG[4]]["user"] = ARG[2]
208         USERS[ARG[4]]["host"] = ARG[3]
209         USERS[ARG[4]]["nick"] = ARG[4]
210         USERS[ARG[4]]["auth"] = _auth
211         USERS[ARG[4]]["real"] = MSG
212 }
213
214 CMD == "JOIN" {
215         _auth = ARG[2] == "*" ? 0 : ARG[2]
216         USERS[FROM]["user"] = USER
217         USERS[FROM]["host"] = HOST
218         USERS[FROM]["nick"] = FROM
219         USERS[FROM]["auth"] = _auth
220         USERS[FROM]["real"] = MSG
221 }
222
223 CMD == "NICK" {
224         USERS[MSG]["user"] = USERS[FROM]["user"]
225         USERS[MSG]["host"] = USERS[FROM]["host"]
226         USERS[MSG]["nick"] = MSG
227         USERS[MSG]["auth"] = USERS[FROM]["auth"]
228         USERS[MSG]["real"] = USERS[FROM]["real"]
229         delete USERS[FROM]
230 }