diff --git a/extensions/dlmoji/README.md b/extensions/dlmoji/README.md index 694c5b509ac..e8d59e2f5f6 100644 --- a/extensions/dlmoji/README.md +++ b/extensions/dlmoji/README.md @@ -24,6 +24,8 @@ ![Config Panel](./assets/Config-Panel.png) +Some APIs might cause timeout errors and be unstable. To avoid these annoying alerts, you can uncheck the corresponding APIs in the following Configuration. + To enable `Emotion Analysis`, you need to deploy deepmoji as a web service on your server. Here we offer an off-the-shelf [deepmoji docker image](https://hub.docker.com/r/thandaanda/deepmoji). If you want to use another model service, remember to follow the response format: ```json diff --git a/extensions/dlmoji/assets/Config-Panel.png b/extensions/dlmoji/assets/Config-Panel.png index 63a2e65b812..e5f91982e59 100644 Binary files a/extensions/dlmoji/assets/Config-Panel.png and b/extensions/dlmoji/assets/Config-Panel.png differ diff --git a/extensions/dlmoji/package-lock.json b/extensions/dlmoji/package-lock.json index 5af14c2aee4..c4fc687bc2b 100644 --- a/extensions/dlmoji/package-lock.json +++ b/extensions/dlmoji/package-lock.json @@ -12,10 +12,12 @@ "cheerio": "^1.0.0-rc.12", "crypto-js": "^4.1.1", "form-data": "^4.0.0", + "lodash": "^4.17.21", "prettier": "^2.7.1" }, "devDependencies": { "@types/crypto-js": "^4.1.1", + "@types/lodash": "^4.14.182", "@types/node": "~16.10.0", "@types/react": "^17.0.28", "@typescript-eslint/eslint-plugin": "^5.0.0", @@ -289,6 +291,12 @@ "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==", + "dev": true + }, "node_modules/@types/node": { "version": "16.10.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.9.tgz", @@ -2406,10 +2414,8 @@ }, "node_modules/lodash": { "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, - "optional": true + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -4141,6 +4147,12 @@ "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, + "@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==", + "dev": true + }, "@types/node": { "version": "16.10.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.9.tgz", @@ -5768,10 +5780,8 @@ }, "lodash": { "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, - "optional": true + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash.merge": { "version": "4.6.2", diff --git a/extensions/dlmoji/package.json b/extensions/dlmoji/package.json index 258c5b9bbeb..76ec847c416 100644 --- a/extensions/dlmoji/package.json +++ b/extensions/dlmoji/package.json @@ -23,6 +23,14 @@ "preferences": [ { "title": "API Selection", + "name": "useEmojiTranslate", + "type": "checkbox", + "label": "Emoji Translate", + "required": false, + "default": true, + "description": "Translate human language to emoji" + }, + { "name": "useVerbatimTranslate", "type": "checkbox", "label": "18dao Verbatim Chinese Translate", @@ -78,10 +86,12 @@ "cheerio": "^1.0.0-rc.12", "crypto-js": "^4.1.1", "form-data": "^4.0.0", + "lodash": "^4.17.21", "prettier": "^2.7.1" }, "devDependencies": { "@types/crypto-js": "^4.1.1", + "@types/lodash": "^4.14.182", "@types/node": "~16.10.0", "@types/react": "^17.0.28", "@typescript-eslint/eslint-plugin": "^5.0.0", diff --git a/extensions/dlmoji/src/TranslateResult.tsx b/extensions/dlmoji/src/TranslateResult.tsx index cbdbf5f2299..c9bb87001ce 100644 --- a/extensions/dlmoji/src/TranslateResult.tsx +++ b/extensions/dlmoji/src/TranslateResult.tsx @@ -1,7 +1,17 @@ import { Component, Fragment } from "react" -import { SECTION_TYPE } from "./consts" -import { Action, ActionPanel, Clipboard, Color, Icon, List, getPreferenceValues } from "@raycast/api" -import { truncate } from "./utils" +import { COPY_SEPARATOR, SECTION_TYPE } from "./consts" +import { + Action, + ActionPanel, + Clipboard, + Color, + Icon, + List, + getPreferenceValues, + KeyEquivalent, + Keyboard, +} from "@raycast/api" +import { clamp, truncate } from "./utils" interface ITranslateResult { inputState?: string @@ -19,7 +29,7 @@ function reformatCopyTextArray(data: string[], limitResultAmount = 10): IReforma return finalData.map((text, idx) => { return { // title: finalData.length - 1 === idx && idx > 0 ? "All" : truncate(text), - title: idx === 0 ? "All" : truncate(text), + title: idx === dataLength ? "All" : truncate(text, 40), value: text, } }) @@ -32,9 +42,9 @@ function ActionCopyListSection(props: IActionCopyListSection) { return null } - const SEPARATOR = "; " - const copyTextArray = props.copyText.split(SEPARATOR) - copyTextArray.length > 1 && copyTextArray.unshift(props.copyText) + const copyTextArray = props.copyText.split(COPY_SEPARATOR) + const newCopyText = copyTextArray.join(" ") + copyTextArray.length > 1 && copyTextArray.push(newCopyText) const finalTextArray = reformatCopyTextArray(copyTextArray, 6) // const shortcutKeyEquivalent: Keyboard.KeyEquivalent[] = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] @@ -67,10 +77,11 @@ function ActionCopyListSection(props: IActionCopyListSection) { {finalTextArray.map((textItem, key) => { const title = textItem.title const value = textItem.value + const shortcutKey = clamp(key + 1).toString() as Keyboard.KeyEquivalent return ( preferences.isAutomaticPaste && Clipboard.paste(textItem.value)} - // shortcut={{ modifiers: ["cmd"], key: [key] }} + shortcut={{ modifiers: ["cmd"], key: shortcutKey }} title={`Copy ${title}`} content={value} key={key} @@ -125,12 +136,11 @@ export default function TranslateResult(props: ITranslateResult) { icon={iconMaps[result.type!]} title={item.title} subtitle={item?.subtitle} - accessoryTitle={item.phonetic} detail={} actions={ } /> diff --git a/extensions/dlmoji/src/api.tsx b/extensions/dlmoji/src/api.tsx index f25e33c6dbb..77d8e48921a 100644 --- a/extensions/dlmoji/src/api.tsx +++ b/extensions/dlmoji/src/api.tsx @@ -3,6 +3,7 @@ import axios from "axios" import querystring from "node:querystring" import CryptoJS from "crypto-js" import { checkURL, defaultBaiduAppId, defaultBaiduAppSecret, preferences, showErrorToast } from "./utils" +import { getEmojiTransKey } from "./storage" // baidu app id and secret const baiduAppId = preferences.baiduAppId.trim().length > 0 ? preferences.baiduAppId.trim() : defaultBaiduAppId @@ -15,6 +16,31 @@ if (deepmojiURL.length > 0 && !checkURL(deepmojiURL)) { showErrorToast("deepmoji", "invalid URL address") } +export async function preConnect() { + const connects = [] + if (preferences.useEmojiTranslate) { + connects.push( + getEmojiTransKey(false).then((key) => { + fetchEmojiTrans("", "en", key) + }) + ) + } + if (preferences.useVerbatimTranslate) { + connects.push(fetchChineseEmojiTrans("")) + } + if (preferences.useEmojiAll) { + connects.push(fetchEmojiAll("", "en")) + } + return axios.all(connects) +} + +export function setAxiosTimeout(seconds = 6) { + axios.interceptors.request.use((config) => { + config.timeout = seconds * 1000 + return config + }) +} + /** * 百度翻译API * Docs: https://fanyi-api.baidu.com/doc/21 @@ -35,7 +61,10 @@ export async function fetchBaiduTrans(queryText: string): Promise { salt: salt, sign: sign, } - return axios.get(url, { params }) + return axios.get(url, { params }).catch((err) => { + showErrorToast("Baidu Translate", err.message) + return + }) } export async function fetchDeepl(queryText: string): Promise { @@ -98,12 +127,8 @@ export async function fetchEmojiAll(queryText: string, fromLanguage: string): Pr lang: lang, }), { - timeout: 6 * 1000, headers: { - // 'User-Agent': 'apifox/1.0.0 (https://www.apifox.cn)', - // 'Accept': '*/*', // 'Content-Type': 'multipart/form-data', - // 'Connection': 'keep-alive', referer: "https://www.emojiall.com/", }, } diff --git a/extensions/dlmoji/src/consts.tsx b/extensions/dlmoji/src/consts.tsx index ddaf951ecdd..53b696df8e3 100644 --- a/extensions/dlmoji/src/consts.tsx +++ b/extensions/dlmoji/src/consts.tsx @@ -3,3 +3,5 @@ export enum SECTION_TYPE { Emoji = "Related Emojis", Phrase = "Phrases", } + +export const COPY_SEPARATOR = "; " diff --git a/extensions/dlmoji/src/dlmoji.tsx b/extensions/dlmoji/src/dlmoji.tsx index 5f540dca60a..7187636aea1 100644 --- a/extensions/dlmoji/src/dlmoji.tsx +++ b/extensions/dlmoji/src/dlmoji.tsx @@ -3,7 +3,16 @@ import { useEffect, useState } from "react" import TranslateResult from "./TranslateResult" import { Icon, List } from "@raycast/api" import axios from "axios" -import { fetchBaiduTrans, fetchChineseEmojiTrans, fetchDeepmoji, fetchEmojiAll, fetchEmojiTrans } from "./api" +import { cloneDeep } from "lodash" +import { + fetchBaiduTrans, + fetchChineseEmojiTrans, + fetchDeepmoji, + fetchEmojiAll, + fetchEmojiTrans, + preConnect, + setAxiosTimeout, +} from "./api" import { formatBaiduTrans, formatChineseEmojiTrans, @@ -14,9 +23,14 @@ import { import { getEmojiTransKey } from "./storage" import { SECTION_TYPE } from "./consts" +// use preConnect to reduce API response time +preConnect() +setTimeout(() => { + setAxiosTimeout(6) +}, 8000) + let delayFetchTranslateAPITimer: NodeJS.Timeout let delayUpdateTargetLanguageTimer: NodeJS.Timeout -// let othersLoaded = false export default function () { const [inputState, updateInputState] = useState() @@ -28,8 +42,8 @@ export default function () { // String Filter const queryGlobal: string = inputState - const queryText: string = queryGlobal.replace(/伶仔|伶伶/g, "公主").replace(/邓港大/g, "猪") - const queryEmoji: string = queryGlobal.replace(/伶仔|伶伶/g, "🐰").replace(/邓港大/g, "🦊") + const queryText: string = queryGlobal.replace(/陈炤伶|伶仔|伶伶/g, "公主").replace(/邓港大/g, "猪") + const queryEmoji: string = queryGlobal.replace(/陈炤伶|伶仔|伶伶/g, "🐰").replace(/邓港大/g, "🦊") const hasChinese = /[\u4E00-\u9FA5]+/g.test(queryText) const lang = hasChinese ? "zh" : "en" @@ -49,46 +63,69 @@ export default function () { } const res = await fetchDeepmoji(enText) if (!res?.data) return + console.log("Deepmoji Data Received") return formatDeepmoji(res.data.emoji[0]) } async function getEmojiTrans(updateKey = false): Promise { + if (!preferences.useEmojiTranslate) return const key = await getEmojiTransKey(updateKey) const res = await fetchEmojiTrans(queryEmoji, lang, key) - if (!res?.data) { + if (!res) return + if (!res.data) { + console.log("Emoji Translation Key Update") return getEmojiTrans(true) } + console.log("EmojiTrans Data Received") return formatEmojiTrans(res.data) } async function getChineseEmojiTrans(): Promise { if (!preferences.useVerbatimTranslate || !hasChinese) return const res = await fetchChineseEmojiTrans(queryEmoji) if (!res?.data) return + console.log("ChineseEmojiTrans Data Received") return formatChineseEmojiTrans(res.data) } async function getEmojiAll(): Promise { if (!preferences.useEmojiAll) return const res = await fetchEmojiAll(queryText, lang) if (!res?.data) return + console.log("EmojiAll Data Received") return formatEmojiAll(res.data) } - axios.all([getDeepmoji(), getEmojiTrans(), getChineseEmojiTrans(), getEmojiAll()]).then( - axios.spread((deepmoji, emojiTrans, verbatimTrans, emojiAll) => { - const result: ITranslateReformatResult = { + getEmojiTrans().then((emojiTrans) => { + if (!emojiTrans) return + if (dataList[0]?.type === SECTION_TYPE.Translate) { + dataList[0].children.unshift(emojiTrans) + } else { + dataList.unshift({ type: SECTION_TYPE.Translate, title: SECTION_TYPE.Translate, - children: [], - } - if (emojiTrans) { - result.children.push(emojiTrans) - } + children: [emojiTrans], + }) + } + updateTranslateResultState(cloneDeep(dataList)) + }) + + axios.all([getDeepmoji(), getChineseEmojiTrans(), getEmojiAll()]).then( + axios.spread((deepmoji, verbatimTrans, emojiAll) => { + const transArray: ITranslateReformatResultItem[] = [] if (deepmoji) { - result.children.push(deepmoji) + transArray.push(deepmoji) } if (verbatimTrans) { - result.children.push(verbatimTrans) + transArray.push(verbatimTrans) + } + + if (dataList[0]?.type === SECTION_TYPE.Translate) { + dataList[0].children.push(...transArray) + } else { + dataList.unshift({ + type: SECTION_TYPE.Translate, + title: SECTION_TYPE.Translate, + children: transArray, + }) } - dataList.unshift(result) if (emojiAll?.length > 0) { dataList.push(...emojiAll) diff --git a/extensions/dlmoji/src/formatter.tsx b/extensions/dlmoji/src/formatter.tsx index 4e8be927830..e03ac4a474f 100644 --- a/extensions/dlmoji/src/formatter.tsx +++ b/extensions/dlmoji/src/formatter.tsx @@ -1,11 +1,15 @@ -import { SECTION_TYPE } from "./consts" +import { COPY_SEPARATOR, SECTION_TYPE } from "./consts" import { load } from "cheerio" import { truncate } from "./utils" const MAX_LENGTH = 5 +export function formatEmojiTrans(emojis: string): ITranslateReformatResultItem { + return constructResultItem("Emoji Translate", emojis) +} + export function formatBaiduTrans(data: BaiduTranslateResult) { - if (data.trans_result) { + if (data?.trans_result) { return data.trans_result[0].dst } return "" @@ -17,25 +21,17 @@ export function formatDeepmoji(preds: EmojiScore[]): ITranslateReformatResultIte return a.prob - b.prob }) .reverse() - const emojis = preds - .slice(0, 5) - .map((value, idx) => { - return value.emoji - }) - .join("; ") + const emojiArray = preds.slice(0, 5).map((value) => { + return value.emoji + }) + const emojiText = emojiArray.join(" ") + const copyText = emojiArray.join(COPY_SEPARATOR) return { title: "Emotion Analysis", - subtitle: emojis, - key: emojis, - } -} - -export function formatEmojiTrans(emojis: string): ITranslateReformatResultItem { - return { - title: "Emoji Translate", - subtitle: emojis, - key: emojis, + subtitle: emojiText, + key: emojiText, + copyText: copyText, } } @@ -43,16 +39,20 @@ export function formatEmojiAll(data: EmojiDataItem[]): ITranslateReformatResult[ if (!data) return function extract(item: EmojiDataItem) { + const emoji = item.emoji_symbol + const description = item.description.replace(/<[^>]+>|\r|\n|\\s/gi, "") // 去掉换行,空格,html标签 + const copyText = description ? emoji + COPY_SEPARATOR + description : emoji return { - title: truncate(item.value, 32) + " " + item.emoji_symbol, - subtitle: item.description.replace(/<[^>]+>|\r|\n|\\s/gi, ""), // 去掉换行,空格,html标签 - key: item.emoji_symbol, + title: truncate(item.value, 26) + " " + item.emoji_symbol, + subtitle: description, + key: emoji, + copyText: copyText, } } const emojiList: ITranslateReformatResultItem[] = [] const combineList: ITranslateReformatResultItem[] = [] - data.forEach((item, idx) => { + data.forEach((item) => { if (item.type === "emoji") { emojiList.push(extract(item)) } else if (item.type === "combine") { @@ -85,10 +85,14 @@ export function formatChineseEmojiTrans(doc: string): ITranslateReformatResultIt const $ = load(doc) const text: string = $("meta[name=keywords]").attr("content")! const emojis: string = text.split(", ").slice(1).join(" ") + return constructResultItem("Verbatim Translate", emojis) +} +function constructResultItem(title: string, emojiText: string) { return { - title: "Verbatim Translate", - subtitle: emojis, - key: emojis, + title: title, + subtitle: emojiText, + key: emojiText, + copyText: emojiText, } } diff --git a/extensions/dlmoji/src/types.d.ts b/extensions/dlmoji/src/types.d.ts index 35ed27e0cf9..670cb9fe42c 100644 --- a/extensions/dlmoji/src/types.d.ts +++ b/extensions/dlmoji/src/types.d.ts @@ -18,9 +18,9 @@ interface ITranslateReformatResult { interface ITranslateReformatResultItem { key: string - phonetic?: string title: string subtitle?: string + copyText: string } interface ITranslateResultWebItem { @@ -37,6 +37,7 @@ interface ITranslateResultBasicItem { interface IPreferences { useVerbatimTranslate: boolean + useEmojiTranslate: boolean useEmojiAll: boolean isAutomaticPaste: boolean deepmojiURL: string diff --git a/extensions/dlmoji/src/utils.ts b/extensions/dlmoji/src/utils.ts index fbcf7dbbbfd..c4334f75509 100644 --- a/extensions/dlmoji/src/utils.ts +++ b/extensions/dlmoji/src/utils.ts @@ -38,3 +38,7 @@ export function truncate(string: string, length = 16, separator = "..") { return string.substring(0, length) + separator } + +export function clamp(num: number, min = 0, max = 9) { + return Math.min(Math.max(num, min), max) +}