Merge pull request #31 from PretendoNetwork/dev
Some checks failed
Build and Publish Docker Image / build-publish (push) Has been cancelled

Merge dev to master
This commit is contained in:
Jonathan Barrow 2025-02-16 19:42:32 -05:00 committed by GitHub
commit b44feb2ae0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
113 changed files with 2518 additions and 2270 deletions

View File

@ -3,5 +3,4 @@
build
log
go.work
*.test
go.work.sum
go.work.sum

56
.github/workflows/docker.yml vendored Normal file
View File

@ -0,0 +1,56 @@
name: Build and Publish Docker Image
on:
push:
pull_request:
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-publish:
env:
SHOULD_PUSH_IMAGE: ${{ (github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev')) || github.event_name == 'workflow_dispatch' }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Set up QEMU for Docker
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log into the container registry
if: ${{ env.SHOULD_PUSH_IMAGE == 'true' }}
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }}
type=raw,value=edge,enable=${{ github.ref == 'refs/heads/dev' }}
type=sha
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v6
with:
platforms: linux/amd64,linux/arm64
push: ${{ env.SHOULD_PUSH_IMAGE }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

View File

@ -1,19 +1,36 @@
# --- builder ---
FROM golang:1.20.6-alpine3.17 as builder
LABEL stage=builder
RUN apk add git
WORKDIR /build
# syntax=docker/dockerfile:1
COPY go.* ./
RUN go mod download
ARG app_dir="/home/go/app"
COPY . ./
ARG BUILD_STRING=pretendo.friends.docker
RUN go build -ldflags "-X 'main.serverBuildString=${BUILD_STRING}'" -v -o server
# --- runner ---
FROM alpine:3.17 as runner
WORKDIR /build
# * Building the application
FROM golang:1.23.6-alpine AS build
ARG app_dir
ARG build_string=pretendo.friends.docker
COPY --from=builder /build/server /build/
CMD ["/build/server"]
WORKDIR ${app_dir}
RUN --mount=type=cache,target=/go/pkg/mod/ \
--mount=type=bind,source=go.sum,target=go.sum \
--mount=type=bind,source=go.mod,target=go.mod \
go mod download -x
COPY . .
RUN --mount=type=cache,target=/go/pkg/mod/ \
CGO_ENABLED=0 go build -v -o ${app_dir}/build/server -ldflags "-X 'main.serverBuildString=${build_string}'"
# * Running the final application
FROM alpine:3.20 AS final
ARG app_dir
WORKDIR ${app_dir}
RUN addgroup go && adduser -D -G go go
RUN mkdir -p ${app_dir}/log && chown go:go ${app_dir}/log
USER go
COPY --from=build ${app_dir}/build/server ${app_dir}/server
CMD [ "./server" ]

View File

@ -84,16 +84,15 @@ All configuration options are handled via environment variables
`.env` files are supported
| Name | Description | Required |
|-----------------------------------------|------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|
| `PN_FRIENDS_CONFIG_DATABASE_URI` | Fully qualified URI to your Postgres server (Example `postgres://username:password@localhost/friends?sslmode=disable`) | Yes |
| `PN_FRIENDS_CONFIG_KERBEROS_PASSWORD` | Password used as part of the internal server data in Kerberos tickets | No (Default password `password` will be used) |
| `PN_FRIENDS_CONFIG_AES_KEY` | AES key used in tokens provided by the account server | Yes |
| `PN_FRIENDS_CONFIG_GRPC_API_KEY` | API key for your GRPC server | No (Assumed to be an open gRPC API) |
| `PN_FRIENDS_GRPC_SERVER_PORT` | Port for the GRPC server | Yes |
| `PN_FRIENDS_AUTHENTICATION_SERVER_PORT` | Port for the authentication server | Yes |
| `PN_FRIENDS_SECURE_SERVER_HOST` | Host name for the secure server (should point to the same address as the authentication server) | Yes |
| `PN_FRIENDS_SECURE_SERVER_PORT` | Port for the secure server | Yes |
| `PN_FRIENDS_ACCOUNT_GRPC_HOST` | Host name for your account server gRPC service | Yes |
| `PN_FRIENDS_ACCOUNT_GRPC_PORT` | Port for your account server gRPC service | Yes |
| `PN_FRIENDS_ACCOUNT_GRPC_API_KEY` | API key for your account server gRPC service | No (Assumed to be an open gRPC API) |
| Name | Description | Required |
|---------------------------------------------|------------------------------------------------------------------------------------------------------------------------|-------------------------------------|
| `PN_FRIENDS_CONFIG_DATABASE_URI` | Fully qualified URI to your Postgres server (Example `postgres://username:password@localhost/friends?sslmode=disable`) | Yes |
| `PN_FRIENDS_CONFIG_AES_KEY` | AES key used in tokens provided by the account server | Yes |
| `PN_FRIENDS_CONFIG_GRPC_API_KEY` | API key for your GRPC server | No (Assumed to be an open gRPC API) |
| `PN_FRIENDS_GRPC_SERVER_PORT` | Port for the GRPC server | Yes |
| `PN_FRIENDS_AUTHENTICATION_SERVER_PORT` | Port for the authentication server | Yes |
| `PN_FRIENDS_SECURE_SERVER_HOST` | Host name for the secure server (should point to the same address as the authentication server) | Yes |
| `PN_FRIENDS_SECURE_SERVER_PORT` | Port for the secure server | Yes |
| `PN_FRIENDS_ACCOUNT_GRPC_HOST` | Host name for your account server gRPC service | Yes |
| `PN_FRIENDS_ACCOUNT_GRPC_PORT` | Port for your account server gRPC service | Yes |
| `PN_FRIENDS_ACCOUNT_GRPC_API_KEY` | API key for your account server gRPC service | No (Assumed to be an open gRPC API) |

View File

@ -1,40 +1,46 @@
package database_3ds
import (
"time"
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
"github.com/lib/pq"
)
// GetFriendMiis returns the Mii of all friends
func GetFriendMiis(pids []uint32) ([]*friends_3ds_types.FriendMii, error) {
friendMiis := make([]*friends_3ds_types.FriendMii, 0)
func GetFriendMiis(pids []uint32) (types.List[friends_3ds_types.FriendMii], error) {
friendMiis := types.NewList[friends_3ds_types.FriendMii]()
rows, err := database.Postgres.Query(`
SELECT pid, mii_name, mii_data FROM "3ds".user_data WHERE pid=ANY($1::int[])`, pq.Array(pids))
rows, err := database.Manager.Query(`
SELECT pid, mii_name, mii_profanity, mii_character_set, mii_data, mii_changed FROM "3ds".user_data WHERE pid=ANY($1::int[])`, pq.Array(pids))
if err != nil {
return friendMiis, err
}
changedTime := nex.NewDateTime(0)
changedTime.FromTimestamp(time.Now())
defer rows.Close()
for rows.Next() {
var pid uint32
var miiName string
var miiProfanity bool
var miiCharacterSet uint8
var miiData []byte
var changedTime uint64
err := rows.Scan(&pid, &miiName, &miiProfanity, &miiCharacterSet, &miiData, &changedTime)
if err != nil {
return friendMiis, err
}
mii := friends_3ds_types.NewMii()
mii.Unknown2 = false
mii.Unknown3 = 0
rows.Scan(&pid, &mii.Name, &mii.MiiData)
mii.Name = types.NewString(miiName)
mii.ProfanityFlag = types.NewBool(miiProfanity)
mii.CharacterSet = types.NewUInt8(miiCharacterSet)
mii.MiiData = types.NewBuffer(miiData)
friendMii := friends_3ds_types.NewFriendMii()
friendMii.PID = pid
friendMii.PID = types.NewPID(uint64(pid))
friendMii.Mii = mii
friendMii.ModifiedAt = changedTime
friendMii.ModifiedAt = types.NewDateTime(changedTime)
friendMiis = append(friendMiis, friendMii)
}

View File

@ -2,39 +2,70 @@ package database_3ds
import (
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
"github.com/lib/pq"
)
// GetFriendPersistentInfos returns the persistent information of all friends
func GetFriendPersistentInfos(user1_pid uint32, pids []uint32) ([]*friends_3ds_types.FriendPersistentInfo, error) {
persistentInfos := make([]*friends_3ds_types.FriendPersistentInfo, 0)
func GetFriendPersistentInfos(user1_pid uint32, pids []uint32) (types.List[friends_3ds_types.FriendPersistentInfo], error) {
persistentInfos := types.NewList[friends_3ds_types.FriendPersistentInfo]()
rows, err := database.Postgres.Query(`
SELECT pid, region, area, language, favorite_title, favorite_title_version, comment, comment_changed, last_online, mii_changed FROM "3ds".user_data WHERE pid=ANY($1::int[])`, pq.Array(pids))
rows, err := database.Manager.Query(`
SELECT pid, region, area, language, country, favorite_title, favorite_title_version, comment, comment_changed, last_online, mii_changed FROM "3ds".user_data WHERE pid=ANY($1::int[])`, pq.Array(pids))
if err != nil {
return persistentInfos, err
}
defer rows.Close()
for rows.Next() {
persistentInfo := friends_3ds_types.NewFriendPersistentInfo()
gameKey := friends_3ds_types.NewGameKey()
var pid uint32
var region uint8
var area uint8
var language uint8
var country uint8
var titleID uint64
var titleVersion uint16
var message string
var lastOnlineTime uint64
var msgUpdateTime uint64
var miiModifiedAtTime uint64
rows.Scan(
&persistentInfo.PID, &persistentInfo.Region, &persistentInfo.Area, &persistentInfo.Language,
&gameKey.TitleID, &gameKey.TitleVersion, &persistentInfo.Message, &msgUpdateTime, &lastOnlineTime, &miiModifiedAtTime)
err := rows.Scan(
&pid,
&region,
&area,
&language,
&country,
&titleID,
&titleVersion,
&message,
&msgUpdateTime,
&lastOnlineTime,
&miiModifiedAtTime,
)
if err != nil {
return persistentInfos, err
}
persistentInfo.MessageUpdatedAt = nex.NewDateTime(msgUpdateTime)
persistentInfo.MiiModifiedAt = nex.NewDateTime(miiModifiedAtTime)
persistentInfo.LastOnline = nex.NewDateTime(lastOnlineTime)
gameKey.TitleID = types.NewUInt64(titleID)
gameKey.TitleVersion = types.NewUInt16(titleVersion)
persistentInfo.PID = types.NewPID(uint64(pid))
persistentInfo.Region = types.NewUInt8(region)
persistentInfo.Country = types.NewUInt8(country)
persistentInfo.Area = types.NewUInt8(area)
persistentInfo.Language = types.NewUInt8(language)
persistentInfo.Platform = types.NewUInt8(2) // * Always 3DS
persistentInfo.GameKey = gameKey
persistentInfo.Platform = 2 // Always 3DS
persistentInfo.Message = types.NewString(message)
persistentInfo.MessageUpdatedAt = types.NewDateTime(msgUpdateTime)
persistentInfo.MiiModifiedAt = types.NewDateTime(miiModifiedAtTime)
persistentInfo.LastOnline = types.NewDateTime(lastOnlineTime)
persistentInfos = append(persistentInfos, persistentInfo)
}

View File

@ -4,27 +4,38 @@ import (
"database/sql"
"github.com/PretendoNetwork/friends/database"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
)
// GetUserFriends returns all friend relationships of a user
func GetUserFriends(pid uint32) ([]*friends_3ds_types.FriendRelationship, error) {
friendRelationships := make([]*friends_3ds_types.FriendRelationship, 0)
func GetUserFriends(pid uint32) (types.List[friends_3ds_types.FriendRelationship], error) {
friendRelationships := types.NewList[friends_3ds_types.FriendRelationship]()
rows, err := database.Postgres.Query(`
SELECT user2_pid, type FROM "3ds".friendships WHERE user1_pid=$1 AND type=1 LIMIT 100`, pid)
rows, err := database.Manager.Query("SELECT user2_pid, type FROM \"3ds\".friendships WHERE user1_pid=$1 AND type=1 LIMIT 100", pid)
if err != nil {
if err == sql.ErrNoRows {
if err == sql.ErrNoRows {
return friendRelationships, database.ErrEmptyList
} else {
return friendRelationships, err
}
}
defer rows.Close()
for rows.Next() {
var pid uint32
var relationshipType uint8
err := rows.Scan(&pid, &relationshipType)
if err != nil {
return friendRelationships, err
}
relationship := friends_3ds_types.NewFriendRelationship()
relationship.LFC = 0
rows.Scan(&relationship.PID, &relationship.RelationshipType)
relationship.LFC = types.NewUInt64(0)
relationship.PID = types.NewPID(uint64(pid))
relationship.RelationshipType = types.NewUInt8(relationshipType)
friendRelationships = append(friendRelationships, relationship)
}

View File

@ -6,7 +6,7 @@ import (
// RemoveFriendship removes a user's friend relationship
func RemoveFriendship(user1_pid uint32, user2_pid uint32) error {
result, err := database.Postgres.Exec(`
result, err := database.Manager.Exec(`
DELETE FROM "3ds".friendships WHERE user1_pid=$1 AND user2_pid=$2`, user1_pid, user2_pid)
if err != nil {
return err
@ -17,7 +17,7 @@ func RemoveFriendship(user1_pid uint32, user2_pid uint32) error {
return database.ErrFriendshipNotFound
}
_, err = database.Postgres.Exec(`
_, err = database.Manager.Exec(`
UPDATE "3ds".friendships SET type=0 WHERE user1_pid=$1 AND user2_pid=$2`, user2_pid, user1_pid)
if err != nil {
return err

View File

@ -1,56 +1,62 @@
package database_3ds
import (
"time"
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
)
// SaveFriendship saves a friend relationship for a user
func SaveFriendship(senderPID uint32, recipientPID uint32) (*friends_3ds_types.FriendRelationship, error) {
func SaveFriendship(senderPID uint32, recipientPID uint32) (friends_3ds_types.FriendRelationship, error) {
friendRelationship := friends_3ds_types.NewFriendRelationship()
friendRelationship.PID = recipientPID
friendRelationship.LFC = 0
friendRelationship.RelationshipType = 0 // Incomplete
nowTime := nex.NewDateTime(0)
nowTime.FromTimestamp(time.Now())
// Ensure that we inputted a valid user.
// * Ensure that we inputted a valid user.
var found bool
err := database.Postgres.QueryRow(`SELECT COUNT(*) FROM "3ds".user_data WHERE pid=$1 LIMIT 1`, recipientPID).Scan(&found)
row, err := database.Manager.QueryRow(`SELECT COUNT(*) FROM "3ds".user_data WHERE pid=$1 LIMIT 1`, recipientPID)
if err != nil {
return nil, err
return friendRelationship, err
}
err = row.Scan(&found)
if err != nil {
return friendRelationship, err
}
if !found {
friendRelationship.RelationshipType = 2 // Non-existent
friendRelationship.PID = types.NewPID(uint64(recipientPID))
friendRelationship.RelationshipType = types.NewUInt8(2) // * Non-existent
return friendRelationship, nil
}
// Get the other side's relationship, we need to know if we've already got one sent to us.
err = database.Postgres.QueryRow(`
SELECT COUNT(*) FROM "3ds".friendships WHERE user1_pid=$1 AND user2_pid=$2 AND type=0 LIMIT 1`, recipientPID, senderPID).Scan(&found)
// * Get the other side's relationship, we need to know if we've already got one sent to us.
row, err = database.Manager.QueryRow(`SELECT COUNT(*) FROM "3ds".friendships WHERE user1_pid=$1 AND user2_pid=$2 AND type=0 LIMIT 1`, recipientPID, senderPID)
if err != nil {
return nil, err
return friendRelationship, err
}
err = row.Scan(&found)
if err != nil {
return friendRelationship, err
}
if !found {
_, err = database.Postgres.Exec(`
_, err = database.Manager.Exec(`
INSERT INTO "3ds".friendships (user1_pid, user2_pid, type)
VALUES ($1, $2, 0)
ON CONFLICT (user1_pid, user2_pid)
DO NOTHING`, senderPID, recipientPID)
if err != nil {
return nil, err
return friendRelationship, err
}
friendRelationship.PID = types.NewPID(uint64(recipientPID))
return friendRelationship, nil
}
acceptedTime := nex.NewDateTime(0).Now()
acceptedTime := uint64(types.NewDateTime(0).Now())
// We need to have two relationships for both sides as friend relationships are not one single object.
_, err = database.Postgres.Exec(`
// * We need to have two relationships for both sides as friend relationships are not one single object.
_, err = database.Manager.Exec(`
INSERT INTO "3ds".friendships (user1_pid, user2_pid, date, type)
VALUES ($1, $2, $3, 1)
ON CONFLICT (user1_pid, user2_pid)
@ -58,10 +64,10 @@ func SaveFriendship(senderPID uint32, recipientPID uint32) (*friends_3ds_types.F
date = $3,
type = 1`, senderPID, recipientPID, acceptedTime)
if err != nil {
return nil, err
return friendRelationship, err
}
_, err = database.Postgres.Exec(`
_, err = database.Manager.Exec(`
INSERT INTO "3ds".friendships (user1_pid, user2_pid, date, type)
VALUES ($1, $2, $3, 1)
ON CONFLICT (user1_pid, user2_pid)
@ -69,9 +75,11 @@ func SaveFriendship(senderPID uint32, recipientPID uint32) (*friends_3ds_types.F
date = $3,
type = 1`, recipientPID, senderPID, acceptedTime)
if err != nil {
return nil, err
return friendRelationship, err
}
friendRelationship.RelationshipType = 1 // Complete
friendRelationship.PID = types.NewPID(uint64(recipientPID))
friendRelationship.RelationshipType = types.NewUInt8(1) // * Complete
return friendRelationship, nil
}

View File

@ -2,20 +2,20 @@ package database_3ds
import (
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-go/v2/types"
)
// UpdateUserComment updates a user's comment
func UpdateUserComment(pid uint32, message string) error {
changed := nex.NewDateTime(0).Now()
changed := types.NewDateTime(0).Now()
_, err := database.Postgres.Exec(`
_, err := database.Manager.Exec(`
INSERT INTO "3ds".user_data (pid, comment, comment_changed)
VALUES ($1, $2, $3)
ON CONFLICT (pid)
DO UPDATE SET
comment = $2,
comment_changed = $3`, pid, message, changed)
comment_changed = $3`, pid, message, uint64(changed))
if err != nil {
return err

View File

@ -2,18 +2,18 @@ package database_3ds
import (
"github.com/PretendoNetwork/friends/database"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
)
// UpdateUserFavoriteGame updates a user's favorite game
func UpdateUserFavoriteGame(pid uint32, gameKey *friends_3ds_types.GameKey) error {
_, err := database.Postgres.Exec(`
func UpdateUserFavoriteGame(pid uint32, gameKey friends_3ds_types.GameKey) error {
_, err := database.Manager.Exec(`
INSERT INTO "3ds".user_data (pid, favorite_title, favorite_title_version)
VALUES ($1, $2, $3)
ON CONFLICT (pid)
DO UPDATE SET
favorite_title = $2,
favorite_title_version = $3`, pid, gameKey.TitleID, gameKey.TitleVersion)
favorite_title_version = $3`, pid, uint64(gameKey.TitleID), uint16(gameKey.TitleVersion))
if err != nil {
return err

View File

@ -4,27 +4,33 @@ import (
"database/sql"
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-go/v2/types"
)
// UpdateUserLastOnlineTime updates a user's last online time
func UpdateUserLastOnlineTime(pid uint32, lastOnline *nex.DateTime) error {
func UpdateUserLastOnlineTime(pid uint32, lastOnline types.DateTime) error {
var showOnline bool
err := database.Postgres.QueryRow(`SELECT show_online FROM "3ds".user_data WHERE pid=$1`, pid).Scan(&showOnline)
row, err := database.Manager.QueryRow(`SELECT show_online FROM "3ds".user_data WHERE pid=$1`, pid)
if err != nil {
return err
}
err = row.Scan(&showOnline)
if err != nil && err != sql.ErrNoRows {
return err
}
if !showOnline {
return nil
}
_, err = database.Postgres.Exec(`
_, err = database.Manager.Exec(`
INSERT INTO "3ds".user_data (pid, last_online)
VALUES ($1, $2)
ON CONFLICT (pid)
DO UPDATE SET
last_online = $2`, pid, lastOnline.Value())
last_online = $2`, pid, uint64(lastOnline))
if err != nil {
return err
}

View File

@ -2,20 +2,22 @@ package database_3ds
import (
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
)
// UpdateUserMii updates a user's mii
func UpdateUserMii(pid uint32, mii *friends_3ds_types.Mii) error {
_, err := database.Postgres.Exec(`
INSERT INTO "3ds".user_data (pid, mii_name, mii_data, mii_changed)
VALUES ($1, $2, $3, $4)
func UpdateUserMii(pid uint32, mii friends_3ds_types.Mii) error {
_, err := database.Manager.Exec(`
INSERT INTO "3ds".user_data (pid, mii_name, mii_profanity, mii_character_set, mii_data, mii_changed)
VALUES ($1, $2, $3, $4, $5, $6)
ON CONFLICT (pid)
DO UPDATE SET
mii_name = $2,
mii_data = $3,
mii_changed = $4`, pid, mii.Name, mii.MiiData, nex.NewDateTime(0).Now())
mii_profanity = $3,
mii_character_set = $4,
mii_data = $5,
mii_changed = $6`, pid, string(mii.Name), bool(mii.ProfanityFlag), uint8(mii.CharacterSet), []byte(mii.MiiData), uint64(types.NewDateTime(0).Now()))
if err != nil {
return err

View File

@ -6,7 +6,7 @@ import (
// UpdateUserPreferences updates a user's preferences
func UpdateUserPreferences(pid uint32, show_online bool, show_current_game bool) error {
_, err := database.Postgres.Exec(`
_, err := database.Manager.Exec(`
INSERT INTO "3ds".user_data (pid, show_online, show_current_game)
VALUES ($1, $2, $3)
ON CONFLICT (pid)

View File

@ -2,19 +2,20 @@ package database_3ds
import (
"github.com/PretendoNetwork/friends/database"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
)
// UpdateUserProfile updates a user's profile
func UpdateUserProfile(pid uint32, profileData *friends_3ds_types.MyProfile) error {
_, err := database.Postgres.Exec(`
INSERT INTO "3ds".user_data (pid, region, area, language)
VALUES ($1, $2, $3, $4)
func UpdateUserProfile(pid uint32, profileData friends_3ds_types.MyProfile) error {
_, err := database.Manager.Exec(`
INSERT INTO "3ds".user_data (pid, region, area, language, country)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (pid)
DO UPDATE SET
region = $2,
area = $3,
language = $4`, pid, profileData.Region, profileData.Area, profileData.Language)
language = $4,
country = $5`, pid, uint8(profileData.Region), uint8(profileData.Area), uint8(profileData.Language), uint8(profileData.Country))
if err != nil {
return err

View File

@ -1,20 +1,20 @@
package database
import (
"database/sql"
"os"
_ "github.com/lib/pq"
"github.com/PretendoNetwork/friends/globals"
sqlmanager "github.com/PretendoNetwork/sql-manager"
)
var Postgres *sql.DB
var Manager *sqlmanager.SQLManager
func ConnectPostgres() {
var err error
Postgres, err = sql.Open("postgres", os.Getenv("PN_FRIENDS_CONFIG_DATABASE_URI"))
Manager, err = sqlmanager.NewSQLManager("postgres", os.Getenv("PN_FRIENDS_CONFIG_DATABASE_URI"), int64(globals.DatabaseMaxConnections))
if err != nil {
globals.Logger.Critical(err.Error())
}

View File

@ -5,7 +5,7 @@ import "github.com/PretendoNetwork/friends/globals"
func initPostgres3DS() {
var err error
_, err = Postgres.Exec(`CREATE SCHEMA IF NOT EXISTS "3ds"`)
_, err = Manager.Exec(`CREATE SCHEMA IF NOT EXISTS "3ds"`)
if err != nil {
globals.Logger.Critical(err.Error())
return
@ -13,28 +13,31 @@ func initPostgres3DS() {
globals.Logger.Success("[3DS] Postgres schema created")
_, err = Postgres.Exec(`CREATE TABLE IF NOT EXISTS "3ds".user_data (
_, err = Manager.Exec(`CREATE TABLE IF NOT EXISTS "3ds".user_data (
pid integer PRIMARY KEY,
show_online boolean DEFAULT true,
show_current_game boolean DEFAULT true,
comment text,
comment_changed bigint,
last_online bigint,
favorite_title bigint,
favorite_title_version integer,
mii_name text,
mii_data bytea,
mii_changed bigint,
region integer,
area integer,
language integer
comment text DEFAULT '',
comment_changed bigint DEFAULT 0,
last_online bigint DEFAULT 0,
favorite_title bigint DEFAULT 0,
favorite_title_version integer DEFAULT 0,
mii_name text DEFAULT '',
mii_profanity boolean DEFAULT false,
mii_character_set smallint DEFAULT 0,
mii_data bytea DEFAULT '',
mii_changed bigint DEFAULT 0,
region integer DEFAULT 0,
area integer DEFAULT 0,
language integer DEFAULT 0,
country integer DEFAULT 0
)`)
if err != nil {
globals.Logger.Critical(err.Error())
return
}
_, err = Postgres.Exec(`CREATE TABLE IF NOT EXISTS "3ds".friendships (
_, err = Manager.Exec(`CREATE TABLE IF NOT EXISTS "3ds".friendships (
id bigserial PRIMARY KEY,
user1_pid integer,
user2_pid integer,

View File

@ -5,7 +5,7 @@ import "github.com/PretendoNetwork/friends/globals"
func initPostgresWiiU() {
var err error
_, err = Postgres.Exec(`CREATE SCHEMA IF NOT EXISTS wiiu`)
_, err = Manager.Exec(`CREATE SCHEMA IF NOT EXISTS wiiu`)
if err != nil {
globals.Logger.Critical(err.Error())
return
@ -13,21 +13,55 @@ func initPostgresWiiU() {
globals.Logger.Success("[Wii U] Postgres schema created")
_, err = Postgres.Exec(`CREATE TABLE IF NOT EXISTS wiiu.user_data (
_, err = Manager.Exec(`CREATE TABLE IF NOT EXISTS wiiu.user_data (
pid integer PRIMARY KEY,
show_online boolean DEFAULT true,
show_current_game boolean DEFAULT true,
block_friend_requests boolean DEFAULT false,
comment text DEFAULT '',
comment_changed bigint DEFAULT 0,
last_online bigint
last_online bigint DEFAULT 0
)`)
if err != nil {
globals.Logger.Critical(err.Error())
return
}
_, err = Postgres.Exec(`CREATE TABLE IF NOT EXISTS wiiu.friendships (
_, err = Manager.Exec(`CREATE TABLE IF NOT EXISTS wiiu.network_account_info (
pid integer PRIMARY KEY,
unknown1 integer,
unknown2 integer,
birthday bigint
)`)
if err != nil {
globals.Logger.Critical(err.Error())
return
}
_, err = Manager.Exec(`CREATE TABLE IF NOT EXISTS wiiu.principal_basic_info (
pid integer PRIMARY KEY,
username text,
unknown integer
)`)
if err != nil {
globals.Logger.Critical(err.Error())
return
}
_, err = Manager.Exec(`CREATE TABLE IF NOT EXISTS wiiu.mii (
pid integer PRIMARY KEY,
name text,
unknown1 integer,
unknown2 integer,
data bytea,
unknown_datetime bigint
)`)
if err != nil {
globals.Logger.Critical(err.Error())
return
}
_, err = Manager.Exec(`CREATE TABLE IF NOT EXISTS wiiu.friendships (
id bigserial PRIMARY KEY,
user1_pid integer,
user2_pid integer,
@ -40,7 +74,7 @@ func initPostgresWiiU() {
return
}
_, err = Postgres.Exec(`CREATE TABLE IF NOT EXISTS wiiu.blocks (
_, err = Manager.Exec(`CREATE TABLE IF NOT EXISTS wiiu.blocks (
id bigserial PRIMARY KEY,
blocker_pid integer,
blocked_pid integer,
@ -54,7 +88,7 @@ func initPostgresWiiU() {
return
}
_, err = Postgres.Exec(`CREATE TABLE IF NOT EXISTS wiiu.friend_requests (
_, err = Manager.Exec(`CREATE TABLE IF NOT EXISTS wiiu.friend_requests (
id bigserial PRIMARY KEY,
sender_pid integer,
recipient_pid integer,

View File

@ -2,129 +2,102 @@ package database_wiiu
import (
"database/sql"
"time"
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/friends/globals"
"github.com/PretendoNetwork/friends/utility"
"github.com/PretendoNetwork/nex-go"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// AcceptFriendRequestAndReturnFriendInfo accepts the given friend reuqest and returns the friend's information
func AcceptFriendRequestAndReturnFriendInfo(friendRequestID uint64) (*friends_wiiu_types.FriendInfo, error) {
func AcceptFriendRequestAndReturnFriendInfo(friendRequestID uint64) (friends_wiiu_types.FriendInfo, error) {
var senderPID uint32
var recipientPID uint32
err := database.Postgres.QueryRow(`SELECT sender_pid, recipient_pid FROM wiiu.friend_requests WHERE id=$1`, friendRequestID).Scan(&senderPID, &recipientPID)
row, err := database.Manager.QueryRow(`SELECT sender_pid, recipient_pid FROM wiiu.friend_requests WHERE id=$1`, friendRequestID)
if err != nil {
return friends_wiiu_types.NewFriendInfo(), err
}
err = row.Scan(&senderPID, &recipientPID)
if err != nil {
if err == sql.ErrNoRows {
return nil, database.ErrFriendRequestNotFound
return friends_wiiu_types.NewFriendInfo(), database.ErrFriendRequestNotFound
} else {
return nil, err
return friends_wiiu_types.NewFriendInfo(), err
}
}
acceptedTime := nex.NewDateTime(0)
acceptedTime.FromTimestamp(time.Now())
acceptedTime := types.NewDateTime(0).Now()
// Friendships are two-way relationships, not just one link between 2 entities
// "A" has friend "B" and "B" has friend "A", so store both relationships
// * Friendships are two-way relationships, not just one link between 2 entities
// * "A" has friend "B" and "B" has friend "A", so store both relationships
// If were friends before, just activate the status again
// * If were friends before, just activate the status again
_, err = database.Postgres.Exec(`
_, err = database.Manager.Exec(`
INSERT INTO wiiu.friendships (user1_pid, user2_pid, date, active)
VALUES ($1, $2, $3, true)
ON CONFLICT (user1_pid, user2_pid)
DO UPDATE SET
date = $3,
active = true`, senderPID, recipientPID, acceptedTime.Value())
active = true`, senderPID, recipientPID, uint64(acceptedTime))
if err != nil {
return nil, err
return friends_wiiu_types.NewFriendInfo(), err
}
_, err = database.Postgres.Exec(`
_, err = database.Manager.Exec(`
INSERT INTO wiiu.friendships (user1_pid, user2_pid, date, active)
VALUES ($1, $2, $3, true)
ON CONFLICT (user1_pid, user2_pid)
DO UPDATE SET
date = $3,
active = true`, recipientPID, senderPID, acceptedTime.Value())
active = true`, recipientPID, senderPID, uint64(acceptedTime))
if err != nil {
return nil, err
return friends_wiiu_types.NewFriendInfo(), err
}
err = SetFriendRequestAccepted(friendRequestID)
if err != nil {
return nil, err
return friends_wiiu_types.NewFriendInfo(), err
}
friendInfo := friends_wiiu_types.NewFriendInfo()
connectedUser := globals.ConnectedUsers[senderPID]
var lastOnline *nex.DateTime
connectedUser, ok := globals.ConnectedUsers.Get(senderPID)
lastOnline := types.NewDateTime(0).Now()
if connectedUser != nil {
// Online
friendInfo.NNAInfo = connectedUser.NNAInfo
friendInfo.Presence = connectedUser.PresenceV2
lastOnline = nex.NewDateTime(0)
lastOnline.FromTimestamp(time.Now())
if ok && connectedUser != nil {
// * Online
friendInfo.Presence = connectedUser.PresenceV2.Copy().(friends_wiiu_types.NintendoPresenceV2)
} else {
// Offline
userInfo, err := utility.GetUserInfoByPID(senderPID)
// * Offline
var lastOnlineTime uint64
row, err = database.Manager.QueryRow(`SELECT last_online FROM wiiu.user_data WHERE pid=$1`, senderPID)
if err != nil {
return nil, err
return friends_wiiu_types.NewFriendInfo(), err
}
friendInfo.NNAInfo = friends_wiiu_types.NewNNAInfo()
friendInfo.NNAInfo.PrincipalBasicInfo = userInfo
friendInfo.NNAInfo.Unknown1 = 0
friendInfo.NNAInfo.Unknown2 = 0
friendInfo.Presence = friends_wiiu_types.NewNintendoPresenceV2()
friendInfo.Presence.ChangedFlags = 0
friendInfo.Presence.Online = false
friendInfo.Presence.GameKey = friends_wiiu_types.NewGameKey()
friendInfo.Presence.GameKey.TitleID = 0
friendInfo.Presence.GameKey.TitleVersion = 0
friendInfo.Presence.Unknown1 = 0
friendInfo.Presence.Message = ""
friendInfo.Presence.Unknown2 = 0
friendInfo.Presence.Unknown3 = 0
friendInfo.Presence.GameServerID = 0
friendInfo.Presence.Unknown4 = 0
friendInfo.Presence.PID = senderPID
friendInfo.Presence.GatheringID = 0
friendInfo.Presence.ApplicationData = make([]byte, 0)
friendInfo.Presence.Unknown5 = 0
friendInfo.Presence.Unknown6 = 0
friendInfo.Presence.Unknown7 = 0
var lastOnlineTime uint64
err = database.Postgres.QueryRow(`SELECT last_online FROM wiiu.user_data WHERE pid=$1`, senderPID).Scan(&lastOnlineTime)
err = row.Scan(&lastOnlineTime)
if err != nil {
if err == sql.ErrNoRows {
return nil, database.ErrPIDNotFound
return friends_wiiu_types.NewFriendInfo(), database.ErrPIDNotFound
} else {
return nil, err
return friends_wiiu_types.NewFriendInfo(), err
}
}
lastOnline = nex.NewDateTime(lastOnlineTime) // TODO: Change this
lastOnline = types.NewDateTime(lastOnlineTime) // TODO - Change this
}
status, err := GetUserComment(senderPID)
if err != nil {
return nil, err
return friends_wiiu_types.NewFriendInfo(), err
}
friendInfo.Status = status
friendInfo.BecameFriend = acceptedTime
friendInfo.LastOnline = lastOnline // TODO: Change this
friendInfo.Unknown = 0
friendInfo.LastOnline = lastOnline // TODO - Change this
friendInfo.Unknown = types.NewUInt64(0)
return friendInfo, nil
}

View File

@ -10,7 +10,12 @@ import (
func DeleteFriendRequestAndReturnFriendPID(friendRequestID uint64) (uint32, error) {
var recipientPID uint32
err := database.Postgres.QueryRow(`SELECT recipient_pid FROM wiiu.friend_requests WHERE id=$1`, friendRequestID).Scan(&recipientPID)
row, err := database.Manager.QueryRow(`SELECT recipient_pid FROM wiiu.friend_requests WHERE id=$1`, friendRequestID)
if err != nil {
return 0, err
}
err = row.Scan(&recipientPID)
if err != nil {
if err == sql.ErrNoRows {
return 0, database.ErrFriendRequestNotFound
@ -19,7 +24,7 @@ func DeleteFriendRequestAndReturnFriendPID(friendRequestID uint64) (uint32, erro
}
}
result, err := database.Postgres.Exec(`
result, err := database.Manager.Exec(`
DELETE FROM wiiu.friend_requests WHERE id=$1`, friendRequestID)
if err != nil {
return 0, err

View File

@ -11,9 +11,12 @@ func GetPIDsByFriendRequestID(friendRequestID uint64) (uint32, uint32, error) {
var senderPID uint32
var recipientPID uint32
err := database.Postgres.QueryRow(`
SELECT sender_pid, recipient_pid FROM wiiu.friend_requests WHERE id=$1
`, friendRequestID).Scan(&senderPID, &recipientPID)
row, err := database.Manager.QueryRow(`SELECT sender_pid, recipient_pid FROM wiiu.friend_requests WHERE id=$1`, friendRequestID)
if err != nil {
return 0, 0, err
}
err = row.Scan(&senderPID, &recipientPID)
if err != nil {
if err == sql.ErrNoRows {
return 0, 0, database.ErrFriendRequestNotFound

View File

@ -4,16 +4,24 @@ import (
"database/sql"
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/friends/utility"
"github.com/PretendoNetwork/nex-go"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// GetUserBlockList returns a user's blacklist
func GetUserBlockList(pid uint32) ([]*friends_wiiu_types.BlacklistedPrincipal, error) {
blockList := make([]*friends_wiiu_types.BlacklistedPrincipal, 0)
func GetUserBlockList(pid uint32) (types.List[friends_wiiu_types.BlacklistedPrincipal], error) {
blockList := types.NewList[friends_wiiu_types.BlacklistedPrincipal]()
rows, err := database.Postgres.Query(`SELECT blocked_pid, title_id, title_version, date FROM wiiu.blocks WHERE blocker_pid=$1`, pid)
rows, err := database.Manager.Query(`
SELECT
b.blocked_pid, b.title_id, b.title_version, b.date,
bi.username, bi.unknown,
mii.name, mii.unknown1, mii.unknown2, mii.data, mii.unknown_datetime
FROM wiiu.blocks AS b
INNER JOIN wiiu.principal_basic_info AS bi ON bi.pid = b.blocked_pid
INNER JOIN wiiu.mii AS mii ON mii.pid = b.blocked_pid
WHERE blocker_pid=$1
`, pid)
if err != nil {
if err == sql.ErrNoRows {
return blockList, database.ErrBlacklistNotFound
@ -21,27 +29,47 @@ func GetUserBlockList(pid uint32) ([]*friends_wiiu_types.BlacklistedPrincipal, e
return blockList, err
}
}
defer rows.Close()
for rows.Next() {
var pid uint32
var titleId uint64
var blockedPID uint32
var titleID uint64
var titleVersion uint16
var date *nex.DateTime
rows.Scan(&pid, &titleId, &titleVersion, &date)
var date uint64
userInfo, err := utility.GetUserInfoByPID(pid)
var blockedNNID string
var unknown uint8
var miiName string
var miiUnknown1 uint8
var miiUnknown2 uint8
var miiData []byte
var miiDatetime uint64
err := rows.Scan(&blockedPID, &titleID, &titleVersion, &date, &blockedNNID, &unknown, &miiName, &miiUnknown1, &miiUnknown2, &miiData, &miiDatetime)
if err != nil {
return nil, err
}
mii := friends_wiiu_types.NewMiiV2()
mii.Name = types.NewString(miiName)
mii.Unknown1 = types.NewUInt8(miiUnknown1)
mii.Unknown2 = types.NewUInt8(miiUnknown2)
mii.MiiData = types.NewBuffer(miiData)
mii.Datetime = types.NewDateTime(miiDatetime)
principalBasicInfo := friends_wiiu_types.NewPrincipalBasicInfo()
principalBasicInfo.PID = types.NewPID(uint64(blockedPID))
principalBasicInfo.NNID = types.NewString(blockedNNID)
principalBasicInfo.Unknown = types.NewUInt8(unknown)
principalBasicInfo.Mii = mii
blacklistPrincipal := friends_wiiu_types.NewBlacklistedPrincipal()
blacklistPrincipal.PrincipalBasicInfo = userInfo
blacklistPrincipal.PrincipalBasicInfo = principalBasicInfo
blacklistPrincipal.GameKey = friends_wiiu_types.NewGameKey()
blacklistPrincipal.GameKey.TitleID = titleId
blacklistPrincipal.GameKey.TitleVersion = titleVersion
blacklistPrincipal.BlackListedSince = date
blacklistPrincipal.GameKey.TitleID = types.NewUInt64(titleID)
blacklistPrincipal.GameKey.TitleVersion = types.NewUInt16(titleVersion)
blacklistPrincipal.BlackListedSince = types.NewDateTime(date)
blockList = append(blockList, blacklistPrincipal)
}

View File

@ -4,27 +4,33 @@ import (
"database/sql"
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// GetUserComment returns a user's comment
func GetUserComment(pid uint32) (*friends_wiiu_types.Comment, error) {
func GetUserComment(pid uint32) (friends_wiiu_types.Comment, error) {
comment := friends_wiiu_types.NewComment()
comment.Unknown = 0
var contents string
var changed uint64 = 0
err := database.Postgres.QueryRow(`SELECT comment, comment_changed FROM wiiu.user_data WHERE pid=$1`, pid).Scan(&comment.Contents, &changed)
row, err := database.Manager.QueryRow(`SELECT comment, comment_changed FROM wiiu.user_data WHERE pid=$1`, pid)
if err != nil {
return comment, err
}
err = row.Scan(&contents, &changed)
if err != nil {
if err == sql.ErrNoRows {
return nil, database.ErrPIDNotFound
return comment, database.ErrPIDNotFound
} else {
return nil, err
return comment, err
}
}
comment.LastChanged = nex.NewDateTime(changed)
comment.Contents = types.NewString(contents)
comment.LastChanged = types.NewDateTime(changed)
return comment, nil
}

View File

@ -2,21 +2,34 @@ package database_wiiu
import (
"database/sql"
"fmt"
"time"
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/friends/globals"
"github.com/PretendoNetwork/friends/utility"
"github.com/PretendoNetwork/nex-go"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// GetUserFriendList returns a user's friend list
func GetUserFriendList(pid uint32) ([]*friends_wiiu_types.FriendInfo, error) {
friendList := make([]*friends_wiiu_types.FriendInfo, 0)
func GetUserFriendList(pid uint32) (types.List[friends_wiiu_types.FriendInfo], error) {
friendList := types.NewList[friends_wiiu_types.FriendInfo]()
rows, err := database.Manager.Query(`
SELECT
f.user2_pid, f.date,
u.comment, u.comment_changed,
u.last_online,
bi.username, bi.unknown,
ai.unknown1, ai.unknown2,
mii.name, mii.unknown1, mii.unknown2, mii.data, mii.unknown_datetime
FROM wiiu.friendships AS f
INNER JOIN wiiu.user_data AS u ON u.pid = f.user2_pid
INNER JOIN wiiu.principal_basic_info AS bi ON bi.pid = f.user2_pid
INNER JOIN wiiu.network_account_info AS ai ON ai.pid = f.user2_pid
INNER JOIN wiiu.mii AS mii ON mii.pid = f.user2_pid
WHERE f.user1_pid=$1 AND f.active=true
LIMIT 100
`, pid)
rows, err := database.Postgres.Query(`SELECT user2_pid, date FROM wiiu.friendships WHERE user1_pid=$1 AND active=true LIMIT 100`, pid)
if err != nil {
if err == sql.ErrNoRows {
return friendList, database.ErrEmptyList
@ -24,87 +37,69 @@ func GetUserFriendList(pid uint32) ([]*friends_wiiu_types.FriendInfo, error) {
return friendList, err
}
}
defer rows.Close()
for rows.Next() {
var friendPID uint32
var date uint64
rows.Scan(&friendPID, &date)
var lastOnlineTime uint64
var commentContents string
var commentChanged uint64 = 0
var nnid string
var unknown uint8
var unknown1 uint8
var unknown2 uint8
var miiName string
var miiUnknown1 uint8
var miiUnknown2 uint8
var miiData []byte
var miiDatetime uint64
friendInfo := friends_wiiu_types.NewFriendInfo()
connectedUser := globals.ConnectedUsers[friendPID]
var lastOnline *nex.DateTime
if connectedUser != nil {
// Online
friendInfo.NNAInfo = connectedUser.NNAInfo
friendInfo.Presence = connectedUser.PresenceV2
if friendInfo.NNAInfo == nil || friendInfo.NNAInfo.PrincipalBasicInfo == nil {
// TODO: Fix this
globals.Logger.Error(fmt.Sprintf("User %d has friend %d with bad presence data", pid, friendPID))
if friendInfo.NNAInfo == nil {
globals.Logger.Error(fmt.Sprintf("%d friendInfo.NNAInfo is nil", friendPID))
} else {
globals.Logger.Error(fmt.Sprintf("%d friendInfo.NNAInfo.PrincipalBasicInfo is nil", friendPID))
}
continue
}
lastOnline = nex.NewDateTime(0)
lastOnline.FromTimestamp(time.Now())
} else {
// Offline
userInfo, err := utility.GetUserInfoByPID(friendPID)
if err != nil {
return nil, err
}
friendInfo.NNAInfo = friends_wiiu_types.NewNNAInfo()
friendInfo.NNAInfo.PrincipalBasicInfo = userInfo
friendInfo.NNAInfo.Unknown1 = 0
friendInfo.NNAInfo.Unknown2 = 0
friendInfo.Presence = friends_wiiu_types.NewNintendoPresenceV2()
friendInfo.Presence.ChangedFlags = 0
friendInfo.Presence.Online = false
friendInfo.Presence.GameKey = friends_wiiu_types.NewGameKey()
friendInfo.Presence.GameKey.TitleID = 0
friendInfo.Presence.GameKey.TitleVersion = 0
friendInfo.Presence.Unknown1 = 0
friendInfo.Presence.Message = ""
friendInfo.Presence.Unknown2 = 0
friendInfo.Presence.Unknown3 = 0
friendInfo.Presence.GameServerID = 0
friendInfo.Presence.Unknown4 = 0
friendInfo.Presence.PID = 0
friendInfo.Presence.GatheringID = 0
friendInfo.Presence.ApplicationData = []byte{0x00}
friendInfo.Presence.Unknown5 = 0
friendInfo.Presence.Unknown6 = 0
friendInfo.Presence.Unknown7 = 0
var lastOnlineTime uint64
err = database.Postgres.QueryRow(`SELECT last_online FROM wiiu.user_data WHERE pid=$1`, friendPID).Scan(&lastOnlineTime)
if err != nil {
return nil, err
}
lastOnline = nex.NewDateTime(lastOnlineTime) // TODO: Change this
}
status, err := GetUserComment(friendPID)
err := rows.Scan(&friendPID, &date, &commentContents, &commentChanged, &lastOnlineTime, &nnid, &unknown, &unknown1, &unknown2, &miiName, &miiUnknown1, &miiUnknown2, &miiData, &miiDatetime)
if err != nil {
return nil, err
}
friendInfo.Status = status
comment := friends_wiiu_types.NewComment()
comment.Unknown = types.NewUInt8(0)
comment.Contents = types.NewString(commentContents)
comment.LastChanged = types.NewDateTime(commentChanged)
friendInfo.BecameFriend = nex.NewDateTime(date)
mii := friends_wiiu_types.NewMiiV2()
mii.Name = types.NewString(miiName)
mii.Unknown1 = types.NewUInt8(miiUnknown1)
mii.Unknown2 = types.NewUInt8(miiUnknown2)
mii.MiiData = types.NewBuffer(miiData)
mii.Datetime = types.NewDateTime(miiDatetime)
principalBasicInfo := friends_wiiu_types.NewPrincipalBasicInfo()
principalBasicInfo.PID = types.NewPID(uint64(friendPID))
principalBasicInfo.NNID = types.NewString(nnid)
principalBasicInfo.Unknown = types.NewUInt8(unknown)
principalBasicInfo.Mii = mii
nnaInfo := friends_wiiu_types.NewNNAInfo()
nnaInfo.Unknown1 = types.NewUInt8(unknown1)
nnaInfo.Unknown2 = types.NewUInt8(unknown2)
nnaInfo.PrincipalBasicInfo = principalBasicInfo
friendInfo := friends_wiiu_types.NewFriendInfo()
friendInfo.NNAInfo = nnaInfo
lastOnline := types.NewDateTime(0).Now()
connectedUser, ok := globals.ConnectedUsers.Get(friendPID)
if ok && connectedUser != nil {
// * Online
friendInfo.Presence = connectedUser.PresenceV2.Copy().(friends_wiiu_types.NintendoPresenceV2)
} else {
// * Offline
lastOnline = types.NewDateTime(lastOnlineTime) // TODO - Change this
}
friendInfo.Status = comment
friendInfo.BecameFriend = types.NewDateTime(date)
friendInfo.LastOnline = lastOnline
friendInfo.Unknown = 0
friendInfo.Unknown = types.NewUInt64(0)
friendList = append(friendList, friendInfo)
}

View File

@ -10,7 +10,7 @@ import (
func GetUserFriendPIDs(pid uint32) ([]uint32, error) {
pids := make([]uint32, 0)
rows, err := database.Postgres.Query(`SELECT user2_pid FROM wiiu.friendships WHERE user1_pid=$1 AND active=true LIMIT 100`, pid)
rows, err := database.Manager.Query(`SELECT user2_pid FROM wiiu.friendships WHERE user1_pid=$1 AND active=true LIMIT 100`, pid)
if err != nil {
if err == sql.ErrNoRows {
return pids, database.ErrEmptyList
@ -22,7 +22,11 @@ func GetUserFriendPIDs(pid uint32) ([]uint32, error) {
for rows.Next() {
var pid uint32
rows.Scan(&pid)
err := rows.Scan(&pid)
if err != nil {
return pids, err
}
pids = append(pids, pid)
}

View File

@ -5,23 +5,33 @@ import (
"time"
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/friends/utility"
"github.com/PretendoNetwork/nex-go"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// GetUserFriendRequestsIn returns the friend requests received by a user
func GetUserFriendRequestsIn(pid uint32) ([]*friends_wiiu_types.FriendRequest, error) {
friendRequestsIn := make([]*friends_wiiu_types.FriendRequest, 0)
func GetUserFriendRequestsIn(pid uint32) (types.List[friends_wiiu_types.FriendRequest], error) {
friendRequests := types.NewList[friends_wiiu_types.FriendRequest]()
rows, err := database.Postgres.Query(`SELECT id, sender_pid, sent_on, expires_on, message, received FROM wiiu.friend_requests WHERE recipient_pid=$1 AND accepted=false AND denied=false`, pid)
rows, err := database.Manager.Query(`
SELECT
fr.id, fr.sender_pid, fr.sent_on, fr.expires_on, fr.message, fr.received,
bi.username, bi.unknown,
mii.name, mii.unknown1, mii.unknown2, mii.data, mii.unknown_datetime
FROM wiiu.friend_requests AS fr
INNER JOIN wiiu.principal_basic_info AS bi ON bi.pid = fr.sender_pid
INNER JOIN wiiu.mii AS mii ON mii.pid = fr.sender_pid
WHERE recipient_pid=$1 AND accepted=false AND denied=false
LIMIT 100
`, pid)
if err != nil {
if err == sql.ErrNoRows {
return friendRequestsIn, database.ErrEmptyList
return friendRequests, database.ErrEmptyList
} else {
return friendRequestsIn, err
return friendRequests, err
}
}
defer rows.Close()
for rows.Next() {
var id uint64
@ -30,35 +40,55 @@ func GetUserFriendRequestsIn(pid uint32) ([]*friends_wiiu_types.FriendRequest, e
var expiresOn uint64
var message string
var received bool
rows.Scan(&id, &senderPID, &sentOn, &expiresOn, &message, &received)
userInfo, err := utility.GetUserInfoByPID(senderPID)
var senderNNID string
var unknown uint8
var miiName string
var miiUnknown1 uint8
var miiUnknown2 uint8
var miiData []byte
var miiDatetime uint64
err := rows.Scan(&id, &senderPID, &sentOn, &expiresOn, &message, &received, &senderNNID, &unknown, &miiName, &miiUnknown1, &miiUnknown2, &miiData, &miiDatetime)
if err != nil {
return nil, err
return friendRequests, err
}
friendRequest := friends_wiiu_types.NewFriendRequest()
mii := friends_wiiu_types.NewMiiV2()
mii.Name = types.NewString(miiName)
mii.Unknown1 = types.NewUInt8(miiUnknown1)
mii.Unknown2 = types.NewUInt8(miiUnknown2)
mii.MiiData = types.NewBuffer(miiData)
mii.Datetime = types.NewDateTime(miiDatetime)
friendRequest.PrincipalInfo = userInfo
principalBasicInfo := friends_wiiu_types.NewPrincipalBasicInfo()
principalBasicInfo.PID = types.NewPID(uint64(senderPID))
principalBasicInfo.NNID = types.NewString(senderNNID)
principalBasicInfo.Unknown = types.NewUInt8(unknown)
principalBasicInfo.Mii = mii
friendRequest := friends_wiiu_types.NewFriendRequest()
friendRequest.PrincipalInfo = principalBasicInfo
friendRequest.Message = friends_wiiu_types.NewFriendRequestMessage()
friendRequest.Message.FriendRequestID = id
friendRequest.Message.Received = received
friendRequest.Message.Unknown2 = 1
friendRequest.Message.Message = message
friendRequest.Message.Unknown3 = 0
friendRequest.Message.Unknown4 = ""
friendRequest.Message.FriendRequestID = types.NewUInt64(id)
friendRequest.Message.Received = types.NewBool(received)
friendRequest.Message.Unknown2 = types.NewUInt8(1)
friendRequest.Message.Message = types.NewString(message)
friendRequest.Message.Unknown3 = types.NewUInt8(0)
friendRequest.Message.Unknown4 = types.NewString("")
friendRequest.Message.GameKey = friends_wiiu_types.NewGameKey()
friendRequest.Message.GameKey.TitleID = 0
friendRequest.Message.GameKey.TitleVersion = 0
friendRequest.Message.Unknown5 = nex.NewDateTime(134222053376) // idk what this value means but its always this
friendRequest.Message.ExpiresOn = nex.NewDateTime(expiresOn)
friendRequest.SentOn = nex.NewDateTime(sentOn)
friendRequest.Message.GameKey.TitleID = types.NewUInt64(0)
friendRequest.Message.GameKey.TitleVersion = types.NewUInt16(0)
friendRequest.Message.Unknown5 = types.NewDateTime(134222053376) // * idk what this value means but its always this
friendRequest.Message.ExpiresOn = types.NewDateTime(expiresOn)
friendRequest.SentOn = types.NewDateTime(sentOn)
// * Filter out expired requests
if friendRequest.Message.ExpiresOn.Standard().After(time.Now()) {
friendRequestsIn = append(friendRequestsIn, friendRequest)
friendRequests = append(friendRequests, friendRequest)
}
}
return friendRequestsIn, nil
return friendRequests, nil
}

View File

@ -4,23 +4,33 @@ import (
"database/sql"
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/friends/utility"
"github.com/PretendoNetwork/nex-go"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// GetUserFriendRequestsOut returns the friend requests sent by a user
func GetUserFriendRequestsOut(pid uint32) ([]*friends_wiiu_types.FriendRequest, error) {
friendRequestsOut := make([]*friends_wiiu_types.FriendRequest, 0)
func GetUserFriendRequestsOut(pid uint32) (types.List[friends_wiiu_types.FriendRequest], error) {
friendRequests := types.NewList[friends_wiiu_types.FriendRequest]()
rows, err := database.Postgres.Query(`SELECT id, recipient_pid, sent_on, expires_on, message, received FROM wiiu.friend_requests WHERE sender_pid=$1 AND accepted=false`, pid)
rows, err := database.Manager.Query(`
SELECT
fr.id, fr.recipient_pid, fr.sent_on, fr.expires_on, fr.message, fr.received,
bi.username, bi.unknown,
mii.name, mii.unknown1, mii.unknown2, mii.data, mii.unknown_datetime
FROM wiiu.friend_requests AS fr
INNER JOIN wiiu.principal_basic_info AS bi ON bi.pid = fr.recipient_pid
INNER JOIN wiiu.mii AS mii ON mii.pid = fr.recipient_pid
WHERE sender_pid=$1 AND accepted=false
LIMIT 100
`, pid)
if err != nil {
if err == sql.ErrNoRows {
return friendRequestsOut, database.ErrEmptyList
return friendRequests, database.ErrEmptyList
} else {
return friendRequestsOut, err
return friendRequests, err
}
}
defer rows.Close()
for rows.Next() {
var id uint64
@ -29,32 +39,52 @@ func GetUserFriendRequestsOut(pid uint32) ([]*friends_wiiu_types.FriendRequest,
var expiresOn uint64
var message string
var received bool
rows.Scan(&id, &recipientPID, &sentOn, &expiresOn, &message, &received)
userInfo, err := utility.GetUserInfoByPID(recipientPID)
var recipientNNID string
var unknown uint8
var miiName string
var miiUnknown1 uint8
var miiUnknown2 uint8
var miiData []byte
var miiDatetime uint64
err := rows.Scan(&id, &recipientPID, &sentOn, &expiresOn, &message, &received, &recipientNNID, &unknown, &miiName, &miiUnknown1, &miiUnknown2, &miiData, &miiDatetime)
if err != nil {
return nil, err
return friendRequests, err
}
mii := friends_wiiu_types.NewMiiV2()
mii.Name = types.NewString(miiName)
mii.Unknown1 = types.NewUInt8(miiUnknown1)
mii.Unknown2 = types.NewUInt8(miiUnknown2)
mii.MiiData = types.NewBuffer(miiData)
mii.Datetime = types.NewDateTime(miiDatetime)
principalBasicInfo := friends_wiiu_types.NewPrincipalBasicInfo()
principalBasicInfo.PID = types.NewPID(uint64(recipientPID))
principalBasicInfo.NNID = types.NewString(recipientNNID)
principalBasicInfo.Unknown = types.NewUInt8(unknown)
principalBasicInfo.Mii = mii
friendRequest := friends_wiiu_types.NewFriendRequest()
friendRequest.PrincipalInfo = userInfo
friendRequest.PrincipalInfo = principalBasicInfo
friendRequest.Message = friends_wiiu_types.NewFriendRequestMessage()
friendRequest.Message.FriendRequestID = id
friendRequest.Message.Received = received
friendRequest.Message.Unknown2 = 1
friendRequest.Message.Message = message
friendRequest.Message.Unknown3 = 0
friendRequest.Message.Unknown4 = ""
friendRequest.Message.FriendRequestID = types.NewUInt64(id)
friendRequest.Message.Received = types.NewBool(received)
friendRequest.Message.Unknown2 = types.NewUInt8(1)
friendRequest.Message.Message = types.NewString(message)
friendRequest.Message.Unknown3 = types.NewUInt8(0)
friendRequest.Message.Unknown4 = types.NewString("")
friendRequest.Message.GameKey = friends_wiiu_types.NewGameKey()
friendRequest.Message.GameKey.TitleID = 0
friendRequest.Message.GameKey.TitleVersion = 0
friendRequest.Message.Unknown5 = nex.NewDateTime(134222053376) // idk what this value means but its always this
friendRequest.Message.ExpiresOn = nex.NewDateTime(expiresOn)
friendRequest.SentOn = nex.NewDateTime(sentOn)
friendRequest.Message.GameKey.TitleID = types.NewUInt64(0)
friendRequest.Message.GameKey.TitleVersion = types.NewUInt16(0)
friendRequest.Message.Unknown5 = types.NewDateTime(134222053376) // * idk what this value means but its always this
friendRequest.Message.ExpiresOn = types.NewDateTime(expiresOn)
friendRequest.SentOn = types.NewDateTime(sentOn)
friendRequestsOut = append(friendRequestsOut, friendRequest)
friendRequests = append(friendRequests, friendRequest)
}
return friendRequestsOut, nil
return friendRequests, nil
}

View File

@ -0,0 +1,42 @@
package database_wiiu
import (
"database/sql"
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// GetUserMii returns the users Mii
func GetUserMii(pid uint32) (friends_wiiu_types.MiiV2, error) {
mii := friends_wiiu_types.NewMiiV2()
var name string
var unknown1 uint8
var unknown2 uint8
var data []byte
var datetime uint64
row, err := database.Manager.QueryRow(`SELECT name, unknown1, unknown2, data, unknown_datetime FROM wiiu.mii WHERE pid=$1`, pid)
if err != nil {
return mii, err
}
err = row.Scan(&name, &unknown1, &unknown2, &data, &datetime)
if err != nil {
if err == sql.ErrNoRows {
return mii, database.ErrPIDNotFound
} else {
return mii, err
}
}
mii.Name = types.NewString(name)
mii.Unknown1 = types.NewUInt8(unknown1)
mii.Unknown2 = types.NewUInt8(unknown2)
mii.MiiData = types.NewBuffer(data)
mii.Datetime = types.NewDateTime(datetime)
return mii, nil
}

View File

@ -0,0 +1,40 @@
package database_wiiu
import (
"database/sql"
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// GetUserNetworkAccountInfo returns the users network account info
func GetUserNetworkAccountInfo(pid uint32) (friends_wiiu_types.NNAInfo, error) {
nnaInfo := friends_wiiu_types.NewNNAInfo()
var unknown1 uint8
var unknown2 uint8
row, err := database.Manager.QueryRow(`SELECT unknown1, unknown2 FROM wiiu.network_account_info WHERE pid=$1`, pid)
if err != nil {
return nnaInfo, err
}
err = row.Scan(&unknown1, &unknown2)
if err != nil {
if err == sql.ErrNoRows {
return nnaInfo, database.ErrPIDNotFound
} else {
return nnaInfo, err
}
}
nnaInfo.Unknown1 = types.NewUInt8(unknown1)
nnaInfo.Unknown2 = types.NewUInt8(unknown2)
nnaInfo.PrincipalBasicInfo, err = GetUserPrincipalBasicInfo(pid)
if err != nil {
return nnaInfo, err
}
return nnaInfo, nil
}

View File

@ -1,8 +1,14 @@
package database_wiiu
import friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
import (
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// GetUserNotifications returns notifications for a user
func GetUserNotifications(pid uint32) []*friends_wiiu_types.PersistentNotification {
return make([]*friends_wiiu_types.PersistentNotification, 0)
func GetUserNotifications(pid uint32) types.List[friends_wiiu_types.PersistentNotification] {
// TODO - Do this
notifications := types.NewList[friends_wiiu_types.PersistentNotification]()
return notifications
}

View File

@ -0,0 +1,41 @@
package database_wiiu
import (
"database/sql"
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// GetUserPrincipalBasicInfo returns the users basic info
func GetUserPrincipalBasicInfo(pid uint32) (friends_wiiu_types.PrincipalBasicInfo, error) {
principalBasicInfo := friends_wiiu_types.NewPrincipalBasicInfo()
var nnid string
var unknown uint8
row, err := database.Manager.QueryRow(`SELECT username, unknown FROM wiiu.principal_basic_info WHERE pid=$1`, pid)
if err != nil {
return principalBasicInfo, err
}
err = row.Scan(&nnid, &unknown)
if err != nil {
if err == sql.ErrNoRows {
return principalBasicInfo, database.ErrPIDNotFound
} else {
return principalBasicInfo, err
}
}
principalBasicInfo.PID = types.NewPID(uint64(pid))
principalBasicInfo.NNID = types.NewString(nnid)
principalBasicInfo.Unknown = types.NewUInt8(unknown)
principalBasicInfo.Mii, err = GetUserMii(pid)
if err != nil {
return principalBasicInfo, err
}
return principalBasicInfo, nil
}

View File

@ -4,21 +4,35 @@ import (
"database/sql"
"github.com/PretendoNetwork/friends/database"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// GetUserPrincipalPreference returns the user preferences
func GetUserPrincipalPreference(pid uint32) (*friends_wiiu_types.PrincipalPreference, error) {
func GetUserPrincipalPreference(pid uint32) (friends_wiiu_types.PrincipalPreference, error) {
preference := friends_wiiu_types.NewPrincipalPreference()
err := database.Postgres.QueryRow(`SELECT show_online, show_current_game, block_friend_requests FROM wiiu.user_data WHERE pid=$1`, pid).Scan(&preference.ShowOnlinePresence, &preference.ShowCurrentTitle, &preference.BlockFriendRequests)
var showOnlinePresence bool
var showCurrentTitle bool
var blockFriendRequests bool
row, err := database.Manager.QueryRow(`SELECT show_online, show_current_game, block_friend_requests FROM wiiu.user_data WHERE pid=$1`, pid)
if err != nil {
return preference, err
}
err = row.Scan(&showOnlinePresence, &showCurrentTitle, &blockFriendRequests)
if err != nil {
if err == sql.ErrNoRows {
return nil, database.ErrPIDNotFound
return preference, database.ErrPIDNotFound
} else {
return nil, err
return preference, err
}
}
preference.ShowOnlinePresence = types.NewBool(showOnlinePresence)
preference.ShowCurrentTitle = types.NewBool(showCurrentTitle)
preference.BlockFriendRequests = types.NewBool(blockFriendRequests)
return preference, nil
}

View File

@ -7,7 +7,13 @@ import (
// IsFriendRequestBlocked determines if a requester PID has blocked a requested PID
func IsFriendRequestBlocked(requesterPID uint32, requestedPID uint32) (bool, error) {
var found bool
err := database.Postgres.QueryRow(`SELECT COUNT(*) FROM wiiu.blocks WHERE blocker_pid=$1 AND blocked_pid=$2 LIMIT 1`, requesterPID, requestedPID).Scan(&found)
row, err := database.Manager.QueryRow(`SELECT COUNT(*) FROM wiiu.blocks WHERE blocker_pid=$1 AND blocked_pid=$2 LIMIT 1`, requesterPID, requestedPID)
if err != nil {
return false, err
}
err = row.Scan(&found)
if err != nil {
return false, err
}

View File

@ -6,7 +6,7 @@ import (
// RemoveFriendship removes a user's friend relationship
func RemoveFriendship(user1_pid uint32, user2_pid uint32) error {
result, err := database.Postgres.Exec(`
result, err := database.Manager.Exec(`
DELETE FROM wiiu.friendships WHERE user1_pid=$1 AND user2_pid=$2`, user1_pid, user2_pid)
if err != nil {
return err
@ -17,7 +17,7 @@ func RemoveFriendship(user1_pid uint32, user2_pid uint32) error {
return database.ErrFriendshipNotFound
}
_, err = database.Postgres.Exec(`
_, err = database.Manager.Exec(`
UPDATE wiiu.friendships SET active=false WHERE user1_pid=$1 AND user2_pid=$2`, user2_pid, user1_pid)
if err != nil {
return err

View File

@ -16,7 +16,12 @@ func SaveFriendRequest(senderPID uint32, recipientPID uint32, sentTime uint64, e
}
// Make sure we don't already have that friend request! If we do, give them the one we already have.
err = database.Postgres.QueryRow(`SELECT id FROM wiiu.friend_requests WHERE sender_pid=$1 AND recipient_pid=$2`, senderPID, recipientPID).Scan(&id)
row, err := database.Manager.QueryRow(`SELECT id FROM wiiu.friend_requests WHERE sender_pid=$1 AND recipient_pid=$2`, senderPID, recipientPID)
if err != nil {
return 0, err
}
err = row.Scan(&id)
if err != nil && err != sql.ErrNoRows {
return 0, err
} else if id != 0 {
@ -33,9 +38,14 @@ func SaveFriendRequest(senderPID uint32, recipientPID uint32, sentTime uint64, e
}
}
err = database.Postgres.QueryRow(`
row, err = database.Manager.QueryRow(`
INSERT INTO wiiu.friend_requests (sender_pid, recipient_pid, sent_on, expires_on, message, received, accepted, denied)
VALUES ($1, $2, $3, $4, $5, false, false, $6) RETURNING id`, senderPID, recipientPID, sentTime, expireTime, message, friendRequestBlocked).Scan(&id)
VALUES ($1, $2, $3, $4, $5, false, false, $6) RETURNING id`, senderPID, recipientPID, sentTime, expireTime, message, friendRequestBlocked)
if err != nil {
return 0, err
}
err = row.Scan(&id)
if err != nil {
return 0, err
}

View File

@ -6,7 +6,7 @@ import (
// SetFriendRequestAccepted marks a friend request as accepted
func SetFriendRequestAccepted(friendRequestID uint64) error {
result, err := database.Postgres.Exec(`UPDATE wiiu.friend_requests SET accepted=true WHERE id=$1`, friendRequestID)
result, err := database.Manager.Exec(`UPDATE wiiu.friend_requests SET accepted=true WHERE id=$1`, friendRequestID)
if err != nil {
return err
}

View File

@ -6,7 +6,7 @@ import (
// SetFriendRequestDenied marks a friend request as denied
func SetFriendRequestDenied(friendRequestID uint64) error {
result, err := database.Postgres.Exec(`UPDATE wiiu.friend_requests SET denied=true WHERE id=$1`, friendRequestID)
result, err := database.Manager.Exec(`UPDATE wiiu.friend_requests SET denied=true WHERE id=$1`, friendRequestID)
if err != nil {
return err
}

View File

@ -6,7 +6,7 @@ import (
// SetFriendRequestReceived marks a friend request as received
func SetFriendRequestReceived(friendRequestID uint64) error {
result, err := database.Postgres.Exec(`UPDATE wiiu.friend_requests SET received=true WHERE id=$1`, friendRequestID)
result, err := database.Manager.Exec(`UPDATE wiiu.friend_requests SET received=true WHERE id=$1`, friendRequestID)
if err != nil {
return err
}

View File

@ -1,23 +1,20 @@
package database_wiiu
import (
"time"
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-go/v2/types"
)
// SetUserBlocked marks a blocked PID as blocked on a bloker PID block list
func SetUserBlocked(blockerPID uint32, blockedPID uint32, titleId uint64, titleVersion uint16) error {
date := nex.NewDateTime(0)
date.FromTimestamp(time.Now())
// SetUserBlocked marks a blocked PID as blocked on a blocker PID block list
func SetUserBlocked(blockerPID uint32, blockedPID uint32, titleID uint64, titleVersion uint16) error {
date := types.NewDateTime(0).Now()
_, err := database.Postgres.Exec(`
_, err := database.Manager.Exec(`
INSERT INTO wiiu.blocks (blocker_pid, blocked_pid, title_id, title_version, date)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (blocker_pid, blocked_pid)
DO UPDATE SET
date = $5`, blockerPID, blockedPID, titleId, titleVersion, date.Value())
date = $5`, blockerPID, blockedPID, titleID, titleVersion, uint64(date))
if err != nil {
return err
}

View File

@ -6,7 +6,7 @@ import (
// UnsetFriendRequestDenied unmarks a friend request as denied
func UnsetFriendRequestDenied(friendRequestID uint64) error {
result, err := database.Postgres.Exec(`UPDATE wiiu.friend_requests SET denied=false WHERE id=$1`, friendRequestID)
result, err := database.Manager.Exec(`UPDATE wiiu.friend_requests SET denied=false WHERE id=$1`, friendRequestID)
if err != nil {
return err
}

View File

@ -6,7 +6,7 @@ import (
// UnsetUserBlocked removes a block from a user
func UnsetUserBlocked(user1_pid uint32, user2_pid uint32) error {
result, err := database.Postgres.Exec(`
result, err := database.Manager.Exec(`
DELETE FROM wiiu.blocks WHERE blocker_pid=$1 AND blocked_pid=$2`, user1_pid, user2_pid)
if err != nil {
return err

View File

@ -2,14 +2,14 @@ package database_wiiu
import (
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-go/v2/types"
)
// UpdateUserComment updates a user's comment
func UpdateUserComment(pid uint32, message string) (uint64, error) {
changed := nex.NewDateTime(0).Now()
changed := uint64(types.NewDateTime(0).Now())
_, err := database.Postgres.Exec(`
_, err := database.Manager.Exec(`
INSERT INTO wiiu.user_data (pid, comment, comment_changed)
VALUES ($1, $2, $3)
ON CONFLICT (pid)

View File

@ -2,17 +2,17 @@ package database_wiiu
import (
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-go/v2/types"
)
// UpdateUserLastOnlineTime updates a user's last online time
func UpdateUserLastOnlineTime(pid uint32, lastOnline *nex.DateTime) error {
_, err := database.Postgres.Exec(`
func UpdateUserLastOnlineTime(pid uint32, lastOnline types.DateTime) error {
_, err := database.Manager.Exec(`
INSERT INTO wiiu.user_data (pid, last_online)
VALUES ($1, $2)
ON CONFLICT (pid)
DO UPDATE SET
last_online = $2`, pid, lastOnline.Value())
last_online = $2`, pid, uint64(lastOnline))
if err != nil {
return err

View File

@ -0,0 +1,33 @@
package database_wiiu
import (
"github.com/PretendoNetwork/friends/database"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// UpdateUserMii updates the user's Mii
func UpdateUserMii(pid uint32, mii friends_wiiu_types.MiiV2) error {
_, err := database.Manager.Exec(`
INSERT INTO wiiu.mii (pid, name, unknown1, unknown2, data, unknown_datetime)
VALUES ($1, $2, $3, $4, $5, $6)
ON CONFLICT (pid)
DO UPDATE
SET
name = $2,
unknown1 = $3,
unknown2 = $4,
data = $5,
unknown_datetime = $6`,
pid,
string(mii.Name),
uint8(mii.Unknown1),
uint8(mii.Unknown2),
[]byte(mii.MiiData),
uint64(mii.Datetime),
)
if err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,27 @@
package database_wiiu
import (
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// UpdateNetworkAccountInfo updates a user's network account information
func UpdateNetworkAccountInfo(pid uint32, nnaInfo friends_wiiu_types.NNAInfo, birthday types.DateTime) error {
_, err := database.Manager.Exec(
`INSERT INTO wiiu.network_account_info (pid, unknown1, unknown2, birthday)
VALUES ($1, $2, $3, $4)
ON CONFLICT (pid)
DO UPDATE
SET unknown1 = $2, unknown2 = $3, birthday = $4`,
pid,
uint8(nnaInfo.Unknown1),
uint8(nnaInfo.Unknown2),
uint64(birthday),
)
if err != nil {
return err
}
return UpdateUserPrincipalBasicInfo(pid, nnaInfo.PrincipalBasicInfo)
}

View File

@ -0,0 +1,25 @@
package database_wiiu
import (
"github.com/PretendoNetwork/friends/database"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// UpdateUserPrincipalBasicInfo updates the user's basic info
func UpdateUserPrincipalBasicInfo(pid uint32, principalBasicInfo friends_wiiu_types.PrincipalBasicInfo) error {
_, err := database.Manager.Exec(
`INSERT INTO wiiu.principal_basic_info (pid, username, unknown)
VALUES ($1, $2, $3)
ON CONFLICT (pid)
DO UPDATE
SET username = $2, unknown = $3`,
pid,
string(principalBasicInfo.NNID),
uint8(principalBasicInfo.Unknown),
)
if err != nil {
return err
}
return UpdateUserMii(pid, principalBasicInfo.Mii)
}

View File

@ -2,19 +2,19 @@ package database_wiiu
import (
"github.com/PretendoNetwork/friends/database"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
// UpdateUserPrincipalPreference updates the user preferences
func UpdateUserPrincipalPreference(pid uint32, principalPreference *friends_wiiu_types.PrincipalPreference) error {
_, err := database.Postgres.Exec(`
func UpdateUserPrincipalPreference(pid uint32, principalPreference friends_wiiu_types.PrincipalPreference) error {
_, err := database.Manager.Exec(`
INSERT INTO wiiu.user_data (pid, show_online, show_current_game, block_friend_requests)
VALUES ($1, $2, $3, $4)
ON CONFLICT (pid)
DO UPDATE SET
show_online = $2,
show_current_game = $3,
block_friend_requests = $4`, pid, principalPreference.ShowOnlinePresence, principalPreference.ShowCurrentTitle, principalPreference.BlockFriendRequests)
block_friend_requests = $4`, pid, bool(principalPreference.ShowOnlinePresence), bool(principalPreference.ShowCurrentTitle), bool(principalPreference.BlockFriendRequests))
if err != nil {
return err

View File

@ -0,0 +1,38 @@
package globals
import (
"context"
"strconv"
pb "github.com/PretendoNetwork/grpc-go/account"
"github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
"google.golang.org/grpc/metadata"
)
func AccountDetailsByPID(pid types.PID) (*nex.Account, *nex.Error) {
if pid.Equals(AuthenticationServerAccount.PID) {
return AuthenticationServerAccount, nil
}
if pid.Equals(SecureServerAccount.PID) {
return SecureServerAccount, nil
}
if pid.Equals(GuestAccount.PID) {
return GuestAccount, nil
}
ctx := metadata.NewOutgoingContext(context.Background(), GRPCAccountCommonMetadata)
response, err := GRPCAccountClient.GetNEXPassword(ctx, &pb.GetNEXPasswordRequest{Pid: uint32(pid)})
if err != nil {
Logger.Error(err.Error())
return nil, nex.NewError(nex.ResultCodes.RendezVous.InvalidPID, "Invalid PID")
}
username := strconv.Itoa(int(pid))
account := nex.NewAccount(pid, username, response.Password)
return account, nil
}

View File

@ -0,0 +1,50 @@
package globals
import (
"context"
"fmt"
"strconv"
pb "github.com/PretendoNetwork/grpc-go/account"
"github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
"google.golang.org/grpc/metadata"
)
func AccountDetailsByUsername(username string) (*nex.Account, *nex.Error) {
if username == AuthenticationEndpoint.ServerAccount.Username {
return AuthenticationEndpoint.ServerAccount, nil
}
if username == SecureEndpoint.ServerAccount.Username {
return SecureEndpoint.ServerAccount, nil
}
if username == GuestAccount.Username {
return GuestAccount, nil
}
// TODO - This is fine for our needs, but not for servers which use non-PID usernames?
pid, err := strconv.Atoi(username)
if err != nil {
fmt.Println(1)
fmt.Println(err)
return nil, nex.NewError(nex.ResultCodes.RendezVous.InvalidUsername, "Invalid username")
}
// * Trying to use AccountDetailsByPID here led to weird nil checks?
// * Would always return an error even when it shouldn't.
// TODO - Look into this more
ctx := metadata.NewOutgoingContext(context.Background(), GRPCAccountCommonMetadata)
response, err := GRPCAccountClient.GetNEXPassword(ctx, &pb.GetNEXPasswordRequest{Pid: uint32(pid)})
if err != nil {
Logger.Error(err.Error())
return nil, nex.NewError(nex.ResultCodes.RendezVous.InvalidPID, "Invalid PID")
}
account := nex.NewAccount(types.NewPID(uint64(pid)), username, response.Password)
return account, nil
}

View File

@ -3,18 +3,24 @@ package globals
import (
"github.com/PretendoNetwork/friends/types"
pb "github.com/PretendoNetwork/grpc-go/account"
"github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/plogger-go"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
var Logger *plogger.Logger
var AuthenticationServerAccount *nex.Account
var SecureServerAccount *nex.Account
var GuestAccount *nex.Account
var KerberosPassword = "password" // * Default password
var AuthenticationServer *nex.Server
var SecureServer *nex.Server
var ConnectedUsers map[uint32]*types.ConnectedUser
var AuthenticationServer *nex.PRUDPServer
var AuthenticationEndpoint *nex.PRUDPEndPoint
var SecureServer *nex.PRUDPServer
var SecureEndpoint *nex.PRUDPEndPoint
var ConnectedUsers *nex.MutexMap[uint32, *types.ConnectedUser]
var AESKey []byte
var GRPCAccountClientConnection *grpc.ClientConn
var GRPCAccountClient pb.AccountClient
var GRPCAccountCommonMetadata metadata.MD
var DatabaseMaxConnections int

View File

@ -1,21 +0,0 @@
package globals
import (
"context"
pb "github.com/PretendoNetwork/grpc-go/account"
"github.com/PretendoNetwork/nex-go"
"google.golang.org/grpc/metadata"
)
func PasswordFromPID(pid uint32) (string, uint32) {
ctx := metadata.NewOutgoingContext(context.Background(), GRPCAccountCommonMetadata)
response, err := GRPCAccountClient.GetNEXPassword(ctx, &pb.GetNEXPasswordRequest{Pid: pid})
if err != nil {
Logger.Error(err.Error())
return "", nex.Errors.RendezVous.InvalidUsername
}
return response.Password, 0
}

44
go.mod
View File

@ -1,31 +1,41 @@
module github.com/PretendoNetwork/friends
go 1.18
go 1.23.0
toolchain go1.23.6
require (
github.com/PretendoNetwork/grpc-go v1.0.2
github.com/PretendoNetwork/nex-go v1.0.41
github.com/PretendoNetwork/nex-protocols-common-go v1.0.28
github.com/PretendoNetwork/nex-protocols-go v1.0.54
github.com/PretendoNetwork/nex-go/v2 v2.1.2
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.2.2
github.com/PretendoNetwork/nex-protocols-go/v2 v2.2.1
github.com/PretendoNetwork/plogger-go v1.0.4
github.com/golang/protobuf v1.5.3
github.com/PretendoNetwork/sql-manager v1.0.0
github.com/golang/protobuf v1.5.4
github.com/joho/godotenv v1.5.1
github.com/lib/pq v1.10.9
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
google.golang.org/grpc v1.58.2
google.golang.org/grpc v1.70.0
)
replace google.golang.org/genproto => google.golang.org/genproto v0.0.0-20240520151616-dc85e6b867a5
require (
github.com/fatih/color v1.15.0 // indirect
github.com/dolthub/maphash v0.1.0 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/jwalton/go-supportscolor v1.2.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/lxzan/gws v1.8.8 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e // indirect
github.com/superwhiskers/crunch/v3 v3.5.7 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/net v0.16.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect
google.golang.org/protobuf v1.31.0 // indirect
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f // indirect
golang.org/x/mod v0.23.0 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/term v0.29.0 // indirect
golang.org/x/text v0.22.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b // indirect
google.golang.org/protobuf v1.36.5 // indirect
)

110
go.sum
View File

@ -1,56 +1,86 @@
github.com/PretendoNetwork/grpc-go v1.0.2 h1:9TvKmX7dCOANyoHEra1MMYqS1N/RGav66TRG4SHInvo=
github.com/PretendoNetwork/grpc-go v1.0.2/go.mod h1:XZjEsij9lL7HJBNkH6JPbBIkUSq/1rjflvjGdv+DAj0=
github.com/PretendoNetwork/nex-go v1.0.41 h1:TcBb1Bpe2KAB+AXaGX1K9NVQBRtZJIoy4yCvRde2xbI=
github.com/PretendoNetwork/nex-go v1.0.41/go.mod h1:QwHEa165DeVd0xIuthrgc3j6NWXT8lyPSG6t5kC/Shk=
github.com/PretendoNetwork/nex-protocols-common-go v1.0.28 h1:ErkWga7Uzn4WoDU8Q/Sy+geHy0fF0G/5wFnL5i6hngI=
github.com/PretendoNetwork/nex-protocols-common-go v1.0.28/go.mod h1:4jYhLg+Cb2qhJHyyA+f2OwCrmc98zuTO3JPWK22mIKw=
github.com/PretendoNetwork/nex-protocols-go v1.0.54 h1:nDbGnNpe7F/cwBZBvFFFPS1afZQ4OLpVHfF8t5xug/Y=
github.com/PretendoNetwork/nex-protocols-go v1.0.54/go.mod h1:136762CMIcAsTZDrt4W7gDE4ppiBuc9zN2QFOHESjS8=
github.com/PretendoNetwork/nex-go/v2 v2.1.2 h1:OJFAS6U6VNzZ4YzteKqUEZ5aJMwWIHODeRrLwNbN7nw=
github.com/PretendoNetwork/nex-go/v2 v2.1.2/go.mod h1:3LyJzsv3AataJW8D0binp15Q8ZH22MWTYly1VNtXi64=
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.2.2 h1:rBJNZDJ92pa9fU3Og0sanyizJTWnELPoGR0Tjz8zlws=
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.2.2/go.mod h1:iuNMuBK/zww+44d6ajfLsOusXx/6Llj3zSkmhJwMuuM=
github.com/PretendoNetwork/nex-protocols-go/v2 v2.2.1 h1:/dsuP0W7bZNvrXoXH0ZRdxpxonfbWmmson51WCQdpEQ=
github.com/PretendoNetwork/nex-protocols-go/v2 v2.2.1/go.mod h1:+soBHmwX6ixGxj6cphLuCvfJqxcZPuowc/5e7Qi9Bz0=
github.com/PretendoNetwork/plogger-go v1.0.4 h1:PF7xHw9eDRHH+RsAP9tmAE7fG0N0p6H4iPwHKnsoXwc=
github.com/PretendoNetwork/plogger-go v1.0.4/go.mod h1:7kD6M4vPq1JL4LTuPg6kuB1OvUBOwQOtAvTaUwMbwvU=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/PretendoNetwork/sql-manager v1.0.0 h1:g0SYpQgi6Kk4ptufrLTSmDxvqaYioTcfXaDH+uXC+a0=
github.com/PretendoNetwork/sql-manager v1.0.0/go.mod h1:NaEdDC0S/9J8eoxCDvuHB8fofv0svh44lWvgCdtuMq0=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dolthub/maphash v0.1.0 h1:bsQ7JsF4FkkWyrP3oCnFJgrCUAFbFf3kOl4L/QxPDyQ=
github.com/dolthub/maphash v0.1.0/go.mod h1:gkg4Ch4CdCDu5h6PMriVLawB7koZ+5ijb9puGMV50a4=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/jwalton/go-supportscolor v1.2.0 h1:g6Ha4u7Vm3LIsQ5wmeBpS4gazu0UP1DRDE8y6bre4H8=
github.com/jwalton/go-supportscolor v1.2.0/go.mod h1:hFVUAZV2cWg+WFFC4v8pT2X/S2qUUBYMioBD9AINXGs=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/lxzan/gws v1.8.8 h1:st193ZG8qN8sSw8/g/UituFhs7etmKzS7jUqhijg5wM=
github.com/lxzan/gws v1.8.8/go.mod h1:FcGeRMB7HwGuTvMLR24ku0Zx0p6RXqeKASeMc4VYgi4=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e h1:dCWirM5F3wMY+cmRda/B1BiPsFtmzXqV9b0hLWtVBMs=
github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e/go.mod h1:9leZcVcItj6m9/CfHY5Em/iBrCz7js8LcRQGTKEEv2M=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/superwhiskers/crunch/v3 v3.5.7 h1:N9RLxaR65C36i26BUIpzPXGy2f6pQ7wisu2bawbKNqg=
github.com/superwhiskers/crunch/v3 v3.5.7/go.mod h1:4ub2EKgF1MAhTjoOCTU4b9uLMsAweHEa89aRrfAypXA=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos=
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f h1:oFMYAjX0867ZD2jcNiLBrI9BdpmEkvPyi5YrBGXbamg=
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk=
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY=
google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I=
google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b h1:FQtJ1MxbXoIIrZHZ33M+w5+dAP9o86rgpjoKr/ZmT7k=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -14,7 +14,7 @@ import (
func (s *gRPCFriendsServer) AcceptFriendRequest(ctx context.Context, in *pb.AcceptFriendRequestRequest) (*pb.AcceptFriendRequestResponse, error) {
friendInfo, err := database_wiiu.AcceptFriendRequestAndReturnFriendInfo(in.GetFriendRequestId())
_, err := database_wiiu.AcceptFriendRequestAndReturnFriendInfo(in.GetFriendRequestId())
if err != nil {
if err == database.ErrFriendRequestNotFound {
return &pb.AcceptFriendRequestResponse{
@ -35,6 +35,6 @@ func (s *gRPCFriendsServer) AcceptFriendRequest(ctx context.Context, in *pb.Acce
}
return &pb.AcceptFriendRequestResponse{
Success: friendInfo != nil,
Success: err == nil,
}, nil
}

View File

@ -37,10 +37,11 @@ func (s *gRPCFriendsServer) GetUserFriendPIDs(ctx context.Context, in *pb.GetUse
return nil, status.Errorf(codes.Internal, "internal server error")
}
for _, relationship := range relationships {
// * Only add complete relationships to the list
if relationship.RelationshipType == 1 {
pids = append(pids, relationship.PID)
if relationships != nil {
for _, relationship := range relationships {
if relationship.RelationshipType == 1 {
pids = append(pids, uint32(relationship.PID))
}
}
}

View File

@ -13,7 +13,6 @@ import (
)
func (s *gRPCFriendsServer) GetUserFriendRequestsIncoming(ctx context.Context, in *pb.GetUserFriendRequestsIncomingRequest) (*pb.GetUserFriendRequestsIncomingResponse, error) {
friendRequestsIn, err := database_wiiu.GetUserFriendRequestsIn(in.GetPid())
if err != nil && err != database.ErrEmptyList {
globals.Logger.Critical(err.Error())
@ -22,17 +21,19 @@ func (s *gRPCFriendsServer) GetUserFriendRequestsIncoming(ctx context.Context, i
friendRequests := make([]*pb.FriendRequest, 0, len(friendRequestsIn))
for i := 0; i < len(friendRequestsIn); i++ {
friendRequest := &pb.FriendRequest{
Id: friendRequestsIn[i].Message.FriendRequestID,
Sender: friendRequestsIn[i].PrincipalInfo.PID,
Recipient: in.GetPid(),
Sent: uint64(friendRequestsIn[i].SentOn.Standard().Unix()),
Expires: uint64(friendRequestsIn[i].Message.ExpiresOn.Standard().Unix()),
Message: friendRequestsIn[i].Message.Message,
}
if friendRequestsIn != nil {
for _, friendRequestIn := range friendRequestsIn {
friendRequest := &pb.FriendRequest{
Id: uint64(friendRequestIn.Message.FriendRequestID),
Sender: uint32(friendRequestIn.PrincipalInfo.PID),
Recipient: in.GetPid(),
Sent: uint64(friendRequestIn.SentOn.Standard().Unix()),
Expires: uint64(friendRequestIn.Message.ExpiresOn.Standard().Unix()),
Message: string(friendRequestIn.Message.Message),
}
friendRequests = append(friendRequests, friendRequest)
friendRequests = append(friendRequests, friendRequest)
}
}
return &pb.GetUserFriendRequestsIncomingResponse{

View File

@ -10,7 +10,7 @@ import (
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
pb "github.com/PretendoNetwork/grpc-go/friends"
nex "github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-go/v2/types"
)
func (s *gRPCFriendsServer) SendUserFriendRequest(ctx context.Context, in *pb.SendUserFriendRequestRequest) (*pb.SendUserFriendRequestResponse, error) {
@ -20,15 +20,15 @@ func (s *gRPCFriendsServer) SendUserFriendRequest(ctx context.Context, in *pb.Se
currentTimestamp := time.Now()
expireTimestamp := currentTimestamp.Add(time.Hour * 24 * 29)
sentTime := nex.NewDateTime(0)
expireTime := nex.NewDateTime(0)
sentTime := types.NewDateTime(0)
expireTime := types.NewDateTime(0)
sentTime.FromTimestamp(currentTimestamp)
expireTime.FromTimestamp(expireTimestamp)
message := in.GetMessage()
id, err := database_wiiu.SaveFriendRequest(sender, recipient, sentTime.Value(), expireTime.Value(), message)
id, err := database_wiiu.SaveFriendRequest(sender, recipient, uint64(sentTime), uint64(expireTime), message)
if err != nil {
globals.Logger.Critical(err.Error())
return &pb.SendUserFriendRequestResponse{

View File

@ -5,35 +5,36 @@ import (
"github.com/PretendoNetwork/friends/globals"
pb "github.com/PretendoNetwork/grpc-go/friends"
nex "github.com/PretendoNetwork/nex-go"
nintendo_notifications "github.com/PretendoNetwork/nex-protocols-go/nintendo-notifications"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/constants"
nintendo_notifications "github.com/PretendoNetwork/nex-protocols-go/v2/nintendo-notifications"
empty "github.com/golang/protobuf/ptypes/empty"
)
// SendUserNotificationWiiU implements helloworld.SendUserNotificationWiiU
func (s *gRPCFriendsServer) SendUserNotificationWiiU(ctx context.Context, in *pb.SendUserNotificationWiiURequest) (*empty.Empty, error) {
connectedUser := globals.ConnectedUsers[in.GetPid()]
connectedUser, ok := globals.ConnectedUsers.Get(in.GetPid())
if connectedUser != nil {
rmcRequest := nex.NewRMCRequest()
rmcRequest.SetProtocolID(nintendo_notifications.ProtocolID)
rmcRequest.SetCallID(3810693103)
rmcRequest.SetMethodID(nintendo_notifications.MethodProcessNintendoNotificationEvent2)
rmcRequest.SetParameters(in.GetNotificationData())
if ok && connectedUser != nil {
rmcRequest := nex.NewRMCRequest(globals.SecureEndpoint)
rmcRequest.ProtocolID = nintendo_notifications.ProtocolID
rmcRequest.CallID = 3810693103
rmcRequest.MethodID = nintendo_notifications.MethodProcessNintendoNotificationEvent2
rmcRequest.Parameters = in.GetNotificationData()
rmcRequestBytes := rmcRequest.Bytes()
requestPacket, _ := nex.NewPacketV0(connectedUser.Client, nil)
requestPacket, _ := nex.NewPRUDPPacketV0(globals.SecureEndpoint.Server, connectedUser.Connection, nil)
requestPacket.SetVersion(0)
requestPacket.SetSource(0xA1)
requestPacket.SetDestination(0xAF)
requestPacket.SetType(nex.DataPacket)
requestPacket.SetType(constants.DataPacket)
requestPacket.AddFlag(constants.PacketFlagNeedsAck)
requestPacket.AddFlag(constants.PacketFlagReliable)
requestPacket.SetSourceVirtualPortStreamType(connectedUser.Connection.StreamType)
requestPacket.SetSourceVirtualPortStreamID(globals.SecureEndpoint.StreamID)
requestPacket.SetDestinationVirtualPortStreamType(connectedUser.Connection.StreamType)
requestPacket.SetDestinationVirtualPortStreamID(connectedUser.Connection.StreamID)
requestPacket.SetPayload(rmcRequestBytes)
requestPacket.AddFlag(nex.FlagNeedsAck)
requestPacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(requestPacket)
}

35
init.go
View File

@ -1,6 +1,8 @@
package main
import (
"cmp"
"crypto/rand"
"encoding/hex"
"fmt"
"os"
@ -10,8 +12,10 @@ import (
"github.com/PretendoNetwork/friends/database"
"github.com/PretendoNetwork/friends/globals"
"github.com/PretendoNetwork/friends/types"
"github.com/PretendoNetwork/plogger-go"
pb "github.com/PretendoNetwork/grpc-go/account"
"github.com/PretendoNetwork/nex-go/v2"
nex_types "github.com/PretendoNetwork/nex-go/v2/types"
"github.com/PretendoNetwork/plogger-go"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
@ -21,8 +25,9 @@ import (
func init() {
globals.Logger = plogger.NewLogger()
globals.ConnectedUsers = make(map[uint32]*types.ConnectedUser)
// Setup RSA private key for token parsing
globals.ConnectedUsers = nex.NewMutexMap[uint32, *types.ConnectedUser]()
// * Setup RSA private key for token parsing
var err error
err = godotenv.Load()
@ -31,7 +36,7 @@ func init() {
}
postgresURI := os.Getenv("PN_FRIENDS_CONFIG_DATABASE_URI")
kerberosPassword := os.Getenv("PN_FRIENDS_CONFIG_KERBEROS_PASSWORD")
databaseMaxConnectionsStr := cmp.Or(os.Getenv("PN_FRIENDS_CONFIG_DATABASE_MAX_CONNECTIONS"), "100")
aesKey := os.Getenv("PN_FRIENDS_CONFIG_AES_KEY")
grpcAPIKey := os.Getenv("PN_FRIENDS_CONFIG_GRPC_API_KEY")
grpcServerPort := os.Getenv("PN_FRIENDS_GRPC_SERVER_PORT")
@ -47,12 +52,28 @@ func init() {
os.Exit(0)
}
if strings.TrimSpace(kerberosPassword) == "" {
globals.Logger.Warningf("PN_FRIENDS_CONFIG_KERBEROS_PASSWORD environment variable not set. Using default password: %q", globals.KerberosPassword)
databaseMaxConnections, err := strconv.Atoi(databaseMaxConnectionsStr)
if err != nil {
globals.Logger.Errorf("PN_FRIENDS_CONFIG_DATABASE_MAX_CONNECTIONS is not a valid number. Got %s", databaseMaxConnectionsStr)
os.Exit(0)
} else {
globals.KerberosPassword = kerberosPassword
globals.DatabaseMaxConnections = databaseMaxConnections
}
kerberosPassword := make([]byte, 0x10)
_, err = rand.Read(kerberosPassword)
if err != nil {
globals.Logger.Error("Error generating Kerberos password")
os.Exit(0)
}
globals.KerberosPassword = string(kerberosPassword)
globals.AuthenticationServerAccount = nex.NewAccount(nex_types.NewPID(1), "Quazal Authentication", globals.KerberosPassword)
globals.SecureServerAccount = nex.NewAccount(nex_types.NewPID(2), "Quazal Rendez-Vous", globals.KerberosPassword)
globals.GuestAccount = nex.NewAccount(nex_types.NewPID(100), "guest", "MMQea3n!fsik") // * Guest account password is always the same, known to all consoles. Only allow on the friends server
if strings.TrimSpace(aesKey) == "" {
globals.Logger.Error("PN_FRIENDS_CONFIG_AES_KEY environment variable not set")
os.Exit(0)

View File

@ -10,89 +10,76 @@ import (
"github.com/PretendoNetwork/friends/globals"
"github.com/PretendoNetwork/friends/utility"
nex "github.com/PretendoNetwork/nex-go"
account_management "github.com/PretendoNetwork/nex-protocols-go/account-management"
account_management_types "github.com/PretendoNetwork/nex-protocols-go/account-management/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
account_management "github.com/PretendoNetwork/nex-protocols-go/v2/account-management"
account_management_types "github.com/PretendoNetwork/nex-protocols-go/v2/account-management/types"
)
func NintendoCreateAccount(err error, client *nex.Client, callID uint32, strPrincipalName string, strKey string, uiGroups uint32, strEmail string, oAuthData *nex.DataHolder) uint32 {
func NintendoCreateAccount(err error, packet nex.PacketInterface, callID uint32, strPrincipalName types.String, strKey types.String, uiGroups types.UInt32, strEmail types.String, oAuthData types.DataHolder) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.Core.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.Core.InvalidArgument, "") // TODO - Add error message
}
var tokenBase64 string
oAuthDataType := oAuthData.TypeName()
oAuthDataType := oAuthData.Object.DataObjectID().(types.String)
switch oAuthDataType {
case "NintendoCreateAccountData": // Wii U
nintendoCreateAccountData := oAuthData.ObjectData().(*account_management_types.NintendoCreateAccountData)
case "NintendoCreateAccountData": // * Wii U
nintendoCreateAccountData := oAuthData.Object.Copy().(account_management_types.NintendoCreateAccountData)
tokenBase64 = nintendoCreateAccountData.Token
case "AccountExtraInfo": // 3DS
accountExtraInfo := oAuthData.ObjectData().(*account_management_types.AccountExtraInfo)
tokenBase64 = string(nintendoCreateAccountData.Token)
case "AccountExtraInfo": // * 3DS
accountExtraInfo := oAuthData.Object.Copy().(account_management_types.AccountExtraInfo)
tokenBase64 = accountExtraInfo.NEXToken
tokenBase64 = string(accountExtraInfo.NEXToken)
tokenBase64 = strings.Replace(tokenBase64, ".", "+", -1)
tokenBase64 = strings.Replace(tokenBase64, "-", "/", -1)
tokenBase64 = strings.Replace(tokenBase64, "*", "=", -1)
default:
globals.Logger.Errorf("Invalid oAuthData data type %s!", oAuthDataType)
return nex.Errors.Authentication.TokenParseError
return nil, nex.NewError(nex.ResultCodes.Authentication.TokenParseError, "") // TODO - Add error message
}
encryptedToken, err := base64.StdEncoding.DecodeString(tokenBase64)
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.Authentication.TokenParseError
return nil, nex.NewError(nex.ResultCodes.Authentication.TokenParseError, "") // TODO - Add error message
}
decryptedToken, err := utility.DecryptToken(encryptedToken)
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.Authentication.TokenParseError
return nil, nex.NewError(nex.ResultCodes.Authentication.TokenParseError, "") // TODO - Add error message
}
pid := decryptedToken.UserPID
pid := types.NewPID(uint64(decryptedToken.UserPID))
pidByteArray := make([]byte, 4)
binary.LittleEndian.PutUint32(pidByteArray, pid)
binary.LittleEndian.PutUint32(pidByteArray, uint32(pid))
mac := hmac.New(md5.New, []byte(strKey))
_, err = mac.Write(pidByteArray)
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.Authentication.Unknown
return nil, nex.NewError(nex.ResultCodes.Authentication.Unknown, "") // TODO - Add error message
}
pidHmac := hex.EncodeToString(mac.Sum(nil))
pidHmac := types.NewString(hex.EncodeToString(mac.Sum(nil)))
rmcResponse := nex.NewRMCResponse(account_management.ProtocolID, callID)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream.WriteUInt32LE(pid)
rmcResponseStream.WriteString(pidHmac)
pid.WriteTo(rmcResponseStream)
pidHmac.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse.SetSuccess(account_management.MethodNintendoCreateAccount, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = account_management.ProtocolID
rmcResponse.MethodID = account_management.MethodNintendoCreateAccount
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -1,38 +1,31 @@
package nex
import (
"fmt"
"os"
"strconv"
"github.com/PretendoNetwork/friends/globals"
"github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-go/v2"
)
var serverBuildString string
func StartAuthenticationServer() {
globals.AuthenticationServer = nex.NewServer()
globals.AuthenticationServer.SetPRUDPVersion(0)
globals.AuthenticationServer.SetPRUDPProtocolMinorVersion(0) // TODO: Figure out what to put here
globals.AuthenticationServer.SetDefaultNEXVersion(&nex.NEXVersion{
Major: 1,
Minor: 1,
Patch: 0,
})
globals.AuthenticationServer.SetKerberosKeySize(16)
globals.AuthenticationServer.SetKerberosPassword(globals.KerberosPassword)
globals.AuthenticationServer.SetAccessKey("ridfebb9")
port, _ := strconv.Atoi(os.Getenv("PN_FRIENDS_AUTHENTICATION_SERVER_PORT"))
globals.AuthenticationServer.On("Data", func(packet *nex.PacketV0) {
request := packet.RMCRequest()
globals.AuthenticationServer = nex.NewPRUDPServer()
globals.AuthenticationEndpoint = nex.NewPRUDPEndPoint(1)
fmt.Println("==Friends - Auth==")
fmt.Printf("Protocol ID: %#v\n", request.ProtocolID())
fmt.Printf("Method ID: %#v\n", request.MethodID())
fmt.Println("===============")
})
globals.AuthenticationEndpoint.ServerAccount = globals.AuthenticationServerAccount
globals.AuthenticationEndpoint.AccountDetailsByPID = globals.AccountDetailsByPID
globals.AuthenticationEndpoint.AccountDetailsByUsername = globals.AccountDetailsByUsername
registerCommonAuthenticationServerProtocols()
globals.AuthenticationServer.Listen(fmt.Sprintf(":%s", os.Getenv("PN_FRIENDS_AUTHENTICATION_SERVER_PORT")))
globals.AuthenticationServer.SetFragmentSize(962)
globals.AuthenticationServer.LibraryVersions.SetDefault(nex.NewLibraryVersion(1, 1, 0))
globals.AuthenticationServer.SessionKeyLength = 16
globals.AuthenticationServer.AccessKey = "ridfebb9"
globals.AuthenticationServer.BindPRUDPEndPoint(globals.AuthenticationEndpoint)
globals.AuthenticationServer.Listen(port)
}

View File

@ -1,73 +0,0 @@
package nex
import (
"time"
"github.com/PretendoNetwork/friends/globals"
"github.com/PretendoNetwork/friends/types"
nex "github.com/PretendoNetwork/nex-go"
)
func connect(packet *nex.PacketV0) {
// * We aren't making any replies here because the common Secure Protocol already does that
// *
// * We only want to check that the data given is right so that we don't register a client
// * with an invalid request
payload := packet.Payload()
stream := nex.NewStreamIn(payload, globals.SecureServer)
ticketData, err := stream.ReadBuffer()
if err != nil {
return
}
requestData, err := stream.ReadBuffer()
if err != nil {
return
}
serverKey := nex.DeriveKerberosKey(2, []byte(globals.SecureServer.KerberosPassword()))
ticket := nex.NewKerberosTicketInternalData()
err = ticket.Decrypt(nex.NewStreamIn(ticketData, globals.SecureServer), serverKey)
if err != nil {
return
}
ticketTime := ticket.Timestamp().Standard()
serverTime := time.Now().UTC()
timeLimit := ticketTime.Add(time.Minute * 2)
if serverTime.After(timeLimit) {
return
}
sessionKey := ticket.SessionKey()
kerberos, err := nex.NewKerberosEncryption(sessionKey)
if err != nil {
return
}
decryptedRequestData := kerberos.Decrypt(requestData)
checkDataStream := nex.NewStreamIn(decryptedRequestData, globals.SecureServer)
userPID, err := checkDataStream.ReadUInt32LE()
if err != nil {
return
}
_, err = checkDataStream.ReadUInt32LE() // CID of secure server station url
if err != nil {
return
}
_, err = checkDataStream.ReadUInt32LE() // Response check
if err != nil {
return
}
connectedUser := types.NewConnectedUser()
connectedUser.PID = userPID
connectedUser.Client = packet.Sender()
globals.ConnectedUsers[userPID] = connectedUser
}

View File

@ -4,50 +4,40 @@ import (
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
"github.com/PretendoNetwork/friends/globals"
notifications_3ds "github.com/PretendoNetwork/friends/notifications/3ds"
nex "github.com/PretendoNetwork/nex-go"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
)
func AddFriendshipByPrincipalID(err error, client *nex.Client, callID uint32, lfc uint64, pid uint32) uint32 {
func AddFriendByPrincipalID(err error, packet nex.PacketInterface, callID uint32, lfc types.UInt64, pid types.PID) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
friendRelationship, err := database_3ds.SaveFriendship(client.PID(), pid)
connection := packet.Sender().(*nex.PRUDPConnection)
friendRelationship, err := database_3ds.SaveFriendship(uint32(connection.PID()), uint32(pid))
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
connectedUser := globals.ConnectedUsers[pid]
if connectedUser != nil {
go notifications_3ds.SendFriendshipCompleted(connectedUser.Client, pid, client.PID())
connectedUser, ok := globals.ConnectedUsers.Get(uint32(pid))
if ok && connectedUser != nil {
go notifications_3ds.SendFriendshipCompleted(connectedUser.Connection, connection.PID())
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream.WriteStructure(friendRelationship)
friendRelationship.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
rmcResponse.SetSuccess(friends_3ds.MethodAddFriendByPrincipalID, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_3ds.ProtocolID
rmcResponse.MethodID = friends_3ds.MethodAddFriendByPrincipalID
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -5,45 +5,34 @@ import (
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
nex "github.com/PretendoNetwork/nex-go/v2"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
)
func GetAllFriends(err error, client *nex.Client, callID uint32) uint32 {
func GetAllFriends(err error, packet nex.PacketInterface, callID uint32) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
friendRelationships, err := database_3ds.GetUserFriends(client.PID())
connection := packet.Sender().(*nex.PRUDPConnection)
friendRelationships, err := database_3ds.GetUserFriends(uint32(connection.PID()))
if err != nil && err != sql.ErrNoRows {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream.WriteListStructure(friendRelationships)
friendRelationships.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
rmcResponse.SetSuccess(friends_3ds.MethodGetAllFriends, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_3ds.ProtocolID
rmcResponse.MethodID = friends_3ds.MethodGetAllFriends
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -5,45 +5,40 @@ import (
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
)
func GetFriendMii(err error, client *nex.Client, callID uint32, pids []uint32) uint32 {
func GetFriendMii(err error, packet nex.PacketInterface, callID uint32, friends types.List[friends_3ds_types.FriendInfo]) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
pids := make([]uint32, 0, len(friends))
for _, friend := range friends {
pids = append(pids, uint32(friend.PID))
}
miiList, err := database_3ds.GetFriendMiis(pids)
if err != nil && err != sql.ErrNoRows {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream.WriteListStructure(miiList)
miiList.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
rmcResponse.SetSuccess(friends_3ds.MethodGetFriendMii, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_3ds.ProtocolID
rmcResponse.MethodID = friends_3ds.MethodGetFriendMii
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -5,45 +5,41 @@ import (
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
)
func GetFriendPersistentInfo(err error, client *nex.Client, callID uint32, pids []uint32) uint32 {
func GetFriendPersistentInfo(err error, packet nex.PacketInterface, callID uint32, pidList types.List[types.PID]) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
infoList, err := database_3ds.GetFriendPersistentInfos(client.PID(), pids)
connection := packet.Sender().(*nex.PRUDPConnection)
friendPIDs := make([]uint32, len(pidList))
for _, pid := range pidList {
friendPIDs = append(friendPIDs, uint32(pid))
}
infoList, err := database_3ds.GetFriendPersistentInfos(uint32(connection.PID()), friendPIDs)
if err != nil && err != sql.ErrNoRows {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream.WriteListStructure(infoList)
infoList.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
rmcResponse.SetSuccess(friends_3ds.MethodGetFriendPersistentInfo, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_3ds.ProtocolID
rmcResponse.MethodID = friends_3ds.MethodGetFriendPersistentInfo
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -2,54 +2,42 @@ package nex_friends_3ds
import (
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
)
func GetFriendPresence(err error, client *nex.Client, callID uint32, pids []uint32) uint32 {
func GetFriendPresence(err error, packet nex.PacketInterface, callID uint32, pidList types.List[types.PID]) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
presenceList := make([]*friends_3ds_types.FriendPresence, 0)
presenceList := types.NewList[friends_3ds_types.FriendPresence]()
for i := 0; i < len(pids); i++ {
connectedUser := globals.ConnectedUsers[pids[i]]
for _, pid := range pidList {
connectedUser, ok := globals.ConnectedUsers.Get(uint32(pid))
if connectedUser != nil && connectedUser.Presence != nil {
if ok && connectedUser != nil {
friendPresence := friends_3ds_types.NewFriendPresence()
friendPresence.PID = pids[i]
friendPresence.Presence = globals.ConnectedUsers[pids[i]].Presence
friendPresence.PID = pid.Copy().(types.PID)
friendPresence.Presence = connectedUser.Presence.Copy().(friends_3ds_types.NintendoPresence)
presenceList = append(presenceList, friendPresence)
}
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream.WriteListStructure(presenceList)
presenceList.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
rmcResponse.SetSuccess(friends_3ds.MethodGetFriendPresence, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_3ds.ProtocolID
rmcResponse.MethodID = friends_3ds.MethodGetFriendPresence
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -2,21 +2,22 @@ package nex_friends_3ds
import (
// "github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
// friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
// friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
)
func RemoveFriendByLocalFriendCode(err error, client *nex.Client, callID uint32, friendLFC uint64) uint32 {
func GetPrincipalIDByLocalFriendCode(err error, packet nex.PacketInterface, callID uint32, lfc types.UInt64, lfcList types.List[types.UInt64]) (*nex.RMCMessage, *nex.Error) {
// Respond with unimplemented, waiting for gRPC to retrieve PID from account server
// rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
// rmcResponse.SetError(nex.Errors.Core.NotImplemented)
// rmcResponse.SetError(nex.ResultCodes.Core.NotImplemented)
// rmcResponseBytes := rmcResponse.Bytes()
// responsePacket, _ := nex.NewPacketV0(client, nil)
// responsePacket, _ := nex.NewPRUDPPacketV0(connection, nil)
// responsePacket.SetVersion(0)
//
// responsePacket.SetSource(0xA1)
// responsePacket.SetDestination(0xAF)
// responsePacket.SetType(nex.DataPacket)
@ -27,5 +28,5 @@ func RemoveFriendByLocalFriendCode(err error, client *nex.Client, callID uint32,
// globals.SecureServer.Send(responsePacket)
return nex.Errors.Core.NotImplemented
return nil, nex.NewError(nex.ResultCodes.Core.NotImplemented, "") // TODO - Add error message
}

View File

@ -2,21 +2,22 @@ package nex_friends_3ds
import (
// "github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
// friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
// friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
)
func GetPrincipalIDByLocalFriendCode(err error, client *nex.Client, callID uint32, lfc uint64, lfcList []uint64) uint32 {
func RemoveFriendByLocalFriendCode(err error, packet nex.PacketInterface, callID uint32, lfc types.UInt64) (*nex.RMCMessage, *nex.Error) {
// Respond with unimplemented, waiting for gRPC to retrieve PID from account server
// rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
// rmcResponse.SetError(nex.Errors.Core.NotImplemented)
// rmcResponse.SetError(nex.ResultCodes.Core.NotImplemented)
// rmcResponseBytes := rmcResponse.Bytes()
// responsePacket, _ := nex.NewPacketV0(client, nil)
// responsePacket, _ := nex.NewPRUDPPacketV0(connection, nil)
// responsePacket.SetVersion(0)
//
// responsePacket.SetSource(0xA1)
// responsePacket.SetDestination(0xAF)
// responsePacket.SetType(nex.DataPacket)
@ -27,5 +28,5 @@ func GetPrincipalIDByLocalFriendCode(err error, client *nex.Client, callID uint3
// globals.SecureServer.Send(responsePacket)
return nex.Errors.Core.NotImplemented
return nil, nex.NewError(nex.ResultCodes.Core.NotImplemented, "") // TODO - Add error message
}

View File

@ -5,47 +5,37 @@ import (
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
"github.com/PretendoNetwork/friends/globals"
notifications_3ds "github.com/PretendoNetwork/friends/notifications/3ds"
nex "github.com/PretendoNetwork/nex-go"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
)
func RemoveFriendByPrincipalID(err error, client *nex.Client, callID uint32, pid uint32) uint32 {
func RemoveFriendByPrincipalID(err error, packet nex.PacketInterface, callID uint32, pid types.PID) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
err = database_3ds.RemoveFriendship(client.PID(), pid)
connection := packet.Sender().(*nex.PRUDPConnection)
err = database_3ds.RemoveFriendship(uint32(connection.PID()), uint32(pid))
if err != nil {
if err == database.ErrFriendshipNotFound {
// * Official servers don't actually check this, but
// * we'll do it ourselves
return nex.Errors.FPD.NotFriend
return nil, nex.NewError(nex.ResultCodes.FPD.NotFriend, "") // TODO - Add error message
} else {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
}
go notifications_3ds.SendUserWentOffline(client, pid)
go notifications_3ds.SendUserWentOffline(connection, pid)
rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
rmcResponse.SetSuccess(friends_3ds.MethodRemoveFriendByPrincipalID, nil)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_3ds.ProtocolID
rmcResponse.MethodID = friends_3ds.MethodRemoveFriendByPrincipalID
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -7,84 +7,88 @@ import (
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
"github.com/PretendoNetwork/friends/globals"
notifications_3ds "github.com/PretendoNetwork/friends/notifications/3ds"
nex "github.com/PretendoNetwork/nex-go"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
"golang.org/x/exp/slices"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
)
func SyncFriend(err error, client *nex.Client, callID uint32, lfc uint64, pids []uint32, lfcList []uint64) uint32 {
func SyncFriend(err error, packet nex.PacketInterface, callID uint32, lfc types.UInt64, pids types.List[types.PID], lfcList types.List[types.UInt64]) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
friendRelationships, err := database_3ds.GetUserFriends(client.PID())
connection := packet.Sender().(*nex.PRUDPConnection)
friendRelationships, err := database_3ds.GetUserFriends(uint32(connection.PID()))
if err != nil && err != sql.ErrNoRows {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
for i := 0; i < len(friendRelationships); i++ {
if !slices.Contains(pids, friendRelationships[i].PID) {
err := database_3ds.RemoveFriendship(client.PID(), friendRelationships[i].PID)
for _, relationship := range friendRelationships {
var hasPID bool
for _, pid := range pids {
if pid == relationship.PID {
hasPID = true
break
}
}
if !hasPID {
err := database_3ds.RemoveFriendship(uint32(connection.PID()), uint32(relationship.PID))
if err != nil && err != database.ErrFriendshipNotFound {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
}
}
for i := 0; i < len(pids); i++ {
if !isPIDInRelationships(friendRelationships, pids[i]) {
friendRelationship, err := database_3ds.SaveFriendship(client.PID(), pids[i])
// TODO - Not needed?
relationships := friendRelationships.Copy().(types.List[friends_3ds_types.FriendRelationship])
for _, pid := range pids {
if !isPIDInRelationships(relationships, uint32(pid)) {
relationship, err := database_3ds.SaveFriendship(uint32(connection.PID()), uint32(pid))
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
friendRelationships = append(friendRelationships, friendRelationship)
relationships = append(relationships, relationship)
// Alert the other side, in case they weren't able to get our presence data
connectedUser := globals.ConnectedUsers[pids[i]]
if connectedUser != nil {
go notifications_3ds.SendFriendshipCompleted(connectedUser.Client, pids[i], client.PID())
// * Alert the other side, in case they weren't able to get our presence data
connectedUser, ok := globals.ConnectedUsers.Get(uint32(pid))
if ok && connectedUser != nil {
go notifications_3ds.SendFriendshipCompleted(connectedUser.Connection, connection.PID())
}
}
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
// TODO - Not needed?
syncedRelationships := relationships.Copy().(types.List[friends_3ds_types.FriendRelationship])
rmcResponseStream.WriteListStructure(friendRelationships)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
syncedRelationships.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
rmcResponse.SetSuccess(friends_3ds.MethodSyncFriend, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_3ds.ProtocolID
rmcResponse.MethodID = friends_3ds.MethodSyncFriend
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}
func isPIDInRelationships(relationships []*friends_3ds_types.FriendRelationship, pid uint32) bool {
func isPIDInRelationships(relationships []friends_3ds_types.FriendRelationship, pid uint32) bool {
for i := range relationships {
if relationships[i].PID == pid {
if uint32(relationships[i].PID) == pid {
return true
}
}
return false
}

View File

@ -1,45 +1,35 @@
package nex_friends_3ds
import (
"github.com/PretendoNetwork/nex-go/v2/types"
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
"github.com/PretendoNetwork/friends/globals"
notifications_3ds "github.com/PretendoNetwork/friends/notifications/3ds"
nex "github.com/PretendoNetwork/nex-go"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
nex "github.com/PretendoNetwork/nex-go/v2"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
)
func UpdateComment(err error, client *nex.Client, callID uint32, comment string) uint32 {
func UpdateComment(err error, packet nex.PacketInterface, callID uint32, comment types.String) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
err = database_3ds.UpdateUserComment(client.PID(), comment)
connection := packet.Sender().(*nex.PRUDPConnection)
err = database_3ds.UpdateUserComment(uint32(connection.PID()), string(comment))
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
go notifications_3ds.SendCommentUpdate(client, comment)
go notifications_3ds.SendCommentUpdate(connection, string(comment))
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_3ds.ProtocolID
rmcResponse.MethodID = friends_3ds.MethodUpdateComment
rmcResponse.CallID = callID
rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
rmcResponse.SetSuccess(friends_3ds.MethodUpdateComment, nil)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -4,42 +4,31 @@ import (
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
"github.com/PretendoNetwork/friends/globals"
notifications_3ds "github.com/PretendoNetwork/friends/notifications/3ds"
nex "github.com/PretendoNetwork/nex-go"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
nex "github.com/PretendoNetwork/nex-go/v2"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
)
func UpdateFavoriteGameKey(err error, client *nex.Client, callID uint32, gameKey *friends_3ds_types.GameKey) uint32 {
func UpdateFavoriteGameKey(err error, packet nex.PacketInterface, callID uint32, gameKey friends_3ds_types.GameKey) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
err = database_3ds.UpdateUserFavoriteGame(client.PID(), gameKey)
connection := packet.Sender().(*nex.PRUDPConnection)
err = database_3ds.UpdateUserFavoriteGame(uint32(connection.PID()), gameKey)
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
go notifications_3ds.SendFavoriteUpdate(client, gameKey)
go notifications_3ds.SendFavoriteUpdate(connection, gameKey)
rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
rmcResponse.SetSuccess(friends_3ds.MethodUpdateFavoriteGameKey, nil)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_3ds.ProtocolID
rmcResponse.MethodID = friends_3ds.MethodUpdateFavoriteGameKey
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -4,42 +4,31 @@ import (
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
"github.com/PretendoNetwork/friends/globals"
notifications_3ds "github.com/PretendoNetwork/friends/notifications/3ds"
nex "github.com/PretendoNetwork/nex-go"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
nex "github.com/PretendoNetwork/nex-go/v2"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
)
func UpdateMii(err error, client *nex.Client, callID uint32, mii *friends_3ds_types.Mii) uint32 {
func UpdateMii(err error, packet nex.PacketInterface, callID uint32, mii friends_3ds_types.Mii) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
err = database_3ds.UpdateUserMii(client.PID(), mii)
connection := packet.Sender().(*nex.PRUDPConnection)
err = database_3ds.UpdateUserMii(uint32(connection.PID()), mii)
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
go notifications_3ds.SendMiiUpdateNotification(client)
go notifications_3ds.SendMiiUpdateNotification(connection)
rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
rmcResponse.SetSuccess(friends_3ds.MethodUpdateMii, nil)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_3ds.ProtocolID
rmcResponse.MethodID = friends_3ds.MethodUpdateMii
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -4,50 +4,41 @@ import (
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
"github.com/PretendoNetwork/friends/globals"
notifications_3ds "github.com/PretendoNetwork/friends/notifications/3ds"
nex "github.com/PretendoNetwork/nex-go"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
)
func UpdatePreference(err error, client *nex.Client, callID uint32, showOnline bool, showCurrentGame bool, showPlayedGame bool) uint32 {
func UpdatePreference(err error, packet nex.PacketInterface, callID uint32, publicMode types.Bool, showGame types.Bool, showPlayedGame types.Bool) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
err = database_3ds.UpdateUserPreferences(client.PID(), showOnline, showCurrentGame)
connection := packet.Sender().(*nex.PRUDPConnection)
err = database_3ds.UpdateUserPreferences(uint32(connection.PID()), bool(publicMode), bool(showGame))
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
if !showCurrentGame {
if !showGame {
emptyPresence := friends_3ds_types.NewNintendoPresence()
emptyPresence.GameKey = friends_3ds_types.NewGameKey()
emptyPresence.ChangedFlags = 0xFFFFFFFF // All flags
notifications_3ds.SendPresenceUpdate(client, emptyPresence)
}
if !showOnline {
notifications_3ds.SendUserWentOfflineGlobally(client)
emptyPresence.ChangedFlags = types.NewUInt32(0xFFFFFFFF) // * All flags
notifications_3ds.SendPresenceUpdate(connection, emptyPresence)
}
rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
rmcResponse.SetSuccess(friends_3ds.MethodUpdatePreference, nil)
if !publicMode {
notifications_3ds.SendUserWentOfflineGlobally(connection)
}
rmcResponseBytes := rmcResponse.Bytes()
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_3ds.ProtocolID
rmcResponse.MethodID = friends_3ds.MethodUpdatePreference
rmcResponse.CallID = callID
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -3,60 +3,51 @@ package nex_friends_3ds
import (
"github.com/PretendoNetwork/friends/globals"
notifications_3ds "github.com/PretendoNetwork/friends/notifications/3ds"
"github.com/PretendoNetwork/friends/types"
nex "github.com/PretendoNetwork/nex-go"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
friends_types "github.com/PretendoNetwork/friends/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
)
func UpdatePresence(err error, client *nex.Client, callID uint32, presence *friends_3ds_types.NintendoPresence, showGame bool) uint32 {
func UpdatePresence(err error, packet nex.PacketInterface, callID uint32, presence friends_3ds_types.NintendoPresence, showGame types.Bool) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
currentPresence := presence
connection := packet.Sender().(*nex.PRUDPConnection)
currentPresence := presence.Copy().(friends_3ds_types.NintendoPresence)
// Send an entirely empty status, with every flag set to update
if !showGame {
currentPresence = friends_3ds_types.NewNintendoPresence()
currentPresence.GameKey = friends_3ds_types.NewGameKey()
currentPresence.ChangedFlags = 0xFFFFFFFF // All flags
currentPresence.ChangedFlags = types.NewUInt32(0xFFFFFFFF) // * All flags
}
go notifications_3ds.SendPresenceUpdate(client, currentPresence)
go notifications_3ds.SendPresenceUpdate(connection, currentPresence)
pid := client.PID()
pid := uint32(connection.PID())
connectedUser, ok := globals.ConnectedUsers.Get(pid)
if globals.ConnectedUsers[pid] == nil {
if !ok || connectedUser == nil {
// TODO - Figure out why this is getting removed
connectedUser := types.NewConnectedUser()
connectedUser = friends_types.NewConnectedUser()
connectedUser.PID = pid
connectedUser.Platform = types.CTR
connectedUser.Client = client
connectedUser.Platform = friends_types.CTR
connectedUser.Connection = connection
globals.ConnectedUsers[pid] = connectedUser
globals.ConnectedUsers.Set(pid, connectedUser)
}
globals.ConnectedUsers[pid].Presence = currentPresence
connectedUser.Presence = currentPresence
rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
rmcResponse.SetSuccess(friends_3ds.MethodUpdatePresence, nil)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_3ds.ProtocolID
rmcResponse.MethodID = friends_3ds.MethodUpdatePresence
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -3,40 +3,29 @@ package nex_friends_3ds
import (
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/friends-3ds/types"
nex "github.com/PretendoNetwork/nex-go/v2"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
friends_3ds_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds/types"
)
func UpdateProfile(err error, client *nex.Client, callID uint32, profileData *friends_3ds_types.MyProfile) uint32 {
func UpdateProfile(err error, packet nex.PacketInterface, callID uint32, profileData friends_3ds_types.MyProfile) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
err = database_3ds.UpdateUserProfile(client.PID(), profileData)
connection := packet.Sender().(*nex.PRUDPConnection)
err = database_3ds.UpdateUserProfile(uint32(connection.PID()), profileData)
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
rmcResponse := nex.NewRMCResponse(friends_3ds.ProtocolID, callID)
rmcResponse.SetSuccess(friends_3ds.MethodUpdateProfile, nil)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_3ds.ProtocolID
rmcResponse.MethodID = friends_3ds.MethodUpdateProfile
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -5,78 +5,77 @@ import (
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
notifications_wiiu "github.com/PretendoNetwork/friends/notifications/wiiu"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
func AcceptFriendRequest(err error, client *nex.Client, callID uint32, id uint64) uint32 {
func AcceptFriendRequest(err error, packet nex.PacketInterface, callID uint32, id types.UInt64) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
friendInfo, err := database_wiiu.AcceptFriendRequestAndReturnFriendInfo(id)
connection := packet.Sender().(*nex.PRUDPConnection)
friendInfo, err := database_wiiu.AcceptFriendRequestAndReturnFriendInfo(uint64(id))
if err != nil {
if err == database.ErrFriendRequestNotFound {
return nex.Errors.FPD.InvalidMessageID
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidMessageID, "") // TODO - Add error message
} else {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
}
friendPID := friendInfo.NNAInfo.PrincipalBasicInfo.PID
connectedUser := globals.ConnectedUsers[friendPID]
friendPID := uint32(friendInfo.NNAInfo.PrincipalBasicInfo.PID)
connectedUser, ok := globals.ConnectedUsers.Get(friendPID)
if connectedUser != nil {
senderPID := client.PID()
senderConnectedUser := globals.ConnectedUsers[senderPID]
if ok && connectedUser != nil {
senderPID := uint32(connection.PID())
senderConnectedUser, ok := globals.ConnectedUsers.Get(senderPID)
senderFriendInfo := friends_wiiu_types.NewFriendInfo()
if ok && senderConnectedUser != nil {
var err error
senderFriendInfo.NNAInfo = senderConnectedUser.NNAInfo
senderFriendInfo.Presence = senderConnectedUser.PresenceV2
status, err := database_wiiu.GetUserComment(senderPID)
if err != nil {
globals.Logger.Critical(err.Error())
senderFriendInfo.Status = friends_wiiu_types.NewComment()
senderFriendInfo.Status.LastChanged = nex.NewDateTime(0)
} else {
senderFriendInfo.Status = status
senderFriendInfo := friends_wiiu_types.NewFriendInfo()
senderFriendInfo.NNAInfo, err = database_wiiu.GetUserNetworkAccountInfo(senderPID)
if err != nil {
globals.Logger.Critical(err.Error())
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
senderFriendInfo.Presence = senderConnectedUser.PresenceV2.Copy().(friends_wiiu_types.NintendoPresenceV2)
status, err := database_wiiu.GetUserComment(senderPID)
if err != nil {
globals.Logger.Critical(err.Error())
senderFriendInfo.Status = friends_wiiu_types.NewComment()
senderFriendInfo.Status.LastChanged = types.NewDateTime(0)
} else {
senderFriendInfo.Status = status
}
senderFriendInfo.BecameFriend = friendInfo.BecameFriend
senderFriendInfo.LastOnline = friendInfo.LastOnline // TODO - Change this
senderFriendInfo.Unknown = types.NewUInt64(0)
go notifications_wiiu.SendFriendRequestAccepted(connectedUser.Connection, senderFriendInfo)
}
senderFriendInfo.BecameFriend = friendInfo.BecameFriend
senderFriendInfo.LastOnline = friendInfo.LastOnline // TODO: Change this
senderFriendInfo.Unknown = 0
go notifications_wiiu.SendFriendRequestAccepted(connectedUser.Client, senderFriendInfo)
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream.WriteStructure(friendInfo)
friendInfo.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
// Build response packet
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodAcceptFriendRequest, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodAcceptFriendRequest
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -1,75 +1,59 @@
package nex_friends_wiiu
import (
"time"
"github.com/PretendoNetwork/friends/database"
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
"github.com/PretendoNetwork/friends/utility"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
func AddBlacklist(err error, client *nex.Client, callID uint32, blacklistPrincipal *friends_wiiu_types.BlacklistedPrincipal) uint32 {
func AddBlackList(err error, packet nex.PacketInterface, callID uint32, blacklistPrincipal friends_wiiu_types.BlacklistedPrincipal) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
connection := packet.Sender().(*nex.PRUDPConnection)
currentBlacklistPrincipal := blacklistPrincipal
senderPID := currentBlacklistPrincipal.PrincipalBasicInfo.PID
titleID := currentBlacklistPrincipal.GameKey.TitleID
titleVersion := currentBlacklistPrincipal.GameKey.TitleVersion
date := nex.NewDateTime(0)
date.FromTimestamp(time.Now())
userInfo, err := utility.GetUserInfoByPID(currentBlacklistPrincipal.PrincipalBasicInfo.PID)
userInfo, err := database_wiiu.GetUserPrincipalBasicInfo(uint32(currentBlacklistPrincipal.PrincipalBasicInfo.PID))
if err != nil {
if err == database.ErrPIDNotFound {
return nex.Errors.FPD.InvalidPrincipalID // TODO: Not sure if this is the correct error.
// TODO - Not sure if this is the correct error.
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidPrincipalID, "") // TODO - Add error message
} else {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
}
currentBlacklistPrincipal.PrincipalBasicInfo = userInfo
currentBlacklistPrincipal.BlackListedSince = date
currentBlacklistPrincipal.BlackListedSince = types.NewDateTime(0).Now()
err = database_wiiu.SetUserBlocked(client.PID(), senderPID, titleID, titleVersion)
err = database_wiiu.SetUserBlocked(uint32(connection.PID()), uint32(senderPID), uint64(titleID), uint16(titleVersion))
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream.WriteStructure(blacklistPrincipal)
blacklistPrincipal.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
// Build response packet
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodAddBlackList, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodAddBlackList
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -7,51 +7,54 @@ import (
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
notifications_wiiu "github.com/PretendoNetwork/friends/notifications/wiiu"
"github.com/PretendoNetwork/friends/utility"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
func AddFriendRequest(err error, client *nex.Client, callID uint32, pid uint32, unknown2 uint8, message string, unknown4 uint8, unknown5 string, gameKey *friends_wiiu_types.GameKey, unknown6 *nex.DateTime) uint32 {
func AddFriendRequest(err error, packet nex.PacketInterface, callID uint32, pid types.PID, unknown2 types.UInt8, message types.String, unknown4 types.UInt8, unknown5 types.String, gameKey friends_wiiu_types.GameKey, unknown6 types.DateTime) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
senderPID := client.PID()
recipientPID := pid
connection := packet.Sender().(*nex.PRUDPConnection)
senderPrincipalInfo, err := utility.GetUserInfoByPID(senderPID)
senderPID := uint32(connection.PID())
recipientPID := uint32(pid)
senderPrincipalInfo, err := database_wiiu.GetUserPrincipalBasicInfo(senderPID)
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
recipientPrincipalInfo, err := utility.GetUserInfoByPID(recipientPID)
recipientPrincipalInfo, err := database_wiiu.GetUserPrincipalBasicInfo(recipientPID)
if err != nil {
if err == database.ErrPIDNotFound {
// TODO - Not sure if this is the correct error.
globals.Logger.Errorf("User %d has sent friend request to invalid PID %d", senderPID, pid)
return nex.Errors.FPD.InvalidPrincipalID // TODO: Not sure if this is the correct error.
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidPrincipalID, "") // TODO - Add error message
} else {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
}
currentTimestamp := time.Now()
expireTimestamp := currentTimestamp.Add(time.Hour * 24 * 29)
sentTime := nex.NewDateTime(0)
expireTime := nex.NewDateTime(0)
sentTime := types.NewDateTime(0)
expireTime := types.NewDateTime(0)
sentTime.FromTimestamp(currentTimestamp)
expireTime.FromTimestamp(expireTimestamp)
friendRequestID, err := database_wiiu.SaveFriendRequest(senderPID, recipientPID, sentTime.Value(), expireTime.Value(), message)
friendRequestID, err := database_wiiu.SaveFriendRequest(senderPID, recipientPID, uint64(sentTime), uint64(expireTime), string(message))
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
friendRequest := friends_wiiu_types.NewFriendRequest()
@ -59,108 +62,92 @@ func AddFriendRequest(err error, client *nex.Client, callID uint32, pid uint32,
friendRequest.PrincipalInfo = recipientPrincipalInfo
friendRequest.Message = friends_wiiu_types.NewFriendRequestMessage()
friendRequest.Message.FriendRequestID = friendRequestID
friendRequest.Message.Received = false
friendRequest.Message.Unknown2 = 1 // replaying from real
friendRequest.Message.FriendRequestID = types.NewUInt64(friendRequestID)
friendRequest.Message.Received = types.NewBool(false)
friendRequest.Message.Unknown2 = types.NewUInt8(1) // * Replaying from official server
friendRequest.Message.Message = message
friendRequest.Message.Unknown3 = 0 // replaying from real server
friendRequest.Message.Unknown4 = "" // replaying from real server
friendRequest.Message.GameKey = gameKey // maybe this is reused?
friendRequest.Message.Unknown5 = unknown6 // maybe this is reused?
friendRequest.Message.ExpiresOn = expireTime // no idea why this is set as the sent time
friendRequest.Message.Unknown3 = types.NewUInt8(0) // * Replaying from official server
friendRequest.Message.Unknown4 = types.NewString("") // * Replaying from official server
friendRequest.Message.GameKey = gameKey // * Maybe this is reused?
friendRequest.Message.Unknown5 = unknown6 // * Maybe this is reused?
friendRequest.Message.ExpiresOn = expireTime // * No idea why this is set as the sent time
friendRequest.SentOn = sentTime
// Why does this exist?? Always empty??
// * Why does this exist?? Always empty??
friendInfo := friends_wiiu_types.NewFriendInfo()
friendInfo.NNAInfo = friends_wiiu_types.NewNNAInfo()
friendInfo.NNAInfo.PrincipalBasicInfo = friends_wiiu_types.NewPrincipalBasicInfo()
friendInfo.NNAInfo.PrincipalBasicInfo.PID = 0
friendInfo.NNAInfo.PrincipalBasicInfo.NNID = ""
friendInfo.NNAInfo.PrincipalBasicInfo.PID = types.NewPID(0)
friendInfo.NNAInfo.PrincipalBasicInfo.NNID = types.NewString("")
friendInfo.NNAInfo.PrincipalBasicInfo.Mii = friends_wiiu_types.NewMiiV2()
friendInfo.NNAInfo.PrincipalBasicInfo.Mii.Name = ""
friendInfo.NNAInfo.PrincipalBasicInfo.Mii.Unknown1 = 0
friendInfo.NNAInfo.PrincipalBasicInfo.Mii.Unknown2 = 0
friendInfo.NNAInfo.PrincipalBasicInfo.Mii.MiiData = []byte{}
friendInfo.NNAInfo.PrincipalBasicInfo.Mii.Datetime = nex.NewDateTime(0)
friendInfo.NNAInfo.PrincipalBasicInfo.Unknown = 0
friendInfo.NNAInfo.Unknown1 = 0
friendInfo.NNAInfo.Unknown2 = 0
friendInfo.NNAInfo.PrincipalBasicInfo.Mii.Name = types.NewString("")
friendInfo.NNAInfo.PrincipalBasicInfo.Mii.Unknown1 = types.NewUInt8(0)
friendInfo.NNAInfo.PrincipalBasicInfo.Mii.Unknown2 = types.NewUInt8(0)
friendInfo.NNAInfo.PrincipalBasicInfo.Mii.MiiData = types.NewBuffer([]byte{})
friendInfo.NNAInfo.PrincipalBasicInfo.Mii.Datetime = types.NewDateTime(0)
friendInfo.NNAInfo.PrincipalBasicInfo.Unknown = types.NewUInt8(0)
friendInfo.NNAInfo.Unknown1 = types.NewUInt8(0)
friendInfo.NNAInfo.Unknown2 = types.NewUInt8(0)
friendInfo.Presence = friends_wiiu_types.NewNintendoPresenceV2()
friendInfo.Presence.ChangedFlags = 0
friendInfo.Presence.Online = false
friendInfo.Presence.GameKey = gameKey // maybe this is reused?
friendInfo.Presence.Unknown1 = 0
friendInfo.Presence.Message = ""
friendInfo.Presence.Unknown2 = 0
friendInfo.Presence.Unknown3 = 0
friendInfo.Presence.GameServerID = 0
friendInfo.Presence.Unknown4 = 0
friendInfo.Presence.PID = 0
friendInfo.Presence.GatheringID = 0
friendInfo.Presence.ApplicationData = []byte{0x00}
friendInfo.Presence.Unknown5 = 0
friendInfo.Presence.Unknown6 = 0
friendInfo.Presence.Unknown7 = 0
friendInfo.Presence.ChangedFlags = types.NewUInt32(0)
friendInfo.Presence.Online = types.NewBool(false)
friendInfo.Presence.GameKey = gameKey // * Maybe this is reused?
friendInfo.Presence.Unknown1 = types.NewUInt8(0)
friendInfo.Presence.Message = types.NewString("")
friendInfo.Presence.Unknown2 = types.NewUInt32(0)
friendInfo.Presence.Unknown3 = types.NewUInt8(0)
friendInfo.Presence.GameServerID = types.NewUInt32(0)
friendInfo.Presence.Unknown4 = types.NewUInt32(0)
friendInfo.Presence.PID = types.NewPID(0)
friendInfo.Presence.GatheringID = types.NewUInt32(0)
friendInfo.Presence.ApplicationData = types.NewBuffer([]byte{0x00})
friendInfo.Presence.Unknown5 = types.NewUInt8(0)
friendInfo.Presence.Unknown6 = types.NewUInt8(0)
friendInfo.Presence.Unknown7 = types.NewUInt8(0)
friendInfo.Status = friends_wiiu_types.NewComment()
friendInfo.Status.Unknown = 0
friendInfo.Status.Contents = ""
friendInfo.Status.LastChanged = nex.NewDateTime(0)
friendInfo.Status.Unknown = types.NewUInt8(0)
friendInfo.Status.Contents = types.NewString("")
friendInfo.Status.LastChanged = types.NewDateTime(0)
friendInfo.BecameFriend = nex.NewDateTime(0)
friendInfo.LastOnline = nex.NewDateTime(0)
friendInfo.Unknown = 0
friendInfo.BecameFriend = types.NewDateTime(0)
friendInfo.LastOnline = types.NewDateTime(0)
friendInfo.Unknown = types.NewUInt64(0)
recipientClient := client.Server().FindClientFromPID(recipientPID)
if recipientClient != nil {
recipientClient, ok := globals.ConnectedUsers.Get(recipientPID)
if ok && recipientClient != nil {
friendRequestNotificationData := friends_wiiu_types.NewFriendRequest()
friendRequestNotificationData.PrincipalInfo = senderPrincipalInfo
friendRequestNotificationData.Message = friends_wiiu_types.NewFriendRequestMessage()
friendRequestNotificationData.Message.FriendRequestID = friendRequestID
friendRequestNotificationData.Message.Received = false
friendRequestNotificationData.Message.Unknown2 = 1 // replaying from real
friendRequestNotificationData.Message.FriendRequestID = types.NewUInt64(friendRequestID)
friendRequestNotificationData.Message.Received = types.NewBool(false)
friendRequestNotificationData.Message.Unknown2 = types.NewUInt8(1) // * Replaying from official server
friendRequestNotificationData.Message.Message = message
friendRequestNotificationData.Message.Unknown3 = 0 // replaying from real server
friendRequestNotificationData.Message.Unknown4 = "" // replaying from real server
friendRequestNotificationData.Message.GameKey = gameKey // maybe this is reused?
friendRequestNotificationData.Message.Unknown5 = unknown6 // maybe this is reused?
friendRequestNotificationData.Message.ExpiresOn = expireTime // no idea why this is set as the sent time
friendRequestNotificationData.Message.Unknown3 = types.NewUInt8(0) // * Replaying from server server
friendRequestNotificationData.Message.Unknown4 = types.NewString("") // * Replaying from server server
friendRequestNotificationData.Message.GameKey = gameKey // * Maybe this is reused?
friendRequestNotificationData.Message.Unknown5 = unknown6 // * Maybe this is reused?
friendRequestNotificationData.Message.ExpiresOn = expireTime // * No idea why this is set as the sent time
friendRequestNotificationData.SentOn = sentTime
go notifications_wiiu.SendFriendRequest(recipientClient, friendRequestNotificationData)
go notifications_wiiu.SendFriendRequest(recipientClient.Connection, friendRequestNotificationData)
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream.WriteStructure(friendRequest)
rmcResponseStream.WriteStructure(friendInfo)
friendRequest.WriteTo(rmcResponseStream)
friendInfo.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
// Build response packet
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodAddFriendRequest, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodAddFriendRequest
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -5,49 +5,39 @@ import (
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
notifications_wiiu "github.com/PretendoNetwork/friends/notifications/wiiu"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
)
func CancelFriendRequest(err error, client *nex.Client, callID uint32, id uint64) uint32 {
func CancelFriendRequest(err error, packet nex.PacketInterface, callID uint32, id types.UInt64) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
pid, err := database_wiiu.DeleteFriendRequestAndReturnFriendPID(id)
connection := packet.Sender().(*nex.PRUDPConnection)
pid, err := database_wiiu.DeleteFriendRequestAndReturnFriendPID(uint64(id))
if err != nil {
if err == database.ErrFriendRequestNotFound {
return nex.Errors.FPD.InvalidMessageID
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidMessageID, "") // TODO - Add error message
} else {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
}
connectedUser := globals.ConnectedUsers[pid]
if connectedUser != nil {
// This may send the friend removed notification, but they are the same.
go notifications_wiiu.SendFriendshipRemoved(connectedUser.Client, client.PID())
connectedUser, ok := globals.ConnectedUsers.Get(pid)
if ok && connectedUser != nil {
// * This may send the friend removed notification, but they are the same.
go notifications_wiiu.SendFriendshipRemoved(connectedUser.Connection, connection.PID())
}
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodCancelFriendRequest, nil)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodCancelFriendRequest
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -2,40 +2,29 @@ package nex_friends_wiiu
import (
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
)
func CheckSettingStatus(err error, client *nex.Client, callID uint32) uint32 {
func CheckSettingStatus(err error, packet nex.PacketInterface, callID uint32) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
status := types.NewUInt8(0xFF) // TODO - What is this??
rmcResponseStream.WriteUInt8(0xFF)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
status.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
// Build response packet
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodCheckSettingStatus, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodCheckSettingStatus
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -4,43 +4,31 @@ import (
"github.com/PretendoNetwork/friends/database"
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
)
func DeleteFriendRequest(err error, client *nex.Client, callID uint32, id uint64) uint32 {
func DeleteFriendRequest(err error, packet nex.PacketInterface, callID uint32, id types.UInt64) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
err = database_wiiu.SetFriendRequestDenied(id)
err = database_wiiu.SetFriendRequestDenied(uint64(id))
if err != nil {
if err == database.ErrFriendRequestNotFound {
return nex.Errors.FPD.InvalidMessageID
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidMessageID, "") // TODO - Add error message
} else {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
}
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodDeleteFriendRequest, nil)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodDeleteFriendRequest
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -2,36 +2,24 @@ package nex_friends_wiiu
import (
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
func DeletePersistentNotification(err error, client *nex.Client, callID uint32, notifications []*friends_wiiu_types.PersistentNotification) uint32 {
func DeletePersistentNotification(err error, packet nex.PacketInterface, callID uint32, notifications types.List[friends_wiiu_types.PersistentNotification]) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
// TODO: Do something here
// TODO - Do something here
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodDeletePersistentNotification, nil)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodDeletePersistentNotification
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -6,80 +6,68 @@ import (
"github.com/PretendoNetwork/friends/database"
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
"github.com/PretendoNetwork/friends/utility"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
func DenyFriendRequest(err error, client *nex.Client, callID uint32, id uint64) uint32 {
func DenyFriendRequest(err error, packet nex.PacketInterface, callID uint32, id types.UInt64) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
err = database_wiiu.SetFriendRequestDenied(id)
connection := packet.Sender().(*nex.PRUDPConnection)
err = database_wiiu.SetFriendRequestDenied(uint64(id))
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
senderPID, _, err := database_wiiu.GetPIDsByFriendRequestID(id)
senderPID, _, err := database_wiiu.GetPIDsByFriendRequestID(uint64(id))
if err != nil {
if err == database.ErrFriendRequestNotFound {
return nex.Errors.FPD.InvalidMessageID
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidMessageID, "") // TODO - Add error message
} else {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
}
err = database_wiiu.SetUserBlocked(client.PID(), senderPID, 0, 0)
err = database_wiiu.SetUserBlocked(uint32(connection.PID()), senderPID, 0, 0)
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
info, err := utility.GetUserInfoByPID(senderPID)
info, err := database_wiiu.GetUserPrincipalBasicInfo(senderPID)
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
date := nex.NewDateTime(0)
date := types.NewDateTime(0)
date.FromTimestamp(time.Now())
// Create a new blacklist principal for the client, as unlike AddBlacklist they don't send one to us.
// Create a new blacklist principal for the connection, as unlike AddBlacklist they don't send one to us.
blacklistPrincipal := friends_wiiu_types.NewBlacklistedPrincipal()
blacklistPrincipal.PrincipalBasicInfo = info
blacklistPrincipal.GameKey = friends_wiiu_types.NewGameKey()
blacklistPrincipal.BlackListedSince = date
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream.WriteStructure(blacklistPrincipal)
blacklistPrincipal.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
// Build response packet
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodDenyFriendRequest, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodDenyFriendRequest
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -1,28 +1,27 @@
package nex_friends_wiiu
import (
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
"github.com/PretendoNetwork/friends/utility"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
func GetBasicInfo(err error, client *nex.Client, callID uint32, pids []uint32) uint32 {
func GetBasicInfo(err error, packet nex.PacketInterface, callID uint32, pids types.List[types.PID]) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
infos := make([]*friends_wiiu_types.PrincipalBasicInfo, 0)
infos := types.NewList[friends_wiiu_types.PrincipalBasicInfo]()
for i := 0; i < len(pids); i++ {
pid := pids[i]
info, err := utility.GetUserInfoByPID(pid)
for _, pid := range pids {
info, err := database_wiiu.GetUserPrincipalBasicInfo(uint32(pid))
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
if info.PID != 0 {
@ -30,30 +29,16 @@ func GetBasicInfo(err error, client *nex.Client, callID uint32, pids []uint32) u
}
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream.WriteListStructure(infos)
infos.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
// Build response packet
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodGetBasicInfo, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodGetBasicInfo
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -3,61 +3,48 @@ package nex_friends_wiiu
import (
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
func GetRequestBlockSettings(err error, client *nex.Client, callID uint32, pids []uint32) uint32 {
func GetRequestBlockSettings(err error, packet nex.PacketInterface, callID uint32, pids types.List[types.UInt32]) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
settings := make([]*friends_wiiu_types.PrincipalRequestBlockSetting, 0)
connection := packet.Sender().(*nex.PRUDPConnection)
// TODO:
// Improve this. Use less database_wiiu.reads
for i := 0; i < len(pids); i++ {
requestedPID := pids[i]
settings := types.NewList[friends_wiiu_types.PrincipalRequestBlockSetting]()
// TODO - Improve this. Use less database_wiiu reads
for _, pid := range pids {
setting := friends_wiiu_types.NewPrincipalRequestBlockSetting()
setting.PID = requestedPID
isBlocked, err := database_wiiu.IsFriendRequestBlocked(client.PID(), requestedPID)
setting.PID = pid
isBlocked, err := database_wiiu.IsFriendRequestBlocked(uint32(connection.PID()), uint32(pid))
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.Core.Unknown
return nil, nex.NewError(nex.ResultCodes.Core.Unknown, "") // TODO - Add error message
}
setting.IsBlocked = isBlocked
setting.IsBlocked = types.NewBool(isBlocked)
settings = append(settings, setting)
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream.WriteListStructure(settings)
settings.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
// Build response packet
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodGetRequestBlockSettings, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodGetRequestBlockSettings
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -3,42 +3,29 @@ package nex_friends_wiiu
import (
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
)
func MarkFriendRequestsAsReceived(err error, client *nex.Client, callID uint32, ids []uint64) uint32 {
func MarkFriendRequestsAsReceived(err error, packet nex.PacketInterface, callID uint32, ids types.List[types.UInt64]) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
for i := 0; i < len(ids); i++ {
id := ids[i]
err = database_wiiu.SetFriendRequestReceived(id)
for _, id := range ids {
err = database_wiiu.SetFriendRequestReceived(uint64(id))
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
}
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodMarkFriendRequestsAsReceived, nil)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodMarkFriendRequestsAsReceived
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -4,43 +4,33 @@ import (
"github.com/PretendoNetwork/friends/database"
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
)
func RemoveBlacklist(err error, client *nex.Client, callID uint32, blockedPID uint32) uint32 {
func RemoveBlackList(err error, packet nex.PacketInterface, callID uint32, blockedPID types.PID) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
err = database_wiiu.UnsetUserBlocked(client.PID(), blockedPID)
connection := packet.Sender().(*nex.PRUDPConnection)
err = database_wiiu.UnsetUserBlocked(uint32(connection.PID()), uint32(blockedPID))
if err != nil {
if err == database.ErrPIDNotFound {
return nex.Errors.FPD.NotInMyBlacklist
return nil, nex.NewError(nex.ResultCodes.FPD.NotInMyBlacklist, "") // TODO - Add error message
} else {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
}
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodRemoveBlackList, nil)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodRemoveBlackList
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -5,48 +5,38 @@ import (
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
notifications_wiiu "github.com/PretendoNetwork/friends/notifications/wiiu"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
)
func RemoveFriend(err error, client *nex.Client, callID uint32, pid uint32) uint32 {
func RemoveFriend(err error, packet nex.PacketInterface, callID uint32, pid types.PID) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
err = database_wiiu.RemoveFriendship(client.PID(), pid)
connection := packet.Sender().(*nex.PRUDPConnection)
err = database_wiiu.RemoveFriendship(uint32(connection.PID()), uint32(pid))
if err != nil {
if err == database.ErrFriendshipNotFound {
return nex.Errors.FPD.NotInMyFriendList
return nil, nex.NewError(nex.ResultCodes.FPD.NotInMyFriendList, "") // TODO - Add error message
} else {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
}
connectedUser := globals.ConnectedUsers[pid]
if connectedUser != nil {
go notifications_wiiu.SendFriendshipRemoved(connectedUser.Client, pid)
connectedUser, ok := globals.ConnectedUsers.Get(uint32(pid))
if ok && connectedUser != nil {
go notifications_wiiu.SendFriendshipRemoved(connectedUser.Connection, pid)
}
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodRemoveFriend, nil)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodRemoveFriend
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -7,84 +7,89 @@ import (
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
notifications_wiiu "github.com/PretendoNetwork/friends/notifications/wiiu"
"github.com/PretendoNetwork/friends/types"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
friends_types "github.com/PretendoNetwork/friends/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
func UpdateAndGetAllInformation(err error, client *nex.Client, callID uint32, nnaInfo *friends_wiiu_types.NNAInfo, presence *friends_wiiu_types.NintendoPresenceV2, birthday *nex.DateTime) uint32 {
func UpdateAndGetAllInformation(err error, packet nex.PacketInterface, callID uint32, nnaInfo friends_wiiu_types.NNAInfo, presence friends_wiiu_types.NintendoPresenceV2, birthday types.DateTime) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
// Get user information
pid := client.PID()
connection := packet.Sender().(*nex.PRUDPConnection)
if globals.ConnectedUsers[pid] == nil {
// TODO - Figure out why this is getting removed
connectedUser := types.NewConnectedUser()
// * Get user information
pid := uint32(connection.PID())
connectedUser, ok := globals.ConnectedUsers.Get(pid)
if !ok || connectedUser == nil {
// * Failsafe
connectedUser = friends_types.NewConnectedUser()
connectedUser.PID = pid
connectedUser.Platform = types.WUP
connectedUser.Client = client
connectedUser.Platform = friends_types.WUP
connectedUser.Connection = connection
globals.ConnectedUsers[pid] = connectedUser
globals.ConnectedUsers.Set(pid, connectedUser)
}
globals.ConnectedUsers[pid].NNAInfo = nnaInfo
globals.ConnectedUsers[pid].PresenceV2 = presence
connectedUser.PresenceV2 = presence.Copy().(friends_wiiu_types.NintendoPresenceV2)
database_wiiu.UpdateNetworkAccountInfo(pid, nnaInfo, birthday)
principalPreference, err := database_wiiu.GetUserPrincipalPreference(pid)
if err != nil {
if err == database.ErrPIDNotFound {
return nex.Errors.FPD.InvalidPrincipalID
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidPrincipalID, "") // TODO - Add error message
} else {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
}
comment, err := database_wiiu.GetUserComment(pid)
if err != nil {
if err == database.ErrPIDNotFound {
return nex.Errors.FPD.InvalidPrincipalID
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidPrincipalID, "") // TODO - Add error message
} else {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
}
friendList, err := database_wiiu.GetUserFriendList(pid)
if err != nil && err != database.ErrEmptyList {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
friendRequestsOut, err := database_wiiu.GetUserFriendRequestsOut(pid)
if err != nil && err != database.ErrEmptyList {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
friendRequestsIn, err := database_wiiu.GetUserFriendRequestsIn(pid)
if err != nil && err != database.ErrEmptyList {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
blockList, err := database_wiiu.GetUserBlockList(pid)
if err != nil && err != database.ErrBlacklistNotFound {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
notifications := database_wiiu.GetUserNotifications(pid)
// Update user information
// * Update user information
presence.Online = true // Force online status. I have no idea why this is always false
presence.PID = pid // WHY IS THIS SET TO 0 BY DEFAULT??
presence.Online = types.NewBool(true) // * Force online status. I have no idea why this is always false
presence.PID = connection.PID() // * WHY IS THIS SET TO 0 BY DEFAULT??
notifications_wiiu.SendPresenceUpdate(presence)
@ -94,23 +99,23 @@ func UpdateAndGetAllInformation(err error, client *nex.Client, callID uint32, nn
bella.NNAInfo = friends_wiiu_types.NewNNAInfo()
bella.Presence = friends_wiiu_types.NewNintendoPresenceV2()
bella.Status = friends_wiiu_types.NewComment()
bella.BecameFriend = nex.NewDateTime(0)
bella.LastOnline = nex.NewDateTime(0)
bella.Unknown = 0
bella.BecameFriend = types.NewDateTime(0)
bella.LastOnline = types.NewDateTime(0)
bella.Unknown = types.NewUInt64(0)
bella.NNAInfo.PrincipalBasicInfo = friends_wiiu_types.NewPrincipalBasicInfo()
bella.NNAInfo.Unknown1 = 0
bella.NNAInfo.Unknown2 = 0
bella.NNAInfo.Unknown1 = types.NewUInt8(0)
bella.NNAInfo.Unknown2 = types.NewUInt8(0)
bella.NNAInfo.PrincipalBasicInfo.PID = 1743126339
bella.NNAInfo.PrincipalBasicInfo.NNID = "bells1998"
bella.NNAInfo.PrincipalBasicInfo.PID = types.NewPID(1743126339)
bella.NNAInfo.PrincipalBasicInfo.NNID = types.NewString("bells1998")
bella.NNAInfo.PrincipalBasicInfo.Mii = friends_wiiu_types.NewMiiV2()
bella.NNAInfo.PrincipalBasicInfo.Unknown = 0
bella.NNAInfo.PrincipalBasicInfo.Unknown = types.NewUInt8(0)
bella.NNAInfo.PrincipalBasicInfo.Mii.Name = "bella"
bella.NNAInfo.PrincipalBasicInfo.Mii.Unknown1 = 0
bella.NNAInfo.PrincipalBasicInfo.Mii.Unknown2 = 0
bella.NNAInfo.PrincipalBasicInfo.Mii.MiiData = []byte{
bella.NNAInfo.PrincipalBasicInfo.Mii.Name = types.NewString("bella")
bella.NNAInfo.PrincipalBasicInfo.Mii.Unknown1 = types.NewUInt8(0)
bella.NNAInfo.PrincipalBasicInfo.Mii.Unknown2 = types.NewUInt8(0)
bella.NNAInfo.PrincipalBasicInfo.Mii.MiiData = types.NewBuffer([]byte{
0x03, 0x00, 0x00, 0x40, 0xE9, 0x55, 0xA2, 0x09,
0xE7, 0xC7, 0x41, 0x82, 0xD9, 0x7D, 0x0B, 0x2D,
0x03, 0xB3, 0xB8, 0x8D, 0x27, 0xD9, 0x00, 0x00,
@ -123,77 +128,61 @@ func UpdateAndGetAllInformation(err error, client *nex.Client, callID uint32, nn
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x86,
}
bella.NNAInfo.PrincipalBasicInfo.Mii.Datetime = nex.NewDateTime(0)
})
bella.NNAInfo.PrincipalBasicInfo.Mii.Datetime = types.NewDateTime(0)
bella.Presence.ChangedFlags = 0x1EE
bella.Presence.Online = true
bella.Presence.ChangedFlags = types.NewUInt32(0x1EE)
bella.Presence.Online = types.NewBool(true)
bella.Presence.GameKey = friends_wiiu_types.NewGameKey()
bella.Presence.Unknown1 = 0
bella.Presence.Message = "Testing"
bella.Presence.Unknown1 = types.NewUInt8(0)
bella.Presence.Message = types.NewString("Testing")
//bella.Presence.Unknown2 = 2
bella.Presence.Unknown2 = 0
bella.Presence.Unknown2 = types.NewUInt32(0)
//bella.Presence.Unknown3 = 2
bella.Presence.Unknown3 = 0
bella.Presence.Unknown3 = types.NewUInt8(0)
//bella.Presence.GameServerID = 0x1010EB00
bella.Presence.GameServerID = 0
bella.Presence.GameServerID = types.NewUInt32(0)
//bella.Presence.Unknown4 = 3
bella.Presence.Unknown4 = 0
bella.Presence.PID = 1743126339
bella.Presence.Unknown4 = types.NewUInt32(0)
bella.Presence.PID = types.NewPID(1743126339)
//bella.Presence.GatheringID = 1743126339 // test fake ID
bella.Presence.GatheringID = 0
bella.Presence.GatheringID = types.NewUInt32(0)
//bella.Presence.ApplicationData, _ = hex.DecodeString("0000200300000000000000001843ffe567000000")
bella.Presence.ApplicationData = []byte{0x0}
bella.Presence.Unknown5 = 0
bella.Presence.Unknown6 = 0
bella.Presence.Unknown7 = 0
bella.Presence.ApplicationData = types.NewBuffer([]byte{0x0})
bella.Presence.Unknown5 = types.NewUInt8(0)
bella.Presence.Unknown6 = types.NewUInt8(0)
bella.Presence.Unknown7 = types.NewUInt8(0)
//bella.Presence.GameKey.TitleID = 0x000500001010EC00
bella.Presence.GameKey.TitleID = 0
bella.Presence.GameKey.TitleID = types.NewUInt64(0)
//bella.Presence.GameKey.TitleVersion = 64
bella.Presence.GameKey.TitleVersion = 0
bella.Presence.GameKey.TitleVersion = types.NewUInt16(0)
bella.Status.Unknown = 0
bella.Status.Contents = "test"
bella.Status.LastChanged = nex.NewDateTime(0)
bella.Status.Unknown = types.NewUInt8(0)
bella.Status.Contents = types.NewString("test")
bella.Status.LastChanged = types.NewDateTime(0)
friendList = append(friendList, bella)
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream.WriteStructure(principalPreference)
rmcResponseStream.WriteStructure(comment)
rmcResponseStream.WriteListStructure(friendList)
rmcResponseStream.WriteListStructure(friendRequestsOut)
rmcResponseStream.WriteListStructure(friendRequestsIn)
rmcResponseStream.WriteListStructure(blockList)
rmcResponseStream.WriteBool(false) // Unknown
rmcResponseStream.WriteListStructure(notifications)
//Unknown Bool
rmcResponseStream.WriteUInt8(0)
principalPreference.WriteTo(rmcResponseStream)
comment.WriteTo(rmcResponseStream)
friendList.WriteTo(rmcResponseStream)
friendRequestsOut.WriteTo(rmcResponseStream)
friendRequestsIn.WriteTo(rmcResponseStream)
blockList.WriteTo(rmcResponseStream)
types.NewBool(false).WriteTo(rmcResponseStream) // * Unknown
notifications.WriteTo(rmcResponseStream)
types.NewBool(false).WriteTo(rmcResponseStream) // * Unknown
rmcResponseBody := rmcResponseStream.Bytes()
// Build response packet
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodUpdateAndGetAllInformation, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodUpdateAndGetAllInformation
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -3,46 +3,36 @@ package nex_friends_wiiu
import (
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
func UpdateComment(err error, client *nex.Client, callID uint32, comment *friends_wiiu_types.Comment) uint32 {
func UpdateComment(err error, packet nex.PacketInterface, callID uint32, comment friends_wiiu_types.Comment) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
changed, err := database_wiiu.UpdateUserComment(client.PID(), comment.Contents)
connection := packet.Sender().(*nex.PRUDPConnection)
changed, err := database_wiiu.UpdateUserComment(uint32(connection.PID()), string(comment.Contents))
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcResponseStream.WriteUInt64LE(changed)
types.NewUInt64(changed).WriteTo(rmcResponseStream) // TODO - This is ugly
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodUpdateComment, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodUpdateComment
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -3,40 +3,29 @@ package nex_friends_wiiu
import (
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
nex "github.com/PretendoNetwork/nex-go/v2"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
func UpdatePreference(err error, client *nex.Client, callID uint32, principalPreference *friends_wiiu_types.PrincipalPreference) uint32 {
func UpdatePreference(err error, packet nex.PacketInterface, callID uint32, principalPreference friends_wiiu_types.PrincipalPreference) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
err = database_wiiu.UpdateUserPrincipalPreference(client.PID(), principalPreference)
connection := packet.Sender().(*nex.PRUDPConnection)
err = database_wiiu.UpdateUserPrincipalPreference(uint32(connection.PID()), principalPreference)
if err != nil {
globals.Logger.Critical(err.Error())
return nex.Errors.FPD.Unknown
return nil, nex.NewError(nex.ResultCodes.FPD.Unknown, "") // TODO - Add error message
}
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodUpdatePreference, nil)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodUpdatePreference
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -3,55 +3,47 @@ package nex_friends_wiiu
import (
"github.com/PretendoNetwork/friends/globals"
notifications_wiiu "github.com/PretendoNetwork/friends/notifications/wiiu"
"github.com/PretendoNetwork/friends/types"
nex "github.com/PretendoNetwork/nex-go"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu/types"
friends_types "github.com/PretendoNetwork/friends/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
friends_wiiu_types "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu/types"
)
func UpdatePresence(err error, client *nex.Client, callID uint32, presence *friends_wiiu_types.NintendoPresenceV2) uint32 {
func UpdatePresence(err error, packet nex.PacketInterface, callID uint32, presence friends_wiiu_types.NintendoPresenceV2) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.FPD.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.FPD.InvalidArgument, "") // TODO - Add error message
}
pid := client.PID()
connection := packet.Sender().(*nex.PRUDPConnection)
presence.Online = true // Force online status. I have no idea why this is always false
presence.PID = pid // WHY IS THIS SET TO 0 BY DEFAULT??
pid := uint32(connection.PID())
if globals.ConnectedUsers[pid] == nil {
presence.Online = types.NewBool(true) // * Force online status. I have no idea why this is always false
presence.PID = connection.PID() // * WHY IS THIS SET TO 0 BY DEFAULT??
connectedUser, ok := globals.ConnectedUsers.Get(pid)
if !ok || connectedUser == nil {
// TODO - Figure out why this is getting removed
connectedUser := types.NewConnectedUser()
connectedUser = friends_types.NewConnectedUser()
connectedUser.PID = pid
connectedUser.Platform = types.WUP
connectedUser.Client = client
connectedUser.Platform = friends_types.WUP
connectedUser.Connection = connection
// TODO - Find a clean way to create a NNAInfo?
globals.ConnectedUsers[pid] = connectedUser
globals.ConnectedUsers.Set(pid, connectedUser)
}
globals.ConnectedUsers[pid].PresenceV2 = presence
connectedUser.PresenceV2 = presence.Copy().(friends_wiiu_types.NintendoPresenceV2)
notifications_wiiu.SendPresenceUpdate(presence)
rmcResponse := nex.NewRMCResponse(friends_wiiu.ProtocolID, callID)
rmcResponse.SetSuccess(friends_wiiu.MethodUpdatePresence, nil)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, nil)
rmcResponse.ProtocolID = friends_wiiu.ProtocolID
rmcResponse.MethodID = friends_wiiu.MethodUpdatePresence
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -5,28 +5,33 @@ import (
"strconv"
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
ticket_granting "github.com/PretendoNetwork/nex-protocols-common-go/ticket-granting"
"github.com/PretendoNetwork/nex-go/v2/constants"
"github.com/PretendoNetwork/nex-go/v2/types"
common_ticket_granting "github.com/PretendoNetwork/nex-protocols-common-go/v2/ticket-granting"
ticket_granting "github.com/PretendoNetwork/nex-protocols-go/v2/ticket-granting"
)
func registerCommonAuthenticationServerProtocols() {
ticketGrantingProtocol := ticket_granting.NewCommonTicketGrantingProtocol(globals.AuthenticationServer)
ticketGrantingProtocol := ticket_granting.NewProtocol()
commonTicketGrantingProtocol := common_ticket_granting.NewCommonProtocol(ticketGrantingProtocol)
port, _ := strconv.Atoi(os.Getenv("PN_FRIENDS_SECURE_SERVER_PORT"))
secureStationURL := nex.NewStationURL("")
secureStationURL.SetScheme("prudps")
secureStationURL := types.NewStationURL("")
secureStationURL.SetURLType(constants.StationURLPRUDPS)
secureStationURL.SetAddress(os.Getenv("PN_FRIENDS_SECURE_SERVER_HOST"))
secureStationURL.SetPort(uint32(port))
secureStationURL.SetCID(1)
secureStationURL.SetPID(2)
secureStationURL.SetSID(1)
secureStationURL.SetStream(10)
secureStationURL.SetPortNumber(uint16(port))
secureStationURL.SetConnectionID(1)
secureStationURL.SetPrincipalID(types.NewPID(2))
secureStationURL.SetStreamID(1)
secureStationURL.SetStreamType(constants.StreamTypeRVSecure)
secureStationURL.SetType(2)
ticketGrantingProtocol.SetSecureStationURL(secureStationURL)
ticketGrantingProtocol.SetBuildName(serverBuildString)
ticketGrantingProtocol.EnableInsecureLogin()
commonTicketGrantingProtocol.SecureServerAccount = globals.SecureEndpoint.ServerAccount
commonTicketGrantingProtocol.SessionKeyLength = 16
commonTicketGrantingProtocol.SecureStationURL = secureStationURL
commonTicketGrantingProtocol.BuildName = types.NewString(serverBuildString)
commonTicketGrantingProtocol.EnableInsecureLogin()
globals.AuthenticationServer.SetPasswordFromPIDFunction(globals.PasswordFromPID)
globals.AuthenticationEndpoint.RegisterServiceProtocol(ticketGrantingProtocol)
}

View File

@ -3,10 +3,15 @@ package nex
import (
"github.com/PretendoNetwork/friends/globals"
nex_secure_connection "github.com/PretendoNetwork/friends/nex/secure-connection"
secureconnection "github.com/PretendoNetwork/nex-protocols-common-go/secure-connection"
common_secure_connection "github.com/PretendoNetwork/nex-protocols-common-go/v2/secure-connection"
secure_connection "github.com/PretendoNetwork/nex-protocols-go/v2/secure-connection"
)
func registerCommonSecureServerProtocols() {
secureConnectionProtocol := secureconnection.NewCommonSecureConnectionProtocol(globals.SecureServer)
secureConnectionProtocol.RegisterEx(nex_secure_connection.RegisterEx)
secureConnectionProtocol := secure_connection.NewProtocol()
common_secure_connection.NewCommonProtocol(secureConnectionProtocol)
secureConnectionProtocol.RegisterEx = nex_secure_connection.RegisterEx
globals.SecureEndpoint.RegisterServiceProtocol(secureConnectionProtocol)
}

View File

@ -5,52 +5,56 @@ import (
nex_account_management "github.com/PretendoNetwork/friends/nex/account-management"
nex_friends_3ds "github.com/PretendoNetwork/friends/nex/friends-3ds"
nex_friends_wiiu "github.com/PretendoNetwork/friends/nex/friends-wiiu"
account_management "github.com/PretendoNetwork/nex-protocols-go/account-management"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/friends-3ds"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/friends-wiiu"
account_management "github.com/PretendoNetwork/nex-protocols-go/v2/account-management"
friends_3ds "github.com/PretendoNetwork/nex-protocols-go/v2/friends-3ds"
friends_wiiu "github.com/PretendoNetwork/nex-protocols-go/v2/friends-wiiu"
)
func registerSecureServerProtocols() {
accountManagementProtocol := account_management.NewProtocol(globals.SecureServer)
friendsWiiUProtocol := friends_wiiu.NewProtocol(globals.SecureServer)
friends3DSProtocol := friends_3ds.NewProtocol(globals.SecureServer)
accountManagementProtocol := account_management.NewProtocol()
friendsWiiUProtocol := friends_wiiu.NewProtocol()
friends3DSProtocol := friends_3ds.NewProtocol()
// Account Management protocol handles
accountManagementProtocol.NintendoCreateAccount(nex_account_management.NintendoCreateAccount)
// * Account Management protocol handles
accountManagementProtocol.NintendoCreateAccount = nex_account_management.NintendoCreateAccount
// Friends (WiiU) protocol handles
friendsWiiUProtocol.UpdateAndGetAllInformation(nex_friends_wiiu.UpdateAndGetAllInformation)
friendsWiiUProtocol.AddFriendRequest(nex_friends_wiiu.AddFriendRequest)
friendsWiiUProtocol.RemoveFriend(nex_friends_wiiu.RemoveFriend)
friendsWiiUProtocol.CancelFriendRequest(nex_friends_wiiu.CancelFriendRequest)
friendsWiiUProtocol.AcceptFriendRequest(nex_friends_wiiu.AcceptFriendRequest)
friendsWiiUProtocol.DeleteFriendRequest(nex_friends_wiiu.DeleteFriendRequest)
friendsWiiUProtocol.DenyFriendRequest(nex_friends_wiiu.DenyFriendRequest)
friendsWiiUProtocol.MarkFriendRequestsAsReceived(nex_friends_wiiu.MarkFriendRequestsAsReceived)
friendsWiiUProtocol.AddBlackList(nex_friends_wiiu.AddBlacklist)
friendsWiiUProtocol.RemoveBlackList(nex_friends_wiiu.RemoveBlacklist)
friendsWiiUProtocol.UpdatePresence(nex_friends_wiiu.UpdatePresence)
friendsWiiUProtocol.UpdateComment(nex_friends_wiiu.UpdateComment)
friendsWiiUProtocol.UpdatePreference(nex_friends_wiiu.UpdatePreference)
friendsWiiUProtocol.GetBasicInfo(nex_friends_wiiu.GetBasicInfo)
friendsWiiUProtocol.DeletePersistentNotification(nex_friends_wiiu.DeletePersistentNotification)
friendsWiiUProtocol.CheckSettingStatus(nex_friends_wiiu.CheckSettingStatus)
friendsWiiUProtocol.GetRequestBlockSettings(nex_friends_wiiu.GetRequestBlockSettings)
// * Friends (WiiU) protocol handles
friendsWiiUProtocol.UpdateAndGetAllInformation = nex_friends_wiiu.UpdateAndGetAllInformation
friendsWiiUProtocol.AddFriendRequest = nex_friends_wiiu.AddFriendRequest
friendsWiiUProtocol.RemoveFriend = nex_friends_wiiu.RemoveFriend
friendsWiiUProtocol.CancelFriendRequest = nex_friends_wiiu.CancelFriendRequest
friendsWiiUProtocol.AcceptFriendRequest = nex_friends_wiiu.AcceptFriendRequest
friendsWiiUProtocol.DeleteFriendRequest = nex_friends_wiiu.DeleteFriendRequest
friendsWiiUProtocol.DenyFriendRequest = nex_friends_wiiu.DenyFriendRequest
friendsWiiUProtocol.MarkFriendRequestsAsReceived = nex_friends_wiiu.MarkFriendRequestsAsReceived
friendsWiiUProtocol.AddBlackList = nex_friends_wiiu.AddBlackList
friendsWiiUProtocol.RemoveBlackList = nex_friends_wiiu.RemoveBlackList
friendsWiiUProtocol.UpdatePresence = nex_friends_wiiu.UpdatePresence
friendsWiiUProtocol.UpdateComment = nex_friends_wiiu.UpdateComment
friendsWiiUProtocol.UpdatePreference = nex_friends_wiiu.UpdatePreference
friendsWiiUProtocol.GetBasicInfo = nex_friends_wiiu.GetBasicInfo
friendsWiiUProtocol.DeletePersistentNotification = nex_friends_wiiu.DeletePersistentNotification
friendsWiiUProtocol.CheckSettingStatus = nex_friends_wiiu.CheckSettingStatus
friendsWiiUProtocol.GetRequestBlockSettings = nex_friends_wiiu.GetRequestBlockSettings
// Friends (3DS) protocol handles
friends3DSProtocol.UpdateProfile(nex_friends_3ds.UpdateProfile)
friends3DSProtocol.UpdateMii(nex_friends_3ds.UpdateMii)
friends3DSProtocol.UpdatePreference(nex_friends_3ds.UpdatePreference)
friends3DSProtocol.SyncFriend(nex_friends_3ds.SyncFriend)
friends3DSProtocol.UpdatePresence(nex_friends_3ds.UpdatePresence)
friends3DSProtocol.UpdateFavoriteGameKey(nex_friends_3ds.UpdateFavoriteGameKey)
friends3DSProtocol.UpdateComment(nex_friends_3ds.UpdateComment)
friends3DSProtocol.AddFriendByPrincipalID(nex_friends_3ds.AddFriendshipByPrincipalID)
friends3DSProtocol.GetFriendPersistentInfo(nex_friends_3ds.GetFriendPersistentInfo)
friends3DSProtocol.GetFriendMii(nex_friends_3ds.GetFriendMii)
friends3DSProtocol.GetFriendPresence(nex_friends_3ds.GetFriendPresence)
friends3DSProtocol.RemoveFriendByPrincipalID(nex_friends_3ds.RemoveFriendByPrincipalID)
friends3DSProtocol.RemoveFriendByLocalFriendCode(nex_friends_3ds.RemoveFriendByLocalFriendCode)
friends3DSProtocol.GetPrincipalIDByLocalFriendCode(nex_friends_3ds.GetPrincipalIDByLocalFriendCode)
friends3DSProtocol.GetAllFriends(nex_friends_3ds.GetAllFriends)
// * Friends (3DS) protocol handles
friends3DSProtocol.UpdateProfile = nex_friends_3ds.UpdateProfile
friends3DSProtocol.UpdateMii = nex_friends_3ds.UpdateMii
friends3DSProtocol.UpdatePreference = nex_friends_3ds.UpdatePreference
friends3DSProtocol.SyncFriend = nex_friends_3ds.SyncFriend
friends3DSProtocol.UpdatePresence = nex_friends_3ds.UpdatePresence
friends3DSProtocol.UpdateFavoriteGameKey = nex_friends_3ds.UpdateFavoriteGameKey
friends3DSProtocol.UpdateComment = nex_friends_3ds.UpdateComment
friends3DSProtocol.AddFriendByPrincipalID = nex_friends_3ds.AddFriendByPrincipalID
friends3DSProtocol.GetFriendPersistentInfo = nex_friends_3ds.GetFriendPersistentInfo
friends3DSProtocol.GetFriendMii = nex_friends_3ds.GetFriendMii
friends3DSProtocol.GetFriendPresence = nex_friends_3ds.GetFriendPresence
friends3DSProtocol.RemoveFriendByPrincipalID = nex_friends_3ds.RemoveFriendByPrincipalID
friends3DSProtocol.RemoveFriendByLocalFriendCode = nex_friends_3ds.RemoveFriendByLocalFriendCode
friends3DSProtocol.GetPrincipalIDByLocalFriendCode = nex_friends_3ds.GetPrincipalIDByLocalFriendCode
friends3DSProtocol.GetAllFriends = nex_friends_3ds.GetAllFriends
globals.SecureEndpoint.RegisterServiceProtocol(accountManagementProtocol)
globals.SecureEndpoint.RegisterServiceProtocol(friendsWiiUProtocol)
globals.SecureEndpoint.RegisterServiceProtocol(friends3DSProtocol)
}

View File

@ -1,93 +1,90 @@
package nex_secure_connection
import (
"time"
"net"
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
"github.com/PretendoNetwork/friends/globals"
"github.com/PretendoNetwork/friends/types"
nex "github.com/PretendoNetwork/nex-go"
secure_connection "github.com/PretendoNetwork/nex-protocols-go/secure-connection"
friends_types "github.com/PretendoNetwork/friends/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
secure_connection "github.com/PretendoNetwork/nex-protocols-go/v2/secure-connection"
)
func RegisterEx(err error, client *nex.Client, callID uint32, stationUrls []*nex.StationURL, loginData *nex.DataHolder) uint32 {
func RegisterEx(err error, packet nex.PacketInterface, callID uint32, vecMyURLs types.List[types.StationURL], hCustomData types.DataHolder) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nex.Errors.Core.InvalidArgument
return nil, nex.NewError(nex.ResultCodes.Core.InvalidArgument, "")
}
retval := nex.NewResultSuccess(nex.Errors.Core.Unknown)
rmcResponseStream := nex.NewStreamOut(globals.SecureServer)
connection := packet.Sender().(*nex.PRUDPConnection)
// TODO: Validate loginData
pid := client.PID()
user := globals.ConnectedUsers[pid]
lastOnline := nex.NewDateTime(0)
lastOnline.FromTimestamp(time.Now())
retval := types.NewQResultSuccess(nex.ResultCodes.Core.Unknown)
// TODO - Validate loginData
pid := uint32(connection.PID())
user := friends_types.NewConnectedUser()
user.PID = pid
user.Connection = connection
lastOnline := types.NewDateTime(0).Now()
loginDataType := hCustomData.Object.DataObjectID().(types.String)
loginDataType := loginData.TypeName()
switch loginDataType {
case "NintendoLoginData":
user.Platform = types.WUP // Platform is Wii U
user.Platform = friends_types.WUP // * Platform is Wii U
err = database_wiiu.UpdateUserLastOnlineTime(pid, lastOnline)
if err != nil {
globals.Logger.Critical(err.Error())
retval = nex.NewResultError(nex.Errors.Authentication.Unknown)
retval = types.NewQResultError(nex.ResultCodes.Authentication.Unknown)
}
case "AccountExtraInfo":
user.Platform = types.CTR // Platform is 3DS
user.Platform = friends_types.CTR // * Platform is 3DS
err = database_3ds.UpdateUserLastOnlineTime(pid, lastOnline)
if err != nil {
globals.Logger.Critical(err.Error())
retval = nex.NewResultError(nex.Errors.Authentication.Unknown)
retval = types.NewQResultError(nex.ResultCodes.Authentication.Unknown)
}
default:
globals.Logger.Errorf("Unknown loginData data type %s!", loginDataType)
retval = nex.NewResultError(nex.Errors.Authentication.ValidationFailed)
retval = types.NewQResultError(nex.ResultCodes.Authentication.ValidationFailed)
}
pidConnectionID := types.NewUInt32(0)
urlPublic := types.NewString("")
if retval.IsSuccess() {
localStation := stationUrls[0]
globals.ConnectedUsers.Set(pid, user)
address := client.Address().IP.String()
localStation := vecMyURLs[0]
localStation.SetAddress(address)
localStation.SetPort(uint32(client.Address().Port))
address := connection.Address().(*net.UDPAddr)
localStationURL := localStation.EncodeToString()
localStation.SetAddress(address.IP.String())
localStation.SetPortNumber(uint16(address.Port))
rmcResponseStream.WriteResult(retval)
rmcResponseStream.WriteUInt32LE(globals.SecureServer.ConnectionIDCounter().Increment())
rmcResponseStream.WriteString(localStationURL)
} else {
rmcResponseStream.WriteResult(retval)
rmcResponseStream.WriteUInt32LE(0)
rmcResponseStream.WriteString("prudp:/")
localStationURL := localStation.URL()
pidConnectionID = types.NewUInt32(connection.ID)
urlPublic = types.NewString(localStationURL)
}
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
retval.WriteTo(rmcResponseStream)
pidConnectionID.WriteTo(rmcResponseStream)
urlPublic.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
// Build response packet
rmcResponse := nex.NewRMCResponse(secure_connection.ProtocolID, callID)
rmcResponse.SetSuccess(secure_connection.MethodRegisterEx, rmcResponseBody)
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = secure_connection.ProtocolID
rmcResponse.MethodID = secure_connection.MethodRegisterEx
rmcResponse.CallID = callID
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV0(client, nil)
responsePacket.SetVersion(0)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.SecureServer.Send(responsePacket)
return 0
return rmcResponse, nil
}

View File

@ -1,8 +1,8 @@
package nex
import (
"fmt"
"os"
"strconv"
"time"
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
@ -10,73 +10,61 @@ import (
"github.com/PretendoNetwork/friends/globals"
notifications_3ds "github.com/PretendoNetwork/friends/notifications/3ds"
notifications_wiiu "github.com/PretendoNetwork/friends/notifications/wiiu"
"github.com/PretendoNetwork/friends/types"
nex "github.com/PretendoNetwork/nex-go"
_ "github.com/PretendoNetwork/nex-protocols-go"
friends_types "github.com/PretendoNetwork/friends/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
_ "github.com/PretendoNetwork/nex-protocols-go/v2"
)
func StartSecureServer() {
globals.SecureServer = nex.NewServer()
globals.SecureServer.SetFragmentSize(900)
globals.SecureServer.SetPRUDPVersion(0)
globals.SecureServer.SetKerberosKeySize(16)
globals.SecureServer.SetKerberosPassword(globals.KerberosPassword)
globals.SecureServer.SetPingTimeout(20) // Maybe too long?
globals.SecureServer.SetAccessKey("ridfebb9")
globals.SecureServer.SetDefaultNEXVersion(&nex.NEXVersion{
Major: 1,
Minor: 1,
Patch: 0,
})
port, _ := strconv.Atoi(os.Getenv("PN_FRIENDS_SECURE_SERVER_PORT"))
globals.SecureServer.On("Data", func(packet *nex.PacketV0) {
request := packet.RMCRequest()
globals.SecureServer = nex.NewPRUDPServer()
globals.SecureEndpoint = nex.NewPRUDPEndPoint(1)
fmt.Println("==Friends - Secure==")
fmt.Printf("Protocol ID: %#v\n", request.ProtocolID())
fmt.Printf("Method ID: %#v\n", request.MethodID())
fmt.Println("====================")
})
globals.SecureEndpoint.ServerAccount = globals.SecureServerAccount
globals.SecureEndpoint.AccountDetailsByPID = globals.AccountDetailsByPID
globals.SecureEndpoint.AccountDetailsByUsername = globals.AccountDetailsByUsername
globals.SecureServer.On("Kick", func(packet *nex.PacketV0) {
pid := packet.Sender().PID()
globals.SecureEndpoint.OnConnectionEnded(func(connection *nex.PRUDPConnection) {
pid := uint32(connection.PID())
user, ok := globals.ConnectedUsers.Get(pid)
if globals.ConnectedUsers[pid] == nil {
if !ok || user == nil {
return
}
platform := globals.ConnectedUsers[pid].Platform
lastOnline := nex.NewDateTime(0)
platform := user.Platform
lastOnline := types.NewDateTime(0)
lastOnline.FromTimestamp(time.Now())
if platform == types.WUP {
if platform == friends_types.WUP {
err := database_wiiu.UpdateUserLastOnlineTime(pid, lastOnline)
if err != nil {
globals.Logger.Critical(err.Error())
}
notifications_wiiu.SendUserWentOfflineGlobally(packet.Sender())
} else if platform == types.CTR {
notifications_wiiu.SendUserWentOfflineGlobally(connection)
} else if platform == friends_types.CTR {
err := database_3ds.UpdateUserLastOnlineTime(pid, lastOnline)
if err != nil {
globals.Logger.Critical(err.Error())
}
notifications_3ds.SendUserWentOfflineGlobally(packet.Sender())
notifications_3ds.SendUserWentOfflineGlobally(connection)
}
delete(globals.ConnectedUsers, pid)
fmt.Println("Leaving (Kick)")
globals.ConnectedUsers.Delete(pid)
})
globals.SecureServer.On("Disconnect", func(packet *nex.PacketV0) {
fmt.Println("Leaving (Disconnect)")
})
globals.SecureServer.On("Connect", connect)
registerCommonSecureServerProtocols()
registerSecureServerProtocols()
globals.SecureServer.Listen(fmt.Sprintf(":%s", os.Getenv("PN_FRIENDS_SECURE_SERVER_PORT")))
globals.SecureEndpoint.IsSecureEndPoint = true
globals.SecureServer.SetFragmentSize(962)
globals.SecureServer.LibraryVersions.SetDefault(nex.NewLibraryVersion(1, 1, 0))
globals.SecureServer.SessionKeyLength = 16
globals.SecureServer.AccessKey = "ridfebb9"
globals.SecureServer.BindPRUDPEndPoint(globals.SecureEndpoint)
globals.SecureServer.Listen(port)
}

View File

@ -5,53 +5,58 @@ import (
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
"github.com/PretendoNetwork/friends/globals"
nex "github.com/PretendoNetwork/nex-go"
nintendo_notifications "github.com/PretendoNetwork/nex-protocols-go/nintendo-notifications"
nintendo_notifications_types "github.com/PretendoNetwork/nex-protocols-go/nintendo-notifications/types"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/constants"
"github.com/PretendoNetwork/nex-go/v2/types"
nintendo_notifications "github.com/PretendoNetwork/nex-protocols-go/v2/nintendo-notifications"
nintendo_notifications_types "github.com/PretendoNetwork/nex-protocols-go/v2/nintendo-notifications/types"
)
func SendCommentUpdate(client *nex.Client, comment string) {
func SendCommentUpdate(connection *nex.PRUDPConnection, comment string) {
notificationEvent := nintendo_notifications_types.NewNintendoNotificationEventGeneral()
notificationEvent.StrParam = comment
notificationEvent.StrParam = types.NewString(comment)
eventObject := nintendo_notifications_types.NewNintendoNotificationEvent()
eventObject.Type = 3
eventObject.SenderPID = client.PID()
eventObject.DataHolder = nex.NewDataHolder()
eventObject.DataHolder.SetTypeName("NintendoNotificationEventGeneral")
eventObject.DataHolder.SetObjectData(notificationEvent)
eventObject.Type = types.NewUInt32(3)
eventObject.SenderPID = connection.PID()
eventObject.DataHolder = types.NewDataHolder()
eventObject.DataHolder.Object = notificationEvent.Copy().(nintendo_notifications_types.NintendoNotificationEventGeneral)
stream := nex.NewStreamOut(globals.SecureServer)
eventObjectBytes := eventObject.Bytes(stream)
stream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
rmcRequest := nex.NewRMCRequest()
rmcRequest.SetProtocolID(nintendo_notifications.ProtocolID)
rmcRequest.SetCallID(3810693103)
rmcRequest.SetMethodID(nintendo_notifications.MethodProcessNintendoNotificationEvent1)
rmcRequest.SetParameters(eventObjectBytes)
eventObject.WriteTo(stream)
rmcRequestBytes := rmcRequest.Bytes()
notificationRequest := nex.NewRMCRequest(globals.SecureEndpoint)
notificationRequest.ProtocolID = nintendo_notifications.ProtocolID
notificationRequest.CallID = 3810693103
notificationRequest.MethodID = nintendo_notifications.MethodProcessNintendoNotificationEvent1
notificationRequest.Parameters = stream.Bytes()
friendsList, err := database_3ds.GetUserFriends(client.PID())
notificationRequestBytes := notificationRequest.Bytes()
friendsList, err := database_3ds.GetUserFriends(uint32(connection.PID()))
if err != nil && err != sql.ErrNoRows {
globals.Logger.Critical(err.Error())
}
for i := 0; i < len(friendsList); i++ {
if friendsList == nil {
return
}
connectedUser := globals.ConnectedUsers[friendsList[i].PID]
for _, friend := range friendsList {
connectedUser, ok := globals.ConnectedUsers.Get(uint32(friend.PID))
if connectedUser != nil {
requestPacket, _ := nex.NewPacketV0(connectedUser.Client, nil)
if ok && connectedUser != nil {
requestPacket, _ := nex.NewPRUDPPacketV0(globals.SecureEndpoint.Server, connectedUser.Connection, nil)
requestPacket.SetVersion(0)
requestPacket.SetSource(0xA1)
requestPacket.SetDestination(0xAF)
requestPacket.SetType(nex.DataPacket)
requestPacket.SetPayload(rmcRequestBytes)
requestPacket.AddFlag(nex.FlagNeedsAck)
requestPacket.AddFlag(nex.FlagReliable)
requestPacket.SetType(constants.DataPacket)
requestPacket.AddFlag(constants.PacketFlagNeedsAck)
requestPacket.AddFlag(constants.PacketFlagReliable)
requestPacket.SetSourceVirtualPortStreamType(connectedUser.Connection.StreamType)
requestPacket.SetSourceVirtualPortStreamID(globals.SecureEndpoint.StreamID)
requestPacket.SetDestinationVirtualPortStreamType(connectedUser.Connection.StreamType)
requestPacket.SetDestinationVirtualPortStreamID(connectedUser.Connection.StreamID)
requestPacket.SetPayload(notificationRequestBytes)
globals.SecureServer.Send(requestPacket)
}

Some files were not shown because too many files have changed in this diff Show More