From 9aca84a923be7da3703713d37d85c8149956958e Mon Sep 17 00:00:00 2001 From: Niko Diamadis Date: Mon, 6 Jan 2025 05:15:38 -0500 Subject: [PATCH 1/4] feat: allow custom F-Droid repo --- services/f-droid/f-droid.service.js | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/services/f-droid/f-droid.service.js b/services/f-droid/f-droid.service.js index bc2d36717d1fe..55f3ee2e519cc 100644 --- a/services/f-droid/f-droid.service.js +++ b/services/f-droid/f-droid.service.js @@ -16,6 +16,8 @@ const schema = Joi.object({ }).required() const queryParamSchema = Joi.object({ + serverFqdn: Joi.string().hostname(), + endpoint: Joi.string(), include_prereleases: Joi.equal(''), }).required() @@ -33,6 +35,14 @@ export default class FDroid extends BaseJsonService { name: 'appId', example: 'org.dystopia.email', }), + queryParam({ + name: 'serverFqdn', + example: 'apt.izzysoft.de', + }), + queryParam({ + name: 'endpoint', + example: 'fdroid', + }), queryParam({ name: 'include_prereleases', schema: { type: 'boolean' }, @@ -45,8 +55,12 @@ export default class FDroid extends BaseJsonService { static defaultBadgeData = { label: 'f-droid' } - async fetch({ appId }) { - const url = `https://f-droid.org/api/v1/packages/${appId}` + async fetch({ serverFqdn, endpoint, appId }) { + endpoint = endpoint.replace('^/|/$', '') + if (endpoint !== '') { + endpoint = `/${endpoint}` + } + const url = `https://${serverFqdn}${endpoint}/api/v1/packages/${appId}` return this._requestJson({ schema, url, @@ -71,8 +85,15 @@ export default class FDroid extends BaseJsonService { return { version } } - async handle({ appId }, { include_prereleases: includePre }) { - const json = await this.fetch({ appId }) + async handle( + { appId }, + { + serverFqdn = 'f-droid.org', + endpoint = '', + include_prereleases: includePre, + }, + ) { + const json = await this.fetch({ serverFqdn, endpoint, appId }) const suggested = includePre === undefined const { version } = this.transform({ json, suggested }) return renderVersionBadge({ version }) From 65e7f21d3d42c83d5f30290c599e6d114646d1a9 Mon Sep 17 00:00:00 2001 From: Niko Diamadis Date: Mon, 6 Jan 2025 05:37:54 -0500 Subject: [PATCH 2/4] docs: update F-Droid documentation --- services/f-droid/f-droid.service.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/services/f-droid/f-droid.service.js b/services/f-droid/f-droid.service.js index 55f3ee2e519cc..f7748dba1a94f 100644 --- a/services/f-droid/f-droid.service.js +++ b/services/f-droid/f-droid.service.js @@ -28,8 +28,11 @@ export default class FDroid extends BaseJsonService { '/f-droid/v/{appId}': { get: { summary: 'F-Droid Version', - description: - '[F-Droid](https://f-droid.org/) is a catalogue of Open Source Android apps', + description: ` + [F-Droid](https://f-droid.org/) is a catalogue of Open Source Android apps. + + This badge by default uses f-droid.org, but also supports custom repos. + `, parameters: [ pathParam({ name: 'appId', @@ -42,6 +45,7 @@ export default class FDroid extends BaseJsonService { queryParam({ name: 'endpoint', example: 'fdroid', + description: `If the API is not located at root path, specify the additional path to the API.`, }), queryParam({ name: 'include_prereleases', From 9e935be535a6fe002168c185b6f41b2720b699be Mon Sep 17 00:00:00 2001 From: Niko Diamadis Date: Mon, 6 Jan 2025 15:05:26 -0500 Subject: [PATCH 3/4] test: update F-Droid tests --- services/f-droid/f-droid.tester.js | 82 +++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/services/f-droid/f-droid.tester.js b/services/f-droid/f-droid.tester.js index 5dde646939987..c1adb67db3042 100644 --- a/services/f-droid/f-droid.tester.js +++ b/services/f-droid/f-droid.tester.js @@ -31,26 +31,33 @@ const testJson = ` const base = 'https://f-droid.org/api/v1' const path = `/packages/${testPkg}` -t.create('Package is found') +t.create('f-droid.org: Package is found') .get(`/v/${testPkg}.json`) .intercept(nock => nock(base).get(path).reply(200, testJson)) .expectBadge({ label: 'f-droid', message: 'v0.2.7' }) -t.create('Package is found (pre-release)') +t.create('f-droid.org: Package is found (pre-release)') .get(`/v/${testPkg}.json?include_prereleases`) .intercept(nock => nock(base).get(path).reply(200, testJson)) .expectBadge({ label: 'f-droid', message: 'v0.2.11' }) -t.create('Package is not found with 403') +t.create('f-droid.org: Package is not found with 403') .get(`/v/${testPkg}.json`) .intercept(nock => nock(base).get(path).reply(403, 'some 403 text')) .expectBadge({ label: 'f-droid', message: 'app not found' }) -t.create('Package is not found with 404') +t.create('f-droid.org: Package is not found with 404') .get('/v/io.shiels.does.not.exist.json') + .intercept(nock => + nock(base) + .get('/packages/io.shiels.does.not.exist') + .reply(404, 'some 404 text'), + ) .expectBadge({ label: 'f-droid', message: 'app not found' }) -t.create('Package is not found with no packages available (empty array)"') +t.create( + 'f-droid.org: Package is not found with no packages available (empty array)"', +) .get(`/v/${testPkg}.json`) .intercept(nock => nock(base) @@ -59,7 +66,9 @@ t.create('Package is not found with no packages available (empty array)"') ) .expectBadge({ label: 'f-droid', message: 'no packages found' }) -t.create('Package is not found with no packages available (missing array)"') +t.create( + 'f-droid.org: Package is not found with no packages available (missing array)"', +) .get(`/v/${testPkg}.json`) .intercept(nock => nock(base).get(path).reply(200, `{"packageName":"${testPkg}"}`), @@ -67,9 +76,68 @@ t.create('Package is not found with no packages available (missing array)"') .expectBadge({ label: 'f-droid', message: 'no packages found' }) /* If this test fails, either the API has changed or the app was deleted. */ -t.create('The real api did not change') +t.create('f-droid.org: The real api did not change') .get('/v/org.thosp.yourlocalweather.json') .expectBadge({ label: 'f-droid', message: isVPlusDottedVersionAtLeastOne, }) + +const base2 = 'https://apt.izzysoft.de/fdroid/api/v1' +const path2 = `/packages/${testPkg}` + +t.create('custom repo: Package is found') + .get(`/v/${testPkg}.json?serverFqdn=apt.izzysoft.de&endpoint=fdroid`) + .intercept(nock => nock(base2).get(path2).reply(200, testJson)) + .expectBadge({ label: 'f-droid', message: 'v0.2.7' }) + +t.create('custom repo: Package is found (pre-release)') + .get( + `/v/${testPkg}.json?serverFqdn=apt.izzysoft.de&endpoint=fdroid&include_prereleases`, + ) + .intercept(nock => nock(base2).get(path2).reply(200, testJson)) + .expectBadge({ label: 'f-droid', message: 'v0.2.11' }) + +t.create('custom repo: Package is not found with 403') + .get(`/v/${testPkg}.json?serverFqdn=apt.izzysoft.de&endpoint=fdroid`) + .intercept(nock => nock(base2).get(path2).reply(403, 'some 403 text')) + .expectBadge({ label: 'f-droid', message: 'app not found' }) + +t.create('custom repo: Package is not found with 404') + .get( + '/v/io.shiels.does.not.exist.json?serverFqdn=apt.izzysoft.de&endpoint=fdroid', + ) + .intercept(nock => + nock(base2) + .get('/packages/io.shiels.does.not.exist') + .reply(404, 'some 404 text'), + ) + .expectBadge({ label: 'f-droid', message: 'app not found' }) + +t.create( + 'custom repo: Package is not found with no packages available (empty array)"', +) + .get(`/v/${testPkg}.json?serverFqdn=apt.izzysoft.de&endpoint=fdroid`) + .intercept(nock => + nock(base2) + .get(path2) + .reply(200, `{"packageName":"${testPkg}","packages":[]}`), + ) + .expectBadge({ label: 'f-droid', message: 'no packages found' }) + +t.create( + 'custom repo: Package is not found with no packages available (missing array)"', +) + .get(`/v/${testPkg}.json?serverFqdn=apt.izzysoft.de&endpoint=fdroid`) + .intercept(nock => + nock(base2).get(path2).reply(200, `{"packageName":"${testPkg}"}`), + ) + .expectBadge({ label: 'f-droid', message: 'no packages found' }) + +/* If this test fails, either the API has changed or the app was deleted. */ +t.create('custom repo: The real api did not change') + .get('/v/com.looker.droidify.json') + .expectBadge({ + label: 'f-droid', + message: isVPlusDottedVersionAtLeastOne, + }) From 2cb8146341343bfc2609e409233ea1286fc525fa Mon Sep 17 00:00:00 2001 From: Niko Diamadis Date: Tue, 7 Jan 2025 15:32:49 -0500 Subject: [PATCH 4/4] test: fix API call on wrong repo --- services/f-droid/f-droid.tester.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/f-droid/f-droid.tester.js b/services/f-droid/f-droid.tester.js index c1adb67db3042..436f2a7379584 100644 --- a/services/f-droid/f-droid.tester.js +++ b/services/f-droid/f-droid.tester.js @@ -136,7 +136,7 @@ t.create( /* If this test fails, either the API has changed or the app was deleted. */ t.create('custom repo: The real api did not change') - .get('/v/com.looker.droidify.json') + .get('/v/com.looker.droidify.json?serverFqdn=apt.izzysoft.de&endpoint=fdroid') .expectBadge({ label: 'f-droid', message: isVPlusDottedVersionAtLeastOne,