diff --git a/doc/INSTALL.md b/INSTALL.md
similarity index 100%
rename from doc/INSTALL.md
rename to INSTALL.md
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..a4af36e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2015 Neale Pickett
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+The software is provided "as is", without warranty of any kind, express or
+implied, including but not limited to the warranties of merchantability,
+fitness for a particular purpose and noninfringement. In no event shall
+the authors or copyright holders be liable for any claim, damages or
+other liability, whether in an action of contract, tort or otherwise,
+arising from, out of or in connection with the Software or the use or
+other dealings in the Software.
+
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 6f90e66..0000000
--- a/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-ICONS += app/icon-16.png
-ICONS += app/icon-32.png
-ICONS += app/icon-48.png
-ICONS += app/icon-128.png
-ICONS += app/icon-256.png
-
-all: icons serverside
-
-serverside: spongy spongy.cgi
-
-spongy: src/spongy/spongy.go
- GOPATH=$(CURDIR) go build -v $@
-
-spongy.cgi: src/spongy.cgi/spongy.cgi.go
- GOPATH=$(CURDIR) go build -v $@
- chmod +s $@
-
-icons: $(ICONS)
-
-app/icon-%.png: chat.svg
- inkscape --export-png=$@ --export-width=$* $<
-
-package: icons
- cd app && zip -ru ../package.zip .
diff --git a/doc/PROTOCOL.md b/PROTOCOL.md
similarity index 100%
rename from doc/PROTOCOL.md
rename to PROTOCOL.md
diff --git a/doc/TODO.md b/TODO.md
similarity index 100%
rename from doc/TODO.md
rename to TODO.md
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
deleted file mode 100644
index 89e140c..0000000
--- a/app/_locales/en/messages.json
+++ /dev/null
@@ -1,75 +0,0 @@
-{
- "appName": {
- "description": "Application name",
- "message": "Spongy Chat Client"
- },
- "appShortName": {
- "description": "Short application name",
- "message": "Spongy Chat"
- },
- "appDesc": {
- "description": "Application description for app store listing",
- "message": "Chat client for the Spongy bouncer thingamajiggy"
- },
-
-
- "unknownCommand": {
- "description": "Text for unrecognized command",
- "message": "??? $COMMAND$ $ARGS$ $TEXT$",
- "placeholders": {
- "fullSender": {
- "content": "$1",
- "example": "fritz!~bob@example.net"
- },
- "command": {
- "content": "$2",
- "example": "PRIVMSG"
- },
- "sender": {
- "content": "$3",
- "example": "fritz"
- },
- "forum": {
- "content": "$4",
- "example": "#hottub"
- },
- "args": {
- "content": "$5",
- "example": "+o,fred"
- },
- "text": {
- "content": "$6",
- "example": "Hello everybody"
- }
- }
- },
-
- "privmsgCommand": {
- "description": "Text for a privmsg (a regular chat message)",
- "message": "$6"
- },
-
- "noticeCommand": {
- "description": "Text for a notice",
- "message": "$6"
- },
-
- "nickCommand": {
- "description": "Text for nickname change",
- "message": "$1 is now known as $3"
- },
-
- "modeCommand": {
- "message": "sets channel mode $5"
- },
-
- "joinCommand": {
- "description": "Channel join",
- "message": "joins the channel."
- },
-
- "faultCommand": {
- "description": "Spongy fault",
- "message": "Spongy error: $6"
- }
-}
diff --git a/app/background.js b/app/background.js
deleted file mode 100644
index 78df071..0000000
--- a/app/background.js
+++ /dev/null
@@ -1,10 +0,0 @@
-chrome.app.runtime.onLaunched.addListener(function() {
- chrome.app.window.create('wirc.html', {
- state: 'normal',
- width: 775,
- height: 400,
- minWidth: 320,
- minHeight: 160,
- id: 'spongy'
- })
-})
diff --git a/app/channel.js b/app/channel.js
deleted file mode 100644
index cde7a42..0000000
--- a/app/channel.js
+++ /dev/null
@@ -1 +0,0 @@
-merf.
\ No newline at end of file
diff --git a/app/example.html b/app/example.html
deleted file mode 100644
index 0c07b8a..0000000
--- a/app/example.html
+++ /dev/null
@@ -1,361 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-CIRC undefined
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
members
-
- also
-
- atob
-
- Bermuda
-
- bit
-
- bk
-
- bz2
-
- caycos
-
- ckape
-
- clavicle
-
- CrackMonkey
-
- Dumont
-
- dzho
-
- emad
-
- eythian
-
- felixc
-
- fo0bar
-
- fuzzie
-
- GodEater
-
- hollow
-
- hoylemd
-
- jhewl
-
- jv
-
- kees
-
- khmer
-
- lamont
-
- lexicondal
-
- neale
-
- nemo
-
- nerdtron3000
-
- nornagon
-
- Octal
-
- pdx6
-
- pedro
-
- Randall
-
- sarah
-
- Sciri
-
- scorche
-
- scorche|sh
-
- Screwtape
-
- sneakums
-
- squinky
-
- stat
-
- teferi
-
- tiaz
-
- watson
-
- wcarss
-
- wombat
-
- X11R5
-
- Zen
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/manifest.json b/app/manifest.json
deleted file mode 100644
index aa8e692..0000000
--- a/app/manifest.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
- "manifest_version": 2,
- "version": "1.0",
-
- "name": "__MSG_appName__",
- "short_name": "__MSG_appShortName__",
- "description": "__MSG_appDesc__",
- "author": "Neale Pickett ",
- "icons": {
- "16": "icon-16.png",
- "32": "icon-32.png",
- "48": "icon-48.png",
- "128": "icon-128.png",
- "256": "icon-256.png"
- },
- "app": {
- "background": {
- "scripts": ["background.js"]
- }
- },
- "permissions": [
- "storage",
- "fileSystem",
- "https://woozle.org/"
- ],
- "default_locale": "en"
-}
diff --git a/app/message_style.css b/app/message_style.css
deleted file mode 100644
index 163113e..0000000
--- a/app/message_style.css
+++ /dev/null
@@ -1,165 +0,0 @@
-.message.mode, .message.nick, .message.join {
- color: #606043;
-}
-
-.message.notice {
- color: #97008B;
- font-style: oblique;
-}
-
-.message.error {
- color: #B33B2D;
-}
-
-.message.self {
- color: #005816;
-}
-
-.message.privmsg {
- color: #505053;
-}
-
-.message.privmsg.self {
- color: gray;
-}
-
-.message.privmsg.mention {
- color: darkred;
-}
-
-.message.privmsg.mention .source {
- font-weight: bold;
-}
-
-.message.privmsg.direct .source {
- color: #488AA8;
-}
-
-/* Nickname Colors. Taken from Textual */
-
-.message.privmsg.self .source-content-container .source {
- color: #ea0d68;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='0'] {
- color: #0080ff;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='1'] {
- color: #059005;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='2'] {
- color: #a80054;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='3'] {
- color: #9b0db1;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='4'] {
- color: #108860;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='5'] {
- color: #7F4FFF;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='6'] {
- color: #58701a;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='7'] {
- color: #620a8e;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='8'] {
- color: #BB0008;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='9'] {
- color: #44345f;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='10'] {
- color: #2f5353;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='11'] {
- color: #904000;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='12'] {
- color: #808000;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='13'] {
- color: #57797e;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='14'] {
- color: #3333dd;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='15'] {
- color: #5f4d22;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='16'] {
- color: #706616;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='17'] {
- color: #46799c;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='18'] {
- color: #80372e;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='19'] {
- color: #8F478E;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='20'] {
- color: #5b9e4c;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='21'] {
- color: #13826c;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='22'] {
- color: #b13637;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='23'] {
- color: #e45d59;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='24'] {
- color: #1b51ae;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='25'] {
- color: #4855ac;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='26'] {
- color: #7f1d86;
-}
-.message:not(.self) .source-content-container .source[colornumber='27'] {
- color: #73643f;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='28'] {
- color: #0b9578;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='29'] {
- color: #569c96;
-}
-
-.message:not(.self) .source-content-container .source[colornumber='30'] {
- color: #08465f;
-}
diff --git a/app/network.js b/app/network.js
deleted file mode 100644
index 7c93913..0000000
--- a/app/network.js
+++ /dev/null
@@ -1,102 +0,0 @@
-// Functionality dealing with server-level things
-
-var maxScrollback = 500;
-var networks = {};
-
-function networkConnect(network, baseURL, authtok) {
- var eventSource;
- var element = getTemplate("server-channels");
- var channels = element.getElementsByClassName("channels")[0];
- var roomElement = element.getElementsByClassName("server")[0];
- var rooms = {".": roomElement};
- newRoom(roomElement, element, network, maxScrollback);
-
- function makeRoom(name) {
- var rElement = getTemplate("channel");
- newRoom(rElement, element, name, maxScrollback);
- channels.appendChild(rElement);
- rooms[name] = rElement;
- return rElement;
- }
-
- function handleEventSourceLine(line) {
- var lhs = line.split(" :", 1)[0];
- var parts = lhs.split(' ');
-
- var timestamp = new Date(parts[0] * 1000);
- var fullSender = parts[1];
- var command = parts[2].toLowerCase();
- var sender = parts[3];
- var forum = parts[4];
- var args = parts.slice(5);
- var txt = line.substr(lhs.length + 2);
-
- switch (command) {
- case "prevlog":
- // Just ignore this
- return;
- }
-
- var room = rooms[forum];
- if (! room) {
- room = makeRoom(forum);
- }
-
- // XXX: Handle differently based on command
- room.addMessage(timestamp, fullSender, command, sender, args, txt);
- }
-
- function handleEventSourceMessage(oEvent) {
- msgs = oEvent.data.split("\n");
-
- var first = Math.max(0, msgs.length - maxScrollback);
- for (var i = first; i < msgs.length; i += 1) {
- handleEventSourceLine(msgs[i]);
- }
- }
-
- function handleEventSourceError(oEvent) {
- timestamp = new Date();
- roomElement.addMessage(timestamp, ".", "fault", ".", [], "Unable to open events feed (permissions problem on server?)");
- console.log(oEvent);
- }
-
- element.send = function(target, text) {
- function handleError(oEvent) {
- console.log("XXX: That didn't work out.", target, text)
- }
-
- var form = new FormData();
- form.append("type", "command");
- form.append("auth", authtok);
- form.append("network", network);
- form.append("target", target);
- form.append("text", text);
-
- var oReq = new XMLHttpRequest();
- oReq.addEventListener("error", handleError);
- oReq.open("POST", baseURL, true);
- oReq.send(form);
- }
-
- element.close = function() {
- console.log("Closing");
- eventSource.close();
- element.parentNode.removeChild(element);
- roomElement.close();
- // XXX: Close all associated rooms, too!
- }
-
-
- if (networks[network]) {
- networks[network].close();
- }
- networks[network] = element;
-
- var pullURL = baseURL + "?network=" + encodeURIComponent(network) + "&auth=" + encodeURIComponent(authtok);
- eventSource = new EventSource(pullURL);
- eventSource.addEventListener("message", handleEventSourceMessage);
- eventSource.addEventListener("error", handleEventSourceError);
-
- document.getElementsByClassName("rooms")[0].appendChild(element);
-}
diff --git a/app/room.js b/app/room.js
deleted file mode 100644
index 24413ed..0000000
--- a/app/room.js
+++ /dev/null
@@ -1,162 +0,0 @@
-function djbhash(a) {
- var r = 5381;
-
- for (var i = 0; i < a.length; i += 1) {
- r = (((r << 5) + r) + a.charCodeAt(i)) & 0xffff;
- }
- return r;
-}
-
-function purtify(text) {
- // 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));
-
- return txtElement;
-}
-
-function kiboze(this_is_currently_busted) {
-
- if ((kiboze) || (-1 != text.search(kibozeRe))) {
- var k = document.getElementById("kiboze");
- var p2 = p.cloneNode(true);
-
- if (k) {
- k.insertBefore(p2, k.firstChild);
- p2.onclick = function() { focus(p); }
-
- // Setting title makes the tab flash sorta
- document.title = document.title;
- }
- }
-}
-
-
-var visibleRoom;
-
-function newRoom(element, network, name, maxSize) {
- var messages = getTemplate("messages");
- var lastmsg;
- if (! maxSize) {
- maxSize = 500;
- }
-
- function purtify(fullSender, command, sender, args, txt) {
- var txtElement = document.createElement("span");
- var msg = chrome.i18n.getMessage(command + "Command", [fullSender, command, sender, name, args, txt]);
- if (! msg) {
- msg = chrome.i18n.getMessage("unknownCommand", [fullSender, command, sender, name, String(args), txt]);
- }
-
- var rhs = msg;
- 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));
-
- return txtElement;
- }
-
-
- element.addMessage = function(timestamp, fullSender, command, sender, args, txt) {
- var message = getTemplate("message");
-
- var eTimestamp = message.getElementsByClassName("timestamp")[0];
- var eSource = message.getElementsByClassName("source")[0];
- var eContent = message.getElementsByClassName("content")[0];
-
- message.classList.add(command);
- if (sender == ".") {
- message.classList.add("self");
- }
-
- eTimestamp.textContent = timestamp.toLocaleTimeString();
- eSource.textContent = sender;
- eSource.setAttribute("colornumber", djbhash(sender) % 31);
- eContent.appendChild(purtify(fullSender, command, sender, args, txt));
-
- messages.appendChild(message);
-
- while (messages.childNodes.length > maxSize) {
- messages.removeChild(messages.firstChild);
- }
-
- lastmsg = message;
-
- if (visibleRoom == element) {
- lastmsg.scrollIntoView(false);
- }
- }
-
- element.hide = function() {
- element.classList.remove("selected");
- messages.style.display = "none";
- }
-
- element.show = function() {
- if (visibleRoom) {
- visibleRoom.hide()
- }
- element.classList.add("selected");
- messages.style.display = null;
- lastmsg.scrollIntoView(false);
- visibleRoom = element;
- }
-
- element.send = function(text) {
- network.send(name, text);
- }
-
- element.close = function() {
- console.log(messages);
- console.log(messages.parent);
- messages.parent.removeChild(messages);
- element.parent.removeChild(element);
- }
-
- function clicked() {
- element.show();
- }
-
- // start hidden
- element.hide();
- element.addEventListener("click", clicked);
- element.getElementsByClassName("content-item")[0].textContent = name;
-
- document.getElementById("messages-container").appendChild(messages);
-
- return element;
-}
\ No newline at end of file
diff --git a/app/style.css b/app/style.css
deleted file mode 100644
index 1fc5645..0000000
--- a/app/style.css
+++ /dev/null
@@ -1,484 +0,0 @@
-html, body {
- margin: 0;
- padding: 0
-}
-
-*, *:before, *:after {
- -moz-box-sizing: border-box;
- -webkit-box-sizing: border-box;
- box-sizing: border-box;
-}
-
-body {
- color: #505053;
- /* font-family: sans-serif; */
- font-size: 100%;
-}
-
-.hidden {
- display: none;
-}
-
-#templates {
- display: none;
-}
-
-ul {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-.footer {
- display: none;
- font-style: italic;
- color: #9493A2;
-}
-
-.help-command {
- display: inline-block;
- width: 7em;
-}
-
-.content-item {
- white-space: nowrap;
- overflow-x: hidden;
- text-overflow: ellipsis;
-}
-
-#main {
- display: -webkit-box;
- -webkit-box-orient: horizontal;
- width: 100%;
- height: 100%;
- position: absolute;
- border-top: 1px solid rgba(0,0,0,0.15);
-}
-
-#main-top-border {
- position: absolute;
- top: 0;
- z-index: 100;
- width: 100%;
- height: 1px;
- background-color: rgba(0,0,0,0.05);
- pointer-events: none;
-}
-
-#rooms-and-nicks {
- background-color: #F7F5E4;
- display: -webkit-box;
- -webkit-box-orient: vertical;
- -webkit-box-flex: 0;
- width: 150px;
- height: inherit;
- padding: 4px 0px;
- border-right: 1px solid rgba(0, 0, 0, .15);
- overflow-y: auto;
- -webkit-overflow-scrolling: touch;
-}
-
-#rooms-and-nicks h1 {
- color: #406698;
- text-transform: uppercase;
- font-size: smaller;
- padding: 8px 0px 2px 8px;
- margin: 0px;
-}
-
-#rooms-and-nicks .nick,
-#rooms-and-nicks .room {
- padding: 0 8px;
- line-height: 26px;
-}
-
-#rooms-and-nicks .room {
- cursor: pointer;
-}
-
-#rooms-and-nicks .server.footer {
- display: block;
-}
-
-.dragbar:hover {
- width: 6px;
- transition: width .1s;
-}
-
-.dragbar {
- height: 100%;
- width: 1px;
- cursor: col-resize;
-}
-
-#ghostbar{
- width:3px;
- background-color:#000;
- opacity:0.8;
- position:absolute;
- cursor: col-resize;
- z-index:999
-}
-
-#rooms-container {
- -webkit-box-flex: 0;
- border-bottom: 1px solid #CCC;
- padding-bottom: 10px;
-}
-
-.no-nicks #rooms-container {
- border-bottom-style: none;
- padding-bottom: 0px;
-}
-
-#rooms-and-nicks.hidden {
- display: none;
-}
-
-#rooms-and-nicks .room.server {
- background-color: #F2EFD3;
- position: relative;
-}
-
-#rooms-and-nicks:hover .room.server .content-item {
- width: 130px;
-}
-
-#rooms-and-nicks .add-channel {
- position: absolute;
- right: 2px;
- top: -1px;
- cursor: pointer;
- font-size: larger;
- display: none;
-}
-
-#rooms-and-nicks:hover .add-channel {
- display: block;
-}
-
-#rooms-and-nicks .add-channel:hover {
- color: #888;
-}
-
-#rooms-and-nicks .room.channel:first-child {
- padding-top: 3px;
-}
-
-#rooms-and-nicks .room.channel:first-child .content-item {
- padding-bottom: 3px;
- line-height: 20px;
-}
-
-#rooms-and-nicks not(.current-server) + .channels .room.channel:nth-last-child(2) {
- padding-bottom: 3px;
-}
-#rooms-and-nicks .room.channel:last-child {
- padding-bottom: 3px;
-}
-
-#rooms-and-nicks not(.current-server) + .channels .room.channel:nth-last-child(2) .content-item {
- padding-top: 3px;
- line-height: 20px;
-}
-#rooms-and-nicks .room.channel:last-child .content-item {
- padding-top: 3px;
- line-height: 20px;
-}
-
-#rooms-and-nicks not(.current-server) + .channels .room.channel:nth-last-child(2):first-child .content-item {
- line-height: 14px;
-}
-#rooms-and-nicks .room.channel:last-child:first-child .content-item {
- line-height: 14px;
-}
-
-#rooms-and-nicks .current-server:not(.always-empty) + .channels .footer {
- display: block;
-}
-
-#rooms-and-nicks .room.channel .content-item {
- border-left: 1px solid rgba(0, 0, 0, .5);
- padding-left: 7px;
-}
-
-#rooms-and-nicks .room.activity {
- font-weight: bold;
-}
-
-#rooms-and-nicks .room.mention {
- color: darkred;
-}
-
-#rooms-and-nicks .room.disconnected .content-item {
- color: #9493A2;
- font-style: italic;
-}
-
-#rooms-and-nicks .room.channel.disconnected .content-item {
- border-left: 1px solid #9493A2;
-}
-
-#rooms-and-nicks .room.selected {
- background-color: #F0E798;
-}
-
-#rooms-and-nicks .room {
- position: relative;
-}
-
-#rooms-and-nicks .room .remove-button {
- position: absolute;
- right: 6px;
- top: -1px;
- cursor: pointer;
- font-size: x-large;
- color: rgba(0, 0, 0, .25);
- display: none;
-}
-
-#rooms-and-nicks .room .remove-button:hover {
- color: rgba(0, 0, 0, .5);
-}
-
-#rooms-and-nicks .room.selected:not(.footer):not(.always-empty) .content-item {
- width: 123px;
-}
-#rooms-and-nicks .room:hover:not(.footer):not(.always-empty) .content-item {
- width: 123px;
-}
-
-#rooms-and-nicks .room.selected:not(.footer):not(.always-empty) .remove-button {
- display: inline-block;
-}
-#rooms-and-nicks .room:hover:not(.footer):not(.always-empty) .remove-button {
- display: inline-block;
-}
-
-#nicks-container {
- border-top: 1px solid #FFF;
- -webkit-box-flex: 1;
-}
-
-.no-nicks #nicks-container {
- display: none;
-}
-
-.rooms,
-.nicks {
- padding-top: 5px;
-}
-
-.nicks li:nth-child(odd) {
- background-color: #F2EFD3;
-}
-
-#notice {
- background-color: #406698;
- box-shadow: 0px 1px 4px #888;
- color: #FFF;
- position: absolute;
- width: 100%;
- -webkit-transition: 150ms;
- top: 0;
- padding: 2px 0;
-}
-
-#notice.hide {
- top: -38px;
-}
-
-#notice .content {
- display: inline;
- padding-left: 14px;
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow-x: hidden;
- position: absolute;
- top: 50%;
- margin-top: -.5em;
-}
-
-#notice button {
- float: right;
- height: 22px;
- font-size: 14px;
- padding: 0px 4px;
- margin: 4px;
- border: none;
- background-color: #ECECEC;
- color: #505053;
- cursor: pointer;
- outline: none;
-}
-
-#notice button.close {
- margin-right: 8px;
- font-size: 12px;
- border-radius: 42px;
- width: 21px;
- height: 21px;
-}
-
-#messages-and-input {
- -webkit-box-flex: 1;
- display: -webkit-box;
- -webkit-box-orient: vertical;
- box-shadow: 0px 0px 8px #CCC;
- position: relative;
-}
-
-#messages-container {
- overflow-y: auto;
- -webkit-overflow-scrolling: touch;
- -webkit-box-flex: 1;
- border-bottom: 1px solid #CCC;
-}
-
-.messages {
- display: table;
-}
-
-.message {
- display: table-row;
- -webkit-user-select: initial;
-}
-
-.message.activity-marker .source-content-container {
- border-top: 1px solid rgb(224, 179, 179);
-}
-
-.message .timestamp {
- color: #6060C0;
- font-style: italic;
- /* font-size: smaller; */
- white-space: nowrap;
- display: table-cell;
- text-align: right;
- padding: 0px 10px 0px 10px;
- border-right: 1px solid rgba(0,0,0,0.15);
- cursor: text;
-}
-
-.source-content-container {
- display: table-cell;
- padding: 1px 10px 1px 15px;
- width: 100%;
-}
-
-.message .source {
- font-weight: bold;
- padding-right: 5px;
- margin-left: -5px;
- white-space: nowrap;
- display: inline;
- text-align: right;
- cursor: text;
-}
-
-.message .source.empty {
- padding-right: 0;
-}
-
-.message .content {
- display: inline;
- white-space: pre-wrap;
- cursor: text;
- word-break: break-word;
-}
-
-#messages-container .messages .message:first-child .source-content-container {
- padding-top: 10px;
-}
-
-#messages-container .messages .message:last-child .source-content-container {
- padding-bottom: 8px;
-}
-
-.message.list {
- /* empty style for now */
-}
-
-.longword { word-break: break-all; }
-
-#nick-and-input {
- border-top: 1px solid #F9F9F9;
- -webkit-box-flex: 0;
- display: -webkit-box;
- background-color: #ECECEC;
- padding: 5px 10px 5px 10px;
-}
-
-#nick {
- padding-top: 5px;
-}
-
-#nick > span {
- padding-right: 10px;
-}
-
-#nick > .name:before {
- font-weight: bold;
- content: "[ "
-}
-#nick > .name:after {
- font-weight: bold;
- content: " ]"
-}
-
-#nick .away:before {
- content: "("
-}
-#nick .away:after {
- content: ")"
-}
-
-#input-bar {
- -webkit-box-flex: 1;
- display: -webkit-box;
-}
-
-#input {
- background-color: #F9F9F9;
- display: block;
- -webkit-box-flex: 1;
- width: 100%;
- height: 30px;
- border: 1px;
- border-radius: 5px;
- -webkit-box-shadow: 0px 0px 3px #888;
- color: #505053;
- font-size: 100%;
- padding: 0px 8px;
- outline: 0;
-}
-
-#input.blink {
- -webkit-box-shadow: 0px 0px 6px #406698;
-}
-
-::-webkit-scrollbar {
- width: 9px;
- height: 9px;
-}
-::-webkit-scrollbar-button:start:decrement,
-::-webkit-scrollbar-button:end:increment {
- display: block;
- height: 0;
-}
-::-webkit-scrollbar-track-piece {
- background-color: rgba(0,0,0,0.1);
-}
-::-webkit-scrollbar-thumb:vertical {
- height: 50px;
- background-color: #999;
- border-radius: 8px;
-}
-::-webkit-scrollbar-thumb:vertical:hover {
- background-color: #888;
-}
-::-webkit-scrollbar-thumb:horizontal {
- width: 50px;
- background-color: #999;
- border-radius: 8px;
-}
diff --git a/app/topbar.css b/app/topbar.css
deleted file mode 100644
index 8db1003..0000000
--- a/app/topbar.css
+++ /dev/null
@@ -1,43 +0,0 @@
-#hide-channels {
- display: inline-block;
- font-size: 12px;
-}
-
-#topic-container {
- border-bottom: 1px solid #CCC;
- -webkit-box-flex: 0;
- display: -webkit-box;
- background-color: #ECECEC;
- padding: 4px 6px;
-}
-
-#status {
- -webkit-box-flex: 1;
- padding: 4px 5px;
-}
-
-#status .topic {
- font-style: italic;
-}
-
-.topbar-button {
- background: rgba(0, 0, 0, .08);
- border: 0 transparent;
- text-decoration: none;
- cursor: pointer;
- border-radius: 2px;
- -webkit-transition: .1s linear -webkit-box-shadow;
- margin-right: 4px;
-}
-
-.topbar-button:active {
- box-shadow: 0 0 0 1px rgba(0 ,0 ,0 ,.15) inset, 0 0 6px rgba(0, 0, 0, .2) inset;
-}
-
-.topbar-button:hover {
- background: rgba(0, 0, 0, .13);
-}
-
-.topbar-button:focus {
- outline: none;
-}
diff --git a/app/wirc.html b/app/wirc.html
deleted file mode 100644
index c383fb5..0000000
--- a/app/wirc.html
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/wirc.js b/app/wirc.js
deleted file mode 100644
index 919f72a..0000000
--- a/app/wirc.js
+++ /dev/null
@@ -1,106 +0,0 @@
-var msgRe = /([^ ]+) (<[^>]+>) (.*)/;
-var kibozeRe = /[Nn]eal/;
-var urlRe = /[a-z]+:\/\/[^ ]*/;
-
-var nick = "Mme. M";
-
-if (String.prototype.startsWith == null) {
- String.prototype.startsWith = function(needle) {
- return this.lastIndexOf(needle, 0) == 0;
- }
-}
-
-function getTemplate(className) {
- return templates.getElementsByClassName(className)[0].cloneNode(true);
-}
-
-function isinView(oObject) {
- return (oObject.offsetParent.clientHeight <= oObject.offsetTop);
-}
-
-function addMessagePart(p, className, text) {
- var e = document.createElement("span");
- e.className = className;
- e.appendChild(document.createTextNode(text));
- p.appendChild(e);
- p.appendChild(document.createTextNode(" "));
-}
-
-function focus(e) {
- var pct = 1;
- var timeout;
-
- selectForum(e.parentNode);
- e.scrollIntoView(false);
- e.style.backgroundColor = "yellow";
-
- timeout = setInterval(function() {
- pct = pct - 0.1;
- e.style.backgroundColor = "rgba(255, 255, 0, " + pct + ")";
- if (pct <= 0) {
- e.style.backgroundColor = "inherit";
- clearInterval(timeout);
- }
- }, 50)
-}
-
-function handleInput(oEvent) {
- console.log(oEvent);
- var txt = oEvent.target.value;
- if (txt.startsWith("/connect ")) {
- // XXX: should allow tokens with spaces
- var parts = txt.split(" ");
- var network = parts[1];
- var url = parts[2];
- var authtok = parts[3];
-
- networkConnect(network, url, authtok);
- storedConnections[network] = [url, authtok];
- chrome.storage.sync.set({"connections": storedConnections});
- } else {
- visibleRoom.send(txt);
- }
-
- oEvent.target.value = "";
-
- return false;
-}
-
-function hideChannels(oEvent) {
- var lhs = document.getElementById("rooms-and-nicks");
-
- if (lhs.classList.contains("hidden")) {
- lhs.classList.remove("hidden");
- } else {
- lhs.classList.add("hidden");
- }
-}
-
-function keyPress(oEvent) {
- document.getElementById("input").focus();
- if (oEvent.keyIdentifier == "Enter") {
- handleInput(oEvent);
- }
-}
-
-function restore(items) {
- storedConnections = items["connections"];
-
- for (var network in storedConnections) {
- var conn = storedConnections[network];
-
- networkConnect(network, conn[0], conn[1]);
- }
-}
-
-function init() {
- chrome.storage.sync.get(["connections"], restore);
- //document.getElementById("input").addEventListener("change", handleInput);
- document.getElementById("hide-channels").addEventListener("click", hideChannels);
- window.addEventListener("keypress", keyPress);
-
- templates = document.getElementById("templates");
- rooms = document.getElementById("rooms-container").getElementsByClassName("rooms")[0];
-}
-
-window.addEventListener("load", init);
diff --git a/doc/LICENSE.md b/doc/LICENSE.md
deleted file mode 100644
index 853d0ff..0000000
--- a/doc/LICENSE.md
+++ /dev/null
@@ -1,22 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 Neale Pickett
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
diff --git a/res/chat.svg b/res/chat.svg
deleted file mode 100644
index 05732e8..0000000
--- a/res/chat.svg
+++ /dev/null
@@ -1,151 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- image/svg+xml
-
-
-
-
- Openclipart
-
-
-
- 2008-02-19T10:10:56
-
- https://openclipart.org/detail/14475/callout-chat-by-ericlemerdy
-
-
- ericlemerdy
-
-
-
-
- balloon
- bubble
- callout
- speech
-
-
-
-
-
-
-
-
-
-
-
diff --git a/spongy.cgi/spongy.cgi b/spongy.cgi/spongy.cgi
new file mode 100755
index 0000000..c198064
Binary files /dev/null and b/spongy.cgi/spongy.cgi differ
diff --git a/spongy/irc.go b/spongy/irc.go
new file mode 100644
index 0000000..0762dbe
--- /dev/null
+++ b/spongy/irc.go
@@ -0,0 +1,98 @@
+package main
+
+import (
+ "strconv"
+ "strings"
+)
+
+type Message struct {
+ Command string
+ FullSender string
+ Sender string
+ Forum string
+ Args []string
+ Text string
+}
+
+func Parse(v string) (Message, error) {
+ var m Message
+ var parts []string
+ var lhs string
+
+ parts = strings.SplitN(v, " :", 2)
+ if len(parts) == 2 {
+ lhs = parts[0]
+ m.Text = parts[1]
+ } else {
+ lhs = v
+ m.Text = ""
+ }
+
+ m.FullSender = "."
+ m.Forum = "."
+ m.Sender = "."
+
+ parts = strings.Split(lhs, " ")
+ if parts[0][0] == ':' {
+ m.FullSender = parts[0][1:]
+ parts = parts[1:]
+
+ n, u, _ := nuhost(m.FullSender)
+ if u != "" {
+ m.Sender = n
+ }
+ }
+
+ m.Command = strings.ToUpper(parts[0])
+ switch m.Command {
+ case "PRIVMSG", "NOTICE":
+ switch {
+ case isChannel(parts[1]):
+ m.Forum = parts[1]
+ case m.FullSender == ".":
+ m.Forum = parts[1]
+ default:
+ m.Forum = m.Sender
+ }
+ case "PART", "MODE", "TOPIC", "KICK":
+ m.Forum = parts[1]
+ m.Args = parts[2:]
+ case "JOIN":
+ if len(parts) == 1 {
+ m.Forum = m.Text
+ m.Text = ""
+ } else {
+ m.Forum = parts[1]
+ }
+ case "INVITE":
+ if m.Text != "" {
+ m.Forum = m.Text
+ m.Text = ""
+ } else {
+ m.Forum = parts[2]
+ }
+ case "NICK":
+ if len(parts) > 1 {
+ m.Sender = parts[1]
+ m.Args = parts[2:]
+ } else {
+ m.Sender = m.Text
+ m.Text = ""
+ m.Args = parts[1:]
+ }
+ m.Forum = m.Sender
+ case "353":
+ m.Forum = parts[3]
+ default:
+ numeric, _ := strconv.Atoi(m.Command)
+ if numeric >= 300 {
+ if len(parts) > 2 {
+ m.Forum = parts[2]
+ }
+ }
+ m.Args = parts[1:]
+ }
+
+ return m, nil
+}
+
diff --git a/spongy/network.go b/spongy/network.go
new file mode 100644
index 0000000..2cde5dd
--- /dev/null
+++ b/spongy/network.go
@@ -0,0 +1,167 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "log"
+ "net"
+ "os"
+ "path"
+ "strings"
+ "time"
+)
+
+// This gets called a lot.
+// So it's easy to fix stuff while running.
+
+func ReadLines(fn string) ([]string, error) {
+ lines := make([]string, 0)
+
+ f, err := os.Open(fn)
+ if err != nil {
+ return lines, err
+ }
+ defer f.Close()
+
+ scanner := bufio.NewScanner(f)
+ for scanner.Scan() {
+ line := strings.TrimSpace(scanner.Text())
+ switch {
+ case line == "":
+ case line[0] == '#':
+ default:
+ lines = append(lines, line)
+ }
+ }
+
+ return lines, nil
+}
+
+type Network struct {
+ basePath string
+
+ conn io.ReadWriteCloser
+ logq chan Message
+ inq chan string
+ outq chan string
+}
+
+func NewNetwork(basePath string) (*Network, error) {
+ nicks, err := ReadLines(path.Join(basePath, "nicks"))
+ if err != nil {
+ return nil, err
+ }
+
+ gecoses, err := ReadLines(path.Join(basePath, "gecos"))
+ if err != nil {
+ return nil, err
+ }
+
+ return &Network{
+ basePath: basePath,
+
+ servers: servers,
+ nicks: nicks,
+ gecos: gecoses[0],
+
+ logq: make(chan Message),
+ inq: make(chan string),
+ outq: make(chan string),
+ }, err
+}
+
+func (n *Network) Close() {
+ close(n.logq)
+ close(n.inq)
+ close(n.outq)
+}
+
+func (n *Network) WatchOutqDirectory() {
+ outqDirname := path.Join(n.basePath, "outq")
+
+ dir, err := os.Open(outqDirname)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer dir.Close()
+
+ // XXX: Do this with fsnotify
+ for running {
+ entities, _ := dir.Readdirnames(0)
+ for _, fn := range entities {
+ pathname := path.Join(outqDirname, fn)
+ n.HandleInfile(pathname)
+ }
+ _, _ = dir.Seek(0, 0)
+ time.Sleep(500 * time.Millisecond)
+ }
+}
+
+func (n *Network) HandleInfile(fn string) {
+ f, err := os.Open(fn)
+ if err != nil {
+ return
+ }
+ defer f.Close()
+
+ // Do this after Open attempt.
+ // If Open fails, the file will stick around.
+ // Hopefully this is helpful for debugging.
+ os.Remove(fn)
+
+ inf := bufio.NewScanner(f)
+ for inf.Scan() {
+ txt := inf.Text()
+ n.outq <- txt
+ }
+}
+
+func (n *Network) WriteLoop() {
+ for v := range n.outq {
+ m, _ := Parse(v)
+ n.logq <- m
+ fmt.Fprintln(n.conn, v)
+ }
+}
+
+func (n *Network) ReadLoop() {
+ scanner := bufio.NewScanner(conn)
+ for scanner.Scan() {
+ n.inq <- scanner.Text()
+ }
+ close(n.inq)
+}
+
+func
+
+func (n *Network) Connect(){
+ serverIndex := 0
+ for running {
+ servers, err := ReadLines(path.Join(basePath, "servers"))
+ if err != nil {
+ log.Print(err)
+ serverIndex := 0
+ time.sleep(2 * time.Second)
+ continue
+ }
+
+ if serverIndex > len(servers) {
+ serverIndex = 0
+ }
+ server := servers[serverIndex]
+
+ switch (server[0]) {
+ case '|':
+
+
+ if dotls {
+ config := &tls.Config{
+ InsecureSkipVerify: true,
+ }
+ return tls.Dial("tcp", host, config)
+ } else {
+ return net.Dial("tcp", host)
+ }
+}
+
diff --git a/spongy/spongy.go b/spongy/spongy.go
index 72b28d0..3725774 100644
--- a/spongy/spongy.go
+++ b/spongy/spongy.go
@@ -5,24 +5,14 @@ import (
"crypto/tls"
"flag"
"fmt"
+ "github.com/nealey/spongy/logfile"
"log"
- "logfile"
"net"
"os"
- "strconv"
"strings"
"time"
)
-type Message struct {
- Command string
- FullSender string
- Sender string
- Forum string
- Args []string
- Text string
-}
-
var running bool = true
var nick string
var gecos string
@@ -30,7 +20,7 @@ var maxlogsize uint
var logq chan Message
func isChannel(s string) bool {
- if (s == "") {
+ if s == "" {
return false
}
@@ -50,7 +40,7 @@ func (m Message) String() string {
func logLoop() {
logf := logfile.NewLogfile(int(maxlogsize))
defer logf.Close()
-
+
for m := range logq {
logf.Log(m.String())
}
@@ -71,114 +61,6 @@ func nuhost(s string) (string, string, string) {
return n, parts[0], parts[1]
}
-func connect(host string, dotls bool) (net.Conn, error) {
- if dotls {
- config := &tls.Config{
- InsecureSkipVerify: true,
- }
- return tls.Dial("tcp", host, config)
- } else {
- return net.Dial("tcp", host)
- }
-}
-
-func readLoop(conn net.Conn, inq chan<- string) {
- scanner := bufio.NewScanner(conn)
- for scanner.Scan() {
- inq <- scanner.Text()
- }
- close(inq)
-}
-
-func writeLoop(conn net.Conn, outq <-chan string) {
- for v := range outq {
- m, _ := parse(v)
- logq <- m
- fmt.Fprintln(conn, v)
- }
-}
-
-func parse(v string) (Message, error) {
- var m Message
- var parts []string
- var lhs string
-
- parts = strings.SplitN(v, " :", 2)
- if len(parts) == 2 {
- lhs = parts[0]
- m.Text = parts[1]
- } else {
- lhs = v
- m.Text = ""
- }
-
- m.FullSender = "."
- m.Forum = "."
- m.Sender = "."
-
- parts = strings.Split(lhs, " ")
- if parts[0][0] == ':' {
- m.FullSender = parts[0][1:]
- parts = parts[1:]
-
- n, u, _ := nuhost(m.FullSender)
- if u != "" {
- m.Sender = n
- }
- }
-
- m.Command = strings.ToUpper(parts[0])
- switch m.Command {
- case "PRIVMSG", "NOTICE":
- switch {
- case isChannel(parts[1]):
- m.Forum = parts[1]
- case m.FullSender == ".":
- m.Forum = parts[1]
- default:
- m.Forum = m.Sender
- }
- case "PART", "MODE", "TOPIC", "KICK":
- m.Forum = parts[1]
- m.Args = parts[2:]
- case "JOIN":
- if len(parts) == 1 {
- m.Forum = m.Text
- m.Text = ""
- } else {
- m.Forum = parts[1]
- }
- case "INVITE":
- if m.Text != "" {
- m.Forum = m.Text
- m.Text = ""
- } else {
- m.Forum = parts[2]
- }
- case "NICK":
- if len(parts) > 1 {
- m.Sender = parts[1]
- m.Args = parts[2:]
- } else {
- m.Sender = m.Text
- m.Text = ""
- m.Args = parts[1:]
- }
- m.Forum = m.Sender
- case "353":
- m.Forum = parts[3]
- default:
- numeric, _ := strconv.Atoi(m.Command)
- if numeric >= 300 {
- if len(parts) > 2 {
- m.Forum = parts[2]
- }
- }
- m.Args = parts[1:]
- }
-
- return m, nil
-}
func dispatch(outq chan<- string, m Message) {
logq <- m
@@ -248,7 +130,7 @@ func main() {
log.Fatal(err)
}
defer dir.Close()
-
+
nick := flag.Arg(0)
host := flag.Arg(1)
@@ -268,7 +150,7 @@ func main() {
outq <- fmt.Sprintf("NICK %s", nick)
outq <- fmt.Sprintf("USER %s %s %s: %s", nick, nick, nick, gecos)
for v := range inq {
- p, err := parse(v)
+ p, err := Parse(v)
if err != nil {
continue
}