Skip to content

Commit

Permalink
Mgmt api improvements
Browse files Browse the repository at this point in the history
Allow for fetching additional account, session, and buddy icon data using the mgmt api

Centralize fetching of buddy icon BART items
  • Loading branch information
jgknight committed Aug 29, 2024
1 parent dece73f commit d369eb4
Show file tree
Hide file tree
Showing 8 changed files with 407 additions and 143 deletions.
116 changes: 116 additions & 0 deletions api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,66 @@ paths:
'404':
description: User not found.

/user/{screenname}/account:
get:
summary: Get account details for a specific screen name.
description: Retrieve account details for a specific screen name.
parameters:
- name: screenname
in: path
description: User's AIM screen name or ICQ UIN.
required: true
type: string
responses:
'200':
description: Successful response containing account details
content:
application/json:
schema:
type: object
properties:
id:
type: string
description: User's unique identifier.
screen_name:
type: string
description: User's AIM screen name or ICQ UIN.
profile:
type: string
description: User's AIM profile HTML.
email_address:
type: string
description: User's email address
confirmed:
type: bool
description: User's account confirmation status
is_icq:
type: boolean
description: If true, indicates an ICQ user instead of an AIM user.
'404':
description: User not found.

/user/{screenname}/icon:
get:
summary: Get AIM buddy icon for a screen name
description: Retrieve account buddy icon for a specific screen name.
parameters:
- name: screenname
in: path
description: User's AIM screen name or ICQ UIN.
required: true
type: string
responses:
'200':
description: Successful response containing buddy icon bytes
content:
image/gif:
schema:
type: string
format: binary
'404':
description: User not found, or user has no buddy icon

/session:
get:
summary: Get active sessions
Expand All @@ -98,10 +158,66 @@ paths:
screen_name:
type: string
description: User's AIM screen name or ICQ UIN.
online_seconds:
type: float
description: Number of seconds this user session has been online.
away_message:
type: string
description: User's AIM away message HTML. Empty if the user is not away.
idle_seconds:
type: float
description: Number of seconds this user session has been idle. 0 if not idle.
is_icq:
type: boolean
description: If true, indicates an ICQ user instead of an AIM user.

/session/{screenname}:
get:
summary: Get active sessions for a given screen name or UIN.
description: Retrieve a list of active sessions of a specific logged in user.
parameters:
- name: screenname
in: path
description: User's AIM screen name or ICQ UIN.
required: true
type: string
responses:
'200':
description: Successful response containing a list of active sessions for the given screen name
content:
application/json:
schema:
type: object
properties:
count:
type: integer
description: The number of active sessions.
sessions:
type: array
items:
type: object
properties:
id:
type: string
description: User's unique identifier.
screen_name:
type: string
description: User's AIM screen name or ICQ UIN.
online_seconds:
type: float
description: Number of seconds this user session has been online.
away_message:
type: string
description: User's AIM away message HTML. Empty if the user is not away.
idle_seconds:
type: float
description: Number of seconds this user session has been idle. 0 if not idle.
is_icq:
type: boolean
description: If true, indicates an ICQ user instead of an AIM user.
'404':
description: User not found.

/user/password:
put:
summary: Set a user's password
Expand Down
2 changes: 1 addition & 1 deletion cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func main() {
wg.Add(7)

go func() {
http.StartManagementAPI(cfg, feedbagStore, sessionManager, feedbagStore, feedbagStore, chatSessionManager, sessionManager, logger)
http.StartManagementAPI(cfg, feedbagStore, sessionManager, feedbagStore, feedbagStore, chatSessionManager, sessionManager, feedbagStore, feedbagStore, feedbagStore, feedbagStore, logger)
wg.Done()
}()
go func(logger *slog.Logger) {
Expand Down
61 changes: 2 additions & 59 deletions foodgroup/buddy.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package foodgroup

import (
"bytes"
"context"
"errors"
"strconv"

"github.com/mk6i/retro-aim-server/state"
"github.com/mk6i/retro-aim-server/wire"
Expand Down Expand Up @@ -87,7 +84,7 @@ func (s BuddyService) DelBuddies(_ context.Context, sess *state.Session, inBody
// buddy icons, warning levels, invisibility status, etc.
func (s BuddyService) UnicastBuddyArrived(ctx context.Context, from *state.Session, to *state.Session) error {
userInfo := from.TLVUserInfo()
icon, err := getBuddyIconRefFromFeedbag(from, s.feedbagManager)
icon, err := s.feedbagManager.BuddyIconRefByName(from.IdentScreenName())
switch {
case err != nil:
return err
Expand Down Expand Up @@ -122,7 +119,7 @@ func (s BuddyService) BroadcastBuddyArrived(ctx context.Context, sess *state.Ses
recipients = append(recipients, legacyUsers...)

userInfo := sess.TLVUserInfo()
icon, err := getBuddyIconRefFromFeedbag(sess, s.feedbagManager)
icon, err := s.feedbagManager.BuddyIconRefByName(sess.IdentScreenName())
switch {
case err != nil:
return err
Expand All @@ -143,60 +140,6 @@ func (s BuddyService) BroadcastBuddyArrived(ctx context.Context, sess *state.Ses
return nil
}

// getBuddyIconRefFromFeedbag retrieves a reference to the user's buddy icon
// from their feedbag. If it exists, the buddy icon is the feedbag item of
// class wire.FeedbagClassIdBart with BART type wire.BARTTypesBuddyIcon.
func getBuddyIconRefFromFeedbag(sess *state.Session, feedbagManager FeedbagManager) (*wire.BARTID, error) {
items, err := feedbagManager.Feedbag(sess.IdentScreenName())
if err != nil {
return nil, err
}

for _, item := range items {
if item.ClassID != wire.FeedbagClassIdBart {
continue
}
bartType, err := extractBARTItemType(item)
if err != nil {
return nil, err
}
if bartType != wire.BARTTypesBuddyIcon {
continue
}
b, hasBuf := item.Slice(wire.FeedbagAttributesBartInfo)
if !hasBuf {
return nil, errors.New("unable to extract icon payload")
}
bartInfo := wire.BARTInfo{}
if err := wire.UnmarshalBE(&bartInfo, bytes.NewBuffer(b)); err != nil {
return nil, err
}
return &wire.BARTID{
Type: bartType,
BARTInfo: wire.BARTInfo{
Flags: bartInfo.Flags,
Hash: bartInfo.Hash,
},
}, nil
}

return nil, nil
}

// extractBARTItemType gets the BART type for item, which is stored in the
// "name" field.
func extractBARTItemType(item wire.FeedbagItem) (uint16, error) {
var bartType uint16
// Feedbag items of type wire.FeedbagClassIdBart store the BART type in the
// name field.
if bt, err := strconv.ParseUint(item.Name, 10, 16); err != nil {
return 0, err
} else {
bartType = uint16(bt)
}
return bartType, nil
}

func (s BuddyService) BroadcastBuddyDeparted(ctx context.Context, sess *state.Session) error {
recipients, err := s.feedbagManager.AdjacentUsers(sess.IdentScreenName())
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions foodgroup/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type FeedbagManager interface {
FeedbagLastModified(screenName state.IdentScreenName) (time.Time, error)
Feedbag(screenName state.IdentScreenName) ([]wire.FeedbagItem, error)
FeedbagUpsert(screenName state.IdentScreenName, items []wire.FeedbagItem) error
BuddyIconRefByName(screenName state.IdentScreenName) (*wire.BARTID, error)
}

// LegacyBuddyListManager defines operations for tracking user relationships
Expand Down
Loading

0 comments on commit d369eb4

Please sign in to comment.