buddy.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package handler
  2. import (
  3. "context"
  4. "github.com/mkaminski/goaim/oscar"
  5. "github.com/mkaminski/goaim/state"
  6. )
  7. func NewBuddyService() *BuddyService {
  8. return &BuddyService{}
  9. }
  10. type BuddyService struct {
  11. }
  12. func (s BuddyService) RightsQueryHandler(_ context.Context, frameIn oscar.SNACFrame) oscar.SNACMessage {
  13. return oscar.SNACMessage{
  14. Frame: oscar.SNACFrame{
  15. FoodGroup: oscar.Buddy,
  16. SubGroup: oscar.BuddyRightsReply,
  17. RequestID: frameIn.RequestID,
  18. },
  19. Body: oscar.SNAC_0x03_0x03_BuddyRightsReply{
  20. TLVRestBlock: oscar.TLVRestBlock{
  21. TLVList: oscar.TLVList{
  22. oscar.NewTLV(0x01, uint16(100)),
  23. oscar.NewTLV(0x02, uint16(100)),
  24. oscar.NewTLV(0x03, uint16(100)),
  25. oscar.NewTLV(0x04, uint16(100)),
  26. },
  27. },
  28. },
  29. }
  30. }
  31. func broadcastArrival(ctx context.Context, sess *state.Session, messageRelayer MessageRelayer, feedbagManager FeedbagManager) error {
  32. screenNames, err := feedbagManager.InterestedUsers(sess.ScreenName())
  33. if err != nil {
  34. return err
  35. }
  36. messageRelayer.BroadcastToScreenNames(ctx, screenNames, oscar.SNACMessage{
  37. Frame: oscar.SNACFrame{
  38. FoodGroup: oscar.Buddy,
  39. SubGroup: oscar.BuddyArrived,
  40. },
  41. Body: oscar.SNAC_0x03_0x0B_BuddyArrived{
  42. TLVUserInfo: sess.TLVUserInfo(),
  43. },
  44. })
  45. return nil
  46. }
  47. func broadcastDeparture(ctx context.Context, sess *state.Session, messageRelayer MessageRelayer, feedbagManager FeedbagManager) error {
  48. screenNames, err := feedbagManager.InterestedUsers(sess.ScreenName())
  49. if err != nil {
  50. return err
  51. }
  52. messageRelayer.BroadcastToScreenNames(ctx, screenNames, oscar.SNACMessage{
  53. Frame: oscar.SNACFrame{
  54. FoodGroup: oscar.Buddy,
  55. SubGroup: oscar.BuddyDeparted,
  56. },
  57. Body: oscar.SNAC_0x03_0x0C_BuddyDeparted{
  58. TLVUserInfo: oscar.TLVUserInfo{
  59. // don't include the TLV block, otherwise the AIM client fails
  60. // to process the block event
  61. ScreenName: sess.ScreenName(),
  62. WarningLevel: sess.Warning(),
  63. },
  64. },
  65. })
  66. return nil
  67. }
  68. func unicastArrival(ctx context.Context, srcScreenName, destScreenName string, messageRelayer MessageRelayer) {
  69. sess := messageRelayer.RetrieveByScreenName(srcScreenName)
  70. switch {
  71. case sess == nil:
  72. fallthrough
  73. case sess.Invisible(): // don't tell user this buddy is online
  74. return
  75. }
  76. messageRelayer.SendToScreenName(ctx, destScreenName, oscar.SNACMessage{
  77. Frame: oscar.SNACFrame{
  78. FoodGroup: oscar.Buddy,
  79. SubGroup: oscar.BuddyArrived,
  80. },
  81. Body: oscar.SNAC_0x03_0x0B_BuddyArrived{
  82. TLVUserInfo: sess.TLVUserInfo(),
  83. },
  84. })
  85. }
  86. func unicastDeparture(ctx context.Context, srcScreenName, destScreenName string, messageRelayer MessageRelayer) {
  87. sess := messageRelayer.RetrieveByScreenName(srcScreenName)
  88. switch {
  89. case sess == nil:
  90. fallthrough
  91. case sess.Invisible(): // don't tell user this buddy is online
  92. return
  93. }
  94. messageRelayer.SendToScreenName(ctx, destScreenName, oscar.SNACMessage{
  95. Frame: oscar.SNACFrame{
  96. FoodGroup: oscar.Buddy,
  97. SubGroup: oscar.BuddyDeparted,
  98. },
  99. Body: oscar.SNAC_0x03_0x0C_BuddyDeparted{
  100. TLVUserInfo: oscar.TLVUserInfo{
  101. // don't include the TLV block, otherwise the AIM client fails
  102. // to process the block event
  103. ScreenName: sess.ScreenName(),
  104. WarningLevel: sess.Warning(),
  105. },
  106. },
  107. })
  108. }