Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2020-04-26] 用 js 写一个 alfred 有道翻译的工作流插件 #32

Open
coppyC opened this issue Apr 26, 2020 · 1 comment
Open

Comments

@coppyC
Copy link
Owner

coppyC commented Apr 26, 2020

最近的我的alfred 有道翻译插件失灵了,这就很尴尬。
image
更尴尬的是,想改一下代码,发现是 python 打包后的运行脚本,对 py 不是很熟,反正就是把不到源码,看来只好另起炉灶,自己写一个了。

有道云翻译抓包

原先的插件是用有道云词典的接口,我看了一下,有道云词典的网页是ssr的,解析起来比较麻烦,估计就是网页的结构变了,导致插件失效了。
所以我这次打算用有道云翻译的接口,这些接口一般不会变,比起ssr解析更稳定。而且,但重要的是,接口返回json处理起来比ssr返回的html更容易解析,反馈速度也更快。缺点就是,内容没有词典的详细。
(ps: 本来是要弄 google翻译的,抓了包发现,返回的json是各种数组嵌套,没有字段名,只能通过解构数组来获取对应值,全靠猜,考虑到稳定性,还是不要用了。而且google返回的东西也很多,论速度,就没有道翻译快了。)
好吧,在抓有道翻译的时候,发现不带 cookie 的话,就不给翻译,而且里面还有很多验证参数,坑爹,懒得研究了。结果我就找官方接口渠道,但是官方接口要收费,这不是坑人嘛,网页给游客随便用,不收费,申请接口用,就要收费了。结果又发现官网有接口体验服务,我就顺着网线,呸,顺着接口抓,这次居然抓到了更好的接口,重点是没有任何验证!而且参数极简,真是功夫不负不心人啊,白嫖党的胜利!

* POST https://aidemo.youdao.com/trans
* Content-Type: application/x-www-form-urlencoded; charset=UTF-8
* body: q=要翻译的文本&from=Auto&to=Auto

用 curl 命令试一下

curl -X POST -d 'q=hello&from=Auto&to=Auto' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' https://aidemo.youdao.com/trans

返回内容

{"tSpeakUrl":"http://openapi.youdao.com/ttsapi?q=%E4%BD%A0%E5%A5%BD&langType=zh-CHS&sign=26C32BC468CFD8A4587AA08F45F4A828&salt=1587889711726&voice=4&format=mp3&appKey=2423360539ba5632","returnPhrase":["hello"],"RequestId":"52c48f0a-bdbb-4ad4-91cf-50c6f43982e0","web":[{"value":["你好","您好","哈啰","喂"],"key":"Hello"},{"value":["凯蒂猫","昵称","吉蒂猫","匿称"],"key":"Hello Kitty"},{"value":["哈乐哈乐","乐扣乐扣"],"key":"Hello Bebe"}],"query":"hello","translation":["你好"],"errorCode":"0","dict":{"url":"yddict://m.youdao.com/dict?le=eng&q=hello"},"webdict":{"url":"http://m.youdao.com/dict?le=eng&q=hello"},"basic":{"exam_type":["初中"],"us-phonetic":"helˈō","phonetic":"həˈləʊ","uk-phonetic":"həˈləʊ","uk-speech":"http://openapi.youdao.com/ttsapi?q=hello&langType=en&sign=897E66F391880756DA0AEDA59D02C567&salt=1587889711725&voice=5&format=mp3&appKey=2423360539ba5632","explains":["int. 喂;哈罗,你好,您好","n. 表示问候, 惊奇或唤起注意时的用语","n. (Hello) 人名;(法)埃洛"],"us-speech":"http://openapi.youdao.com/ttsapi?q=hello&langType=en&sign=897E66F391880756DA0AEDA59D02C567&salt=1587889711725&voice=6&format=mp3&appKey=2423360539ba5632"},"l":"en2zh-CHS","speakUrl":"http://openapi.youdao.com/ttsapi?q=hello&langType=en&sign=2AEEF43C4AEFCA21F615A6A55DC8610E&salt=1587889711726&voice=4&format=mp3&appKey=2423360539ba5632"}

完美,连发音url都有,就是不知道接口稳不稳定,可能以后用着用着,就需要 appKey 才能用了。也可能有 ip 频率限制,不过个人使用频率也不会很高。

