From f53639153e63730d0f530d35c153785a5460213e Mon Sep 17 00:00:00 2001 From: PiEgg Date: Mon, 5 Apr 2021 17:47:06 +0800 Subject: [PATCH] :sparkles: Feature: add baidu tongji for analytics --- src/main.ts | 3 +++ src/main/apis/app/uploader/index.ts | 24 ++++++++++++++++++++++++ src/main/events/ipcList.ts | 28 +++++++++++++++++++++++++++- src/renderer/utils/analytics.ts | 26 ++++++++++++++++++++++++++ src/renderer/utils/common.ts | 9 +++++++++ src/universal/events/constants.ts | 4 ++++ src/universal/types/shims-tsx.d.ts | 4 ++++ src/universal/types/types.d.ts | 16 ++++++++++++++++ 8 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 src/renderer/utils/analytics.ts create mode 100644 src/renderer/utils/common.ts diff --git a/src/main.ts b/src/main.ts index 17bd2a3fb..452231d29 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,6 +9,7 @@ import VueLazyLoad from 'vue-lazyload' import axios from 'axios' import mainMixin from './renderer/utils/mainMixin' import bus from '@/utils/bus' +import { initBaiduTongJi } from './renderer/utils/analytics' webFrame.setVisualZoomLevelLimits(1, 1) webFrame.setLayoutZoomLevelLimits(0, 0) @@ -36,3 +37,5 @@ new Vue({ router, render: h => h(App) }).$mount('#app') + +initBaiduTongJi() diff --git a/src/main/apis/app/uploader/index.ts b/src/main/apis/app/uploader/index.ts index c97970274..939ec18d0 100644 --- a/src/main/apis/app/uploader/index.ts +++ b/src/main/apis/app/uploader/index.ts @@ -12,6 +12,7 @@ import { IWindowList } from 'apis/app/window/constants' import util from 'util' import { IPicGo } from 'picgo/dist/src/types' import { showNotification } from '~/main/utils/common' +import { BAIDU_TONGJI_EVENT } from '~/universal/events/constants' const waitForShow = (webcontent: WebContents) => { return new Promise((resolve, reject) => { @@ -36,6 +37,20 @@ const waitForRename = (window: BrowserWindow, id: number): Promise }) } +const handleBaiduTongJi = (webContents: WebContents, options: IAnalyticsData) => { + const data: IBaiduTongJiOptions = { + category: 'upload', + action: options.fromClipboard ? 'clipboard' : 'files', // 上传剪贴板图片还是选择的文件 + opt_label: JSON.stringify({ + type: options.type, // 上传的图床种类 + count: options.count, // 上传的图片数量 + timestamp: dayjs().format('YYYYMMDDHHmmss'), // 上传完成的时间戳 + duration: options.duration // 耗时 + }) + } + webContents.send(BAIDU_TONGJI_EVENT, data) +} + class Uploader { private webContents: WebContents | null = null private uploading: boolean = false @@ -102,11 +117,20 @@ class Uploader { } return new Promise((resolve) => { try { + const startTime = Date.now() this.uploading = true picgo.upload(img) picgo.once('finished', ctx => { this.uploading = false if (ctx.output.every((item: ImgInfo) => item.imgUrl)) { + if (this.webContents) { + handleBaiduTongJi(this.webContents, { + fromClipboard: !img, + type: db.get('picBed.current') || 'smms', + count: img ? img.length : 1, + duration: Date.now() - startTime + } as IAnalyticsData) + } resolve(ctx.output) } else { resolve(false) diff --git a/src/main/events/ipcList.ts b/src/main/events/ipcList.ts index 1142e47c4..bfd8a193f 100644 --- a/src/main/events/ipcList.ts +++ b/src/main/events/ipcList.ts @@ -13,13 +13,19 @@ import server from '~/main/server' import getPicBeds from '~/main/utils/getPicBeds' import shortKeyHandler from 'apis/app/shortKey/shortKeyHandler' import bus from '@core/bus' -import { TOGGLE_SHORTKEY_MODIFIED_MODE } from '#/events/constants' +import { + TOGGLE_SHORTKEY_MODIFIED_MODE, + BAIDU_TONGJI_INIT, + BAIDU_TONGJI_CODE, + BAIDU_TONGJI_INIT_RES +} from '#/events/constants' import { uploadClipboardFiles, uploadChoosedFiles } from '~/main/apis/app/uploader/apis' import picgoCoreIPC from './picgoCoreIPC' import { handleCopyUrl } from '~/main/utils/common' +import axios from 'axios' export default { listen () { @@ -139,6 +145,26 @@ export default { ipcMain.on('updateServer', () => { server.restart() }) + + ipcMain.on(BAIDU_TONGJI_INIT, (evt: IpcMainEvent) => { + axios.get(`https://hm.baidu.com/hm.js?${BAIDU_TONGJI_CODE}`, { + headers: { + referer: 'https://molunerfinn.com/' + } + }).then(res => { + if (res.status === 200) { + let scriptContent: string = res.data + // thanks to https://github.com/joehecn/electron-baidu-tongji/blob/master/index.js + const source = '(h.c.b.su=h.c.b.u||document.location.href),h.c.b.u=f.protocol+"//"+document.location.host+' + if (scriptContent.includes(source)) { + const target = '(h.c.b.su=h.c.b.u||"https://"+c.dm[0]+a[1]),h.c.b.u="https://"+c.dm[0]+' + const target2 = '"https://"+c.dm[0]+window.location.pathname+window.location.hash' + scriptContent = scriptContent.replace(source, target).replace(/window.location.href/g, target2) + } + evt.sender.send(BAIDU_TONGJI_INIT_RES, scriptContent) + } + }) + }) }, dispose () {} } diff --git a/src/renderer/utils/analytics.ts b/src/renderer/utils/analytics.ts new file mode 100644 index 000000000..da8e32cec --- /dev/null +++ b/src/renderer/utils/analytics.ts @@ -0,0 +1,26 @@ +/* eslint-disable camelcase */ +import { ipcRenderer } from 'electron' +import { + BAIDU_TONGJI_INIT, + BAIDU_TONGJI_INIT_RES, + BAIDU_TONGJI_EVENT +} from '~/universal/events/constants' +import { handleBaiduTongJiEvent } from './common' + +ipcRenderer.on(BAIDU_TONGJI_INIT_RES, (_, scriptContent) => { + window._hmt = window._hmt || [] + const hm = document.createElement('script') + hm.text = scriptContent + const head = document.getElementsByTagName('head')[0] + head.appendChild(hm) +}) + +ipcRenderer.on(BAIDU_TONGJI_EVENT, (_, data: IBaiduTongJiOptions) => { + handleBaiduTongJiEvent(data) +}) + +export const initBaiduTongJi = () => { + setTimeout(() => { + ipcRenderer.send(BAIDU_TONGJI_INIT) + }, 0) +} diff --git a/src/renderer/utils/common.ts b/src/renderer/utils/common.ts new file mode 100644 index 000000000..19133e6b0 --- /dev/null +++ b/src/renderer/utils/common.ts @@ -0,0 +1,9 @@ +const isDevelopment = process.env.NODE_ENV !== 'production' +/* eslint-disable camelcase */ +export const handleBaiduTongJiEvent = (data: IBaiduTongJiOptions) => { + const { category, action, opt_label = '', opt_value = Date.now() } = data + window._hmt.push(['_trackEvent', category, action, opt_label, opt_value]) + if (isDevelopment) { + console.log('baidu tongji', data) + } +} diff --git a/src/universal/events/constants.ts b/src/universal/events/constants.ts index b1e44ff87..a1cba48f4 100644 --- a/src/universal/events/constants.ts +++ b/src/universal/events/constants.ts @@ -1,3 +1,7 @@ export const SHOW_INPUT_BOX = 'SHOW_INPUT_BOX' export const SHOW_INPUT_BOX_RESPONSE = 'SHOW_INPUT_BOX_RESPONSE' export const TOGGLE_SHORTKEY_MODIFIED_MODE = 'TOGGLE_SHORTKEY_MODIFIED_MODE' +export const BAIDU_TONGJI_INIT = 'BAIDU_TONDJI_INIT' +export const BAIDU_TONGJI_INIT_RES = 'BAIDU_TONDJI_INIT_RES' +export const BAIDU_TONGJI_CODE = '19a7ebdbb87f2403773c7ab0cae16d21' +export const BAIDU_TONGJI_EVENT = 'BAIDU_TONGJI_EVENT' diff --git a/src/universal/types/shims-tsx.d.ts b/src/universal/types/shims-tsx.d.ts index c656c68b8..cf749eb41 100644 --- a/src/universal/types/shims-tsx.d.ts +++ b/src/universal/types/shims-tsx.d.ts @@ -10,4 +10,8 @@ declare global { [elem: string]: any } } + + interface Window { + _hmt: any[] + } } diff --git a/src/universal/types/types.d.ts b/src/universal/types/types.d.ts index 1eec28af2..b04bdb2f2 100644 --- a/src/universal/types/types.d.ts +++ b/src/universal/types/types.d.ts @@ -295,3 +295,19 @@ interface IAppNotification { body: string icon?: string } + +interface IBaiduTongJiOptions { + category: string + action: string + // eslint-disable-next-line camelcase + opt_label?: string + // eslint-disable-next-line camelcase + opt_value?: number +} + +interface IAnalyticsData { + fromClipboard: boolean + type: string + count: number + duration?: number // 耗时 +}