From 1dd0547e3fd8d4cacc125def5800c9019dd72cef Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Wed, 7 Aug 2024 18:51:24 +0300 Subject: vnext: `releases` middleware * Help android app to find upgrade path --- vnext/server/index.js | 2 + vnext/server/middleware/android.js | 43 ++++++++++ vnext/server/middleware/android.spec.js | 37 +++++++++ vnext/server/middleware/legacy.json | 142 ++++++++++++++++++++++++++++++++ 4 files changed, 224 insertions(+) create mode 100644 vnext/server/middleware/android.js create mode 100644 vnext/server/middleware/android.spec.js create mode 100644 vnext/server/middleware/legacy.json (limited to 'vnext') diff --git a/vnext/server/index.js b/vnext/server/index.js index 16abc8db..692fbd76 100644 --- a/vnext/server/index.js +++ b/vnext/server/index.js @@ -9,6 +9,7 @@ import serverRenderer from './middleware/renderer' import event from './middleware/event' import oembed from './middleware/oembed' import urlExpand from './middleware/urlexpand' +import releases from './middleware/android' const PORT = process.env.LISTEN_PORT || 8081 import path from 'path' @@ -23,6 +24,7 @@ const router = express.Router() router.post('/api/v2/sender', event) router.get('/api/v2/oembed', oembed) router.get('/api/v2/urlexpand', urlExpand) +router.get('/api/apps/android/releases', releases) const durov_webhook = webhookPath() if (durov_webhook) { diff --git a/vnext/server/middleware/android.js b/vnext/server/middleware/android.js new file mode 100644 index 00000000..ae5f8fe8 --- /dev/null +++ b/vnext/server/middleware/android.js @@ -0,0 +1,43 @@ +import debug from 'debug' +var log = debug('android') + +import * as legacy_data from './legacy.json' + +const releases_url = 'https://api.github.com/repos/Juick/Juick-Android/releases' + +/** + * Return android releases + * @type {import('express').RequestParamHandler} + */ +const releases = async (req, res) => { + let agent = req.headers['user-agent'] || 'unknown' + let android_version = parse_agent_android_sdk_version(agent) + log(`releases request from ${android_version || agent}`) + if (android_version > 0) { + if (is_legacy_android(android_version)) { + log('responding with legacy stub') + return res.json([legacy_data]) + } else { + log('redirecting to Github') + return res.redirect(releases_url) + } + } + return res.json([]) +} + +const parse_agent_android_sdk_version = (agent = '') => { + let version = agent.split(' ', 3) + let is_android_app = version.length == 3 && version[2].startsWith('Android') + if (is_android_app) { + let android_version = version[2].split('/') + let is_valid_version = android_version.length == 2 + return is_valid_version ? +(android_version[1]) : NaN + } + return NaN +} + +const is_legacy_android = (version) => { + return version < 24 +} + +export default releases diff --git a/vnext/server/middleware/android.spec.js b/vnext/server/middleware/android.spec.js new file mode 100644 index 00000000..448714ac --- /dev/null +++ b/vnext/server/middleware/android.spec.js @@ -0,0 +1,37 @@ +import request from 'supertest' +import express from 'express' + +import releases from './android' + +const app = express() +app.get('/releases', releases) + +describe('Releases helper', () => { + it('Should respond with empty array to unknown user agents', async () => { + return request(app) + .get('/releases') + .expect(200) + .then(response => { + expect(response.body).toStrictEqual([]) + }) + }) + it('Should respond with a single legacy version data to old Android app', async () => { + return request(app) + .get('/releases') + .set('User-Agent', 'Juick/100 okhttp/3.12 Android/19') + .expect(200) + .then(response => { + expect(response.body.length).toBe(1) + expect(response.body[0].name).toBe('3.1.216') + }) + }) + it('Should redirect to Github when Android version is ok', async () => { + return request(app) + .get('/releases') + .set('User-Agent', 'Juick/100 okhttp/3.12 Android/24') + .expect(302) + .then(response => { + expect(response.redirect).toBe(true) + }) + }) +}) diff --git a/vnext/server/middleware/legacy.json b/vnext/server/middleware/legacy.json new file mode 100644 index 00000000..840708e6 --- /dev/null +++ b/vnext/server/middleware/legacy.json @@ -0,0 +1,142 @@ +{ + "url": "https://api.github.com/repos/juick/Juick-Android/releases/164308344", + "assets_url": "https://api.github.com/repos/juick/Juick-Android/releases/164308344/assets", + "upload_url": "https://uploads.github.com/repos/juick/Juick-Android/releases/164308344/assets{?name,label}", + "html_url": "https://github.com/juick/Juick-Android/releases/tag/v3.1.216", + "id": 164308344, + "author": { + "login": "vitalyster", + "id": 1052407, + "node_id": "MDQ6VXNlcjEwNTI0MDc=", + "avatar_url": "https://avatars.githubusercontent.com/u/1052407?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vitalyster", + "html_url": "https://github.com/vitalyster", + "followers_url": "https://api.github.com/users/vitalyster/followers", + "following_url": "https://api.github.com/users/vitalyster/following{/other_user}", + "gists_url": "https://api.github.com/users/vitalyster/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vitalyster/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vitalyster/subscriptions", + "organizations_url": "https://api.github.com/users/vitalyster/orgs", + "repos_url": "https://api.github.com/users/vitalyster/repos", + "events_url": "https://api.github.com/users/vitalyster/events{/privacy}", + "received_events_url": "https://api.github.com/users/vitalyster/received_events", + "type": "User", + "site_admin": false + }, + "node_id": "RE_kwDOADJkWc4JyyV4", + "tag_name": "v3.1.216", + "target_commitish": "master", + "name": "3.1.216", + "draft": false, + "prerelease": true, + "created_at": "2024-07-07T19:47:32Z", + "published_at": "2024-07-07T19:51:29Z", + "assets": [ + { + "url": "https://api.github.com/repos/juick/Juick-Android/releases/assets/178215973", + "id": 178215973, + "node_id": "RA_kwDOADJkWc4Kn1wl", + "name": "Juick-free-v3.1.216.apk", + "label": null, + "uploader": { + "login": "vitalyster", + "id": 1052407, + "node_id": "MDQ6VXNlcjEwNTI0MDc=", + "avatar_url": "https://avatars.githubusercontent.com/u/1052407?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vitalyster", + "html_url": "https://github.com/vitalyster", + "followers_url": "https://api.github.com/users/vitalyster/followers", + "following_url": "https://api.github.com/users/vitalyster/following{/other_user}", + "gists_url": "https://api.github.com/users/vitalyster/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vitalyster/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vitalyster/subscriptions", + "organizations_url": "https://api.github.com/users/vitalyster/orgs", + "repos_url": "https://api.github.com/users/vitalyster/repos", + "events_url": "https://api.github.com/users/vitalyster/events{/privacy}", + "received_events_url": "https://api.github.com/users/vitalyster/received_events", + "type": "User", + "site_admin": false + }, + "content_type": "application/vnd.android.package-archive", + "state": "uploaded", + "size": 7807858, + "download_count": 2, + "created_at": "2024-07-07T19:51:12Z", + "updated_at": "2024-07-07T19:51:25Z", + "browser_download_url": "https://github.com/juick/Juick-Android/releases/download/v3.1.216/Juick-free-v3.1.216.apk" + }, + { + "url": "https://api.github.com/repos/juick/Juick-Android/releases/assets/178215894", + "id": 178215894, + "node_id": "RA_kwDOADJkWc4Kn1vW", + "name": "Juick-google-v3.1.216.apk", + "label": null, + "uploader": { + "login": "vitalyster", + "id": 1052407, + "node_id": "MDQ6VXNlcjEwNTI0MDc=", + "avatar_url": "https://avatars.githubusercontent.com/u/1052407?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vitalyster", + "html_url": "https://github.com/vitalyster", + "followers_url": "https://api.github.com/users/vitalyster/followers", + "following_url": "https://api.github.com/users/vitalyster/following{/other_user}", + "gists_url": "https://api.github.com/users/vitalyster/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vitalyster/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vitalyster/subscriptions", + "organizations_url": "https://api.github.com/users/vitalyster/orgs", + "repos_url": "https://api.github.com/users/vitalyster/repos", + "events_url": "https://api.github.com/users/vitalyster/events{/privacy}", + "received_events_url": "https://api.github.com/users/vitalyster/received_events", + "type": "User", + "site_admin": false + }, + "content_type": "application/vnd.android.package-archive", + "state": "uploaded", + "size": 8421195, + "download_count": 7, + "created_at": "2024-07-07T19:50:49Z", + "updated_at": "2024-07-07T19:51:04Z", + "browser_download_url": "https://github.com/juick/Juick-Android/releases/download/v3.1.216/Juick-google-v3.1.216.apk" + }, + { + "url": "https://api.github.com/repos/juick/Juick-Android/releases/assets/178215877", + "id": 178215877, + "node_id": "RA_kwDOADJkWc4Kn1vF", + "name": "Juick-huawei-v3.1.216.apk", + "label": null, + "uploader": { + "login": "vitalyster", + "id": 1052407, + "node_id": "MDQ6VXNlcjEwNTI0MDc=", + "avatar_url": "https://avatars.githubusercontent.com/u/1052407?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vitalyster", + "html_url": "https://github.com/vitalyster", + "followers_url": "https://api.github.com/users/vitalyster/followers", + "following_url": "https://api.github.com/users/vitalyster/following{/other_user}", + "gists_url": "https://api.github.com/users/vitalyster/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vitalyster/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vitalyster/subscriptions", + "organizations_url": "https://api.github.com/users/vitalyster/orgs", + "repos_url": "https://api.github.com/users/vitalyster/repos", + "events_url": "https://api.github.com/users/vitalyster/events{/privacy}", + "received_events_url": "https://api.github.com/users/vitalyster/received_events", + "type": "User", + "site_admin": false + }, + "content_type": "application/vnd.android.package-archive", + "state": "uploaded", + "size": 8275073, + "download_count": 3, + "created_at": "2024-07-07T19:50:27Z", + "updated_at": "2024-07-07T19:50:41Z", + "browser_download_url": "https://github.com/juick/Juick-Android/releases/download/v3.1.216/Juick-huawei-v3.1.216.apk" + } + ], + "tarball_url": "https://api.github.com/repos/juick/Juick-Android/tarball/v3.1.216", + "zipball_url": "https://api.github.com/repos/juick/Juick-Android/zipball/v3.1.216", + "body": "* Bugfixes and performance improvements" +} -- cgit v1.2.3