From e43445ea0348eb3fd8b4d266900cb25e15f1844e Mon Sep 17 00:00:00 2001 From: Surmon Date: Tue, 8 Oct 2024 16:46:37 +0700 Subject: [PATCH] feat: v4.49.4 --- package.json | 11 ++--- pnpm-lock.yaml | 63 +++++++++++------------- src/components/widget/share.vue | 28 ++++++----- src/composables/head.ts | 2 +- src/pages/photography/index.vue | 14 ++---- src/server/getters/instagram/_profile.ts | 38 ++++++++++++++ src/server/getters/instagram/profile.ts | 47 ++++++------------ src/transforms/email.ts | 4 +- src/transforms/qs.ts | 24 +++++++++ 9 files changed, 137 insertions(+), 94 deletions(-) create mode 100644 src/server/getters/instagram/_profile.ts create mode 100644 src/transforms/qs.ts diff --git a/package.json b/package.json index ecf1bca7a..af7ebf64e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "surmon.me", - "version": "4.49.3", + "version": "4.49.4", "description": "Surmon.me blog", "author": "Surmon", "license": "MIT", @@ -45,14 +45,13 @@ "lodash-es": "^4.17.21", "lozad": "^1.16.x", "lru-cache": "^11.x", - "mapbox-gl": "^3.6.x", + "mapbox-gl": "^3.7.x", "marked": "^14.1.x", "marked-highlight": "^2.1.4", "marked-mangle": "^1.1.9", "marked-xhtml": "^1.0.11", - "pinia": "^2.2.2", + "pinia": "^2.2.x", "qrcode": "^1.5.x", - "qs": "^6.13.0", "redis": "^4.7.0", "rss": "^1.2.2", "serialize-javascript": "^6.0.2", @@ -87,11 +86,11 @@ "eslint-config-prettier": "^9.x", "eslint-plugin-prettier": "^5.x", "eslint-plugin-vue": "^9.x", - "globals": "^15.9.0", + "globals": "^15.10.x", "prettier": "^3.x", "sass": "^1.79.x", "tsx": "^4.19.x", - "typescript": "^5.5.x", + "typescript": "^5.6.x", "typescript-eslint": "^8.x", "vite": "^5.4.x" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 72ac459f5..659a9ca17 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,8 +89,8 @@ importers: specifier: ^11.x version: 11.0.1 mapbox-gl: - specifier: ^3.6.x - version: 3.6.0 + specifier: ^3.7.x + version: 3.7.0 marked: specifier: ^14.1.x version: 14.1.2 @@ -104,14 +104,11 @@ importers: specifier: ^1.0.11 version: 1.0.11(marked@14.1.2) pinia: - specifier: ^2.2.2 + specifier: ^2.2.x version: 2.2.2(typescript@5.6.2)(vue@3.5.9(typescript@5.6.2)) qrcode: specifier: ^1.5.x version: 1.5.4 - qs: - specifier: ^6.13.0 - version: 6.13.0 redis: specifier: ^4.7.0 version: 4.7.0 @@ -210,8 +207,8 @@ importers: specifier: ^9.x version: 9.28.0(eslint@9.11.1) globals: - specifier: ^15.9.0 - version: 15.9.0 + specifier: ^15.10.x + version: 15.10.0 prettier: specifier: ^3.x version: 3.3.3 @@ -222,7 +219,7 @@ importers: specifier: ^4.19.x version: 4.19.1 typescript: - specifier: ^5.5.x + specifier: ^5.6.x version: 5.6.2 typescript-eslint: specifier: ^8.x @@ -952,6 +949,9 @@ packages: '@types/fs-extra@11.0.4': resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + '@types/geojson-vt@3.2.5': + resolution: {integrity: sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g==} + '@types/geojson@7946.0.14': resolution: {integrity: sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==} @@ -1027,6 +1027,9 @@ packages: '@types/serve-static@1.15.7': resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + '@types/supercluster@7.1.3': + resolution: {integrity: sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==} + '@types/through2@2.0.41': resolution: {integrity: sha512-ryQ0tidWkb1O1JuYvWKyMLYEtOWDqF5mHerJzKz/gQpoAaJq2l/dsMPBF0B5BNVT34rbARYJ5/tsZwLfUi2kwQ==} @@ -1744,9 +1747,6 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - fflate@0.8.2: - resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} - file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -1914,8 +1914,8 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@15.9.0: - resolution: {integrity: sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==} + globals@15.10.0: + resolution: {integrity: sha512-tqFIbz83w4Y5TCbtgjZjApohbuh7K9BxGYFm7ifwDR240tvdb7P9x+/9VvUKlmkPoiknoJtanI8UOrqxS3a7lQ==} engines: {node: '>=18'} gopd@1.0.1: @@ -2265,8 +2265,8 @@ packages: resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} engines: {node: '>=8'} - mapbox-gl@3.6.0: - resolution: {integrity: sha512-xjYHHIJDh6haYcKY+/9jh1eywwYfIOWCgT5Fowj4JriZexx/oOtg2S7BQDMZtpFyg9IN4VLCysmUWxY0pFNRWA==} + mapbox-gl@3.7.0: + resolution: {integrity: sha512-dCbVyH1uGobwv6f4QKRv2Z2wuVT/RmspsudK3sTxGRFxZi6Pd2P9axdbVyZpmGddCAREy44pHhvzvO0qgpdKAg==} marked-highlight@2.1.4: resolution: {integrity: sha512-D1GOkcdzP+1dzjoColL7umojefFrASDuLeyaHS0Zr/Uo9jkr1V6vpLRCzfi1djmEaWyK0SYMFtHnpkZ+cwFT1w==} @@ -2805,9 +2805,6 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - rw@1.3.3: - resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} - safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -3044,9 +3041,6 @@ packages: engines: {node: '>=12'} hasBin: true - tweakpane@4.0.4: - resolution: {integrity: sha512-RkWD54zDlEbnN01wQPk0ANHGbdCvlJx/E8A1QxhTfCbX+ROWos1Ws2MnhOm39aUGMOh+36TjUwpDmLfmwTr1Fg==} - type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -3956,6 +3950,10 @@ snapshots: '@types/jsonfile': 6.1.4 '@types/node': 22.7.3 + '@types/geojson-vt@3.2.5': + dependencies: + '@types/geojson': 7946.0.14 + '@types/geojson@7946.0.14': {} '@types/http-errors@2.0.4': {} @@ -4029,6 +4027,10 @@ snapshots: '@types/node': 22.7.3 '@types/send': 0.17.4 + '@types/supercluster@7.1.3': + dependencies: + '@types/geojson': 7946.0.14 + '@types/through2@2.0.41': dependencies: '@types/node': 22.7.3 @@ -4902,8 +4904,6 @@ snapshots: dependencies: reusify: 1.0.4 - fflate@0.8.2: {} - file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -5108,7 +5108,7 @@ snapshots: globals@14.0.0: {} - globals@15.9.0: {} + globals@15.10.0: {} gopd@1.0.1: dependencies: @@ -5419,7 +5419,7 @@ snapshots: map-obj@4.3.0: {} - mapbox-gl@3.6.0: + mapbox-gl@3.7.0: dependencies: '@mapbox/jsonlint-lines-primitives': 2.0.2 '@mapbox/mapbox-gl-supported': 3.0.0 @@ -5429,11 +5429,14 @@ snapshots: '@mapbox/vector-tile': 1.3.1 '@mapbox/whoots-js': 3.1.0 '@types/geojson': 7946.0.14 + '@types/geojson-vt': 3.2.5 + '@types/mapbox__point-geometry': 0.1.4 '@types/mapbox__vector-tile': 1.3.4 + '@types/pbf': 3.0.5 + '@types/supercluster': 7.1.3 cheap-ruler: 4.0.0 csscolorparser: 1.0.3 earcut: 3.0.0 - fflate: 0.8.2 geojson-vt: 4.0.2 gl-matrix: 3.4.3 grid-index: 1.1.0 @@ -5442,11 +5445,9 @@ snapshots: pbf: 3.3.0 potpack: 2.0.0 quickselect: 3.0.0 - rw: 1.3.3 serialize-to-js: 3.1.2 supercluster: 8.0.1 tinyqueue: 3.0.0 - tweakpane: 4.0.4 vt-pbf: 3.1.3 marked-highlight@2.1.4(marked@14.1.2): @@ -5986,8 +5987,6 @@ snapshots: dependencies: queue-microtask: 1.2.3 - rw@1.3.3: {} - safe-buffer@5.1.2: {} safe-buffer@5.2.1: {} @@ -6242,8 +6241,6 @@ snapshots: - bluebird - supports-color - tweakpane@4.0.4: {} - type-check@0.4.0: dependencies: prelude-ls: 1.2.1 diff --git a/src/components/widget/share.vue b/src/components/widget/share.vue index ff9b39ff1..d5b465472 100755 --- a/src/components/widget/share.vue +++ b/src/components/widget/share.vue @@ -11,13 +11,14 @@ diff --git a/src/server/getters/instagram/_profile.ts b/src/server/getters/instagram/_profile.ts new file mode 100644 index 000000000..db1b93382 --- /dev/null +++ b/src/server/getters/instagram/_profile.ts @@ -0,0 +1,38 @@ +import axios, { isAxiosError } from '@/server/services/axios' +import { IDENTITIES } from '@/config/app.config' + +export interface InstagramProfile { + name: string + avatar: string + category: string + biography: string + mediaCount: number + followerCount: number + followingCount: number +} + +// Unstable access to Instagram API +// https://stackoverflow.com/a/73376216/6222535 +export const getInstagramProfile = async (): Promise => { + try { + const url = `https://i.instagram.com/api/v1/users/web_profile_info/?username=${IDENTITIES.INSTAGRAM_USERNAME}` + const agent = + 'Instagram 76.0.0.15.395 Android (24/7.0; 640dpi; 1440x2560; samsung; SM-G930F; herolte; samsungexynos8890; en_US; 138226743)' + const response = await axios.get(url, { timeout: 8000, headers: { 'User-Agent': agent } }) + if (response.data.status !== 'ok') { + return Promise.reject(response.data) + } else { + return { + name: response.data.data.user.full_name, + avatar: response.data.data.user.profile_pic_url_hd, + category: response.data.data.user.category_name, + biography: response.data.data.user.biography, + mediaCount: response.data.data.user.edge_owner_to_timeline_media.count, + followerCount: response.data.data.user.edge_followed_by.count, + followingCount: response.data.data.user.edge_follow.count + } + } + } catch (error) { + throw isAxiosError(error) ? error.toJSON() : error + } +} diff --git a/src/server/getters/instagram/profile.ts b/src/server/getters/instagram/profile.ts index db1b93382..dafd0a21d 100644 --- a/src/server/getters/instagram/profile.ts +++ b/src/server/getters/instagram/profile.ts @@ -1,38 +1,23 @@ import axios, { isAxiosError } from '@/server/services/axios' -import { IDENTITIES } from '@/config/app.config' +import { INSTAGRAM_TOKEN } from '@/config/bff.yargs' export interface InstagramProfile { - name: string - avatar: string - category: string - biography: string - mediaCount: number - followerCount: number - followingCount: number + id: string + username: string + account_type: 'BUSINESS' | 'MEDIA_CREATOR' | 'PERSONAL' + media_count: number } -// Unstable access to Instagram API -// https://stackoverflow.com/a/73376216/6222535 -export const getInstagramProfile = async (): Promise => { - try { - const url = `https://i.instagram.com/api/v1/users/web_profile_info/?username=${IDENTITIES.INSTAGRAM_USERNAME}` - const agent = - 'Instagram 76.0.0.15.395 Android (24/7.0; 640dpi; 1440x2560; samsung; SM-G930F; herolte; samsungexynos8890; en_US; 138226743)' - const response = await axios.get(url, { timeout: 8000, headers: { 'User-Agent': agent } }) - if (response.data.status !== 'ok') { - return Promise.reject(response.data) - } else { - return { - name: response.data.data.user.full_name, - avatar: response.data.data.user.profile_pic_url_hd, - category: response.data.data.user.category_name, - biography: response.data.data.user.biography, - mediaCount: response.data.data.user.edge_owner_to_timeline_media.count, - followerCount: response.data.data.user.edge_followed_by.count, - followingCount: response.data.data.user.edge_follow.count - } - } - } catch (error) { - throw isAxiosError(error) ? error.toJSON() : error +// https://developers.facebook.com/docs/instagram-basic-display-api/reference/user +export const getInstagramProfile = () => { + const params = { + access_token: INSTAGRAM_TOKEN, + fields: `id,username,account_type,media_count` } + return axios + .get(`https://graph.instagram.com/me`, { timeout: 8000, params }) + .then((response) => response.data) + .catch((error) => { + return Promise.reject(isAxiosError(error) ? (error.response?.data?.error ?? error.toJSON()) : error) + }) } diff --git a/src/transforms/email.ts b/src/transforms/email.ts index 987cec3d3..46a647944 100644 --- a/src/transforms/email.ts +++ b/src/transforms/email.ts @@ -4,7 +4,7 @@ * @author Surmon */ -import qs from 'qs' +import { stringify } from '/@/transforms/qs' export interface EmailLinkOptions { email: string @@ -17,5 +17,5 @@ export const emailLink = (email: string | EmailLinkOptions) => { } const { email: _email, ...content } = email - return `mailto:${_email}?` + qs.stringify(content) + return `mailto:${_email}?` + stringify(content) } diff --git a/src/transforms/qs.ts b/src/transforms/qs.ts new file mode 100644 index 000000000..5c5a4584f --- /dev/null +++ b/src/transforms/qs.ts @@ -0,0 +1,24 @@ +/** + * @file query string + * @module transforms.qs + * @author Surmon + */ + +export const stringify = (object: any, sep = '&', eq = '=') => { + let str = '' + for (let k in object) { + if (object.hasOwnProperty(k)) { + let value = object[k] + if (value === null || value === undefined) continue + let encodedKey = encodeURIComponent(k) + let encodedValue = encodeURIComponent(value) + str += encodedKey + eq + encodedValue + sep + } + } + + return str.slice(0, -1) +} + +export const parse = (string) => { + // TODO.. +}