From 927e7df4e90262abf5d37b2814c4c5460deff692 Mon Sep 17 00:00:00 2001 From: Zhiyuan Zheng Date: Mon, 21 Jun 2021 11:59:29 +0200 Subject: [PATCH] Use new api gateway --- .envrc.example | 2 +- .github/workflows/build.yml | 2 +- app.config.ts | 2 +- package.json | 4 +- src/api/tooot.ts | 104 ++++++++++++++++++ src/utils/push/useConnect.ts | 13 +-- src/utils/queryHooks/translate.ts | 19 +--- src/utils/slices/instances/push/register.ts | 20 ++-- src/utils/slices/instances/push/unregister.ts | 10 +- .../slices/instances/updatePushDecode.ts | 10 +- src/utils/slices/instancesSlice.ts | 2 - 11 files changed, 137 insertions(+), 51 deletions(-) create mode 100644 src/api/tooot.ts diff --git a/.envrc.example b/.envrc.example index 70045951..ef1c1556 100644 --- a/.envrc.example +++ b/.envrc.example @@ -5,7 +5,7 @@ export SENTRY_PROJECT="" export SENTRY_AUTH_TOKEN="" export SENTRY_DSN="" -export TRANSLATE_KEY="" +export TOOOT_API_KEY="" # Fastlane start export LC_ALL="" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9bd506fc..73ce0f1d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,7 @@ jobs: SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN: ${{ secrets.SENTRY_DSN }} - TRANSLATE_KEY: ${{ secrets.TRANSLATE_KEY }} + TOOOT_API_KEY: ${{ secrets.TOOOT_API_KEY }} FASTLANE_USER: ${{ secrets.FASTLANE_USER }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }} diff --git a/app.config.ts b/app.config.ts index 7882a256..6344887b 100644 --- a/app.config.ts +++ b/app.config.ts @@ -14,7 +14,7 @@ export default (): ExpoConfig => ({ assetBundlePatterns: ['assets/*'], extra: { sentryDSN: process.env.SENTRY_DSN, - translateKey: process.env.TRANSLATE_KEY + toootApiKey: process.env.TOOOT_API_KEY }, hooks: { postPublish: [ diff --git a/package.json b/package.json index 77704b68..103cb6b0 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "versions": { "native": "210511", "major": 2, - "minor": 0, - "patch": 5, + "minor": 1, + "patch": 0, "expo": "41.0.0" }, "description": "tooot app for Mastodon", diff --git a/src/api/tooot.ts b/src/api/tooot.ts new file mode 100644 index 00000000..0958661a --- /dev/null +++ b/src/api/tooot.ts @@ -0,0 +1,104 @@ +import axios from 'axios' +import chalk from 'chalk' +import { Constants } from 'react-native-unimodules' +import * as Sentry from 'sentry-expo' + +const ctx = new chalk.Instance({ level: 3 }) + +export type Params = { + service: 'push' | 'translate' + method: 'get' | 'post' + url: string + params?: { + [key: string]: string | number | boolean | string[] | number[] | boolean[] + } + headers?: { [key: string]: string } + body?: FormData | Object + sentry?: boolean +} + +const DOMAIN = __DEV__ ? 'testapi.tooot.app' : 'api.tooot.app' + +const apiTooot = async ({ + service, + method, + url, + params, + headers, + body, + sentry = false +}: Params): Promise<{ body: T }> => { + const key = Constants.manifest.extra?.toootApiKey + + console.log( + ctx.bgGreen.bold(' API tooot ') + + ' ' + + method + + ctx.green(' -> ') + + `/${url}` + + (params ? ctx.green(' -> ') : ''), + params ? params : '' + ) + + return axios({ + timeout: method === 'post' ? 1000 * 60 : 1000 * 15, + method, + baseURL: `https://${DOMAIN}/`, + url: `${service}/${url}`, + params, + headers: { + ...(key && { 'x-tooot-key': key }), + 'Content-Type': 'application/json', + 'User-Agent': `tooot/${Constants.manifest.version}`, + Accept: '*/*', + ...headers + }, + ...(body && { data: body }) + }) + .then(response => { + return Promise.resolve({ + body: response.data + }) + }) + .catch(error => { + if (sentry) { + Sentry.Native.setExtras(error.response) + Sentry.Native.captureException(error) + } + + if (error.response) { + // The request was made and the server responded with a status code + // that falls out of the range of 2xx + console.error( + ctx.bold(' API tooot '), + ctx.bold('response'), + error.response.status, + error.response.data.error + ) + return Promise.reject({ + status: error.response.status, + message: error.response.data.error + }) + } else if (error.request) { + // The request was made but no response was received + // `error.request` is an instance of XMLHttpRequest in the browser and an instance of + // http.ClientRequest in node.js + console.error( + ctx.bold(' API tooot '), + ctx.bold('request'), + error.request + ) + return Promise.reject() + } else { + console.error( + ctx.bold(' API tooot '), + ctx.bold('internal'), + error.message, + url + ) + return Promise.reject() + } + }) +} + +export default apiTooot diff --git a/src/utils/push/useConnect.ts b/src/utils/push/useConnect.ts index e39f0c07..3144349f 100644 --- a/src/utils/push/useConnect.ts +++ b/src/utils/push/useConnect.ts @@ -1,12 +1,9 @@ import apiGeneral from '@api/general' +import apiTooot from '@api/tooot' import { displayMessage } from '@components/Message' import { NavigationContainerRef } from '@react-navigation/native' import { Dispatch } from '@reduxjs/toolkit' -import { - disableAllPushes, - Instance, - PUSH_SERVER -} from '@utils/slices/instancesSlice' +import { disableAllPushes, Instance } from '@utils/slices/instancesSlice' import * as Notifications from 'expo-notifications' import { useEffect } from 'react' import { TFunction } from 'react-i18next' @@ -34,10 +31,10 @@ const pushUseConnect = ({ }) ).data - apiGeneral({ + apiTooot({ method: 'post', - domain: PUSH_SERVER, - url: 'v1/connect', + service: 'push', + url: 'connect', body: { expoToken }, diff --git a/src/utils/queryHooks/translate.ts b/src/utils/queryHooks/translate.ts index 6b479627..f7f20e24 100644 --- a/src/utils/queryHooks/translate.ts +++ b/src/utils/queryHooks/translate.ts @@ -1,4 +1,4 @@ -import apiGeneral from '@api/general' +import apiTooot from '@api/tooot' import haptics from '@components/haptics' import { AxiosError } from 'axios' import { Buffer } from 'buffer' @@ -21,16 +21,7 @@ export type QueryKeyTranslate = [ } ] -export const TRANSLATE_SERVER = __DEV__ - ? 'testtranslate.tooot.app' - : 'translate.tooot.app' - const queryFunction = async ({ queryKey }: { queryKey: QueryKeyTranslate }) => { - const key = Constants.manifest.extra?.translateKey - if (!key) { - return Promise.reject() - } - const { uri, source, target, text } = queryKey[1] const uriEncoded = Buffer.from(uri.replace(/https?:\/\//, '')) @@ -42,11 +33,11 @@ const queryFunction = async ({ queryKey }: { queryKey: QueryKeyTranslate }) => { 'base64' ) - const res = await apiGeneral({ - domain: TRANSLATE_SERVER, + const res = await apiTooot({ method: 'get', - url: `v1/translate/${uriEncoded}/${target}`, - headers: { key, original } + service: 'translate', + url: `source/${uriEncoded}/target/${target}`, + headers: { original } }) haptics('Light') return res.body diff --git a/src/utils/slices/instances/push/register.ts b/src/utils/slices/instances/push/register.ts index 830fe9a8..5d631303 100644 --- a/src/utils/slices/instances/push/register.ts +++ b/src/utils/slices/instances/push/register.ts @@ -1,12 +1,8 @@ -import apiGeneral from '@api/general' import apiInstance from '@api/instance' +import apiTooot from '@api/tooot' import i18n from '@root/i18n/i18n' import { RootState } from '@root/store' -import { - getInstance, - Instance, - PUSH_SERVER -} from '@utils/slices/instancesSlice' +import { getInstance, Instance } from '@utils/slices/instancesSlice' import * as Notifications from 'expo-notifications' import { Platform } from 'react-native' import androidDefaults from './androidDefaults' @@ -22,13 +18,13 @@ const register1 = async ({ accountId: Mastodon.Account['id'] accountFull: string }) => { - return apiGeneral<{ + return apiTooot<{ endpoint: string keys: { public: string; private: string; auth: string } }>({ method: 'post', - domain: PUSH_SERVER, - url: 'v1/register1', + service: 'push', + url: 'register1', body: { expoToken, instanceUrl, accountId, accountFull }, sentry: true }) @@ -47,10 +43,10 @@ const register2 = async ({ accountId: Mastodon.Account['id'] removeKeys: boolean }) => { - return apiGeneral({ + return apiTooot({ method: 'post', - domain: PUSH_SERVER, - url: 'v1/register2', + service: 'push', + url: 'register2', body: { expoToken, instanceUrl, accountId, serverKey, removeKeys }, sentry: true }) diff --git a/src/utils/slices/instances/push/unregister.ts b/src/utils/slices/instances/push/unregister.ts index 09949eca..da05239c 100644 --- a/src/utils/slices/instances/push/unregister.ts +++ b/src/utils/slices/instances/push/unregister.ts @@ -1,7 +1,7 @@ -import apiGeneral from '@api/general' import apiInstance from '@api/instance' +import apiTooot from '@api/tooot' import { RootState } from '@root/store' -import { getInstance, PUSH_SERVER } from '@utils/slices/instancesSlice' +import { getInstance } from '@utils/slices/instancesSlice' import * as Notifications from 'expo-notifications' import { Platform } from 'react-native' @@ -19,10 +19,10 @@ const pushUnregister = async (state: RootState, expoToken: string) => { url: 'push/subscription' }) - await apiGeneral<{ endpoint: string; publicKey: string; auth: string }>({ + await apiTooot<{ endpoint: string; publicKey: string; auth: string }>({ method: 'post', - domain: PUSH_SERVER, - url: 'v1/unregister', + service: 'push', + url: 'unregister', body: { expoToken, instanceUrl: instance.url, diff --git a/src/utils/slices/instances/updatePushDecode.ts b/src/utils/slices/instances/updatePushDecode.ts index 2cbcde29..b1c5ef7f 100644 --- a/src/utils/slices/instances/updatePushDecode.ts +++ b/src/utils/slices/instances/updatePushDecode.ts @@ -1,10 +1,10 @@ -import apiGeneral from '@api/general' +import apiTooot from '@api/tooot' import { createAsyncThunk } from '@reduxjs/toolkit' import i18n from '@root/i18n/i18n' import { RootState } from '@root/store' import * as Notifications from 'expo-notifications' import { Platform } from 'react-native' -import { getInstance, Instance, PUSH_SERVER } from '../instancesSlice' +import { getInstance, Instance } from '../instancesSlice' import androidDefaults from './push/androidDefaults' export const updateInstancePushDecode = createAsyncThunk( @@ -25,10 +25,10 @@ export const updateInstancePushDecode = createAsyncThunk( }) ).data - await apiGeneral({ + await apiTooot({ method: 'post', - domain: PUSH_SERVER, - url: 'v1/update-decode', + service: 'push', + url: 'update-decode', body: { expoToken, instanceUrl: instance.url, diff --git a/src/utils/slices/instancesSlice.ts b/src/utils/slices/instancesSlice.ts index 1183184c..16a9345f 100644 --- a/src/utils/slices/instancesSlice.ts +++ b/src/utils/slices/instancesSlice.ts @@ -11,8 +11,6 @@ import { updateInstancePush } from './instances/updatePush' import { updateInstancePushAlert } from './instances/updatePushAlert' import { updateInstancePushDecode } from './instances/updatePushDecode' -export const PUSH_SERVER = __DEV__ ? 'testpush.tooot.app' : 'push.tooot.app' - export type Instance = { active: boolean appData: {