编写脚本

我这次用的是苹果的 oascript,支持 js。
不用 node 主要是写完的脚本可以分享给其他没有 node 环境的 alfred 用户

JXA 的学习资料
本文使用了 JXA 与命令行交互的能力。

由于JXA不能发网络请求,所以我用 curl 封装一个。

/**
 * curl 命令封装
 * @param {string} url
 * @param {object} config
 * @param {'GET'|'POST'|'PUT'|'DELETE'} config.method
 * @param {*} config.headers
 * @param {string} config.data
 */
function curl(url, config) {
  // 获取当前的app实例
  const app = Application.currentApplication()
  // 获得命令行交互等能力
  app.includeStandardAdditions = true
  const response = app.doShellScript([
    'curl',
    config.method && `-X '${config.method.toUpperCase()}'`,
    config.headers && Object.keys(config.headers)
      .map(key => `-H '${key}: ${config.headers[key]}'`)
      .join(' '),
    config.data && `-d '${config.data}'`,
    `'${url}'`,
  ].filter(x => x).join(' '))
  try {
    return JSON.parse(response)
  } catch {
    return response
  }
}

然后是翻译 api 的封装

/**
 * 有道翻译 api
 * @param {string} query
 * @returns {{
    "returnPhrase": string[],
    "RequestId": string,
    "web": {
      "value": string[],"key": string}[],
      "query": string,
      "translation": string[],
      "errorCode": string,
      "dict": {"url": string},
      "webdict": {"url": string},
      "basic": {
        "exam_type": string[],
        "us-phonetic": string,
        "phonetic": string,
        "uk-phonetic": string,
        "uk-speech": string,
        "explains": string[],
        "us-speech": string
      },
      "l": string,
      "speakUrl": string,
      "tSpeakUrl": string,
    }}
 */
function youDaoTranslate(query) {
  return curl('https://aidemo.youdao.com/trans', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
    },
    data: `q=${query}&from=Auto&to=Auto`
  })
}

最后是就是主函数运行,返回 JSON 数据给 alfred ,就大功告诉成了。

/**
 *
 * @param {string[]} argv
 */
function run(argv) {
  const result = youDaoTranslate(argv.join(' '))
  return JSON.stringify({
    items: result.translation.map(item => ({
      uid: item,
      title: item,
      arg: item,
      icon: {
        path: './icon.png'
      }
    }))
  })
}

将代码写入 index.js 文件 中,在命令行运行
osascript -l JavaScript ./index.js hello world 查看效果。

创建 alfred 工作流

脚本写好了,接着把脚本放入 alfred 就完事了。

打开 alfred workflow,新建个空白的 workflow,
image
在 workflow 的编辑界面,右键添加一个脚本过滤器
image

双击脚本过滤器,添加一些基本信息
然后把脚本语言改成 js后,将代码复制进去,保存
image
当然,你也可以用 bash 调用 刚才的脚本,这样下次修改代码就不用在 alfred 那个垃圾编辑器中改到头痛。

此时,wf 已经可以用了,试试看一下效果
image

回车复制与自动粘贴

此时工作流已经凑合能用了,但我们还可以做更好

右键 再加一个把转出复制到剪切板
image

然后双击编辑,钩上 Automatically paste to front most app,这样一回车,就会把翻译的内容自动粘贴,一气呵成。

当然,你也可以 钩上 Mark item as transient in clipboard,这样复制的内容不会出现在 alfred 的剪切板历史中,(毕竟我只是想自动粘贴翻译内容,不想你帮我记住我翻译过的东西啊喂)

对了,别忘了连上线。
image

完善

是的,还有很多东西没有完善,比如发音,词联想,在有道词典查看什么的。
还有我自己经常用的功能,把翻译后的英文,按shift+enter,进行驼峰拼接 也没有做。

@coppyC coppyC changed the title [2020-04-26] 用 js 写一个 alfred 工作流插件 [2020-04-26] 用 js 写一个 alfred 有道翻译的工作流插件 Apr 26, 2020
@coppyC
Copy link
Owner Author

coppyC commented Apr 26, 2020

经测试,该接口如果调用频率过高,ip会在一段时间内被限制访问。
毕竟是免费的接口,做下防抖处理就行了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant