diff --git a/README b/README
new file mode 100644
index 0000000..2fa3013
--- /dev/null
+++ b/README
@@ -0,0 +1,29 @@
+Woozle IRC
+=========
+
+This is a sort of bouncer for clients with transient network connections,
+like cell phones and laptops.
+It's a lot like [tapchat](https://github.com/tapchat/tapchat) but is a whole lot simpler
+while being (at time of writing) much more feature-complete.
+
+It supports (currently) an JavaScript browser-based client,
+and can also be worked from the command-line using Unix tools like "tail" and "echo".
+
+Ironically, it doesn't currently work with any existing IRC clients,
+although we are kicking around ideas for such a thing.
+Honestly, though, if you want a bouncer for a traditional IRC client,
+you are better off using something like znc.
+
+We have an [architectural diagram](https://docs.google.com/drawings/d/1am_RTUh89kul-318GoYK73AbjOE_jMYi4vI4NyEgKrY/edit?usp=sharing) if you care about such things.
+
+
+Features
+--------
+
+* Gracefully handles clients with transient networking, such as cell phones and laptops.
+
+
+Todo
+-----
+
+I need to make this document suck less.
diff --git a/index.html b/index.html
index 323399b..7d42f5a 100644
--- a/index.html
+++ b/index.html
@@ -3,58 +3,16 @@
#tron
-
-
+
+
-
+
+
diff --git a/irc.css b/irc.css
new file mode 100644
index 0000000..4e2e243
--- /dev/null
+++ b/irc.css
@@ -0,0 +1,58 @@
+
+#foraText, #kiboze {
+ max-height: 20em;
+ overflow: scroll;
+}
+#foraText p, #kiboze p {
+ margin: 0em 0em 0em 4em;
+ text-indent: -4em;
+}
+#kiboze {
+ max-height: 7em;
+ background-color: #eee;
+}
+.timestamp {
+ color: silver;
+}
+.forum {
+ color: darkblue;
+ display: none;
+}
+.sender {
+ color: green;
+}
+.sender:before {
+ content: "<";
+}
+.sender:after {
+ content: ">";
+}
+.sender.notice {
+ color: olive;
+}
+.sender.notice:before {
+ content: "-";
+}
+.sender.notice:after {
+ content: "-";
+}
+.raw {
+ color: purple;
+}
+
+.active {
+ background-color: yellow;
+}
+.current {
+ background-color: aquamarine;
+}
+
+input[name~=target] {
+ width: 7em;
+}
+input[name~=text] {
+ width: 75%;
+}
+body {
+ height: 100%;
+}
\ No newline at end of file
diff --git a/irc.go b/irc.go
index 7d7ef5e..ceba86b 100644
--- a/irc.go
+++ b/irc.go
@@ -123,9 +123,12 @@ func parse(v string) (Message, error) {
m.Command = strings.ToUpper(parts[0])
switch m.Command {
case "PRIVMSG", "NOTICE":
- if isChannel(parts[1]) {
+ switch {
+ case isChannel(parts[1]):
m.Forum = parts[1]
- } else {
+ case m.FullSender == ".":
+ m.Forum = parts[1]
+ default:
m.Forum = m.Sender
}
case "PART", "MODE", "TOPIC", "KICK":
diff --git a/irc.js b/irc.js
index 133ab01..6ef0ab7 100644
--- a/irc.js
+++ b/irc.js
@@ -1,10 +1,59 @@
var msgRe = /([^ ]+) (<[^>]+>) (.*)/;
-var kibozeRe = "[Nn]eal";
+var kibozeRe = /[Nn]eal/;
+var urlRe = /[a-z]+:\/\/[^ ]*/;
+
+var nick = "Mme. M";
function isinView(oObject) {
return (oObject.offsetParent.clientHeight <= oObject.offsetTop);
}
+function selectForum(fe) {
+ var kids = document.getElementById("foraText").childNodes;
+
+ for (i = 0; i < kids.length; i += 1) {
+ e = kids[i];
+ console.log(i, e);
+ if (e == fe) {
+ e.style.display = "block";
+ } else {
+ e.style.display = "none";
+ if (e.button.className == "current") {
+ e.button.className = "";
+ }
+ }
+ }
+
+ fe.button.className = "current";
+ if (fe.lastChild) {
+ fe.lastChild.scrollIntoView(false);
+ }
+ document.getElementById("target").value = fe.forum;
+}
+
+function getForumElement(forum) {
+ var id = "a:" + forum;
+ var fe = document.getElementById(id);
+
+ if (! fe) {
+ var button = document.createElement("button");
+ button.appendChild(document.createTextNode(forum));
+ button.onclick = function() { selectForum(fe); }
+ document.getElementById("foraButtons").appendChild(button);
+
+ fe = document.createElement("div");
+ fe.id = id
+ fe.forum = forum
+ fe.button = button
+ document.getElementById("foraText").appendChild(fe);
+ }
+
+ if (fe.button.className != "current") {
+ fe.button.className = "active";
+ }
+ return fe;
+}
+
function addMessagePart(p, className, text) {
var e = document.createElement("span");
e.className = className;
@@ -12,11 +61,48 @@ function addMessagePart(p, className, text) {
p.appendChild(e);
p.appendChild(document.createTextNode(" "));
}
+
+function addText(p, text, kiboze) {
+ // Look for a URL
+ var txtElement = document.createElement("span");
+ txtElement.className = "text";
+ var rhs = text;
+ var match;
+
+ while ((match = urlRe.exec(rhs)) != null) {
+ var before = rhs.substr(0, match.index);
+ var a = document.createElement("a");
+ var href = match[0];
+
+ if (href.indexOf("hxx") == 0) {
+ href = "htt" + href.substr(3);
+ }
+ a.href = href
+ a.target = "_blank";
+ a.appendChild(document.createTextNode(match[0]));
+ txtElement.appendChild(document.createTextNode(before));
+ txtElement.appendChild(a);
+ rhs = rhs.substr(match.index + match[0].length);
+ }
+ txtElement.appendChild(document.createTextNode(rhs));
+ p.appendChild(txtElement);
+
+ if ((kiboze) || (-1 != text.search(kibozeRe))) {
+ var k = document.getElementById("kiboze");
+ var p2 = p.cloneNode(true);
+ k.insertBefore(p2, k.firstChild);
+ p2.onclick = function() { focus(p); }
+
+ // Setting title makes the tab flash sorta
+ document.title = document.title;
+ }
+}
function focus(e) {
var pct = 1;
var timeout;
+ selectForum(e.parentNode);
e.scrollIntoView(false);
e.style.backgroundColor = "yellow";
@@ -41,7 +127,7 @@ function addMessage(txt) {
var args = parts.slice(5);
var msg = txt.substr(lhs.length + 2)
- var a = document.getElementById("a");
+ var forumElement = getForumElement(forum);
var p = document.createElement("p");
addMessagePart(p, "timestamp", ts.toLocaleTimeString());
@@ -54,17 +140,12 @@ function addMessage(txt) {
case "PRIVMSG":
addMessagePart(p, "forum", forum);
addMessagePart(p, "sender", sender);
- addMessagePart(p, "text", msg);
- if ((sender == forum) || (-1 != msg.search(kibozeRe))) {
- var k = document.getElementById("kiboze");
- var p2 = p.cloneNode(true);
- k.insertBefore(p2, k.firstChild);
- p2.onclick = function() { focus(p); }
- // Supposedly changing title makes the tab flash sorta
- t = document.title
- document.title = "!"
- document.title = t
- }
+ addText(p, msg, (sender == forum));
+ break;
+ case "NOTICE":
+ addMessagePart(p, "forum", forum);
+ addMessagePart(p, "sender notice", sender);
+ addText(p, msg, (sender == forum));
break;
default:
addMessagePart(p, "forum", forum);
@@ -72,7 +153,7 @@ function addMessage(txt) {
addMessagePart(p, "raw", command + " " + args + " " + msg);
break;
}
- a.appendChild(p);
+ forumElement.appendChild(p);
p.scrollIntoView(false);
}