Skip to content

Commit 54da85e

Browse files
committed
Remote meta download support
1 parent 009bddc commit 54da85e

11 files changed

Lines changed: 659 additions & 164 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ ultupdater.exe
22
*.sqlite*
33
venv
44
test
5-
.idea
5+
.idea
6+
./*.exe

FyneApp.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Website = "https://flashpointarchive.org"
2+
3+
[Details]
4+
Icon = "icon.png"
5+
Name = "Flashpoint Ultimate Updater"
6+
ID = "com.flashpointarchive.ultimate-updater"
7+
Version = "1.0.0"
8+
Build = 2

Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
bundle:
2+
fyne bundle -o bundle.go config.json
3+
4+
build-mac:
5+
fyne package -os darwin
6+
7+
build-linux:
8+
fyne package -os linux
9+
10+
build-win:
11+
fyne package -os windows
12+
13+
build:
14+
fyne package

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Flashpoint Ultimate Updater
2+
3+
## Building
4+
5+
Bundle any resources
6+
7+
`fyne bundle -o bundle.go config.json`
8+
9+
Package for desired operation system
10+
11+
`fyne package -os windows/linux/darwin`

config.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"meta_url": "https://download.unstable.life/ult-index/meta.json"
3+
}

downloader.go

Lines changed: 108 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"fyne.io/fyne/v2/dialog"
1010
"github.com/cavaliergopher/grab/v3"
11+
"github.com/dustin/go-humanize"
1112
"hash/crc32"
1213
"os"
1314
"path/filepath"
@@ -20,6 +21,7 @@ type Update struct {
2021
IndexFile *IndexedFile
2122
Retry bool
2223
RemoveTakenFlag bool
24+
Failure error
2325
Progress float64
2426
Bytes int64
2527
Done bool
@@ -74,6 +76,10 @@ func (d *Downloader) Resume() error {
7476
// Reset context
7577
d.ctx, d.cancel = context.WithCancel(context.Background())
7678

79+
// Reset failure count
80+
d.state.downloadFailures = 0
81+
_ = d.state.formatDownloadFailures.Set("0")
82+
7783
// Set up background
7884
d.reqch = make(chan *grab.Request, 10)
7985
d.respch = make(chan *grab.Response, 4)
@@ -121,19 +127,31 @@ func (d *Downloader) Resume() error {
121127
IndexFile: f,
122128
Retry: false,
123129
RemoveTakenFlag: true,
130+
Failure: nil,
124131
Progress: 1,
125132
Bytes: 0,
126133
Done: true,
127134
}
128135
return
129136
} else {
130-
// Bad download, retry if below 3 retries
131-
if f.RetryCount < 3 {
137+
// Bad download, retry if below 5 retries
138+
if f.RetryCount < 5 {
132139
f.RetryCount += 1
133140
d.updatech <- &Update{
134141
IndexFile: f,
135142
Retry: true,
136143
RemoveTakenFlag: false,
144+
Failure: nil,
145+
Progress: 1,
146+
Bytes: 0,
147+
Done: true,
148+
}
149+
} else {
150+
d.updatech <- &Update{
151+
IndexFile: f,
152+
Retry: false,
153+
RemoveTakenFlag: false,
154+
Failure: err,
137155
Progress: 1,
138156
Bytes: 0,
139157
Done: true,
@@ -146,6 +164,7 @@ func (d *Downloader) Resume() error {
146164
IndexFile: f,
147165
Retry: false,
148166
RemoveTakenFlag: false,
167+
Failure: nil,
149168
Progress: 1,
150169
Bytes: resp.BytesComplete(),
151170
Done: true,
@@ -175,8 +194,10 @@ func (d *Downloader) Resume() error {
175194
// Get next empty dir
176195
dir, err := d.state.Repo.GetNextEmptyDir()
177196
if err != nil {
178-
dialog.NewError(&DatabaseError{err}, d.state.window).Show()
179-
return
197+
if err != sql.ErrNoRows {
198+
dialog.NewError(&DatabaseError{err}, d.state.window).Show()
199+
return
200+
}
180201
}
181202
dest := filepath.Join(d.installPath, dir)
182203
err = os.MkdirAll(dest, os.ModePerm)
@@ -270,6 +291,12 @@ func (d *Downloader) Resume() error {
270291
_ = d.state.fileProgress4.Set(0)
271292

272293
for update := range d.updatech {
294+
// Download failure, maximum retries reached
295+
if update.Failure != nil {
296+
d.state.downloadFailures += 1
297+
_ = d.state.formatDownloadFailures.Set(humanize.Comma(d.state.downloadFailures))
298+
}
299+
273300
// Failed download because of context cancel, remove taken flag instead, ignore ui update
274301
if update.RemoveTakenFlag {
275302
err = d.state.Repo.ClearTaken(update.IndexFile)
@@ -284,6 +311,7 @@ func (d *Downloader) Resume() error {
284311
d.newRequestWg.Add(1)
285312
go func() {
286313
defer d.newRequestWg.Done()
314+
time.Sleep(time.Second * 1) // Retry after 3 seconds
287315
select {
288316
case <-d.ctx.Done():
289317
{
@@ -305,62 +333,68 @@ func (d *Downloader) Resume() error {
305333
}
306334

307335
// Update UI element
308-
updateIdx := -1
309-
for idx, f := range uifiles {
310-
if f.Filepath == update.IndexFile.Filepath {
311-
// Send bytes update to speed handler
312-
bytesDiff := update.Bytes - f.Bytes
313-
speedch <- bytesDiff
314-
// Update ui file
315-
f.Progress = update.Progress
316-
f.Done = update.Done
317-
f.Bytes = update.Bytes
318-
updateIdx = idx
319-
break
320-
}
321-
}
322-
if updateIdx == -1 {
323-
// Didn't find existing entry, find an older one to replace
336+
if update.Failure == nil {
337+
updateIdx := -1
324338
for idx, f := range uifiles {
325-
if f.Done == true {
339+
if f.Filepath == update.IndexFile.Filepath {
326340
// Send bytes update to speed handler
327-
bytesDiff := update.Bytes
341+
bytesDiff := update.Bytes - f.Bytes
328342
speedch <- bytesDiff
329343
// Update ui file
330-
f.Filepath = update.IndexFile.Filepath
331344
f.Progress = update.Progress
332345
f.Done = update.Done
333346
f.Bytes = update.Bytes
334347
updateIdx = idx
335348
break
336349
}
337350
}
338-
}
339-
// If updated ui state, update element
340-
if updateIdx != -1 {
341-
if updateIdx == 0 {
342-
_ = d.state.fileTitle1.Set(update.IndexFile.Filepath)
343-
_ = d.state.fileProgress1.Set(update.Progress)
344-
}
345-
if updateIdx == 1 {
346-
_ = d.state.fileTitle2.Set(update.IndexFile.Filepath)
347-
_ = d.state.fileProgress2.Set(update.Progress)
348-
}
349-
if updateIdx == 2 {
350-
_ = d.state.fileTitle3.Set(update.IndexFile.Filepath)
351-
_ = d.state.fileProgress3.Set(update.Progress)
351+
if updateIdx == -1 {
352+
// Didn't find existing entry, find an older one to replace
353+
for idx, f := range uifiles {
354+
if f.Done == true {
355+
// Send bytes update to speed handler
356+
bytesDiff := update.Bytes
357+
speedch <- bytesDiff
358+
// Update ui file
359+
f.Filepath = update.IndexFile.Filepath
360+
f.Progress = update.Progress
361+
f.Done = update.Done
362+
f.Bytes = update.Bytes
363+
updateIdx = idx
364+
break
365+
}
366+
}
352367
}
353-
if updateIdx == 3 {
354-
_ = d.state.fileTitle4.Set(update.IndexFile.Filepath)
355-
_ = d.state.fileProgress4.Set(update.Progress)
368+
// If updated ui state, update element
369+
if updateIdx != -1 {
370+
if updateIdx == 0 {
371+
_ = d.state.fileTitle1.Set(update.IndexFile.Filepath)
372+
_ = d.state.fileProgress1.Set(update.Progress)
373+
}
374+
if updateIdx == 1 {
375+
_ = d.state.fileTitle2.Set(update.IndexFile.Filepath)
376+
_ = d.state.fileProgress2.Set(update.Progress)
377+
}
378+
if updateIdx == 2 {
379+
_ = d.state.fileTitle3.Set(update.IndexFile.Filepath)
380+
_ = d.state.fileProgress3.Set(update.Progress)
381+
}
382+
if updateIdx == 3 {
383+
_ = d.state.fileTitle4.Set(update.IndexFile.Filepath)
384+
_ = d.state.fileProgress4.Set(update.Progress)
385+
}
356386
}
357387
}
358388

359389
if update.Done {
360-
// Mark as done
361-
err := d.state.Repo.MarkFileDone(update.IndexFile)
362-
if err != nil {
363-
dialog.NewError(&DatabaseError{err}, d.state.window).Show()
390+
if update.Failure == nil {
391+
// Mark as done
392+
d.state.downloadedSize += update.IndexFile.Size
393+
d.state.downloadedFiles += 1
394+
err := d.state.Repo.MarkFileDone(update.IndexFile)
395+
if err != nil {
396+
dialog.NewError(&DatabaseError{err}, d.state.window).Show()
397+
}
364398
}
365399

366400
d.newRequestWg.Add(1)
@@ -392,18 +426,40 @@ func (d *Downloader) Resume() error {
392426
}()
393427

394428
// Update Total Progress bar state
395-
d.state.downloadedSize += update.IndexFile.Size
396-
d.state.downloadedFiles += 1
397429
err = d.state.formatDownloadedSize.Set(FormatBytes(d.state.downloadedSize))
398430
if err != nil {
399431
dialog.NewError(err, d.state.window).Show()
400432
}
433+
err = d.state.formatDownloadedFiles.Set(humanize.Comma(d.state.downloadedFiles))
434+
if err != nil {
435+
dialog.NewError(err, d.state.window).Show()
436+
}
401437
progress := float64(d.state.downloadedSize) / float64(d.state.totalSize)
402438
err = d.state.progressBarTotal.Set(progress)
403439
if err != nil {
404440
dialog.NewError(err, d.state.window).Show()
405441
}
406442

443+
// Check if we're done
444+
totalFiles := d.state.downloadedFiles + d.state.downloadFailures
445+
if totalFiles == d.state.totalFiles {
446+
// Done!
447+
err := d.state.Repo.ClearTakenAll()
448+
d.cancel()
449+
go func() {
450+
d.Stop(true)
451+
if err != nil {
452+
dialog.NewError(&DatabaseError{err}, d.state.window).Show()
453+
} else {
454+
if d.state.downloadFailures > 0 {
455+
dialog.NewInformation("Finished", fmt.Sprintf("Install finished with %d failures, you will have to press start again to retry these failed files.", d.state.downloadFailures), d.state.window).Show()
456+
} else {
457+
dialog.NewInformation("Finished", "Install finished with no failures", d.state.window).Show()
458+
}
459+
}
460+
}()
461+
}
462+
407463
}
408464
}
409465
}()
@@ -423,18 +479,20 @@ func (d *Downloader) Resume() error {
423479
d.reqch <- req
424480
}
425481
d.running = true
426-
d.started = true
482+
_ = d.state.runningLabel.Set("Running")
427483

428484
return nil
429485
}
430486

431-
func (d *Downloader) Stop() {
487+
func (d *Downloader) Stop(skipCancelContext bool) {
432488
if !d.running {
433489
return
434490
}
435491

436492
// Stop new and current requests
437-
d.cancel()
493+
if !skipCancelContext {
494+
d.cancel()
495+
}
438496
d.newRequestWg.Wait()
439497
close(d.reqch)
440498

@@ -448,6 +506,7 @@ func (d *Downloader) Stop() {
448506
d.updaterWg.Wait()
449507

450508
d.running = false
509+
_ = d.state.runningLabel.Set("Stopped")
451510
}
452511

453512
func (d *Downloader) NewRequest(f *IndexedFile) (*grab.Request, error) {

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
require (
1212
fyne.io/systray v1.10.1-0.20230602210930-b6a2d6ca2a7b // indirect
1313
github.com/davecgh/go-spew v1.1.1 // indirect
14+
github.com/dustin/go-humanize v1.0.1 // indirect
1415
github.com/fredbi/uri v0.1.0 // indirect
1516
github.com/fsnotify/fsnotify v1.5.4 // indirect
1617
github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
6868
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6969
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
7070
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
71+
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
72+
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
7173
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
7274
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
7375
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=

0 commit comments

Comments
 (0)