Compare commits
	
		
			11 Commits
		
	
	
		
			v0.0.4
			...
			099b0cd849
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 099b0cd849 | |||
| c9c00e0072 | |||
| b2ffb2062a | |||
| 2e8c825fff | |||
| 7b870950d1 | |||
| 3a877c41a4 | |||
| 04fb390bee | |||
| 50b17d3266 | |||
| 763d408405 | |||
| fbb7cd9bc1 | |||
| f1b7f70313 | 
							
								
								
									
										96
									
								
								api/fs.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								api/fs.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	"go.arsenm.dev/itd/internal/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (c *Client) Rename(old, new string) error {
 | 
			
		||||
	_, err := c.request(types.Request{
 | 
			
		||||
		Type: types.ReqTypeFS,
 | 
			
		||||
		Data: types.ReqDataFS{
 | 
			
		||||
			Type:  types.FSTypeMove,
 | 
			
		||||
			Files: []string{old, new},
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) Remove(paths ...string) error {
 | 
			
		||||
	_, err := c.request(types.Request{
 | 
			
		||||
		Type: types.ReqTypeFS,
 | 
			
		||||
		Data: types.ReqDataFS{
 | 
			
		||||
			Type:  types.FSTypeDelete,
 | 
			
		||||
			Files: paths,
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) Mkdir(paths ...string) error {
 | 
			
		||||
	_, err := c.request(types.Request{
 | 
			
		||||
		Type: types.ReqTypeFS,
 | 
			
		||||
		Data: types.ReqDataFS{
 | 
			
		||||
			Type:  types.FSTypeMkdir,
 | 
			
		||||
			Files: paths,
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) ReadDir(path string) ([]types.FileInfo, error) {
 | 
			
		||||
	res, err := c.request(types.Request{
 | 
			
		||||
		Type: types.ReqTypeFS,
 | 
			
		||||
		Data: types.ReqDataFS{
 | 
			
		||||
			Type:  types.FSTypeList,
 | 
			
		||||
			Files: []string{path},
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	var out []types.FileInfo
 | 
			
		||||
	err = mapstructure.Decode(res.Value, &out)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) ReadFile(path string) (string, error) {
 | 
			
		||||
	res, err := c.request(types.Request{
 | 
			
		||||
		Type: types.ReqTypeFS,
 | 
			
		||||
		Data: types.ReqDataFS{
 | 
			
		||||
			Type:  types.FSTypeRead,
 | 
			
		||||
			Files: []string{path},
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return res.Value.(string), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) WriteFile(path, data string) error {
 | 
			
		||||
	_, err := c.request(types.Request{
 | 
			
		||||
		Type: types.ReqTypeFS,
 | 
			
		||||
		Data: types.ReqDataFS{
 | 
			
		||||
			Type:  types.FSTypeWrite,
 | 
			
		||||
			Files: []string{path},
 | 
			
		||||
			Data:  data,
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								cmd/itctl/filesystem/filesystem.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								cmd/itctl/filesystem/filesystem.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
/*
 | 
			
		||||
 *	itd uses bluetooth low energy to communicate with InfiniTime devices
 | 
			
		||||
 *	Copyright (C) 2021 Arsen Musayelyan
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 *	it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *	the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 *	(at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *	GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *	You should have received a copy of the GNU General Public License
 | 
			
		||||
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package filesystem
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"go.arsenm.dev/itd/cmd/itctl/root"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// filesystemCmd represents the get command
 | 
			
		||||
var filesystemCmd = &cobra.Command{
 | 
			
		||||
	Use:   "filesystem",
 | 
			
		||||
	Aliases: []string{"fs"},
 | 
			
		||||
	Short: "Perform filesystem operations on the PineTime",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	root.RootCmd.AddCommand(filesystemCmd)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										56
									
								
								cmd/itctl/filesystem/list.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								cmd/itctl/filesystem/list.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
			
		||||
/*
 | 
			
		||||
 *	itd uses bluetooth low energy to communicate with InfiniTime devices
 | 
			
		||||
 *	Copyright (C) 2021 Arsen Musayelyan
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 *	it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *	the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 *	(at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *	GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *	You should have received a copy of the GNU General Public License
 | 
			
		||||
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package filesystem
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/rs/zerolog/log"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
	"go.arsenm.dev/itd/api"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// listCmd represents the heart command
 | 
			
		||||
var listCmd = &cobra.Command{
 | 
			
		||||
	Use:     "list [path]",
 | 
			
		||||
	Aliases: []string{"ls"},
 | 
			
		||||
	Short:   "List a directory",
 | 
			
		||||
	Run: func(cmd *cobra.Command, args []string) {
 | 
			
		||||
		dirPath := "/"
 | 
			
		||||
		if len(args) > 0 {
 | 
			
		||||
			dirPath = args[0]
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		client := viper.Get("client").(*api.Client)
 | 
			
		||||
 | 
			
		||||
		listing, err := client.ReadDir(dirPath)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal().Err(err).Msg("Error getting directory listing")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, entry := range listing {
 | 
			
		||||
			fmt.Println(entry)
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	filesystemCmd.AddCommand(listCmd)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								cmd/itctl/filesystem/mkdir.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								cmd/itctl/filesystem/mkdir.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
/*
 | 
			
		||||
 *	itd uses bluetooth low energy to communicate with InfiniTime devices
 | 
			
		||||
 *	Copyright (C) 2021 Arsen Musayelyan
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 *	it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *	the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 *	(at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *	GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *	You should have received a copy of the GNU General Public License
 | 
			
		||||
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package filesystem
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/rs/zerolog/log"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
	"go.arsenm.dev/itd/api"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// heartCmd represents the heart command
 | 
			
		||||
var mkdirCmd = &cobra.Command{
 | 
			
		||||
	Use:   "mkdir <path...>",
 | 
			
		||||
	Short: "Create a new directory",
 | 
			
		||||
	Run: func(cmd *cobra.Command, args []string) {
 | 
			
		||||
		if len(args) < 1 {
 | 
			
		||||
			cmd.Usage()
 | 
			
		||||
			log.Fatal().Msg("Command mkdir requires one or more arguments")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		client := viper.Get("client").(*api.Client)
 | 
			
		||||
 | 
			
		||||
		err := client.Mkdir(args...)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal().Err(err).Msg("Error creating directory")
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	filesystemCmd.AddCommand(mkdirCmd)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								cmd/itctl/filesystem/move.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								cmd/itctl/filesystem/move.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
/*
 | 
			
		||||
 *	itd uses bluetooth low energy to communicate with InfiniTime devices
 | 
			
		||||
 *	Copyright (C) 2021 Arsen Musayelyan
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 *	it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *	the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 *	(at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *	GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *	You should have received a copy of the GNU General Public License
 | 
			
		||||
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package filesystem
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/rs/zerolog/log"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
	"go.arsenm.dev/itd/api"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// heartCmd represents the heart command
 | 
			
		||||
var moveCmd = &cobra.Command{
 | 
			
		||||
	Use:     "move <old> <new>",
 | 
			
		||||
	Aliases: []string{"mv"},
 | 
			
		||||
	Short:   "Move a file or directory",
 | 
			
		||||
	Run: func(cmd *cobra.Command, args []string) {
 | 
			
		||||
		if len(args) != 2 {
 | 
			
		||||
			cmd.Usage()
 | 
			
		||||
			log.Fatal().Msg("Command move requires two arguments")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		client := viper.Get("client").(*api.Client)
 | 
			
		||||
 | 
			
		||||
		err := client.Rename(args[0], args[1])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal().Err(err).Msg("Error moving file or directory")
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	filesystemCmd.AddCommand(moveCmd)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										69
									
								
								cmd/itctl/filesystem/read.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								cmd/itctl/filesystem/read.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
/*
 | 
			
		||||
 *	itd uses bluetooth low energy to communicate with InfiniTime devices
 | 
			
		||||
 *	Copyright (C) 2021 Arsen Musayelyan
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 *	it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *	the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 *	(at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *	GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *	You should have received a copy of the GNU General Public License
 | 
			
		||||
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package filesystem
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/rs/zerolog/log"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
	"go.arsenm.dev/itd/api"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// heartCmd represents the heart command
 | 
			
		||||
var readCmd = &cobra.Command{
 | 
			
		||||
	Use:   `read <remote path> <local path | "-">`,
 | 
			
		||||
	Short: "Read a file from InfiniTime",
 | 
			
		||||
	Run: func(cmd *cobra.Command, args []string) {
 | 
			
		||||
		if len(args) != 2 {
 | 
			
		||||
			cmd.Usage()
 | 
			
		||||
			log.Fatal().Msg("Command read requires two arguments")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		start := time.Now()
 | 
			
		||||
		client := viper.Get("client").(*api.Client)
 | 
			
		||||
 | 
			
		||||
		data, err := client.ReadFile(args[0])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal().Err(err).Msg("Error moving file or directory")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var out *os.File
 | 
			
		||||
		if args[1] == "-" {
 | 
			
		||||
			out = os.Stdout
 | 
			
		||||
		} else {
 | 
			
		||||
			out, err = os.Create(args[1])
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Fatal().Err(err).Msg("Error opening local file")
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		n, err := out.WriteString(data)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal().Err(err).Msg("Error writing to local file")
 | 
			
		||||
		}
 | 
			
		||||
		log.Info().Msgf("Read %d bytes in %s", n, time.Since(start))
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	filesystemCmd.AddCommand(readCmd)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								cmd/itctl/filesystem/remove.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								cmd/itctl/filesystem/remove.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
/*
 | 
			
		||||
 *	itd uses bluetooth low energy to communicate with InfiniTime devices
 | 
			
		||||
 *	Copyright (C) 2021 Arsen Musayelyan
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 *	it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *	the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 *	(at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *	GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *	You should have received a copy of the GNU General Public License
 | 
			
		||||
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package filesystem
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/rs/zerolog/log"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
	"go.arsenm.dev/itd/api"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// heartCmd represents the heart command
 | 
			
		||||
var removeCmd = &cobra.Command{
 | 
			
		||||
	Use:   "remove <path...>",
 | 
			
		||||
	Aliases: []string{"rm"},
 | 
			
		||||
	Short: "Create a new directory",
 | 
			
		||||
	Run: func(cmd *cobra.Command, args []string) {
 | 
			
		||||
		if len(args) < 1 {
 | 
			
		||||
			cmd.Usage()
 | 
			
		||||
			log.Fatal().Msg("Command mkdir requires one or more arguments")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		client := viper.Get("client").(*api.Client)
 | 
			
		||||
 | 
			
		||||
		err := client.Remove(args...)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal().Err(err).Msg("Error removing file or directory")
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	filesystemCmd.AddCommand(removeCmd)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										72
									
								
								cmd/itctl/filesystem/write.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								cmd/itctl/filesystem/write.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
			
		||||
/*
 | 
			
		||||
 *	itd uses bluetooth low energy to communicate with InfiniTime devices
 | 
			
		||||
 *	Copyright (C) 2021 Arsen Musayelyan
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 *	it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *	the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 *	(at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *	This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *	GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *	You should have received a copy of the GNU General Public License
 | 
			
		||||
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package filesystem
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/rs/zerolog/log"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
	"go.arsenm.dev/itd/api"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// heartCmd represents the heart command
 | 
			
		||||
var writeCmd = &cobra.Command{
 | 
			
		||||
	Use:   `write <local path | "-"> <remote path>`,
 | 
			
		||||
	Short: "Write a file to InfiniTime",
 | 
			
		||||
	Run: func(cmd *cobra.Command, args []string) {
 | 
			
		||||
		if len(args) != 2 {
 | 
			
		||||
			cmd.Usage()
 | 
			
		||||
			log.Fatal().Msg("Command write requires two arguments")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		start := time.Now()
 | 
			
		||||
		client := viper.Get("client").(*api.Client)
 | 
			
		||||
 | 
			
		||||
		var in *os.File
 | 
			
		||||
		if args[0] == "-" {
 | 
			
		||||
			in = os.Stdin
 | 
			
		||||
		} else {
 | 
			
		||||
			fl, err := os.Open(args[0])
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Fatal().Err(err).Msg("Error opening local file")
 | 
			
		||||
			}
 | 
			
		||||
			in = fl
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		data, err := io.ReadAll(in)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal().Err(err).Msg("Error moving file or directory")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err = client.WriteFile(args[1], string(data))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal().Err(err).Msg("Error writing to remote file")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log.Info().Msgf("Wrote %d bytes in %s", len(data), time.Since(start))
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	filesystemCmd.AddCommand(writeCmd)
 | 
			
		||||
}
 | 
			
		||||
@@ -19,6 +19,9 @@
 | 
			
		||||
package firmware
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/cheggaaa/pb/v3"
 | 
			
		||||
	"github.com/rs/zerolog/log"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
@@ -38,6 +41,8 @@ var upgradeCmd = &cobra.Command{
 | 
			
		||||
	Short:   "Upgrade InfiniTime firmware using files or archive",
 | 
			
		||||
	Aliases: []string{"upg"},
 | 
			
		||||
	Run: func(cmd *cobra.Command, args []string) {
 | 
			
		||||
		start := time.Now()
 | 
			
		||||
 | 
			
		||||
		client := viper.Get("client").(*api.Client)
 | 
			
		||||
 | 
			
		||||
		var upgType api.UpgradeType
 | 
			
		||||
@@ -79,6 +84,9 @@ var upgradeCmd = &cobra.Command{
 | 
			
		||||
		}
 | 
			
		||||
		// Finish progress bar
 | 
			
		||||
		bar.Finish()
 | 
			
		||||
 | 
			
		||||
		fmt.Printf("Transferred %d B in %s.\n", bar.Total(), time.Since(start))
 | 
			
		||||
		fmt.Println("Remember to validate the new firmware in the InfiniTime settings.")
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ import (
 | 
			
		||||
	"go.arsenm.dev/itd/cmd/itctl/root"
 | 
			
		||||
	_ "go.arsenm.dev/itd/cmd/itctl/set"
 | 
			
		||||
	_ "go.arsenm.dev/itd/cmd/itctl/watch"
 | 
			
		||||
	_ "go.arsenm.dev/itd/cmd/itctl/filesystem"
 | 
			
		||||
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -134,8 +134,6 @@ func upgradeTab(parent fyne.Window, client *api.Client) *fyne.Container {
 | 
			
		||||
 | 
			
		||||
		// Show progress dialog
 | 
			
		||||
		progressDlg.Show()
 | 
			
		||||
		// Hide progress dialog after completion
 | 
			
		||||
		defer progressDlg.Hide()
 | 
			
		||||
 | 
			
		||||
		for event := range progress {
 | 
			
		||||
			// Set label text to received / total B
 | 
			
		||||
@@ -150,6 +148,24 @@ func upgradeTab(parent fyne.Window, client *api.Client) *fyne.Container {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Hide progress dialog after completion
 | 
			
		||||
		progressDlg.Hide()
 | 
			
		||||
 | 
			
		||||
		// Reset screen to default
 | 
			
		||||
		upgradeTypeSelect.SetSelectedIndex(0)
 | 
			
		||||
		firmwareBtn.SetText("Select firmware (.bin)")
 | 
			
		||||
		initPktBtn.SetText("Select init packet (.dat)")
 | 
			
		||||
		archiveBtn.SetText("Select archive (.zip)")
 | 
			
		||||
		firmwarePath = ""
 | 
			
		||||
		initPktPath = ""
 | 
			
		||||
		archivePath = ""
 | 
			
		||||
 | 
			
		||||
		dialog.NewInformation(
 | 
			
		||||
			"Upgrade Complete",
 | 
			
		||||
			"The firmware was transferred successfully.\nRemember to validate the firmware in InfiniTime settings.",
 | 
			
		||||
			parent,
 | 
			
		||||
		).Show()
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	// Return container containing all elements
 | 
			
		||||
 
 | 
			
		||||
@@ -28,17 +28,21 @@ func init() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setCfgDefaults() {
 | 
			
		||||
	viper.SetDefault("cfg.version", 2)
 | 
			
		||||
 | 
			
		||||
	viper.SetDefault("socket.path", "/tmp/itd/socket")
 | 
			
		||||
 | 
			
		||||
	viper.SetDefault("conn.reconnect", true)
 | 
			
		||||
 | 
			
		||||
	viper.SetDefault("conn.whitelist.enabled", false)
 | 
			
		||||
	viper.SetDefault("conn.whitelist.devices", []string{})
 | 
			
		||||
 | 
			
		||||
	viper.SetDefault("on.connect.notify", true)
 | 
			
		||||
 | 
			
		||||
	viper.SetDefault("on.reconnect.notify", true)
 | 
			
		||||
	viper.SetDefault("on.reconnect.setTime", true)
 | 
			
		||||
 | 
			
		||||
	viper.SetDefault("notifs.translit.use", []string{"eASCII"})
 | 
			
		||||
	viper.SetDefault("notifs.translit.custom", []string{})
 | 
			
		||||
 | 
			
		||||
	viper.SetDefault("notifs.ignore.sender", []string{})
 | 
			
		||||
	viper.SetDefault("notifs.ignore.summary", []string{"InfiniTime"})
 | 
			
		||||
	viper.SetDefault("notifs.ignore.body", []string{})
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							@@ -25,7 +25,7 @@ require (
 | 
			
		||||
	github.com/srwiley/oksvg v0.0.0-20210519022825-9fc0c575d5fe // indirect
 | 
			
		||||
	github.com/srwiley/rasterx v0.0.0-20210519020934-456a8d69b780 // indirect
 | 
			
		||||
	github.com/yuin/goldmark v1.4.1 // indirect
 | 
			
		||||
	go.arsenm.dev/infinitime v0.0.0-20211023042633-53aa6f8a0c72
 | 
			
		||||
	go.arsenm.dev/infinitime v0.0.0-20211123052001-ec1548ec0f30
 | 
			
		||||
	golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect
 | 
			
		||||
	golang.org/x/net v0.0.0-20211011170408-caeb26a5c8c0 // indirect
 | 
			
		||||
	golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								go.sum
									
									
									
									
									
								
							@@ -287,8 +287,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
 | 
			
		||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 | 
			
		||||
github.com/mozillazg/go-pinyin v0.18.0 h1:hQompXO23/0ohH8YNjvfsAITnCQImCiR/Fny8EhIeW0=
 | 
			
		||||
github.com/mozillazg/go-pinyin v0.18.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
 | 
			
		||||
github.com/muka/go-bluetooth v0.0.0-20210812063148-b6c83362e27d h1:EG/xyWjHT19rkUpwsWSkyiCCmyqNwFovr9m10rhyOxU=
 | 
			
		||||
github.com/muka/go-bluetooth v0.0.0-20210812063148-b6c83362e27d/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0=
 | 
			
		||||
github.com/muka/go-bluetooth v0.0.0-20211122080231-b99792bbe62a h1:KxRXeSWoBM5FCPAnSUYxt1qwEzmoH/K7upb4fiSDwdc=
 | 
			
		||||
github.com/muka/go-bluetooth v0.0.0-20211122080231-b99792bbe62a/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0=
 | 
			
		||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
 | 
			
		||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
 | 
			
		||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 | 
			
		||||
@@ -367,8 +367,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
 | 
			
		||||
github.com/yuin/goldmark v1.3.8/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 | 
			
		||||
github.com/yuin/goldmark v1.4.1 h1:/vn0k+RBvwlxEmP5E7SZMqNxPhfMVFEJiykr15/0XKM=
 | 
			
		||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 | 
			
		||||
go.arsenm.dev/infinitime v0.0.0-20211023042633-53aa6f8a0c72 h1:e8kOuL6Jj8ZjJzkGwJ3xqpGG9EhUzfvZk9AlSsm3X1U=
 | 
			
		||||
go.arsenm.dev/infinitime v0.0.0-20211023042633-53aa6f8a0c72/go.mod h1:gaepaueUz4J5FfxuV19B4w5pi+V3mD0LTef50ryxr/Q=
 | 
			
		||||
go.arsenm.dev/infinitime v0.0.0-20211123052001-ec1548ec0f30 h1:nhuJfwWxBxfolMU5go3rBLhvl59HMRIMqEKi405Ja9w=
 | 
			
		||||
go.arsenm.dev/infinitime v0.0.0-20211123052001-ec1548ec0f30/go.mod h1:kNBKxQfqeLUfi13GM6tB1kSvLm8HlZ7PM47AYeJQIiw=
 | 
			
		||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
 | 
			
		||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
 | 
			
		||||
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,10 @@
 | 
			
		||||
package types
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	ReqTypeHeartRate = iota
 | 
			
		||||
	ReqTypeBattLevel
 | 
			
		||||
@@ -15,6 +20,7 @@ const (
 | 
			
		||||
	ReqTypeStepCount
 | 
			
		||||
	ReqTypeWatchStepCount
 | 
			
		||||
	ReqTypeCancel
 | 
			
		||||
	ReqTypeFS
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
@@ -22,6 +28,21 @@ const (
 | 
			
		||||
	UpgradeTypeFiles
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	FSTypeWrite = iota
 | 
			
		||||
	FSTypeRead
 | 
			
		||||
	FSTypeMove
 | 
			
		||||
	FSTypeDelete
 | 
			
		||||
	FSTypeList
 | 
			
		||||
	FSTypeMkdir
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ReqDataFS struct {
 | 
			
		||||
	Type  int      `json:"type"`
 | 
			
		||||
	Files []string `json:"files"`
 | 
			
		||||
	Data  string   `json:"data,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ReqDataFwUpgrade struct {
 | 
			
		||||
	Type  int
 | 
			
		||||
	Files []string
 | 
			
		||||
@@ -56,3 +77,66 @@ type MotionValues struct {
 | 
			
		||||
	Y int16
 | 
			
		||||
	Z int16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FileInfo struct {
 | 
			
		||||
	Name  string `json:"name"`
 | 
			
		||||
	Size  int64  `json:"size"`
 | 
			
		||||
	IsDir bool   `json:"isDir"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fi FileInfo) String() string {
 | 
			
		||||
	var isDirChar rune
 | 
			
		||||
	if fi.IsDir {
 | 
			
		||||
		isDirChar = 'd'
 | 
			
		||||
	} else {
 | 
			
		||||
		isDirChar = '-'
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get human-readable value for file size
 | 
			
		||||
	val, unit := bytesHuman(fi.Size)
 | 
			
		||||
	prec := 0
 | 
			
		||||
	// If value is less than 10, set precision to 1
 | 
			
		||||
	if val < 10 {
 | 
			
		||||
		prec = 1
 | 
			
		||||
	}
 | 
			
		||||
	// Convert float to string
 | 
			
		||||
	valStr := strconv.FormatFloat(val, 'f', prec, 64)
 | 
			
		||||
 | 
			
		||||
	// Return string formatted like so:
 | 
			
		||||
	// -  10 kB file
 | 
			
		||||
	// or:
 | 
			
		||||
	// d   0 B  .
 | 
			
		||||
	return fmt.Sprintf(
 | 
			
		||||
		"%c %3s %-2s %s",
 | 
			
		||||
		isDirChar,
 | 
			
		||||
		valStr,
 | 
			
		||||
		unit,
 | 
			
		||||
		fi.Name,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// bytesHuman returns a human-readable string for
 | 
			
		||||
// the amount of bytes inputted.
 | 
			
		||||
func bytesHuman(b int64) (float64, string) {
 | 
			
		||||
	const unit = 1000
 | 
			
		||||
	// Set possible units prefixes (PineTime flash is 4MB)
 | 
			
		||||
	units := [2]rune{'k', 'M'}
 | 
			
		||||
	// If amount of bytes is less than smallest unit
 | 
			
		||||
	if b < unit {
 | 
			
		||||
		// Return unchanged with unit "B"
 | 
			
		||||
		return float64(b), "B"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	div, exp := int64(unit), 0
 | 
			
		||||
	// Get decimal values and unit prefix index
 | 
			
		||||
	for n := b / unit; n >= unit; n /= unit {
 | 
			
		||||
		div *= unit
 | 
			
		||||
		exp++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create string for full unit
 | 
			
		||||
	unitStr := string([]rune{units[exp], 'B'})
 | 
			
		||||
 | 
			
		||||
	// Return decimal with unit string
 | 
			
		||||
	return float64(b) / float64(div), unitStr
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								itd.toml
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								itd.toml
									
									
									
									
									
								
							@@ -1,13 +1,13 @@
 | 
			
		||||
# This is temporary, it is to show a notice
 | 
			
		||||
# to people still using the old config
 | 
			
		||||
cfg.version = 2
 | 
			
		||||
 | 
			
		||||
[socket]
 | 
			
		||||
    path = "/tmp/itd/socket"
 | 
			
		||||
 | 
			
		||||
[conn]
 | 
			
		||||
    reconnect = true
 | 
			
		||||
 | 
			
		||||
[conn.whitelist]
 | 
			
		||||
    enabled = false
 | 
			
		||||
    devices = []
 | 
			
		||||
 | 
			
		||||
[on.connect]
 | 
			
		||||
    notify = true
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								main.go
									
									
									
									
									
								
							@@ -29,16 +29,15 @@ import (
 | 
			
		||||
var firmwareUpdating = false
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	if viper.GetInt("cfg.version") != 2 {
 | 
			
		||||
		log.Fatal().Msg("Please update your config to the newest format, only v2 configs supported.")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	infinitime.Init()
 | 
			
		||||
	// Cleanly exit after function
 | 
			
		||||
	defer infinitime.Exit()
 | 
			
		||||
 | 
			
		||||
	// Connect to InfiniTime with default options
 | 
			
		||||
	dev, err := infinitime.Connect(&infinitime.Options{
 | 
			
		||||
		AttemptReconnect: viper.GetBool("conn.reconnect"),
 | 
			
		||||
		WhitelistEnabled: viper.GetBool("conn.whitelist.enabled"),
 | 
			
		||||
		Whitelist:        viper.GetStringSlice("conn.whitelist.devices"),
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Error().Err(err).Msg("Error connecting to InfiniTime")
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										109
									
								
								socket.go
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								socket.go
									
									
									
									
									
								
							@@ -22,6 +22,7 @@ import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
@@ -100,6 +101,11 @@ func startSocket(dev *infinitime.Device) error {
 | 
			
		||||
func handleConnection(conn net.Conn, dev *infinitime.Device) {
 | 
			
		||||
	defer conn.Close()
 | 
			
		||||
 | 
			
		||||
	fs, err := dev.FS()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		connErr(conn, 0, nil, "Error getting device filesystem")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create new scanner on connection
 | 
			
		||||
	scanner := bufio.NewScanner(conn)
 | 
			
		||||
	for scanner.Scan() {
 | 
			
		||||
@@ -431,6 +437,109 @@ func handleConnection(conn net.Conn, dev *infinitime.Device) {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			firmwareUpdating = false
 | 
			
		||||
		case types.ReqTypeFS:
 | 
			
		||||
			// If no data, return error
 | 
			
		||||
			if req.Data == nil {
 | 
			
		||||
				connErr(conn, req.Type, nil, "Data required for firmware upgrade request")
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			var reqData types.ReqDataFS
 | 
			
		||||
			// Decode data map to firmware upgrade request data
 | 
			
		||||
			err = mapstructure.Decode(req.Data, &reqData)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				connErr(conn, req.Type, err, "Error decoding request data")
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			switch reqData.Type {
 | 
			
		||||
			case types.FSTypeDelete:
 | 
			
		||||
				for _, file := range reqData.Files {
 | 
			
		||||
					err := fs.Remove(file)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						connErr(conn, req.Type, err, "Error removing file")
 | 
			
		||||
						break
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case types.FSTypeMove:
 | 
			
		||||
				if len(reqData.Files) != 2 {
 | 
			
		||||
					connErr(conn, req.Type, nil, "Move FS command requires an old path and new path in the files list")
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				err := fs.Rename(reqData.Files[0], reqData.Files[1])
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					connErr(conn, req.Type, err, "Error moving file")
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			case types.FSTypeMkdir:
 | 
			
		||||
				for _, file := range reqData.Files {
 | 
			
		||||
					err := fs.Mkdir(file)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						connErr(conn, req.Type, err, "Error creating directory")
 | 
			
		||||
						break
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case types.FSTypeList:
 | 
			
		||||
				if len(reqData.Files) != 1 {
 | 
			
		||||
					connErr(conn, req.Type, nil, "List FS command requires a path to list in the files list")
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				entries, err := fs.ReadDir(reqData.Files[0])
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					connErr(conn, req.Type, err, "Error reading directory")
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				var out []types.FileInfo
 | 
			
		||||
				for _, entry := range entries {
 | 
			
		||||
					info, err := entry.Info()
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						connErr(conn, req.Type, err, "Error getting file info")
 | 
			
		||||
						break
 | 
			
		||||
					}
 | 
			
		||||
					out = append(out, types.FileInfo{
 | 
			
		||||
						Name:  info.Name(),
 | 
			
		||||
						Size:  info.Size(),
 | 
			
		||||
						IsDir: info.IsDir(),
 | 
			
		||||
					})
 | 
			
		||||
				}
 | 
			
		||||
				json.NewEncoder(conn).Encode(types.Response{
 | 
			
		||||
					Type:  req.Type,
 | 
			
		||||
					Value: out,
 | 
			
		||||
				})
 | 
			
		||||
			case types.FSTypeWrite:
 | 
			
		||||
				if len(reqData.Files) != 1 {
 | 
			
		||||
					connErr(conn, req.Type, nil, "Write FS command requires a path to the file to write")
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				file, err := fs.Create(reqData.Files[0], uint32(len(reqData.Data)))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					connErr(conn, req.Type, err, "Error creating file")
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				_, err = file.WriteString(reqData.Data)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					connErr(conn, req.Type, err, "Error writing to file")
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				json.NewEncoder(conn).Encode(types.Response{Type: req.Type})
 | 
			
		||||
			case types.FSTypeRead:
 | 
			
		||||
				if len(reqData.Files) != 1 {
 | 
			
		||||
					connErr(conn, req.Type, nil, "Read FS command requires a path to the file to read")
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				file, err := fs.Open(reqData.Files[0])
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					connErr(conn, req.Type, err, "Error opening file")
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				data, err := io.ReadAll(file)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					connErr(conn, req.Type, err, "Error reading from file")
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				json.NewEncoder(conn).Encode(types.Response{
 | 
			
		||||
					Type:  req.Type,
 | 
			
		||||
					Value: string(data),
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		case types.ReqTypeCancel:
 | 
			
		||||
			if req.Data == nil {
 | 
			
		||||
				connErr(conn, req.Type, nil, "No data provided. Cancel request requires request ID string as data.")
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user