codename-sendaround/cmd/sendaround/main.go

180 lines
4.5 KiB
Go
Raw Normal View History

2019-07-11 12:00:45 +00:00
package main
import (
"io"
"log"
"os"
"path/filepath"
"github.com/cheggaaa/pb/v3"
"github.com/icedream/sendaround"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
var (
cli = kingpin.New("sendaround", "CLI to send and receive file transfers via the Sendaround service.")
flagServerURL = cli.Flag("url", "The Sendaround server URL.").
URL()
cmdRecv = cli.Command("receive", "Receive a file transfer using a token.").
Alias("recv").
Alias("r")
cmdRecvArgToken = cmdRecv.Arg("token", "The token of the session to connect to. You receive this token directly from the sender or as part of a URL.").
Required().
String()
cmdRecvFlagOutputDirectory = cmdRecv.Flag("output-directory", "The directory to store the downloaded files to. Defaults to current directory.").
Short('o').
Default(".").
ExistingDir()
cmdSend = cli.Command("send", "Send a file.").
Alias("s")
cmdSendArgFiles = cmdSend.Arg("input-file", "The file to be transmitted.").
Required().
ExistingFiles()
)
func main() {
subcmd := kingpin.MustParse(cli.Parse(os.Args[1:]))
cfg := new(sendaround.SendaroundClientConfiguration)
if flagServerURL != nil {
cfg.ServerURL = *flagServerURL
}
c := sendaround.NewSendaroundClient(cfg)
switch subcmd {
case cmdRecv.FullCommand():
conn, err := c.Receive(*cmdRecvArgToken)
if err != nil {
log.Fatal(err)
return
}
defer conn.Close()
connectLoop:
for state := range conn.StateC() {
switch state.Type {
case sendaround.Failed:
log.Fatal("Failed:", state.Error)
return
case sendaround.Disconnected:
log.Fatal("Early disconnect, aborting.")
return
case sendaround.Connected:
break connectLoop
}
}
pbars := map[string]*pb.ProgressBar{}
files := conn.Files()
for _, f := range files {
bar := pb.New64(int64(f.Length()))
bar.Set(pb.Bytes, true)
bar.Set("prefix", f.FileName()+": ")
pbars[f.FileName()] = bar
}
go func() {
for state := range conn.StateC() {
switch state.Type {
case sendaround.TransmittingFile:
if !pbars[state.CurrentFile.FileName()].IsStarted() {
pbars[state.CurrentFile.FileName()].Start()
}
pbars[state.CurrentFile.FileName()].SetCurrent(int64(state.TransmittedLength))
case sendaround.Connected:
if state.CurrentFile != nil { // Was a file transferred successfully just now?
if state.TransmittedLength == state.CurrentFile.Length() {
pbars[state.CurrentFile.FileName()].Finish()
}
2019-07-11 12:00:45 +00:00
}
case sendaround.Failed:
log.Fatal(state.Error)
return
}
}
}()
for filePath, f := range files {
r, err := conn.RetrieveFile(filePath)
if err != nil {
log.Fatal(err)
return
}
ofPath := filepath.Join(*cmdRecvFlagOutputDirectory, filepath.FromSlash(f.FileName()))
of, err := os.Create(ofPath)
if err != nil {
log.Fatal(err)
return
}
defer of.Close()
_, err = io.Copy(of, r)
if err != nil {
log.Fatal(err)
return
}
}
case cmdSend.FullCommand():
log.Println("Preparing offer...")
conn, err := c.Offer()
if err != nil {
log.Fatal(err)
return
}
defer conn.Close()
log.Println("")
log.Println("=============================")
log.Printf("Token: %s", conn.Token())
log.Printf("URL: %s", conn.URL())
log.Println("=============================")
log.Println("")
pbars := map[string]*pb.ProgressBar{}
for _, inputFilePath := range *cmdSendArgFiles {
f, err := os.Open(inputFilePath)
if err != nil {
log.Fatal(err)
return
}
rf, err := sendaround.FileFromFilesystem(f, "")
if err != nil {
log.Fatal(err)
return
}
err = conn.AddFile(rf)
if err != nil {
log.Fatal(err)
return
}
log.Printf("%s will be transmitted as %s", f.Name(), rf.FileName())
bar := pb.New64(int64(rf.Length()))
bar.Set(pb.Bytes, true)
bar.Set("prefix", rf.FileName()+": ")
pbars[rf.FileName()] = bar
}
log.Println("Now waiting for client...")
for state := range conn.StateC() {
switch state.Type {
case sendaround.TransmittingFile:
if !pbars[state.CurrentFile.FileName()].IsStarted() {
pbars[state.CurrentFile.FileName()].Start()
}
pbars[state.CurrentFile.FileName()].SetCurrent(int64(state.TransmittedLength))
case sendaround.Connected:
if state.CurrentFile != nil { // Was a file transferred successfully just now?
if state.TransmittedLength == state.CurrentFile.Length() {
pbars[state.CurrentFile.FileName()].Finish()
}
2019-07-11 12:00:45 +00:00
}
case sendaround.Failed:
log.Fatal("Failed:", state.Error)
return
}
}
}
}