You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

339 lines
7.0 KiB

package main
import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"errors"
"flag"
"fmt"
"github.com/AlecAivazis/survey"
"github.com/tencentyun/cos-go-sdk-v5"
"github.com/wailovet/osmanthuswine/src/helper"
"io/ioutil"
"net/http"
"net/url"
"os"
"os/exec"
"os/user"
"path/filepath"
"runtime"
"strings"
)
var config TencentYunConfig
var op string
var path string
var qpath string
var key string
func loadKey() {
homePath, err := home()
if err != nil {
fmt.Println("错误 102: ", err)
return
}
keyFile := filepath.Join(homePath, ".qcloud-key")
data, _ := ioutil.ReadFile(keyFile)
if string(data) == "" {
fmt.Println("错误 204 找不到key,请使用使用set-key进行初始化.")
return
}
key = string(data)
}
func initKey() {
if key == "" {
fmt.Println("key is empty!")
os.Exit(1)
}
var err error
var dekey []byte
dekey, err = base64.StdEncoding.DecodeString(key)
if err != nil {
fmt.Println("错误 201:", err)
os.Exit(1)
}
dekey, err = helper.DefaultAesDecrypt(dekey)
if err != nil {
fmt.Println("错误 202:", err)
os.Exit(1)
}
err = json.Unmarshal(dekey, &config)
if err != nil {
fmt.Println("错误 203:", err)
os.Exit(1)
}
}
func main() {
helper.AesKey = []byte("3136352472abcdef")
flag.StringVar(&op, "op", "", "操作:make-key[生成密钥] | set-key[设置密钥] | upload [上传文件] | list [获取文件]")
flag.StringVar(&path, "path", "", "上传目录")
flag.StringVar(&qpath, "qpath", "", "云上传目的目录")
flag.StringVar(&key, "key", "", "key")
flag.Parse()
switch op {
case "set-key":
key = askText("输入key")
initKey()
_, err := getTencentYunCosFiles("")
if err != nil {
fmt.Println("key error 101:", err)
return
}
homePath, err := home()
if err != nil {
fmt.Println("错误 102:", err)
return
}
keyFile := filepath.Join(homePath, ".qcloud-key")
err = ioutil.WriteFile(keyFile, []byte(key), 0644)
if err != nil {
fmt.Println("错误 103:", err)
return
}
fmt.Println("完成!")
case "make-key":
config.SecretID = askText("输入SecretID")
config.SecretKey = askText("输入SecretKey")
config.BucketURL = askText("输入BucketURL")
config.Root = askText("输入Root")
mkey, err := helper.DefaultAesEncrypt([]byte(helper.JsonEncode(config)))
if err != nil {
fmt.Println("错误 104:", err)
return
}
mkey = []byte(base64.StdEncoding.EncodeToString(mkey))
fmt.Println("key:", string(mkey), " ==> ", "key.txt")
_ = ioutil.WriteFile("key.txt", mkey, 0644)
os.Exit(0)
case "upload":
loadKey()
initKey()
if path != "" {
url := ""
if qpath == "" {
url = UploadDir(path)
} else {
url = UploadDir(path, qpath)
}
fmt.Println("url:", url)
} else {
flag.Usage()
}
case "list":
loadKey()
initKey()
for {
data, err := getTencentYunCosFiles(path)
if err != nil {
fmt.Println("错误 106:", err)
return
}
//for e := range data.CommonPrefixes {
// fmt.Println(data.CommonPrefixes[e])
//}
var files []string
for e := range data.Contents {
files = append(files, data.Contents[e].Key)
}
_, menu := askSelect("Path:"+path, append([]string{".."}, append(data.CommonPrefixes, files...)...)...)
if menu == ".." {
pathSplit := strings.Split(path, "/")
if len(pathSplit) > 1 {
path = strings.Join(pathSplit[0:len(pathSplit)-1], "/")
} else {
path = ""
}
} else {
path = menu
}
}
default:
flag.Usage()
}
}
type TencentYunConfig struct {
SecretID string
SecretKey string
SessionToken string
BucketURL string
Root string
}
var client *cos.Client
func getTencentYunConf(c *TencentYunConfig) *cos.Client {
if client == nil {
BucketURL, _ := url.Parse(c.BucketURL)
b := &cos.BaseURL{
BucketURL: BucketURL,
}
// 1.永久密钥
client = cos.NewClient(b, &http.Client{
Transport: &cos.AuthorizationTransport{
SecretID: c.SecretID,
SecretKey: c.SecretKey,
},
})
}
return client
}
func getTencentYunCosFiles(prefix string) (*cos.BucketGetResult, error) {
// 1.永久密钥
client := getTencentYunConf(&config)
if prefix == "" {
prefix = strings.Replace(config.Root+"/", `//`, `/`, -1)
}
res, _, err := client.Bucket.Get(context.Background(), &cos.BucketGetOptions{
Prefix: prefix,
Delimiter: "/",
})
if err != nil {
return nil, err
}
return res, nil
}
func UploadDir(fpath string, qpaths ...string) string {
qpath := ""
if len(qpaths) > 0 {
qpath = qpaths[0]
} else {
separator := "/"
if runtime.GOOS == "windows" {
separator = `\`
}
separatordir := strings.Split(fpath, separator)
if len(separatordir) > 0 {
qpath = separatordir[len(separatordir)-1]
}
}
client := getTencentYunConf(&config)
files, _ := ioutil.ReadDir(fpath)
for _, f := range files {
if f.Name()[0] == '.' {
continue
}
if f.IsDir() {
UploadDir(filepath.Join(fpath, f.Name()), filepath.Join(qpath, f.Name()))
} else {
filename := filepath.Join(fpath, f.Name())
fmt.Print("上传:", filename, " ==> ", filepath.Join(config.Root, filename), " ")
_, err := client.Object.PutFromFile(context.Background(), strings.Replace(filepath.Join(config.Root, qpath, f.Name()), `\`, `/`, -1), filename, nil)
if err != nil {
fmt.Println("错误 105:", err)
} else {
fmt.Println("完成")
}
}
}
urlPath := "/" + strings.Replace(filepath.Join(config.Root, qpath), `\`, `/`, -1)
for strings.Index(urlPath, "//") > -1 {
urlPath = strings.Replace(urlPath, "//", "/", -1)
}
return config.BucketURL + urlPath
}
func askSelect(title string, v ...string) (int, string) {
result := -1
prompt := &survey.Select{
Message: title,
Options: v,
}
err := survey.AskOne(prompt, &result)
if err != nil {
return 0, ""
}
if result == -1 {
return askSelect(title, v...)
}
return result, v[result]
}
func askText(title string) string {
result := ""
prompt := &survey.Input{
Message: title,
}
survey.AskOne(prompt, &result)
if result == "" {
fmt.Println("不允许为空")
return askText(title)
}
return result
}
func home() (string, error) {
user, err := user.Current()
if nil == err {
return user.HomeDir, nil
}
// cross compile support
if "windows" == runtime.GOOS {
return homeWindows()
}
// Unix-like system, so just assume Unix
return homeUnix()
}
func homeUnix() (string, error) {
// First prefer the HOME environmental variable
if home := os.Getenv("HOME"); home != "" {
return home, nil
}
// If that fails, try the shell
var stdout bytes.Buffer
cmd := exec.Command("sh", "-c", "eval echo ~$USER")
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {
return "", err
}
result := strings.TrimSpace(stdout.String())
if result == "" {
return "", errors.New("blank output when reading home directory")
}
return result, nil
}
func homeWindows() (string, error) {
drive := os.Getenv("HOMEDRIVE")
path := os.Getenv("HOMEPATH")
home := drive + path
if drive == "" || path == "" {
home = os.Getenv("USERPROFILE")
}
if home == "" {
return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank")
}
return home, nil
}