chat.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. package server
  2. import (
  3. "github.com/mkaminski/goaim/oscar"
  4. "io"
  5. )
  6. const (
  7. ChatErr uint16 = 0x0001
  8. ChatRoomInfoUpdate = 0x0002
  9. ChatUsersJoined = 0x0003
  10. ChatUsersLeft = 0x0004
  11. ChatChannelMsgTohost = 0x0005
  12. ChatChannelMsgToclient = 0x0006
  13. ChatEvilRequest = 0x0007
  14. ChatEvilReply = 0x0008
  15. ChatClientErr = 0x0009
  16. ChatPauseRoomReq = 0x000A
  17. ChatPauseRoomAck = 0x000B
  18. ChatResumeRoom = 0x000C
  19. ChatShowMyRow = 0x000D
  20. ChatShowRowByUsername = 0x000E
  21. ChatShowRowByNumber = 0x000F
  22. ChatShowRowByName = 0x0010
  23. ChatRowInfo = 0x0011
  24. ChatListRows = 0x0012
  25. ChatRowListInfo = 0x0013
  26. ChatMoreRows = 0x0014
  27. ChatMoveToRow = 0x0015
  28. ChatToggleChat = 0x0016
  29. ChatSendQuestion = 0x0017
  30. ChatSendComment = 0x0018
  31. ChatTallyVote = 0x0019
  32. ChatAcceptBid = 0x001A
  33. ChatSendInvite = 0x001B
  34. ChatDeclineInvite = 0x001C
  35. ChatAcceptInvite = 0x001D
  36. ChatNotifyMessage = 0x001E
  37. ChatGotoRow = 0x001F
  38. ChatStageUserJoin = 0x0020
  39. ChatStageUserLeft = 0x0021
  40. ChatUnnamedSnac22 = 0x0022
  41. ChatClose = 0x0023
  42. ChatUserBan = 0x0024
  43. ChatUserUnban = 0x0025
  44. ChatJoined = 0x0026
  45. ChatUnnamedSnac27 = 0x0027
  46. ChatUnnamedSnac28 = 0x0028
  47. ChatUnnamedSnac29 = 0x0029
  48. ChatRoomInfoOwner = 0x0030
  49. )
  50. func routeChat(sess *Session, sm SessionManager, snac oscar.SnacFrame, r io.Reader, w io.Writer, sequence *uint32) error {
  51. switch snac.SubGroup {
  52. case ChatChannelMsgTohost:
  53. return SendAndReceiveChatChannelMsgTohost(sess, sm, snac, r, w, sequence)
  54. default:
  55. return ErrUnsupportedSubGroup
  56. }
  57. }
  58. func SendAndReceiveChatChannelMsgTohost(sess *Session, sm SessionManager, snac oscar.SnacFrame, r io.Reader, w io.Writer, sequence *uint32) error {
  59. snacPayloadIn := oscar.SNAC_0x0E_0x05_ChatChannelMsgToHost{}
  60. if err := oscar.Unmarshal(&snacPayloadIn, r); err != nil {
  61. return err
  62. }
  63. snacFrameOut := oscar.SnacFrame{
  64. FoodGroup: CHAT,
  65. SubGroup: ChatChannelMsgToclient,
  66. }
  67. snacPayloadOut := oscar.SNAC_0x0E_0x06_ChatChannelMsgToClient{
  68. Cookie: snacPayloadIn.Cookie,
  69. Channel: snacPayloadIn.Channel,
  70. TLVRestBlock: oscar.TLVRestBlock{
  71. TLVList: snacPayloadIn.TLVList,
  72. },
  73. }
  74. snacPayloadOut.AddTLV(oscar.TLV{
  75. TType: oscar.ChatTLVSenderInformation,
  76. Val: oscar.TLVUserInfo{
  77. ScreenName: sess.ScreenName,
  78. WarningLevel: sess.GetWarning(),
  79. TLVBlock: oscar.TLVBlock{
  80. TLVList: sess.GetUserInfo(),
  81. },
  82. },
  83. })
  84. // send message to all the participants except sender
  85. sm.BroadcastExcept(sess, XMessage{
  86. snacFrame: snacFrameOut,
  87. snacOut: snacPayloadOut,
  88. })
  89. if _, ackMsg := snacPayloadIn.GetTLV(oscar.ChatTLVEnableReflectionFlag); !ackMsg {
  90. return nil
  91. }
  92. // reflect the message back to the sender
  93. return writeOutSNAC(snac, snacFrameOut, snacPayloadOut, sequence, w)
  94. }
  95. func SetOnlineChatUsers(sm SessionManager, w io.Writer, sequence *uint32) error {
  96. snacFrameOut := oscar.SnacFrame{
  97. FoodGroup: CHAT,
  98. SubGroup: ChatUsersJoined,
  99. }
  100. snacPayloadOut := oscar.SNAC_0x0E_0x03_ChatUsersJoined{}
  101. sessions := sm.Participants()
  102. for _, uSess := range sessions {
  103. snacPayloadOut.Users = append(snacPayloadOut.Users, oscar.TLVUserInfo{
  104. ScreenName: uSess.ScreenName,
  105. WarningLevel: uSess.GetWarning(),
  106. TLVBlock: oscar.TLVBlock{
  107. TLVList: uSess.GetUserInfo(),
  108. },
  109. })
  110. }
  111. return writeOutSNAC(oscar.SnacFrame{}, snacFrameOut, snacPayloadOut, sequence, w)
  112. }
  113. func AlertUserJoined(sess *Session, sm SessionManager) {
  114. sm.BroadcastExcept(sess, XMessage{
  115. snacFrame: oscar.SnacFrame{
  116. FoodGroup: CHAT,
  117. SubGroup: ChatUsersJoined,
  118. },
  119. snacOut: oscar.SNAC_0x0E_0x03_ChatUsersJoined{
  120. Users: []oscar.TLVUserInfo{
  121. {
  122. ScreenName: sess.ScreenName,
  123. WarningLevel: sess.GetWarning(),
  124. TLVBlock: oscar.TLVBlock{
  125. TLVList: sess.GetUserInfo(),
  126. },
  127. },
  128. },
  129. },
  130. })
  131. }
  132. func AlertUserLeft(sess *Session, sm SessionManager) {
  133. sm.BroadcastExcept(sess, XMessage{
  134. snacFrame: oscar.SnacFrame{
  135. FoodGroup: CHAT,
  136. SubGroup: ChatUsersLeft,
  137. },
  138. snacOut: oscar.SNAC_0x0E_0x04_ChatUsersLeft{
  139. Users: []oscar.TLVUserInfo{
  140. {
  141. ScreenName: sess.ScreenName,
  142. WarningLevel: sess.GetWarning(),
  143. TLVBlock: oscar.TLVBlock{
  144. TLVList: sess.GetUserInfo(),
  145. },
  146. },
  147. },
  148. },
  149. })
  150. }
  151. func SendChatRoomInfoUpdate(room ChatRoom, w io.Writer, sequence *uint32) error {
  152. snacFrameOut := oscar.SnacFrame{
  153. FoodGroup: CHAT,
  154. SubGroup: ChatRoomInfoUpdate,
  155. }
  156. snacPayloadOut := oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate{
  157. Exchange: 4,
  158. Cookie: room.Cookie,
  159. InstanceNumber: 100,
  160. DetailLevel: 2,
  161. TLVBlock: oscar.TLVBlock{
  162. TLVList: room.TLVList(),
  163. },
  164. }
  165. return writeOutSNAC(oscar.SnacFrame{}, snacFrameOut, snacPayloadOut, sequence, w)
  166. }