aboutsummaryrefslogtreecommitdiffstats
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/cli.go307
1 files changed, 307 insertions, 0 deletions
diff --git a/cli/cli.go b/cli/cli.go
new file mode 100644
index 0000000..d78c838
--- /dev/null
+++ b/cli/cli.go
@@ -0,0 +1,307 @@
+package cli
+
+import (
+ "fmt"
+ "os"
+ "io"
+ "path/filepath"
+ "strings"
+ "code.google.com/p/google-api-go-client/drive/v2"
+ "../util"
+ "../gdrive"
+)
+
+func List(d *gdrive.Drive, query, titleFilter string, maxResults int, sharedStatus bool) {
+ caller := d.Files.List()
+
+ if maxResults > 0 {
+ caller.MaxResults(int64(maxResults))
+ }
+
+ if titleFilter != "" {
+ q := fmt.Sprintf("title contains '%s'", titleFilter)
+ caller.Q(q)
+ }
+
+ if query != "" {
+ caller.Q(query)
+ }
+
+ list, err := caller.Do()
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+
+ items := make([]map[string]string, 0, 0)
+
+ for _, f := range list.Items {
+ // Skip files that dont have a download url (they are not stored on google drive)
+ if f.DownloadUrl == "" {
+ continue
+ }
+
+ items = append(items, map[string]string{
+ "Id": f.Id,
+ "Title": util.TruncateString(f.Title, 40),
+ "Size": util.FileSizeFormat(f.FileSize),
+ "Created": util.ISODateToLocal(f.CreatedDate),
+ })
+ }
+
+ columnOrder := []string{"Id", "Title", "Size", "Created"}
+
+ if sharedStatus {
+ addSharedStatus(d, items)
+ columnOrder = append(columnOrder, "Shared")
+ }
+
+ util.PrintColumns(items, columnOrder, 3)
+}
+
+// Adds the key-value-pair 'Shared: True/False' to the map
+func addSharedStatus(d *gdrive.Drive, items []map[string]string) {
+ // Limit to 10 simultaneous requests
+ active := make(chan bool, 10)
+ done := make(chan bool)
+
+ // Closure that performs the check
+ checkStatus := func(item map[string]string) {
+ // Wait for an empty spot in the active queue
+ active <- true
+
+ // Perform request
+ shared := isShared(d, item["Id"])
+ item["Shared"] = util.FormatBool(shared)
+
+ // Decrement the active queue and notify that we are done
+ <-active
+ done <- true
+ }
+
+ // Go, go, go!
+ for _, item := range items {
+ go checkStatus(item)
+ }
+
+ // Wait for all goroutines to finish
+ for i := 0; i < len(items); i++ {
+ <-done
+ }
+}
+
+func Info(d *gdrive.Drive, fileId string) {
+ info, err := d.Files.Get(fileId).Do()
+ if err != nil {
+ fmt.Printf("An error occurred: %v\n", err)
+ return
+ }
+ printInfo(d, info)
+}
+
+func printInfo(d *gdrive.Drive, f *drive.File) {
+ fields := map[string]string{
+ "Id": f.Id,
+ "Title": f.Title,
+ "Description": f.Description,
+ "Size": util.FileSizeFormat(f.FileSize),
+ "Created": util.ISODateToLocal(f.CreatedDate),
+ "Modified": util.ISODateToLocal(f.ModifiedDate),
+ "Owner": strings.Join(f.OwnerNames, ", "),
+ "Md5sum": f.Md5Checksum,
+ "Shared": util.FormatBool(isShared(d, f.Id)),
+ }
+
+ order := []string{"Id", "Title", "Description", "Size", "Created", "Modified", "Owner", "Md5sum", "Shared"}
+ util.Print(fields, order)
+}
+
+// Upload file to drive
+func Upload(d *gdrive.Drive, input io.ReadCloser, title string, share bool) {
+ // Use filename or 'untitled' as title if no title is specified
+ if title == "" {
+ if f, ok := input.(*os.File); ok && input != os.Stdin {
+ title = filepath.Base(f.Name())
+ } else {
+ title = "untitled"
+ }
+ }
+
+ metadata := &drive.File{Title: title}
+ getRate := util.MeasureTransferRate()
+
+ info, err := d.Files.Insert(metadata).Media(input).Do()
+ if err != nil {
+ fmt.Printf("An error occurred uploading the document: %v\n", err)
+ return
+ }
+
+ // Total bytes transferred
+ bytes := info.FileSize
+
+ // Print information about uploaded file
+ printInfo(d, info)
+ fmt.Printf("Uploaded '%s' at %s, total %s\n", info.Title, getRate(bytes), util.FileSizeFormat(bytes))
+
+ // Share file if the share flag was provided
+ if share {
+ Share(d, info.Id)
+ }
+}
+
+func DownloadLatest(d *gdrive.Drive, stdout bool) {
+ list, err := d.Files.List().Do()
+
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+
+ if len(list.Items) == 0 {
+ fmt.Println("No files found")
+ return
+ }
+
+ latestId := list.Items[0].Id
+ Download(d, latestId, stdout, true)
+}
+
+// Download file from drive
+func Download(d *gdrive.Drive, fileId string, stdout, deleteAfterDownload bool) {
+ // Get file info
+ info, err := d.Files.Get(fileId).Do()
+ if err != nil {
+ fmt.Printf("An error occurred: %v\n", err)
+ return
+ }
+
+ if info.DownloadUrl == "" {
+ // If there is no DownloadUrl, there is no body
+ fmt.Println("An error occurred: File is not downloadable")
+ return
+ }
+
+ // Measure transfer rate
+ getRate := util.MeasureTransferRate()
+
+ // GET the download url
+ res, err := d.Client().Get(info.DownloadUrl)
+ if err != nil {
+ fmt.Printf("An error occurred: %v\n", err)
+ return
+ }
+
+ // Close body on function exit
+ defer res.Body.Close()
+
+ if err != nil {
+ fmt.Printf("An error occurred: %v\n", err)
+ return
+ }
+
+ // Write file content to stdout
+ if stdout {
+ io.Copy(os.Stdout, res.Body)
+ return
+ }
+
+ // Check if file exists
+ if util.FileExists(info.Title) {
+ fmt.Printf("An error occurred: '%s' already exists\n", info.Title)
+ return
+ }
+
+ // Create a new file
+ outFile, err := os.Create(info.Title)
+ if err != nil {
+ fmt.Printf("An error occurred: %v\n", err)
+ return
+ }
+
+ // Close file on function exit
+ defer outFile.Close()
+
+ // Save file to disk
+ bytes, err := io.Copy(outFile, res.Body)
+ if err != nil {
+ fmt.Printf("An error occurred: %v")
+ return
+ }
+
+ fmt.Printf("Downloaded '%s' at %s, total %s\n", info.Title, getRate(bytes), util.FileSizeFormat(bytes))
+
+ if deleteAfterDownload {
+ Delete(d, fileId)
+ }
+}
+
+// Delete file with given file id
+func Delete(d *gdrive.Drive, fileId string) {
+ info, err := d.Files.Get(fileId).Do()
+ if err != nil {
+ fmt.Printf("An error occurred: %v\n", err)
+ return
+ }
+
+ if err = d.Files.Delete(fileId).Do(); err != nil {
+ fmt.Printf("An error occurred: %v\n", err)
+ return
+ }
+
+ fmt.Printf("Removed file '%s'\n", info.Title)
+}
+
+// Make given file id readable by anyone -- auth not required to view/download file
+func Share(d *gdrive.Drive, fileId string) {
+ info, err := d.Files.Get(fileId).Do()
+ if err != nil {
+ fmt.Printf("An error occurred: %v\n", err)
+ return
+ }
+
+ perm := &drive.Permission{
+ Value: "me",
+ Type: "anyone",
+ Role: "reader",
+ }
+
+ _, err = d.Permissions.Insert(fileId, perm).Do()
+ if err != nil {
+ fmt.Printf("An error occurred: %v\n", err)
+ return
+ }
+
+ fmt.Printf("File '%s' is now readable by everyone @ %s\n", info.Title, util.PreviewUrl(fileId))
+}
+
+// Removes the 'anyone' permission -- auth will be required to view/download file
+func Unshare(d *gdrive.Drive, fileId string) {
+ info, err := d.Files.Get(fileId).Do()
+ if err != nil {
+ fmt.Printf("An error occurred: %v\n", err)
+ return
+ }
+
+ err = d.Permissions.Delete(fileId, "anyone").Do()
+ if err != nil {
+ fmt.Printf("An error occurred: %v\n", err)
+ return
+ }
+
+ fmt.Printf("File '%s' is now longer shared to 'anyone'\n", info.Title)
+}
+
+func isShared(d *gdrive.Drive, fileId string) bool {
+ r, err := d.Permissions.List(fileId).Do()
+ if err != nil {
+ fmt.Printf("An error occurred: %v\n", err)
+ return false
+ }
+
+ for _, perm := range r.Items {
+ if perm.Type == "anyone" {
+ return true
+ }
+ }
+ return false
+}