main.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io"
  6. "io/ioutil"
  7. "log"
  8. "net/http"
  9. "os"
  10. "strings"
  11. "sync"
  12. "time"
  13. "github.com/kardianos/osext"
  14. )
  15. // 配置文件
  16. type configuration struct {
  17. Proxy string
  18. }
  19. var G_config configuration
  20. func readConfig() {
  21. folderPath, err := osext.ExecutableFolder()
  22. if err != nil {
  23. log.Fatal(err)
  24. }
  25. // 打开文件
  26. file, err := os.Open(folderPath + "/config.json")
  27. if err != nil {
  28. return
  29. }
  30. // 关闭文件
  31. defer file.Close()
  32. //NewDecoder创建一个从file读取并解码json对象的*Decoder,解码器有自己的缓冲,并可能超前读取部分json数据。
  33. decoder := json.NewDecoder(file)
  34. G_config = configuration{}
  35. //Decode从输入流读取下一个json编码值并保存在v指向的值里
  36. err = decoder.Decode(&G_config)
  37. if err != nil {
  38. fmt.Println("Error:", err)
  39. }
  40. // fmt.Println("proxy:" + G_config.Proxy)
  41. }
  42. // 下载
  43. type people struct {
  44. Tag_name string `json:"tag_name"` //Tag_name 小写变成私有
  45. }
  46. func api_get_version(project string) string {
  47. git_api := "https://api.github.com/repos/" + project + "/releases/latest"
  48. // 目标URL
  49. url := git_api
  50. // 发送HTTP GET请求
  51. resp, err := http.Get(url)
  52. if err != nil {
  53. panic(err)
  54. }
  55. defer resp.Body.Close()
  56. // 读取响应体
  57. body, err := ioutil.ReadAll(resp.Body)
  58. if err != nil {
  59. panic(err)
  60. }
  61. // 解析JSON数据
  62. responseData := people{}
  63. if err := json.Unmarshal(body, &responseData); err != nil {
  64. panic(err)
  65. }
  66. // 打印解析后的数据
  67. // fmt.Println("tag_name:" + responseData.Tag_name)
  68. // latest_version = responseData.tag_name
  69. return responseData.Tag_name
  70. }
  71. type Downloader struct {
  72. io.Reader
  73. Total int64
  74. Current int64
  75. }
  76. func printProgressBar(progress int64, total int64) {
  77. // bar := ""
  78. // numSlashes := progress * 100 / total / 5
  79. // for i := 0; i < numSlashes; i++ {
  80. // bar += "\u2588" // 这是一个完整的块字符
  81. // }
  82. // fmt.Printf("下载进度: [%-21s] %.2f%%\r", bar, float64(progress*100.0/total))
  83. fmt.Printf(" 正在下载:%d / %d bytes (%.2f%%)\r", progress, total, float32(progress*10000/total)/100)
  84. }
  85. func (d *Downloader) Read(p []byte) (n int, err error) {
  86. n, err = d.Reader.Read(p)
  87. d.Current += int64(n)
  88. printProgressBar(d.Current, d.Total)
  89. return
  90. }
  91. func downloadFile(item int, url string, filePath string) {
  92. defer wg.Done()
  93. fmt.Printf("%d.下载%s\n", item, filePath)
  94. resp, err := http.Get(url)
  95. if err != nil {
  96. log.Fatalln(err)
  97. }
  98. defer func() {
  99. _ = resp.Body.Close()
  100. }()
  101. file, err := os.Create(filePath)
  102. if err != nil {
  103. fmt.Println("文件创建失败:", err)
  104. // 其他处理
  105. }
  106. defer func() {
  107. _ = file.Close()
  108. }()
  109. downloader := &Downloader{
  110. Reader: resp.Body,
  111. Total: resp.ContentLength,
  112. }
  113. if _, err := io.Copy(file, downloader); err != nil {
  114. log.Fatalln(err)
  115. }
  116. fmt.Println() // 新的一行以清除进度条打印
  117. }
  118. var wg sync.WaitGroup
  119. func http_down(project string, down_list string, proxy string) {
  120. // fmt.Println(project, down_list, proxy)
  121. // 获取最新版本
  122. latest_version := api_get_version(project)
  123. // 创建文件夹
  124. folderPath := latest_version
  125. err := os.MkdirAll(folderPath, os.ModePerm)
  126. if err != nil {
  127. fmt.Printf("创建文件夹错误: %v\n", err)
  128. return
  129. }
  130. // 分割下载列表
  131. git_down_url := proxy + project + "/releases/download/" + latest_version + "/"
  132. parts := strings.Split(down_list, ",")
  133. task := make(map[string]string)
  134. for i := 0; i < len(parts); i++ {
  135. // 替换
  136. version_str := strings.ReplaceAll(latest_version, "v", "")
  137. version_str = strings.ReplaceAll(version_str, "V", "")
  138. filename := strings.ReplaceAll(parts[i], "[version]", version_str)
  139. // 存入
  140. task[git_down_url+filename] = folderPath + "/" + filename
  141. }
  142. item := 1
  143. for k, v := range task {
  144. wg.Add(1)
  145. downloadFile(item, k, v)
  146. item += 1
  147. }
  148. wg.Wait()
  149. fmt.Println("下载完成")
  150. time.Sleep(1 * time.Second)
  151. }
  152. func main() {
  153. // parser := argparse.NewParser("GitAutoupdater", "这是git最新版本的更新工具")
  154. // name := parser.String("n", "name", &argparse.Options{Required: false, Help: "项目,譬如 fatedier/frp", Default: "fatedier/frp"})
  155. // list := parser.String("l", "list", &argparse.Options{Required: false, Help: "下载列表(1.[version]可替换最新版本 2.用,分割多个文件),譬如 frp_[version]_windows_amd64.zip", Default: "frp_[version]_windows_amd64.zip"})
  156. // proxy := parser.String("p", "proxy", &argparse.Options{Required: false, Help: "代理,譬如 https://ghproxy.com/https://github.com/", Default: "https://github.com/"})
  157. // err := parser.Parse(os.Args)
  158. // if err != nil {
  159. // fmt.Print(parser.Usage(err)) // 帮助 -h or --help
  160. // return
  161. // }
  162. name := ""
  163. list := ""
  164. proxy := "https://github.com/"
  165. for i, num := range os.Args[1:] {
  166. switch i {
  167. case 0:
  168. name = num
  169. case 1:
  170. list = num
  171. case 2:
  172. proxy = num
  173. default:
  174. fmt.Println(`未知参数:`, num)
  175. }
  176. }
  177. // 优先级:命令>配置>默认
  178. readConfig()
  179. if proxy == "https://github.com/" && G_config.Proxy != "" {
  180. proxy = G_config.Proxy
  181. }
  182. fmt.Println("proxy:", proxy)
  183. http_down(name, list, proxy)
  184. }