Skip to content

Commit

Permalink
Add Nakama API to get users by facebook ID (heroiclabs#551)
Browse files Browse the repository at this point in the history
  • Loading branch information
sesposito authored Feb 15, 2021
1 parent fe2763a commit 5980b7a
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 102 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ All notable changes to this project are documented below.
The format is based on [keep a changelog](http://keepachangelog.com) and this project uses [semantic versioning](http://semver.org).

## [Unreleased]
### Added
- Added Nakama API to get users by facebook ID.

### Fixed
- Fix an issue that prevented the JavaScript runtime hooks to be invoked correctly.
- Fix the delete button not working in the console leaderboard listing.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ require (
github.com/gorilla/mux v1.7.4
github.com/gorilla/websocket v1.4.2
github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1
github.com/heroiclabs/nakama-common v1.12.0
github.com/heroiclabs/nakama-common v1.12.1-0.20210215124839-bf495fa30713
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect
github.com/jackc/pgx v3.5.0+incompatible
github.com/jmhodges/levigo v1.0.0 // indirect
Expand Down
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1/go.mod h1:oVMjMN64nzEcepv1kdZKg
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/heroiclabs/nakama-common v1.11.1-0.20210204123435-b06844f83f0c h1:h3vOxFXzI59n2zN9O2I6y8hxFs3D5c2bVTcy0AL+fZE=
github.com/heroiclabs/nakama-common v1.11.1-0.20210204123435-b06844f83f0c/go.mod h1:li7bMQwOYA0NjT3DM4NKQBNruULPa2hrqdiSaaTwui4=
github.com/heroiclabs/nakama-common v1.12.0 h1:PLyEsC9onuO79j80fbExVyG3N8xRi7OHW4nw6beD3cg=
github.com/heroiclabs/nakama-common v1.12.0/go.mod h1:li7bMQwOYA0NjT3DM4NKQBNruULPa2hrqdiSaaTwui4=
github.com/heroiclabs/nakama-common v1.12.1-0.20210215124839-bf495fa30713 h1:rJu3e+1VcwIV1gMal5ChIFdVHKJndFmUxyYaEoRWu94=
github.com/heroiclabs/nakama-common v1.12.1-0.20210215124839-bf495fa30713/go.mod h1:li7bMQwOYA0NjT3DM4NKQBNruULPa2hrqdiSaaTwui4=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
Expand Down
6 changes: 3 additions & 3 deletions server/runtime_go_nakama.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,8 +415,8 @@ func (n *RuntimeGoNakamaModule) AccountExportId(ctx context.Context, userID stri
return exportString, nil
}

func (n *RuntimeGoNakamaModule) UsersGetId(ctx context.Context, userIDs []string) ([]*api.User, error) {
if len(userIDs) == 0 {
func (n *RuntimeGoNakamaModule) UsersGetId(ctx context.Context, userIDs []string, facebookIDs []string) ([]*api.User, error) {
if len(userIDs) == 0 && len(facebookIDs) == 0 {
return make([]*api.User, 0), nil
}

Expand All @@ -426,7 +426,7 @@ func (n *RuntimeGoNakamaModule) UsersGetId(ctx context.Context, userIDs []string
}
}

users, err := GetUsers(ctx, n.logger, n.db, n.tracker, userIDs, nil, nil)
users, err := GetUsers(ctx, n.logger, n.db, n.tracker, userIDs, nil, facebookIDs)
if err != nil {
return nil, err
}
Expand Down
45 changes: 32 additions & 13 deletions server/runtime_javascript_nakama.go
Original file line number Diff line number Diff line change
Expand Up @@ -1470,29 +1470,48 @@ func (n *runtimeJavascriptNakamaModule) accountExportId(r *goja.Runtime) func(go

func (n *runtimeJavascriptNakamaModule) usersGetId(r *goja.Runtime) func(goja.FunctionCall) goja.Value {
return func(f goja.FunctionCall) goja.Value {
var input []interface{}
if f.Argument(0) == goja.Undefined() {
panic(r.NewTypeError("expects list of user ids"))
} else {
var userIds []string
if f.Argument(0) != goja.Undefined() && f.Argument(0) != goja.Null() {
var ok bool
input, ok = f.Argument(0).Export().([]interface{})
userIdsIn, ok := f.Argument(0).Export().([]interface{})
if !ok {
panic(r.NewTypeError("Invalid argument - user ids must be an array."))
}
uIds := make([]string, 0, len(userIdsIn))
for _, userID := range userIdsIn {
id, ok := userID.(string)
if !ok {
panic(r.NewTypeError(fmt.Sprintf("invalid user id: %v - must be a string", userID)))
} else if _, err := uuid.FromString(id); err != nil {
panic(r.NewTypeError(fmt.Sprintf("invalid user id: %v", userID)))
}
uIds = append(uIds, id)
}
userIds = uIds
}

userIDs := make([]string, 0, len(input))
for _, userID := range input {
id, ok := userID.(string)
var facebookIds []string
if f.Argument(1) != goja.Undefined() && f.Argument(1) != goja.Null() {
facebookIdsIn, ok := f.Argument(1).Export().([]interface{})
if !ok {
panic(r.NewTypeError(fmt.Sprintf("invalid user id: %v - must be a string", userID)))
} else if _, err := uuid.FromString(id); err != nil {
panic(r.NewTypeError(fmt.Sprintf("invalid user id: %v", userID)))
panic(r.NewTypeError("Invalid argument - facebook ids must be an array."))
}
userIDs = append(userIDs, id)
fIds := make([]string, 0, len(facebookIdsIn))
for _, fIdIn := range facebookIdsIn {
fId, ok := fIdIn.(string)
if !ok {
panic(r.NewTypeError("Invalid argument - facebook id must be a string"))
}
fIds = append(fIds, fId)
}
facebookIds = fIds
}

if userIds == nil && facebookIds == nil {
return r.ToValue(make([]string, 0, 0))
}

users, err := GetUsers(context.Background(), n.logger, n.db, n.tracker, userIDs, nil, nil)
users, err := GetUsers(context.Background(), n.logger, n.db, n.tracker, userIds, nil, facebookIds)
if err != nil {
panic(r.NewGoError(fmt.Errorf("failed to get users: %s", err.Error())))
}
Expand Down
146 changes: 67 additions & 79 deletions server/runtime_lua_nakama.go
Original file line number Diff line number Diff line change
Expand Up @@ -1972,50 +1972,79 @@ func (n *RuntimeLuaNakamaModule) accountsGetId(l *lua.LState) int {
}

func (n *RuntimeLuaNakamaModule) usersGetId(l *lua.LState) int {
// Input table validation.
input := l.OptTable(1, nil)
if input == nil {
l.ArgError(1, "invalid user id list")
return 0
}
if input.Len() == 0 {
l.Push(l.CreateTable(0, 0))
return 1
}
userIDs, ok := RuntimeLuaConvertLuaValue(input).([]interface{})
if !ok {
l.ArgError(1, "invalid user id data")
return 0
}
if len(userIDs) == 0 {
l.Push(l.CreateTable(0, 0))
return 1
// User IDs Input table validation.
userIDsIn := l.OptTable(1, nil)
var userIDs []string
if userIDsIn != nil {
userIDsTable, ok := RuntimeLuaConvertLuaValue(userIDsIn).([]interface{})
if !ok {
l.ArgError(1, "invalid user ids list")
return 0
}

userIDStrings := make([]string, 0, len(userIDsTable))
for _, id := range userIDsTable {
if ids, ok := id.(string); !ok || ids == "" {
l.ArgError(1, "each user id must be a string")
return 0
} else if _, err := uuid.FromString(ids); err != nil {
l.ArgError(1, "each user id must be a valid id string")
return 0
} else {
userIDStrings = append(userIDStrings, ids)
}
}
userIDs = userIDStrings
}

// Input individual ID validation.
userIDStrings := make([]string, 0, len(userIDs))
for _, id := range userIDs {
if ids, ok := id.(string); !ok || ids == "" {
l.ArgError(1, "each user id must be a string")
return 0
} else if _, err := uuid.FromString(ids); err != nil {
l.ArgError(1, "each user id must be a valid id string")
// Facebook IDs Input table validation.
facebookIDsIn := l.OptTable(2, nil)
var facebookIDs []string
if facebookIDsIn != nil {
facebookIDsTable, ok := RuntimeLuaConvertLuaValue(facebookIDsIn).([]interface{})
if !ok {
l.ArgError(1, "invalid facebook ids list")
return 0
} else {
userIDStrings = append(userIDStrings, ids)
}

facebookIDStrings := make([]string, 0, len(facebookIDsTable))
for _, id := range facebookIDsTable {
if ids, ok := id.(string); !ok || ids == "" {
l.ArgError(1, "each facebook id must be a string")
return 0
} else {
facebookIDStrings = append(facebookIDStrings, ids)
}
}
facebookIDs = facebookIDStrings
}

if userIDs == nil && facebookIDs == nil {
l.Push(l.CreateTable(0, 0))
return 1
}

// Get the user accounts.
users, err := GetUsers(l.Context(), n.logger, n.db, n.tracker, userIDStrings, nil, nil)
users, err := GetUsers(l.Context(), n.logger, n.db, n.tracker, userIDs, nil, facebookIDs)
if err != nil {
l.RaiseError(fmt.Sprintf("failed to get users: %s", err.Error()))
return 0
}

// Convert and push the values.
usersTable := l.CreateTable(len(users.Users), 0)
for i, u := range users.Users {
usersTable, err := usersToLuaTable(l, users.Users)
if err != nil {
l.RaiseError(err.Error())
return 0
}

l.Push(usersTable)
return 1
}

func usersToLuaTable(l *lua.LState, users []*api.User) (*lua.LTable, error) {
usersTable := l.CreateTable(len(users), 0)
for i, u := range users {
ut := l.CreateTable(0, 18)
ut.RawSetString("user_id", lua.LString(u.Id))
ut.RawSetString("username", lua.LString(u.Username))
Expand Down Expand Up @@ -2048,19 +2077,17 @@ func (n *RuntimeLuaNakamaModule) usersGetId(l *lua.LState) int {
ut.RawSetString("update_time", lua.LNumber(u.UpdateTime.Seconds))

metadataMap := make(map[string]interface{})
err = json.Unmarshal([]byte(u.Metadata), &metadataMap)
err := json.Unmarshal([]byte(u.Metadata), &metadataMap)
if err != nil {
l.RaiseError(fmt.Sprintf("failed to convert metadata to json: %s", err.Error()))
return 0
return nil, fmt.Errorf("failed to convert metadata to json: %s", err.Error())
}
metadataTable := RuntimeLuaConvertMap(l, metadataMap)
ut.RawSetString("metadata", metadataTable)

usersTable.RawSetInt(i+1, ut)
}

l.Push(usersTable)
return 1
return usersTable, nil
}

func (n *RuntimeLuaNakamaModule) usersGetUsername(l *lua.LState) int {
Expand Down Expand Up @@ -2103,49 +2130,10 @@ func (n *RuntimeLuaNakamaModule) usersGetUsername(l *lua.LState) int {
}

// Convert and push the values.
usersTable := l.CreateTable(len(users.Users), 0)
for i, u := range users.Users {
ut := l.CreateTable(0, 18)
ut.RawSetString("user_id", lua.LString(u.Id))
ut.RawSetString("username", lua.LString(u.Username))
ut.RawSetString("display_name", lua.LString(u.DisplayName))
ut.RawSetString("avatar_url", lua.LString(u.AvatarUrl))
ut.RawSetString("lang_tag", lua.LString(u.LangTag))
ut.RawSetString("location", lua.LString(u.Location))
ut.RawSetString("timezone", lua.LString(u.Timezone))
if u.AppleId != "" {
ut.RawSetString("apple_id", lua.LString(u.AppleId))
}
if u.FacebookId != "" {
ut.RawSetString("facebook_id", lua.LString(u.FacebookId))
}
if u.FacebookInstantGameId != "" {
ut.RawSetString("facebook_instant_game_id", lua.LString(u.FacebookInstantGameId))
}
if u.GoogleId != "" {
ut.RawSetString("google_id", lua.LString(u.GoogleId))
}
if u.GamecenterId != "" {
ut.RawSetString("gamecenter_id", lua.LString(u.GamecenterId))
}
if u.SteamId != "" {
ut.RawSetString("steam_id", lua.LString(u.SteamId))
}
ut.RawSetString("online", lua.LBool(u.Online))
ut.RawSetString("edge_count", lua.LNumber(u.EdgeCount))
ut.RawSetString("create_time", lua.LNumber(u.CreateTime.Seconds))
ut.RawSetString("update_time", lua.LNumber(u.UpdateTime.Seconds))

metadataMap := make(map[string]interface{})
err = json.Unmarshal([]byte(u.Metadata), &metadataMap)
if err != nil {
l.RaiseError(fmt.Sprintf("failed to convert metadata to json: %s", err.Error()))
return 0
}
metadataTable := RuntimeLuaConvertMap(l, metadataMap)
ut.RawSetString("metadata", metadataTable)

usersTable.RawSetInt(i+1, ut)
usersTable, err := usersToLuaTable(l, users.Users)
if err != nil {
l.RaiseError(err.Error())
return 0
}

l.Push(usersTable)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/internal/genopena
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options
github.com/grpc-ecosystem/grpc-gateway/v2/runtime
github.com/grpc-ecosystem/grpc-gateway/v2/utilities
# github.com/heroiclabs/nakama-common v1.12.0
# github.com/heroiclabs/nakama-common v1.12.1-0.20210215124839-bf495fa30713
github.com/heroiclabs/nakama-common/api
github.com/heroiclabs/nakama-common/rtapi
github.com/heroiclabs/nakama-common/runtime
Expand Down

0 comments on commit 5980b7a

Please sign in to comment.