Skip to content

Commit

Permalink
mostly finished backend code (com.retwis.model)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphaelcm committed Aug 7, 2011
1 parent 95a2ff8 commit dea62bd
Show file tree
Hide file tree
Showing 6 changed files with 274 additions and 49 deletions.
6 changes: 4 additions & 2 deletions .gitignore
Expand Up @@ -27,9 +27,11 @@

# OS generated files #
######################
.DS_Store?
.DS_Store
.keep
.history
ehthumbs.db
Icon?
Icon
Thumbs.db

# sbt specific #
Expand Down
3 changes: 2 additions & 1 deletion DATA-LAYOUT
Expand Up @@ -17,7 +17,8 @@ uid:1000:posts (list of posts ids)
UPDATES

incr global:nextPostId => 134
post:134 id|time|message...
pid:134:time => time (in mills)
pid:134:message => message

TIMELINE

Expand Down
3 changes: 2 additions & 1 deletion build.sbt
Expand Up @@ -27,5 +27,6 @@ libraryDependencies ++= Seq(
//"javax.servlet" % "servlet-api" % "2.5" % "provided->default",
//"com.h2database" % "h2" % "1.2.138",
"ch.qos.logback" % "logback-classic" % "0.9.26" % "compile->default",
"redis.clients" % "jedis" % "2.0.0" // % "compile"
"redis.clients" % "jedis" % "2.0.0",
"net.debasishg" % "redisclient_2.9.0" % "2.3.1"
)
64 changes: 19 additions & 45 deletions src/main/scala/com/retwis/model/Retwis.scala
@@ -1,60 +1,33 @@
package com.retwis.model

import _root_.redis.clients.jedis._
import scala.collection.JavaConversions._
import compat.Platform

