chat.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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(
  48. oscar.NewTLV(oscar.ChatTLVSenderInformation, oscar.TLVUserInfo{
  49. ScreenName: sess.ScreenName,
  50. WarningLevel: sess.GetWarning(),
  51. TLVBlock: oscar.TLVBlock{
  52. TLVList: sess.GetUserInfo(),
  53. },
  54. }),
  55. )
  56. // send message to all the participants except sender
  57. sm.BroadcastExcept(sess, XMessage{
  58. snacFrame: snacFrameOut,
  59. snacOut: snacPayloadOut,
  60. })
  61. var ret *XMessage
  62. if _, ackMsg := snacPayloadIn.GetTLV(oscar.ChatTLVEnableReflectionFlag); ackMsg {
  63. // reflect the message back to the sender
  64. ret = &XMessage{
  65. snacFrame: snacFrameOut,
  66. snacOut: snacPayloadOut,
  67. }
  68. }
  69. return ret, nil
  70. }
  71. func SetOnlineChatUsers(sess *Session, sm SessionManager) {
  72. snacPayloadOut := oscar.SNAC_0x0E_0x03_ChatUsersJoined{}
  73. sessions := sm.Participants()
  74. for _, uSess := range sessions {
  75. snacPayloadOut.Users = append(snacPayloadOut.Users, oscar.TLVUserInfo{
  76. ScreenName: uSess.ScreenName,
  77. WarningLevel: uSess.GetWarning(),
  78. TLVBlock: oscar.TLVBlock{
  79. TLVList: uSess.GetUserInfo(),
  80. },
  81. })
  82. }
  83. sm.SendToScreenName(sess.ScreenName, XMessage{
  84. snacFrame: oscar.SnacFrame{
  85. FoodGroup: oscar.CHAT,
  86. SubGroup: oscar.ChatUsersJoined,
  87. },
  88. snacOut: snacPayloadOut,
  89. })
  90. }
  91. func AlertUserJoined(sess *Session, sm SessionManager) {
  92. sm.BroadcastExcept(sess, XMessage{
  93. snacFrame: oscar.SnacFrame{
  94. FoodGroup: oscar.CHAT,
  95. SubGroup: oscar.ChatUsersJoined,
  96. },
  97. snacOut: oscar.SNAC_0x0E_0x03_ChatUsersJoined{
  98. Users: []oscar.TLVUserInfo{
  99. {
  100. ScreenName: sess.ScreenName,
  101. WarningLevel: sess.GetWarning(),
  102. TLVBlock: oscar.TLVBlock{
  103. TLVList: sess.GetUserInfo(),
  104. },
  105. },
  106. },
  107. },
  108. })
  109. }
  110. func AlertUserLeft(sess *Session, sm SessionManager) {
  111. sm.BroadcastExcept(sess, XMessage{
  112. snacFrame: oscar.SnacFrame{
  113. FoodGroup: oscar.CHAT,
  114. SubGroup: oscar.ChatUsersLeft,
  115. },
  116. snacOut: oscar.SNAC_0x0E_0x04_ChatUsersLeft{
  117. Users: []oscar.TLVUserInfo{
  118. {
  119. ScreenName: sess.ScreenName,
  120. WarningLevel: sess.GetWarning(),
  121. TLVBlock: oscar.TLVBlock{
  122. TLVList: sess.GetUserInfo(),
  123. },
  124. },
  125. },
  126. },
  127. })
  128. }
  129. func SendChatRoomInfoUpdate(sess *Session, sm SessionManager, room ChatRoom) {
  130. sm.SendToScreenName(sess.ScreenName, XMessage{
  131. snacFrame: oscar.SnacFrame{
  132. FoodGroup: oscar.CHAT,
  133. SubGroup: oscar.ChatRoomInfoUpdate,
  134. },
  135. snacOut: oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate{
  136. Exchange: 4,
  137. Cookie: room.Cookie,
  138. InstanceNumber: 100,
  139. DetailLevel: 2,
  140. TLVBlock: oscar.TLVBlock{
  141. TLVList: room.TLVList(),
  142. },
  143. },
  144. })
  145. }