summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsostler <sbostler@gmail.com>2009-12-18 21:56:51 -0500
committersostler <sbostler@gmail.com>2009-12-18 21:56:51 -0500
commit704efb06cd424de7411f198bc4c6ce6b99a9dcbe (patch)
tree076c19e5c97264948f4d94f32b6869c5dd396f60
parent5a8312ca25868679df1acb3b3fc208482460ee0e (diff)
Checkin before leaving
-rwxr-xr-xdb/0-create.psql4
-rw-r--r--src/site.clj48
-rwxr-xr-xstatic/home.js2
-rw-r--r--static/index.html354
-rwxr-xr-xstatic/pichat.js10
-rwxr-xr-xtemplate/chat.st4
6 files changed, 217 insertions, 205 deletions
diff --git a/db/0-create.psql b/db/0-create.psql
index 35278c7..5bd8622 100755
--- a/db/0-create.psql
+++ b/db/0-create.psql
@@ -4,6 +4,7 @@ CREATE TABLE users (
hash text NOT NULL,
email text NOT NULL,
created_on timestamp NOT NULL DEFAULT now(),
+ avatar text,
contact text,
bio text
);
@@ -19,7 +20,8 @@ CREATE TABLE messages (
user_id integer NOT NULL REFERENCES users,
room_id integer NOT NULL REFERENCES rooms,
content text NOT NULL,
- created_on timestamp NOT NULL DEFAULT now()
+ created_on timestamp NOT NULL DEFAULT now(),
+ is_image bool
);
CREATE TABLE user_session (
diff --git a/src/site.clj b/src/site.clj
index cc7dfd3..7fdd5ed 100644
--- a/src/site.clj
+++ b/src/site.clj
@@ -1,5 +1,3 @@
-; site.clj
-
(ns pichat
(:import java.lang.System
java.text.SimpleDateFormat
@@ -25,7 +23,7 @@
(.setRefreshInterval template-group 3)
(defstruct user-struct :user-id :nick :last-seen)
-(defstruct message-struct :nick :avatar :content :created_on)
+(defstruct message-struct :nick :content :created_on)
(def users (ref {}))
(def messages (ref []))
@@ -101,7 +99,6 @@
(defn process-message-for-output [d]
(let [avatar (d :avatar)]
{"nick" (encode-html-entities (d :nick))
- "avatar" (if avatar (encode-html-entities avatar) nil)
"created_on" (.format formatter (d :created_on))
"content" (encode-html-entities (d :content))}))
@@ -118,17 +115,18 @@
"messages" (map process-message-for-json (new-messages since))}))
(defn fetch-messages-by-room [room-id]
- (let [query (str "SELECT m.content, m.created_on, u.nick, u.avatar "
+ (let [query (str "SELECT m.content, m.created_on, u.nick "
"FROM messages m, users u "
"WHERE room_id = ? AND m.user_id = u.user_id "
"ORDER BY created_on DESC "
"LIMIT 20")]
(do-select [query room-id])))
-(defn fetch-messages-by-nick [nick]
- (let [query (str "SELECT m.content, m.created_on, u.nick, u.avatar "
+(defn fetch-messages-by-nick [nick image-only]
+ (let [query (str "SELECT m.content, m.created_on, u.nick "
"FROM messages m, users u "
"WHERE m.user_id = u.user_id AND u.nick = ? "
+ (if image-only "AND m.is_image = true " "")
"ORDER BY created_on DESC "
"LIMIT 20")]
(do-select [query nick])))
@@ -151,7 +149,7 @@
(defn landing [session]
(let [nick (session :nick)]
(if nick
- (redirect-to (str "/u/" nick))
+ (redirect-to "/chat")
(serve-file "static" "index.html"))))
(defn login [session params]
@@ -198,7 +196,7 @@
(let [nick (session :nick)
is-home (and nick (= nick profile-nick))
has-avatar (non-empty-string? (user-info :avatar))
- dumps (fetch-messages-by-nick profile-nick)
+ dumps (fetch-messages-by-nick profile-nick true)
st (fetch-template "profile" session)]
(do
(.setAttribute st "is_home" is-home)
@@ -264,26 +262,36 @@
; TODO: session should store room-id of anon. users
(resp-error "NOT_IN_CHAT"))))
+;; http://snippets.dzone.com/posts/show/6995
+(def url-regex #"((http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?")
+(def pic-regex #"^.*\.(jpg|jpeg|png|gif|bmp)$")
+
+(defn is-image? [content]
+ (let [lower-content (.toLowerCase content)]
+ (if (and (re-matches url-regex lower-content)
+ (re-matches pic-regex lower-content))
+ true false)))
+
(defn msg-transaction [nick msg]
(dosync
- (if (contains? (ensure users) nick)
- (do (alter messages (swap cons) msg)
- true)
- false)))
+ (and (contains? (ensure users) nick)
+ (do (alter messages (swap cons) msg)
+ true))))
(defn msg-db [user-id room-id msg]
- (with-connection db
- (insert-values :messages
- [:user_id :room_id :content]
- [user-id room-id (msg :content)])))
+ (let [content (msg :content)
+ is-image (is-image? content)]
+ (with-connection db
+ (insert-values :messages
+ [:user_id :room_id :content :is_image]
+ [user-id room-id content is-image]))))
(defn msg [session params]
(let [user-id (session :user-id)
nick (session :nick)
- avatar (session :avatar)
- content (params :content)
+ content (.trim (params :content))
now (new Date)
- msg (struct message-struct nick avatar content now)]
+ msg (struct message-struct nick content now)]
(if (msg-transaction nick msg)
(do
(msg-db user-id 1 msg)
diff --git a/static/home.js b/static/home.js
index 5857368..8416703 100755
--- a/static/home.js
+++ b/static/home.js
@@ -15,7 +15,7 @@ function login() {
var hash = hex_sha1(nick + '$' + password + '$dumpfm');
var onSuccess = function(json) {
- location.href = "u/" + nick;
+ location.href = "/chat";
};
var onError = function(resp, textStatus, errorThrown) {
diff --git a/static/index.html b/static/index.html
index fb5224e..0ccb121 100644
--- a/static/index.html
+++ b/static/index.html
@@ -1,196 +1,193 @@
-<head>
+<html>
+ <head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="static/sha1.js"></script>
<script type="text/javascript" src="static/home.js"></script>
- <script type="text/javascript" src="static/background.js"></script>
+ <script type="text/javascript" src="static/background.js"></script>
<script>
$(document).ready(initHome);
</script>
<link rel="stylesheet" type="text/css" href="static/reset.css">
- <link rel="shortcut icon" href="static/favicon.ico">
-
- <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"></head>
-<style type="text/css">
-<!--
-.white a:link {
- text-decoration: none;
- text-shadow: -1px 1px 1px #ccc;
- color: #504F61;
-}
-.white a:visited {
- text-decoration: none;
- text-shadow: -1px 1px 1px #ccc;
- color: #504F61;
-}
-.white a:hover {
- text-decoration: none;
- text-shadow: -1px 1px 1px #ccc;
- background-color:#e3e3e3;
-
- color: #fff;
-}
-.white a:active {
- text-decoration: none;
- text-shadow: -1px 1px 1px #ccc;
- color: #504F61;
-}
-#header7{
- background-color:#666;
- background-image:url(/static/dblue2.png);
- background-attachment:fixed;
- margin: 0px auto -1px auto;
- top: 0px;
- width:100%;
- left: 0px;
- height: 60px;
-}
-#bar7{
- top:32px;
- position:absolute;
- font-family: Arial, Helvetica, sans-serif;
- font-weight: bold;
- width: 500px;
- font-size: 20px;
- left: 170px;
- margin-left: 10%;
- margin-right: 8%;
- letter-spacing: -1px;
- z-index: 999;
-}
-#main {
- background-position:center;
- width:500px;
- margin: 0px auto -1px auto;
- top:150px;
- height:380px;
- z-index:2;
- opacity:0.9;
- border-top-left-radius:10px;
- border-top-right-radius:10px;
- -webkit-border-top-left-radius:10px;
- -webkit-border-top-right-radius:10px;
- -moz-border-radius-topleft:10px;
- -moz-border-radius-topright:10px;
- border-bottom-left-radius:10px;
- border-bottom-right-radius:10px;
- -webkit-border-bottom-left-radius:10px;
- -webkit-border-bottom-right-radius:10px;
- -moz-border-radius-bottomleft:10px;
- -moz-border-radius-bottomright:10px;
- border:solid 4px #F5F5F5;
- position: relative;
- background-color: #FFF;
- background-position:center;
- background-repeat:no-repeat;
-}
-#logout7{
- top:5px;
- position:relative;
- font-size:13px;
- margin-right: 10px;
- float:right;
- z-index: 999;
- font-family: "Times New Roman", Times, serif;
-}
-#logo7{
- top:20px;
- margin-left: 10%;
- margin-right: 10%;
- z-index:1000;
- float:left;
-}
-#rapper7{
- top: 0px;
- left:0px;
- position:absolute;
- width: 100%;
- height: 78px;
- z-index: 1000;
-}
-#bottombar{
- top: 69px;
- left:0px;
- position:absolute;
- width: 100%;
- height: 20px;
- z-index: 1000;
-}
-p {
- font-family: Arial, Helvetica, sans-serif;
- font-size: 24px;
-}
-td {
- font-family: Arial, Helvetica, sans-serif;
- letter-spacing:-1px;
- font-size: 12px;
- color: #000000;
-}
-.btnav { border: 0px #000000 solid;}
-body {
-
- background-color:#e3e3e3;
-
- background-image:url(static/brokenlink.gif);
- background-position:center;
-
- background-repeat:no-repeat;
- overflow:hidden;
-}
-.submit {
-
-
- text-shadow: -1px 1px 1px #ccc;
-
- font-size:15px;
-}
-.feild {
- height:40px;
- width:300px;
- border:3px #ccc;
- background:#e3e3e3;
- margin:10px;
- font-size:30px;
-}
-.txt {
- font-family:Arial, Helvetica, sans-serif;
- font-size:12px;
- text-shadow: -1px 1px 1px #ccc;
-}
- .line {
- font-family:Arial, Helvetica, sans-serif;
-
- letter-spacing: -1px;
- color:#000;
- font-size:18px;
-
-}
+ <link rel="shortcut icon" href="static/favicon.ico">
+ <style type="text/css">
+ <!--
+ .white a:link {
+ text-decoration: none;
+ text-shadow: -1px 1px 1px #ccc;
+ color: #504F61;
+ }
+ .white a:visited {
+ text-decoration: none;
+ text-shadow: -1px 1px 1px #ccc;
+ color: #504F61;
+ }
+ .white a:hover {
+ text-decoration: none;
+ text-shadow: -1px 1px 1px #ccc;
+ background-color:#e3e3e3;
+
+ color: #fff;
+ }
+ .white a:active {
+ text-decoration: none;
+ text-shadow: -1px 1px 1px #ccc;
+ color: #504F61;
+ }
+ #header7{
+ background-color:#666;
+ background-image:url(/static/dblue2.png);
+ background-attachment:fixed;
+ margin: 0px auto -1px auto;
+ top: 0px;
+ width:100%;
+ left: 0px;
+ height: 60px;
+ }
+ #bar7{
+ top:32px;
+ position:absolute;
+ font-family: Arial, Helvetica, sans-serif;
+ font-weight: bold;
+ width: 500px;
+ font-size: 20px;
+ left: 170px;
+ margin-left: 10%;
+ margin-right: 8%;
+ letter-spacing: -1px;
+ z-index: 999;
+ }
+ #main {
+ background-position:center;
+ width:500px;
+ margin: 0px auto -1px auto;
+ top:150px;
+ height:380px;
+ z-index:2;
+ opacity:0.9;
+ border-top-left-radius:10px;
+ border-top-right-radius:10px;
+ -webkit-border-top-left-radius:10px;
+ -webkit-border-top-right-radius:10px;
+ -moz-border-radius-topleft:10px;
+ -moz-border-radius-topright:10px;
+ border-bottom-left-radius:10px;
+ border-bottom-right-radius:10px;
+ -webkit-border-bottom-left-radius:10px;
+ -webkit-border-bottom-right-radius:10px;
+ -moz-border-radius-bottomleft:10px;
+ -moz-border-radius-bottomright:10px;
+ border:solid 4px #F5F5F5;
+ position: relative;
+ background-color: #FFF;
+ background-position:center;
+ background-repeat:no-repeat;
+ }
+ #logout7{
+ top:5px;
+ position:relative;
+ font-size:13px;
+ margin-right: 10px;
+ float:right;
+ z-index: 999;
+ font-family: "Times New Roman", Times, serif;
+ }
+ #logo7{
+ top:20px;
+ margin-left: 10%;
+ margin-right: 10%;
+ z-index:1000;
+ float:left;
+ }
+ #rapper7{
+ top: 0px;
+ left:0px;
+ position:absolute;
+ width: 100%;
+ height: 78px;
+ z-index: 1000;
+ }
+ #bottombar{
+ top: 69px;
+ left:0px;
+ position:absolute;
+ width: 100%;
+ height: 20px;
+ z-index: 1000;
+ }
+ p {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 24px;
+ }
+ td {
+ font-family: Arial, Helvetica, sans-serif;
+ letter-spacing:-1px;
+ font-size: 12px;
+ color: #000000;
+ }
+ .btnav { border: 0px #000000 solid;}
+ body {
+
+ background-color:#e3e3e3;
+
+ background-image:url(static/brokenlink.gif);
+ background-position:center;
+
+ background-repeat:no-repeat;
+ overflow:hidden;
+ }
+ .submit {
+
+
+ text-shadow: -1px 1px 1px #ccc;
+
+ font-size:15px;
+ }
+ .feild {
+ height:40px;
+ width:300px;
+ border:3px #ccc;
+ background:#e3e3e3;
+ margin:10px;
+ font-size:30px;
+ }
+ .txt {
+ font-family:Arial, Helvetica, sans-serif;
+ font-size:12px;
+ text-shadow: -1px 1px 1px #ccc;
+ }
+ .line {
+ font-family:Arial, Helvetica, sans-serif;
+
+ letter-spacing: -1px;
+ color:#000;
+ font-size:18px;
+
+ }
--->
-</style>
-
-<body>
-<div id="rapper7">
-<div id="header7">
-
- <div id="bottombar"></div>
+ -->
+ </style>
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+ </head>
+ <body>
+ <div id="rapper7">
+ <div id="header7">
+ <div id="bottombar"></div>
<div align="center">
<p><img src="static/wordlogo2.gif" width="500" height="239"><br>
</p>
</div>
-
- <div class="white"></div>
- <div align="center"><br />
+ <div class="white"></div>
+ <div align="center"><br /></div>
+ </div>
</div>
</div>
-</div>
-</div>
<div id="main" align="center">
- <p align="center"><br />
+ <p align="center"><br />
</p>
<div id="registerbox">
<p align="right" class="line">&nbsp;</p>
@@ -210,18 +207,19 @@ body {
<p align="center">&nbsp;</p>
<p>&nbsp;</p>
<div align="right" class="txt">
- <div align="center"><span class="txt"><a href="http://dump.fm/register" class="txt">Register</a></span></div>
+ <div align="center"><span class="txt"><a href="/register" class="txt">Register</a></span></div>
</div>
<div align="center"></div>
</div>
</div>
- </div></div>
+</div></div>
</div>
- </h1>
- </div>
+</h1>
+</div>
</div>
<div style="position: fixed; bottom: 3px; right: 3px; font-size: xx-small; z-index: 10;"><button onclick="getBackground()" title="Rotate background image" style="font-size: xx-small;">+</button></div>
-</body> \ No newline at end of file
+</body>
+</html>
diff --git a/static/pichat.js b/static/pichat.js
index 826bcba..d489bba 100755
--- a/static/pichat.js
+++ b/static/pichat.js
@@ -15,7 +15,8 @@ function escapeHtml(txt) {
}
function buildUserDiv(user) {
- return '<div>' + escapeHtml(user) + '</div>';
+ var nick = escapeHtml(user);
+ return '<div><a href="/u/' + nick + '">' + nick + '</a></div>';
}
// http://stackoverflow.com/questions/37684/replace-url-with-html-links-javascript
@@ -29,6 +30,7 @@ var URLRegex = /((http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S
var PicRegex = /\.(jpg|jpeg|png|gif|bmp)$/i;
function buildMsgContent(content) {
+ content = $.trim(content);
var match = URLRegex.exec(content)
if (match && PicRegex.test(match[0])) {
return '<a href="' + match[0] + '" target="_blank">'
@@ -39,7 +41,8 @@ function buildMsgContent(content) {
}
function buildMessageDiv(msg) {
- return '<div class="msgDiv"><b>' + escapeHtml(msg.nick) + ': </b>'
+ var nick = escapeHtml(msg.nick);
+ return '<div class="msgDiv"><b><a href="/u/' + nick + ' ">' + nick + '</a>: </b>'
+ buildMsgContent(msg.content) + '</div>';
}
@@ -150,6 +153,7 @@ function initProfile() {
});
var onSubmit = function(original_element, edit, old) {
+ edit = $.trim(edit);
if (edit == old) { return old };
// MAJOR TODO: Prevent entering script tags
if (original_element == 'avatar' && edit.indexOf("<") != -1) {
@@ -161,7 +165,7 @@ function initProfile() {
url: "/update-profile",
data: { 'attr': original_element, 'val': edit }
});
- if (original_element == 'avatar') {
+ if (original_element == 'avatar') {
var s = '<img id="avatarPic" src="' + edit + '" width="150" />';
$('#avatarPic').replaceWith(s);
}
diff --git a/template/chat.st b/template/chat.st
index 3a8f79f..3a4cbfd 100755
--- a/template/chat.st
+++ b/template/chat.st
@@ -28,14 +28,14 @@
</div>
<div id="userList">
$users: { u |
- <div>$u$</div>
+ <div><a href="/u/$u$">$u$</a></div>
}$
</div>
<div id="messagePane">
<div id="messageList">
$messages: { m |
- <div class="msgDiv oldmsg"><b>$m.nick$: </b>
+ <div class="msgDiv oldmsg"><b><a href="/u/$m.nick$">$m.nick$</a>: </b>
<span class="content">$m.content$<span></div>
}$
<hr />