mirror of https://github.com/nealey/spongy
Moving to multi-server support
This commit is contained in:
parent
30eaf147f1
commit
c04d246d9e
|
@ -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.
|
||||||
|
|
24
Makefile
24
Makefile
|
@ -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 .
|
|
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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'
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1 +0,0 @@
|
||||||
merf.
|
|
361
app/example.html
361
app/example.html
|
@ -1,361 +0,0 @@
|
||||||
<html><head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
|
|
||||||
<!-- generic -->
|
|
||||||
<script src="util.js"></script>
|
|
||||||
<script src="keycodes.js"></script>
|
|
||||||
<script src="message_handler.js"></script>
|
|
||||||
<script src="event_emitter.js"></script>
|
|
||||||
<script src="chat/notification.js"></script>
|
|
||||||
<script src="chat/notification_group.js"></script>
|
|
||||||
<script src="net/abstract_tcp_socket.js"></script>
|
|
||||||
<script src="event.js"></script>
|
|
||||||
<script src="timer.js"></script>
|
|
||||||
<script src="context.js"></script>
|
|
||||||
|
|
||||||
<!-- net -->
|
|
||||||
<script src="net/chrome_socket.js"></script>
|
|
||||||
<script src="net/ssl_socket.js"></script>
|
|
||||||
<script src="net/remote_socket.js"></script>
|
|
||||||
|
|
||||||
<!-- irc protocol -->
|
|
||||||
<script src="irc/irc.js"></script>
|
|
||||||
<script src="irc/irc_util.js"></script>
|
|
||||||
<script src="irc/ctcp_handler.js"></script>
|
|
||||||
<script src="irc/server_response_handler.js"></script>
|
|
||||||
|
|
||||||
<!-- scripting -->
|
|
||||||
<script src="script/script.js"></script>
|
|
||||||
<script src="script/prepackaged/source_array.js"></script>
|
|
||||||
<script src="script/script_handler.js"></script>
|
|
||||||
<script src="script/script_loader.js"></script>
|
|
||||||
|
|
||||||
<!-- one identity -->
|
|
||||||
<script src="remote_connection.js"></script>
|
|
||||||
<script src="chat/remote_connection_handler.js"></script>
|
|
||||||
<script src="remote_device.js"></script>
|
|
||||||
|
|
||||||
<!-- user input -->
|
|
||||||
<script src="chat/custom_command_parser.js"></script>
|
|
||||||
<script src="input_stack.js"></script>
|
|
||||||
<script src="completion_finder.js"></script>
|
|
||||||
<script src="auto_complete.js"></script>
|
|
||||||
<script src="keyboard_shortcut_map.js"></script>
|
|
||||||
<script src="user_input_handler.js"></script>
|
|
||||||
<script src="chat/user_command_handler.js"></script>
|
|
||||||
<script src="chat/user_command.js"></script>
|
|
||||||
<script src="chat/developer_commands.js"></script>
|
|
||||||
|
|
||||||
<!-- client and UI -->
|
|
||||||
<script src="chat/chat.js"></script>
|
|
||||||
<script src="chat/walkthrough.js"></script>
|
|
||||||
<script src="chat/storage.js"></script>
|
|
||||||
<script src="chat/chat_log.js"></script>
|
|
||||||
<script src="chat/notice.js"></script>
|
|
||||||
<script src="chat/message_formatter.js"></script>
|
|
||||||
<script src="chat/html_list.js"></script>
|
|
||||||
<script src="chat/nick_mentioned_notification.js"></script>
|
|
||||||
<script src="chat/irc_message_handler.js"></script>
|
|
||||||
<script src="chat/window.js"></script>
|
|
||||||
<script src="chat/window_message_renderer.js"></script>
|
|
||||||
<script src="chat/scrollable.js"></script>
|
|
||||||
<script src="chat/help_message_renderer.js"></script>
|
|
||||||
<script src="chat/nick_list.js"></script>
|
|
||||||
<script src="chat/channel_list.js"></script>
|
|
||||||
<script src="chat/window_list.js"></script>
|
|
||||||
|
|
||||||
<!-- third party -->
|
|
||||||
<script src="third_party/jquery.js"></script>
|
|
||||||
<script src="third_party/md5.js"></script>
|
|
||||||
|
|
||||||
<!-- forge SSL library -->
|
|
||||||
<script type="text/javascript" src="third_party/forge/debug.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/util.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/log.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/socket.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/md5.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/sha1.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/sha256.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/hmac.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/aes.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/pem.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/asn1.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/jsbn.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/prng.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/random.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/oids.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/rsa.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/pbe.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/x509.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/pki.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/tls.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/aesCipherSuites.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/tlssocket.js"></script>
|
|
||||||
<script type="text/javascript" src="third_party/forge/http.js"></script>
|
|
||||||
|
|
||||||
<link id="main-style" rel="stylesheet" href="style.css">
|
|
||||||
<link rel="stylesheet" href="message_style.css">
|
|
||||||
<link rel="stylesheet" href="topbar.css">
|
|
||||||
<title>CIRC undefined</title></head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<!-- templates -->
|
|
||||||
<div id="templates">
|
|
||||||
|
|
||||||
<div class="server-channels">
|
|
||||||
<div class="server room">
|
|
||||||
<div class="content-item"></div>
|
|
||||||
<div class="remove-button">-</div>
|
|
||||||
</div>
|
|
||||||
<ul class="channels"></ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<li class="channel room">
|
|
||||||
<div class="content-item"></div>
|
|
||||||
<div class="remove-button">-</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<ul class="nicks"></ul>
|
|
||||||
|
|
||||||
<li class="nick">
|
|
||||||
<div class="content-item"></div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<ul class="messages"></ul>
|
|
||||||
|
|
||||||
<li class="message">
|
|
||||||
<div class="timestamp"></div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source"></div>
|
|
||||||
<div class="content"></div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- main -->
|
|
||||||
<div id="main">
|
|
||||||
<div id="main-top-border"></div>
|
|
||||||
<div id="rooms-and-nicks" class="">
|
|
||||||
<div id="rooms-container">
|
|
||||||
<h1>rooms</h1>
|
|
||||||
<div class="rooms"><div class="server-channels">
|
|
||||||
<div class="server room current-server">
|
|
||||||
<div class="content-item">us.slashnet.org</div>
|
|
||||||
<div class="remove-button">-</div>
|
|
||||||
</div>
|
|
||||||
<ul class="channels"><li class="channel room selected">
|
|
||||||
<div class="content-item">#tron</div>
|
|
||||||
<div class="remove-button">-</div>
|
|
||||||
</li><li class="channel room footer">
|
|
||||||
<div class="content-item">+ add channel</div>
|
|
||||||
<div class="remove-button">-</div>
|
|
||||||
</li></ul>
|
|
||||||
</div><div class="server-channels">
|
|
||||||
<div class="server room footer">
|
|
||||||
<div class="content-item">+ add server</div>
|
|
||||||
<div class="remove-button">-</div>
|
|
||||||
</div>
|
|
||||||
<ul class="channels"></ul>
|
|
||||||
</div></div>
|
|
||||||
</div>
|
|
||||||
<div id="nicks-container">
|
|
||||||
<h1>members</h1>
|
|
||||||
<ul class="nicks"><li class="nick">
|
|
||||||
<div class="content-item">also</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">atob</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">Bermuda</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">bit</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">bk</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">bz2</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">caycos</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">ckape</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">clavicle</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">CrackMonkey</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">Dumont</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">dzho</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">emad</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">eythian</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">felixc</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">fo0bar</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">fuzzie</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">GodEater</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">hollow</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">hoylemd</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">jhewl</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">jv</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">kees</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">khmer</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">lamont</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">lexicondal</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">neale</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">nemo</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">nerdtron3000</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">nornagon</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">Octal</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">pdx6</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">pedro</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">Randall</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">sarah</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">Sciri</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">scorche</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">scorche|sh</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">Screwtape</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">sneakums</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">squinky</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">stat</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">teferi</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">tiaz</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">watson</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">wcarss</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">wombat</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">X11R5</div>
|
|
||||||
</li><li class="nick">
|
|
||||||
<div class="content-item">Zen</div>
|
|
||||||
</li><li class="nick footer">
|
|
||||||
<div class="content-item">footer</div>
|
|
||||||
</li></ul></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="dragbar"></div>
|
|
||||||
|
|
||||||
<div id="messages-and-input">
|
|
||||||
<div id="topic-container">
|
|
||||||
<button id="hide-channels" class="topbar-button">=</button>
|
|
||||||
<div id="status" class="content-item"><span title="Spel werkt, vertel het door! | hype mismatch error | ERG DRUK | <ginnie> everything is awesome! | Save The Date: 20150212 is Dumont's 15th Birthday | sparrows form Voltron | Deksels! | sysadmin establishment "hanged" by lunatic devop | Levis dehydrates unisexual cleavage. | A fanfare for locked traffic --" class="topic">Spel werkt, vertel het door! | hype mismatch error | ERG DRUK | <ginnie> everything is awesome! | Save The Date: 20150212 is Dumont's 15th Birthday | sparrows form Voltron | Deksels! | sysadmin establishment "hanged" by lunatic devop | Levis dehydrates unisexual cleavage. | A fanfare for locked traffic --</span></div>
|
|
||||||
</div>
|
|
||||||
<div id="notice" class="hide">
|
|
||||||
<div class="content"></div>
|
|
||||||
<button class="close">X</button>
|
|
||||||
<button class="option2 hidden"></button>
|
|
||||||
<button class="option1 hidden"></button>
|
|
||||||
</div>
|
|
||||||
<div id="messages-container"><ul class="messages"><li class="message system">
|
|
||||||
<div class="timestamp">3:46:12 PM</div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source empty"></div>
|
|
||||||
<div class="content"><span>Awesome, you've connected to #tron.</span></div>
|
|
||||||
</div>
|
|
||||||
</li><li class="message system">
|
|
||||||
<div class="timestamp">3:46:12 PM</div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source empty"></div>
|
|
||||||
<div class="content"><span>If you're ever stuck, type /help to see a list of all commands.</span></div>
|
|
||||||
</div>
|
|
||||||
</li><li class="message system">
|
|
||||||
<div class="timestamp">3:46:12 PM</div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source empty"></div>
|
|
||||||
<div class="content"><span>You can switch windows with alt+[0-9] or click in the channel list on the left.</span></div>
|
|
||||||
</div>
|
|
||||||
</li><li class="message update join self">
|
|
||||||
<div class="timestamp">3:46:12 PM</div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source empty"></div>
|
|
||||||
<div class="content"><span>(You joined the channel)</span></div>
|
|
||||||
</div>
|
|
||||||
</li><li class="message notice topic">
|
|
||||||
<div class="timestamp">3:46:12 PM</div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source empty"></div>
|
|
||||||
<div class="content"><span>The topic is: Spel werkt, vertel het door! | hype mismatch error | ERG DRUK | <ginnie> everything is awesome! | Save The Date: 20150212 is Dumont's 15th Birthday | sparrows form Voltron | Deksels! | sysadmin establishment "hanged" by lunatic devop | Levis dehydrates unisexual cleavage. | A fanfare for locked traffic --</span></div>
|
|
||||||
</div>
|
|
||||||
</li><li class="message notice topic_info">
|
|
||||||
<div class="timestamp">3:46:12 PM</div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source empty"></div>
|
|
||||||
<div class="content"><span>Topic set by sneakums on Fri Oct 17 2014 16:05:00 GMT-0600 (MDT).</span></div>
|
|
||||||
</div>
|
|
||||||
</li><li class="message notice-group notice">
|
|
||||||
<div class="timestamp">3:46:12 PM</div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source empty"></div>
|
|
||||||
<div class="content"><span>Received a CTCP VERSION from squinky.</span></div>
|
|
||||||
</div>
|
|
||||||
</li><li class="message update privmsg self">
|
|
||||||
<div class="timestamp">3:47:13 PM</div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source" colornumber="22"><span>nerdtron3000</span></div>
|
|
||||||
<div class="content"><span>merf</span></div>
|
|
||||||
</div>
|
|
||||||
</li><li class="message update privmsg self">
|
|
||||||
<div class="timestamp">3:47:53 PM</div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source" colornumber="22"><span>nerdtron3000</span></div>
|
|
||||||
<div class="content"><span>X11R5: say something to me</span></div>
|
|
||||||
</div>
|
|
||||||
</li><li class="message update mention privmsg">
|
|
||||||
<div class="timestamp">3:47:55 PM</div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source" colornumber="22"><span>X11R5</span></div>
|
|
||||||
<div class="content"><span>nerdtron3000: Get me some of those things where 99 times out on to something.</span></div>
|
|
||||||
</div>
|
|
||||||
</li><li class="message update privmsg self">
|
|
||||||
<div class="timestamp">3:48:01 PM</div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source" colornumber="22"><span>nerdtron3000</span></div>
|
|
||||||
<div class="content"><span>...</span></div>
|
|
||||||
</div>
|
|
||||||
</li><li class="message update privmsg">
|
|
||||||
<div class="timestamp">3:48:02 PM</div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source" colornumber="12"><span>Dumont</span></div>
|
|
||||||
<div class="content"><span>[You have a sad feeling for a moment, then it passes.]</span></div>
|
|
||||||
</div>
|
|
||||||
</li></ul></div>
|
|
||||||
<div id="nick-and-input">
|
|
||||||
<div id="nick"><span class="name">nerdtron3000</span></div><input id="input" class="" style="-webkit-transition: 300ms; transition: 300ms;">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="main.js"></script>
|
|
||||||
|
|
||||||
<iframe src="script_frame.html" style="display: none;"></iframe></body></html>
|
|
|
@ -1,27 +0,0 @@
|
||||||
{
|
|
||||||
"manifest_version": 2,
|
|
||||||
"version": "1.0",
|
|
||||||
|
|
||||||
"name": "__MSG_appName__",
|
|
||||||
"short_name": "__MSG_appShortName__",
|
|
||||||
"description": "__MSG_appDesc__",
|
|
||||||
"author": "Neale Pickett <neale@woozle.org>",
|
|
||||||
"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"
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
102
app/network.js
102
app/network.js
|
@ -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);
|
|
||||||
}
|
|
162
app/room.js
162
app/room.js
|
@ -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;
|
|
||||||
}
|
|
484
app/style.css
484
app/style.css
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<link rel="stylesheet" href="message_style.css">
|
|
||||||
<link rel="stylesheet" href="topbar.css">
|
|
||||||
|
|
||||||
<script src="network.js"></script>
|
|
||||||
<script src="room.js"></script>
|
|
||||||
<script src="wirc.js"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<!-- templates -->
|
|
||||||
<div id="templates">
|
|
||||||
|
|
||||||
<div class="server-channels">
|
|
||||||
<div class="server room">
|
|
||||||
<div class="content-item"></div>
|
|
||||||
<div class="remove-button">-</div>
|
|
||||||
</div>
|
|
||||||
<ul class="channels"></ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<li class="channel room">
|
|
||||||
<div class="content-item"></div>
|
|
||||||
<div class="remove-button">-</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<ul class="nicks"></ul>
|
|
||||||
|
|
||||||
<li class="nick">
|
|
||||||
<div class="content-item"></div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<ul class="messages"></ul>
|
|
||||||
|
|
||||||
<li class="message">
|
|
||||||
<div class="timestamp"></div>
|
|
||||||
<div class="source-content-container">
|
|
||||||
<div class="source"></div>
|
|
||||||
<div class="content"></div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- main -->
|
|
||||||
<div id="main">
|
|
||||||
<div id="main-top-border"></div>
|
|
||||||
<div id="rooms-and-nicks" class="no-nicks">
|
|
||||||
<div id="rooms-container">
|
|
||||||
<h1>rooms</h1>
|
|
||||||
<div class="rooms"></div>
|
|
||||||
</div>
|
|
||||||
<div id="nicks-container">
|
|
||||||
<h1>members</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="dragbar"></div>
|
|
||||||
|
|
||||||
<div id="messages-and-input">
|
|
||||||
<div id="topic-container">
|
|
||||||
<button id="hide-channels" class="topbar-button">=</button>
|
|
||||||
<div id="status" class="content-item"></div>
|
|
||||||
</div>
|
|
||||||
<div id="notice" class="hide">
|
|
||||||
<div class="content"></div>
|
|
||||||
<button class="close">X</button>
|
|
||||||
<button class="option2 hidden"></button>
|
|
||||||
<button class="option1 hidden"></button>
|
|
||||||
</div>
|
|
||||||
<div id="messages-container"></div>
|
|
||||||
<div id="nick-and-input">
|
|
||||||
<div id="nick"></div><input id="input">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
106
app/wirc.js
106
app/wirc.js
|
@ -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);
|
|
|
@ -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.
|
|
||||||
|
|
151
res/chat.svg
151
res/chat.svg
|
@ -1,151 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
id="svg548"
|
|
||||||
inkscape:version="0.48.5 r10040"
|
|
||||||
inkscape:export-filename="/home/neale/tmp/chat.png"
|
|
||||||
viewBox="0 0 500 500"
|
|
||||||
sodipodi:version="0.32"
|
|
||||||
inkscape:export-xdpi="11.52"
|
|
||||||
version="1.0"
|
|
||||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
|
||||||
inkscape:export-ydpi="11.52"
|
|
||||||
sodipodi:docname="chat.svg"
|
|
||||||
width="100%"
|
|
||||||
height="100%">
|
|
||||||
<defs
|
|
||||||
id="defs550" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:zoom="0.89095454"
|
|
||||||
inkscape:current-layer="g3182"
|
|
||||||
inkscape:cx="-30.955534"
|
|
||||||
inkscape:cy="263.18068"
|
|
||||||
inkscape:window-width="1280"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-height="751"
|
|
||||||
inkscape:window-maximized="1" />
|
|
||||||
<g
|
|
||||||
id="g3182"
|
|
||||||
transform="translate(14.44,59.9282)">
|
|
||||||
<g
|
|
||||||
id="g2992"
|
|
||||||
transform="translate(21.564741,35.474988)">
|
|
||||||
<path
|
|
||||||
transform="matrix(1,0,0,1.1018519,-7.7056497,-111.52964)"
|
|
||||||
d="m 448.9567,198.07663 c 0,66.94702 -88.69335,121.21831 -198.10215,121.21831 -109.40879,0 -198.102139,-54.27129 -198.102139,-121.21831 0,-66.94702 88.693349,-121.218308 198.102139,-121.218308 109.4088,0 198.10215,54.271288 198.10215,121.218308 z"
|
|
||||||
sodipodi:ry="121.21831"
|
|
||||||
sodipodi:rx="198.10214"
|
|
||||||
sodipodi:cy="198.07663"
|
|
||||||
sodipodi:cx="250.85455"
|
|
||||||
id="path2984"
|
|
||||||
style="fill:#5f5fd3;fill-opacity:1;fill-rule:nonzero"
|
|
||||||
sodipodi:type="arc" />
|
|
||||||
<path
|
|
||||||
inkscape:transform-center-y="-12.189045"
|
|
||||||
inkscape:transform-center-x="7.8620881"
|
|
||||||
transform="matrix(0.9919143,-0.12690949,0.12690949,0.9919143,457.74643,65.434728)"
|
|
||||||
d="M -88.668932,214.91251 -260.45097,138.9978 -108.81589,28.187543 z"
|
|
||||||
inkscape:randomized="0"
|
|
||||||
inkscape:rounded="0"
|
|
||||||
inkscape:flatsided="true"
|
|
||||||
sodipodi:arg2="1.9869145"
|
|
||||||
sodipodi:arg1="0.93971694"
|
|
||||||
sodipodi:r2="54.215702"
|
|
||||||
sodipodi:r1="108.43141"
|
|
||||||
sodipodi:cy="127.36595"
|
|
||||||
sodipodi:cx="-152.64526"
|
|
||||||
sodipodi:sides="3"
|
|
||||||
id="path2986"
|
|
||||||
style="fill:#5f5fd3;fill-opacity:1;fill-rule:nonzero"
|
|
||||||
sodipodi:type="star" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
transform="matrix(-0.74359868,0,0,0.69642414,335.20139,175.05754)"
|
|
||||||
id="g3000"
|
|
||||||
style="fill:#ffcc00">
|
|
||||||
<path
|
|
||||||
sodipodi:type="arc"
|
|
||||||
style="fill:#ffcc00;fill-opacity:1;fill-rule:nonzero"
|
|
||||||
id="path3002"
|
|
||||||
sodipodi:cx="250.85455"
|
|
||||||
sodipodi:cy="198.07663"
|
|
||||||
sodipodi:rx="198.10214"
|
|
||||||
sodipodi:ry="121.21831"
|
|
||||||
d="m 448.9567,198.07663 c 0,66.94702 -88.69335,121.21831 -198.10215,121.21831 -109.40879,0 -198.102139,-54.27129 -198.102139,-121.21831 0,-66.94702 88.693349,-121.218308 198.102139,-121.218308 109.4088,0 198.10215,54.271288 198.10215,121.218308 z"
|
|
||||||
transform="matrix(1,0,0,1.1018519,-7.7056497,-111.52964)" />
|
|
||||||
<path
|
|
||||||
sodipodi:type="star"
|
|
||||||
style="fill:#ffcc00;fill-opacity:1;fill-rule:nonzero"
|
|
||||||
id="path3004"
|
|
||||||
sodipodi:sides="3"
|
|
||||||
sodipodi:cx="-152.64526"
|
|
||||||
sodipodi:cy="127.36595"
|
|
||||||
sodipodi:r1="108.43141"
|
|
||||||
sodipodi:r2="54.215702"
|
|
||||||
sodipodi:arg1="0.93971694"
|
|
||||||
sodipodi:arg2="1.9869145"
|
|
||||||
inkscape:flatsided="true"
|
|
||||||
inkscape:rounded="0"
|
|
||||||
inkscape:randomized="0"
|
|
||||||
d="M -88.668932,214.91251 -260.45097,138.9978 -108.81589,28.187543 z"
|
|
||||||
transform="matrix(0.9919143,-0.12690949,0.12690949,0.9919143,457.74643,65.434728)"
|
|
||||||
inkscape:transform-center-x="7.8620881"
|
|
||||||
inkscape:transform-center-y="-12.189045" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<metadata
|
|
||||||
id="metadata3045">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work>
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<cc:license
|
|
||||||
rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
|
|
||||||
<dc:publisher>
|
|
||||||
<cc:Agent
|
|
||||||
rdf:about="http://openclipart.org/">
|
|
||||||
<dc:title>Openclipart</dc:title>
|
|
||||||
</cc:Agent>
|
|
||||||
</dc:publisher>
|
|
||||||
<dc:title />
|
|
||||||
<dc:date>2008-02-19T10:10:56</dc:date>
|
|
||||||
<dc:description />
|
|
||||||
<dc:source>https://openclipart.org/detail/14475/callout-chat-by-ericlemerdy</dc:source>
|
|
||||||
<dc:creator>
|
|
||||||
<cc:Agent>
|
|
||||||
<dc:title>ericlemerdy</dc:title>
|
|
||||||
</cc:Agent>
|
|
||||||
</dc:creator>
|
|
||||||
<dc:subject>
|
|
||||||
<rdf:Bag>
|
|
||||||
<rdf:li>balloon</rdf:li>
|
|
||||||
<rdf:li>bubble</rdf:li>
|
|
||||||
<rdf:li>callout</rdf:li>
|
|
||||||
<rdf:li>speech</rdf:li>
|
|
||||||
</rdf:Bag>
|
|
||||||
</dc:subject>
|
|
||||||
</cc:Work>
|
|
||||||
<cc:License
|
|
||||||
rdf:about="http://creativecommons.org/licenses/publicdomain/">
|
|
||||||
<cc:permits
|
|
||||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
|
||||||
<cc:permits
|
|
||||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
|
||||||
<cc:permits
|
|
||||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
|
||||||
</cc:License>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 5.5 KiB |
Binary file not shown.
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
128
spongy/spongy.go
128
spongy/spongy.go
|
@ -5,24 +5,14 @@ import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/nealey/spongy/logfile"
|
||||||
"log"
|
"log"
|
||||||
"logfile"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Message struct {
|
|
||||||
Command string
|
|
||||||
FullSender string
|
|
||||||
Sender string
|
|
||||||
Forum string
|
|
||||||
Args []string
|
|
||||||
Text string
|
|
||||||
}
|
|
||||||
|
|
||||||
var running bool = true
|
var running bool = true
|
||||||
var nick string
|
var nick string
|
||||||
var gecos string
|
var gecos string
|
||||||
|
@ -30,7 +20,7 @@ var maxlogsize uint
|
||||||
var logq chan Message
|
var logq chan Message
|
||||||
|
|
||||||
func isChannel(s string) bool {
|
func isChannel(s string) bool {
|
||||||
if (s == "") {
|
if s == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +40,7 @@ func (m Message) String() string {
|
||||||
func logLoop() {
|
func logLoop() {
|
||||||
logf := logfile.NewLogfile(int(maxlogsize))
|
logf := logfile.NewLogfile(int(maxlogsize))
|
||||||
defer logf.Close()
|
defer logf.Close()
|
||||||
|
|
||||||
for m := range logq {
|
for m := range logq {
|
||||||
logf.Log(m.String())
|
logf.Log(m.String())
|
||||||
}
|
}
|
||||||
|
@ -71,114 +61,6 @@ func nuhost(s string) (string, string, string) {
|
||||||
return n, parts[0], parts[1]
|
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) {
|
func dispatch(outq chan<- string, m Message) {
|
||||||
logq <- m
|
logq <- m
|
||||||
|
@ -248,7 +130,7 @@ func main() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
defer dir.Close()
|
defer dir.Close()
|
||||||
|
|
||||||
nick := flag.Arg(0)
|
nick := flag.Arg(0)
|
||||||
host := flag.Arg(1)
|
host := flag.Arg(1)
|
||||||
|
|
||||||
|
@ -268,7 +150,7 @@ func main() {
|
||||||
outq <- fmt.Sprintf("NICK %s", nick)
|
outq <- fmt.Sprintf("NICK %s", nick)
|
||||||
outq <- fmt.Sprintf("USER %s %s %s: %s", nick, nick, nick, gecos)
|
outq <- fmt.Sprintf("USER %s %s %s: %s", nick, nick, nick, gecos)
|
||||||
for v := range inq {
|
for v := range inq {
|
||||||
p, err := parse(v)
|
p, err := Parse(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue