-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update the sync command #211
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,63 +55,6 @@ func NewAppWithPrintOptions(unicodeSupport bool, colorSupport bool) *App { | |
func (a *App) InitializeRepo() { | ||
a.TodoStore.Initialize() | ||
fmt.Println("Repo initialized.") | ||
|
||
backend := NewBackend() | ||
eventLogger := &EventLogger{Store: a.TodoStore, CurrentTodoList: a.TodoList} | ||
eventLogger.LoadSyncedLists() | ||
|
||
if !backend.CredsFileExists() { | ||
return | ||
} | ||
|
||
prompt := promptui.Prompt{ | ||
Label: "Do you wish to sync this list with ultralist.io", | ||
IsConfirm: true, | ||
} | ||
|
||
result, _ := prompt.Run() | ||
if result != "y" { | ||
return | ||
} | ||
|
||
if !backend.CanConnect() { | ||
fmt.Println("I cannot connect to ultralist.io right now.") | ||
return | ||
} | ||
|
||
// fetch lists from ultralist.io, or allow user to create a new list | ||
// use the "select_add" example in promptui as a way to do this | ||
type Response struct { | ||
Todolists []TodoList `json:"todolists"` | ||
} | ||
|
||
var response *Response | ||
|
||
resp := backend.PerformRequest("GET", "/api/v1/todo_lists", []byte{}) | ||
json.Unmarshal(resp, &response) | ||
|
||
var todolistNames []string | ||
for _, todolist := range response.Todolists { | ||
todolistNames = append(todolistNames, todolist.Name) | ||
} | ||
|
||
prompt2 := promptui.SelectWithAdd{ | ||
Label: "You can sync with an existing list on ultralist, or create a new list.", | ||
Items: todolistNames, | ||
AddLabel: "New list...", | ||
} | ||
|
||
idx, name, _ := prompt2.Run() | ||
if idx == -1 { | ||
eventLogger.CurrentSyncedList.Name = name | ||
} else { | ||
eventLogger.CurrentSyncedList.Name = response.Todolists[idx].Name | ||
eventLogger.CurrentSyncedList.UUID = response.Todolists[idx].UUID | ||
a.TodoList = &response.Todolists[idx] | ||
a.save() | ||
} | ||
|
||
eventLogger.WriteSyncedLists() | ||
} | ||
|
||
// AddTodo is adding a new todo. | ||
|
@@ -360,19 +303,16 @@ func (a *App) GarbageCollect() { | |
|
||
// Sync will sync the todolist with ultralist.io. | ||
func (a *App) Sync(quiet bool) { | ||
a.Load() | ||
|
||
if a.EventLogger.CurrentSyncedList.Name == "" { | ||
prompt := promptui.Prompt{ | ||
Label: "Give this list a name", | ||
} | ||
backend := NewBackend() | ||
if !backend.CredsFileExists() { | ||
fmt.Println("You're not authenticated with ultralist.io yet. Please run `ultralist auth` first.") | ||
return | ||
} | ||
|
||
result, err := prompt.Run() | ||
if err != nil { | ||
fmt.Println("A name is required to sync a list.") | ||
return | ||
} | ||
a.EventLogger.CurrentSyncedList.Name = result | ||
a.Load() | ||
if !a.TodoList.IsSynced { | ||
fmt.Println("This list isn't currently syncing with ultralist.io. Please run `ultralist sync --setup` to set up syncing.") | ||
return | ||
} | ||
|
||
var synchronizer *Synchronizer | ||
|
@@ -389,6 +329,96 @@ func (a *App) Sync(quiet bool) { | |
} | ||
} | ||
|
||
// SetupSync sets up a todolist to sync with ultralist.io. | ||
func (a *App) SetupSync() { | ||
backend := NewBackend() | ||
if !backend.CredsFileExists() { | ||
fmt.Println("You're not authenticated with ultralist.io yet. Please run `ultralist auth` first.") | ||
return | ||
} | ||
|
||
if a.TodoStore.LocalTodosFileExists() { | ||
a.Load() | ||
|
||
if a.TodoList.IsSynced { | ||
fmt.Println("This list is already sycned with ultralist.io. Use the --unsync flag to stop syncing this list.") | ||
return | ||
} | ||
|
||
prompt := promptui.Select{ | ||
Label: "You have a todos list in this directory. What would you like to do?", | ||
Items: []string{"Sync my list to ultralist.io", "Pull a list from ultralist.io, replacing the list that's here"}, | ||
} | ||
_, result, err := prompt.Run() | ||
if err != nil { | ||
return | ||
} | ||
if strings.HasPrefix(result, "Sync my list") { | ||
prompt := promptui.Prompt{ | ||
Label: "Give this list a name", | ||
} | ||
|
||
result, err := prompt.Run() | ||
if err != nil { | ||
fmt.Println("A name is required to sync a list.") | ||
return | ||
} | ||
a.EventLogger.CurrentSyncedList.Name = result | ||
a.TodoList.IsSynced = true | ||
a.EventLogger.WriteSyncedLists() | ||
a.Sync(false) | ||
return | ||
} | ||
} | ||
// pull a list from ultralist.io | ||
type Response struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. may be its me not being a full time golang programmer, but a struct, definition inside of a func seems a little odd (unless you are trying to hide it) |
||
Todolists []TodoList `json:"todolists"` | ||
} | ||
|
||
var response *Response | ||
|
||
resp := backend.PerformRequest("GET", "/api/v1/todo_lists", []byte{}) | ||
json.Unmarshal(resp, &response) | ||
|
||
var todolistNames []string | ||
for _, todolist := range response.Todolists { | ||
todolistNames = append(todolistNames, todolist.Name) | ||
} | ||
prompt2 := promptui.Select{ | ||
Label: "Choose a list to import", | ||
Items: todolistNames, | ||
} | ||
|
||
idx, _, _ := prompt2.Run() | ||
// a.EventLogger.CurrentSyncedList.Name = response.Todolists[idx].Name | ||
// a.EventLogger.CurrentSyncedList.UUID = response.Todolists[idx].UUID | ||
a.TodoList = &response.Todolists[idx] | ||
a.TodoStore.Save(a.TodoList.Data) | ||
|
||
a.EventLogger = NewEventLogger(a.TodoList, a.TodoStore) | ||
a.EventLogger.WriteSyncedLists() | ||
} | ||
|
||
// Unsync stops a list from syncing with Ultralist.io. | ||
func (a *App) Unsync() { | ||
backend := NewBackend() | ||
if !backend.CredsFileExists() { | ||
fmt.Println("You're not authenticated with ultralist.io yet. Please run `ultralist auth` first.") | ||
return | ||
} | ||
|
||
a.Load() | ||
|
||
if !a.TodoList.IsSynced { | ||
fmt.Println("This list isn't currently syncing with ultralist.io.") | ||
return | ||
} | ||
|
||
a.EventLogger.DeleteCurrentSyncedList() | ||
a.EventLogger.WriteSyncedLists() | ||
fmt.Println("This list will no longer sync with ultralist.io. To set up syncing again, run `ultralist sync --setup`.") | ||
} | ||
|
||
// CheckAuth is checking the authentication against ultralist.io. | ||
func (a *App) CheckAuth() { | ||
synchronizer := NewSynchronizer() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,41 +7,45 @@ import ( | |
"os" | ||
) | ||
|
||
// the filename to use | ||
const FILENAME = ".todos.json" | ||
|
||
// FileStore is the main struct of this file. | ||
type FileStore struct { | ||
FileLocation string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removing this breaks tests.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good catch! |
||
Loaded bool | ||
Loaded bool | ||
} | ||
|
||
// NewFileStore is creating a new file store. | ||
func NewFileStore() *FileStore { | ||
return &FileStore{FileLocation: "", Loaded: false} | ||
return &FileStore{Loaded: false} | ||
} | ||
|
||
// Initialize is initializing a new .todos.json file. | ||
func (f *FileStore) Initialize() { | ||
if f.FileLocation == "" { | ||
f.FileLocation = ".todos.json" | ||
} | ||
|
||
_, err := ioutil.ReadFile(f.FileLocation) | ||
if err == nil { | ||
if f.LocalTodosFileExists() { | ||
fmt.Println("It looks like a .todos.json file already exists! Doing nothing.") | ||
os.Exit(0) | ||
} | ||
if err := ioutil.WriteFile(f.FileLocation, []byte("[]"), 0644); err != nil { | ||
if err := ioutil.WriteFile(FILENAME, []byte("[]"), 0644); err != nil { | ||
fmt.Println("Error writing json file", err) | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
// Load is loading a .todos.json file. | ||
func (f *FileStore) Load() ([]*Todo, error) { | ||
if f.FileLocation == "" { | ||
f.FileLocation = f.GetLocation() | ||
// Returns if a local .todos.json file exists in the current dir. | ||
func (f *FileStore) LocalTodosFileExists() bool { | ||
dir, _ := os.Getwd() | ||
localrepo := fmt.Sprintf("%s/.todos.json", dir) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep it would. |
||
_, err := os.Stat(localrepo) | ||
if err != nil { | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
data, err := ioutil.ReadFile(f.FileLocation) | ||
// Load is loading a .todos.json file, either from cwd, or the home directory | ||
func (f *FileStore) Load() ([]*Todo, error) { | ||
data, err := ioutil.ReadFile(f.GetLocation()) | ||
if err != nil { | ||
fmt.Println("No todo file found!") | ||
fmt.Println("Initialize a new todo repo by running 'ultralist init'") | ||
|
@@ -71,20 +75,15 @@ func (f *FileStore) Save(todos []*Todo) { | |
} | ||
|
||
data, _ := json.Marshal(todos) | ||
if err := ioutil.WriteFile(f.FileLocation, []byte(data), 0644); err != nil { | ||
if err := ioutil.WriteFile(FILENAME, []byte(data), 0644); err != nil { | ||
fmt.Println("Error writing json file", err) | ||
} | ||
} | ||
|
||
// GetLocation is returning the location of the .todos.json file. | ||
func (f *FileStore) GetLocation() string { | ||
dir, _ := os.Getwd() | ||
localrepo := fmt.Sprintf("%s/.todos.json", dir) | ||
_, ferr := os.Stat(localrepo) | ||
if ferr == nil { | ||
return localrepo | ||
if f.LocalTodosFileExists() { | ||
return FILENAME | ||
} | ||
|
||
home := UserHomeDir() | ||
return fmt.Sprintf("%s/.todos.json", home) | ||
return fmt.Sprintf("%s/.todos.json", UserHomeDir()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this error isnt strictly true, it is only checking for if the file exists and could contain bad auth keys.
NewBackend(), already check and loads this file, so would a more correct test be.
Side note: If you are using JWT (I dont have a UL account so I am guessing) as the authentication, should we also check to see it is
valid
before trying to use it? or as part of the loadCreds, or a new function checkCreds.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, that's a good catch!
Regarding the JWT, I don't feel strongly about validating, since the request would ultimately fail if they have invalid creds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did try it with just using
backend.Creds
, and it didn't seem to work. idk 🤷There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try with a ~/.config/ultralist/cred.json with
{}
.Also a blank file will cause a panic when NewBackend() tries to parse it.
I was thinking about turning those panics into a log and non-0 exit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure there's a scenario where creds.json would have that info in it though.