feat!: Finalize code
This commit is contained in:
parent
006f301484
commit
80f5b39961
1 changed files with 116 additions and 5 deletions
121
src/main.go
121
src/main.go
|
|
@ -1,10 +1,17 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/joho/godotenv"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/smtp"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type BudgetClient struct {
|
||||
|
|
@ -14,6 +21,41 @@ type BudgetClient struct {
|
|||
fullUrl string
|
||||
}
|
||||
|
||||
type BudgetMonthsResponse struct {
|
||||
Data struct {
|
||||
Month string `json:"month"`
|
||||
IncomeAvailable int `json:"incomeAvailable"`
|
||||
LastMonthOverspent int `json:"lastMonthOverspent"`
|
||||
ForNextMonth int `json:"forNextMonth"`
|
||||
TotalBudgeted int `json:"totalBudgeted"`
|
||||
ToBudget int `json:"toBudget"`
|
||||
FromLastMonth int `json:"fromLastMonth"`
|
||||
TotalIncome int `json:"totalIncome"`
|
||||
TotalSpent int `json:"totalSpent"`
|
||||
TotalBalance int `json:"totalBalance"`
|
||||
CategoryGroups []struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
IsIncome bool `json:"is_income"`
|
||||
Hidden bool `json:"hidden"`
|
||||
Budgeted int `json:"budgeted"`
|
||||
Spent int `json:"spent"`
|
||||
Balance int `json:"balance"`
|
||||
Categories []struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
IsIncome bool `json:"is_income"`
|
||||
Hidden bool `json:"hidden"`
|
||||
GroupID string `json:"group_id"`
|
||||
Budgeted int `json:"budgeted"`
|
||||
Spent int `json:"spent"`
|
||||
Balance int `json:"balance"`
|
||||
Carryover bool `json:"carryover"`
|
||||
} `json:"categories"`
|
||||
} `json:"categoryGroups"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func CreateBudgetClient(baseUrl string, apiKey string, syncId string) *BudgetClient {
|
||||
fullUrl := baseUrl + "/v1/budgets/" + syncId
|
||||
client := BudgetClient{baseUrl, apiKey, syncId, fullUrl}
|
||||
|
|
@ -25,7 +67,7 @@ func CreateBudgetClient(baseUrl string, apiKey string, syncId string) *BudgetCli
|
|||
// method is POST, GET, ect
|
||||
// route is the route to call with a leading / ex. /accounts/banksync
|
||||
// headers is a map of strings expecting "header" "value"
|
||||
func (b BudgetClient) callApi(method string, route string, headers map[string]string) bool {
|
||||
func (b BudgetClient) callApi(method string, route string, headers map[string]string) *http.Response {
|
||||
var httpClient http.Client
|
||||
req, err := http.NewRequest(method, b.fullUrl+route, http.NoBody)
|
||||
if err != nil {
|
||||
|
|
@ -39,12 +81,35 @@ func (b BudgetClient) callApi(method string, route string, headers map[string]st
|
|||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Println(resp)
|
||||
return resp
|
||||
}
|
||||
|
||||
// Triggers a bank sync, returns true if successful
|
||||
func (b BudgetClient) BankSync() bool {
|
||||
resp := b.callApi("POST", "/accounts/banksync", nil)
|
||||
return resp.StatusCode == http.StatusOK
|
||||
}
|
||||
|
||||
func (b BudgetClient) BankSync() bool {
|
||||
return b.callApi("POST", "/accounts/banksync", nil)
|
||||
func (b BudgetClient) GetBudgetMonths() *BudgetMonthsResponse {
|
||||
currentTime := time.Now()
|
||||
year, month := currentTime.Year(), int(currentTime.Month())
|
||||
budgetMonth := fmt.Sprintf("%v-%v", year, month)
|
||||
resp := b.callApi("GET", "/months/"+budgetMonth, nil)
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
log.Fatal("GetBudgetAmounts failed with: " + string(resp.Status))
|
||||
}
|
||||
var data bytes.Buffer
|
||||
|
||||
_, err := io.Copy(&data, resp.Body)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
var budgetMonths BudgetMonthsResponse
|
||||
err = json.Unmarshal(data.Bytes(), &budgetMonths)
|
||||
return &budgetMonths
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
|
@ -57,6 +122,52 @@ func main() {
|
|||
var baseUrl = os.Getenv("BASE_URL")
|
||||
var apiKey = os.Getenv("API_KEY")
|
||||
var syncId = os.Getenv("SYNC_ID")
|
||||
var smtpUsername = os.Getenv("SMTP_USERNAME")
|
||||
var smtpPassword = os.Getenv("SMTP_PASSWORD")
|
||||
var smtpHost = os.Getenv("SMTP_HOST")
|
||||
var smtpRecipients = os.Getenv("SMTP_RECIPIENTS")
|
||||
client := CreateBudgetClient(baseUrl, apiKey, syncId)
|
||||
client.BankSync()
|
||||
//if !client.BankSync() {
|
||||
// log.Println("Bank Sync failed, information may not be up to date")
|
||||
//}
|
||||
budgetMonths := client.GetBudgetMonths()
|
||||
|
||||
subject := "Subject: Budget Report\n"
|
||||
mime := "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n"
|
||||
const bodyTemplate = `
|
||||
<p>Good day,</p>
|
||||
<p>Your unallocated budget total as of %s: <b>$%v</b></p>
|
||||
|
||||
<p>Category breakdown:</p>
|
||||
`
|
||||
var categories strings.Builder
|
||||
|
||||
for _, v := range budgetMonths.Data.CategoryGroups {
|
||||
for _, v2 := range v.Categories {
|
||||
if !v2.IsIncome {
|
||||
bal := float32(v2.Balance)
|
||||
bal /= 100
|
||||
fmt.Fprintf(&categories, "<p>%v: <b>$%v</b></p>", v2.Name, bal)
|
||||
}
|
||||
}
|
||||
}
|
||||
categories.Write([]byte("<p>This is an automated report generated by <a href=\"https://git.wanderingcrow.net/TheWanderingCrow/actualbudget-report\">actualbudget-report</a>"))
|
||||
|
||||
currentTime := time.Now()
|
||||
toBudget := float32(budgetMonths.Data.ToBudget)
|
||||
toBudget /= 100
|
||||
body := fmt.Sprintf(bodyTemplate, currentTime.Format(time.RFC850), toBudget)
|
||||
message := []byte(subject + mime + body + categories.String())
|
||||
|
||||
var auth smtp.Auth
|
||||
if os.Getenv("ENVIRONMENT") == "dev" {
|
||||
auth = nil
|
||||
} else {
|
||||
auth = smtp.PlainAuth("", smtpUsername, smtpPassword, smtpHost)
|
||||
}
|
||||
err := smtp.SendMail(smtpHost, auth, smtpUsername, []string{smtpRecipients}, []byte(message))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue