]> Pileus Git - ~andy/rhawk/blob - irc.awk
Updates
[~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 |& socket
23         print "  > " msg
24 }
25 function recv(msg) {
26         print msg |& child
27         print "  < " msg
28 }
29 function debug(msg) {
30         print "  # " msg > "/dev/stderr"
31 }
32
33 function set() {
34         debug("CMD:  " CMD)
35         debug("SRC:  " SRC)
36         debug("DST:  " DST)
37         debug("FROM: " FROM)
38         debug("TO:   " TO)
39         debug("ARG:  " ARG)
40         debug("MSG:  " MSG)
41 }
42
43 # Reloading
44 function setup() {
45         "whoami"   | getline _name
46         "hostname" | getline _host
47         send("USER " _name " " _host " " server " :" nick)
48         send("NICK " nick)
49 }
50
51 function connect(server, port, nick, channel) {
52         SERVER  = server
53         PORT    = port
54         NICK    = nick
55         CHANNEL = channel
56
57         if (CHILD == "") {
58                 child  = "awk -f rhawk -v CHILD=1 -v FIRST=1"
59                 socket = "/inet/tcp/0/" SERVER "/" PORT
60
61                 debug("Starting server");
62                 while (running) {
63                         printf "" |& child 
64                         printf "" |& socket
65
66                         while (connected) {
67                                 if (!(fd = select("from", child, socket))) {
68                                         print "timeout"
69                                         continue
70                                 }
71                                 if (!(st = fd |& getline line)) {
72                                         print "broken pipe"
73                                         close(fd)
74                                         break
75                                 }
76                                 if (fd == socket)
77                                         recv(line)
78                                 if (fd == child)
79                                         send(line)
80                                 fflush()
81                         }
82                 }
83         } else {
84                 if (first)
85                         setup()
86                 debug("Starting child: CHILD=" CHILD " FIRST=" FIRST);
87         }
88
89 }
90
91 function quit() {
92         exit(0)
93 }
94
95 function reload() {
96         exit(1)
97 }
98
99 # Functions
100 function privmsg(to, msg) {
101         send("PRIVMSG " to " :" msg)
102 }
103
104 function say(msg) {
105         if (DST ~ "^#")
106                 privmsg(DST, msg)
107         else if (DST == NICK && FROM)
108                 privmsg(FROM, msg)
109         else
110                 privmsg(CHANNEL, msg)
111 }
112
113 function reply(msg) {
114         say(FROM ": " msg)
115 }
116
117 function join(chan) {
118         send("JOIN " chan)
119         send("TOPIC " chan)
120 }
121
122 function part(chan) {
123         send("PART " chan)
124 }
125
126 function topic(chan, msg) {
127         send("TOPIC " chan " :" msg)
128 }
129
130 # Input parsing
131 // {
132         match($0, /(:([^ ]+) +)?(([A-Z0-9]+) +)(([^ ]+) +)?(([^: ]+) +)?(:(.*))/, arr);
133         gsub(/\s+/,     " ", arr[8])
134         gsub(/^ | $/,    "", arr[8])
135         gsub(/\3[0-9]*/, "", arr[8])
136         SRC = arr[2]
137         CMD = arr[4]
138         DST = arr[6]
139         ARG = arr[8]
140         MSG = arr[10]
141
142         match(SRC, /([^! ]+)!/, arr);
143         FROM = arr[1]
144
145         match(MSG, /(([^ :,]*)[:,] *)?(.*)/, arr);
146         TO  = arr[2]
147         $0  = TO == NICK ? arr[3] : MSG
148
149         if (CMD == "PRIVMSG" && DST == NICK && FROM)
150                 TO = DST
151 }
152
153 # IRC client
154 CMD == "001" && MSG ~ /Welcome/ {
155         join(CHANNEL)
156 }
157
158 CMD == "PING" {
159         send("PING " MSG)
160 }
161
162 CMD == "332" {
163         CMD = "TOPIC"
164         DST = ARG
165 }
166
167 CMD == "TOPIC" {
168         topics[DST] = MSG
169 }