diff --git a/akka-bbb-apps/scala/Collections.sc b/akka-bbb-apps/scala/Collections.sc new file mode 100755 index 0000000000000000000000000000000000000000..9640c593bf0e190c01f6572dc9dc4edfb7b04084 --- /dev/null +++ b/akka-bbb-apps/scala/Collections.sc @@ -0,0 +1,9 @@ +import scala.collection.mutable + +object Collections { + val messages = new mutable.Queue[String]() + messages += "foo" + messages += "bar" + messages += "baz" + messages.foreach(f => println(f)) +} \ No newline at end of file diff --git a/akka-bbb-apps/scala/Test2.sc b/akka-bbb-apps/scala/Test2.sc index 784ccd76cfadf6fa45957f106f5e5bdbcf2bd07b..214b311d850eefe4ec2417dc64d854c91d5e7366 100755 --- a/akka-bbb-apps/scala/Test2.sc +++ b/akka-bbb-apps/scala/Test2.sc @@ -1,23 +1,23 @@ import scala.collection.immutable.StringOps import java.net.URLEncoder import scala.collection._ - + object Test2 { - println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet + println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet - val userId = new StringOps("abc_12") //> userId : scala.collection.immutable.StringOps = abc_12 - val s2 = userId.split('_') //> s2 : Array[String] = Array(abc, 12) - val s1 = if (s2.length == 2) s2(0) else userId //> s1 : Comparable[String] = abc + val userId = new StringOps("abc_12") //> userId : scala.collection.immutable.StringOps = abc_12 + val s2 = userId.split('_') //> s2 : Array[String] = Array(abc, 12) + val s1 = if (s2.length == 2) s2(0) else userId //> s1 : Comparable[String] = abc def sortParam(params: mutable.Map[String, String]):SortedSet[String] = { collection.immutable.SortedSet[String]() ++ params.keySet } //> sortParam: (params: scala.collection.mutable.Map[String,String])scala.collec - //| tion.SortedSet[String] + //| tion.SortedSet[String] def createBaseString(params: mutable.Map[String, String]): String = { val csbuf = new StringBuffer() var keys = sortParam(params) - + var first = true; for (key <- keys) { for (value <- params.get(key)) { @@ -26,42 +26,52 @@ object Test2 { } else { csbuf.append("&"); } - + csbuf.append(key); csbuf.append("="); csbuf.append(value); } } - + return csbuf.toString(); } //> createBaseString: (params: scala.collection.mutable.Map[String,String])Strin - //| g + //| g def urlEncode(s: String): String = { URLEncoder.encode(s, "UTF-8"); - } //> urlEncode: (s: String)String + } //> urlEncode: (s: String)String val baseString = "fullName=User+4621018&isBreakout=true&meetingID=random-1853792&password=mp&redirect=true" //> baseString : String = fullName=User+4621018&isBreakout=true&meetingID=rand - //| om-1853792&password=mp&redirect=true + //| om-1853792&password=mp&redirect=true val params = new collection.mutable.HashMap[String, String] - //> params : scala.collection.mutable.HashMap[String,String] = Map() + //> params : scala.collection.mutable.HashMap[String,String] = Map() params += "fullName" -> urlEncode("User 4621018") - //> res0: Test2.params.type = Map(fullName -> User+4621018) + //> res0: Test2.params.type = Map(fullName -> User+4621018) params += "isBreakout" -> urlEncode("true") //> res1: Test2.params.type = Map(fullName -> User+4621018, isBreakout -> true) - //| + //| params += "meetingID" -> urlEncode("random-1853792") //> res2: Test2.params.type = Map(fullName -> User+4621018, isBreakout -> true, - //| meetingID -> random-1853792) + //| meetingID -> random-1853792) params += "password" -> urlEncode("mp") //> res3: Test2.params.type = Map(fullName -> User+4621018, isBreakout -> true, - //| meetingID -> random-1853792, password -> mp) + //| meetingID -> random-1853792, password -> mp) params += "redirect" -> urlEncode("true") //> res4: Test2.params.type = Map(fullName -> User+4621018, isBreakout -> true, - //| meetingID -> random-1853792, redirect -> true, password -> mp) + //| meetingID -> random-1853792, redirect -> true, password -> mp) val keys = sortParam(params) //> keys : scala.collection.SortedSet[String] = TreeSet(fullName, isBreakout, - //| meetingID, password, redirect) + //| meetingID, password, redirect) val result = createBaseString(params) //> result : String = fullName=User+4621018&isBreakout=true&meetingID=random-1 - //| 853792&password=mp&redirect=true - + //| 853792&password=mp&redirect=true + + val between = Set("xab", "bc") + val u2 = Set("bc", "xab") + val u3 = u2 + "zxc" + val foo = between subsetOf(u2) + + val id = between.toSeq.sorted.mkString("-") + + + + } \ No newline at end of file diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/ChatAppHandlers.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/ChatAppHandlers.scala new file mode 100755 index 0000000000000000000000000000000000000000..0424174c091086ee2e82304819ec3138b07a9ea2 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/ChatAppHandlers.scala @@ -0,0 +1,29 @@ +package org.bigbluebutton.core.apps + +import org.bigbluebutton.core.OutMessageGateway +import org.bigbluebutton.core.api.SendDirectChatMsgCmd +import org.bigbluebutton.core.models.DirectChats +import org.bigbluebutton.core.running.LiveMeeting + +trait ChatAppHandlers { + val liveMeeting: LiveMeeting + val outGW: OutMessageGateway + + def handleSendDirectChatMsgCmd(msg: SendDirectChatMsgCmd): Unit = { + def send(): Unit = { + + } + + val between = Set("foo", "bar") + for { + chat <- DirectChats.find(between, liveMeeting.chatModel.directChats) + + } yield { + send() + } + } + + def handleCreatePublicChatCmd(): Unit = { + + } +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/ChatModel.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/ChatModel.scala index 515dd2adabfd34c9409c3d90c324353f0d6b9266..593c795a1fcb804f174a27293b9d2863d454a27e 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/ChatModel.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/ChatModel.scala @@ -1,9 +1,14 @@ package org.bigbluebutton.core.apps +import org.bigbluebutton.core.models.{ DirectChats, PublicChats, UserIdAndName } + import scala.collection.mutable.ArrayBuffer -import scala.collection.immutable.HashMap class ChatModel { + + val directChats = new DirectChats + val publicChats = new PublicChats + private val messages = new ArrayBuffer[Map[String, String]]() def getChatHistory(): Array[Map[String, String]] = { @@ -20,4 +25,5 @@ class ChatModel { def clearPublicChatHistory() { messages.clear(); } -} \ No newline at end of file +} + diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/PermisssionCheck.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/PermisssionCheck.scala new file mode 100755 index 0000000000000000000000000000000000000000..e5bceaa6b392d80090b8bd518e295bf9bcc43ec4 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/PermisssionCheck.scala @@ -0,0 +1,10 @@ +package org.bigbluebutton.core.apps + +import org.bigbluebutton.core.models.UserVO + +trait PermisssionCheck { + + def isAllowed(permission: String, role: String, user: UserVO): Boolean = { + true + } +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/DirectChat.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/DirectChat.scala new file mode 100755 index 0000000000000000000000000000000000000000..00732e3de249b757f787a3efad358e7df32ae384 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/DirectChat.scala @@ -0,0 +1,61 @@ +package org.bigbluebutton.core.models + +import scala.collection.mutable + +object DirectChats { + + def create(between: Set[String], chats: DirectChats): DirectChat = { + val chat = DirectChat(between) + chats.save(chat) + chat + } + + def find(between: Set[String], chats: DirectChats): Option[DirectChat] = { + chats.toVector.find { c => between subsetOf (c.between) } + } + +} + +class DirectChats { + private var chats: collection.immutable.HashMap[String, DirectChat] = new collection.immutable.HashMap[String, DirectChat] + + def toVector: Vector[DirectChat] = chats.values.toVector + + private def save(chat: DirectChat): DirectChat = { + chats += chat.id -> chat + chat + } + + private def remove(id: String): Option[DirectChat] = { + for { + chat <- chats.get(id) + } yield { + chats -= chat.id + chat + } + } +} + +object DirectChat { + private def createId(between: Set[String]): String = { + between.toSeq.sorted.mkString("-") + } + + def apply(between: Set[String]) = new DirectChat(createId(between), between) +} + +class DirectChat(val id: String, val between: Set[String]) { + private var msgs: collection.mutable.Queue[DirectChatMessage] = new mutable.Queue[DirectChatMessage]() + + def messages: Vector[DirectChatMessage] = msgs.toVector + + def append(msg: DirectChatMessage): DirectChatMessage = { + msgs += msg + msg + } + +} + +case class DirectChatMessage(msgId: String, timestamp: Long, from: UserIdAndName, to: UserIdAndName, message: ChatMessage) + +case class ChatMessage(font: String, size: Int, color: String, message: String) \ No newline at end of file diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/PublicChat.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/PublicChat.scala new file mode 100755 index 0000000000000000000000000000000000000000..8593aaab729ccb689fe6d8ff5053c13209cf0133 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/PublicChat.scala @@ -0,0 +1,57 @@ +package org.bigbluebutton.core.models + +import org.bigbluebutton.core.util.RandomStringGenerator + +import scala.collection.mutable + +object PublicChats { + def create(chats: PublicChats): PublicChat = { + val id = RandomStringGenerator.randomAlphanumericString(20) + val chat = new PublicChat(id) + chats.save(chat) + chat + } + + def find(id: String, chats: PublicChats): Option[PublicChat] = { + chats.toVector.find { chat => chat.id == id } + } +} + +class PublicChats { + private var chats: collection.immutable.HashMap[String, PublicChat] = new collection.immutable.HashMap[String, PublicChat] + + private def toVector: Vector[PublicChat] = chats.values.toVector + + private def save(chat: PublicChat): PublicChat = { + chats += chat.id -> chat + chat + } + + private def remove(id: String): Option[PublicChat] = { + for { + chat <- chats.get(id) + } yield { + chat + } + } +} + +object PublicChat { + + def append(chat: PublicChat, msg: PublicChatMessage): PublicChatMessage = { + chat.append(msg) + } +} + +class PublicChat(val id: String) { + private var messages: collection.mutable.Queue[PublicChatMessage] = new mutable.Queue[PublicChatMessage]() + + private def toVector: Vector[PublicChatMessage] = messages.toVector + + private def append(msg: PublicChatMessage): PublicChatMessage = { + messages += msg + msg + } +} + +case class PublicChatMessage(msgId: String, timestamp: Long, from: UserIdAndName, message: ChatMessage) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Streams.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Streams.scala new file mode 100755 index 0000000000000000000000000000000000000000..f0ecc2eeb7095c5377af04ae194e25fda75cc578 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Streams.scala @@ -0,0 +1,23 @@ +package org.bigbluebutton.core.models + +import com.softwaremill.quicklens._ + +object Streams { + + def add(stream: Stream, user: String): Stream = { + val newViewers = stream.viewers + user + modify(stream)(_.viewers).setTo(newViewers) + } + + def remove(stream: Stream, user: String): Stream = { + val newViewers = stream.viewers - user + modify(stream)(_.viewers).setTo(newViewers) + } +} + +/** + * Borrow some ideas from SDP. + * https://en.wikipedia.org/wiki/Session_Description_Protocol + */ +case class MediaAttribute(key: String, value: String) +case class Stream(id: String, sessionId: String, attributes: Set[MediaAttribute], viewers: Set[String]) diff --git a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/models/ChatModelTest.scala b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/models/ChatModelTest.scala new file mode 100755 index 0000000000000000000000000000000000000000..bacacdfec0eb015616b18308948c3b32fed72859 --- /dev/null +++ b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/models/ChatModelTest.scala @@ -0,0 +1,17 @@ +package org.bigbluebutton.core.models + +import org.scalatest._ +import org.bigbluebutton.core.UnitSpec +import scala.collection.mutable.Stack + +class ChatModelTest extends UnitSpec { + + "A Stack" should "pop values in last-in-first-out order" in { + val stack = new Stack[Int] + stack.push(1) + stack.push(2) + assert(stack.pop() === 2) + assert(stack.pop() === 1) + } + +} diff --git a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/models/DirectChatModelTest.scala b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/models/DirectChatModelTest.scala new file mode 100755 index 0000000000000000000000000000000000000000..6be1a84ff8e50de110f2e0637e111fe64df93c17 --- /dev/null +++ b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/models/DirectChatModelTest.scala @@ -0,0 +1,39 @@ +package org.bigbluebutton.core.models + +import org.bigbluebutton.core.UnitSpec + +class DirectChatModelTest extends UnitSpec { + + "A DirectChat" should "be able to add a message" in { + val msg = ChatMessage("arial", 10, "red", "Hello") + val from = UserIdAndName("user1", "User 1") + val to = UserIdAndName("user2", "User 2") + val dm = new DirectChatMessage("msgId", System.currentTimeMillis(), from, to, msg) + + val between = Set("user1", "user2") + val directChats = new DirectChats() + val dc = DirectChats.create(between, directChats) + val dm2 = dc.append(dm) + assert(dc.messages.length == 1) + + val dm3 = dc.append(dm) + assert(dc.messages.length == 2) + + val dc2 = DirectChats.find(between, directChats) + dc2 match { + case Some(directChat) => assert(directChat.messages.length == 2) + case None => fail("No direct chat found!") + } + + val dm4 = dc.append(dm) + assert(dc.messages.length == 3) + + val dc3 = DirectChats.find(between, directChats) + dc3 match { + case Some(directChat) => assert(directChat.messages.length == 3) + case None => fail("No direct chat found!") + } + + } + +}