aim-oscar-server/online_routine.go

80 lines
2.5 KiB
Go
Raw Normal View History

2021-12-19 01:14:25 -05:00
package main
import (
"aim-oscar/models"
"aim-oscar/oscar"
"aim-oscar/util"
"context"
"log"
"time"
"github.com/uptrace/bun"
)
2021-12-24 12:41:16 -05:00
func OnlineNotification(sm *SessionManager) (chan *models.User, routineFn) {
2021-12-19 01:14:25 -05:00
commCh := make(chan *models.User, 1)
routine := func(db *bun.DB) {
log.Printf("online notification starting up")
for {
user, more := <-commCh
if !more {
log.Printf("online notification routine shutting down")
return
}
2021-12-19 17:17:47 -05:00
if user.Status == models.UserStatusOnline {
log.Printf("%s is now online", user.Username)
} else if user.Status == models.UserStatusAway {
log.Printf("%s is now away", user.Username)
}
2021-12-19 01:14:25 -05:00
2021-12-19 17:17:47 -05:00
ctx := context.Background()
2021-12-19 01:14:25 -05:00
2021-12-19 17:17:47 -05:00
// Find buddies who are friends with the user
var buddies []*models.Buddy
err := db.NewSelect().Model(&buddies).Where("with_uin = ?", user.UIN).Relation("Source").Scan(ctx, &buddies)
if err != nil {
log.Printf("could not find user's buddies: %s", err.Error())
return
}
2021-12-19 01:14:25 -05:00
2021-12-19 17:17:47 -05:00
for _, buddy := range buddies {
if buddy.Source.Status == models.UserStatusAway || buddy.Source.Status == models.UserStatusDnd {
continue
}
log.Printf("telling %s that %s has a new status: %d!", buddy.Source.Username, user.Username, user.Status)
2021-12-19 01:14:25 -05:00
2021-12-24 12:41:16 -05:00
if s := sm.GetSession(buddy.Source.Username); s != nil {
2021-12-19 17:17:47 -05:00
onlineSnac := oscar.NewSNAC(3, 0xb)
onlineSnac.Data.WriteLPString(user.Username)
onlineSnac.Data.WriteUint16(0) // TODO: user warning level
2021-12-19 01:14:25 -05:00
2021-12-19 17:17:47 -05:00
tlvs := []*oscar.TLV{
2021-12-24 13:38:22 -05:00
oscar.NewTLV(1, util.Word(0)), // TODO: user class
oscar.NewTLV(0x06, util.Dword(uint32(user.Status))), // TODO: User Status
// oscar.NewTLV(0x0a, util.Dword(binary.BigEndian.Uint32([]byte(OSCAR_HOST)))), // TODO: External IP of the client?
2021-12-19 17:17:47 -05:00
oscar.NewTLV(0x0f, util.Dword(uint32(time.Since(user.LastActivityAt).Seconds()))), // Idle Time
oscar.NewTLV(0x03, util.Dword(uint32(time.Now().Unix()))), // Client Signon Time
oscar.NewTLV(0x05, util.Dword(uint32(user.CreatedAt.Unix()))), // Member since
2021-12-19 01:14:25 -05:00
}
2021-12-19 17:17:47 -05:00
onlineSnac.Data.WriteUint16(uint16(len(tlvs)))
for _, tlv := range tlvs {
onlineSnac.Data.WriteBinary(tlv)
}
2021-12-19 01:14:25 -05:00
2021-12-19 17:17:47 -05:00
onlineFlap := oscar.NewFLAP(2)
onlineFlap.Data.WriteBinary(onlineSnac)
if err := s.Send(onlineFlap); err != nil {
log.Printf("could not tell %s that %s is online", buddy.Source.Username, user.Username)
2021-12-19 01:14:25 -05:00
}
}
}
}
}
return commCh, routine
}