chat_nav.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. package server
  2. import (
  3. "errors"
  4. "github.com/google/uuid"
  5. "github.com/mkaminski/goaim/oscar"
  6. "io"
  7. "time"
  8. )
  9. type ChatNavHandler interface {
  10. CreateRoomHandler(sess *Session, cr *ChatRegistry, newChatRoom ChatRoomFactory, snacPayloadIn oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate) (XMessage, error)
  11. RequestChatRightsHandler() XMessage
  12. RequestRoomInfoHandler(cr *ChatRegistry, snacPayloadIn oscar.SNAC_0x0D_0x04_ChatNavRequestRoomInfo) (XMessage, error)
  13. }
  14. func NewChatNavRouter() ChatNavRouter {
  15. return ChatNavRouter{
  16. ChatNavHandler: ChatNavService{},
  17. }
  18. }
  19. type ChatNavRouter struct {
  20. ChatNavHandler
  21. }
  22. func (rt *ChatNavRouter) RouteChatNav(sess *Session, cr *ChatRegistry, SNACFrame oscar.SnacFrame, r io.Reader, w io.Writer, sequence *uint32) error {
  23. switch SNACFrame.SubGroup {
  24. case oscar.ChatNavRequestChatRights:
  25. outSNAC := rt.RequestChatRightsHandler()
  26. return writeOutSNAC(SNACFrame, outSNAC.snacFrame, outSNAC.snacOut, sequence, w)
  27. case oscar.ChatNavRequestRoomInfo:
  28. inSNAC := oscar.SNAC_0x0D_0x04_ChatNavRequestRoomInfo{}
  29. if err := oscar.Unmarshal(&inSNAC, r); err != nil {
  30. return err
  31. }
  32. outSNAC, err := rt.RequestRoomInfoHandler(cr, inSNAC)
  33. if err != nil {
  34. return err
  35. }
  36. return writeOutSNAC(SNACFrame, outSNAC.snacFrame, outSNAC.snacOut, sequence, w)
  37. case oscar.ChatNavCreateRoom:
  38. snacPayloadIn := oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate{}
  39. if err := oscar.Unmarshal(&snacPayloadIn, r); err != nil {
  40. return err
  41. }
  42. outSNAC, err := rt.CreateRoomHandler(sess, cr, NewChatRoom, snacPayloadIn)
  43. if err != nil {
  44. return err
  45. }
  46. return writeOutSNAC(SNACFrame, outSNAC.snacFrame, outSNAC.snacOut, sequence, w)
  47. default:
  48. return ErrUnsupportedSubGroup
  49. }
  50. }
  51. type ChatNavService struct {
  52. }
  53. type ChatCookie struct {
  54. Cookie []byte `len_prefix:"uint16"`
  55. SessID string `len_prefix:"uint16"`
  56. }
  57. func (s ChatNavService) RequestChatRightsHandler() XMessage {
  58. return XMessage{
  59. snacFrame: oscar.SnacFrame{
  60. FoodGroup: oscar.CHAT_NAV,
  61. SubGroup: oscar.ChatNavNavInfo,
  62. },
  63. snacOut: oscar.SNAC_0x0D_0x09_ChatNavNavInfo{
  64. TLVRestBlock: oscar.TLVRestBlock{
  65. TLVList: oscar.TLVList{
  66. {
  67. TType: 0x02,
  68. Val: uint8(10),
  69. },
  70. {
  71. TType: 0x03,
  72. Val: oscar.SNAC_0x0D_0x09_TLVExchangeInfo{
  73. Identifier: 4,
  74. TLVBlock: oscar.TLVBlock{
  75. TLVList: oscar.TLVList{
  76. {
  77. TType: 0x0002,
  78. Val: uint16(0x0010),
  79. },
  80. {
  81. TType: 0x00c9,
  82. Val: uint16(15),
  83. },
  84. {
  85. TType: 0x00d3,
  86. Val: "default Exchange",
  87. },
  88. {
  89. TType: 0x00d5,
  90. Val: uint8(2),
  91. },
  92. {
  93. TType: 0xd6,
  94. Val: "us-ascii",
  95. },
  96. {
  97. TType: 0xd7,
  98. Val: "en",
  99. },
  100. {
  101. TType: 0xd8,
  102. Val: "us-ascii",
  103. },
  104. {
  105. TType: 0xd9,
  106. Val: "en",
  107. },
  108. },
  109. },
  110. },
  111. },
  112. },
  113. },
  114. },
  115. }
  116. }
  117. func NewChatRoom() ChatRoom {
  118. return ChatRoom{
  119. Cookie: uuid.New().String(),
  120. CreateTime: time.Now(),
  121. SessionManager: NewSessionManager(),
  122. }
  123. }
  124. type ChatRoomFactory func() ChatRoom
  125. func (s ChatNavService) CreateRoomHandler(sess *Session, cr *ChatRegistry, newChatRoom ChatRoomFactory, snacPayloadIn oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate) (XMessage, error) {
  126. name, hasName := snacPayloadIn.GetString(oscar.ChatTLVRoomName)
  127. if !hasName {
  128. return XMessage{}, errors.New("unable to find chat name")
  129. }
  130. room := newChatRoom()
  131. room.DetailLevel = snacPayloadIn.DetailLevel
  132. room.Exchange = snacPayloadIn.Exchange
  133. room.InstanceNumber = snacPayloadIn.InstanceNumber
  134. room.Name = name
  135. cr.Register(room)
  136. // add user to chat room
  137. room.NewSessionWithSN(sess.ID, sess.ScreenName)
  138. return XMessage{
  139. snacFrame: oscar.SnacFrame{
  140. FoodGroup: oscar.CHAT_NAV,
  141. SubGroup: oscar.ChatNavNavInfo,
  142. },
  143. snacOut: oscar.SNAC_0x0D_0x09_ChatNavNavInfo{
  144. TLVRestBlock: oscar.TLVRestBlock{
  145. TLVList: oscar.TLVList{
  146. {
  147. TType: oscar.ChatNavTLVRoomInfo,
  148. Val: oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate{
  149. Exchange: snacPayloadIn.Exchange,
  150. Cookie: room.Cookie,
  151. InstanceNumber: snacPayloadIn.InstanceNumber,
  152. DetailLevel: snacPayloadIn.DetailLevel,
  153. TLVBlock: oscar.TLVBlock{
  154. TLVList: room.TLVList(),
  155. },
  156. },
  157. },
  158. },
  159. },
  160. },
  161. }, nil
  162. }
  163. func (s ChatNavService) RequestRoomInfoHandler(cr *ChatRegistry, snacPayloadIn oscar.SNAC_0x0D_0x04_ChatNavRequestRoomInfo) (XMessage, error) {
  164. room, err := cr.Retrieve(string(snacPayloadIn.Cookie))
  165. if err != nil {
  166. return XMessage{}, err
  167. }
  168. return XMessage{
  169. snacFrame: oscar.SnacFrame{
  170. FoodGroup: oscar.CHAT_NAV,
  171. SubGroup: oscar.ChatNavNavInfo,
  172. },
  173. snacOut: oscar.SNAC_0x0D_0x09_ChatNavNavInfo{
  174. TLVRestBlock: oscar.TLVRestBlock{
  175. TLVList: oscar.TLVList{
  176. {
  177. TType: 0x04,
  178. Val: oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate{
  179. Exchange: 4,
  180. Cookie: room.Cookie,
  181. InstanceNumber: 100,
  182. DetailLevel: 2,
  183. TLVBlock: oscar.TLVBlock{
  184. TLVList: room.TLVList(),
  185. },
  186. },
  187. },
  188. },
  189. },
  190. },
  191. }, nil
  192. }