]> Pileus Git - ~andy/rhawk/blob - irc.awk
Add auth
[~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         if (!DEBUG)
25                 system("sleep 1")
26         fflush()
27 }
28
29 // {
30         #print ""         > "/dev/stderr"
31         print "  < " $0  > "/dev/stderr"
32 }
33
34 function debug(msg) {
35         print "  # " msg > "/dev/stderr"
36         fflush()
37 }
38
39 function set() {
40         debug("CMD:  [" CMD  "]")
41         debug("SRC:  [" SRC  "]")
42         debug("DST:  [" DST  "]")
43         debug("FROM: [" FROM "]")
44         debug("TO:   [" TO   "]")
45         debug("ARG:  [" ARG  "]")
46         debug("MSG:  [" MSG  "]")
47         debug("$0:   [" $0   "]")
48 }
49
50 # Functions
51 function connect(server, nick, channel) {
52         SERVER  = server
53         NICK    = nick
54         CHANNEL = channel
55         if (FIRST) {
56                 "whoami"   | getline _name
57                 "hostname" | getline _host
58                 send("USER " _name " " _host " " server " :" nick)
59                 send("NICK " nick)
60         }
61 }
62
63 function say(to, msg) {
64         if (msg == "") {
65                 msg = to
66                 if (DST ~ "^#")
67                         to = DST
68                 else if (DST == NICK && FROM)
69                         to = FROM
70                 else
71                         to = CHANNEL
72         }
73         send("PRIVMSG " to " :" msg)
74 }
75
76 function action(to, msg)
77 {
78         if (msg)
79                 say(to, "\001ACTION " msg "\001")
80         else
81                 say("\001ACTION " to "\001")
82 }
83
84 function reply(msg) {
85         say(FROM ": " msg)
86 }
87
88 function join(chan) {
89         send("JOIN " chan)
90         send("TOPIC " chan)
91         send("WHO " chan " %na")
92 }
93
94 function part(chan) {
95         send("PART " chan)
96 }
97
98 function topic(chan, msg) {
99         send("TOPIC " chan " :" msg)
100 }
101
102 # Reloading
103 BEGIN {
104         if (CHILD == "") {
105                 debug("Starting server");
106                 cmd = "awk -f rhawk" \
107                       " -v CHILD=1" \
108                       " -v START=" systime() \
109                       " -v DEBUG=" !!DEBUG
110                 status = system(cmd " -v FIRST=1");
111                 while (status)
112                         status = system(cmd);
113                 exit(0);
114         } else {
115                 debug("Starting child:" \
116                       " DEBUG=" DEBUG   \
117                       " CHILD=" CHILD   \
118                       " START=" START   \
119                       " FIRST=" FIRST);
120         }
121 }
122
123 function quit() {
124         exit(0)
125 }
126
127 function reload() {
128         exit(1)
129 }
130
131 # Input parsing
132 // {
133         gsub(/\s+/,     " ")
134         gsub(/^ | $/,    "")
135         gsub(/\3[0-9]*/, "")
136         match($0, /(:([^ ]+) +)?(([A-Z0-9]+) +)(([^ ]+) +)?(([^: ]+) +)?(:(.*))/, arr);
137         SRC = arr[2]
138         CMD = arr[4]
139         DST = arr[6]
140         ARG = arr[8]
141         MSG = arr[10]
142
143         match(SRC, /([^! ]+)!([^@ ]+)@([^ ]+\/[^ ]+)?/, arr);
144         FROM = arr[1]
145         AUTH = arr[3]
146
147         match(MSG, /(([^ :,]*)[:,] *)?(.*)/, arr);
148         TO  = arr[2]
149         $0  = TO ? arr[3] : MSG
150
151         if (CMD == "PRIVMSG" && DST == NICK && FROM && !TO)
152                 TO = DST
153
154         #set()
155 }
156
157 # IRC client
158 CMD == "001" && MSG ~ /Welcome/ {
159         join(CHANNEL)
160 }
161
162 CMD == "PING" {
163         send("PING " MSG)
164 }
165
166 CMD == "332" {
167         CMD = "TOPIC"
168         DST = ARG
169 }
170
171 CMD == "TOPIC" {
172         topics[DST] = MSG
173 }
174
175 # Authentication
176 # todo - netsplits
177 BEGIN {
178         send("CAP REQ :account-notify")
179         send("CAP REQ :extended-join")
180 }
181
182 CMD == "ACCOUNT" {
183         if (ARG == "*")
184                 debug("logout")
185         else
186                 debug("name change")
187         set()
188 }
189
190 CMD == "354" {
191         debug("user list")
192         set()
193 }
194
195 CMD == "JOIN" {
196         debug("join")
197         set()
198 }