wip-account-creation #4
850
cmd/main.go
850
cmd/main.go
@ -1,790 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"git.defalsify.org/vise.git/cache"
|
||||
"git.defalsify.org/vise.git/engine"
|
||||
"git.defalsify.org/vise.git/lang"
|
||||
"git.defalsify.org/vise.git/persist"
|
||||
"git.defalsify.org/vise.git/resource"
|
||||
"git.defalsify.org/vise.git/state"
|
||||
"git.grassecon.net/urdt/ussd/internal/server/handlers"
|
||||
"git.grassecon.net/urdt/ussd/internal/utils"
|
||||
"git.grassecon.net/urdt/ussd/internal/models"
|
||||
"git.grassecon.net/urdt/ussd/internal/handlers/ussd"
|
||||
)
|
||||
|
||||
const (
|
||||
USERFLAG_LANGUAGE_SET = iota + state.FLAG_USERSTART
|
||||
USERFLAG_ACCOUNT_CREATED
|
||||
USERFLAG_ACCOUNT_PENDING
|
||||
USERFLAG_ACCOUNT_SUCCESS
|
||||
USERFLAG_ACCOUNT_UNLOCKED
|
||||
USERFLAG_INVALID_RECIPIENT
|
||||
USERFLAG_INVALID_RECIPIENT_WITH_INVITE
|
||||
USERFLAG_INCORRECTPIN
|
||||
USERFLAG_UNLOCKFORUPDATE
|
||||
USERFLAG_INVALID_AMOUNT
|
||||
USERFLAG_QUERYPIN
|
||||
USERFLAG_VALIDPIN
|
||||
USERFLAG_INVALIDPIN
|
||||
USERFLAG_INCORRECTDATEFORMAT
|
||||
)
|
||||
|
||||
type fsData struct {
|
||||
path string
|
||||
st *state.State
|
||||
}
|
||||
|
||||
func codeFromCtx(ctx context.Context) string {
|
||||
var code string
|
||||
engine.Logg.DebugCtxf(ctx, "in msg", "ctx", ctx, "val", code)
|
||||
if ctx.Value("Language") != nil {
|
||||
lang := ctx.Value("Language").(lang.Language)
|
||||
code = lang.Code
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
func (fsd *fsData) save_firstname(cxt context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if len(input) > 0 {
|
||||
name := string(input)
|
||||
accountData["FirstName"] = name
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) save_familyname(cxt context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if len(input) > 0 {
|
||||
//Save name
|
||||
secondname := string(input)
|
||||
accountData["FamilyName"] = secondname
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
func (fsd *fsData) save_yob(cxt context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if len(input) > 0 {
|
||||
yob := string(input)
|
||||
accountData["YOB"] = yob
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) save_location(cxt context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if len(input) > 0 {
|
||||
location := string(input)
|
||||
accountData["Location"] = location
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) save_gender(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if len(input) > 0 {
|
||||
gender := string(input)
|
||||
|
||||
switch gender {
|
||||
case "1":
|
||||
gender = "Male"
|
||||
case "2":
|
||||
gender = "Female"
|
||||
case "3":
|
||||
gender = "Other"
|
||||
}
|
||||
accountData["Gender"] = gender
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) save_offerings(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if len(input) > 0 {
|
||||
offerings := string(input)
|
||||
accountData["Offerings"] = offerings
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) set_language(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
inputStr := string(input)
|
||||
res := resource.Result{}
|
||||
switch inputStr {
|
||||
case "0":
|
||||
res.FlagSet = []uint32{state.FLAG_LANG}
|
||||
res.Content = "eng"
|
||||
case "1":
|
||||
res.FlagSet = []uint32{state.FLAG_LANG}
|
||||
res.Content = "swa"
|
||||
default:
|
||||
}
|
||||
|
||||
res.FlagSet = append(res.FlagSet, USERFLAG_LANGUAGE_SET)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) create_account(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
f, err := os.OpenFile(fp, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
f.Close()
|
||||
accountResp, err := handlers.CreateAccount()
|
||||
if err != nil {
|
||||
fmt.Println("Failed to create account:", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
accountData := map[string]string{
|
||||
"TrackingId": accountResp.Result.TrackingId,
|
||||
"PublicKey": accountResp.Result.PublicKey,
|
||||
"CustodialId": accountResp.Result.CustodialId.String(),
|
||||
"Status": "PENDING",
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, jsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
res.FlagSet = append(res.FlagSet, USERFLAG_ACCOUNT_CREATED)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (fsd *fsData) reset_unlock_for_update(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
res.FlagReset = append(res.FlagReset, USERFLAG_UNLOCKFORUPDATE)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) reset_account_unlocked(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
res.FlagReset = append(res.FlagReset, USERFLAG_ACCOUNT_UNLOCKED)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) check_identifier(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
res.Content = accountData["PublicKey"]
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) unlock(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
pin := string(input)
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if len(input) > 1 {
|
||||
if pin != accountData["AccountPIN"] {
|
||||
res.FlagSet = append(res.FlagSet, USERFLAG_INCORRECTPIN)
|
||||
res.FlagReset = append(res.FlagReset, USERFLAG_ACCOUNT_UNLOCKED)
|
||||
return res, nil
|
||||
}
|
||||
if fsd.st.MatchFlag(USERFLAG_ACCOUNT_UNLOCKED, false) {
|
||||
res.FlagReset = append(res.FlagReset, USERFLAG_INCORRECTPIN)
|
||||
res.FlagSet = append(res.FlagSet, USERFLAG_UNLOCKFORUPDATE)
|
||||
res.FlagSet = append(res.FlagSet, USERFLAG_ACCOUNT_UNLOCKED)
|
||||
} else {
|
||||
res.FlagReset = append(res.FlagReset, USERFLAG_ACCOUNT_UNLOCKED)
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) reset_incorrect_pin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
res.FlagReset = append(res.FlagReset, USERFLAG_INCORRECTPIN)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) check_account_status(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
//status, err := checkAccountStatus(accountData["TrackingId"])
|
||||
status, err := handlers.CheckAccountStatus(accountData["TrackingId"])
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Error checking account status:", err)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
accountData["Status"] = status
|
||||
|
||||
if status == "SUCCESS" {
|
||||
res.FlagSet = append(res.FlagSet, USERFLAG_ACCOUNT_SUCCESS)
|
||||
res.FlagReset = append(res.FlagReset, USERFLAG_ACCOUNT_PENDING)
|
||||
} else {
|
||||
res.FlagReset = append(res.FlagSet, USERFLAG_ACCOUNT_SUCCESS)
|
||||
res.FlagSet = append(res.FlagReset, USERFLAG_ACCOUNT_PENDING)
|
||||
}
|
||||
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) quit(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
switch codeFromCtx(ctx) {
|
||||
case "swa":
|
||||
res.Content = "Asante kwa kutumia huduma ya Sarafu. Kwaheri!"
|
||||
default:
|
||||
res.Content = "Thank you for using Sarafu. Goodbye!"
|
||||
}
|
||||
res.FlagReset = append(res.FlagReset, USERFLAG_ACCOUNT_UNLOCKED)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) verify_yob(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
date := string(input)
|
||||
|
||||
dateRegex := regexp.MustCompile(`^\d{2}/\d{2}/\d{4}$`)
|
||||
isCorrectFormat := dateRegex.MatchString(date)
|
||||
if !isCorrectFormat {
|
||||
res.FlagSet = append(res.FlagSet, USERFLAG_INCORRECTDATEFORMAT)
|
||||
} else {
|
||||
res.FlagReset = append(res.FlagReset, USERFLAG_INCORRECTDATEFORMAT)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) reset_incorrect_yob(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
res.FlagReset = append(res.FlagReset, USERFLAG_INCORRECTDATEFORMAT)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) check_balance(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
|
||||
fp := fsd.path + "_data"
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
balance, err := handlers.CheckBalance(accountData["PublicKey"])
|
||||
if err != nil {
|
||||
return res, nil
|
||||
}
|
||||
res.Content = balance
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) validate_recipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
recipient := string(input)
|
||||
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if recipient != "0" {
|
||||
// mimic invalid number check
|
||||
if recipient == "000" {
|
||||
res.FlagSet = append(res.FlagSet, USERFLAG_INVALID_RECIPIENT)
|
||||
res.Content = recipient
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
accountData["Recipient"] = recipient
|
||||
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) transaction_reset(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// reset the recipient
|
||||
accountData["Recipient"] = ""
|
||||
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
res.FlagReset = append(res.FlagReset, USERFLAG_INVALID_RECIPIENT, USERFLAG_INVALID_RECIPIENT_WITH_INVITE)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) reset_transaction_amount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// reset the amount
|
||||
accountData["Amount"] = ""
|
||||
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
res.FlagReset = append(res.FlagReset, USERFLAG_INVALID_AMOUNT)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) max_amount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
|
||||
// mimic a max amount
|
||||
res.Content = "10.00"
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) validate_amount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
amount := string(input)
|
||||
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if amount != "0" {
|
||||
// mimic invalid amount
|
||||
if amount == "00" {
|
||||
res.FlagSet = append(res.FlagSet, USERFLAG_INVALID_AMOUNT)
|
||||
res.Content = amount
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
res.Content = amount
|
||||
|
||||
accountData["Amount"] = amount
|
||||
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) get_recipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
res.Content = accountData["Recipient"]
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) get_profile_info(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
name := accountData["FirstName"] + " " + accountData["FamilyName"]
|
||||
gender := accountData["Gender"]
|
||||
yob := accountData["YOB"]
|
||||
location := accountData["Location"]
|
||||
offerings := accountData["Offerings"]
|
||||
|
||||
layout := "02/01/2006"
|
||||
|
||||
birthdate, err := time.Parse(layout, yob)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
currentDate := time.Now()
|
||||
formattedDate := currentDate.Format(layout)
|
||||
today, err := time.Parse(layout, formattedDate)
|
||||
if err != nil {
|
||||
return res, nil
|
||||
}
|
||||
age := utils.CalculateAge(birthdate, today)
|
||||
|
||||
formattedData := fmt.Sprintf("Name: %s\nGender: %s\nAge: %d\nLocation: %s\nYou provide: %s\n", name, gender, age, location, offerings)
|
||||
res.Content = formattedData
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) get_sender(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
res.Content = accountData["PublicKey"]
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) quit_with_balance(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
balance, err := handlers.CheckBalance(accountData["PublicKey"])
|
||||
if err != nil {
|
||||
return res, nil
|
||||
}
|
||||
res.Content = fmt.Sprintf("Your account balance is: %s", balance)
|
||||
res.FlagReset = append(res.FlagReset, USERFLAG_ACCOUNT_UNLOCKED)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) save_pin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
accountPIN := string(input)
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
accountData["AccountPIN"] = accountPIN
|
||||
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (fsd *fsData) verify_pin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := fsd.path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if bytes.Equal(input, []byte(accountData["AccountPIN"])) {
|
||||
res.FlagSet = []uint32{USERFLAG_VALIDPIN}
|
||||
res.FlagReset = []uint32{USERFLAG_INVALIDPIN}
|
||||
} else {
|
||||
res.FlagSet = []uint32{USERFLAG_INVALIDPIN}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
var (
|
||||
scriptDir = path.Join("services", "registration")
|
||||
)
|
||||
@ -802,13 +33,13 @@ func main() {
|
||||
fmt.Fprintf(os.Stderr, "starting session at symbol '%s' using resource dir: %s\n", root, dir)
|
||||
|
||||
ctx := context.Background()
|
||||
st := state.NewState(15)
|
||||
st := state.NewState(14)
|
||||
st.UseDebug()
|
||||
Alfred-mk marked this conversation as resolved
Outdated
|
||||
state.FlagDebugger.Register(USERFLAG_LANGUAGE_SET, "LANGUAGE_CHANGE")
|
||||
state.FlagDebugger.Register(USERFLAG_ACCOUNT_CREATED, "ACCOUNT_CREATED")
|
||||
state.FlagDebugger.Register(USERFLAG_ACCOUNT_SUCCESS, "ACCOUNT_SUCCESS")
|
||||
state.FlagDebugger.Register(USERFLAG_ACCOUNT_PENDING, "ACCOUNT_PENDING")
|
||||
state.FlagDebugger.Register(USERFLAG_INCORRECTPIN, "INCORRECTPIN")
|
||||
state.FlagDebugger.Register(models.USERFLAG_LANGUAGE_SET, "LANGUAGE_CHANGE")
|
||||
state.FlagDebugger.Register(models.USERFLAG_ACCOUNT_CREATED, "ACCOUNT_CREATED")
|
||||
state.FlagDebugger.Register(models.USERFLAG_ACCOUNT_SUCCESS, "ACCOUNT_SUCCESS")
|
||||
state.FlagDebugger.Register(models.USERFLAG_ACCOUNT_PENDING, "ACCOUNT_PENDING")
|
||||
Alfred-mk marked this conversation as resolved
Outdated
lash
commented
Please can we have all the http stuff in a separate package?
Please can we have all the http stuff in a separate package?
* urls
* responses
* gets
|
||||
state.FlagDebugger.Register(models.USERFLAG_INCORRECTPIN, "INCORRECTPIN")
|
||||
|
||||
rfs := resource.NewFsResource(scriptDir)
|
||||
ca := cache.NewCache()
|
||||
@ -840,39 +71,38 @@ func main() {
|
||||
}
|
||||
|
||||
fp := path.Join(dp, sessionId)
|
||||
fs := &fsData{
|
||||
path: fp,
|
||||
st: &st,
|
||||
}
|
||||
rfs.AddLocalFunc("select_language", fs.set_language)
|
||||
rfs.AddLocalFunc("create_account", fs.create_account)
|
||||
rfs.AddLocalFunc("save_pin", fs.save_pin)
|
||||
rfs.AddLocalFunc("verify_pin", fs.verify_pin)
|
||||
rfs.AddLocalFunc("check_identifier", fs.check_identifier)
|
||||
rfs.AddLocalFunc("check_account_status", fs.check_account_status)
|
||||
rfs.AddLocalFunc("unlock_account", fs.unlock)
|
||||
rfs.AddLocalFunc("quit", fs.quit)
|
||||
rfs.AddLocalFunc("check_balance", fs.check_balance)
|
||||
rfs.AddLocalFunc("validate_recipient", fs.validate_recipient)
|
||||
rfs.AddLocalFunc("transaction_reset", fs.transaction_reset)
|
||||
rfs.AddLocalFunc("max_amount", fs.max_amount)
|
||||
rfs.AddLocalFunc("validate_amount", fs.validate_amount)
|
||||
rfs.AddLocalFunc("reset_transaction_amount", fs.reset_transaction_amount)
|
||||
rfs.AddLocalFunc("get_recipient", fs.get_recipient)
|
||||
rfs.AddLocalFunc("get_sender", fs.get_sender)
|
||||
rfs.AddLocalFunc("reset_incorrect", fs.reset_incorrect_pin)
|
||||
rfs.AddLocalFunc("save_firstname", fs.save_firstname)
|
||||
rfs.AddLocalFunc("save_familyname", fs.save_familyname)
|
||||
rfs.AddLocalFunc("save_gender", fs.save_gender)
|
||||
rfs.AddLocalFunc("save_location", fs.save_location)
|
||||
rfs.AddLocalFunc("save_yob", fs.save_yob)
|
||||
rfs.AddLocalFunc("save_offerings", fs.save_offerings)
|
||||
rfs.AddLocalFunc("quit_with_balance", fs.quit_with_balance)
|
||||
rfs.AddLocalFunc("reset_unlocked", fs.reset_account_unlocked)
|
||||
rfs.AddLocalFunc("reset_unlock_for_update", fs.reset_unlock_for_update)
|
||||
rfs.AddLocalFunc("get_profile_info", fs.get_profile_info)
|
||||
rfs.AddLocalFunc("verify_yob", fs.verify_yob)
|
||||
rfs.AddLocalFunc("reset_incorrect_date_format", fs.reset_incorrect_yob)
|
||||
|
||||
ussdHandlers := ussd.NewHandlers(fp, &st)
|
||||
|
||||
rfs.AddLocalFunc("select_language", ussdHandlers.SetLanguage)
|
||||
Alfred-mk marked this conversation as resolved
Outdated
lash
commented
can this (and all its methods) be moved to a separate package please? can this (and all its methods) be moved to a separate package please?
|
||||
rfs.AddLocalFunc("create_account", ussdHandlers.CreateAccount)
|
||||
rfs.AddLocalFunc("save_pin", ussdHandlers.SavePin)
|
||||
rfs.AddLocalFunc("verify_pin", ussdHandlers.VerifyPin)
|
||||
rfs.AddLocalFunc("check_identifier", ussdHandlers.CheckIdentifier)
|
||||
rfs.AddLocalFunc("check_account_status", ussdHandlers.CheckAccountStatus)
|
||||
rfs.AddLocalFunc("unlock_account", ussdHandlers.Unlock)
|
||||
rfs.AddLocalFunc("quit", ussdHandlers.Quit)
|
||||
rfs.AddLocalFunc("check_balance", ussdHandlers.CheckBalance)
|
||||
rfs.AddLocalFunc("validate_recipient", ussdHandlers.ValidateRecipient)
|
||||
rfs.AddLocalFunc("transaction_reset", ussdHandlers.TransactionReset)
|
||||
rfs.AddLocalFunc("max_amount", ussdHandlers.MaxAmount)
|
||||
rfs.AddLocalFunc("validate_amount", ussdHandlers.ValidateAmount)
|
||||
rfs.AddLocalFunc("reset_transaction_amount", ussdHandlers.ResetTransactionAmount)
|
||||
rfs.AddLocalFunc("get_recipient", ussdHandlers.GetRecipient)
|
||||
rfs.AddLocalFunc("get_sender", ussdHandlers.GetSender)
|
||||
rfs.AddLocalFunc("reset_incorrect", ussdHandlers.ResetIncorrectPin)
|
||||
rfs.AddLocalFunc("save_firstname", ussdHandlers.SaveFirstname)
|
||||
rfs.AddLocalFunc("save_familyname", ussdHandlers.SaveFamilyname)
|
||||
rfs.AddLocalFunc("save_gender", ussdHandlers.SaveGender)
|
||||
rfs.AddLocalFunc("save_location", ussdHandlers.SaveLocation)
|
||||
rfs.AddLocalFunc("save_yob", ussdHandlers.SaveYob)
|
||||
rfs.AddLocalFunc("save_offerings", ussdHandlers.SaveOfferings)
|
||||
rfs.AddLocalFunc("quit_with_balance", ussdHandlers.QuitWithBalance)
|
||||
rfs.AddLocalFunc("reset_unlocked", ussdHandlers.ResetAccountUnlocked)
|
||||
rfs.AddLocalFunc("reset_unlock_for_update", ussdHandlers.ResetUnlockForUpdate)
|
||||
rfs.AddLocalFunc("get_profile_info", ussdHandlers.GetProfileInfo)
|
||||
rfs.AddLocalFunc("verify_yob", ussdHandlers.VerifyYob)
|
||||
rfs.AddLocalFunc("reset_incorrect_date_format", ussdHandlers.ResetIncorrectYob)
|
||||
|
||||
cont, err := en.Init(ctx)
|
||||
en.SetDebugger(engine.NewSimpleDebug(nil))
|
||||
|
@ -1,4 +1,4 @@
|
||||
package handlers
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@ -9,7 +9,6 @@ import (
|
||||
"git.grassecon.net/urdt/ussd/internal/models"
|
||||
)
|
||||
|
||||
|
||||
func CheckAccountStatus(trackingId string) (string, error) {
|
||||
resp, err := http.Get(config.TrackStatusURL + trackingId)
|
||||
if err != nil {
|
||||
@ -31,4 +30,4 @@ func CheckAccountStatus(trackingId string) (string, error) {
|
||||
status := trackResp.Result.Transaction.Status
|
||||
|
||||
return status, nil
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package handlers
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
@ -1,4 +1,4 @@
|
||||
package handlers
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
780
internal/handlers/ussd/menuhandler.go
Normal file
780
internal/handlers/ussd/menuhandler.go
Normal file
@ -0,0 +1,780 @@
|
||||
package ussd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"git.defalsify.org/vise.git/engine"
|
||||
"git.defalsify.org/vise.git/lang"
|
||||
"git.defalsify.org/vise.git/resource"
|
||||
"git.defalsify.org/vise.git/state"
|
||||
"git.grassecon.net/urdt/ussd/internal/models"
|
||||
"git.grassecon.net/urdt/ussd/internal/handlers/server"
|
||||
"git.grassecon.net/urdt/ussd/internal/utils"
|
||||
)
|
||||
|
||||
type FSData struct {
|
||||
Path string
|
||||
St *state.State
|
||||
}
|
||||
|
||||
type Handlers struct {
|
||||
fs *FSData
|
||||
}
|
||||
|
||||
func NewHandlers(path string, st *state.State) *Handlers {
|
||||
return &Handlers{
|
||||
fs: &FSData{
|
||||
Path: path,
|
||||
St: st,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handlers) SetLanguage(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
inputStr := string(input)
|
||||
res := resource.Result{}
|
||||
switch inputStr {
|
||||
case "0":
|
||||
res.FlagSet = []uint32{state.FLAG_LANG}
|
||||
res.Content = "eng"
|
||||
case "1":
|
||||
res.FlagSet = []uint32{state.FLAG_LANG}
|
||||
res.Content = "swa"
|
||||
default:
|
||||
}
|
||||
|
||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_LANGUAGE_SET)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
f, err := os.OpenFile(fp, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
f.Close()
|
||||
accountResp, err := server.CreateAccount()
|
||||
if err != nil {
|
||||
fmt.Println("Failed to create account:", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
accountData := map[string]string{
|
||||
"TrackingId": accountResp.Result.TrackingId,
|
||||
"PublicKey": accountResp.Result.PublicKey,
|
||||
"CustodialId": accountResp.Result.CustodialId.String(),
|
||||
"Status": "PENDING",
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(accountData)
|
||||
Alfred-mk marked this conversation as resolved
Outdated
lash
commented
should not be necessary to set the flag when it already has been set and persisted. That will reduce one file access call each run. should not be necessary to set the flag when it already has been set and persisted. That will reduce one file access call each run.
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, jsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_CREATED)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (h *Handlers) SavePin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
accountPIN := string(input)
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
accountData["AccountPIN"] = accountPIN
|
||||
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) VerifyPin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if bytes.Equal(input, []byte(accountData["AccountPIN"])) {
|
||||
res.FlagSet = []uint32{models.USERFLAG_VALIDPIN}
|
||||
res.FlagReset = []uint32{models.USERFLAG_PINMISMATCH}
|
||||
} else {
|
||||
res.FlagSet = []uint32{models.USERFLAG_PINMISMATCH}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func codeFromCtx(ctx context.Context) string {
|
||||
var code string
|
||||
engine.Logg.DebugCtxf(ctx, "in msg", "ctx", ctx, "val", code)
|
||||
if ctx.Value("Language") != nil {
|
||||
lang := ctx.Value("Language").(lang.Language)
|
||||
code = lang.Code
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
func (h *Handlers) SaveFirstname(cxt context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if len(input) > 0 {
|
||||
name := string(input)
|
||||
accountData["FirstName"] = name
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
Alfred-mk marked this conversation as resolved
Outdated
lash
commented
I prefer putting regexes like this on top of the file as a const. I prefer putting regexes like this on top of the file as a const.
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) SaveFamilyname(cxt context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if len(input) > 0 {
|
||||
//Save name
|
||||
secondname := string(input)
|
||||
accountData["FamilyName"] = secondname
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) SaveYob(cxt context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if len(input) > 0 {
|
||||
yob := string(input)
|
||||
accountData["YOB"] = yob
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) SaveLocation(cxt context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if len(input) > 0 {
|
||||
location := string(input)
|
||||
accountData["Location"] = location
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if len(input) > 0 {
|
||||
gender := string(input)
|
||||
|
||||
switch gender {
|
||||
case "1":
|
||||
gender = "Male"
|
||||
case "2":
|
||||
gender = "Female"
|
||||
case "3":
|
||||
gender = "Other"
|
||||
}
|
||||
accountData["Gender"] = gender
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
lash
commented
Please change to "Unspecified" Please change to "Unspecified"
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if len(input) > 0 {
|
||||
offerings := string(input)
|
||||
accountData["Offerings"] = offerings
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) ResetUnlockForUpdate(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
lash
commented
"unlocked" risks being an ambiguous term when we introduce account blocking due to direct action or incorrect pin attempts. can we rename it please? "unlocked" risks being an ambiguous term when we introduce account blocking due to direct action or incorrect pin attempts. can we rename it please?
|
||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_UNLOCKFORUPDATE)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) ResetAccountUnlocked(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) CheckIdentifier(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
res.Content = accountData["PublicKey"]
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) Unlock(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
pin := string(input)
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if len(input) > 1 {
|
||||
if pin != accountData["AccountPIN"] {
|
||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_INCORRECTPIN)
|
||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
|
||||
return res, nil
|
||||
}
|
||||
if h.fs.St.MatchFlag(models.USERFLAG_ACCOUNT_UNLOCKED, false) {
|
||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTPIN)
|
||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_UNLOCKFORUPDATE)
|
||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_UNLOCKED)
|
||||
} else {
|
||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) ResetIncorrectPin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTPIN)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
//status, err := checkAccountStatus(accountData["TrackingId"])
|
||||
status, err := server.CheckAccountStatus(accountData["TrackingId"])
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Error checking account status:", err)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
accountData["Status"] = status
|
||||
|
||||
if status == "SUCCESS" {
|
||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_SUCCESS)
|
||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_PENDING)
|
||||
Alfred-mk marked this conversation as resolved
Outdated
lash
commented
were we using gettext here too? were we using gettext here too?
|
||||
} else {
|
||||
res.FlagReset = append(res.FlagSet, models.USERFLAG_ACCOUNT_SUCCESS)
|
||||
res.FlagSet = append(res.FlagReset, models.USERFLAG_ACCOUNT_PENDING)
|
||||
}
|
||||
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) Quit(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
switch codeFromCtx(ctx) {
|
||||
case "swa":
|
||||
res.Content = "Asante kwa kutumia huduma ya Sarafu. Kwaheri!"
|
||||
default:
|
||||
res.Content = "Thank you for using Sarafu. Goodbye!"
|
||||
}
|
||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) VerifyYob(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
date := string(input)
|
||||
|
||||
dateRegex := regexp.MustCompile(`^\d{2}/\d{2}/\d{4}$`)
|
||||
isCorrectFormat := dateRegex.MatchString(date)
|
||||
if !isCorrectFormat {
|
||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_INCORRECTDATEFORMAT)
|
||||
} else {
|
||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTDATEFORMAT)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) ResetIncorrectYob(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTDATEFORMAT)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
|
||||
fp := h.fs.Path + "_data"
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
balance, err := server.CheckBalance(accountData["PublicKey"])
|
||||
if err != nil {
|
||||
return res, nil
|
||||
}
|
||||
res.Content = balance
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
recipient := string(input)
|
||||
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if recipient != "0" {
|
||||
// mimic invalid number check
|
||||
if recipient == "000" {
|
||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_INVALID_RECIPIENT)
|
||||
res.Content = recipient
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
accountData["Recipient"] = recipient
|
||||
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) TransactionReset(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// reset the recipient
|
||||
accountData["Recipient"] = ""
|
||||
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_INVALID_RECIPIENT, models.USERFLAG_INVALID_RECIPIENT_WITH_INVITE)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) ResetTransactionAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// reset the amount
|
||||
accountData["Amount"] = ""
|
||||
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_INVALID_AMOUNT)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) MaxAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
|
||||
// mimic a max amount
|
||||
res.Content = "10.00"
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
amount := string(input)
|
||||
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if amount != "0" {
|
||||
// mimic invalid amount
|
||||
if amount == "00" {
|
||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_INVALID_AMOUNT)
|
||||
res.Content = amount
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
res.Content = amount
|
||||
|
||||
accountData["Amount"] = amount
|
||||
|
||||
updatedJsonData, err := json.Marshal(accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = os.WriteFile(fp, updatedJsonData, 0644)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
res.Content = accountData["Recipient"]
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) GetProfileInfo(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
name := accountData["FirstName"] + " " + accountData["FamilyName"]
|
||||
gender := accountData["Gender"]
|
||||
yob := accountData["YOB"]
|
||||
location := accountData["Location"]
|
||||
offerings := accountData["Offerings"]
|
||||
|
||||
layout := "02/01/2006"
|
||||
|
||||
birthdate, err := time.Parse(layout, yob)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
currentDate := time.Now()
|
||||
formattedDate := currentDate.Format(layout)
|
||||
today, err := time.Parse(layout, formattedDate)
|
||||
if err != nil {
|
||||
return res, nil
|
||||
}
|
||||
age := utils.CalculateAge(birthdate, today)
|
||||
|
||||
formattedData := fmt.Sprintf("Name: %s\nGender: %s\nAge: %d\nLocation: %s\nYou provide: %s\n", name, gender, age, location, offerings)
|
||||
res.Content = formattedData
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) GetSender(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
res.Content = accountData["PublicKey"]
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) QuitWithBalance(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
fp := h.fs.Path + "_data"
|
||||
|
||||
jsonData, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
var accountData map[string]string
|
||||
err = json.Unmarshal(jsonData, &accountData)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
balance, err := server.CheckBalance(accountData["PublicKey"])
|
||||
if err != nil {
|
||||
return res, nil
|
||||
}
|
||||
res.Content = fmt.Sprintf("Your account balance is: %s", balance)
|
||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_UNLOCKED)
|
||||
return res, nil
|
||||
}
|
20
internal/models/flags.go
Normal file
20
internal/models/flags.go
Normal file
@ -0,0 +1,20 @@
|
||||
package models
|
||||
|
||||
import "git.defalsify.org/vise.git/state"
|
||||
|
||||
const (
|
||||
USERFLAG_LANGUAGE_SET = iota + state.FLAG_USERSTART
|
||||
USERFLAG_ACCOUNT_CREATED
|
||||
USERFLAG_ACCOUNT_PENDING
|
||||
USERFLAG_ACCOUNT_SUCCESS
|
||||
USERFLAG_ACCOUNT_UNLOCKED
|
||||
USERFLAG_INVALID_RECIPIENT
|
||||
USERFLAG_INVALID_RECIPIENT_WITH_INVITE
|
||||
USERFLAG_INCORRECTPIN
|
||||
USERFLAG_UNLOCKFORUPDATE
|
||||
USERFLAG_INVALID_AMOUNT
|
||||
USERFLAG_QUERYPIN
|
||||
USERFLAG_VALIDPIN
|
||||
USERFLAG_PINMISMATCH
|
||||
USERFLAG_INCORRECTDATEFORMAT
|
||||
)
|
Loading…
Reference in New Issue
Block a user
please rename this flag to USERFLAG_PINMISMATCH to avoid ambiguity.
priority