fix(wpcarro/ynab): Remove .skip-subtree

**TL;DR:**
- Delete half-baked packaging attempts (`job.nix`, `token.nix`).
- Ensure golang code compiles.
  - Some "packages" were being treated like "programs" presumably for
    debugging/testing purposes back when I was working on this. Make those
    behave like libraries.
  - Remove stale imports.
  - Fix syntax errors.
  - Miscellaneous other chores.
- Drop `shell.nix` and `use_nix` directive.

Change-Id: I63c275680bac55a3cad3b9cb48d51cdc431fbe48
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7318
Autosubmit: wpcarro <wpcarro@gmail.com>
Tested-by: BuildkiteCI
Reviewed-by: wpcarro <wpcarro@gmail.com>
This commit is contained in:
William Carroll 2022-11-20 21:24:47 -08:00 committed by clbot
parent 982022826d
commit d36aaeb967
11 changed files with 33 additions and 118 deletions

View file

@ -1,5 +1,5 @@
source_up source_up
use_nix
# TODO(wpcarro): Prefer age-nix solution if possible. # TODO(wpcarro): Prefer age-nix solution if possible.
export monzo_client_id="$(jq -j '.monzo | .clientId' < $WPCARRO/secrets.json)" export monzo_client_id="$(jq -j '.monzo | .clientId' < $WPCARRO/secrets.json)"
export monzo_client_secret="$(jq -j '.monzo | .clientSecret' < $WPCARRO/secrets.json)" export monzo_client_secret="$(jq -j '.monzo | .clientSecret' < $WPCARRO/secrets.json)"

View file

@ -1,2 +0,0 @@
Subdirectories of this folder should not be imported since they are
internal to buildGo.nix and incompatible with readTree.

View file

@ -1,15 +0,0 @@
{ depot, ... }:
let
inherit (depot.users.wpcarro) gopkgs;
in
depot.nix.buildGo.program {
name = "job";
srcs = [
./main.go
];
deps = with gopkgs; [
kv
utils
];
}

View file

@ -10,8 +10,11 @@
package main package main
import ( import (
"monzoClient"
"monzoSerde" "monzoSerde"
"os" "os"
"ynabClient"
"ynabSerde"
) )
var ( var (
@ -34,11 +37,12 @@ func toYnab(tx monzoSerde.Transaction) ynabSerde.Transaction {
} }
func main() { func main() {
monzo := monzoClient.Create()
txs := monzo.TransactionsLast24Hours() txs := monzo.TransactionsLast24Hours()
var ynabTxs []ynabSerde.Transaction var ynabTxs []ynabSerde.Transaction
for tx := range txs { for _, tx := range txs {
append(ynabTxs, toYnab(tx)) ynabTxs = append(ynabTxs, toYnab(tx))
} }
ynab.PostTransactions(ynabTxs) ynabClient.PostTransactions(ynabTxs)
os.Exit(0) os.Exit(0)
} }

View file

@ -27,8 +27,8 @@ func Create() *Client {
} }
// Returns a slice of transactions from the last 24 hours. // Returns a slice of transactions from the last 24 hours.
func (c *Client) Transactions24Hours() []monzoSerde.Transaction { func (c *Client) TransactionsLast24Hours() []monzoSerde.Transaction {
token := tokens.AccessToken() token := tokens.GetState().AccessToken
form := url.Values{"account_id": {accountID}} form := url.Values{"account_id": {accountID}}
client := http.Client{} client := http.Client{}
req, _ := http.NewRequest("POST", "https://api.monzo.com/transactions", req, _ := http.NewRequest("POST", "https://api.monzo.com/transactions",

View file

@ -1,11 +1,9 @@
// This package hosts the serialization and deserialization logic for all of the // This package hosts the serialization and deserialization logic for all of the
// data types with which our application interacts from the Monzo API. // data types with which our application interacts from the Monzo API.
package main package monzoSerde
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io/ioutil"
"time" "time"
) )
@ -72,11 +70,3 @@ func deserializeTx(x string) (*Transaction, error) {
err := json.Unmarshal([]byte(x), target) err := json.Unmarshal([]byte(x), target)
return target, err return target, err
} }
func main() {
b, _ := ioutil.ReadFile("./fixture.json")
tx := string(b)
target, _ := deserializeTx(tx)
out, _ := serializeTx(target)
fmt.Println(out)
}

View file

@ -1,9 +0,0 @@
{ pkgs, ... }:
pkgs.mkShell {
buildInputs = with pkgs; [
go
goimports
godef
];
}

View file

@ -1,7 +1,7 @@
// Creating a Tokens server to manage my access and refresh tokens. Keeping this // Creating a Tokens server to manage my access and refresh tokens. Keeping this
// as a separate server allows me to develop and use the access tokens without // as a separate server allows me to develop and use the access tokens without
// going through client authorization. // going through client authorization.
package main package tokens
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Dependencies // Dependencies
@ -46,7 +46,7 @@ type setTokensRequest struct {
// This is our application state. // This is our application state.
type state struct { type state struct {
accessToken string `json:"access_token"` AccessToken string `json:"access_token"`
refreshToken string `json:"refresh_token"` refreshToken string `json:"refresh_token"`
} }
@ -90,7 +90,7 @@ func logTokens(access string, refresh string) {
} }
func (state *state) String() string { func (state *state) String() string {
return fmt.Sprintf("state{\n\taccessToken: \"%s\",\n\trefreshToken: \"%s\"\n}\n", state.accessToken, state.refreshToken) return fmt.Sprintf("state{\n\tAccessToken: \"%s\",\n\trefreshToken: \"%s\"\n}\n", state.AccessToken, state.refreshToken)
} }
// Schedule a token refresh for `expiresIn` seconds using the provided // Schedule a token refresh for `expiresIn` seconds using the provided
@ -104,10 +104,10 @@ func scheduleTokenRefresh(expiresIn int, refreshToken string) {
log.Printf("Scheduling token refresh for %v\n", timestamp) log.Printf("Scheduling token refresh for %v\n", timestamp)
time.Sleep(duration) time.Sleep(duration)
log.Println("Refreshing tokens now...") log.Println("Refreshing tokens now...")
accessToken, refreshToken := refreshTokens(refreshToken) AccessToken, refreshToken := refreshTokens(refreshToken)
log.Println("Successfully refreshed tokens.") log.Println("Successfully refreshed tokens.")
logTokens(accessToken, refreshToken) logTokens(AccessToken, refreshToken)
setState(accessToken, refreshToken) setState(AccessToken, refreshToken)
} }
// Exchange existing credentials for a new access token and `refreshToken`. Also // Exchange existing credentials for a new access token and `refreshToken`. Also
@ -169,8 +169,8 @@ func handleInterrupts() {
go func() { go func() {
sig := <-sigs sig := <-sigs
log.Printf("Received signal to shutdown. %v\n", sig) log.Printf("Received signal to shutdown. %v\n", sig)
state := getState() state := GetState()
persistTokens(state.accessToken, state.refreshToken) persistTokens(state.AccessToken, state.refreshToken)
done <- true done <- true
}() }()
@ -179,25 +179,21 @@ func handleInterrupts() {
os.Exit(0) os.Exit(0)
} }
// Set `accessToken` and `refreshToken` on application state. // Set `AccessToken` and `refreshToken` on application state.
func setState(accessToken string, refreshToken string) { func setState(AccessToken string, refreshToken string) {
msg := writeMsg{state{accessToken, refreshToken}, make(chan bool)} msg := writeMsg{state{AccessToken, refreshToken}, make(chan bool)}
chans.writes <- msg chans.writes <- msg
<-msg.sender <-msg.sender
} }
// Return our application state. // Return our application state.
func getState() state { func GetState() state {
msg := readMsg{make(chan state)} msg := readMsg{make(chan state)}
chans.reads <- msg chans.reads <- msg
return <-msg.sender return <-msg.sender
} }
//////////////////////////////////////////////////////////////////////////////// func StartServer() {
// Main
////////////////////////////////////////////////////////////////////////////////
func main() {
// Manage application state. // Manage application state.
go func() { go func() {
state := &state{} state := &state{}
@ -215,7 +211,7 @@ func main() {
// As an attempt to maintain consistency between application // As an attempt to maintain consistency between application
// state and persisted state, everytime we write to the // state and persisted state, everytime we write to the
// application state, we will write to the store. // application state, we will write to the store.
persistTokens(state.accessToken, state.refreshToken) persistTokens(state.AccessToken, state.refreshToken)
msg.sender <- true msg.sender <- true
} }
} }
@ -251,7 +247,7 @@ func main() {
log.Fatal(http.ListenAndServe(":4242", log.Fatal(http.ListenAndServe(":4242",
http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if req.URL.Path == "/refresh-tokens" && req.Method == "POST" { if req.URL.Path == "/refresh-tokens" && req.Method == "POST" {
state := getState() state := GetState()
go scheduleTokenRefresh(0, state.refreshToken) go scheduleTokenRefresh(0, state.refreshToken)
fmt.Fprintf(w, "Done.") fmt.Fprintf(w, "Done.")
} else if req.URL.Path == "/set-tokens" && req.Method == "POST" { } else if req.URL.Path == "/set-tokens" && req.Method == "POST" {
@ -273,7 +269,7 @@ func main() {
} else if req.URL.Path == "/state" && req.Method == "GET" { } else if req.URL.Path == "/state" && req.Method == "GET" {
// TODO(wpcarro): Ensure that this returns serialized state. // TODO(wpcarro): Ensure that this returns serialized state.
w.Header().Set("Content-type", "application/json") w.Header().Set("Content-type", "application/json")
state := getState() state := GetState()
payload, _ := json.Marshal(state) payload, _ := json.Marshal(state)
io.WriteString(w, string(payload)) io.WriteString(w, string(payload))
} else { } else {

View file

@ -1,26 +0,0 @@
{ depot, ... }:
let
inherit (depot.users.wpcarro) gopkgs;
auth = depot.nix.buildGo.package {
name = "auth";
srcs = [
./auth.go
];
deps = with gopkgs; [
utils
];
};
in
depot.nix.buildGo.program {
name = "token-server";
srcs = [
./tokens.go
];
deps = with gopkgs; [
kv
utils
auth
];
}

View file

@ -1,24 +1,9 @@
package client package ynabClient
import ( import (
"serde" "ynabSerde"
) )
// // See requests.txt for more details. // See requests.txt for more details.
// func PostTransactions(accountID string, txs []serde.Transaction{}) error { func PostTransactions(txs []ynabSerde.Transaction) {
// return map[string]string{ }
// "transactions": [
// {
// "account_id": accountID,
// "date": "2019-12-30",
// "amount": 10000,
// "payee_name": "Richard Stallman",
// "memo": "Not so free software after all...",
// "cleared": "cleared",
// "approved": true,
// "flag_color": "red",
// "import_id": "xyz-123"
// }
// ]
// }
// }

View file

@ -1,10 +1,9 @@
// This package hosts the serialization and deserialization logic for all of the // This package hosts the serialization and deserialization logic for all of the
// data types with which our application interacts from the YNAB API. // data types with which our application interacts from the YNAB API.
package main package ynabSerde
import ( import (
"encoding/json" "encoding/json"
"fmt"
"time" "time"
) )
@ -43,10 +42,3 @@ func deserializeTx(x string) (*Transaction, error) {
err := json.Unmarshal([]byte(x), target) err := json.Unmarshal([]byte(x), target)
return target, err return target, err
} }
func main() {
target, _ := deserializeTx(tx)
out, _ := serializeTx(target)
fmt.Println(out)
fmt.Println(ynabOut)
}