Advertisement
Guest User

Untitled

a guest
Sep 19th, 2019
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 21.41 KB | None | 0 0
  1. import android.util.Base64
  2. import com.facebook.react.bridge.Promise
  3. import com.facebook.react.bridge.ReactApplicationContext
  4. import com.facebook.react.bridge.ReactContextBaseJavaModule
  5. import com.facebook.react.bridge.ReactMethod
  6. import com.google.gson.Gson
  7. import com.google.gson.JsonObject
  8. import com.moonshrd.models.UserModel
  9. import com.moonshrd.utils.matrix.Matrix
  10. import com.moonshrd.utils.sendEventWithOneStringArg
  11. import java9.util.concurrent.CompletableFuture
  12. import kotlinx.coroutines.GlobalScope
  13. import kotlinx.coroutines.launch
  14. import org.matrix.androidsdk.core.callback.ApiCallback
  15. import org.matrix.androidsdk.core.model.MatrixError
  16. import org.matrix.androidsdk.data.Room
  17. import org.matrix.androidsdk.data.RoomMediaMessage
  18. import org.matrix.androidsdk.data.RoomState
  19. import org.matrix.androidsdk.data.RoomSummary
  20. import org.matrix.androidsdk.data.timeline.EventTimeline
  21. import org.matrix.androidsdk.listeners.IMXMediaUploadListener
  22. import org.matrix.androidsdk.rest.model.ChunkEvents
  23. import org.matrix.androidsdk.rest.model.Event
  24. import org.matrix.androidsdk.rest.model.User
  25. import org.matrix.androidsdk.rest.model.search.SearchUsersResponse
  26. import java.io.ByteArrayInputStream
  27. import java.net.URLConnection.guessContentTypeFromStream
  28. import javax.inject.Inject
  29. import org.matrix.androidsdk.rest.model.TokensChunkEvents
  30. import org.matrix.androidsdk.rest.model.sync.RoomResponse
  31.  
  32. class MatrixClientModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
  33.     private val eventListeners = HashMap<String, NewEventsListener>()
  34.  
  35.     @Inject
  36.     lateinit var gson: Gson
  37.  
  38.     @Inject
  39.     lateinit var matrixInstance: Matrix
  40.  
  41.     init {
  42.         MainApplication.getComponent().injectsMatrixClientModule(this)
  43.     }
  44.  
  45.     override fun getName(): String {
  46.         return "MatrixClient"
  47.     }
  48.  
  49.     private fun isSessionExists(promise: Promise): Boolean {
  50.         if (matrixInstance.defaultSession == null) {
  51.             promise.reject("NullSession", "Session must not be null!")
  52.             return false
  53.         }
  54.         return true
  55.     }
  56.  
  57.     @ReactMethod
  58.     fun getDirectChats(promise: Promise) {
  59.         if (!isSessionExists(promise)) {
  60.             return
  61.         }
  62.         GlobalScope.launch {
  63.             for (i in 0 until 15) {
  64.                 if (!Globals.State.isInitialSyncComplete) {
  65.                     if (i == 14) {
  66.                         promise.reject("onUnexpectedError", "Sync waiting timeout!")
  67.                     }
  68.                     Thread.sleep(1000)
  69.                 }
  70.                 break
  71.             }
  72.  
  73.             promise.resolve(gson.toJson(getDirectChatsInternal()))
  74.         }
  75.     }
  76.  
  77.     private fun getDirectChatsInternal(): List<UserModel> {
  78.         val directChats = matrixInstance.defaultSession.dataHandler.store.rooms.filter {
  79.             it.isDirect
  80.         }
  81.  
  82.         val chatModels = mutableListOf<UserModel>()
  83.         directChats.forEach { room ->
  84.             val roomSummary = room.roomSummary
  85.             // hack for optimization: since we hold the same listener, we will not create a useless instance of this listener (else it will add new object to internal list of listeners and messing up the memory)
  86.             if (eventListeners[roomSummary!!.roomId] == null) {
  87.                 eventListeners[roomSummary.roomId] = NewEventsListener(reactApplicationContext, room, roomSummary)
  88.             }
  89.             room.timeline.addEventTimelineListener(eventListeners[room.roomId])
  90.             // hack end
  91.             val contactID = room.state.loadedMembers.filter {
  92.                 it.userId != matrixInstance.defaultSession.myUserId
  93.             }[0].userId
  94.             val contact = matrixInstance.defaultSession.dataHandler.store.getUser(contactID)
  95.             val chat = UserModel(
  96.                     contactID,
  97.                     room.getRoomDisplayName(reactApplicationContext),
  98.                     room.avatarUrl ?: "",
  99.                     contact.latestPresenceTs,
  100.                     contact.isActive,
  101.                     matrixInstance.defaultLatestChatMessageCache.getLatestText(reactApplicationContext, roomSummary.roomId),
  102.                     roomSummary.latestReceivedEvent.originServerTs,
  103.                     roomSummary.latestReceivedEvent.mSentState.name,
  104.                     roomSummary.mUnreadEventsCount,
  105.                     roomId = room.roomId
  106.             )
  107.             chatModels.add(chat)
  108.         }
  109.         return chatModels
  110.     }
  111.  
  112.     @ReactMethod
  113.     fun getUserById(userID: String, promise: Promise) {
  114.       getDataUser(userID,promise)
  115.     }
  116.  
  117.     private fun getDataUser(userID: String, promise: Promise){
  118.         if (!isSessionExists(promise)) {
  119.             return
  120.         }
  121.  
  122.         val userName = CompletableFuture<String?>()
  123.         val userAvatarUrl = CompletableFuture<String?>()
  124.         val userIsActive = CompletableFuture<Boolean?>()
  125.         val userLastSeen = CompletableFuture<Long?>()
  126.         val userMembership = CompletableFuture<String?>()
  127.  
  128.  
  129.  
  130.         val directChats = matrixInstance.defaultSession.dataHandler.store.rooms.filter {
  131.             it.isDirect
  132.         }
  133.  
  134.         val roomId = getRoomId(directChats,userID)
  135.  
  136.         matrixInstance.defaultSession.presenceApiClient.getPresence(userID,object : ApiCallback<User>{
  137.             override fun onSuccess(info: User?) {
  138.                 userIsActive.complete(info?.isActive)
  139.                 userLastSeen.complete(info?.lastActiveAgo)
  140.             }
  141.  
  142.             override fun onUnexpectedError(e: java.lang.Exception?) {
  143.                 userIsActive.complete(null)
  144.                 userLastSeen.complete(null)
  145.             }
  146.  
  147.             override fun onMatrixError(e: MatrixError?) {
  148.                 userIsActive.complete(null)
  149.                 userLastSeen.complete(null)
  150.             }
  151.  
  152.             override fun onNetworkError(e: java.lang.Exception?) {
  153.                 userIsActive.complete(null)
  154.                 userLastSeen.complete(null)
  155.             }
  156.         })
  157.  
  158.         matrixInstance.defaultSession.profileApiClient.displayname(userID, object : ApiCallback<String> {
  159.             override fun onSuccess(info: String?) {
  160.                 userName.complete(info)
  161.             }
  162.  
  163.             override fun onUnexpectedError(e: Exception?) {
  164.                 promise.reject(e)
  165.                 userName.complete(null)
  166.             }
  167.  
  168.             override fun onMatrixError(e: MatrixError?) {
  169.                 //promise.reject(RuntimeException(e!!.error))
  170.                 userName.complete("")
  171.             }
  172.  
  173.             override fun onNetworkError(e: Exception?) {
  174.                 promise.reject(e)
  175.                 userName.complete(null)
  176.             }
  177.         })
  178.  
  179.         matrixInstance.defaultSession.profileApiClient.avatarUrl(userID, object : ApiCallback<String> {
  180.             override fun onSuccess(info: String?) {
  181.                 userAvatarUrl.complete(info)
  182.             }
  183.  
  184.             override fun onUnexpectedError(e: Exception?) {
  185.                 promise.reject(e)
  186.                 userAvatarUrl.complete(null)
  187.             }
  188.  
  189.             override fun onMatrixError(e: MatrixError?) {
  190.                 //promise.reject(RuntimeException(e!!.error))
  191.                 userAvatarUrl.complete(null)
  192.             }
  193.  
  194.             override fun onNetworkError(e: Exception?) {
  195.                 promise.reject(e)
  196.                 userAvatarUrl.complete(null)
  197.             }
  198.         })
  199.  
  200.  
  201.         matrixInstance.defaultSession.roomsApiClient.getRoomMembers(roomId,null,null,null,object:ApiCallback<ChunkEvents>{
  202.             override fun onSuccess(info: ChunkEvents?) {
  203.                 info?.let{
  204.                     for(i in it.chunk.indices){
  205.                             if(userID== it.chunk[i].userId){
  206.                                 val membershipInfo = info.chunk[i].contentAsJsonObject.get("membership").toString()
  207.                                 userMembership.complete(membershipInfo)
  208.                                 break
  209.                             }
  210.                     }
  211.                 }
  212.             }
  213.  
  214.             override fun onUnexpectedError(e: java.lang.Exception?) {
  215.                 var kek = ""
  216.             }
  217.  
  218.             override fun onMatrixError(e: MatrixError?) {
  219.                 var kek = ""
  220.             }
  221.  
  222.             override fun onNetworkError(e: java.lang.Exception?) {
  223.                 var kek = ""
  224.             }
  225.         })
  226.  
  227.         GlobalScope.launch {
  228.             val name = userName.get()
  229.             val avatarUrl = userAvatarUrl.get()
  230.             val isActive = userIsActive.get()
  231.             val lastSeen = userLastSeen.get()
  232.             val membership = userMembership.get()
  233.             if (name != null && avatarUrl != null) {
  234.                 promise.resolve(gson.toJson(UserModel(userID, name, avatarUrl,lastSeen = lastSeen,isActive = isActive,roomId = roomId,membership = membership)))
  235.             } else {
  236.                 promise.resolve(gson.toJson(UserModel(userID, "", "")))
  237.             }
  238.         }
  239.     }
  240.  
  241.     private fun getRoomId(rooms:List<Room>, useriD: String):String?{
  242.         for( i in rooms.indices){
  243.             if(rooms[i].getMember(useriD)!=null){
  244.                 return rooms[i].roomId
  245.             }
  246.         }
  247.         return null
  248.     }
  249.  
  250.     @ReactMethod
  251.     fun getMyMxId(promise: Promise) {
  252.         if (!isSessionExists(promise)) {
  253.             return
  254.         }
  255.  
  256.         promise.resolve(matrixInstance.defaultSession.myUserId)
  257.     }
  258.  
  259.     @ReactMethod
  260.     fun getMyProfile(promise: Promise) {
  261.         if (!isSessionExists(promise)) {
  262.             return
  263.         }
  264.  
  265.         val currentSession = matrixInstance.defaultSession
  266.         val httpUrlAvatar = currentSession.contentManager.getDownloadableUrl(currentSession.dataHandler.myUser.avatarUrl,false)
  267.         promise.resolve(gson.toJson(UserModel(currentSession.myUserId,
  268.                 currentSession.dataHandler.myUser.displayname,
  269.                 currentSession.dataHandler.myUser.avatarUrl,
  270.                 avatarLink = httpUrlAvatar)))
  271.     }
  272.  
  273.     @ReactMethod
  274.     fun createDirectChat(participantUserId: String, promise: Promise) {
  275.         if (!isSessionExists(promise)) {
  276.             return
  277.         }
  278.  
  279.         if (isDirectChatExists(participantUserId)) {
  280.             getDataUser(participantUserId,promise)
  281.             return
  282.         }
  283.  
  284.         matrixInstance.defaultSession.createDirectMessageRoom(participantUserId, object : ApiCallback<String> {
  285.             override fun onSuccess(roomId: String?) {
  286.                 promise.resolve(roomId)
  287.             }
  288.  
  289.             override fun onUnexpectedError(e: java.lang.Exception?) {
  290.                 promise.reject("onUnexpectedError", e)
  291.             }
  292.  
  293.             override fun onMatrixError(e: MatrixError?) {
  294.                 promise.reject("onMatrixError", e!!.message)
  295.             }
  296.  
  297.             override fun onNetworkError(e: java.lang.Exception?) {
  298.                 promise.reject("onNetworkError", e)
  299.             }
  300.         })
  301.     }
  302.  
  303.     private fun isDirectChatExists(participantUserId: String): Boolean {
  304.         val directChats = getDirectChatsInternal()
  305.         var exists = false
  306.         directChats.forEach {
  307.             if (it.userId == participantUserId) {
  308.                 exists = true
  309.             }
  310.         }
  311.         return exists
  312.     }
  313.  
  314.     @ReactMethod
  315.     fun searchUserById(userName: String, limit: Int?, promise: Promise) {
  316.         if (!isSessionExists(promise)) {
  317.             return
  318.         }
  319.  
  320.         val tempLimit: Int?
  321.         if (limit == 0) {
  322.             tempLimit = null
  323.         } else {
  324.             tempLimit = limit
  325.         }
  326.  
  327.         val users = ArrayList<UserModel>()
  328.         matrixInstance.defaultSession.searchUsers(userName, tempLimit, null, object : ApiCallback<SearchUsersResponse> {
  329.             override fun onSuccess(info: SearchUsersResponse?) {
  330.                 info!!.results.forEach {
  331.                     users.add(UserModel(it.user_id, it.displayname, it.avatarUrl))
  332.                 }
  333.                 promise.resolve(gson.toJson(users))
  334.             }
  335.  
  336.             override fun onUnexpectedError(e: java.lang.Exception?) {
  337.                 promise.reject("onUnexpectedError", e!!.message)
  338.             }
  339.  
  340.             override fun onMatrixError(e: MatrixError?) {
  341.                 promise.reject("onMatrixError", e!!.message)
  342.             }
  343.  
  344.             override fun onNetworkError(e: java.lang.Exception?) {
  345.                 promise.reject("onNetworkError", e!!.message)
  346.             }
  347.         })
  348.     }
  349.  
  350.     @ReactMethod
  351.     fun updateDisplayName(newDisplayName: String, promise: Promise) {
  352.         if (!isSessionExists(promise)) {
  353.             return
  354.         }
  355.  
  356.         matrixInstance.defaultSession.profileApiClient.updateDisplayname(newDisplayName, object : ApiCallback<Void> {
  357.             override fun onSuccess(info: Void?) {
  358.                 promise.resolve(true)
  359.             }
  360.  
  361.             override fun onUnexpectedError(e: java.lang.Exception?) {
  362.                 promise.reject("onUnexpectedError", e!!.message)
  363.             }
  364.  
  365.             override fun onMatrixError(e: MatrixError?) {
  366.                 promise.reject("onMatrixError", e!!.message)
  367.             }
  368.  
  369.             override fun onNetworkError(e: java.lang.Exception?) {
  370.                 promise.reject("onNetworkError", e!!.message)
  371.             }
  372.         })
  373.     }
  374.  
  375.     @ReactMethod
  376.     fun updateAvatar(base64Avatar: String, promise: Promise) {
  377.         if (!isSessionExists(promise)) {
  378.             return
  379.         }
  380.  
  381.         val future = uploadImage(base64Avatar)
  382.         future.thenAccept {
  383.             matrixInstance.defaultSession.profileApiClient.updateAvatarUrl(it, object : ApiCallback<Void> {
  384.                 override fun onSuccess(info: Void?) {
  385.                     promise.resolve(true)
  386.                 }
  387.  
  388.                 override fun onUnexpectedError(e: java.lang.Exception?) {
  389.                     promise.reject("onUnexpectedError", e!!.message)
  390.                 }
  391.  
  392.                 override fun onMatrixError(e: MatrixError?) {
  393.                     promise.reject("onMatrixError", e!!.message)
  394.                 }
  395.  
  396.                 override fun onNetworkError(e: java.lang.Exception?) {
  397.                     promise.reject("onNetworkError", e!!.message)
  398.                 }
  399.             })
  400.         }
  401.         future.exceptionally {
  402.             promise.reject(it)
  403.             ""
  404.         }
  405.     }
  406.  
  407.     private fun uploadImage(base64Image: String): CompletableFuture<String> {
  408.         val imageByteArray = Base64.decode(base64Image, Base64.DEFAULT)
  409.         val imageInputStream = ByteArrayInputStream(imageByteArray)
  410.         val fileMimeType = guessContentTypeFromStream(imageInputStream)
  411.  
  412.         val future = CompletableFuture<String>()
  413.  
  414.         matrixInstance.defaultSession.mediaCache.uploadContent(imageInputStream, null, fileMimeType, null, object : IMXMediaUploadListener {
  415.             override fun onUploadProgress(uploadId: String?, uploadStats: IMXMediaUploadListener.UploadStats?) {
  416.                 //
  417.             }
  418.  
  419.             override fun onUploadCancel(uploadId: String?) {
  420.                 future.completeExceptionally(RuntimeException("onUploadCancel, uploadId=$uploadId"))
  421.             }
  422.  
  423.             override fun onUploadStart(uploadId: String?) {
  424.                 //
  425.             }
  426.  
  427.             override fun onUploadComplete(uploadId: String?, contentUri: String?) {
  428.                 future.complete(contentUri)
  429.             }
  430.  
  431.             override fun onUploadError(uploadId: String?, serverResponseCode: Int, serverErrorMessage: String?) {
  432.                 future.completeExceptionally(RuntimeException("Error occurred! Response code=$serverResponseCode, error message=$serverErrorMessage"))
  433.             }
  434.         })
  435.  
  436.         return future
  437.     }
  438.  
  439.     @ReactMethod
  440.     private fun sendMessage(message: String, roomId: String, promise: Promise) {
  441.         val room = matrixInstance.defaultSession.dataHandler.getRoom(roomId)
  442.         room.sendTextMessage(message, message, message, object : RoomMediaMessage.EventCreationListener {
  443.             override fun onEventCreated(roomMediaMessage: RoomMediaMessage?) {
  444.               //  getHistoryMessageTest(roomId,null)
  445.                 promise.resolve(true)
  446.             }
  447.  
  448.             override fun onEventCreationFailed(roomMediaMessage: RoomMediaMessage?, errorMessage: String?) {
  449.                 promise.reject("onEventCreationError", roomMediaMessage!!.text.toString())
  450.             }
  451.  
  452.             override fun onEncryptionFailed(roomMediaMessage: RoomMediaMessage?) {
  453.                 promise.reject("onEncryptionError", roomMediaMessage!!.text.toString())
  454.             }
  455.         })
  456.     }
  457.  
  458.     @ReactMethod
  459.     private fun getHistoryMessage(roomId:String,tokenMessageEnd:String, promise: Promise){
  460.         val room = matrixInstance.defaultSession.dataHandler.getRoom(roomId)
  461.  
  462.         matrixInstance.defaultSession.roomsApiClient.getRoomMessagesFrom(room.roomId, tokenMessageEnd, EventTimeline.Direction.BACKWARDS, 15,null, object : ApiCallback<TokensChunkEvents> {
  463.  
  464.             override fun onSuccess(info: TokensChunkEvents) {
  465.                 //it hack need because we can`t direct convert info to Json
  466.                 val messages = arrayListOf<JsonObject>()
  467.  
  468.                 val newInfo: HashMap<String, Any> = hashMapOf()
  469.  
  470.                 for(i in info.chunk.indices){
  471.                         messages.add(info.chunk[i].toJsonObject())
  472.                 }
  473.  
  474.                 newInfo["start"] = info.start
  475.                 newInfo["end"] = info.end
  476.                 newInfo["messages"] = messages
  477.  
  478.                 val jsonMessages = gson.toJson(newInfo)
  479.                 promise.resolve(jsonMessages)
  480.             }
  481.  
  482.             override fun onUnexpectedError(e: Exception) {
  483.                 promise.reject("onUnexpectedError", e.message)
  484.             }
  485.  
  486.             override fun onNetworkError(e: Exception) {
  487.                 promise.reject("onNetworkError", e.message)
  488.             }
  489.  
  490.             override fun onMatrixError(e: MatrixError) {
  491.                 promise.reject("onMatrixError", e.message)
  492.             }
  493.         })
  494.     }
  495.  
  496.     @ReactMethod
  497.     fun acceptInvite(roomId:String,promise: Promise){
  498.         val room = matrixInstance.defaultSession.dataHandler.getRoom(roomId)
  499.         matrixInstance.defaultSession.roomsApiClient.joinRoom(roomId,null,null,object:ApiCallback<RoomResponse> {
  500.             override fun onSuccess(info: RoomResponse?) {
  501.                 val infoRoom = gson.toJson(info)
  502.                 promise.resolve(infoRoom)
  503.             }
  504.  
  505.             override fun onUnexpectedError(e: Exception) {
  506.                 promise.reject("onUnexpectedError", e.message)
  507.  
  508.             }
  509.  
  510.             override fun onMatrixError(e: MatrixError) {
  511.                 promise.reject("onMatrixError", e.message)
  512.             }
  513.  
  514.             override fun onNetworkError(e: java.lang.Exception) {
  515.                 promise.reject("onNetworkError", e.message)
  516.             }
  517.         })
  518.     }
  519.  
  520.     private fun getHistoryMessageTest(roomId:String,tokenMessageEnd:String?){
  521.         val room = matrixInstance.defaultSession.dataHandler.getRoom(roomId)
  522.  
  523.         matrixInstance.defaultSession.roomsApiClient.getRoomMessagesFrom(room.roomId, tokenMessageEnd, EventTimeline.Direction.BACKWARDS, 15,null, object : ApiCallback<TokensChunkEvents> {
  524.  
  525.             override fun onSuccess(info: TokensChunkEvents) {
  526.                 val messages = arrayListOf<JsonObject>()
  527.  
  528.                 val newInfo: HashMap<String, Any> = hashMapOf()
  529.  
  530.                 for(i in info.chunk.indices){
  531.                         messages.add(info.chunk[i].toJsonObject())
  532.                 }
  533.  
  534.                 newInfo["start"] = info.start
  535.                 newInfo["end"] = info.end
  536.                 newInfo["messages"] = messages
  537.  
  538.                 val jsonMessages = gson.toJson(newInfo)
  539.  
  540.  
  541.                 matrixInstance.defaultSession.roomsApiClient.getRoomMessagesFrom(room.roomId, info.end, EventTimeline.Direction.BACKWARDS, 15,null, object : ApiCallback<TokensChunkEvents> {
  542.  
  543.                     override fun onSuccess(info: TokensChunkEvents) {
  544.  
  545.                     }
  546.  
  547.                     override fun onUnexpectedError(e: Exception) {
  548.                     }
  549.  
  550.                     override fun onNetworkError(e: Exception) {
  551.                     }
  552.  
  553.                     override fun onMatrixError(e: MatrixError) {
  554.                     }
  555.                 })
  556.             }
  557.  
  558.             override fun onUnexpectedError(e: Exception) {
  559.             }
  560.  
  561.             override fun onNetworkError(e: Exception) {
  562.             }
  563.  
  564.             override fun onMatrixError(e: MatrixError) {
  565.             }
  566.         })
  567.     }
  568.  
  569.     //can refactor with use dagger2
  570.     internal class NewEventsListener(private val reactContext: ReactApplicationContext,
  571.                                      private val room: Room,
  572.                                      private val roomSummary: RoomSummary) : EventTimeline.Listener {
  573.         private val matrixInstance = Matrix.getInstance(reactContext)
  574.  
  575.         override fun onEvent(event: Event?, direction: EventTimeline.Direction?, roomState: RoomState?) {
  576.             event?.let {
  577.                 matrixInstance.defaultLatestChatMessageCache.updateLatestMessage(reactContext, room.roomId, event!!.contentAsJsonObject.get("body").asString)
  578.                 roomSummary.setLatestReceivedEvent(event, roomState)
  579.                 val gson =  Gson()
  580.                 val msg = gson.toJson(event.toJsonObject())
  581.                 sendEventWithOneStringArg(reactContext, "eventMessage", "message", msg)
  582.             }
  583.         }
  584.     }
  585. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement