204 lines
4.6 KiB
Go
204 lines
4.6 KiB
Go
|
|
/*
|
||
|
|
* Copyright (c) 2026 Kaiy Ragur
|
||
|
|
*
|
||
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||
|
|
*/
|
||
|
|
package shell
|
||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/hex"
|
||
|
|
"encoding/json"
|
||
|
|
"flag"
|
||
|
|
"fmt"
|
||
|
|
"log"
|
||
|
|
"os"
|
||
|
|
|
||
|
|
"github.com/neilalexander/yggmail/internal/account"
|
||
|
|
"github.com/neilalexander/yggmail/internal/config"
|
||
|
|
"github.com/neilalexander/yggmail/internal/storage"
|
||
|
|
"github.com/neilalexander/yggmail/internal/storage/types"
|
||
|
|
"github.com/neilalexander/yggmail/internal/utils"
|
||
|
|
)
|
||
|
|
|
||
|
|
type Shell struct {
|
||
|
|
storage storage.Storage
|
||
|
|
account *account.Manager
|
||
|
|
cfg *config.Config
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewShell(storage storage.Storage, log *log.Logger, cfg *config.Config) *Shell {
|
||
|
|
return &Shell{
|
||
|
|
storage: storage,
|
||
|
|
account: account.NewManager(storage, log),
|
||
|
|
cfg: cfg,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func passwordProvider() (string, error) {
|
||
|
|
p, err := account.DefaultProvider("Enter password for your new mail account: ")
|
||
|
|
if err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
p2, err := account.DefaultProvider("Comfirm your password: ")
|
||
|
|
if err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
if p == p2 {
|
||
|
|
return p2, nil
|
||
|
|
}
|
||
|
|
return "", fmt.Errorf("Password not match")
|
||
|
|
}
|
||
|
|
|
||
|
|
type shellCommand func(args []string) error
|
||
|
|
|
||
|
|
func (s *Shell) Run(c string, args []string) {
|
||
|
|
// fmt.Println(c, args)
|
||
|
|
var err error
|
||
|
|
|
||
|
|
commands := map[string]shellCommand{
|
||
|
|
"accountAdd": s.accountAdd,
|
||
|
|
"accountCreateNew": s.accountCreateNew,
|
||
|
|
"accountGet": s.accountGet,
|
||
|
|
"accountList": s.accountList,
|
||
|
|
"accountDelete": s.accountDelete,
|
||
|
|
"nodeInfo": s.getNodeInfo,
|
||
|
|
}
|
||
|
|
cmd, ok := commands[c]
|
||
|
|
if !ok {
|
||
|
|
log.Fatal("Command not found!")
|
||
|
|
os.Exit(1)
|
||
|
|
}
|
||
|
|
err = cmd(args)
|
||
|
|
if err != nil {
|
||
|
|
fmt.Println(err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *Shell) accountAdd(args []string) error {
|
||
|
|
|
||
|
|
flags := flag.NewFlagSet("addAccount", flag.ExitOnError)
|
||
|
|
// All flags
|
||
|
|
pubkey := flags.String("pub", "", "Account public key")
|
||
|
|
file := flags.String("f", "", "Added from file")
|
||
|
|
|
||
|
|
flags.Parse(args)
|
||
|
|
|
||
|
|
var (
|
||
|
|
err error
|
||
|
|
acc *types.Account = new(types.Account)
|
||
|
|
)
|
||
|
|
if *file != "" {
|
||
|
|
cont, err := os.ReadFile(*file)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if err := json.Unmarshal(cont, acc); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if err := s.storage.AccountCreate(acc); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
fmt.Printf("Account %s@%s added", acc.PublicKey, utils.EncodeString(s.cfg.PublicKey))
|
||
|
|
for _, folder := range []string{"INBOX", "Outbox", "Sent", "Trash", "Drafts"} {
|
||
|
|
s.storage.MailboxCreate(acc.PublicKey, folder)
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
if acc, err = s.account.AddAccount(*pubkey); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
fmt.Printf("Account %s@%s added", acc.PublicKey, utils.EncodeString(s.cfg.PublicKey))
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *Shell) getNodeInfo(args []string) error {
|
||
|
|
|
||
|
|
flags := flag.NewFlagSet("nodeInfo", flag.ExitOnError)
|
||
|
|
flags.Parse(args)
|
||
|
|
|
||
|
|
pks := utils.EncodeString(s.cfg.PublicKey)
|
||
|
|
accList, err := s.storage.AccountList()
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
fmt.Println("== Node Info == ")
|
||
|
|
fmt.Println("Address base32:", pks)
|
||
|
|
fmt.Println("Address hex16:", hex.EncodeToString(s.cfg.PublicKey))
|
||
|
|
fmt.Println("Accounts: ", len(accList))
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *Shell) accountList(args []string) error {
|
||
|
|
accList, err := s.storage.AccountList()
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
fmt.Println("Accounts: ", len(accList))
|
||
|
|
for i, a := range accList {
|
||
|
|
count, err := s.storage.MailCount(a.PublicKey, "INBOX")
|
||
|
|
if err != nil {
|
||
|
|
count = 0
|
||
|
|
}
|
||
|
|
fmt.Printf("\n| %d | %s | %s | Mails: %d", i, a.PublicKey, a.Aliases, count)
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *Shell) accountCreateNew(args []string) error {
|
||
|
|
a, err := s.account.CreateNewAccount(passwordProvider)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
fmt.Printf("Created account: %s@%s", a.PublicKey, utils.EncodeString(s.cfg.PublicKey))
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *Shell) accountGet(args []string) error {
|
||
|
|
flags := flag.NewFlagSet("getAccount", flag.ExitOnError)
|
||
|
|
// All flags
|
||
|
|
pubkey := flags.String("pub", "", "Account Publickey")
|
||
|
|
file := flags.String("o", "", "Write to file")
|
||
|
|
|
||
|
|
flags.Parse(args)
|
||
|
|
|
||
|
|
var (
|
||
|
|
err error
|
||
|
|
acc *types.Account
|
||
|
|
)
|
||
|
|
|
||
|
|
if acc, err = s.account.GetAccount(*pubkey); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
b, err := json.Marshal(acc)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if *file == "" {
|
||
|
|
fmt.Println(string(b))
|
||
|
|
} else {
|
||
|
|
os.WriteFile(*file, b, 0600)
|
||
|
|
fmt.Println("Write to ", *file)
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *Shell) accountDelete(args []string) error {
|
||
|
|
flags := flag.NewFlagSet("getAccount", flag.ExitOnError)
|
||
|
|
// All flags
|
||
|
|
pubkey := flags.String("pub", "", "Account Publickey")
|
||
|
|
flags.Parse(args)
|
||
|
|
|
||
|
|
var (
|
||
|
|
err error
|
||
|
|
)
|
||
|
|
if err = s.account.DeleteAccount(*pubkey); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
|
||
|
|
}
|