All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sss.openstar.rpc.MessageAdapter.scala Maven / Gradle / Ivy

package sss.openstar.rpc

import java.time.LocalDateTime
import org.jsoup.Jsoup
import org.jsoup.safety.Safelist
import sss.ancillary.FailWithException.fail
import sss.ancillary.Guid
import sss.openstar.UniqueNodeIdentifier
import sss.openstar.account.{NodeIdTag, NodeIdentity, NodeVerifier}
import sss.openstar.identityledger.IdentityServiceQuery
import sss.openstar.message.MessageInBox.SavedMessage
import sss.openstar.message.payloads.MessageEcryption.EncryptedMessage
import sss.openstar.message.payloads._
import sss.openstar.message.{ConsumedMonitoredUtxo, DecodedMessageCache, MonitoredUtxo, UtxoQuery}
import sss.openstar.ui.rpc.MessagePayloadType.MessagePayloadType
import sss.openstar.ui.rpc.{MessagePayloadType, ReadReceipt}
import sss.openstar.util.DateOps._

import scala.concurrent.{ExecutionContext, Future}
import scala.util.Try

object MessageAdapter {


  case class AdaptedMessage(
                             msgType: MessagePayloadType,
                             index: Long,
                             guid: Guid,
                             children: Seq[Guid],
                             from: UniqueNodeIdentifier,
                             description: String,
                             coins: Option[Long],
                             receivedAt: LocalDateTime,
                             readReceipts: Seq[ReadReceipt]
                           )

  def adapt(savedMessage: SavedMessage)(
    implicit userId: NodeIdentity,
    utxoQuery: UtxoQuery,
    identityServiceQuery: IdentityServiceQuery,
    ec: ExecutionContext): Future[AdaptedMessage] = Future {
    DecodedMessageCache(savedMessage.msg).getOrElse(fail(s"Can't decode message ${savedMessage.msg.msgPayload.payloadType}"))
  } flatMap {
    case m: EncryptedMessage => adapt(savedMessage, m)
    case m: NewQuorumMemberMessage => adapt(savedMessage, m)
    case m: NewContactMessage => adapt(savedMessage, m)
    case m: CompletedNewContactMessage => adapt(savedMessage, m)

  }


  def toReadReceipt(returnBlockHeightOpt: Option[Long])(p: (UniqueNodeIdentifier, Option[MonitoredUtxo])): ReadReceipt =
    (p, returnBlockHeightOpt) match {
    case ((identity, Some(ConsumedMonitoredUtxo(_, atHeight, when))), Some(returnBlockHeight)) if (atHeight < returnBlockHeight) =>
      ReadReceipt(identity, Some(when.toMillis))
    case ((identity, _), _) =>
      ReadReceipt(identity, None)
  }

  def adapt(savedMessage: SavedMessage,
            enc: EncryptedMessage)(implicit userId: NodeIdentity,
                                   identityServiceQuery: IdentityServiceQuery,
                                   txIndexQuery: UtxoQuery,
                                   ec: ExecutionContext): Future[AdaptedMessage] = Future {

    val lookupId: NodeIdTag => NodeVerifier = MessageEcryption.createLookupId(identityServiceQuery)
    enc.decrypt(userId, lookupId) map { textWithSecret =>

      require(savedMessage.msg.guid == enc.guid, "Impossible, guids must be the same.")

      val readReceipts = enc
        .receivers
        .map(_.identity.nodeId)
        .zip(enc.watch.map(txIndexQuery))
        .map(toReadReceipt(enc.bountyOpt.map(_.bountyReturnBlockHeight)))

      AdaptedMessage(
        MessagePayloadType(savedMessage.msg.msgPayload.payloadType),
        savedMessage.index,
        savedMessage.msg.guid,
        enc.childGuids,
        enc.author.nodeId,
        Jsoup.clean(
          if (textWithSecret.text.length > 150) textWithSecret.text.substring(0, 150)
          else textWithSecret.text
          , Safelist.none()
        ),
        enc.bountyOpt.map(_.amountOfBounty),
        savedMessage.savedAt,
        readReceipts
      )
    }
  }.flatten

  def adapt(savedMessage: SavedMessage,
            msg: NewQuorumMemberMessage)(implicit userId: NodeIdentity,
                                         identityServiceQuery: IdentityServiceQuery,
                                         ec: ExecutionContext): Future[AdaptedMessage] = Future {


    AdaptedMessage(
      MessagePayloadType(savedMessage.msg.msgPayload.payloadType),
      savedMessage.index,
      savedMessage.msg.guid,
      Seq.empty,
      "",
      "Add new Quorum Member",
      None,
      savedMessage.savedAt,
      Seq.empty)
  }


  def adapt(savedMessage: SavedMessage,
            msg: NewContactMessage)(implicit userId: NodeIdentity,
                                    identityServiceQuery: IdentityServiceQuery,
                                    ec: ExecutionContext): Future[AdaptedMessage] = Future {

    val paywalls = identityServiceQuery.paywalls(msg.invitor)
    val isReply = savedMessage.msg.parentGuid.isDefined
    val desc = paywalls.find(_.category == msg.category.toLowerCase).map { paywall =>
      if(isReply) {
        s"${msg.invitor} responds by adding ${msg.invitee} to paywall category ${paywall.category} (currently ${paywall.amount.get})"
      } else {
        s"${msg.invitor} requests adding ${msg.invitee} to paywall category ${paywall.category} (currently ${paywall.amount.get})"
      }
    }.getOrElse(s"Bad contact request from ${msg.invitor}")


    AdaptedMessage(
      MessagePayloadType(savedMessage.msg.msgPayload.payloadType),
      savedMessage.index,
      savedMessage.msg.guid,
      Seq.empty,
      msg.invitor,
      desc,
      None,
      savedMessage.savedAt,
      Seq.empty)
  }

  def adapt(savedMessage: SavedMessage,
            ncm: CompletedNewContactMessage)(implicit userId: NodeIdentity,
                                             identityServiceQuery: IdentityServiceQuery,
                                             ec: ExecutionContext): Future[AdaptedMessage] = Future {

    //println(s"ADAPT a Completed new ${savedMessage.msg.guid} ${savedMessage.msg.parentGuid}")
    val invitorCurrentAmount: Long = identityServiceQuery.getCurrentCharge(
      ncm.invitor,
      ncm.invitorCategory
      )

    val inviteeCurrentAmount: Long = identityServiceQuery.getCurrentCharge(
      ncm.invitee,
      ncm.inviteeCategory
      )

    val desc =
      s"${ncm.invitor} requires $inviteeCurrentAmount to send to ${ncm.invitee} and $invitorCurrentAmount to receive"


    AdaptedMessage(
      MessagePayloadType.NewContactType,
      savedMessage.index,
      savedMessage.msg.guid,
      Seq.empty,
      ncm.invitor,
      desc,
      None,
      savedMessage.savedAt,
      Seq.empty)
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy