buddy.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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. oscar.NewTLV(0x01, uint16(100)),
  42. oscar.NewTLV(0x02, uint16(100)),
  43. oscar.NewTLV(0x03, uint16(100)),
  44. oscar.NewTLV(0x04, uint16(100)),
  45. },
  46. },
  47. },
  48. }
  49. }
  50. func BroadcastArrival(sess *Session, sm SessionManager, fm FeedbagManager) error {
  51. screenNames, err := fm.InterestedUsers(sess.ScreenName)
  52. if err != nil {
  53. return err
  54. }
  55. sm.BroadcastToScreenNames(screenNames, XMessage{
  56. snacFrame: oscar.SnacFrame{
  57. FoodGroup: oscar.BUDDY,
  58. SubGroup: oscar.BuddyArrived,
  59. },
  60. snacOut: oscar.SNAC_0x03_0x0A_BuddyArrived{
  61. TLVUserInfo: oscar.TLVUserInfo{
  62. ScreenName: sess.ScreenName,
  63. WarningLevel: sess.GetWarning(),
  64. TLVBlock: oscar.TLVBlock{
  65. TLVList: sess.GetUserInfo(),
  66. },
  67. },
  68. },
  69. })
  70. return nil
  71. }
  72. func BroadcastDeparture(sess *Session, sm SessionManager, fm *FeedbagStore) error {
  73. screenNames, err := fm.InterestedUsers(sess.ScreenName)
  74. if err != nil {
  75. return err
  76. }
  77. sm.BroadcastToScreenNames(screenNames, XMessage{
  78. snacFrame: oscar.SnacFrame{
  79. FoodGroup: oscar.BUDDY,
  80. SubGroup: oscar.BuddyDeparted,
  81. },
  82. snacOut: oscar.SNAC_0x03_0x0B_BuddyDeparted{
  83. TLVUserInfo: oscar.TLVUserInfo{
  84. ScreenName: sess.ScreenName,
  85. WarningLevel: sess.GetWarning(),
  86. },
  87. },
  88. })
  89. return nil
  90. }
  91. func UnicastArrival(srcScreenName, destScreenName string, sm SessionManager) error {
  92. sess, err := sm.RetrieveByScreenName(srcScreenName)
  93. switch {
  94. case err != nil:
  95. return err
  96. case sess.Invisible(): // don't tell user this buddy is online
  97. return nil
  98. }
  99. sm.SendToScreenName(destScreenName, XMessage{
  100. snacFrame: oscar.SnacFrame{
  101. FoodGroup: oscar.BUDDY,
  102. SubGroup: oscar.BuddyArrived,
  103. },
  104. snacOut: oscar.SNAC_0x03_0x0A_BuddyArrived{
  105. TLVUserInfo: sess.GetTLVUserInfo(),
  106. },
  107. })
  108. return nil
  109. }
  110. func UnicastDeparture(srcScreenName, destScreenName string, sm SessionManager) error {
  111. sess, err := sm.RetrieveByScreenName(srcScreenName)
  112. switch {
  113. case err != nil:
  114. return err
  115. case sess.Invisible(): // don't tell user this buddy is online
  116. return nil
  117. }
  118. sm.SendToScreenName(destScreenName, XMessage{
  119. snacFrame: oscar.SnacFrame{
  120. FoodGroup: oscar.BUDDY,
  121. SubGroup: oscar.BuddyDeparted,
  122. },
  123. snacOut: oscar.SNAC_0x03_0x0B_BuddyDeparted{
  124. TLVUserInfo: oscar.TLVUserInfo{
  125. // don't include the TLV block, otherwise the AIM client fails
  126. // to process the block event
  127. ScreenName: sess.ScreenName,
  128. WarningLevel: sess.GetWarning(),
  129. },
  130. },
  131. })
  132. return nil
  133. }