Enabled donates url for iOS
Old iOS versions (without donate menu item support) do not send build number and flavor. Newer iOS versions send it in the form: 2022.11.21-3-ios. Signed-off-by: Alexander Borsuk <me@alex.bio>
This commit is contained in:
parent
8a4330d582
commit
cda02e3a23
4 changed files with 136 additions and 26 deletions
16
src/index.ts
16
src/index.ts
|
@ -47,8 +47,9 @@ export const SERVER = {
|
|||
},
|
||||
};
|
||||
|
||||
const DONATE_URL = 'https://organicmaps.app/donate/';
|
||||
const DONATE_URL_RU = 'https://organicmaps.app/ru/donate/';
|
||||
// Exported for tests.
|
||||
export const DONATE_URL = 'https://organicmaps.app/donate/';
|
||||
export const DONATE_URL_RU = 'https://organicmaps.app/ru/donate/';
|
||||
|
||||
// Main entry point.
|
||||
addEventListener('fetch', (event) => {
|
||||
|
@ -119,8 +120,9 @@ export async function handleRequest(request: Request) {
|
|||
servers: servers,
|
||||
};
|
||||
|
||||
// Disable donates for Google reviewers for all google app versions AFTER this one.
|
||||
// Disable donates for reviewers for all app versions AFTER this one.
|
||||
const lastApprovedAndReleasedGoogleAppVersionCode = 221102;
|
||||
const lastApprovedAndReleasediOSAppVersionCode = 221120;
|
||||
let donatesEnabled = true;
|
||||
if (
|
||||
appVersion.flavor === 'google' &&
|
||||
|
@ -128,6 +130,14 @@ export async function handleRequest(request: Request) {
|
|||
appVersion.code > lastApprovedAndReleasedGoogleAppVersionCode)
|
||||
) {
|
||||
donatesEnabled = false;
|
||||
} else if (appVersion.build === undefined) {
|
||||
// Disable donates for older iOS versions without donates menu support.
|
||||
donatesEnabled = false;
|
||||
} else if (
|
||||
(appVersion.flavor === 'ios' && (request.cf?.asOrganization || '').toLowerCase().includes('apple')) ||
|
||||
appVersion.code > lastApprovedAndReleasediOSAppVersionCode
|
||||
) {
|
||||
donatesEnabled = false;
|
||||
}
|
||||
|
||||
if (donatesEnabled) {
|
||||
|
|
|
@ -13,37 +13,46 @@ export function parseDataVersion(strDataVersion: string | null): number | null {
|
|||
return dataVersion;
|
||||
}
|
||||
|
||||
const VERSION_RE = new RegExp('(\\d{4}).(\\d{1,2}).(\\d{1,2})-(\\d{1,9})(?:-([^-]+))?');
|
||||
// 2022.11.20 for iOS versions released before November 21 (without donate menu)
|
||||
// 2022.11.24-4-ios for newer iOS versions (with donate menu)
|
||||
// 2022.12.24-10-Google for Android
|
||||
const VERSION_RE = /(\d{4}).(\d{1,2}).(\d{1,2})(?:$|-(\d{1,9})(?:-([^-]+))?)/;
|
||||
// Returns code like 221224 for both platforms, build and flavor for Android and newer iOS versions.
|
||||
export function parseAppVersion(
|
||||
versionName: string | null,
|
||||
): { code: number; build: number | undefined; flavor: string | undefined } | null {
|
||||
): { code: number; build?: number; flavor?: string | undefined } | null {
|
||||
if (!versionName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const m = versionName.match(VERSION_RE);
|
||||
if (m === null || m.length < 6) {
|
||||
if (m === null || m.length < 4) {
|
||||
return null;
|
||||
}
|
||||
const yyyy = parseInt(m[1]);
|
||||
const mm = parseInt(m[2]);
|
||||
const dd = parseInt(m[3]);
|
||||
const build = Number.isNaN(parseInt(m[4])) ? undefined : parseInt(m[4]);
|
||||
const flavor = (m[5] !== undefined && m[5].toLowerCase()) || undefined;
|
||||
if (
|
||||
Number.isNaN(yyyy) ||
|
||||
yyyy > 2099 ||
|
||||
yyyy < 2022 ||
|
||||
Number.isNaN(mm) ||
|
||||
mm > 12 ||
|
||||
mm < 1 ||
|
||||
Number.isNaN(dd) ||
|
||||
dd > 31 ||
|
||||
dd < 1
|
||||
) {
|
||||
if (Number.isNaN(yyyy) || yyyy > 2099 || yyyy < 2022) {
|
||||
return null;
|
||||
}
|
||||
const mm = parseInt(m[2]);
|
||||
if (Number.isNaN(mm) || mm > 12 || mm < 1) {
|
||||
return null;
|
||||
}
|
||||
const dd = parseInt(m[3]);
|
||||
if (Number.isNaN(dd) || dd > 31 || dd < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const code = parseInt(String(yyyy % 100) + String(mm).padStart(2, '0') + String(dd).padStart(2, '0'));
|
||||
// Older iOS versions without donate button.
|
||||
if (m[4] === undefined) {
|
||||
return { code: code };
|
||||
}
|
||||
|
||||
const buildNumber = parseInt(m[4]);
|
||||
const build = Number.isNaN(buildNumber) ? 0 : buildNumber;
|
||||
// 'ios' for iOS devices.
|
||||
const flavor = (m[5] !== undefined && m[5].toLowerCase()) || undefined;
|
||||
|
||||
return {
|
||||
code: code,
|
||||
flavor: flavor,
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
import { describe, expect, test } from '@jest/globals';
|
||||
import { handleRequest, SERVER } from '../src/index';
|
||||
import { handleRequest, SERVER, DONATE_URL, DONATE_URL_RU } from '../src/index';
|
||||
|
||||
const URL = 'https://worker/servers';
|
||||
const LAST_DATA_VERSION = SERVER.planet.dataVersions[SERVER.planet.dataVersions.length - 1];
|
||||
|
||||
describe('old versions', () => {
|
||||
test('no dataVersion', async () => {
|
||||
// Note: CF lowercases all headers.
|
||||
describe('X-OM-DataVersion', () => {
|
||||
test('no X-OM-DataVersion', async () => {
|
||||
const req = new Request(URL);
|
||||
const result = await handleRequest(req);
|
||||
expect(result.status).toBe(200);
|
||||
expect(JSON.parse(await result.text())).toEqual([SERVER.backblaze.url]);
|
||||
});
|
||||
test('has dataVersion', async () => {
|
||||
|
||||
test('has X-OM-DataVersion', async () => {
|
||||
const server = SERVER.fi1;
|
||||
let req = new Request(URL, {
|
||||
headers: {
|
||||
|
@ -22,7 +24,8 @@ describe('old versions', () => {
|
|||
expect(result.status).toBe(200);
|
||||
expect(JSON.parse(await result.text())).toContain(server.url);
|
||||
});
|
||||
test('default routing to planet', async () => {
|
||||
|
||||
test('Default routing to planet', async () => {
|
||||
let req = new Request(URL, {
|
||||
headers: {
|
||||
'X-OM-DataVersion': '210000', // this version doesn't exist on servers
|
||||
|
@ -33,3 +36,75 @@ describe('old versions', () => {
|
|||
expect(JSON.parse(await result.text())).toEqual([SERVER.planet.url]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('X-OM-AppVersion DonateUrl', () => {
|
||||
test('Old versions without X-OM-AppVersion and old metaserver JSON format', async () => {
|
||||
const req = new Request(URL);
|
||||
const response = await handleRequest(req);
|
||||
expect(response.status).toBe(200);
|
||||
expect(JSON.parse(await response.text())).toEqual([SERVER.backblaze.url]);
|
||||
});
|
||||
|
||||
const server = SERVER.fi1;
|
||||
|
||||
test('Newer metaserver JSON format with donates support', async () => {
|
||||
let req = new Request(URL, {
|
||||
headers: {
|
||||
'X-OM-AppVersion': '2022.08.23-1-Google',
|
||||
'X-OM-DataVersion': String(server.dataVersions[0]),
|
||||
},
|
||||
});
|
||||
const response = await handleRequest(req);
|
||||
expect(response.status).toBe(200);
|
||||
const result = JSON.parse(await response.text());
|
||||
expect(result.servers).toBeDefined();
|
||||
expect(result.servers.length).toBeGreaterThan(0);
|
||||
expect(result.servers).toContain(server.url);
|
||||
expect(result.settings).toBeDefined();
|
||||
expect(result.settings.DonateUrl).toBeDefined();
|
||||
expect(result.settings.DonateUrl).toEqual(DONATE_URL);
|
||||
});
|
||||
|
||||
test('Newer metaserver JSON format with donates support', async () => {
|
||||
let req = new Request(URL, {
|
||||
headers: {
|
||||
'X-OM-AppVersion': '2022.08.23-1-Google',
|
||||
'X-OM-DataVersion': String(server.dataVersions[0]),
|
||||
},
|
||||
//@ts-ignore
|
||||
cf: { country: 'RU' },
|
||||
});
|
||||
const response = await handleRequest(req);
|
||||
expect(response.status).toBe(200);
|
||||
const result = JSON.parse(await response.text());
|
||||
expect(result.settings.DonateUrl).toBeDefined();
|
||||
expect(result.settings.DonateUrl).toEqual(DONATE_URL_RU);
|
||||
});
|
||||
|
||||
test('Older iOS versions with X-OM-AppVersion but without donates', async () => {
|
||||
let req = new Request(URL, {
|
||||
headers: {
|
||||
'X-OM-AppVersion': '2022.11.20',
|
||||
'X-OM-DataVersion': String(server.dataVersions[0]),
|
||||
},
|
||||
});
|
||||
const response = await handleRequest(req);
|
||||
expect(response.status).toBe(200);
|
||||
const result = JSON.parse(await response.text());
|
||||
expect(result.settings).not.toBeDefined();
|
||||
});
|
||||
|
||||
test('Newer iOS versions with donate menu support', async () => {
|
||||
let req = new Request(URL, {
|
||||
headers: {
|
||||
'X-OM-AppVersion': '2022.11.20-4-ios',
|
||||
'X-OM-DataVersion': String(server.dataVersions[0]),
|
||||
},
|
||||
});
|
||||
const response = await handleRequest(req);
|
||||
expect(response.status).toBe(200);
|
||||
const result = JSON.parse(await response.text());
|
||||
expect(result.settings.DonateUrl).toBeDefined();
|
||||
expect(result.settings.DonateUrl).toEqual(DONATE_URL);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -20,6 +20,10 @@ describe('parseDataVersion', () => {
|
|||
|
||||
describe('parseAppVersion', () => {
|
||||
const tests: { [key: string]: object | null } = {
|
||||
// Older iOS releases without donate menu
|
||||
'2022.08.01': { code: 220801 },
|
||||
// Newer iOS releases with donate menu
|
||||
'2022.11.25-5-ios': { code: 221125, build: 5, flavor: 'ios' },
|
||||
'2022.08.01-1': { code: 220801, build: 1 },
|
||||
'2022.08.01-1-Google': { code: 220801, build: 1, flavor: 'google' },
|
||||
// -debug is ignored
|
||||
|
@ -32,8 +36,20 @@ describe('parseAppVersion', () => {
|
|||
'2022.13.31-1': null,
|
||||
'2022.01.00-1': null,
|
||||
'2022.01.32-1': null,
|
||||
'22.01.31-1': null,
|
||||
'22.01.31': null,
|
||||
'22.01.31-3-flavor': null,
|
||||
'202.01.31-1': null,
|
||||
'202.01.312-1': null,
|
||||
'202.01.312': null,
|
||||
'202.01.31-aa-flavor': null,
|
||||
'202.01.31-5a-flavor': null,
|
||||
'202.01.31-a5-flavor': null,
|
||||
'2022..31-11': null,
|
||||
'2022..31-11-flavor': null,
|
||||
'.11.31-11': null,
|
||||
'.11.31-11-flavor': null,
|
||||
'.11..31-11-flavor': null,
|
||||
garbage: null,
|
||||
'': null,
|
||||
null: null,
|
||||
|
|
Loading…
Add table
Reference in a new issue