diff --git a/database.sql b/database.sql index f5b3a04..4b0d127 100644 --- a/database.sql +++ b/database.sql @@ -38,7 +38,7 @@ ALTER TABLE public.owned_titles OWNER TO wiisoap; -- CREATE TABLE public.tickets ( - title_id character varying NOT NULL, + title_id character varying(16) NOT NULL, ticket bytea, version integer ); diff --git a/ecs.go b/ecs.go index 4cffcf0..57efe14 100644 --- a/ecs.go +++ b/ecs.go @@ -20,6 +20,7 @@ package main import ( "errors" "fmt" + "github.com/wii-tools/wadlib" "log" ) @@ -28,13 +29,26 @@ const ( FROM owned_titles, tickets WHERE owned_titles.title_id = tickets.title_id AND owned_titles.account_id = $1` + + QueryTicketStatement = `SELECT ticket, version FROM tickets WHERE title_id = $1` + + AssociateTicketStatement = `INSERT INTO owned_titles (account_id, title_id, version) + VALUES ($1, $2, $3)` + + // SharedBalanceAmount describes the maximum signed 32-bit integer value. + // It is not an actual tracked points value, but exists to permit reuse. + SharedBalanceAmount = 2147483647 ) -func checkDeviceStatus(e *Envelope) { - e.AddCustomType(Balance{ - Amount: 2147483647, +func getBalance() Balance { + return Balance{ + Amount: SharedBalanceAmount, Currency: "POINTS", - }) + } +} + +func checkDeviceStatus(e *Envelope) { + e.AddCustomType(getBalance()) e.AddKVNode("ForceSyncTime", "0") e.AddKVNode("ExtTicketTime", e.Timestamp()) e.AddKVNode("SyncTime", e.Timestamp()) @@ -94,19 +108,62 @@ func getETickets(e *Envelope) { } func purchaseTitle(e *Envelope) { - e.AddCustomType(Balance{ - Amount: 2018, - Currency: "POINTS", - }) + //accountId, err := e.AccountId() + //if err != nil { + // e.Error(2, "missing account ID", err) + // return + //} + + // Determine the title ID we're going to purchase. + titleId, err := e.getKey("TitleId") + if err != nil { + e.Error(2, "missing account ID", err) + return + } + + // Query the ticket and current version for this title. + var ticket []byte + var version int + row := pool.QueryRow(ctx, QueryTicketStatement, titleId) + + err = row.Scan(&ticket, &version) + if err != nil { + log.Printf("unexpected error purchasing: %v", err) + // TODO(spotlightishere): Can we more elegantly return an error when a title may not exist here? + e.Error(2, "error purchasing", nil) + } + + // Associate the given title ID with the user. + //_, err = pool.Exec(ctx, AssociateTicketStatement, accountId, titleId, version) + //if err != nil { + // log.Printf("unexpected error purchasing: %v", err) + // e.Error(2, "error purchasing", nil) + //} + + // The returned ticket is expected to have two other certificates associated. + ticketString := b64(append(ticket, wadlib.CertChainTemplate...)) + + e.AddCustomType(getBalance()) e.AddCustomType(Transactions{ TransactionId: "00000000", Date: e.Timestamp(), Type: "PURCHGAME", + TotalPaid: 0, + Currency: "POINTS", + ItemId: 0, }) e.AddKVNode("SyncTime", e.Timestamp()) - e.AddKVNode("Certs", "00000000") - e.AddKVNode("TitleId", "00000000") - e.AddKVNode("ETickets", "00000000") + + //// Two cert types must be present. + //type Certs struct { + // XMLName xml.Name `xml:"Certs"` + // Value string `xml:",chardata"` + //} + + e.AddKVNode("ETickets", ticketString) + e.AddKVNode("Certs", b64(wadlib.CertChainTemplate)) + e.AddKVNode("Certs", b64(wadlib.CertChainTemplate)) + e.AddKVNode("TitleId", titleId) } func listPurchaseHistory(e *Envelope) { @@ -115,9 +172,9 @@ func listPurchaseHistory(e *Envelope) { TransactionId: "12345678", Date: e.Timestamp(), Type: "SERVICE", - TotalPaid: "7", + TotalPaid: 7, Currency: "POINTS", - ItemId: "000100014843494A", + ItemId: 0, TitleId: "000100014843494A", ItemPricing: []Limits{ LimitStruct(DR), diff --git a/go.mod b/go.mod index 38a4ba2..a5c232a 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/jackc/pgconn v1.10.1 github.com/jackc/pgx/v4 v4.14.1 github.com/logrusorgru/aurora/v3 v3.0.0 + github.com/wii-tools/wadlib v0.3.1 ) require ( diff --git a/go.sum b/go.sum index d685081..2d47618 100644 --- a/go.sum +++ b/go.sum @@ -103,6 +103,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/wii-tools/wadlib v0.3.1 h1:g0Szzof/YsBLghP+JpoVzT/6M6jpl+AH9PHiUuG3cd8= +github.com/wii-tools/wadlib v0.3.1/go.mod h1:GK+f2POk+rVu1p4xqLSb4ll1SKKbfOO6ZAB+oPLV3uQ= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= diff --git a/structure.go b/structure.go index 1b7c270..bd7a023 100644 --- a/structure.go +++ b/structure.go @@ -114,9 +114,9 @@ type Transactions struct { TransactionId string `xml:"TransactionId"` Date string `xml:"Date"` Type string `xml:"Type"` - TotalPaid string `xml:"TotalPaid"` + TotalPaid int `xml:"TotalPaid"` Currency string `xml:"Currency"` - ItemId string `xml:"ItemId"` + ItemId int `xml:"ItemId"` // TODO: Is this correct? getComplex is called and then limits are queried ItemPricing []Limits `xml:"ItemPricing"` TitleId string `xml:"TitleId,omitempty"` diff --git a/utils.go b/utils.go index 951b098..96f2e42 100644 --- a/utils.go +++ b/utils.go @@ -18,6 +18,7 @@ package main import ( + "encoding/base64" "encoding/xml" "errors" "fmt"