chat.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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 SetOnlineChatUsersTmp(sm SessionManager) XMessage {
  114. snacPayloadOut := oscar.SNAC_0x0E_0x03_ChatUsersJoined{}
  115. sessions := sm.Participants()
  116. for _, uSess := range sessions {
  117. snacPayloadOut.Users = append(snacPayloadOut.Users, oscar.TLVUserInfo{
  118. ScreenName: uSess.ScreenName,
  119. WarningLevel: uSess.GetWarning(),
  120. TLVBlock: oscar.TLVBlock{
  121. TLVList: uSess.GetUserInfo(),
  122. },
  123. })
  124. }
  125. return XMessage{
  126. snacFrame: oscar.SnacFrame{
  127. FoodGroup: CHAT,
  128. SubGroup: ChatUsersJoined,
  129. },
  130. snacOut: snacPayloadOut,
  131. }
  132. }
  133. func AlertUserJoined(sess *Session, sm SessionManager) {
  134. sm.BroadcastExcept(sess, XMessage{
  135. snacFrame: oscar.SnacFrame{
  136. FoodGroup: CHAT,
  137. SubGroup: ChatUsersJoined,
  138. },
  139. snacOut: oscar.SNAC_0x0E_0x03_ChatUsersJoined{
  140. Users: []oscar.TLVUserInfo{
  141. {
  142. ScreenName: sess.ScreenName,
  143. WarningLevel: sess.GetWarning(),
  144. TLVBlock: oscar.TLVBlock{
  145. TLVList: sess.GetUserInfo(),
  146. },
  147. },
  148. },
  149. },
  150. })
  151. }
  152. func AlertUserLeft(sess *Session, sm SessionManager) {
  153. sm.BroadcastExcept(sess, XMessage{
  154. snacFrame: oscar.SnacFrame{
  155. FoodGroup: CHAT,
  156. SubGroup: ChatUsersLeft,
  157. },
  158. snacOut: oscar.SNAC_0x0E_0x04_ChatUsersLeft{
  159. Users: []oscar.TLVUserInfo{
  160. {
  161. ScreenName: sess.ScreenName,
  162. WarningLevel: sess.GetWarning(),
  163. TLVBlock: oscar.TLVBlock{
  164. TLVList: sess.GetUserInfo(),
  165. },
  166. },
  167. },
  168. },
  169. })
  170. }
  171. func SendChatRoomInfoUpdate(room ChatRoom, w io.Writer, sequence *uint32) error {
  172. snacFrameOut := oscar.SnacFrame{
  173. FoodGroup: CHAT,
  174. SubGroup: ChatRoomInfoUpdate,
  175. }
  176. snacPayloadOut := oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate{
  177. Exchange: 4,
  178. Cookie: room.Cookie,
  179. InstanceNumber: 100,
  180. DetailLevel: 2,
  181. TLVBlock: oscar.TLVBlock{
  182. TLVList: room.TLVList(),
  183. },
  184. }
  185. return writeOutSNAC(oscar.SnacFrame{}, snacFrameOut, snacPayloadOut, sequence, w)
  186. }
  187. func SendChatRoomInfoUpdateTmp(room ChatRoom) XMessage {
  188. return XMessage{
  189. snacFrame: oscar.SnacFrame{
  190. FoodGroup: CHAT,
  191. SubGroup: ChatRoomInfoUpdate,
  192. },
  193. snacOut: oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate{
  194. Exchange: 4,
  195. Cookie: room.Cookie,
  196. InstanceNumber: 100,
  197. DetailLevel: 2,
  198. TLVBlock: oscar.TLVBlock{
  199. TLVList: room.TLVList(),
  200. },
  201. },
  202. }
  203. }