shithub: irc.myr

Download patch

ref: 777033348977a2350f2a9d051f33711acabfc79e
parent: 46e3bc47f9e4e925efd9ad90455535b5a50d2c65
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Oct 17 06:15:32 EDT 2019

Improve usability, error handling.

--- a/irc.myr
+++ b/irc.myr
@@ -33,9 +33,6 @@
 	| `std.Ok 0:	closed(irc, srv, "eof")
 	| `std.Ok n:	srv.nbuf += n
 	;;
-	if srv.death == 0
-		srv.ping = std.now()
-	;;
 
 	while true
 		match nextln(irc, srv)
@@ -46,6 +43,8 @@
 		(src, cmd, args) = parse(ln)
 		a0 = args.len > 0 ? args[0] : ""
 		uppercase(cmd)
+		srv.ping = std.now()
+
 		match cmd
 		| "001":	srvmsg(irc, args)
 		| "002":	srvmsg(irc, args)
@@ -62,6 +61,7 @@
 		| "372":	srvmsg(irc, args)
 		| "376":	srvmsg(irc, args)
 		| "333":	srvmsg(irc, args)
+		| "328":	srvmsg(irc, args)
 		| "470":	srvmsg(irc, args)
 		| "332":	topic(irc, srv, args)
 		| "353":	addusers(irc, srv, args)
@@ -69,6 +69,7 @@
 		| "PART":	delchanuser(irc, srv, src, args)
 		| "366":	shownames(irc, srv, args, 1)
 		| "401":	badmsg(irc, srv, args, ln)
+		| "477":	receivemsg(irc, srv, src, args.len > 0 ? args[1:] : args)
 		| "NOTICE":	receivemsg(irc, srv, src, args)
 		| "PRIVMSG":	receivemsg(irc, srv, src, args)
 		| "PING":	send(irc, srv, "PONG :{}\r\n", a0)
@@ -292,11 +293,20 @@
 }
 
 
-const displayname = {src
-	match std.strfind(src, "!")
-	| `std.Some i:	-> src[:i]
-	| `std.None:	-> src
+const displayname = {s
+	while true
+		match std.decode(s)
+		| '@':	s = s[1:]
+		| '%':	s = s[1:]
+		| '+':	s = s[1:]
+		| '~':	s = s[1:]
+		| _:	break;
+		;;
 	;;
+	match std.strfind(s, "!")
+	| `std.Some i:	-> s[:i]
+	| `std.None:	-> s
+	;;
 }
 
 const freechan = {chan
@@ -347,27 +357,40 @@
 }
 
 const changenick = {irc, args
-	if args.len != 1
+	var n, s
+
+	if args.len == 1
+		match cursrv(irc)
+		| `std.Some srv:
+			n = &srv.nick
+			s = srv.ds
+		| `std.None:
+			n = &irc.nick
+			s = "default"
+		;;
+	elif args.len == 3
+		match findsrv(irc, args[2])
+		| `std.Some srv:
+			n = &srv.nick
+			s = srv.ds
+		| `std.None:
+			status(irc, irc.self, "no server '{}'", args[2])
+			-> void
+		;;
+	else
 		status(irc, irc.self, "/nick: invalid args {j= }", args)
 		-> void
 	;;
 
-	match cursrv(irc)
-	| `std.None:
-		std.slfree(irc.nick)
-		irc.nick = std.sldup(args[0])
-		status(irc, irc.self, "default nick changed: {}", args[0])
-	| `std.Some srv:
-		std.slfree(irc.nick)
-		srv.nick = std.sldup(args[0])
-		send(irc, srv, "NICK {}\r\n", srv.nick)
-		status(irc, irc.self, "nick changed for {}: {}", srv.ds, args[0])
-	;;
+
+	std.slfree(n#)
+	n# = std.sldup(args[0])
+	status(irc, irc.self, "{} changed to {}", s, n#)
 }
 
 const changeuser = {irc, args
 	if args.len != 1
-		status(irc, irc.self, "/nick: invalid args {j= }", args)
+		status(irc, irc.self, "/user: invalid args {j= }", args)
 		-> void
 	;;
 
@@ -384,7 +407,7 @@
 
 const changeserver = {irc, args
 	if args.len != 1
-		status(irc, irc.self, "/nick: invalid args {j= }", args)
+		status(irc, irc.self, "/server: invalid args {j= }", args)
 		-> void
 	;;
 	match findsrv(irc, args[0])
@@ -670,7 +693,7 @@
 	elif msg.len > 3 && std.eq(msg[1], "-srv")
 		match findsrv(irc, msg[2])
 		| `std.Some s:	srv = s
-		| `std.None:	-> status(irc, irc.self, "can't message: no server '{}", msg[1])
+		| `std.None:	-> status(irc, irc.self, "can't message: no server '{}'", msg[2])
 		;;
 		txt = std.fmt("{j= }", msg[3:])
 	else
--- a/main.myr
+++ b/main.myr
@@ -46,17 +46,32 @@
 		elif fd >= 0
 			io(irc, fd)
 		;;
+		ping(irc)
 		redial(irc)
 	;;
 }
 
+const ping = {irc
+	for s : irc.srv
+		if s.death == 0 && (std.now() - s.ping) > 60*std.Sec
+			send(irc, s, "PING irc.myr")
+			/* let's not flood */
+			s.ping = std.now()
+		;;
+	;;
+}
+
 const redial = {irc
 	var pingtime, droptime
 
 	for s : irc.srv
-		droptime = std.now() - s.death 
+		droptime = s.death == 0 ? 0 : std.now() - s.death 
 		pingtime = std.now() - s.ping
-		if pingtime < 600*std.Sec || s.death == 0 || droptime < 60*std.Sec
+		if droptime >= 60*std.Sec
+			status(irc, irc.self, "{}: connection dropped\n", s.ds)
+		elif pingtime >= 300*std.Sec
+			status(irc, irc.self, "{}: ping timed out\n", s.ds)
+		else
 			continue
 		;;
 		std.close(s.fd)
@@ -65,7 +80,7 @@
 		| `std.Ok fd:
 			s.fd = fd
 			handshake(irc, s)
-			s.death = 0
+			s.death = std.now()
 			for c : irc.onconn
 				do(irc, c)
 				redraw(irc)
--