/backend/sosmessage-api/src/main/scala/SosMessage.scala

https://github.com/troger/sosmessagedecarte · Scala · 146 lines · 112 code · 20 blank · 14 comment · 5 complexity · 1a9e7c9fd8069ae545ae64596545e038 MD5 · raw file

  1. package fr.arnk.sosmessage
  2. import scala.util.Random
  3. import unfiltered.request._
  4. import unfiltered.response._
  5. import com.mongodb.casbah.MongoConnection
  6. import net.liftweb.json.JsonAST._
  7. import net.liftweb.json.JsonDSL._
  8. import net.liftweb.json.Printer._
  9. import net.liftweb.json.JsonParser._
  10. import com.mongodb.casbah.commons.MongoDBObject
  11. import org.bson.types.ObjectId
  12. import com.mongodb.casbah.Imports._
  13. import java.util.Date
  14. class SosMessage extends unfiltered.filter.Plan {
  15. val DataBaseName = "sosmessage"
  16. val MessagesCollectionName = "messages"
  17. val CategoriesCollectionName = "categories"
  18. val mongo = MongoConnection()
  19. val messagesCollection = mongo(DataBaseName)(MessagesCollectionName)
  20. val categoriesCollection = mongo(DataBaseName)(CategoriesCollectionName)
  21. val random = new Random()
  22. def intent = {
  23. case GET(Path("/api/v1/categories")) =>
  24. val categoryOrder = MongoDBObject("name" -> 1)
  25. val categories = categoriesCollection.find().sort(categoryOrder).foldLeft(List[JValue]())((l, a) =>
  26. categoryToJSON(a) :: l
  27. ).reverse
  28. val json = ("count", categories.size) ~ ("items", categories)
  29. JsonContent ~> ResponseString(pretty(render(json)))
  30. case GET(Path(Seg("api" :: "v1" :: "category" :: id :: "messages" :: Nil))) =>
  31. val messageOrder = MongoDBObject("createdAt" -> -1)
  32. val q = MongoDBObject("categoryId" -> new ObjectId(id), "state" -> "approved")
  33. val keys = MongoDBObject("category" -> 1, "categoryId" -> 1, "text" -> 1, "createdAt" -> 1)
  34. val messages = messagesCollection.find(q, keys).sort(messageOrder).foldLeft(List[JValue]())((l, a) =>
  35. messageToJSON(a) :: l
  36. ).reverse
  37. val json = ("count", messages.size) ~ ("items", messages)
  38. JsonContent ~> ResponseString(pretty(render(json)))
  39. case GET(Path(Seg("api" :: "v1" :: "category" :: id :: "message" :: Nil))) =>
  40. val q = MongoDBObject("categoryId" -> new ObjectId(id), "state" -> "approved")
  41. val count = messagesCollection.find(q, MongoDBObject("_id")).count
  42. val skip = random.nextInt(if (count <= 0) 1 else count)
  43. val keys = MongoDBObject("category" -> 1, "categoryId" -> 1, "text" -> 1, "createdAt" -> 1)
  44. val messages = messagesCollection.find(q, keys).limit(-1).skip(skip)
  45. if (!messages.isEmpty) {
  46. val message = messages.next()
  47. val r = """
  48. function(doc, out) {
  49. for (var prop in doc.ratings) {
  50. out.count++;
  51. out.total += doc.ratings[prop];
  52. }
  53. }
  54. """
  55. val f = """
  56. function(out) {
  57. out.avg = out.total / out.count;
  58. }
  59. """
  60. val rating = messagesCollection.group(MongoDBObject("ratings" -> 1),
  61. MongoDBObject("_id" -> message.get("_id")), MongoDBObject("count" -> 0, "total" -> 0), r, f)
  62. val json = messageToJSON(message, Some(parse(rating.mkString)))
  63. JsonContent ~> ResponseString(pretty(render(json)))
  64. } else {
  65. NoContent
  66. }
  67. case req @ POST(Path(Seg("api" :: "v1" :: "category" :: categoryId :: "message" :: Nil))) =>
  68. categoriesCollection.findOne(MongoDBObject("_id" -> new ObjectId(categoryId))).map { category =>
  69. val Params(form) = req
  70. val text = form("text")(0)
  71. val builder = MongoDBObject.newBuilder
  72. builder += "categoryId" -> category.get("_id")
  73. builder += "category" -> category.get("name")
  74. builder += "text" -> text
  75. builder += "state" -> "waiting"
  76. builder += "createdAt" -> new Date()
  77. builder += "random" -> scala.math.random
  78. messagesCollection += builder.result
  79. }
  80. NoContent
  81. case req @ POST(Path(Seg("api" :: "v1" :: "message" :: messageId :: "rate" :: Nil))) =>
  82. val Params(form) = req
  83. val uid = form("uid")(0)
  84. val rating = if(form("rating")(0).toInt > 5) 5 else form("rating")(0).toInt
  85. val key = "ratings." + uid.replaceAll ("\\.", "-")
  86. messagesCollection.update(MongoDBObject("_id" -> new ObjectId(messageId)), $set (key -> rating), false, false)
  87. NoContent
  88. // case GET(Path(Seg("api" :: "v1" :: "category" :: id :: "randomMessage" :: Nil))) =>
  89. // val random = scala.math.random
  90. // println(random)
  91. // val q: DBObject = ("random" $gte random) ++ ("categoryId" -> new ObjectId(id))
  92. // messagesCollection.findOne(q) match {
  93. // case None =>
  94. // val q: DBObject = ("random" $lte random) ++ ("categoryId" -> new ObjectId(id))
  95. // val message = messagesCollection.findOne(q).get
  96. // val json = messageToJSON(message)
  97. // JsonContent ~> ResponseString(pretty(render(json)))
  98. // case Some(message) =>
  99. // val json = messageToJSON(message)
  100. // JsonContent ~> ResponseString(pretty(render(json)))
  101. // }
  102. }
  103. private def messageToJSON(message: DBObject, rating: Option[JValue] = None) = {
  104. val json = ("id", message.get("_id").toString) ~
  105. ("type", "message") ~
  106. ("category", message.get("category").toString) ~
  107. ("categoryId", message.get("categoryId").toString) ~
  108. ("text", message.get("text").toString) ~
  109. ("createdAt", message.get("createdAt").toString)
  110. rating match {
  111. case None => json ~ ("rating" -> 0) ~ ("ratingCount" -> 0)
  112. case Some(r) =>
  113. json ~ ("rating" -> rating \ "avg") ~ ("ratingCount" -> rating \ "count")
  114. }
  115. }
  116. private def categoryToJSON(o: DBObject) = {
  117. ("id", o.get("_id").toString) ~
  118. ("type", "category") ~
  119. ("name", o.get("name").toString)
  120. }
  121. }
  122. object AppServer {
  123. def main(args: Array[String]) {
  124. unfiltered.jetty.Http(3000).filter(new SosMessage).run
  125. }
  126. }