Skip to content
This repository has been archived by the owner on Dec 17, 2024. It is now read-only.

Commit

Permalink
fix: patch for animated pfps
Browse files Browse the repository at this point in the history
  • Loading branch information
TroyKomodo committed Feb 20, 2024
1 parent c47b8c8 commit b0496ec
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 130 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ lint:

format:
gofmt -s -w .
yarn prettier --write .
# yarn prettier --write .

deps:
go install github.com/swaggo/swag/cmd/[email protected]
Expand Down
9 changes: 1 addition & 8 deletions data/events/payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
type AnyPayload interface {
json.RawMessage | HelloPayload | AckPayload | HeartbeatPayload | ReconnectPayload | ResumePayload |
SubscribePayload | UnsubscribePayload | DispatchPayload | SignalPayload |
ErrorPayload | EndOfStreamPayload | BridgedCommandPayload[json.RawMessage]
ErrorPayload | EndOfStreamPayload | BridgedCommandBody
}

type HelloPayload struct {
Expand Down Expand Up @@ -156,10 +156,3 @@ type EndOfStreamPayload struct {
Code CloseCode `json:"code"`
Message string `json:"message"`
}

type BridgedCommandPayload[T BridgedCommandBody] struct {
Command string `json:"command"`
SessionID string `json:"sid"`
ClientIP string `json:"ip"`
Body T `json:"body"`
}
8 changes: 1 addition & 7 deletions data/events/payload_commands.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
package events

import (
"encoding/json"

"github.com/seventv/common/structures/v3"
)

type BridgedCommandBody interface {
json.RawMessage | UserStateCommandBody
}

type UserStateCommandBody struct {
type BridgedCommandBody struct {
Platform structures.UserConnectionPlatform `json:"platform"`
Identifiers []string `json:"identifiers"`
Kinds []structures.CosmeticKind `json:"kinds"`
Expand Down
3 changes: 1 addition & 2 deletions docker/full.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ FROM $BASE_IMG as go-builder

COPY . .

RUN make generate && \
make test
RUN make generate

ARG BUILDER
ARG VERSION
Expand Down
21 changes: 3 additions & 18 deletions internal/api/eventbridge/eventbridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,10 @@ import (
const SESSION_ID_KEY = utils.Key("session_id")

func handle(gctx global.Context, body []byte) ([]events.Message[json.RawMessage], error) {
var err error

req := getCommandBody[json.RawMessage](body)

ctx, cancel := context.WithCancel(gctx)
ctx = context.WithValue(ctx, SESSION_ID_KEY, req.SessionID)

defer cancel()

var result []events.Message[json.RawMessage]

switch req.Command {
case "userstate", "cosmetics":
data := getCommandBody[events.UserStateCommandBody](body).Body

result, err = handleUserState(gctx, ctx, data)
}

return result, err
return handleUserState(gctx, ctx, getCommandBody(body))
}

// The EventAPI Bridge allows passing commands from the eventapi via the websocket
Expand Down Expand Up @@ -91,8 +76,8 @@ func New(gctx global.Context) <-chan struct{} {
return done
}

func getCommandBody[T events.BridgedCommandBody](body []byte) events.BridgedCommandPayload[T] {
var result events.BridgedCommandPayload[T]
func getCommandBody(body []byte) events.BridgedCommandBody {
var result events.BridgedCommandBody

if err := json.Unmarshal(body, &result); err != nil {
zap.S().Errorw("invalid eventapi bridge message", "err", err)
Expand Down
161 changes: 67 additions & 94 deletions internal/api/eventbridge/eventbridge_cosmetics.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,50 +23,40 @@ const (
identifier_id = "id"
)

var userStateLoader *dataloader.DataLoader[string, structures.User]
type UserIdentifier struct {
Platform structures.UserConnectionPlatform `json:"platform"`
IdType string `json:"id_type"`
Id string `json:"id"`
}

var userStateLoader *dataloader.DataLoader[UserIdentifier, structures.User]

type identifier struct {
Platform structures.UserConnectionPlatform
Id string
}

func createUserStateLoader(gctx global.Context) {
userStateLoader = dataloader.New(dataloader.Config[string, structures.User]{
Fetch: func(keys []string) ([]structures.User, []error) {
userStateLoader = dataloader.New(dataloader.Config[UserIdentifier, structures.User]{
Fetch: func(keys []UserIdentifier) ([]structures.User, []error) {
var (
errs []error
v []structures.User
errs []error
resultMap map[UserIdentifier]structures.User = map[UserIdentifier]structures.User{}
)

identifierMap := map[string]utils.Set[string]{
identifierMap := map[string]utils.Set[identifier]{
identifier_foreign_username: {},
identifier_foreign_id: {},
identifier_id: {},
identifier_username: {},
}

for _, key := range keys {
// Identify the target
keysp := strings.SplitN(key, "|", 2)
if len(keysp) != 2 {
continue
}

platform := keysp[0]

idsp := strings.SplitN(keysp[1], ":", 2)
idType := idsp[0]
identifier := idsp[1]

// Platform specified: find by connection
if platform != "" {
switch idType {
case "id":
identifierMap["foreign_id"].Add(platform + ":" + identifier)
case "username":
identifierMap["foreign_username"].Add(platform + ":" + identifier)
}
} else { // no platform means app user
switch idType {
case "id":
identifierMap["id"].Add(identifier)
case "username":
identifierMap["username"].Add(identifier)
if key.Platform != "" {
switch key.IdType {
case identifier_id:
identifierMap[identifier_foreign_id].Add(identifier{Platform: key.Platform, Id: key.Id})
case identifier_username:
identifierMap[identifier_foreign_username].Add(identifier{Platform: key.Platform, Id: key.Id})
}
}
}
Expand All @@ -81,7 +71,7 @@ func createUserStateLoader(gctx global.Context) {

wg.Add(1)

go func(idType string, identifiers utils.Set[string]) {
go func(idType string, identifiers utils.Set[identifier]) {
defer wg.Done()

var users = []structures.User{}
Expand All @@ -90,91 +80,75 @@ func createUserStateLoader(gctx global.Context) {
case identifier_foreign_id, identifier_foreign_username:
l := utils.Ternary(idType == identifier_foreign_id, gctx.Inst().Loaders.UserByConnectionID, gctx.Inst().Loaders.UserByConnectionUsername)

m := make(map[structures.UserConnectionPlatform][]string)
m := map[structures.UserConnectionPlatform][]string{}

for _, id := range identifiers.Values() {
idsp := strings.SplitN(id, ":", 2)
if len(idsp) != 2 {
continue
}

platform := structures.UserConnectionPlatform((idsp[0]))
id := idsp[1]

m[platform] = append(m[platform], id)
m[id.Platform] = append(m[id.Platform], id.Id)
}

for p, ids := range m {
users, errs = l(p).LoadAll(ids)
}
case identifier_id:
//iden := identifiers.Values()
//idList := utils.Map(iden, func(x string) primitive.ObjectID {
// oid, err := primitive.ObjectIDFromHex(x)
// if err != nil {
// return primitive.NilObjectID
// }

// return oid
//})

// v, errs = gctx.Inst().Loaders.UserByID().LoadAll(idList)
case identifier_username:
// v, errs = gctx.Inst().Loaders.UserByUsername().LoadAll(identifiers.Values())
}

mx.Lock()

v = append(v, users...)

mx.Unlock()
mx.Lock()

for i := range users {
if errs[i] != nil {
if errors.Compare(errs[i], errors.ErrUnknownUser()) {
continue
}

zap.S().Errorw("failed to load user for bridged cosmetics request command", "error", errs[i])
break
}

id := ids[i]
key := UserIdentifier{
Platform: p,
IdType: utils.Ternary(idType == identifier_foreign_id, identifier_id, identifier_username),
Id: id,
}

resultMap[key] = users[i]
}

for _, err := range errs {
if err == nil || errors.Compare(err, errors.ErrUnknownUser()) {
continue
mx.Unlock()
}

zap.S().Errorw("failed to load users for bridged cosmetics request command", "error", err)

break
}
}(idType, identifiers)
}

wg.Wait()

return v, errs
result := make([]structures.User, len(keys))
for i, key := range keys {
result[i] = resultMap[key]
}

return result, errs
},
Wait: 250 * time.Millisecond,
MaxBatch: 500,
})
}

func handleUserState(gctx global.Context, ctx context.Context, body events.UserStateCommandBody) ([]events.Message[json.RawMessage], error) {
keys := make([]string, len(body.Identifiers))
func handleUserState(gctx global.Context, ctx context.Context, body events.BridgedCommandBody) ([]events.Message[json.RawMessage], error) {
keys := make([]UserIdentifier, len(body.Identifiers))

for i, id := range body.Identifiers {
params := strings.Builder{}
params.WriteString(string(body.Platform))
params.WriteString("|")
params.WriteString(id)

keys[i] = params.String()
}

users, _ := userStateLoader.LoadAll(keys)
splits := strings.SplitN(id, ":", 2)

var sid string
switch t := ctx.Value(SESSION_ID_KEY).(type) {
case string:
sid = t
}
if len(splits) != 2 {
zap.S().Errorw("invalid user identifier", "identifier", id)
return nil, nil
}

if sid == "" {
zap.S().Errorw("failed to get session id from context")
return nil, nil
keys[i] = UserIdentifier{
Platform: body.Platform,
IdType: splits[0],
Id: splits[1],
}
}

users, _ := userStateLoader.LoadAll(keys)
result := []events.Message[json.RawMessage]{}

// Dispatch user avatar
Expand All @@ -191,7 +165,6 @@ func handleUserState(gctx global.Context, ctx context.Context, body events.UserS
Contextual: true,
Object: av,
},
Whisper: sid,
}).ToRaw())
}
}
Expand Down

0 comments on commit b0496ec

Please sign in to comment.