// Provide some static methods and access to JedisPool
object Retwis {
val pool = new JedisPool(new JedisPoolConfig(), "localhost");

//return a random MD5 hash value
def getRand(): String = {
return "Stub!"
}

//return TRUE if logged in
def isLoggedIn(auth: String): Boolean = {
val jedis = pool.getResource()
try {
var userid = jedis.get("auth:" + auth)
if(userid != null) {
if(jedis.get("uid:" + userid + ":auth") == auth) {
pool.returnResource(jedis)
return true
}
} else {
pool.returnResource(jedis)
return false
}
//create a string showing the time elapsed
def strElapsed(time: Long): String = {
val elapsedSeconds = (Platform.currentTime - time) / 1000
if(elapsedSeconds < 60) return elapsedSeconds + " seconds"
if(elapsedSeconds < 3600) {
val m = elapsedSeconds / 60
return m + " minute"
}
}

def loadUserInfo(userid: String): User = {
val jedis = pool.getResource()
var username = jedis.get("uid:" + userid + ":username")
var password = jedis.get("uid:" + userid + ":password")
if (username == null || password == null) {
pool.returnResource(jedis)
return null
if(elapsedSeconds < 3600*24) {
val h = elapsedSeconds / 3600
return h + " hour"
}
return new User(userid, username, password)
val d = elapsedSeconds / (3600*24)
return d + " day"
}

/*
function strElapsed($t) {
$d = time()-$t;
if ($d < 60) return "$d seconds";
if ($d < 3600) {
$m = (int)($d/60);
return "$m minute".($m > 1 ? "s" : "");
}
if ($d < 3600*24) {
$h = (int)($d/3600);
return "$h hour".($h > 1 ? "s" : "");
}
$d = (int)($d/(3600*24));
return "$d day".($d > 1 ? "s" : "");
}


/*
// Some of this will go in view snippets
function showPost($id) {
$r = redisLink();
$postdata = $r->get("post:$id");
Expand All @@ -73,6 +46,7 @@ function showPost($id) {
return true;
}
/*
addPostsToTimeline
Expand Down
21 changes: 21 additions & 0 deletions src/main/scala/com/retwis/model/Tweet.scala
@@ -1,5 +1,26 @@
package com.retwis.model

object Tweet {
//get Tweet object based on tweet id
def getTweet(id: String): Tweet = {
val jedis = Retwis.pool.getResource()

try {
var time = jedis.get("pid:" + id + ":time")
var message = jedis.get("pid:" + id + ":message")
if (time != null && message != null) {
return new Tweet(id, time.toLong, message)
}
} catch {
case e => e.printStackTrace()
} finally {
Retwis.pool.returnResource(jedis)
}

return null
}
}

class Tweet(id: String, time: Long, message: String) {
/* Getters */
def getId(): String = return id
Expand Down
226 changes: 226 additions & 0 deletions src/main/scala/com/retwis/model/User.scala
@@ -1,8 +1,234 @@
package com.retwis.model

import net.liftweb.http._
import net.liftweb.http.provider._
import _root_.redis.clients.jedis._
import scala.collection.JavaConversions._
import compat.Platform
import java.security.MessageDigest
import java.security.SecureRandom
import java.math.BigInteger

//Static User methods
object User {
private val random = new SecureRandom();

//return a random MD5 hash value (for session keys)
private def getRand(): String = {
val s = new BigInteger(130, random).toString(32)
return new String(MessageDigest.getInstance("MD5").digest(s.getBytes))
}

def createUser(username: String, password: String): Boolean = {
val jedis = Retwis.pool.getResource

if(username != null && password != null) {
try {
if(jedis.get("username:" + username + ":uid") != null) return false
val nextUserId = jedis.incr("glabal:nextUserId")
jedis.set("username:" + username + ":uid", nextUserId.toString)
jedis.set("uid:" + nextUserId.toString + ":username", username)
jedis.set("uid:" + nextUserId.toString + ":password", password)
return true
} catch {
case e => e.printStackTrace
} finally {
Retwis.pool.returnResource(jedis)
}
}
return false
}

//return TRUE and set AUTH hash if login info is value, otherwise return FALSE
def login(username: String, password: String): Boolean = {
val jedis = Retwis.pool.getResource()
try {
val userid = jedis.get("username:" + username + ":uid")
if(userid != null && password == jedis.get("uid:" + userid + ":password")) {
val authToken = getRand()
jedis.set("uid:" + userid + ":auth", authToken)
jedis.set("auth:" + authToken, userid)
val cookie = HTTPCookie("auth", authToken)
S.addCookie(cookie)
return true
}
} catch {
case e => e.printStackTrace()
} finally {
Retwis.pool.returnResource(jedis)
}
return false
}

//return TRUE if logged in
def isLoggedIn(): Boolean = {
val jedis = Retwis.pool.getResource()
val authCookie = S.findCookie("auth")
var retVal = false

if(!authCookie.isEmpty) {
try {
val auth = authCookie.openTheBox.value.openTheBox //this seems awfully complicated
val userid = jedis.get("auth:" + auth)
if(userid != null && jedis.get("uid:" + userid + ":auth") == auth) {
retVal = true
}
} catch {
case e => e.printStackTrace()
} finally {
Retwis.pool.returnResource(jedis)
}
}
return retVal
}

//return a User object corresponding to userid
def getUserById(userid: String): User = {
val jedis = Retwis.pool.getResource()
try {
var username = jedis.get("uid:" + userid + ":username")
var password = jedis.get("uid:" + userid + ":password")
if (username != null && password != null) {
return new User(userid, username, password)
}
} catch {
case e => e.printStackTrace()
} finally {
Retwis.pool.returnResource(jedis)
}
return null
}

//return a User object corresponding to username
def getUserByName(username: String): User = {
val jedis = Retwis.pool.getResource()
try {
val userid = jedis.get("username:" + username + ":uid")
val password = jedis.get("uid:" + userid + ":password")
if (userid != null && password != null) {
return new User(userid, username, password)
}
} catch {
case e => e.printStackTrace()
} finally {
Retwis.pool.returnResource(jedis)
}
return null
}
}

class User(id: String, username: String, password: String) {
/* Getters */
def getId(): String = return id
def getUsername(): String = return username
def getPassword(): String = return password

//get all tweets belonging to user
def getAllTweets(): List[Tweet] = {
val jedis = Retwis.pool.getResource

try {
val numPosts = jedis.llen("uid:" + id + "posts")
return this.getNRecentTweets(numPosts.toInt)
} catch {
case e => e.printStackTrace
return null
} finally {
Retwis.pool.returnResource(jedis)
}
}

//get N most recent tweets
def getNRecentTweets(n: Int): List[Tweet] = {
val jedis = Retwis.pool.getResource

try {
val postIdIter = jedis.lrange("uid:" + id + "posts", 0, n).iterator
var tweets: List[Tweet] = null
while(postIdIter.hasNext) {
val postId = postIdIter.next
val postTime = jedis.get("pid:" + postId + "time")
val postMessage = jedis.get("pid:" + postId + "message")
tweets = tweets :+ new Tweet(postId, postTime.toLong, postMessage)
}
return tweets
} catch {
case e => e.printStackTrace
return null
} finally {
Retwis.pool.returnResource(jedis)
}
}

//post new tweet
def newTweet(message: String) = {
val jedis = Retwis.pool.getResource

try {
val nextPostId = jedis.incr("global:nextPostId")
val setTimeResponse = jedis.set("pid:" + nextPostId.toString + ":time", Platform.currentTime.toString)
val setMessageResponse = jedis.set("pid:" + nextPostId + ":message", message)
val setUserPostsResponse = jedis.rpush("uid:" + id + ":posts", nextPostId.toString)
if(setTimeResponse != "OK" || setMessageResponse != "OK" || setUserPostsResponse < 1)
throw new Exception("Response *not* OK. setTimeResponse=" + setTimeResponse + " setMessageResponse=" + setMessageResponse + " setUserPostsResponse=" + setUserPostsResponse)
} catch {
case e => e.printStackTrace
} finally {
Retwis.pool.returnResource(jedis)
}
}

//begin following user
def follow(followeeId: String) = {
val jedis = Retwis.pool.getResource

try {
jedis.sadd("uid:" + id + ":following", followeeId)
} catch {
case e => e.printStackTrace
} finally {
Retwis.pool.returnResource(jedis)
}
}

//stop following user
def unFollow(followeeId: String) = {
val jedis = Retwis.pool.getResource

try {
jedis.srem("uid:" + id + ":following", followeeId)
} catch {
case e => e.printStackTrace
} finally {
Retwis.pool.returnResource(jedis)
}
}

//return a list of all followers
def getFollowers(): List[User] = {
return this.getRelatedUsers("followers")
}

//return a list of all followees
def getFollowing(): List[User] = {
return this.getRelatedUsers("following")
}

def getRelatedUsers(relation: String): List[User] = {
val jedis = Retwis.pool.getResource

try {
val relatedIdIterator = jedis.smembers("uid:" + id + ":" + relation).iterator
var related: List[User] = null
while(relatedIdIterator.hasNext) {
related = related :+ new User(relatedIdIterator.next, jedis.get("uid:" + id + ":username"), "") //don't include password
}
return related
} catch {
case e => e.printStackTrace
return null
} finally {
Retwis.pool.returnResource(jedis)
}
}
}

0 comments on commit dea62bd

Please sign in to comment.