Split commands out into their own files.
- add login, register commands - make "similar" parse out the parts of speach and only give us back entries that match those parts.
This commit is contained in:
parent
1884f88912
commit
31af3d75d2
@ -1,10 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"os/user"
|
||||
"path"
|
||||
|
||||
"github.com/peterbourgon/ff/v2/ffcli"
|
||||
)
|
||||
|
||||
func getPath() (*string, error) {
|
||||
@ -53,3 +57,29 @@ func (c *Config) ReadConfig() error {
|
||||
|
||||
return json.Unmarshal(data, c)
|
||||
}
|
||||
|
||||
// NewConfig creates a new config ffcli command
|
||||
func NewConfig() *ffcli.Command {
|
||||
var configFlagSet = flag.NewFlagSet("cromp config", flag.ExitOnError)
|
||||
urlConfFS := configFlagSet.String("url", "", "URL of cromp server")
|
||||
tokenConfFS := configFlagSet.String("token", "", "Access token for cromp server")
|
||||
|
||||
return &ffcli.Command{
|
||||
Name: "config",
|
||||
ShortUsage: "cromp config -token [token] -url [url]",
|
||||
FlagSet: configFlagSet,
|
||||
Exec: func(ctx context.Context, args []string) error {
|
||||
cfg := &Config{
|
||||
Token: *tokenConfFS,
|
||||
URL: *urlConfFS,
|
||||
}
|
||||
|
||||
err := cfg.WriteConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
58
cmd/cromp/load.go
Normal file
58
cmd/cromp/load.go
Normal file
@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/peterbourgon/ff/v2/ffcli"
|
||||
"suah.dev/cromp/db"
|
||||
cromp "suah.dev/cromp/internal"
|
||||
)
|
||||
|
||||
// NewLoad returns the load ffcli command
|
||||
func NewLoad() *ffcli.Command {
|
||||
return &ffcli.Command{
|
||||
Name: "load",
|
||||
ShortUsage: "cromp load <file>",
|
||||
Exec: func(ctx context.Context, args []string) error {
|
||||
var entry db.CreateEntryParams
|
||||
resp := &db.CreateEntryRow{}
|
||||
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("missing file name")
|
||||
}
|
||||
header, err := cromp.ParseFileHeader(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s := header.UUID.String()
|
||||
if s == "" || s == "00000000-0000-0000-0000-000000000000" {
|
||||
|
||||
header.UUID = uuid.New()
|
||||
}
|
||||
|
||||
entry.Title = header.Title
|
||||
entry.EntryID = header.UUID
|
||||
|
||||
fmt.Printf("%#v\n", entry)
|
||||
|
||||
data, err := cromp.ReadFileBody(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
entry.Body = string(data)
|
||||
|
||||
err = Post("/entries/add", entry, resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("%#v\n", resp)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
64
cmd/cromp/login.go
Normal file
64
cmd/cromp/login.go
Normal file
@ -0,0 +1,64 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/peterbourgon/ff/v2/ffcli"
|
||||
"suah.dev/cromp/db"
|
||||
)
|
||||
|
||||
// NewLogin creates a new config ffcli command
|
||||
func NewLogin() *ffcli.Command {
|
||||
var loginFlagSet = flag.NewFlagSet("cromp login", flag.ExitOnError)
|
||||
urlConfFS := loginFlagSet.String("url", "", "URL of cromp server")
|
||||
return &ffcli.Command{
|
||||
Name: "login",
|
||||
ShortUsage: "login -url [url]",
|
||||
FlagSet: loginFlagSet,
|
||||
Exec: func(ctx context.Context, args []string) error {
|
||||
var loginParams db.AuthUserParams
|
||||
resp := &db.AuthUserRow{}
|
||||
|
||||
cfg := &Config{}
|
||||
err := cfg.ReadConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cfg.URL == "" && *urlConfFS == "" {
|
||||
return fmt.Errorf("please specify -url")
|
||||
}
|
||||
|
||||
user, err := Prompt("Login: ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pass, err := SecurePrompt("Password: ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
|
||||
loginParams.Username = *user
|
||||
loginParams.Crypt = *pass
|
||||
|
||||
err = Post("/user/auth", loginParams, resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("New token expires %s\n", resp.TokenExpires)
|
||||
|
||||
cfg.Token = resp.Token
|
||||
err = cfg.WriteConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
@ -5,24 +5,14 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/peterbourgon/ff/v2/ffcli"
|
||||
"suah.dev/cromp/db"
|
||||
cromp "suah.dev/cromp/internal"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var (
|
||||
rootFlagSet = flag.NewFlagSet("cromp", flag.ExitOnError)
|
||||
|
||||
loadFlagSet = flag.NewFlagSet("cromp load", flag.ExitOnError)
|
||||
|
||||
configFlagSet = flag.NewFlagSet("cromp config", flag.ExitOnError)
|
||||
urlConfFS = configFlagSet.String("url", "", "URL of cromp server")
|
||||
tokenConfFS = configFlagSet.String("token", "", "Access token for cromp server")
|
||||
|
||||
//createFlagSet = flag.NewFlagSet("cromp create", flag.ExitOnError)
|
||||
)
|
||||
|
||||
@ -30,113 +20,12 @@ func main() {
|
||||
ShortUsage: "cromp <subcommand>",
|
||||
FlagSet: rootFlagSet,
|
||||
Subcommands: []*ffcli.Command{
|
||||
&ffcli.Command{
|
||||
Name: "config",
|
||||
ShortUsage: "cromp config -token [token] -url [url]",
|
||||
FlagSet: configFlagSet,
|
||||
Exec: func(ctx context.Context, args []string) error {
|
||||
cfg := &Config{
|
||||
Token: *tokenConfFS,
|
||||
URL: *urlConfFS,
|
||||
}
|
||||
|
||||
err := cfg.WriteConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
&ffcli.Command{
|
||||
Name: "similar",
|
||||
ShortUsage: "cromp similar [text]",
|
||||
Exec: func(ctx context.Context, args []string) error {
|
||||
var params db.SimilarEntriesParams
|
||||
resp := &[]db.SimilarEntriesRow{}
|
||||
|
||||
params.Similarity = strings.Join(args, " ")
|
||||
|
||||
err := Post("/entries/similar", params, resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, e := range *resp {
|
||||
fmt.Printf("%s\t%s\t%f\n",
|
||||
e.EntryID,
|
||||
e.Title,
|
||||
e.Similarity)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
&ffcli.Command{
|
||||
Name: "list",
|
||||
ShortUsage: "cromp list",
|
||||
FlagSet: configFlagSet,
|
||||
Exec: func(ctx context.Context, args []string) error {
|
||||
resp := &[]db.Entry{}
|
||||
|
||||
err := Get("/entries/list", resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, e := range *resp {
|
||||
fmt.Printf("%s\t%s\t%s\n", e.EntryID.String(),
|
||||
e.CreatedAt,
|
||||
e.Title)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
&ffcli.Command{
|
||||
Name: "load",
|
||||
ShortUsage: "cromp load <file>",
|
||||
FlagSet: loadFlagSet,
|
||||
Exec: func(ctx context.Context, args []string) error {
|
||||
var entry db.CreateEntryParams
|
||||
resp := &db.CreateEntryRow{}
|
||||
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("missing file name")
|
||||
}
|
||||
header, err := cromp.ParseFileHeader(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s := header.UUID.String()
|
||||
if s == "" || s == "00000000-0000-0000-0000-000000000000" {
|
||||
|
||||
header.UUID = uuid.New()
|
||||
}
|
||||
|
||||
entry.Title = header.Title
|
||||
entry.EntryID = header.UUID
|
||||
|
||||
fmt.Printf("%#v\n", entry)
|
||||
|
||||
data, err := cromp.ReadFileBody(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
entry.Body = string(data)
|
||||
|
||||
err = Post("/entries/add", entry, resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("%#v\n", resp)
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
NewConfig(),
|
||||
NewLoad(),
|
||||
NewLogin(),
|
||||
NewPOS(),
|
||||
NewRegister(),
|
||||
NewSimilar(),
|
||||
},
|
||||
Exec: func(context.Context, []string) error {
|
||||
return flag.ErrHelp
|
||||
|
58
cmd/cromp/pos.go
Normal file
58
cmd/cromp/pos.go
Normal file
@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/peterbourgon/ff/v2/ffcli"
|
||||
"gopkg.in/jdkato/prose.v2"
|
||||
)
|
||||
|
||||
// GetPOS returns the parts of speech from a text file
|
||||
func GetPOS(p string) (map[string][]string, error) {
|
||||
// We only care about word like things
|
||||
var wre = regexp.MustCompile(`^\w+$`)
|
||||
var pos = map[string][]string{}
|
||||
|
||||
data, err := ioutil.ReadFile(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
doc, err := prose.NewDocument(string(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, tok := range doc.Tokens() {
|
||||
if wre.MatchString(tok.Text) {
|
||||
pos[tok.Tag] = append(pos[tok.Tag], tok.Text)
|
||||
}
|
||||
}
|
||||
|
||||
return pos, nil
|
||||
}
|
||||
|
||||
// NewPOS returns a new ffcli.Command
|
||||
func NewPOS() *ffcli.Command {
|
||||
return &ffcli.Command{
|
||||
Name: "pos",
|
||||
ShortUsage: "cromp pos <file>",
|
||||
Exec: func(ctx context.Context, args []string) error {
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("missing file name")
|
||||
}
|
||||
|
||||
pos, err := GetPOS(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Nouns: %s\n", strings.Join(pos["NN"], ", "))
|
||||
fmt.Printf("Verbs: %s\n", strings.Join(pos["VB"], ", "))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
27
cmd/cromp/prompts.go
Normal file
27
cmd/cromp/prompts.go
Normal file
@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
// SecurePrompt presents the user with a non-echoing prompt
|
||||
func SecurePrompt(prompt string) (*string, error) {
|
||||
fmt.Print(prompt)
|
||||
b, err := terminal.ReadPassword(int(os.Stdin.Fd()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pass := string(b)
|
||||
return &pass, nil
|
||||
}
|
||||
|
||||
// Prompt presents the user with an echoing prompt
|
||||
func Prompt(prompt string) (*string, error) {
|
||||
var user string
|
||||
fmt.Print(prompt)
|
||||
fmt.Scanln(&user)
|
||||
return &user, nil
|
||||
}
|
82
cmd/cromp/register.go
Normal file
82
cmd/cromp/register.go
Normal file
@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/peterbourgon/ff/v2/ffcli"
|
||||
"suah.dev/cromp/db"
|
||||
)
|
||||
|
||||
// NewRegister creates a new config ffcli command
|
||||
func NewRegister() *ffcli.Command {
|
||||
var regFlagSet = flag.NewFlagSet("cromp reg", flag.ExitOnError)
|
||||
urlConfFS := regFlagSet.String("url", "", "URL of cromp server")
|
||||
return &ffcli.Command{
|
||||
Name: "reg",
|
||||
ShortUsage: "reg -url [url]",
|
||||
FlagSet: regFlagSet,
|
||||
Exec: func(ctx context.Context, args []string) error {
|
||||
var regParams db.CreateUserParams
|
||||
resp := &db.CreateUserRow{}
|
||||
|
||||
cfg := &Config{}
|
||||
err := cfg.ReadConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cfg.URL == "" && *urlConfFS == "" {
|
||||
return fmt.Errorf("please specify -url")
|
||||
}
|
||||
|
||||
fn, err := Prompt("First Name: ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ln, err := Prompt("Last Name: ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
email, err := Prompt("Email: ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user, err := Prompt("Username: ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pass, err := SecurePrompt("Password: ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
|
||||
regParams.Username = *user
|
||||
regParams.Password = *pass
|
||||
regParams.FirstName = *fn
|
||||
regParams.LastName = *ln
|
||||
regParams.Email = *email
|
||||
|
||||
err = Post("/user/new", regParams, resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("New token expires %s\n", resp.TokenExpires)
|
||||
|
||||
cfg.Token = resp.Token
|
||||
err = cfg.WriteConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
46
cmd/cromp/similar.go
Normal file
46
cmd/cromp/similar.go
Normal file
@ -0,0 +1,46 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/peterbourgon/ff/v2/ffcli"
|
||||
"suah.dev/cromp/db"
|
||||
)
|
||||
|
||||
// NewSimilar creates a new config ffcli command
|
||||
func NewSimilar() *ffcli.Command {
|
||||
return &ffcli.Command{
|
||||
Name: "similar",
|
||||
ShortUsage: "cromp similar [text]",
|
||||
Exec: func(ctx context.Context, args []string) error {
|
||||
var params db.SimilarEntriesParams
|
||||
resp := &[]db.SimilarEntriesRow{}
|
||||
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("missing file name")
|
||||
}
|
||||
|
||||
pos, err := GetPOS(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
params.Similarity = strings.Join(pos["NN"], "|")
|
||||
|
||||
err = Post("/entries/similar", params, resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, e := range *resp {
|
||||
fmt.Printf("%s\t%s\n",
|
||||
e.Title,
|
||||
e.Headline)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user