2018-01-28 14:55:43 +08:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
2018-05-19 23:43:15 +08:00
|
|
|
"errors"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
2018-04-28 22:02:36 +08:00
|
|
|
nurl "net/url"
|
2018-03-03 17:50:54 +08:00
|
|
|
"os"
|
2018-04-28 22:02:36 +08:00
|
|
|
"os/exec"
|
2018-05-19 23:43:15 +08:00
|
|
|
fp "path/filepath"
|
2018-04-28 22:02:36 +08:00
|
|
|
"runtime"
|
2018-05-19 23:43:15 +08:00
|
|
|
"strconv"
|
2018-04-28 22:02:36 +08:00
|
|
|
"strings"
|
2018-05-19 23:43:15 +08:00
|
|
|
"time"
|
2018-03-03 17:50:54 +08:00
|
|
|
|
2018-01-28 14:55:43 +08:00
|
|
|
"github.com/fatih/color"
|
2018-01-31 11:59:27 +08:00
|
|
|
"golang.org/x/crypto/ssh/terminal"
|
2018-01-28 14:55:43 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
cIndex = color.New(color.FgHiCyan)
|
|
|
|
cSymbol = color.New(color.FgHiMagenta)
|
|
|
|
cTitle = color.New(color.FgHiGreen).Add(color.Bold)
|
|
|
|
cReadTime = color.New(color.FgHiMagenta)
|
|
|
|
cURL = color.New(color.FgHiYellow)
|
|
|
|
cError = color.New(color.FgHiRed)
|
|
|
|
cExcerpt = color.New(color.FgHiWhite)
|
|
|
|
cTag = color.New(color.FgHiBlue)
|
2018-05-19 23:43:15 +08:00
|
|
|
|
|
|
|
errInvalidIndex = errors.New("Index is not valid")
|
2018-01-28 14:55:43 +08:00
|
|
|
)
|
2018-01-31 11:59:27 +08:00
|
|
|
|
2018-04-28 22:02:36 +08:00
|
|
|
func normalizeSpace(str string) string {
|
|
|
|
return strings.Join(strings.Fields(str), " ")
|
|
|
|
}
|
|
|
|
|
2018-05-19 23:43:15 +08:00
|
|
|
func clearUTMParams(url *nurl.URL) {
|
2018-04-28 22:02:36 +08:00
|
|
|
newQuery := nurl.Values{}
|
|
|
|
for key, value := range url.Query() {
|
2018-05-19 23:43:15 +08:00
|
|
|
if !strings.HasPrefix(key, "utm_") {
|
|
|
|
newQuery[key] = value
|
2018-04-28 22:02:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
url.RawQuery = newQuery.Encode()
|
2018-05-19 23:43:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func downloadFile(url, dstPath string, timeout time.Duration) error {
|
|
|
|
// Fetch data from URL
|
|
|
|
client := &http.Client{Timeout: timeout}
|
|
|
|
resp, err := client.Get(url)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
// Make sure destination directory exist
|
|
|
|
err = os.MkdirAll(fp.Dir(dstPath), os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create destination file
|
|
|
|
dst, err := os.Create(dstPath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer dst.Close()
|
|
|
|
|
|
|
|
// Write response body to the file
|
|
|
|
_, err = io.Copy(dst, resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2018-04-28 22:02:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// openBrowser tries to open the URL in a browser,
|
|
|
|
// and returns whether it succeed in doing so.
|
|
|
|
func openBrowser(url string) error {
|
|
|
|
var args []string
|
|
|
|
switch runtime.GOOS {
|
|
|
|
case "darwin":
|
|
|
|
args = []string{"open"}
|
|
|
|
case "windows":
|
|
|
|
args = []string{"cmd", "/c", "start"}
|
|
|
|
default:
|
|
|
|
args = []string{"xdg-open"}
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd := exec.Command(args[0], append(args[1:], url)...)
|
|
|
|
return cmd.Run()
|
|
|
|
}
|
|
|
|
|
2018-05-19 23:43:15 +08:00
|
|
|
// parseIndexList converts a list of indices to their integer values
|
|
|
|
func parseIndexList(indices []string) ([]int, error) {
|
|
|
|
var listIndex []int
|
|
|
|
for _, strIndex := range indices {
|
|
|
|
if !strings.Contains(strIndex, "-") {
|
|
|
|
index, err := strconv.Atoi(strIndex)
|
|
|
|
if err != nil || index < 1 {
|
|
|
|
return nil, errInvalidIndex
|
|
|
|
}
|
|
|
|
|
|
|
|
listIndex = append(listIndex, index)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
parts := strings.Split(strIndex, "-")
|
|
|
|
if len(parts) != 2 {
|
|
|
|
return nil, errInvalidIndex
|
|
|
|
}
|
|
|
|
|
|
|
|
minIndex, errMin := strconv.Atoi(parts[0])
|
|
|
|
maxIndex, errMax := strconv.Atoi(parts[1])
|
|
|
|
if errMin != nil || errMax != nil || minIndex < 1 || minIndex > maxIndex {
|
|
|
|
return nil, errInvalidIndex
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := minIndex; i <= maxIndex; i++ {
|
|
|
|
listIndex = append(listIndex, i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return listIndex, nil
|
|
|
|
}
|
|
|
|
|
2018-01-31 11:59:27 +08:00
|
|
|
func getTerminalWidth() int {
|
|
|
|
width, _, _ := terminal.GetSize(int(os.Stdin.Fd()))
|
|
|
|
return width
|
|
|
|
}
|
2018-02-11 22:00:56 +08:00
|
|
|
|
|
|
|
func checkError(err error) {
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|