From 51244133e0757bae57d0fda17fd6dbc9c89e2cfc Mon Sep 17 00:00:00 2001 From: Levi Date: Sat, 7 Sep 2024 10:10:39 +0800 Subject: [PATCH] feat: support extension onDone event (#728) --- pkg/download/downloader.go | 1 + pkg/download/extension.go | 23 +++++++++-- pkg/download/extension_test.go | 41 ++++++++++++++++++- .../testdata/extensions/on_done/index.js | 5 +++ .../testdata/extensions/on_done/manifest.json | 16 ++++++++ 5 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 pkg/download/testdata/extensions/on_done/index.js create mode 100644 pkg/download/testdata/extensions/on_done/manifest.json diff --git a/pkg/download/downloader.go b/pkg/download/downloader.go index c8eef3f84..f2db1a5e1 100644 --- a/pkg/download/downloader.go +++ b/pkg/download/downloader.go @@ -761,6 +761,7 @@ func (d *Downloader) watch(task *Task) { d.emit(EventKeyDone, task) d.emit(EventKeyFinally, task, err) d.notifyRunning() + d.triggerOnDone(task) if e, ok := task.Meta.Opts.Extra.(*http.OptsExtra); ok { downloadFilePath := task.Meta.SingleFilepath() diff --git a/pkg/download/extension.go b/pkg/download/extension.go index 642f37b45..89bf1d213 100644 --- a/pkg/download/extension.go +++ b/pkg/download/extension.go @@ -38,7 +38,7 @@ const ( EventOnResolve ActivationEvent = "onResolve" EventOnStart ActivationEvent = "onStart" EventOnError ActivationEvent = "onError" - //EventOnDone ActivationEvent = "onDone" + EventOnDone ActivationEvent = "onDone" ) func (d *Downloader) InstallExtensionByGit(url string) (*Extension, error) { @@ -304,6 +304,17 @@ func (d *Downloader) triggerOnError(task *Task, err error) { ) } +func (d *Downloader) triggerOnDone(task *Task) { + doTrigger(d, + EventOnDone, + task.Meta.Req, + &OnErrorContext{ + Task: NewExtensionTask(d, task), + }, + nil, + ) +} + func doTrigger[T any](d *Downloader, event ActivationEvent, req *base.Request, ctx T, handler func(ext *Extension, gopeed *Instance, ctx T)) error { // init extension global object gopeed := &Instance{ @@ -611,9 +622,9 @@ func (h InstanceEvents) OnError(fn goja.Callable) { h.register(EventOnError, fn) } -//func (h InstanceEvents) OnDone(fn goja.Callable) { -// h.register(HookEventOnDone, fn) -//} +func (h InstanceEvents) OnDone(fn goja.Callable) { + h.register(EventOnDone, fn) +} type ExtensionInfo struct { Identity string `json:"identity"` @@ -687,6 +698,10 @@ type OnErrorContext struct { Error error `json:"error"` } +type OnDoneContext struct { + Task *Task `json:"task"` +} + type ExtensionTask struct { *Task diff --git a/pkg/download/extension_test.go b/pkg/download/extension_test.go index 59707722f..50160e70e 100644 --- a/pkg/download/extension_test.go +++ b/pkg/download/extension_test.go @@ -247,8 +247,45 @@ func TestDownloader_Extension_OnError(t *testing.T) { } // extension on error modify url and continue download task := downloader.GetTask(id) - if task.Meta.Req.URL != "https://github.com" { - t.Fatalf("except url: https://github.com, actual: %s", task.Meta.Req.URL) + if task.Status != base.DownloadStatusDone { + t.Fatalf("except status is done, actual: %s", task.Status) + } + }) +} + +func TestDownloader_Extension_OnDone(t *testing.T) { + setupDownloader(func(downloader *Downloader) { + if _, err := downloader.InstallExtensionByFolder("./testdata/extensions/on_done", false); err != nil { + t.Fatal(err) + } + errCh := make(chan error, 1) + downloader.Listener(func(event *Event) { + if event.Key == EventKeyFinally { + errCh <- event.Err + } + }) + id, err := downloader.CreateDirect(&base.Request{ + URL: "https://github.com", + }, nil) + if err != nil { + t.Fatal(err) + } + select { + case err = <-errCh: + break + case <-time.After(time.Second * 10): + err = errors.New("timeout") + } + // wait for script execution + time.Sleep(time.Millisecond * 3000) + + if err != nil { + panic("extension on done download error: " + err.Error()) + } + // extension on error modify url and continue download + task := downloader.GetTask(id) + if task.Meta.Req.Labels["modified"] != "true" { + t.Fatalf("except label: modified=true, actual: %s", task.Meta.Req.Labels["modified"]) } if task.Status != base.DownloadStatusDone { t.Fatalf("except status is done, actual: %s", task.Status) diff --git a/pkg/download/testdata/extensions/on_done/index.js b/pkg/download/testdata/extensions/on_done/index.js new file mode 100644 index 000000000..3fe8a85e4 --- /dev/null +++ b/pkg/download/testdata/extensions/on_done/index.js @@ -0,0 +1,5 @@ +gopeed.events.onDone(async function (ctx) { + gopeed.logger.info("url", ctx.task.meta.req.url); + ctx.task.meta.req.labels['modified'] = 'true'; +}); + diff --git a/pkg/download/testdata/extensions/on_done/manifest.json b/pkg/download/testdata/extensions/on_done/manifest.json new file mode 100644 index 000000000..eb6e6e60d --- /dev/null +++ b/pkg/download/testdata/extensions/on_done/manifest.json @@ -0,0 +1,16 @@ +{ + "name": "on-done", + "title": "gopeed extension on done event test", + "version": "0.0.1", + "scripts": [ + { + "event": "onDone", + "match": { + "urls": [ + "*://github.com/*" + ] + }, + "entry": "index.js" + } + ] +} \ No newline at end of file