├── src ├── icon.png ├── utils.js ├── info.json ├── config.js ├── main.js ├── d.js └── b.js ├── scripts └── update_appcast.py ├── .github └── workflows │ └── release.yml ├── appcast.json ├── README.md ├── node_js └── bd.js └── LICENSE /src/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akl7777777/bob-plugin-akl-baidu-free-translate/HEAD/src/icon.png -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | var config = require('./config.js'); 2 | 3 | const langMap = new Map(config.supportedLanguages); 4 | const langMapReverse = new Map(config.supportedLanguages.map(([standardLang, lang]) => [lang, standardLang])); 5 | 6 | exports.langMap = langMap; 7 | exports.langMapReverse = langMapReverse; 8 | -------------------------------------------------------------------------------- /scripts/update_appcast.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | import json 3 | import sys 4 | from pathlib import Path 5 | 6 | 7 | def update_appcast(message): 8 | with open ("src/info.json", "r") as f: 9 | info = json.load(f) 10 | version = info["version"] 11 | release_file = Path(f"release/bob-plugin-akl-baidu-free-translate.bobplugin") 12 | assert release_file.is_file(), "Release file not exist" 13 | with open(release_file, "rb") as f: 14 | c = f.read() 15 | file_hash = hashlib.sha256(c).hexdigest() 16 | version_info = { 17 | "version": version, 18 | "desc": message, 19 | "sha256": file_hash, 20 | "url": f"https://github.com/akl7777777/bob-plugin-akl-baidu-free-translate/releases/download/v{version}/bob-plugin-akl-baidu-free-translate_v{version}.bobplugin", 21 | "minBobVersion": "0.5.0" 22 | } 23 | appcast_file = Path("appcast.json") 24 | if appcast_file.is_file(): 25 | with open(appcast_file, "r") as f: 26 | appcast = json.load(f) 27 | else: 28 | appcast = dict(identifier="com.akl.bob-plugin-akl-baidu-free-translate", versions=[]) 29 | appcast["versions"].insert(0, version_info) 30 | with open(appcast_file, "w") as f: 31 | json.dump(appcast, f, ensure_ascii=False, indent=2) 32 | print(f"v{version}") 33 | 34 | 35 | if __name__ == "__main__": 36 | message = sys.argv[1] 37 | update_appcast(message) 38 | -------------------------------------------------------------------------------- /src/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "identifier": "com.akl.bob-plugin-akl-baidu-free-translate", 3 | "version": "0.1.0", 4 | "category": "translate", 5 | "name": "Free 百度翻译", 6 | "summary": "免token调用百度翻译", 7 | "icon": "103", 8 | "author": "akl7777777 ", 9 | "homepage": "https://github.com/akl7777777/bob-plugin-akl-baidu-free-translate", 10 | "appcast": "https://raw.githubusercontent.com/akl7777777/bob-plugin-akl-baidu-free-translate/main/appcast.json", 11 | "minBobVersion": "0.5.0", 12 | "options": [ 13 | { 14 | "identifier": "desc", 15 | "type": "menu", 16 | "title": "描述", 17 | "defaultValue": "akl7777777", 18 | "menuValues": [ 19 | { 20 | "title": "免费调用百度翻译;无需token;无需key;", 21 | "value": "akl7777777" 22 | } 23 | ], 24 | "desc":"小芍同学免费调用百度翻译;无需token;无需key;" 25 | }, 26 | { 27 | "identifier": "service", 28 | "type": "menu", 29 | "title": "服务商", 30 | "defaultValue": "d", 31 | "menuValues": [ 32 | { 33 | "title": "默认服务商", 34 | "value": "d" 35 | },{ 36 | "title": "Alpha服务商", 37 | "value": "b" 38 | } 39 | ], 40 | "desc":"默认服务商(建议使用默认服务商)" 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | const supportedLanguages2 = [ 2 | ["auto", "auto"], 3 | ["de", "de"], 4 | ["en", "en"], 5 | ["es", "es"], 6 | ["fr", "fr"], 7 | ["it", "it"], 8 | ["ja", "ja"], 9 | ["ko", "ko"], 10 | ["nl", "nl"], 11 | ["pl", "pl"], 12 | ["pt", "pt"], 13 | ["ru", "ru"], 14 | ["zh-Hans", "cn"], 15 | ["zh-Hant", "cn"], 16 | ["bg", "bg"], 17 | ["cs", "cs"], 18 | ["da", "da"], 19 | ["el", "el"], 20 | ["et", "et"], 21 | ["fi", "fi"], 22 | ["hu", "hu"], 23 | ["lt", "lt"], 24 | ["lv", "lv"], 25 | ["ro", "ro"], 26 | ["sk", "sk"], 27 | ["sl", "sl"], 28 | ["sv", "sv"] 29 | ]; 30 | 31 | const supportedLanguages = [["auto","auto"],["zh-Hans","zh"],["zh-Hant","cht"],["yue","yue"],["wyw","wyw"],["en","en"],["ja","jp"],["th","th"],["fr","fra"],["es","spa"],["ko","kor"],["tr","tr"],["vi","vie"],["ms","ms"],["de","de"],["ru","ru"],["ir","ir"],["ar","ara"],["et","est"],["be","be"],["bg","bul"],["hi","hi"],["is","is"],["pl","pl"],["fa","fa"],["da","dan"],["tl","tl"],["fi","fin"],["nl","nl"],["ca","ca"],["cs","cs"],["hr","hr"],["lv","lv"],["lt","lt"],["ro","rom"],["af","af"],["no","no"],["pt","pt"],["sv","swe"],["sr","sr"],["eo","eo"],["sk","sk"],["sl","slo"],["sw","sw"],["uk","uk"],["he","iw"],["el","el"],["hu","hu"],["hy","hy"],["it","it"],["id","id"],["sq","sq"],["am","am"],["as","as"],["az","az"],["eu","eu"],["bn","bn"],["bs","bs"],["gl","gl"],["ka","ka"],["gu","gu"],["ha","ha"],["ig","ig"],["iu","iu"],["ga","ga"],["zu","zu"],["kn","kn"],["kk","kk"],["ky","ky"],["lb","lb"],["mk","mk"],["mt","mt"],["mi","mi"],["mr","mr"],["ne","ne"],["or","or"],["pa","pa"],["qu","qu"],["tn","tn"],["si","si"],["ta","ta"],["tt","tt"],["te","te"],["ur","ur"],["uz","uz"],["cy","cy"],["yo","yo"]] 32 | 33 | exports.supportedLanguages = supportedLanguages; 34 | exports.supportedLanguages2 = supportedLanguages2; 35 | 36 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | var config = require('./config.js'); 2 | var utils = require('./utils.js'); 3 | var bb = require('./b') 4 | var dd = require('./d') 5 | 6 | 7 | function supportLanguages() { 8 | const serv = $option.service; 9 | if (serv === 'd') { 10 | return config.supportedLanguages2.map(([standardLang]) => standardLang); 11 | } else { 12 | return config.supportedLanguages.map(([standardLang]) => standardLang); 13 | } 14 | } 15 | 16 | function translate(query, completion) { 17 | (async () => { 18 | const serv = $option.service; 19 | const targetLanguage = utils.langMap.get(query.detectTo); 20 | const sourceLanguage = utils.langMap.get(query.detectFrom); 21 | if (!targetLanguage) { 22 | const err = new Error(); 23 | Object.assign(err, { 24 | _type: 'unsupportLanguage', 25 | _message: '不支持该语种', 26 | }); 27 | throw err; 28 | } 29 | const source_lang = sourceLanguage || 'cn'; 30 | const target_lang = targetLanguage || 'en'; 31 | const translate_text = query.text || ''; 32 | if (translate_text !== '') { 33 | 34 | if (serv === 'b') { 35 | await bb.translate(query, source_lang, target_lang, translate_text, completion) 36 | } else { 37 | await dd.translate(query, source_lang, target_lang, translate_text, completion) 38 | } 39 | } 40 | })().catch((err) => { 41 | $log.error('***********解析返回值异常==>' + JSON.stringify(err)) 42 | completion({ 43 | error: { 44 | type: err._type || 'unknown', 45 | message: err._message || '未知错误', 46 | addtion: err._addtion, 47 | }, 48 | }); 49 | }); 50 | } 51 | 52 | exports.supportLanguages = supportLanguages; 53 | exports.translate = translate; 54 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Plugin 2 | on: 3 | push: 4 | paths: 5 | - "src/info.json" 6 | jobs: 7 | release: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | with: 12 | fetch-depth: 0 13 | 14 | - name: Get version 15 | id: get_version 16 | uses: battila7/get-version-action@v2 17 | 18 | - name: Package plugin 19 | run: mkdir release && zip -j -r release/bob-plugin-akl-baidu-free-translate.bobplugin ./src/* 20 | 21 | - name: Get last commit title 22 | id: last-commit 23 | run: echo "::set-output name=last_commit_title::$(git log -1 --pretty=format:%s)" 24 | 25 | - run: git checkout -- src/ 26 | 27 | - name: Update appcast.json 28 | id: run_script 29 | run: | 30 | output=$(python3 scripts/update_appcast.py "${{ steps.last-commit.outputs.last_commit_title }}") 31 | echo "version=$output" >> $GITHUB_OUTPUT 32 | 33 | - name: Package plugin final 34 | run: mv release/bob-plugin-akl-baidu-free-translate.bobplugin release/bob-plugin-akl-baidu-free-translate_${{ steps.run_script.outputs.version }}.bobplugin 35 | 36 | - name: Commit files 37 | run: | 38 | git config --global user.name 'akl7777777' 39 | git config --global user.email 'akl7777777@163.com' 40 | git add appcast.json 41 | git commit -am 'update appcast.json' 42 | 43 | - name: Push changes 44 | uses: ad-m/github-push-action@master 45 | with: 46 | github_token: ${{ secrets.GITHUB_TOKEN }} 47 | 48 | - name: Upload binaries to release 49 | uses: svenstaro/upload-release-action@v2 50 | with: 51 | repo_token: ${{ secrets.GITHUB_TOKEN }} 52 | file: release/bob-plugin-akl-baidu-free-translate_${{ steps.run_script.outputs.version }}.bobplugin 53 | asset_name: bob-plugin-akl-baidu-free-translate_${{ steps.run_script.outputs.version }}.bobplugin 54 | tag: ${{ steps.run_script.outputs.version }} 55 | overwrite: true 56 | body: "${{ steps.last-commit.outputs.last_commit_title }}" 57 | -------------------------------------------------------------------------------- /appcast.json: -------------------------------------------------------------------------------- 1 | { 2 | "identifier": "com.akl.bob-plugin-akl-baidu-free-translate", 3 | "versions": [ 4 | { 5 | "version": "0.1.0", 6 | "desc": "优化插件性能", 7 | "sha256": "996955cc96423f0b9c58f60e164364d9a9da0d0849fa69a0681320edd753ab1b", 8 | "url": "https://github.com/akl7777777/bob-plugin-akl-baidu-free-translate/releases/download/v0.1.0/bob-plugin-akl-baidu-free-translate_v0.1.0.bobplugin", 9 | "minBobVersion": "0.5.0" 10 | }, 11 | { 12 | "version": "0.0.7", 13 | "desc": "替换bob官方提供的图标", 14 | "sha256": "f98b33d03af834a79b20ee9baab1a1a5dcba63274a6e4777750a78179f1d900c", 15 | "url": "https://github.com/akl7777777/bob-plugin-akl-baidu-free-translate/releases/download/v0.0.7/bob-plugin-akl-baidu-free-translate_v0.0.7.bobplugin", 16 | "minBobVersion": "0.5.0" 17 | }, 18 | { 19 | "version": "0.0.6", 20 | "desc": "修复日语翻译问题,扩展多语种的支持列表", 21 | "sha256": "9c0d6a4b566af7ad191dff64a65233b048d933b938283d47ec622b902b6fa8f9", 22 | "url": "https://github.com/akl7777777/bob-plugin-akl-baidu-free-translate/releases/download/v0.0.6/bob-plugin-akl-baidu-free-translate_v0.0.6.bobplugin", 23 | "minBobVersion": "0.5.0" 24 | }, 25 | { 26 | "version": "0.0.5", 27 | "desc": "整体重构,突破200上限,支持多家服务商切换,翻译更流畅,不报错", 28 | "sha256": "405f43456cf32716a72cac60f97d65c3c643a8c2e68876c92ad1c5c7aa55e37e", 29 | "url": "https://github.com/akl7777777/bob-plugin-akl-baidu-free-translate/releases/download/v0.0.5/bob-plugin-akl-baidu-free-translate_v0.0.5.bobplugin", 30 | "minBobVersion": "0.5.0" 31 | }, 32 | { 33 | "version": "0.0.3", 34 | "desc": "修改请求方式,修复部分用户无法访问的bug", 35 | "sha256": "b8812bda0cbe941b32e1435f88fcb4208e673606ea02a059030b24e04641b2db", 36 | "url": "https://github.com/akl7777777/bob-plugin-akl-baidu-free-translate/releases/download/v0.0.3/bob-plugin-akl-baidu-free-translate_v0.0.3.bobplugin", 37 | "minBobVersion": "0.5.0" 38 | }, 39 | { 40 | "version": "0.0.2", 41 | "desc": "修改请求方式,增加详细日志", 42 | "sha256": "6f485babe0b42b66a6ab8cc85aec8e0df383b4f1db4badfd6d65ecddd8312f76", 43 | "url": "https://github.com/akl7777777/bob-plugin-akl-baidu-free-translate/releases/download/v0.0.2/bob-plugin-akl-baidu-free-translate_v0.0.2.bobplugin", 44 | "minBobVersion": "0.5.0" 45 | }, 46 | { 47 | "version": "0.0.1", 48 | "desc": "初始版本", 49 | "sha256": "1fee5494fd88f6d0e02d15f7d063f75c08d735f1d997942a158a8d60c7414494", 50 | "url": "https://github.com/akl7777777/bob-plugin-akl-baidu-free-translate/releases/download/v_0.0.1/bob-plugin-akl-baidu-translate_v0.0.1.bobplugin", 51 | "minBobVersion": "0.5.0" 52 | } 53 | ] 54 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bob-plugin-akl-baidu-free-translate 2 | 免费无限次使用百度翻译,根据网页版JavaScript加密算法开发的bobplugin;所以只要官网的算法不改,理论上就可以无限使用 3 | 4 | bob插件主要为bob用户开发,bob是一款macOS上的翻译软件,bob官网地址:https://bobtranslate.com/ 5 | 6 | **下载地址:[百度翻译Bob插件(免秘钥)](https://github.com/akl7777777/bob-plugin-akl-baidu-free-translate/releases/download/v0.0.6/bob-plugin-akl-baidu-free-translate_v0.0.6.bobplugin)** 7 | 8 | 9 | ~~(发现一个问题,由于我调用的是沪江的服务,沪江在接口返回后如果超过200字符会自动阶段,导致译文不全,要寻找替代方案;如果不长的内容可以用,太长会被截断)~~ 10 | 11 | **200字截断的问题已解决,蒸鹅心啊...** 12 | 13 | **应大家要求,写了一版不依赖Bob内置环境,基于nodejs环境的代码,可以直接终端输入node bd.js调用,需要的自行取用[bd.js](https://github.com/akl7777777/bob-plugin-akl-baidu-free-translate/blob/main/node_js/bd.js)** 14 | 15 | 简单描述一下代码逻辑(免得自己以后忘了): 16 | 第一次登录,获取cookie,然后马上刷页面,根据带上这个cookie重复请求上一个地址,然后会给你一个token还有一个gtk,最后你通过这个gtk和你要翻译的内容进行一系列复杂的加密算法,得到一个sign,然后把token,sign,cookie还有翻译内容都发给翻译服务,后台会校验你请求是否篡改 17 | 18 | ### 友情链接==>ChatGPT免费桌面版客户端(支持Windows,macOS,Android) 19 | 桌面版ChatGPT下载地址:[OpenAI-ChatGPT免费桌面版客户端](https://github.com/akl7777777/free-chatgpt-client-pub) 20 | 21 | 手机版ChatGPT下载地址:[OpenAI-ChatGPT免费手机版客户端](https://github.com/akl7777777/free-chatgpt-client-mobile-pub) 22 | 23 | ### bob翻译插件大合集: 24 | 25 | >[OpenAI ChatGPT(免秘钥)插件](https://github.com/akl7777777/bob-plugin-akl-chatgpt-free-translate) 26 | 27 | >[DeepL翻译插件(免秘钥)](https://github.com/akl7777777/bob-plugin-akl-deepl-free-translate) 28 | 29 | >[有道翻译插件(免秘钥)](https://github.com/akl7777777/bob-plugin-akl-youdao-free-translate) 30 | 31 | >[CNKI学术翻译插件(免秘钥)](https://github.com/akl7777777/bob-plugin-akl-cnki-free-translate) 32 | 33 | >[火山翻译插件(免秘钥)](https://github.com/akl7777777/bob-plugin-akl-volcengine-free-translate) 34 | 35 | >[百度翻译插件(免秘钥)](https://github.com/akl7777777/bob-plugin-akl-baidu-free-translate) 36 | 37 | >[腾讯翻译君插件(免秘钥)](https://github.com/akl7777777/bob-plugin-akl-tencent-free-translate) 38 | 39 | >[腾讯交互翻译插件(免秘钥)](https://github.com/akl7777777/bob-plugin-akl-transmart-free-translate) 40 | 41 | >[彩云小译插件(免秘钥)](https://github.com/akl7777777/bob-plugin-akl-caiyunxiaoyi-free-translate) 42 | 43 | >[只为日语 - MOJi辞書(じしょ)](https://github.com/akl7777777/bob-plugin-akl-mojidict-translate) 44 | 45 | >[Papago Naver 韩语翻译(免秘钥)](https://github.com/akl7777777/bob-plugin-akl-papago-free-translate) 46 | 47 | >[Bob翻译剪切板图片的AlfredWorkflow](https://github.com/akl7777777/BobTranslateClipboard) 48 | 49 | >[Bob的Postman接口调试插件](https://github.com/akl7777777/bob-plugin-akl-postman) 50 | 51 | 52 | 53 | 使用截图如下 54 | 55 | image 56 | 57 | 58 | ### 开发不易,如果喜欢可以请作者喝一杯可乐,谢谢! 59 | 60 | 61 | ![image](https://user-images.githubusercontent.com/84266551/219829283-3ed1798e-aeed-4174-bbcb-f93bf3008817.png) 62 | -------------------------------------------------------------------------------- /src/d.js: -------------------------------------------------------------------------------- 1 | var CryptoJS = require("crypto-js"); 2 | 3 | // 加密 4 | function btoa(str) { 5 | return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(str)); 6 | } 7 | 8 | // 解密 9 | function atob(str) { 10 | return CryptoJS.enc.Base64.parse(str).toString(CryptoJS.enc.Utf8); 11 | } 12 | 13 | 14 | async function translate(query, source_lang, target_lang, translate_text, completion) { 15 | // 获取登录令牌 16 | const loginUrl = 'http://track.hujiang.com/v4/track' 17 | // const url = 'http://res.d.hjfile.cn/v10/dict/translation/cn/en?content=hi'; 18 | const url = 'http://res.d.hjfile.cn/v10/dict/translation/' + source_lang + '/' + target_lang; 19 | const loginHeaders = { 20 | 'Accept': 'application/json, text/javascript, */*;', 21 | 'Accept-Encoding': 'gzip, deflate', 22 | 'Accept-Language': 'zh-CN,zh;q=0.9', 23 | 'Cache-Control': 'no-cache', 24 | // 'Content-Length': '1910', 25 | 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 26 | // 'Host': 'track.hujiang.com', 27 | 'Origin': 'http://res.d.hjfile.cn', 28 | 'Pragma': 'no-cache', 29 | 'Proxy-Connection': 'keep-alive', 30 | 'Referer': 'http://res.d.hjfile.cn/app/trans', 31 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36' 32 | } 33 | const translateHeaders = { 34 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 35 | // 'Accept-Encoding': 'gzip, deflate', 36 | // 'Accept-Language': 'zh-CN,zh;q=0.9', 37 | // 'Cache-Control': 'no-cache', 38 | // 'Content-Length': '1910', 39 | 'Host': 'res.d.hjfile.cn', 40 | 'Origin': 'http://res.d.hjfile.cn', 41 | // 'Pragma': 'no-cache', 42 | // 'Proxy-Connection': 'keep-alive', 43 | 'Referer': 'http://res.d.hjfile.cn/app/trans', 44 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36' 45 | } 46 | 47 | // const d = btoa(encodeURIComponent('{"hj_siteid":3,"hj_uid":"e2235725-ea43-9572-4cc8-998d7ed13e9b","hj_sid":"7636bbd9-294e-bf2d-5f29-6b800c77a6e9","hj_ssid":"d5d98b26-2a60-91d0-f37b-27b0ce05c2c0","hj_url":"http://res.d.hjfile.cn/app/trans","hj_urlref":"","hjid":0,"hj_p":"{\\"res\\":\\"1440*900\\",\\"wres\\":\\"291*796\\",\\"bdhm\\":null,\\"title\\":\\"%E5%85%A8%E6%96%87%E7%BF%BB%E8%AF%91_%E5%A4%9A%E8%AF%AD%E7%A7%8D%E5%9C%A8%E7%BA%BF%E7%BF%BB%E8%AF%91_%E6%B2%AA%E6%B1%9F%E5%B0%8FD\\"}","hj_vt":0,"hj_sst":1,"hj_csst":1,"hj_st":1,"hj_cst":0,"hj_ref":"","hj_sref":"","hj_fp":1370931257,"hj_v":"1.4.7","hj_ua":"mozilla/5.0 (macintosh; intel mac os x 10_15_7) applewebkit/537.36 (khtml, like gecko) chrome/109.0.0.0 safari/537.36","hj_t":1676825564724,"ch_source":"","hj_sr":"direct","hj_srp":"","hj_src":"","hj_srpt":"","hj_ssr":"direct","hj_ssrp":"","hj_ssrc":"","hj_ssrpt":"","hj_tm":"pc","_":"56496300e94da42f","is_sync":1}')) 48 | // TODO 尝试篡改id后,服务端并未报错,说明后端未校验,暂且先用着;后续研究id生成算法,自行生成id,而不应该写死 49 | const d = btoa(encodeURIComponent('{"hj_siteid":3,"hj_uid":"e2235234-ea43-9572-4cc8-998d7ed13e9b","hj_sid":"7666bbd9-294e-bf2d-5f29-6b800c77a6e9","hj_ssid":"d5d99b26-2a60-91d0-f37b-27b0ce05c2c0","hj_url":"http://res.d.hjfile.cn/app/trans","hj_urlref":"","hjid":0,"hj_p":"{\\"res\\":\\"1440*900\\",\\"wres\\":\\"291*796\\",\\"bdhm\\":null,\\"title\\":\\"%E5%85%A8%E6%96%87%E7%BF%BB%E8%AF%91_%E5%A4%9A%E8%AF%AD%E7%A7%8D%E5%9C%A8%E7%BA%BF%E7%BF%BB%E8%AF%91_%E6%B2%AA%E6%B1%9F%E5%B0%8FD\\"}","hj_vt":0,"hj_sst":1,"hj_csst":1,"hj_st":1,"hj_cst":0,"hj_ref":"","hj_sref":"","hj_fp":1370931257,"hj_v":"1.4.7","hj_ua":"mozilla/5.0 (macintosh; intel mac os x 10_15_7) applewebkit/537.36 (khtml, like gecko) chrome/109.0.0.0 safari/537.36","hj_t":1676825564724,"ch_source":"","hj_sr":"direct","hj_srp":"","hj_src":"","hj_srpt":"","hj_ssr":"direct","hj_ssrp":"","hj_ssrc":"","hj_ssrpt":"","hj_tm":"pc","_":"56496300e94da42f","is_sync":1}')) 50 | 51 | const loginFormData = { 52 | 'd': d, 53 | 't': Date.now() 54 | } 55 | try { 56 | /*const uid_resp = await $http.request({ 57 | method: "POST", 58 | url: loginUrl, 59 | header: loginHeaders, 60 | body: loginFormData 61 | }); 62 | if (uid_resp.data && uid_resp.data.HJ_UID) { 63 | translateHeaders.Cookie = 'HJ_UID='+uid_resp.data.HJ_UID+'; HJC_USRC=uzhi; HJC_NUID=1' 64 | } else { 65 | const errMsg = uid_resp.data ? JSON.stringify(uid_resp.data) : '获取UID未返回有效结果=>' + JSON.stringify(uid_resp) 66 | completion({ 67 | error: { 68 | type: 'unknown', 69 | message: errMsg, 70 | addtion: errMsg, 71 | }, 72 | }); 73 | }*/ 74 | translateHeaders.Cookie = 'HJ_UID=390f25c7-c9f3-b237-f639-62bd23cd431f; HJC_USRC=uzhi; HJC_NUID=1' 75 | const resp = await $http.request({ 76 | method: "POST", 77 | url: url, 78 | header: translateHeaders, 79 | body: {content: translate_text} 80 | }); 81 | if (resp.data && resp.data.data && resp.data.data.content) { 82 | completion({ 83 | result: { 84 | from: query.detectFrom, 85 | to: query.detectTo, 86 | toParagraphs: resp.data.data.content.split('\n'), 87 | }, 88 | }); 89 | } else { 90 | const errMsg = resp.data ? JSON.stringify(resp.data) : '请求翻译接口失败,请检查网络' 91 | completion({ 92 | error: { 93 | type: 'unknown', 94 | message: errMsg, 95 | addtion: errMsg, 96 | }, 97 | }); 98 | } 99 | } catch (e) { 100 | $log.error('接口请求错误 ==> ' + JSON.stringify(e)) 101 | Object.assign(e, { 102 | _type: 'network', 103 | _message: '接口请求错误 - ' + JSON.stringify(e), 104 | }); 105 | throw e; 106 | } 107 | 108 | } 109 | 110 | exports.translate = translate; 111 | -------------------------------------------------------------------------------- /node_js/bd.js: -------------------------------------------------------------------------------- 1 | /** 2 | * nodejs 爬取百度翻译 3 | */ 4 | const axios = require('axios'); 5 | 6 | async function fetchHtml(url, headers) { 7 | try { 8 | return await axios.get(url, {headers}); 9 | } catch (error) { 10 | throw new Error(error); 11 | } 12 | } 13 | 14 | async function postData(url, data, headers) { 15 | try { 16 | const response = await axios.post(url, data, {headers}); 17 | return response.data; 18 | } catch (error) { 19 | throw new Error(error); 20 | } 21 | } 22 | 23 | 24 | function n(t, e) { 25 | for (var n = 0; n < e.length - 2; n += 3) { 26 | var r = e.charAt(n + 2); 27 | r = "a" <= r ? r.charCodeAt(0) - 87 : Number(r), 28 | r = "+" === e.charAt(n + 1) ? t >>> r : t << r, 29 | t = "+" === e.charAt(n) ? t + r & 4294967295 : t ^ r 30 | } 31 | return t 32 | } 33 | 34 | function encrypt(t, gtk) { 35 | // window.gtk = "320305.131321201"; 36 | console.log(t, gtk) 37 | let r = gtk 38 | var o, i = t.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g); 39 | if (null === i) { 40 | var a = t.length; 41 | a > 30 && (t = "".concat(t.substr(0, 10)).concat(t.substr(Math.floor(a / 2) - 5, 10)).concat(t.substr(-10, 10))) 42 | } else { 43 | for (var s = t.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), c = 0, l = s.length, u = []; c < l; c++) 44 | "" !== s[c] && u.push.apply(u, function (t) { 45 | if (Array.isArray(t)) 46 | return e(t) 47 | }(o = s[c].split("")) || function (t) { 48 | if ("undefined" != typeof Symbol && null != t[Symbol.iterator] || null != t["@@iterator"]) 49 | return Array.from(t) 50 | }(o) || function (t, n) { 51 | if (t) { 52 | if ("string" == typeof t) 53 | return e(t, n); 54 | var r = Object.prototype.toString.call(t).slice(8, -1); 55 | return "Object" === r && t.constructor && (r = t.constructor.name), 56 | "Map" === r || "Set" === r ? Array.from(t) : "Arguments" === r || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r) ? e(t, n) : void 0 57 | } 58 | }(o) || function () { 59 | throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.") 60 | }()), 61 | c !== l - 1 && u.push(i[c]); 62 | var p = u.length; 63 | p > 30 && (t = u.slice(0, 10).join("") + u.slice(Math.floor(p / 2) - 5, Math.floor(p / 2) + 5).join("") + u.slice(-10).join("")) 64 | } 65 | for (var d = "".concat(String.fromCharCode(103)).concat(String.fromCharCode(116)).concat(String.fromCharCode(107)), h = (null !== r ? r : (r = window[d] || "") || "").split("."), f = Number(h[0]) || 0, m = Number(h[1]) || 0, g = [], y = 0, v = 0; v < t.length; v++) { 66 | var _ = t.charCodeAt(v); 67 | _ < 128 ? g[y++] = _ : (_ < 2048 ? g[y++] = _ >> 6 | 192 : (55296 == (64512 & _) && v + 1 < t.length && 56320 == (64512 & t.charCodeAt(v + 1)) ? (_ = 65536 + ((1023 & _) << 10) + (1023 & t.charCodeAt(++v)), 68 | g[y++] = _ >> 18 | 240, 69 | g[y++] = _ >> 12 & 63 | 128) : g[y++] = _ >> 12 | 224, 70 | g[y++] = _ >> 6 & 63 | 128), 71 | g[y++] = 63 & _ | 128) 72 | } 73 | for (var b = f, w = "".concat(String.fromCharCode(43)).concat(String.fromCharCode(45)).concat(String.fromCharCode(97)) + "".concat(String.fromCharCode(94)).concat(String.fromCharCode(43)).concat(String.fromCharCode(54)), k = "".concat(String.fromCharCode(43)).concat(String.fromCharCode(45)).concat(String.fromCharCode(51)) + "".concat(String.fromCharCode(94)).concat(String.fromCharCode(43)).concat(String.fromCharCode(98)) + "".concat(String.fromCharCode(43)).concat(String.fromCharCode(45)).concat(String.fromCharCode(102)), x = 0; x < g.length; x++) 74 | b = n(b += g[x], w); 75 | return b = n(b, k), 76 | (b ^= m) < 0 && (b = 2147483648 + (2147483647 & b)), 77 | "".concat((b %= 1e6).toString(), ".").concat(b ^ f) 78 | } 79 | 80 | 81 | (async () => { 82 | try { 83 | const url = 'https://fanyi.baidu.com/'; 84 | // 第一轮取cookie 85 | const htmlResp = await fetchHtml(url); 86 | const cookie = htmlResp.headers.get('set-cookie')[0] 87 | console.log(cookie) 88 | // console.log(htmlResp.text.match(/Set-Cookie:\s*(.*?);/i)) 89 | // 第二轮取gtk,token 90 | const htmlResp2 = await fetchHtml(url, {Cookie: cookie}); 91 | // console.log(html2) 92 | // const specialChar = html.match(//)[1]; 93 | // console.log(htmlResp2.data) 94 | const gtkMatch = htmlResp2.data.match(/window\.gtk\s*=\s*"([\d.]+)"/); 95 | const token = htmlResp2.data.match(/token:\s*'(\w+)'/)[1]; 96 | const gtk = gtkMatch ? gtkMatch[1] : null; 97 | console.log(token,gtk) 98 | const headers = { 99 | Cookie: cookie, 100 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 101 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36' 102 | }; 103 | const t = 'The API reference documentation provides detailed information about a function or object in Node.js. This documentation indicates what arguments a method accepts, the return value of that method, and what errors may be related to that method. It also indicates which methods are available for different versions of Node.js.'; 104 | const _encrypt = encrypt(t, gtk); 105 | console.log(_encrypt) 106 | const data = { 107 | from: 'en', 108 | to: 'zh', 109 | query: t, 110 | transtype: 'realtime', 111 | simple_means_flag: '3', 112 | sign: _encrypt, 113 | token: token 114 | }; 115 | const response = await postData('https://fanyi.baidu.com/v2transapi?from=zh&to=en', data, headers); 116 | console.log(response.trans_result.data[0].dst); 117 | } catch (error) { 118 | console.error(error); 119 | } 120 | })(); 121 | 122 | -------------------------------------------------------------------------------- /src/b.js: -------------------------------------------------------------------------------- 1 | function n(t, e) { 2 | for (var n = 0; n < e.length - 2; n += 3) { 3 | var r = e.charAt(n + 2); 4 | r = "a" <= r ? r.charCodeAt(0) - 87 : Number(r), 5 | r = "+" === e.charAt(n + 1) ? t >>> r : t << r, 6 | t = "+" === e.charAt(n) ? t + r & 4294967295 : t ^ r 7 | } 8 | return t 9 | } 10 | 11 | function encrypt(t, gtk) { 12 | console.log(t, gtk) 13 | let r = gtk 14 | var o, i = t.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g); 15 | if (null === i) { 16 | var a = t.length; 17 | a > 30 && (t = "".concat(t.substr(0, 10)).concat(t.substr(Math.floor(a / 2) - 5, 10)).concat(t.substr(-10, 10))) 18 | } else { 19 | for (var s = t.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), c = 0, l = s.length, u = []; c < l; c++) 20 | "" !== s[c] && u.push.apply(u, function (t) { 21 | if (Array.isArray(t)) 22 | return e(t) 23 | }(o = s[c].split("")) || function (t) { 24 | if ("undefined" != typeof Symbol && null != t[Symbol.iterator] || null != t["@@iterator"]) 25 | return Array.from(t) 26 | }(o) || function (t, n) { 27 | if (t) { 28 | if ("string" == typeof t) 29 | return e(t, n); 30 | var r = Object.prototype.toString.call(t).slice(8, -1); 31 | return "Object" === r && t.constructor && (r = t.constructor.name), 32 | "Map" === r || "Set" === r ? Array.from(t) : "Arguments" === r || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r) ? e(t, n) : void 0 33 | } 34 | }(o) || function () { 35 | throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.") 36 | }()), 37 | c !== l - 1 && u.push(i[c]); 38 | var p = u.length; 39 | p > 30 && (t = u.slice(0, 10).join("") + u.slice(Math.floor(p / 2) - 5, Math.floor(p / 2) + 5).join("") + u.slice(-10).join("")) 40 | } 41 | for (var d = "".concat(String.fromCharCode(103)).concat(String.fromCharCode(116)).concat(String.fromCharCode(107)), h = (null !== r ? r : (r = window[d] || "") || "").split("."), f = Number(h[0]) || 0, m = Number(h[1]) || 0, g = [], y = 0, v = 0; v < t.length; v++) { 42 | var _ = t.charCodeAt(v); 43 | _ < 128 ? g[y++] = _ : (_ < 2048 ? g[y++] = _ >> 6 | 192 : (55296 == (64512 & _) && v + 1 < t.length && 56320 == (64512 & t.charCodeAt(v + 1)) ? (_ = 65536 + ((1023 & _) << 10) + (1023 & t.charCodeAt(++v)), 44 | g[y++] = _ >> 18 | 240, 45 | g[y++] = _ >> 12 & 63 | 128) : g[y++] = _ >> 12 | 224, 46 | g[y++] = _ >> 6 & 63 | 128), 47 | g[y++] = 63 & _ | 128) 48 | } 49 | for (var b = f, w = "".concat(String.fromCharCode(43)).concat(String.fromCharCode(45)).concat(String.fromCharCode(97)) + "".concat(String.fromCharCode(94)).concat(String.fromCharCode(43)).concat(String.fromCharCode(54)), k = "".concat(String.fromCharCode(43)).concat(String.fromCharCode(45)).concat(String.fromCharCode(51)) + "".concat(String.fromCharCode(94)).concat(String.fromCharCode(43)).concat(String.fromCharCode(98)) + "".concat(String.fromCharCode(43)).concat(String.fromCharCode(45)).concat(String.fromCharCode(102)), x = 0; x < g.length; x++) 50 | b = n(b += g[x], w); 51 | return b = n(b, k), 52 | (b ^= m) < 0 && (b = 2147483648 + (2147483647 & b)), 53 | "".concat((b %= 1e6).toString(), ".").concat(b ^ f) 54 | } 55 | 56 | 57 | async function translate(query, source_lang, target_lang, translate_text, completion) { 58 | // 特殊处理把cn替换为zh 59 | if (source_lang == 'cn') { 60 | source_lang = 'zh' 61 | } 62 | if (target_lang == 'cn') { 63 | target_lang = 'zh' 64 | } 65 | // 特殊处理日语 66 | if (source_lang == 'ja') { 67 | source_lang = 'jp' 68 | } 69 | if (target_lang == 'ja') { 70 | target_lang = 'jp' 71 | } 72 | try { 73 | const url = 'https://fanyi.baidu.com/'; 74 | // 第一轮取cookie 75 | const respCookie = await $http.request({ 76 | method: "GET", 77 | url: url, 78 | header: { 79 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', 80 | 'Accept-Encoding': 'gzip, deflate, br', 81 | 'Accept-Language': 'zh-CN,zh;q=0.9', 82 | 'Cache-Control': 'no-cache', 83 | 'Connection': 'keep-alive', 84 | 'Host': 'fanyi.baidu.com', 85 | 'Pragma': 'no-cache', 86 | 'sec-ch-ua': '"Chromium";v="110", "Not A(Brand";v="24", "Google Chrome";v="110"', 87 | 'sec-ch-ua-mobile': '?0', 88 | 'sec-ch-ua-platform': '"macOS"', 89 | 'Sec-Fetch-Dest': 'document', 90 | 'Sec-Fetch-Mode': 'navigate', 91 | 'Sec-Fetch-Site': 'none', 92 | 'Sec-Fetch-User': '?1', 93 | 'Upgrade-Insecure-Requests': '1', 94 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36' 95 | } 96 | }); 97 | 98 | // 第二轮取gtk,token 99 | const respTks = await $http.request({ 100 | method: "GET", 101 | header: { 102 | // 'Cookie': cookie, 103 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36' 104 | 105 | }, 106 | url: url 107 | }); 108 | const gtk = respTks.data.match(/window\.gtk\s*=\s*"([\d.]+)"/)[1]; 109 | const token = respTks.data.match(/token:\s*'(\w+)'/)[1]; 110 | const headers = { 111 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 112 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36' 113 | }; 114 | const sign = encrypt(translate_text, gtk) 115 | 116 | const data = { 117 | from: source_lang, 118 | to: target_lang, 119 | query: translate_text, 120 | transtype: 'realtime', 121 | simple_means_flag: '3', 122 | sign: sign, 123 | token: token 124 | }; 125 | const resp = await $http.request({ 126 | method: "POST", 127 | url: 'https://fanyi.baidu.com/v2transapi?from=' + source_lang + '&to=' + target_lang, 128 | header: headers, 129 | body: data 130 | }); 131 | if (resp.data && resp.data.trans_result && resp.data.trans_result.data.length && resp.data.trans_result.data[0].dst) { 132 | const rs = [] 133 | resp.data.trans_result.data.forEach(function (item) { 134 | rs.push(item.dst) 135 | }) 136 | completion({ 137 | result: { 138 | from: query.detectFrom, 139 | to: query.detectTo, 140 | toParagraphs: rs, 141 | }, 142 | }); 143 | } else { 144 | const errMsg = resp.data ? JSON.stringify(resp.data) : '请求翻译接口失败,请检查网络' 145 | completion({ 146 | error: { 147 | type: 'unknown', 148 | message: errMsg, 149 | addtion: errMsg, 150 | }, 151 | }); 152 | } 153 | } catch (e) { 154 | $log.error('接口请求错误 ==> ' + JSON.stringify(e)) 155 | Object.assign(e, { 156 | _type: 'network', 157 | _message: '接口请求错误 - ' + JSON.stringify(e), 158 | }); 159 | throw e; 160 | } 161 | } 162 | 163 | exports.translate = translate; 164 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------