chat.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package server
  2. import (
  3. "io"
  4. "github.com/mkaminski/goaim/oscar"
  5. )
  6. type ChatHandler interface {
  7. ChannelMsgToHostHandler(sess *Session, sm SessionManager, snacPayloadIn oscar.SNAC_0x0E_0x05_ChatChannelMsgToHost) (*XMessage, error)
  8. }
  9. func NewChatRouter() ChatRouter {
  10. return ChatRouter{
  11. ChatHandler: ChatService{},
  12. }
  13. }
  14. type ChatRouter struct {
  15. ChatHandler
  16. }
  17. func (rt *ChatRouter) RouteChat(sess *Session, sm SessionManager, SNACFrame oscar.SnacFrame, r io.Reader, w io.Writer, sequence *uint32) error {
  18. switch SNACFrame.SubGroup {
  19. case oscar.ChatChannelMsgToHost:
  20. inSNAC := oscar.SNAC_0x0E_0x05_ChatChannelMsgToHost{}
  21. if err := oscar.Unmarshal(&inSNAC, r); err != nil {
  22. return err
  23. }
  24. outSNAC, err := rt.ChannelMsgToHostHandler(sess, sm, inSNAC)
  25. if err != nil || outSNAC == nil {
  26. return err
  27. }
  28. return writeOutSNAC(SNACFrame, outSNAC.snacFrame, outSNAC.snacOut, sequence, w)
  29. default:
  30. return ErrUnsupportedSubGroup
  31. }
  32. }
  33. type ChatService struct {
  34. }
  35. func (s ChatService) ChannelMsgToHostHandler(sess *Session, sm SessionManager, snacPayloadIn oscar.SNAC_0x0E_0x05_ChatChannelMsgToHost) (*XMessage, error) {
  36. snacFrameOut := oscar.SnacFrame{
  37. FoodGroup: oscar.CHAT,
  38. SubGroup: oscar.ChatChannelMsgToClient,
  39. }
  40. snacPayloadOut := oscar.SNAC_0x0E_0x06_ChatChannelMsgToClient{
  41. Cookie: snacPayloadIn.Cookie,
  42. Channel: snacPayloadIn.Channel,
  43. TLVRestBlock: oscar.TLVRestBlock{
  44. TLVList: snacPayloadIn.TLVList,
  45. },
  46. }
  47. snacPayloadOut.AddTLV(oscar.TLV{
  48. TType: oscar.ChatTLVSenderInformation,
  49. Val: oscar.TLVUserInfo{
  50. ScreenName: sess.ScreenName,
  51. WarningLevel: sess.GetWarning(),
  52. TLVBlock: oscar.TLVBlock{
  53. TLVList: sess.GetUserInfo(),
  54. },
  55. },
  56. })
  57. // send message to all the participants except sender
  58. sm.BroadcastExcept(sess, XMessage{
  59. snacFrame: snacFrameOut,
  60. snacOut: snacPayloadOut,
  61. })
  62. var ret *XMessage
  63. if _, ackMsg := snacPayloadIn.GetTLV(oscar.ChatTLVEnableReflectionFlag); ackMsg {
  64. // reflect the message back to the sender
  65. ret = &XMessage{
  66. snacFrame: snacFrameOut,
  67. snacOut: snacPayloadOut,
  68. }
  69. }
  70. return ret, nil
  71. }
  72. func SetOnlineChatUsers(sess *Session, sm SessionManager) {
  73. snacPayloadOut := oscar.SNAC_0x0E_0x03_ChatUsersJoined{}
  74. sessions := sm.Participants()
  75. for _, uSess := range sessions {
  76. snacPayloadOut.Users = append(snacPayloadOut.Users, oscar.TLVUserInfo{
  77. ScreenName: uSess.ScreenName,
  78. WarningLevel: uSess.GetWarning(),
  79. TLVBlock: oscar.TLVBlock{
  80. TLVList: uSess.GetUserInfo(),
  81. },
  82. })
  83. }
  84. sm.SendToScreenName(sess.ScreenName, XMessage{
  85. snacFrame: oscar.SnacFrame{
  86. FoodGroup: oscar.CHAT,
  87. SubGroup: oscar.ChatUsersJoined,
  88. },
  89. snacOut: snacPayloadOut,
  90. })
  91. }
  92. func AlertUserJoined(sess *Session, sm SessionManager) {
  93. sm.BroadcastExcept(sess, XMessage{
  94. snacFrame: oscar.SnacFrame{
  95. FoodGroup: oscar.CHAT,
  96. SubGroup: oscar.ChatUsersJoined,
  97. },
  98. snacOut: oscar.SNAC_0x0E_0x03_ChatUsersJoined{
  99. Users: []oscar.TLVUserInfo{
  100. {
  101. ScreenName: sess.ScreenName,
  102. WarningLevel: sess.GetWarning(),
  103. TLVBlock: oscar.TLVBlock{
  104. TLVList: sess.GetUserInfo(),
  105. },
  106. },
  107. },
  108. },
  109. })
  110. }
  111. func AlertUserLeft(sess *Session, sm SessionManager) {
  112. sm.BroadcastExcept(sess, XMessage{
  113. snacFrame: oscar.SnacFrame{
  114. FoodGroup: oscar.CHAT,
  115. SubGroup: oscar.ChatUsersLeft,
  116. },
  117. snacOut: oscar.SNAC_0x0E_0x04_ChatUsersLeft{
  118. Users: []oscar.TLVUserInfo{
  119. {
  120. ScreenName: sess.ScreenName,
  121. WarningLevel: sess.GetWarning(),
  122. TLVBlock: oscar.TLVBlock{
  123. TLVList: sess.GetUserInfo(),
  124. },
  125. },
  126. },
  127. },
  128. })
  129. }
  130. func SendChatRoomInfoUpdate(sess *Session, sm SessionManager, room ChatRoom) {
  131. sm.SendToScreenName(sess.ScreenName, XMessage{
  132. snacFrame: oscar.SnacFrame{
  133. FoodGroup: oscar.CHAT,
  134. SubGroup: oscar.ChatRoomInfoUpdate,
  135. },
  136. snacOut: oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate{
  137. Exchange: 4,
  138. Cookie: room.Cookie,
  139. InstanceNumber: 100,
  140. DetailLevel: 2,
  141. TLVBlock: oscar.TLVBlock{
  142. TLVList: room.TLVList(),
  143. },
  144. },
  145. })
  146. }