feat(analytics): Google Analytics・同意モード・一部機能のトラッキング実装 (MisskeyIO#784)

This commit is contained in:
あわわわとーにゅ 2024-11-06 01:28:14 +09:00 committed by GitHub
parent 2f4c48bbe6
commit fcfd004c38
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
53 changed files with 805 additions and 113 deletions

View file

@ -7,8 +7,39 @@ import * as Misskey from 'misskey-js';
import { ref } from 'vue';
import { apiUrl } from '@/config.js';
import { $i } from '@/account.js';
import { miLocalStorage } from '@/local-storage.js';
export const pendingApiRequestsCount = ref(0);
let id: string | null = miLocalStorage.getItem('id');
export function generateClientTransactionId(initiator: string) {
if (id === null) {
id = crypto.randomUUID();
miLocalStorage.setItem('id', id);
}
return `${id}-${initiator}-${crypto.randomUUID()}`;
}
function handleResponse<_ResT>(
resolve: (value: (_ResT | PromiseLike<_ResT>)) => void,
reject: (reason?: any) => void,
): ((value: Response) => (void | PromiseLike<void>)) {
return async (res) => {
if (res.ok && res.status !== 204) {
const body = await res.json();
resolve(body);
} else if (res.status === 204) {
resolve(undefined as _ResT); // void -> undefined
} else {
// エラー応答で JSON.parse に失敗した場合は HTTP ステータスコードとメッセージを返す
const body = await res
.json()
.catch(() => ({ statusCode: res.status, message: res.statusText }));
reject(typeof body.error === 'object' ? body.error : body);
}
};
}
// Implements Misskey.api.ApiClient.request
export function misskeyApi<
ResT = void,
@ -20,6 +51,7 @@ export function misskeyApi<
data: P = {} as any,
token?: string | null | undefined,
signal?: AbortSignal,
initiator: string = 'misskey',
): Promise<_ResT> {
if (endpoint.includes('://')) throw new Error('invalid endpoint');
pendingApiRequestsCount.value++;
@ -41,20 +73,10 @@ export function misskeyApi<
cache: 'no-cache',
headers: {
'Content-Type': 'application/json',
'X-Client-Transaction-Id': generateClientTransactionId(initiator),
},
signal,
}).then(async (res) => {
if (res.ok && res.status !== 204) {
const body = await res.json();
resolve(body);
} else if (res.status === 204) {
resolve(undefined as _ResT); // void -> undefined
} else {
// エラー応答で JSON.parse に失敗した場合は HTTP ステータスコードとメッセージを返す
const body = await res.json().catch(() => ({ statusCode: res.status, message: res.statusText }));
reject(typeof body.error === 'object' ? body.error : body);
}
}).catch(reject);
}).then(handleResponse(resolve, reject)).catch(reject);
});
promise.then(onFinally, onFinally);
@ -71,6 +93,7 @@ export function misskeyApiGet<
>(
endpoint: E,
data: P = {} as any,
initiator: string = 'misskey',
): Promise<_ResT> {
pendingApiRequestsCount.value++;
@ -86,17 +109,10 @@ export function misskeyApiGet<
method: 'GET',
credentials: 'omit',
cache: 'default',
}).then(async (res) => {
const body = res.status === 204 ? null : await res.json();
if (res.status === 200) {
resolve(body);
} else if (res.status === 204) {
resolve(undefined as _ResT); // void -> undefined
} else {
reject(body.error);
}
}).catch(reject);
headers: {
'X-Client-Transaction-Id': generateClientTransactionId(initiator),
},
}).then(handleResponse(resolve, reject)).catch(reject);
});
promise.then(onFinally, onFinally);