Beispiel #1
0
func DownloadProductionVersion() (s string, err error) {
	resp, err := download.Request(download.ProductionVersion)
	if err != nil {
		return
	}

	s, err = LoadVersion(resp.Body)
	resp.Body.Close()
	return
}
Beispiel #2
0
func DownloadChanges(pso2path string, changes []*download.PatchEntry, parallel int) (errs []error) {
	if parallel <= 0 {
		parallel = 1
	}

	changesSize := int64(0)
	for _, e := range changes {
		changesSize += e.Size
	}

	pbar := pb.New64(changesSize)
	pbar.SetUnits(pb.U_BYTES)
	pbar.SetRefreshRate(time.Second / 30)
	pbar.ShowSpeed = true
	pbar.Start()

	queue := make(chan *download.PatchEntry)
	done := make(chan bool)

	errlock := sync.Mutex{}

	complain := func(err error) bool {
		if err != nil {
			errlock.Lock()
			errs = append(errs, err)
			errlock.Unlock()
			return true
		}

		return false
	}

	for i := 0; i < parallel; i++ {
		go func() {
			h := md5.New()

			for {
				e, ok := <-queue
				if !ok {
					break
				}

				filepath := path.Join(pso2path, download.RemoveExtension(e.Path))

				err := os.MkdirAll(path.Dir(filepath), 0777)
				if complain(err) {
					break
				}

				pathUrl, err := e.URL()
				if complain(err) {
					continue
				}

				resp, err := download.Request(pathUrl.String())
				if complain(err) {
					continue
				}

				if resp.StatusCode != 200 {
					complain(errors.New(pathUrl.String() + ": " + resp.Status))
					continue
				}

				if resp.ContentLength >= 0 && resp.ContentLength != e.Size {
					resp.Body.Close()
					complain(errors.New(e.Path + ": invalid file size"))
					continue
				}

				f, err := os.Create(filepath)
				if complain(err) {
					resp.Body.Close()
					continue
				}

				h.Reset()
				n, err := io.Copy(io.MultiWriter(f, h, pbar), resp.Body)

				resp.Body.Close()
				f.Close()

				if !complain(err) {
					if n != e.Size {
						complain(errors.New(pathUrl.String() + ": download finished prematurely"))
					} else if bytes.Compare(h.Sum(nil), e.MD5[:]) != 0 {
						complain(errors.New(pathUrl.String() + ": download hash mismatch"))
					}
				}
			}

			done <- true
		}()
	}

	for _, e := range changes {
		queue <- e
	}
	close(queue)

	for i := 0; i < parallel; i++ {
		<-done
	}

	pbar.Finish()

	return
}
Beispiel #3
0
func DownloadEnglishFiles(pso2path string) (translationChanged bool, err error) {
	resp, err := download.Request(EnglishUpdateURL)
	if err != nil {
		return
	}

	var data struct {
		ItemTimestamp, EnglishTimestamp, TranslationTimestamp int64
		ItemURL, EnglishURL, TranslationURL                   string
	}

	d := json.NewDecoder(resp.Body)
	err = d.Decode(&data)
	resp.Body.Close()

	if err != nil {
		return
	}

	scratch := PathScratch(pso2path)
	itemPath := path.Join(scratch, PathTranslateDll)
	translationPath := path.Join(scratch, PathTranslationBin)
	englishPath := path.Join(scratch, PathEnglishDb)
	rootUrl, _ := url.Parse(EnglishUpdateURL)

	updateEnglishFile := func(path string, timestamp int64, urlStr string) (bool, error) {
		url, err := url.Parse(urlStr)
		if err != nil {
			return false, err
		}

		st, err := os.Stat(path)

		if os.IsNotExist(err) || (err == nil && st.ModTime().Unix() < timestamp) {
			resp, err := download.Request(rootUrl.ResolveReference(url).String())
			if err != nil {
				return false, err
			}

			f, err := os.Create(path)
			if err != nil {
				return false, err
			}

			_, err = io.Copy(f, resp.Body)
			f.Close()
			resp.Body.Close()

			return true, err
		}

		return false, err
	}

	translationChanged, err = updateEnglishFile(englishPath, data.EnglishTimestamp, data.EnglishURL)
	if err != nil {
		return
	}

	_, err = updateEnglishFile(translationPath, data.TranslationTimestamp, data.TranslationURL)
	if err != nil {
		return
	}

	_, err = updateEnglishFile(itemPath, data.ItemTimestamp, data.ItemURL)

	return
}