|
@@ -3,30 +3,24 @@ package handler
|
|
|
import (
|
|
import (
|
|
|
"context"
|
|
"context"
|
|
|
"errors"
|
|
"errors"
|
|
|
|
|
+
|
|
|
"log/slog"
|
|
"log/slog"
|
|
|
- "time"
|
|
|
|
|
|
|
|
|
|
- "github.com/google/uuid"
|
|
|
|
|
"github.com/mkaminski/goaim/oscar"
|
|
"github.com/mkaminski/goaim/oscar"
|
|
|
"github.com/mkaminski/goaim/state"
|
|
"github.com/mkaminski/goaim/state"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
-func NewChatRoom() state.ChatRoom {
|
|
|
|
|
- return state.ChatRoom{
|
|
|
|
|
- Cookie: uuid.New().String(),
|
|
|
|
|
- CreateTime: time.Now(),
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func NewChatNavService(logger *slog.Logger, chatRegistry *state.ChatRegistry, newChatSessMgr func() SessionManager) *ChatNavService {
|
|
|
|
|
|
|
+// NewChatNavService creates a new instance of NewChatNavService.
|
|
|
|
|
+func NewChatNavService(logger *slog.Logger, chatRegistry *state.ChatRegistry, newChatRoom func() state.ChatRoom, newChatSessMgr func() SessionManager) *ChatNavService {
|
|
|
return &ChatNavService{
|
|
return &ChatNavService{
|
|
|
logger: logger,
|
|
logger: logger,
|
|
|
chatRegistry: chatRegistry,
|
|
chatRegistry: chatRegistry,
|
|
|
- newChatRoom: NewChatRoom,
|
|
|
|
|
|
|
+ newChatRoom: newChatRoom,
|
|
|
newChatSessMgr: newChatSessMgr,
|
|
newChatSessMgr: newChatSessMgr,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// ChatNavService provides handlers for the ChatNav food group.
|
|
|
type ChatNavService struct {
|
|
type ChatNavService struct {
|
|
|
logger *slog.Logger
|
|
logger *slog.Logger
|
|
|
chatRegistry *state.ChatRegistry
|
|
chatRegistry *state.ChatRegistry
|
|
@@ -34,6 +28,8 @@ type ChatNavService struct {
|
|
|
newChatSessMgr func() SessionManager
|
|
newChatSessMgr func() SessionManager
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// RequestChatRightsHandler returns SNAC oscar.ChatNavNavInfo, which contains
|
|
|
|
|
+// chat navigation service parameters and limits.
|
|
|
func (s ChatNavService) RequestChatRightsHandler(_ context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage {
|
|
func (s ChatNavService) RequestChatRightsHandler(_ context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage {
|
|
|
return oscar.SNACMessage{
|
|
return oscar.SNACMessage{
|
|
|
Frame: oscar.SNACFrame{
|
|
Frame: oscar.SNACFrame{
|
|
@@ -44,19 +40,19 @@ func (s ChatNavService) RequestChatRightsHandler(_ context.Context, inFrame osca
|
|
|
Body: oscar.SNAC_0x0D_0x09_ChatNavNavInfo{
|
|
Body: oscar.SNAC_0x0D_0x09_ChatNavNavInfo{
|
|
|
TLVRestBlock: oscar.TLVRestBlock{
|
|
TLVRestBlock: oscar.TLVRestBlock{
|
|
|
TLVList: oscar.TLVList{
|
|
TLVList: oscar.TLVList{
|
|
|
- oscar.NewTLV(0x02, uint8(10)),
|
|
|
|
|
- oscar.NewTLV(0x03, oscar.SNAC_0x0D_0x09_TLVExchangeInfo{
|
|
|
|
|
|
|
+ oscar.NewTLV(oscar.ChatNavTLVMaxConcurrentRooms, uint8(10)),
|
|
|
|
|
+ oscar.NewTLV(oscar.ChatNavTLVExchangeInfo, oscar.SNAC_0x0D_0x09_TLVExchangeInfo{
|
|
|
Identifier: 4,
|
|
Identifier: 4,
|
|
|
TLVBlock: oscar.TLVBlock{
|
|
TLVBlock: oscar.TLVBlock{
|
|
|
TLVList: oscar.TLVList{
|
|
TLVList: oscar.TLVList{
|
|
|
- oscar.NewTLV(0x0002, uint16(0x0010)),
|
|
|
|
|
- oscar.NewTLV(0x00c9, uint16(15)),
|
|
|
|
|
- oscar.NewTLV(0x00d3, "default Exchange"),
|
|
|
|
|
- oscar.NewTLV(0x00d5, uint8(2)),
|
|
|
|
|
- oscar.NewTLV(0xd6, "us-ascii"),
|
|
|
|
|
- oscar.NewTLV(0xd7, "en"),
|
|
|
|
|
- oscar.NewTLV(0xd8, "us-ascii"),
|
|
|
|
|
- oscar.NewTLV(0xd9, "en"),
|
|
|
|
|
|
|
+ oscar.NewTLV(oscar.ChatNavTLVClassPerms, uint16(0x0010)),
|
|
|
|
|
+ oscar.NewTLV(oscar.ChatNavTLVFlags, uint16(15)),
|
|
|
|
|
+ oscar.NewTLV(oscar.ChatNavTLVExchangeDesc, "default exchange"),
|
|
|
|
|
+ oscar.NewTLV(oscar.ChatNavTLVCreatePerms, uint8(2)),
|
|
|
|
|
+ oscar.NewTLV(oscar.ChatNavTLVCharSet1, "us-ascii"),
|
|
|
|
|
+ oscar.NewTLV(oscar.ChatNavTLVLang1, "en"),
|
|
|
|
|
+ oscar.NewTLV(oscar.ChatNavTLVCharSet2, "us-ascii"),
|
|
|
|
|
+ oscar.NewTLV(oscar.ChatNavTLVLang2, "en"),
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
}),
|
|
}),
|
|
@@ -66,6 +62,9 @@ func (s ChatNavService) RequestChatRightsHandler(_ context.Context, inFrame osca
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// CreateRoomHandler creates a chat room with the current user as the first
|
|
|
|
|
+// participant. It returns SNAC oscar.ChatNavNavInfo, which contains metadata
|
|
|
|
|
+// for the chat room.
|
|
|
func (s ChatNavService) CreateRoomHandler(_ context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate) (oscar.SNACMessage, error) {
|
|
func (s ChatNavService) CreateRoomHandler(_ context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate) (oscar.SNACMessage, error) {
|
|
|
name, hasName := inBody.GetString(oscar.ChatTLVRoomName)
|
|
name, hasName := inBody.GetString(oscar.ChatTLVRoomName)
|
|
|
if !hasName {
|
|
if !hasName {
|
|
@@ -94,7 +93,7 @@ func (s ChatNavService) CreateRoomHandler(_ context.Context, sess *state.Session
|
|
|
Body: oscar.SNAC_0x0D_0x09_ChatNavNavInfo{
|
|
Body: oscar.SNAC_0x0D_0x09_ChatNavNavInfo{
|
|
|
TLVRestBlock: oscar.TLVRestBlock{
|
|
TLVRestBlock: oscar.TLVRestBlock{
|
|
|
TLVList: oscar.TLVList{
|
|
TLVList: oscar.TLVList{
|
|
|
- oscar.NewTLV(oscar.ChatNavTLVRoomInfo, oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate{
|
|
|
|
|
|
|
+ oscar.NewTLV(oscar.ChatNavRequestRoomInfo, oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate{
|
|
|
Exchange: inBody.Exchange,
|
|
Exchange: inBody.Exchange,
|
|
|
Cookie: room.Cookie,
|
|
Cookie: room.Cookie,
|
|
|
InstanceNumber: inBody.InstanceNumber,
|
|
InstanceNumber: inBody.InstanceNumber,
|
|
@@ -109,6 +108,8 @@ func (s ChatNavService) CreateRoomHandler(_ context.Context, sess *state.Session
|
|
|
}, nil
|
|
}, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// RequestRoomInfoHandler returns oscar.ChatNavNavInfo, which contains metadata
|
|
|
|
|
+// for the chat room specified in the inFrame.Cookie.
|
|
|
func (s ChatNavService) RequestRoomInfoHandler(_ context.Context, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x0D_0x04_ChatNavRequestRoomInfo) (oscar.SNACMessage, error) {
|
|
func (s ChatNavService) RequestRoomInfoHandler(_ context.Context, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x0D_0x04_ChatNavRequestRoomInfo) (oscar.SNACMessage, error) {
|
|
|
room, _, err := s.chatRegistry.Retrieve(string(inBody.Cookie))
|
|
room, _, err := s.chatRegistry.Retrieve(string(inBody.Cookie))
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -124,11 +125,11 @@ func (s ChatNavService) RequestRoomInfoHandler(_ context.Context, inFrame oscar.
|
|
|
Body: oscar.SNAC_0x0D_0x09_ChatNavNavInfo{
|
|
Body: oscar.SNAC_0x0D_0x09_ChatNavNavInfo{
|
|
|
TLVRestBlock: oscar.TLVRestBlock{
|
|
TLVRestBlock: oscar.TLVRestBlock{
|
|
|
TLVList: oscar.TLVList{
|
|
TLVList: oscar.TLVList{
|
|
|
- oscar.NewTLV(0x04, oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate{
|
|
|
|
|
- Exchange: 4,
|
|
|
|
|
|
|
+ oscar.NewTLV(oscar.ChatNavRequestRoomInfo, oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate{
|
|
|
|
|
+ Exchange: room.Exchange,
|
|
|
Cookie: room.Cookie,
|
|
Cookie: room.Cookie,
|
|
|
- InstanceNumber: 100,
|
|
|
|
|
- DetailLevel: 2,
|
|
|
|
|
|
|
+ InstanceNumber: room.InstanceNumber,
|
|
|
|
|
+ DetailLevel: room.DetailLevel,
|
|
|
TLVBlock: oscar.TLVBlock{
|
|
TLVBlock: oscar.TLVBlock{
|
|
|
TLVList: room.TLVList(),
|
|
TLVList: room.TLVList(),
|
|
|
},
|
|
},
|