Compare commits

...
Sign in to create a new pull request.

124 commits

Author SHA1 Message Date
Viktor Havaka
882b7a7cec
Enable donates for AppStore (250302).
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2025-03-05 17:42:47 -03:00
18c36b18d2 Add 250227
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-03-02 16:15:54 +00:00
Viktor Havaka
7c48e43fc4
Set iOS donates on 250301.
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2025-02-28 17:51:56 -03:00
Viktor Havaka
7c92fc3ce6
Enable donates.
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2025-02-26 23:05:57 -03:00
71c8217bb8 Add 250213
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-02-17 17:08:42 +00:00
Viktor Havaka
fc751e37aa
Enable donates for Google Play.
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2025-01-31 12:48:41 -03:00
Viktor Havaka
9a794b9652
Enable donates for AppStore.
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2025-01-29 10:43:31 -03:00
a2be921690 Add 250121
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2025-01-26 22:53:10 +03:00
878dfa9c06 Disable Xmas tree
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-01-26 11:32:08 +03:00
eab3488455 Specify GitHub Environment to allow access to CF secrets
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-12-23 17:25:08 +00:00
e65565a1e8 Enable Xmas tree 2024-12-23 17:19:01 +00:00
22617fa964 Add actual CONTRIBUTORS file 2024-12-13 22:54:17 +01:00
Alexander Borsuk
e41c085fd7 npm run upgrade
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-12-13 14:57:57 +01:00
Alexander Borsuk
cc43bceb03 Added vietnam server
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-12-13 14:52:26 +01:00
3ec9d9e5b9 Distinct links for About/Donate and PlacePage/Other 2024-12-13 14:52:26 +01:00
Viktor Havaka
4b8c381c33 Enable donates for Google Play (241127)
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2024-12-13 14:52:26 +01:00
Viktor Havaka
a269f44aa4 Enable donates for AppStore (241127).
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2024-12-13 14:52:26 +01:00
Viktor Havaka
bb534682fd Added 241122 data version.
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2024-12-13 14:52:26 +01:00
Viktor Havaka
7fb90b0444 Enable iOS donates for TestFlight (241126).
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2024-12-13 14:52:26 +01:00
14b002618e Add PlacePage donations
https://docs.google.com/document/d/1f2zjYBr24Wlh1vBcTtCmisx-HidaYwivkXZGCHjlTTY/edit
2024-12-13 14:52:26 +01:00
Viktor Havaka
05100af769
Added 241017 data version.
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2024-11-14 16:20:57 -03:00
Alexander Borsuk
9eb4405f03 241107 data version
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-11-14 19:59:28 +01:00
Viktor Havaka
5d26908ec2
Enable donates for AppStore and GP.
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2024-11-13 08:04:31 -03:00
Alexander Borsuk
d7ac8bc5fa Added new version of MapXPlorer 1.8.7-1-ios into abusers list
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-11-12 12:38:53 +01:00
Alexander Borsuk
fde585a122 Added new version of MapXPlorer into abusers list
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-11-12 07:52:36 +01:00
Viktor Havaka
13ad21530d
Enable donates for Google Play (241023)
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2024-10-26 09:31:03 -03:00
Alexander Borsuk
50c140ebcb
Trap for cdn abusers with a specific map/app version (#89) 2024-10-25 14:18:57 +02:00
Viktor Havaka
cbe27ccda4
Enable donates for AppStore (241022).
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2024-10-23 17:59:13 -03:00
Viktor Havaka
087cbaf316
Enable donates for Google Play (241008)
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2024-10-11 19:12:54 -03:00
Viktor Havaka
30cbe4463c
Update donates for Apple (08) and Google (04).
Signed-off-by: Viktor Havaka <viktor.govako@gmail.com>
2024-10-09 20:26:22 -03:00
0cb3ff3dc1 Don't use cdn-us1 (Cloudflare + Backbaze) for the actual versions
Cloudflare almost always have lowest ping, leaving no chance to
other servers to server data for iOS users. Viktor reported some
issues with Cloudflare from Argentina. "Let's see if us-west1 +
us-east1 + uk1 + nl1 servers can handle America and Oceania.
2024-10-05 11:19:58 -07:00
b8200aadc8
Enable donates for Apple 241004
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-10-05 07:07:00 -07:00
375533572c Add 241001 2024-10-04 07:50:54 +01:00
ecc91e7737 Refactor the list of servers + add us-east1 2024-09-25 22:46:45 +03:00
Viktor Govako
225cc73df7 Run prettier. 2024-09-21 08:03:54 -03:00
Viktor Govako
2783718dd0 Enable donates for GP 240919. 2024-09-21 08:03:54 -03:00
37b706fa51
Enable donates for iOS 240908
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-09-15 18:36:45 +01:00
9c8fac62f2
Disable donates in Google Play while waiting for an appeal
https://github.com/organicmaps/organicmaps/issues/9240#issuecomment-2342973474

Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-09-11 09:38:20 +01:00
983913c1af Add 240904 2024-09-08 21:33:59 +01:00
Alexander Borsuk
0fdfb8a2ea Replaced us2 with us3
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-08-22 15:51:26 +02:00
Alexander Borsuk
fe6e1d889c Enabled donations for GP 240817
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-08-19 15:56:31 +02:00
Alexander Borsuk
3a7b3fe8cd Enabled donations for iOS 240815
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-08-17 15:02:58 +02:00
Alexander Borsuk
a177326249 New map data 240810
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-08-16 17:46:11 +02:00
671d4934db
Remove DONATE_URL_RU
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-08-13 11:30:36 +01:00
Alexander Borsuk
9a9af6fdcc Add cdn-de3 node 2024-07-31 09:04:25 +02:00
Alexander Borsuk
84689e9ec6 Update github actions 2024-07-31 09:04:25 +02:00
Alexander Borsuk
db02d73f9e Update readme 2024-07-31 09:04:25 +02:00
Alexander Borsuk
9587929d85 Removed eslint
It fails with dependency error for several months:

Running custom build: npm ci --prefer-offline --no-audit && npm run build
npm error code ERESOLVE
npm error ERESOLVE could not resolve
npm error
npm error While resolving: @typescript-eslint/eslint-plugin@7.18.0
npm error Found: eslint@9.8.0
npm error node_modules/eslint
npm error   dev eslint@"^9.8.0" from the root project
npm error   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm error   node_modules/@eslint-community/eslint-utils
npm error     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.18.0
npm error     node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils
npm error       @typescript-eslint/utils@"7.18.0" from @typescript-eslint/eslint-plugin@7.18.0
npm error       node_modules/@typescript-eslint/eslint-plugin
npm error         dev @typescript-eslint/eslint-plugin@"^7.18.0" from the root project
npm error       1 more (@typescript-eslint/type-utils)
npm error     @eslint-community/eslint-utils@"^4.2.0" from eslint@9.8.0
npm error
npm error Could not resolve dependency:
npm error peer eslint@"^8.56.0" from @typescript-eslint/eslint-plugin@7.18.0
npm error node_modules/@typescript-eslint/eslint-plugin
npm error   dev @typescript-eslint/eslint-plugin@"^7.18.0" from the root project
npm error
npm error Conflicting peer dependency: eslint@8.57.0
npm error node_modules/eslint
npm error   peer eslint@"^8.56.0" from @typescript-eslint/eslint-plugin@7.18.0
npm error   node_modules/@typescript-eslint/eslint-plugin
npm error     dev @typescript-eslint/eslint-plugin@"^7.18.0" from the root project
npm error
npm error Fix the upstream dependency conflict, or retry
npm error this command with --force or --legacy-peer-deps
npm error to accept an incorrect (and potentially broken) dependency resolution.
npm error
npm error
npm error For a full report see:
npm error /Users/alex/.npm/_logs/2024-07-31T06_48_17_698Z-eresolve-report.txt
npm error A complete log of this run can be found in: /Users/alex/.npm/_logs/2024-07-31T06_48_17_698Z-debug-0.log

✘ [ERROR] Running custom build `npm ci --prefer-offline --no-audit && npm run build` failed. There are likely more logs from your build command above.
2024-07-31 09:03:41 +02:00
Alexander Borsuk
424bfab1f1 npm run upgrade 2024-07-31 07:58:20 +02:00
Alexander Borsuk
9fc90d1dd5 Enable donates for GP android 240729
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-07-29 20:42:12 +02:00
f7840e6a5a Add 240723 2024-07-28 11:00:18 +03:00
Alexander Borsuk
3e1d1e7aab Enable donates for iOS 240727
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-07-27 19:00:27 +02:00
Alexander Borsuk
265f65c8e3 Enable donations for Android hotfix 240723
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-07-25 09:37:20 +02:00
Alexander Borsuk
6bafd059da Enabled GP donates for 240708
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-07-15 14:23:20 +03:00
Alexander Borsuk
da32ce8662 npm run upgrade
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-07-10 09:13:09 +03:00
Alexander Borsuk
9afb5094d2 Enabled donations for iOS July release 2024-07-10 09:10:43 +03:00
d4e1a65e23 Add 240702 2024-07-08 22:00:01 +01:00
8b3b48d689
Enable donations for 240619 (Apple)
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-06-21 14:37:52 +03:00
02e58cb29b
Enable donations for 240619 (Google)
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-06-20 10:06:58 +03:00
441e08f964 Add 240613 2024-06-19 10:24:46 +03:00
73e5aed304
Donates 240602
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-06-05 11:27:01 +03:00
36e12a6497 Add 240528 2024-06-02 21:03:42 +03:00
c2ae1236eb
Enable donations for 240511 (Google)
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-05-13 19:43:56 +03:00
Alexander Borsuk
6bfc5c45c4 Enable donates iOS 240510
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-05-11 23:05:08 +02:00
2a92abd741 Add 240429
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-05-04 21:23:48 +03:00
ea3cef7ca5 Revert "Add G-Core CDN"
This reverts commit af1ba4f50d.
2024-05-04 21:23:48 +03:00
7410279e36 Add G-Core CDN
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-04-26 15:57:06 +03:00
a7e13bea9a
Enable donations for 240331 (Apple)
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-04-03 17:44:34 +03:00
988c8d4c7d
Enable donations for 240331 (Google)
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-04-03 07:15:43 +03:00
6c95780f09 Add 240326
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-03-31 10:17:15 +03:00
accf6a5607
Enable donates for 240307 (AppStore) 2024-03-08 22:42:27 +03:00
944fe69dcb
Enable donates for 240303 (AppStore) 2024-03-07 18:06:32 +03:00
342050ba56
Enable donates for 240303 2024-03-05 09:24:42 +03:00
fc36848ecb Add 240228
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2024-03-04 08:23:15 +02:00
Alexander Borsuk
2341c15787 Enabled donations for Android 240301
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-03-02 08:40:57 +02:00
Alexander Borsuk
9bb0348fca Enable iOS donates 240227
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-03-01 20:34:17 +02:00
28e9b826d1
Enable donates for 240220 2024-02-20 23:23:26 +03:00
Alexander Borsuk
a2225f5d04 Enable donates for 240206
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-02-08 00:56:42 +02:00
2f43b868ab Add 240202 2024-02-06 11:43:01 +02:00
Alexander Borsuk
83919b9a79 Disabled Christmas Tree
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-01-21 03:45:15 +02:00
Alexander Borsuk
d0524e78d1 Enable donates for ios and android 240109
Signed-off-by: Alexander Borsuk <me@alex.bio>
2024-01-10 23:33:54 +02:00
c57a691110 Add 240105 2024-01-09 23:13:05 +02:00
57daba6e09 Temporary disable donates Google Play for case [0-8882000035986]
https://github.com/organicmaps/organicmaps/issues/7000
2023-12-28 14:21:44 +01:00
Alexander Borsuk
8fa182c15b Donates for iOS 12 hotfix release 231222
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-12-24 20:03:32 +01:00
245f3f61ad
Enable donates for Google 231221 2023-12-23 10:02:58 +03:00
b08cf5bff0
Redirect users from Russia directly to CloudPayments (test)
Skip https://organicmaps.app/ru/donate web-site and redirect users to https://pay.cloudtips.ru/p/774e5188 via https://donate.organicmaps.ru
2023-12-22 12:02:07 +03:00
Alexander Borsuk
fccf37e9e7 Enable donates for iOS 231220
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-12-21 19:18:51 +01:00
f02e1ec6a4
Enable donates and NY for iOS 231218 2023-12-19 21:12:28 +03:00
923b8f7274
Enable donates and NY for Google 231218 2023-12-19 09:11:01 +03:00
4468cdd776 Add 231213
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2023-12-17 22:37:10 +02:00
Alexander Borsuk
dc91b633ba npm run upgrade, fixed toml prettier error
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-12-14 22:56:17 +02:00
Alexander Borsuk
9b2e72600d Enable donates for 2023.12.13 iOS hotfix
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-12-14 21:51:24 +01:00
38e9ce98bb Enable donations for Apple Store 2023-11-21 20:48:07 +02:00
428d8a7cf1
Enable donation for Google Play 2023-11-21 12:26:38 +03:00
8261dad9e7 Add 231113 2023-11-17 11:58:21 +02:00
Alexander Borsuk
749a23eaaf Enabled donations on iOS
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-09-25 19:58:45 +02:00
Alexander Borsuk
a51a9a1a66 Enable GP donates
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-09-23 20:15:21 +03:00
8811f9eb9f Add 230920 2023-09-22 21:00:45 +02:00
Alexander Borsuk
b72a43642c Enabled donates on iOS 2023-08-21 19:33:41 +03:00
3cb3a0b021 Add 230814 2023-08-18 18:27:23 +03:00
Alexander Borsuk
646d1d742a New data version on servers
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-07-15 03:13:38 +02:00
Alexander Borsuk
9f8037a8b8 npm run upgrade
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-07-15 03:13:38 +02:00
Alexander Borsuk
daefc2b9f8 Enable donates
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-07-15 03:13:38 +02:00
Viktor Govako
b9923075d7 Set iOS version 230604 2023-06-07 23:08:29 +02:00
8e58be8700 Add 230602 2023-06-05 17:28:37 +02:00
Alexander Borsuk
f9cda06dce npm run upgrade to use wrangler 3 for dev
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-06-01 06:59:32 +02:00
Alexander Borsuk
7956637a53 Respond with CF-cached beta server for all non-official data versions
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-05-31 08:55:17 +02:00
8eff170a1c Enable donations 2023-05-10 10:11:42 +02:00
4e0f234f0d Add 230503 2023-05-08 18:44:39 +02:00
Alexander Borsuk
1f2b52bc34 Enabled donations
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-04-05 10:17:58 +03:00
6ce9fc1bdf Add 230329 2023-04-02 21:25:18 +02:00
Alexander Borsuk
64a0fc7363 Support Linux and Mac versions parsing 2023-03-31 22:04:48 +02:00
Alexander Borsuk
535a7e1f56 Removed unused donation logs 2023-03-31 18:43:17 +03:00
Alexander Borsuk
e1e4cbbd0d Fixed type error 2023-03-31 18:43:17 +03:00
Alexander Borsuk
d41bc4228d Moved servers-endpoint reply into servers.ts
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-03-31 18:43:14 +03:00
Alexander Borsuk
c5f24e9912 Updated dependencies
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-03-31 18:42:47 +03:00
0b2824e067 Fix missing Android donation button
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2023-03-31 18:42:27 +03:00
ce61738a7e Enable donates for 230305 2023-03-08 16:05:50 +01:00
Alexander Borsuk
351fcfbfca npm run upgrade
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-03-08 16:01:28 +01:00
Alexander Borsuk
524651fe87 Returned back 3 data versions for nl1 and uk1, after applying btrfs with compression
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-03-08 16:01:28 +01:00
156e7d1cc3 Bump versions 2023-03-03 22:22:28 +01:00
Alexander Borsuk
51ba0a3752 Updated dependencies
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-02-15 12:14:08 +01:00
Alexander Borsuk
c523ab02a6 Enabled donates
Signed-off-by: Alexander Borsuk <me@alex.bio>
2023-02-15 12:14:08 +01:00
b41355f6c4 Bump versions
Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
2023-02-13 14:38:59 +02:00
21 changed files with 2663 additions and 12377 deletions

View file

@ -1,18 +0,0 @@
env:
es2020: true
worker: true
extends: ['plugin:@typescript-eslint/recommended']
parser: '@typescript-eslint/parser'
parserOptions:
ecmaVersion: 2020
ecmaFeatures:
impliedStrict: true
sourceType: module
root: true
rules:
indent: [error, 2, { SwitchCase: 1 }]
semi: [error, always]
quotes: [error, single, avoid-escape]
no-trailing-spaces: [error]
no-unused-vars: [error, { argsIgnorePattern: ^_ }]
prefer-const: [error, { destructuring: all }]

View file

@ -24,8 +24,9 @@ jobs:
- name: Dependencies
run: npm ci
- name: Lint
run: npm run lint:ci
# TODO(AB): ESLint dependencies are broken. Replace with a better and less complex linter.
# - name: Lint
# run: npm run lint:ci
- name: Format
run: npm run format:ci

View file

@ -7,10 +7,11 @@ on:
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: wrangler publish
uses: cloudflare/wrangler-action@2.0.0
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
environment: prod

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
dist/
.wrangler/
# Autogenerated by esbuild.
workers-site/index.js
node_modules/

View file

@ -1,4 +1,5 @@
{
"plugins": ["prettier-plugin-toml"],
"printWidth": 120,
"tabWidth": 2,
"singleQuote": true,

4
CONTRIBUTORS Normal file
View file

@ -0,0 +1,4 @@
Alexander Borsuk <me@alex.bio>
Roman Tsisyk <roman@organicmaps.app>
Viktor Havaka <viktor.govako@gmail.com>

View file

@ -1,4 +1,5 @@
Copyright 2021 Alexander Borsuk <me@alex.bio>
Copyright 2024 Organic Maps Contributors (see the CONTRIBUTORS file).
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View file

@ -12,9 +12,11 @@ npm i
## Development
Use `npx wrangler dev --local` for localhost development.
Use `npx wrangler dev` for localhost development and for testing using Cloudflare dev tools.
Use `npx wrangler dev` to test local changes using Cloudflare dev tools.
```
curl -H "X-OM-DataVersion: 241001" -H "X-OM-AppVersion: 2024.10.22-10-Google" -H 'Accept-Language: fr-FR' http://localhost:8787/maps
```
## Update node dependencies to their major versions

14191
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,30 +7,25 @@
"scripts": {
"build": "esbuild src/index.ts --bundle --outfile=dist/index.js",
"test": "jest",
"lint": "eslint --fix --ext .tsx,.ts src/",
"lint:ci": "eslint --ext .tsx,.ts src/ --max-warnings 0",
"format": "prettier --write '{src,test}/**/*.{ts,tsx}' '*.json' '*.yml' '*.toml' '.github/**/*.yml'",
"format:ci": "prettier --check '{src,test}/**/*.{ts,tsx}' '*.json' '*.yml' '*.toml' '.github/**/*.yml'",
"format": "prettier --write '{src,test}/**/*.{ts,tsx,json}' '*.json' '*.toml' '.github/**/*.yml'",
"format:ci": "prettier --check '{src,test}/**/*.{ts,tsx,json}' '*.json' '*.toml' '.github/**/*.yml'",
"upgrade": "npx npm-check-updates -u && npm install",
"logs": "npx wrangler tail --env prod --format json"
},
"author": "Alexander Borsuk <me@alex.bio>",
"license": "MIT",
"devDependencies": {
"@cloudflare/workers-types": "^4.20221111.1",
"@types/jest": "^29.2.5",
"@typescript-eslint/eslint-plugin": "^5.48.1",
"@typescript-eslint/parser": "^5.48.1",
"esbuild": "^0.16.17",
"eslint": "^8.31.0",
"jest": "^29.3.1",
"jest-environment-miniflare": "^2.11.0",
"miniflare": "^2.11.0",
"npm-check-updates": "^16.6.2",
"prettier": "^2.8.2",
"prettier-plugin-toml": "^0.3.1",
"ts-jest": "^29.0.5",
"typescript": "^4.9.4",
"wrangler": "^2.7.1"
"@cloudflare/workers-types": "^4.20241205.0",
"@types/jest": "^29.5.14",
"esbuild": "^0.24.0",
"jest": "^29.7.0",
"jest-environment-miniflare": "^2.14.4",
"miniflare": "^3.20241205.0",
"npm-check-updates": "^17.1.11",
"prettier": "^3.4.2",
"prettier-plugin-toml": "^2.0.1",
"ts-jest": "^29.2.5",
"typescript": "^5.7.2",
"wrangler": "^3.95.0"
}
}

View file

@ -1,60 +1,6 @@
export {};
import { parseDataVersion, parseAppVersion } from './versions';
// TODO: Implement automated version checks from this metaserver script.
// It should check by cron if actual files are really available on all servers.
export const SERVER = {
backblaze: {
// BackBlaze + CloudFlare (US-West) unmetered.
url: 'https://cdn-us1.organicmaps.app/',
dataVersions: [
210529, 210703, 210729, 210825, 211002, 211022, 211122, 220103, 220204, 220314, 220415, 220515, 220613, 220718,
220816, 220912, 221029, 221119, 221216, 230121,
],
},
uk1: {
// Mythic Beasts VPS (London, UK) 200TB/mo.
url: 'https://cdn-uk1.organicmaps.app/',
dataVersions: [221119, 221216, 230121],
},
nl1: {
// // Mythic Beasts VPS (Amsterdam, NL) 200TB/mo.
url: 'https://cdn-nl1.organicmaps.app/',
dataVersions: [221119, 221216, 230121],
},
planet: {
// Hetzner BareMetal (Falkenstein, Germany) unmetered
url: 'https://cdn.organicmaps.app/',
dataVersions: [
220103, 220204, 220314, 220415, 220515, 220613, 220718, 220816, 220912, 221029, 221119, 221216, 230121,
],
},
fi1: {
// Hetzner Cloud (Helsinki, Finland), 20TB/mo
url: 'https://cdn-fi1.organicmaps.app/',
dataVersions: [221216, 230121],
},
de1: {
// Hetzner Cloud (Falkenstein, Germany), 20TB/mo
url: 'https://cdn-eu2.organicmaps.app/',
dataVersions: [221216, 230121],
},
de2: {
// Hetzner Cloud (Falkenstein, Germany), 20TB/mo
url: 'https://cdn-de2.organicmaps.app/',
dataVersions: [221119, 221216, 230121],
},
us2: {
// Hetzner Cloud (Asburn, US East), 20TB/mo
url: 'https://cdn-us2.organicmaps.app/',
dataVersions: [221216, 230121],
},
};
// Exported for tests.
export const DONATE_URL = 'https://organicmaps.app/donate/';
export const DONATE_URL_RU = 'https://organicmaps.app/ru/donate/';
import { getServersList } from './servers';
// Main entry point.
addEventListener('fetch', (event) => {
@ -67,107 +13,8 @@ export async function handleRequest(request: Request) {
switch (pathname) {
case '/maps': // Public for map files.
case '/resources': // Public for resources.
case '/servers': {
// Private for map files.
let servers;
// Starting from 2021-09, our clients have 'X-OM-DataVersion' header with the value
// of their current maps data version, for example, "211022" (October 22, 2021).
// It is lowercased by Cloudflare.
const dataVersion = parseDataVersion(request.headers.get('x-om-dataversion'));
if (dataVersion === null) {
// Older clients download from the archive.
servers = [SERVER.backblaze];
} else {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore workarounds error TS2339: Property 'continent' does not exist on type 'IncomingRequestCfProperties<unknown>'.
switch (request.cf?.continent) {
// See https://developers.cloudflare.com/firewall/cf-firewall-language/fields for a list of all continents.
case 'NA': // North America
case 'SA': // South America
case 'OC': // Oceania
servers = [SERVER.backblaze, SERVER.us2, SERVER.uk1, SERVER.nl1, SERVER.planet].filter((server) =>
server.dataVersions.includes(dataVersion),
);
break;
default:
// Every other continent + Tor networks.
servers = [SERVER.planet, SERVER.uk1, SERVER.nl1, SERVER.fi1, SERVER.de1, SERVER.de2].filter((server) =>
server.dataVersions.includes(dataVersion),
);
// Only fallback to the archive in the US if nothing was found closer.
if (servers.length == 0 && SERVER.backblaze.dataVersions.includes(dataVersion)) {
servers = [SERVER.backblaze];
}
}
}
// Fallback to the planet with freshly generated/beta data.
if (servers.length == 0) {
servers = [SERVER.planet];
}
servers = servers.map((server) => server.url);
// Header "X-OM-AppVersion: 2022.09.22-3-Google" (lowercased by CF) is supported from August 23, 2022.
const appVersion = parseAppVersion(request.headers.get('x-om-appversion'));
if (!appVersion) {
// Old format for <220823
return new Response(JSON.stringify(servers), {
headers: { 'Content-Type': 'application/json' },
});
}
// New format for >=220823
const response: {
servers: string[];
settings?: {
DonateUrl?: string;
NY?: string;
};
} = {
servers: servers,
};
// Disable donates for reviewers for all app versions AFTER this one.
const lastApprovedAndReleasedGoogleAppVersionCode = 230125;
const lastApprovedAndReleasediOSAppVersionCode = 230125;
let donatesEnabled = true;
if (
appVersion.flavor === 'google' &&
((request.cf?.asOrganization || '').toLowerCase().includes('google') ||
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) {
// To count enabled donations.
console.log('Donates enabled');
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore workarounds error TS2339: Property 'country' does not exist on type 'IncomingRequestCfProperties<unknown>'.
if (request.cf?.country == 'RU') {
response.settings = {
DonateUrl: DONATE_URL_RU,
NY: 'false', // Must be `string` instead of `bool`, otherwise clients will crash
};
} else {
response.settings = {
DonateUrl: DONATE_URL,
NY: 'false', // Must be `string` instead of `bool`, otherwise clients will crash
};
}
}
return new Response(JSON.stringify(response), {
headers: { 'Content-Type': 'application/json' },
});
}
case '/servers':
return getServersList(request);
}
return new Response('', { status: 404 });
}

44
src/locales.json Normal file
View file

@ -0,0 +1,44 @@
{
"en": {
"placePagePrompt": "Organic Maps app is free for everyone, thanks to your donations. No ads. No trackers. Open source.",
"perMonth": "/month",
"perYear": "/year",
"otherAmount": "Other"
},
"de": {
"placePagePrompt": "Organic Maps ist dank deiner Spenden für alle kostenlos. Keine Werbung. Keine Tracker. Open Source.",
"perMonth": "/Monat",
"perYear": "/Jahr",
"otherAmount": "Andere"
},
"fr": {
"placePagePrompt": "L'application Organic Maps est gratuite pour tout le monde grâce à vos dons. Pas de publicité. Pas de trackers. Open-source.",
"perMonth": "/mois",
"perYear": "/an",
"otherAmount": "Autre"
},
"nl": {
"placePagePrompt": "De Organic Maps app is gratis voor iedereen dankzij jullie donaties. Geen advertenties. Geen trackers. Open-source.",
"perMonth": "/maand",
"perYear": "/jaar",
"otherAmount": "Ander"
},
"it": {
"placePagePrompt": "L'app Organic Maps è gratuita per tutti grazie alle vostre donazioni. Nessuna pubblicità. Nessun tracker. Open-source.",
"perMonth": "/mese",
"perYear": "/anno",
"otherAmount": "Altro"
},
"es": {
"placePagePrompt": "Organic Maps es gratis para todos gracias a sus donaciones. Sin anuncios. Sin rastreadores. Código abierto.",
"perMonth": "/mes",
"perYear": "/año",
"otherAmount": "Otro"
},
"pt": {
"placePagePrompt": "O app Organic Maps é gratuito para todos graças às suas doações. Sem anúncios. Sem rastreadores. Código aberto.",
"perMonth": "/mês",
"perYear": "/ano",
"otherAmount": "Outro"
}
}

15
src/locales.ts Normal file
View file

@ -0,0 +1,15 @@
import LOCALES_JSON from './locales.json';
export interface Locale {
placePagePrompt: string;
perMonth: string;
perYear: string;
otherAmount: string;
}
export interface Locales {
[key: string]: Locale;
}
const LOCALES = LOCALES_JSON as Locales;
export default LOCALES;

198
src/products.json Normal file
View file

@ -0,0 +1,198 @@
{
"FR": [
{
"title": "4,99€$per_month",
"link": "https://donate.stripe.com/6oEg2912f2c81r200j"
},
{
"title": "34,99€$per_year",
"link": "https://donate.stripe.com/eVa2bjdP19EA0mY6oI"
},
{
"title": "$other",
"link": "https://donate.stripe.com/3csg29aCP0401r2dRj"
}
],
"DE": [
{
"title": "4,99€$per_month",
"link": "https://donate.stripe.com/6oEg2912f2c81r200j"
},
{
"title": "34,99€$per_year",
"link": "https://donate.stripe.com/eVa2bjdP19EA0mY6oI"
},
{
"title": "$other",
"link": "https://donate.stripe.com/3csg29aCP0401r2dRj"
}
],
"NL": [
{
"title": "4,99€$per_month",
"link": "https://donate.stripe.com/6oEg2912f2c81r200j"
},
{
"title": "34,99€$per_year",
"link": "https://donate.stripe.com/eVa2bjdP19EA0mY6oI"
},
{
"title": "$other",
"link": "https://donate.stripe.com/3csg29aCP0401r2dRj"
}
],
"IT": [
{
"title": "4,99€$per_month",
"link": "https://donate.stripe.com/6oEg2912f2c81r200j"
},
{
"title": "34,99€$per_year",
"link": "https://donate.stripe.com/eVa2bjdP19EA0mY6oI"
},
{
"title": "$other",
"link": "https://donate.stripe.com/3csg29aCP0401r2dRj"
}
],
"ES": [
{
"title": "4,99€$per_month",
"link": "https://donate.stripe.com/6oEg2912f2c81r200j"
},
{
"title": "34,99€$per_year",
"link": "https://donate.stripe.com/eVa2bjdP19EA0mY6oI"
},
{
"title": "$other",
"link": "https://donate.stripe.com/3csg29aCP0401r2dRj"
}
],
"PT": [
{
"title": "4,99€$per_month",
"link": "https://donate.stripe.com/6oEg2912f2c81r200j"
},
{
"title": "34,99€$per_year",
"link": "https://donate.stripe.com/eVa2bjdP19EA0mY6oI"
},
{
"title": "$other",
"link": "https://donate.stripe.com/3csg29aCP0401r2dRj"
}
],
"BE": [
{
"title": "4,99€$per_month",
"link": "https://donate.stripe.com/6oEg2912f2c81r200j"
},
{
"title": "34,99€$per_year",
"link": "https://donate.stripe.com/eVa2bjdP19EA0mY6oI"
},
{
"title": "$other",
"link": "https://donate.stripe.com/3csg29aCP0401r2dRj"
}
],
"AT": [
{
"title": "4,99€$per_month",
"link": "https://donate.stripe.com/6oEg2912f2c81r200j"
},
{
"title": "34,99€$per_year",
"link": "https://donate.stripe.com/eVa2bjdP19EA0mY6oI"
},
{
"title": "$other",
"link": "https://donate.stripe.com/3csg29aCP0401r2dRj"
}
],
"LU": [
{
"title": "4,99€$per_month",
"link": "https://donate.stripe.com/6oEg2912f2c81r200j"
},
{
"title": "34,99€$per_year",
"link": "https://donate.stripe.com/eVa2bjdP19EA0mY6oI"
},
{
"title": "$other",
"link": "https://donate.stripe.com/3csg29aCP0401r2dRj"
}
],
"MC": [
{
"title": "4,99€$per_month",
"link": "https://donate.stripe.com/6oEg2912f2c81r200j"
},
{
"title": "34,99€$per_year",
"link": "https://donate.stripe.com/eVa2bjdP19EA0mY6oI"
},
{
"title": "$other",
"link": "https://donate.stripe.com/3csg29aCP0401r2dRj"
}
],
"AD": [
{
"title": "4,99€$per_month",
"link": "https://donate.stripe.com/6oEg2912f2c81r200j"
},
{
"title": "34,99€$per_year",
"link": "https://donate.stripe.com/eVa2bjdP19EA0mY6oI"
},
{
"title": "$other",
"link": "https://donate.stripe.com/3csg29aCP0401r2dRj"
}
],
"SM": [
{
"title": "4,99€$per_month",
"link": "https://donate.stripe.com/6oEg2912f2c81r200j"
},
{
"title": "34,99€$per_year",
"link": "https://donate.stripe.com/eVa2bjdP19EA0mY6oI"
},
{
"title": "$other",
"link": "https://donate.stripe.com/3csg29aCP0401r2dRj"
}
],
"GB": [
{
"title": "£4.99$per_month",
"link": "https://donate.stripe.com/8wMg29fX98Awd9K28u"
},
{
"title": "£34.99$per_year",
"link": "https://donate.stripe.com/eVabLT9yL2c89Xy7sP"
},
{
"title": "$other",
"link": "https://donate.stripe.com/9AQg29h1dcQMedO3cH"
}
],
"US": [
{
"title": "$5.49$per_month",
"link": "https://donate.stripe.com/00g3fncKXcQMedO5kL"
},
{
"title": "$36.99$per_year",
"link": "https://donate.stripe.com/bIY6rz5ivcQM9XyaF6"
},
{
"title": "$other",
"link": "https://donate.stripe.com/eVa8zH5ivbMIfhS6oS"
}
]
}

40
src/products.ts Normal file
View file

@ -0,0 +1,40 @@
import LOCALES from './locales';
import PRODUCTS_JSON from './products.json';
export interface Product {
title: string;
link: string;
}
const PRODUCTS = PRODUCTS_JSON as Record<string, Product[]>;
export interface ProductsConfig {
placePagePrompt: string;
products: Product[];
}
export function getProducts(locale: string | null): ProductsConfig | undefined {
if (!locale) {
return undefined;
}
const parts = locale.split(/[-_]/);
const language = parts[0].toLowerCase();
const country = parts[1] ? parts[1].toUpperCase() : '';
const products = PRODUCTS[country];
const trans = LOCALES[language];
if (products === undefined || trans === undefined) {
return undefined;
}
return {
placePagePrompt: trans.placePagePrompt,
products: products.map((product) => ({
...product,
title: product.title
.replace('$other', trans.otherAmount)
.replace('$per_month', trans.perMonth)
.replace('$per_year', trans.perYear),
})),
};
}

239
src/servers.ts Normal file
View file

@ -0,0 +1,239 @@
import { parseDataVersion, parseAppVersion } from './versions';
import { getProducts, ProductsConfig } from './products';
export const DATA_VERSIONS = [
210529, //
210703,
210729,
210825,
211002,
211022,
211122,
220103,
220204,
220314,
220415,
220515,
220613,
220718,
220816,
220912,
221029,
221119,
221216,
230121,
230210,
230227,
230329,
230503,
230602,
230710,
230814,
230920,
231113,
231213,
240105,
240202,
240228,
240326,
240429,
240528,
240613,
240702,
240723,
240810,
240904,
241001,
241017,
241107,
241122,
250121,
250213,
250227,
];
const kUnlimited = 99999;
// TODO: Implement automated version checks from this metaserver script.
// It should check by cron if actual files are really available on all servers.
export const SERVER = {
backblaze: {
// BackBlaze + CloudFlare (US-West) unmetered.
url: 'https://cdn-us1.organicmaps.app/',
dataVersions: kUnlimited,
},
uk1: {
// Mythic Beasts VPS (London, UK) 200TB/mo.
url: 'https://cdn-uk1.organicmaps.app/',
dataVersions: 3,
},
nl1: {
// // Mythic Beasts VPS (Amsterdam, NL) 200TB/mo.
url: 'https://cdn-nl1.organicmaps.app/',
dataVersions: 3,
},
planet: {
// Hetzner BareMetal (Helsinki, Finland) unmetered
url: 'https://cdn.organicmaps.app/',
dataVersions: kUnlimited,
},
beta: {
// Alias of the planet above that is proxied via CF and with enabled /maps/ *.mwm caching,
// to speed-up downloads for beta testers.
url: 'https://cdn-beta.organicmaps.app/',
// Can have any non-publicly available maps data version.
dataVersions: [],
},
fi1: {
// Hetzner Cloud (Helsinki, Finland), 20TB/mo
url: 'https://cdn-fi1.organicmaps.app/',
dataVersions: 2,
},
de1: {
// Hetzner Cloud (Falkenstein, Germany), 20TB/mo
url: 'https://cdn-eu2.organicmaps.app/',
dataVersions: 2,
},
de2: {
// Hetzner Cloud (Falkenstein, Germany), 20TB/mo
url: 'https://cdn-de2.organicmaps.app/',
dataVersions: 3,
},
de3: {
// Hetzner Cloud (Nuremberg, Germany), 20TB/mo
url: 'https://cdn-de3.organicmaps.app/',
dataVersions: 4,
},
us_east1: {
// Hetzner Cloud (Ashburn, US East), 20TB/mo
url: 'https://cdn-us-east1.organicmaps.app/',
dataVersions: 3,
},
us_west1: {
// Hetzner Cloud (Hillsdate, US West), 20TB/mo
url: 'https://cdn-us-west1.organicmaps.app/',
dataVersions: 2,
},
vi1: {
// Vietnam, unlimited 1Gbps bandwidth
url: 'https://cdn-vi1.organicmaps.app/',
dataVersions: 5,
},
};
// Exported for tests.
export const DONATE_URL = 'https://organicmaps.app/donate/';
export async function getServersList(request: Request) {
// Private for map files.
let servers;
// Starting from 2021-09, our clients have 'X-OM-DataVersion' header with the value
// of their current maps data version, for example, "211022" (October 22, 2021).
// It is lowercased by Cloudflare.
const dataVersion = parseDataVersion(request.headers.get('x-om-dataversion'));
const abusedVersions = ['1.8.6-4-ios', '1.8.7-1-ios', '1.8.8-1-ios'];
if (dataVersion === null) {
// Older clients download from the archive.
servers = [SERVER.backblaze];
} else if (dataVersion == 240702 && abusedVersions.includes(request.headers.get('x-om-appversion') || 'unknown')) {
// Redirect https://apps.apple.com/us/app/mapxplorer-navigation-radar/id6463052823
// who abuses our servers to a slow download "trap" node.
return new Response('["https://cdn-fi2.organicmaps.app/"]', {
headers: { 'Content-Type': 'application/json' },
});
} else {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore workarounds error TS2339: Property 'continent' does not exist on type 'IncomingRequestCfProperties<unknown>'.
switch (request.cf?.continent) {
// See https://developers.cloudflare.com/firewall/cf-firewall-language/fields for a list of all continents.
case 'NA': // North America
case 'SA': // South America
servers = [SERVER.us_east1, SERVER.us_west1, SERVER.uk1, SERVER.nl1, SERVER.planet].filter((server) =>
DATA_VERSIONS.slice(-server.dataVersions).includes(dataVersion),
);
break;
case 'OC': // Oceania
servers = [SERVER.vi1, SERVER.us_east1, SERVER.us_west1, SERVER.planet].filter((server) =>
DATA_VERSIONS.slice(-server.dataVersions).includes(dataVersion),
);
break;
case 'AS': // Asia
servers = [SERVER.vi1, SERVER.uk1, SERVER.nl1, SERVER.planet].filter((server) =>
DATA_VERSIONS.slice(-server.dataVersions).includes(dataVersion),
);
break;
default:
// Every other continent + Tor networks.
servers = [SERVER.planet, SERVER.uk1, SERVER.nl1, SERVER.fi1, SERVER.de1, SERVER.de2, SERVER.de3].filter(
(server) => DATA_VERSIONS.slice(-server.dataVersions).includes(dataVersion),
);
// Only fallback to the archive in the US if nothing was found closer.
if (servers.length == 0 && DATA_VERSIONS.slice(-SERVER.backblaze.dataVersions).includes(dataVersion)) {
servers = [SERVER.backblaze];
}
}
}
// Fallback to the planet with freshly generated/beta data.
if (servers.length == 0) {
servers = [SERVER.beta, SERVER.planet];
}
servers = servers.map((server) => server.url);
// Header "X-OM-AppVersion: 2022.09.22-3-Google" (lowercased by CF) is supported from August 23, 2022.
const appVersion = parseAppVersion(request.headers.get('x-om-appversion'));
if (!appVersion) {
// Old format for <220823
return new Response(JSON.stringify(servers), {
headers: { 'Content-Type': 'application/json' },
});
}
// New format for >=220823
const response: {
servers: string[];
settings?: {
DonateUrl?: string;
NY?: string;
};
productsConfig?: ProductsConfig;
} = {
servers: servers,
};
// Disable donates for reviewers for all app versions AFTER this one.
const lastApprovedAndReleasedGoogleAppVersionCode = 250217;
const lastApprovedAndReleasediOSAppVersionCode = 250303;
let donatesEnabled = true;
if (
appVersion.flavor === 'google' &&
((typeof request.cf?.asOrganization === 'string' && request.cf?.asOrganization.toLowerCase().includes('google')) ||
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' &&
((typeof request.cf?.asOrganization === 'string' && request.cf?.asOrganization.toLowerCase().includes('apple')) ||
appVersion.code > lastApprovedAndReleasediOSAppVersionCode)
) {
donatesEnabled = false;
}
if (donatesEnabled) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
response.settings = {
DonateUrl: DONATE_URL,
NY: 'false', // Must be `string` instead of `bool`, otherwise clients will crash
};
if (appVersion.code >= 241022) {
const locale = request.headers.get('accept-language');
response.productsConfig = getProducts(locale);
}
}
return new Response(JSON.stringify(response), {
headers: { 'Content-Type': 'application/json' },
});
}

View file

@ -16,7 +16,10 @@ export function parseDataVersion(strDataVersion: string | null): number | null {
// 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})(?:-([^-]+))?)/;
// 2022.12.24-3-3f4ca43-Linux or 2022.12.24-3-3f4ca43-dirty-Linux for Linux
// 2022.12.24-3-3f4ca43-Darwin for Mac
const VERSION_RE =
/(?<year>\d{4})\.(?<month>\d{1,2})\.(?<day>\d{1,2})(?:$|-(?<build>[0-9]+)(?:-[0-9a-f]+)?(?:-dirty)?-(?<flavor>[A-Za-z3264]+))/;
// Returns code like 221224 for both platforms, build and flavor for Android and newer iOS versions.
export function parseAppVersion(
versionName: string | null,
@ -26,32 +29,32 @@ export function parseAppVersion(
}
const m = versionName.match(VERSION_RE);
if (m === null || m.length < 4) {
if (m === null || m.length < 4 || !m.groups) {
return null;
}
const yyyy = parseInt(m[1]);
const yyyy = parseInt(m.groups.year);
if (Number.isNaN(yyyy) || yyyy > 2099 || yyyy < 2022) {
return null;
}
const mm = parseInt(m[2]);
const mm = parseInt(m.groups.month);
if (Number.isNaN(mm) || mm > 12 || mm < 1) {
return null;
}
const dd = parseInt(m[3]);
const dd = parseInt(m.groups.day);
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) {
if (!m.groups.build) {
return { code: code };
}
const buildNumber = parseInt(m[4]);
const buildNumber = parseInt(m.groups.build);
const build = Number.isNaN(buildNumber) ? 0 : buildNumber;
// 'ios' for iOS devices.
const flavor = (m[5] !== undefined && m[5].toLowerCase()) || undefined;
const flavor = (m.groups.flavor !== undefined && m.groups.flavor.toLowerCase()) || undefined;
return {
code: code,

14
test/products.test.ts Normal file
View file

@ -0,0 +1,14 @@
import { describe, expect, test } from '@jest/globals';
import { getProducts } from '../src/products';
describe('getProducts', () => {
test('fr-FR', () => {
const fr_FR = getProducts('fr-FR');
expect(fr_FR).toBeDefined();
if (!fr_FR) return;
expect(fr_FR.placePagePrompt).toBe(
"L'application Organic Maps est gratuite pour tout le monde grâce à vos dons. Pas de publicité. Pas de trackers. Open-source.",
);
expect(fr_FR.products[fr_FR.products.length - 1].title).toEqual('Autre');
});
});

View file

@ -1,14 +1,14 @@
import { describe, expect, test } from '@jest/globals';
import { handleRequest, SERVER, DONATE_URL, DONATE_URL_RU } from '../src/index';
import { getServersList, SERVER, DATA_VERSIONS, DONATE_URL } from '../src/servers';
const URL = 'https://worker/servers';
const LAST_DATA_VERSION = SERVER.planet.dataVersions[SERVER.planet.dataVersions.length - 1];
const LAST_DATA_VERSION = DATA_VERSIONS[DATA_VERSIONS.length - 1];
// 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);
const result = await getServersList(req);
expect(result.status).toBe(200);
expect(JSON.parse(await result.text())).toEqual([SERVER.backblaze.url]);
});
@ -17,10 +17,10 @@ describe('X-OM-DataVersion', () => {
const server = SERVER.fi1;
let req = new Request(URL, {
headers: {
'X-OM-DataVersion': String(server.dataVersions[0]),
'X-OM-DataVersion': String(LAST_DATA_VERSION),
},
});
const result = await handleRequest(req);
const result = await getServersList(req);
expect(result.status).toBe(200);
expect(JSON.parse(await result.text())).toContain(server.url);
});
@ -31,16 +31,16 @@ describe('X-OM-DataVersion', () => {
'X-OM-DataVersion': '210000', // this version doesn't exist on servers
},
});
const result = await handleRequest(req);
const result = await getServersList(req);
expect(result.status).toBe(200);
expect(JSON.parse(await result.text())).toEqual([SERVER.planet.url]);
expect(JSON.parse(await result.text())).toEqual([SERVER.beta.url, 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);
const response = await getServersList(req);
expect(response.status).toBe(200);
expect(JSON.parse(await response.text())).toEqual([SERVER.backblaze.url]);
});
@ -51,10 +51,10 @@ describe('X-OM-AppVersion DonateUrl', () => {
let req = new Request(URL, {
headers: {
'X-OM-AppVersion': '2022.08.23-1-Google',
'X-OM-DataVersion': String(server.dataVersions[0]),
'X-OM-DataVersion': String(LAST_DATA_VERSION),
},
});
const response = await handleRequest(req);
const response = await getServersList(req);
expect(response.status).toBe(200);
const result = JSON.parse(await response.text());
expect(result.servers).toBeDefined();
@ -69,26 +69,25 @@ describe('X-OM-AppVersion DonateUrl', () => {
let req = new Request(URL, {
headers: {
'X-OM-AppVersion': '2022.08.23-1-Google',
'X-OM-DataVersion': String(server.dataVersions[0]),
'X-OM-DataVersion': String(LAST_DATA_VERSION),
},
//@ts-ignore
cf: { country: 'RU' },
});
const response = await handleRequest(req);
const response = await getServersList(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]),
'X-OM-DataVersion': String(LAST_DATA_VERSION),
},
});
const response = await handleRequest(req);
const response = await getServersList(req);
expect(response.status).toBe(200);
const result = JSON.parse(await response.text());
expect(result.settings).not.toBeDefined();
@ -98,10 +97,10 @@ describe('X-OM-AppVersion DonateUrl', () => {
let req = new Request(URL, {
headers: {
'X-OM-AppVersion': '2022.11.20-4-ios',
'X-OM-DataVersion': String(server.dataVersions[0]),
'X-OM-DataVersion': String(LAST_DATA_VERSION),
},
});
const response = await handleRequest(req);
const response = await getServersList(req);
expect(response.status).toBe(200);
const result = JSON.parse(await response.text());
expect(result.settings.DonateUrl).toBeDefined();

View file

@ -24,12 +24,19 @@ describe('parseAppVersion', () => {
'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 },
// There were no such versions in production.
'2022.08.01-1': null,
'2022.08.01-1-Google': { code: 220801, build: 1, flavor: 'google' },
// -debug is ignored
'2022.08.01-1-Google-debug': { code: 220801, build: 1, flavor: 'google' },
'2022.1.1-0': { code: 220101, build: 0 },
'2099.12.31-999999999': { code: 991231, build: 999999999 },
// TODO: Fix regexp. Not it should not happen in production.
//'2022.08.01-1-fd-debug': { code: 220801, build: 1, flavor: 'fd' },
'2022.1.1-0': null,
'2099.12.31-999999999': null,
'2023.03.22-1-4fac32de-Linux': { code: 230322, build: 1, flavor: 'linux' },
'2023.03.22-1-4fac32de-dirty-Linux': { code: 230322, build: 1, flavor: 'linux' },
'2023.03.22-1-4fac32de-Darwin': { code: 230322, build: 1, flavor: 'darwin' },
'2023.03.22-1-4fac32de-dirty-Darwin': { code: 230322, build: 1, flavor: 'darwin' },
'2021.01.31-1': null,
'2100.01.31-1': null,
'2022.00.31-1': null,

View file

@ -11,6 +11,7 @@
"preserveConstEnums": true,
"sourceMap": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"types": ["@cloudflare/workers-types"]
},
"include": ["src/"],