buddy.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. package server
  2. import (
  3. "io"
  4. "github.com/mkaminski/goaim/oscar"
  5. )
  6. type BuddyHandler interface {
  7. RightsQueryHandler() XMessage
  8. }
  9. func NewBuddyRouter() BuddyRouter {
  10. return BuddyRouter{
  11. BuddyHandler: BuddyService{},
  12. }
  13. }
  14. type BuddyRouter struct {
  15. BuddyHandler
  16. }
  17. func (rt *BuddyRouter) RouteBuddy(SNACFrame oscar.SnacFrame, r io.Reader, w io.Writer, sequence *uint32) error {
  18. switch SNACFrame.SubGroup {
  19. case oscar.BuddyRightsQuery:
  20. inSNAC := oscar.SNAC_0x03_0x02_BuddyRightsQuery{}
  21. if err := oscar.Unmarshal(&inSNAC, r); err != nil {
  22. return err
  23. }
  24. outSNAC := rt.RightsQueryHandler()
  25. return writeOutSNAC(SNACFrame, outSNAC.snacFrame, outSNAC.snacOut, sequence, w)
  26. default:
  27. return ErrUnsupportedSubGroup
  28. }
  29. }
  30. type BuddyService struct {
  31. }
  32. func (s BuddyService) RightsQueryHandler() XMessage {
  33. return XMessage{
  34. snacFrame: oscar.SnacFrame{
  35. FoodGroup: oscar.BUDDY,
  36. SubGroup: oscar.BuddyRightsReply,
  37. },
  38. snacOut: oscar.SNAC_0x03_0x03_BuddyRightsReply{
  39. TLVRestBlock: oscar.TLVRestBlock{
  40. TLVList: oscar.TLVList{
  41. {
  42. TType: 0x01,
  43. Val: uint16(100),
  44. },
  45. {
  46. TType: 0x02,
  47. Val: uint16(100),
  48. },
  49. {
  50. TType: 0x03,
  51. Val: uint16(100),
  52. },
  53. {
  54. TType: 0x04,
  55. Val: uint16(100),
  56. },
  57. },
  58. },
  59. },
  60. }
  61. }
  62. func BroadcastArrival(sess *Session, sm SessionManager, fm FeedbagManager) error {
  63. screenNames, err := fm.InterestedUsers(sess.ScreenName)
  64. if err != nil {
  65. return err
  66. }
  67. sm.BroadcastToScreenNames(screenNames, XMessage{
  68. snacFrame: oscar.SnacFrame{
  69. FoodGroup: oscar.BUDDY,
  70. SubGroup: oscar.BuddyArrived,
  71. },
  72. snacOut: oscar.SNAC_0x03_0x0A_BuddyArrived{
  73. TLVUserInfo: oscar.TLVUserInfo{
  74. ScreenName: sess.ScreenName,
  75. WarningLevel: sess.GetWarning(),
  76. TLVBlock: oscar.TLVBlock{
  77. TLVList: sess.GetUserInfo(),
  78. },
  79. },
  80. },
  81. })
  82. return nil
  83. }
  84. func BroadcastDeparture(sess *Session, sm SessionManager, fm *FeedbagStore) error {
  85. screenNames, err := fm.InterestedUsers(sess.ScreenName)
  86. if err != nil {
  87. return err
  88. }
  89. sm.BroadcastToScreenNames(screenNames, XMessage{
  90. snacFrame: oscar.SnacFrame{
  91. FoodGroup: oscar.BUDDY,
  92. SubGroup: oscar.BuddyDeparted,
  93. },
  94. snacOut: oscar.SNAC_0x03_0x0B_BuddyDeparted{
  95. TLVUserInfo: oscar.TLVUserInfo{
  96. ScreenName: sess.ScreenName,
  97. WarningLevel: sess.GetWarning(),
  98. },
  99. },
  100. })
  101. return nil
  102. }
  103. func UnicastArrival(srcScreenName, destScreenName string, sm SessionManager) error {
  104. sess, err := sm.RetrieveByScreenName(srcScreenName)
  105. switch {
  106. case err != nil:
  107. return err
  108. case sess.Invisible(): // don't tell user this buddy is online
  109. return nil
  110. }
  111. sm.SendToScreenName(destScreenName, XMessage{
  112. snacFrame: oscar.SnacFrame{
  113. FoodGroup: oscar.BUDDY,
  114. SubGroup: oscar.BuddyArrived,
  115. },
  116. snacOut: oscar.SNAC_0x03_0x0A_BuddyArrived{
  117. TLVUserInfo: sess.GetTLVUserInfo(),
  118. },
  119. })
  120. return nil
  121. }
  122. func UnicastDeparture(srcScreenName, destScreenName string, sm SessionManager) error {
  123. sess, err := sm.RetrieveByScreenName(srcScreenName)
  124. switch {
  125. case err != nil:
  126. return err
  127. case sess.Invisible(): // don't tell user this buddy is online
  128. return nil
  129. }
  130. sm.SendToScreenName(destScreenName, XMessage{
  131. snacFrame: oscar.SnacFrame{
  132. FoodGroup: oscar.BUDDY,
  133. SubGroup: oscar.BuddyDeparted,
  134. },
  135. snacOut: oscar.SNAC_0x03_0x0B_BuddyDeparted{
  136. TLVUserInfo: oscar.TLVUserInfo{
  137. // don't include the TLV block, otherwise the AIM client fails
  138. // to process the block event
  139. ScreenName: sess.ScreenName,
  140. WarningLevel: sess.GetWarning(),
  141. },
  142. },
  143. })
  144. return nil
  145. }