From 1fcd127393770c4f93c0fe97d3676c41382adec8 Mon Sep 17 00:00:00 2001 From: Dokiy Date: Tue, 23 Feb 2021 18:46:45 +0800 Subject: [PATCH 1/3] update shanbay private api --- assets/manifest.json | 1 + src/background.js | 8 +++ src/components/add_word.js | 69 ++++++++++++++++------- src/components/icons.js | 2 + src/event_page.js | 102 +++++---------------------------- src/shanbay_api.js | 112 +++++++++++++++++++++++++++++++++++++ 6 files changed, 187 insertions(+), 107 deletions(-) create mode 100644 src/background.js create mode 100644 src/shanbay_api.js diff --git a/assets/manifest.json b/assets/manifest.json index b44911c..66891ed 100644 --- a/assets/manifest.json +++ b/assets/manifest.json @@ -44,6 +44,7 @@ "storage", "activeTab", "tabs", + "notifications", "http://dict.youdao.com/", "https://api.shanbay.com/" ] diff --git a/src/background.js b/src/background.js new file mode 100644 index 0000000..2ff95f0 --- /dev/null +++ b/src/background.js @@ -0,0 +1,8 @@ +window.__shanbayExtensionAuthInfo = { + checkAuth (callback) { + chrome.cookies.getAll({url: 'https://www.shanbay.com'}, cookies => { + const auth_token = (cookies.find(cookie => cookie.name === 'auth_token') || {}).value + callback(auth_token) + }) + } +} \ No newline at end of file diff --git a/src/components/add_word.js b/src/components/add_word.js index 0add774..0548219 100644 --- a/src/components/add_word.js +++ b/src/components/add_word.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import icons from './icons' import { addNotebookWord } from '../message' -const SHANBAY_URL = 'https://www.shanbay.com/bdc/learnings/library/' +const SHANBAY_URL = 'https://web.shanbay.com/wordsweb/#/collection' const styles = { container: { @@ -24,18 +24,33 @@ const styles = { width: 8, height: 8, }, + check: { + position: 'absolute', + left: 8, + bottom: 0, + width: 10, + height: 10, + }, + invalid: { + position: 'absolute', + left: 8, + bottom: 0, + width: 10, + height: 10, + }, } class AddWord extends Component { constructor(props) { super(props) - const { defaultAdded } = props + const { defaultAdded, defaultInvalid } = props this.addWord = this.addWord.bind(this) this.state = { added: defaultAdded, + invalid: defaultInvalid } } @@ -45,17 +60,17 @@ class AddWord extends Component { addWord() { const { word } = this.props - addNotebookWord(word).then((response) => { const { success, msg } = response - - if (!success) { - throw new Error(msg) + + if (!!success) { + this.setState({ added: true, }) + } else if(msg == 'Invalid Token!') { + this.setState({ invalid: true, added: false }) + } else { + throw new Error(msg); } - this.setState({ - added: true, - }) }).catch((err) => { this.props.flash(err.message) }) @@ -64,32 +79,46 @@ class AddWord extends Component { render() { const { addWord } = this const { word, showWordsPage } = this.props - const { added } = this.state + const { added, invalid } = this.state if (!word || !showWordsPage) { return null } const content = ( -
- book - {!added ? ( +
+ + { !!invalid ? ( + invalid + ) : !added? ( plus - ) : null} + ) : ( + check + ) } + + book
) return added ? ( { - oauth.authorize(() => { - resolve() - }) - }) -} - -const ADD_WORD_URL = 'https://api.shanbay.com/bdc/learning/' -const SEARCH_WORD_URL = 'https://api.shanbay.com/bdc/search/' - -function getWord(url) { - return fetch(url).then(res => res.json()).then((res) => { - const { data, msg } = res - - if (msg !== 'SUCCESS') { - throw new Error(msg) - } - - return data - }) -} - -function clearShanbayToken() { - oauth.clearToken() -} - async function addWordToShanbay(data, sendRes) { - // redirect - if (!oauth.token_valid()) { - await authorize() - } - - const token = oauth.access_token() - - const searchURL = `${SEARCH_WORD_URL}?word=${data}&access_token=${token}` let response = null - try { - response = await getWord(searchURL) - } catch (err) { - // 如果token失效,清除token并重新添加 - if (err.message === 'Invalid token') { - clearShanbayToken() - await addWordToShanbay(data, sendRes) - return - } - - sendRes({ - success: false, - msg: err.message, - }) - - return - } - - const { id } = response + // get shanbay word id + response = await lookUp(data) + const { id } = response - const addWordURL = `${ADD_WORD_URL}?access_token=${token}` + // add word + addWord(id) - try { - response = await fetch(addWordURL, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - id, - access_token: token, - }), - }).then(res => res.json()).then((res) => { - const { data: d, msg } = res - - if (msg !== 'SUCCESS') { - throw new Error(msg) - } - - return d - }) + sendRes({ success: true }) } catch (err) { - sendRes({ - success: false, - msg: err.message, - }) + sendRes({ success: false, msg: 'Invalid Token!' }) - return + notify({ + title: '扇贝认证失败!', + message: '登录后才能使用生词本功能。\n点击此消息前往扇贝登录', + url: 'https://web.shanbay.com/web/account/login/' + }) } - - sendRes({ - success: true, - }) } function openNewTab(word) { @@ -125,8 +53,6 @@ function openNewTab(word) { } function init() { - oauth = ShanbayOauth.initPage() - onMessage(SEARCH_WORD, (data, sendRes) => { getWords(data, sendRes) }) diff --git a/src/shanbay_api.js b/src/shanbay_api.js new file mode 100644 index 0000000..f8a9b8d --- /dev/null +++ b/src/shanbay_api.js @@ -0,0 +1,112 @@ +/** + * @author maicss + * @file some licences file + * @copyright 2017-2020 maicss + * */ + +/** + * chrome 通知处理方法, 传入的参数就是chrome notifications的参数 + * @function notify + * @param {object} opt - chrome notifications 的参数 + * @param {string} opt.title=人丑多读书 - notifications title + * @param {string} [opt.message=少壮不努力,老大背单词] - notifications message + * @param {string} [opt.url=https://www.shanbay.com/] - notifications url, notifications可以点击跳转 + * */ +export const notify = (opt = {title: '人丑多读书', message: '少壮不努力,老大背单词', url: 'https://www.shanbay.com/'}) => { + let hasNotified = false + const options = { + type: 'basic', + title: opt.title, + message: opt.message, + iconUrl: './icons/icon48.png', + } + let noteID = Math.random().toString(36) + chrome.notifications.create(noteID, options, (notifyID) => { + hasNotified = true + }) + chrome.notifications.onClicked.addListener(function (notifyID) { + chrome.notifications.clear(notifyID) + if (noteID === notifyID) { + chrome.tabs.create({ + url: opt.url + }) + } + hasNotified = false + }) +} + +/** + * 基于fetch的网络请求方法的封装,只有两种数据的返回,buffer和json,因为这个应用里面只用到了这两种 + * @function request + * @see [use fetch API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch} + * @param {string} url - request url + * @param {object} [options] - fetch options + * @param {string} [options.type='buffer'] - whether need return buffer + * @return Promise + * */ +const request = (url, options = {}) => { + options = Object.assign(options, { credentials: 'include' }) + return fetch(url, options) + .then(res => { + if (res.ok) { + if (options.type === 'buffer') return res.arrayBuffer() + return res.json() + } else { + return Promise.reject(res.json ? res.json() : res.text()) + } + }) + // .catch(e => debugLogger('error', `[${new Date().toLocaleDateString()}] fetch failed ${options.method || 'GET'} ${url} ${JSON.stringify(e)}`)) + .catch(e => { + if (e.status === 400) { + notify({ + title: '扇贝认证失败', + message: '点击此消息登录', + url: 'https://web.shanbay.com/web/account/login/' + }) + } else { + return e.then ? e.then(error => Promise.reject(error)) : Promise.reject(e) + } + }) +} + +/** + * shanbay API的需要用到的方法,没什么用,只是一个参考 + * 扇贝开放API关闭之后,直接读取扇贝网的cookie,使用扇贝私有API + * @constant + * @readonly + * @enum {object} + * */ +const shanbayAPI = { + /** 查询单词*/ + lookUp: { + method: 'GET', + url: 'https://apiv3.shanbay.com/abc/words/senses?vocabulary_content={word}', + params: ['word'] + }, + /** 添加生词和标记已添加生词已忘记 */ + addWord: { + method: 'POST', + url: 'https://apiv3.shanbay.com/news/words', + params: [{"vocab_id":"","business_id":2,"paragraph_id":"1","sentence_id":"A1","source_content":"","article_id":"ca","source_name":"","summary":""}] + } +} + +/** + * @description 查询单词 + * @function lookUp + * @param {string} word - 需要查询的单词 + * @return Promise + * */ +export const lookUp = word => request((shanbayAPI.lookUp.url).replace('{word}', word), {method: shanbayAPI.lookUp.method}) + +/** + * @description 添加单词到单词本或忘记单词 + * @param {string} word - 单词 + * @param {string} wordID - 单词id + * @return Promise + */ +export const addWord = (wordID) => request(shanbayAPI.addWord.url, { + method: shanbayAPI.addWord.method, + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({"vocab_id": wordID,"business_id":2,"paragraph_id":"1","sentence_id":"A1","source_content":"","article_id":"ca","source_name":"","summary":""}) +}) \ No newline at end of file From 0811fcb2aca72e329a1d9f9c07a1024e88464da4 Mon Sep 17 00:00:00 2001 From: Dokiy Date: Wed, 24 Feb 2021 09:21:36 +0800 Subject: [PATCH 2/3] delete unused file --- src/background.js | 8 -------- src/shanbay_api.js | 7 ++----- 2 files changed, 2 insertions(+), 13 deletions(-) delete mode 100644 src/background.js diff --git a/src/background.js b/src/background.js deleted file mode 100644 index 2ff95f0..0000000 --- a/src/background.js +++ /dev/null @@ -1,8 +0,0 @@ -window.__shanbayExtensionAuthInfo = { - checkAuth (callback) { - chrome.cookies.getAll({url: 'https://www.shanbay.com'}, cookies => { - const auth_token = (cookies.find(cookie => cookie.name === 'auth_token') || {}).value - callback(auth_token) - }) - } -} \ No newline at end of file diff --git a/src/shanbay_api.js b/src/shanbay_api.js index f8a9b8d..07f503a 100644 --- a/src/shanbay_api.js +++ b/src/shanbay_api.js @@ -46,17 +46,14 @@ export const notify = (opt = {title: '人丑多读书', message: '少壮不努 * */ const request = (url, options = {}) => { options = Object.assign(options, { credentials: 'include' }) - return fetch(url, options) - .then(res => { + return fetch(url, options).then(res => { if (res.ok) { if (options.type === 'buffer') return res.arrayBuffer() return res.json() } else { return Promise.reject(res.json ? res.json() : res.text()) } - }) - // .catch(e => debugLogger('error', `[${new Date().toLocaleDateString()}] fetch failed ${options.method || 'GET'} ${url} ${JSON.stringify(e)}`)) - .catch(e => { + }).catch(e => { if (e.status === 400) { notify({ title: '扇贝认证失败', From a26db2797adf01401f80a0a36cc674377d83739a Mon Sep 17 00:00:00 2001 From: Dokiy Date: Fri, 26 Feb 2021 17:01:40 +0800 Subject: [PATCH 3/3] fix word not found --- build.pem | 28 ++++++++++++++++++++++++++++ src/components/audio.js | 2 +- src/event_page.js | 6 +++++- 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 build.pem diff --git a/build.pem b/build.pem new file mode 100644 index 0000000..9eb6b41 --- /dev/null +++ b/build.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCinep+LvPP9QVz +cFTrWmSGIvEG9YId8DyYJJudIKtpZXtt7vAum7etFtJaVoEyC/ucVLvcvtDPBI+9 +ixgL1iMuITfBY8uk6UpjghkT0kl5HR+oa6U8aNMr1MFdcMXIwd753s9ci6a/2cjh +Apvp82Wpkrhs+N/d/GbA5dyoawYZIXXgqBKKIP323PFjezmW1NGcwNoFY7GQeAqs +M1VGAsiHzVoauWwPgcl+USvLfFJXd0m+zw00BRPbbmFEY+bivVvxI0Lapi8iO453 +L+WONScwQCrJvZlILD+aoxlEX9lS6ZJtmek30o0v/lxICBBqVG2BkzpOMuL3n6G+ +yDGPs9aDAgMBAAECggEAMSHXTKKxBZ75M6S385gPETwTaM/arWL9W9aLsdDCGYkQ +3uk3Zk2kFEb17Vd/l3hpYBV14T9B5ZpyN4mEDWd4n6JnryWQzNWzpRcUrpl1m4NC +ImfLt9HQI8kXVz0QdRSmYwZ/zm1fR03s1JcuNmRUzgRHdp1HPlHZVeTdY4FaiVLI +cq4nMAayY14oXL8CmEjSQIP+cNUvhYrSHgZRPdH3Lul4Kh4qsg3uS9Btjp4uydCL +TKKbFXGJ+AUtzfvIJUpwx3pjwBqBIvlUL8Mqp/kJMA3X50PNrZEq9RL5pnWvLbC1 +09EzgVCAnLDTGjYLiWQTjgGBNUp3FGLHXptZNdOAMQKBgQDQCprue7gAxS1xbAKd +fjtT/LIX/6X3Ro1LO+LyuI+E2IOuH3wDR1SyFjzYx+LWtAFGPVb5mmPz5PaebzeU +80kE3RfYkjoR9ldAKiFW/PJMf9ADrZPhwHvTc1zeGurbEi4hl9eRsdNWueolxjBp +VUFXuGN997g5XXZRlUSsJ3wdmwKBgQDIGp34HAnUMk/exg2VAeQ5aMwmbbE1S5sw +ec+Zbs6DwrlZMRVYimu9NOyg6JUBIHNmkAp1UGtcu6qclnLetuJSvD53qFzKWCqY +yB65qCLKBeVglt9aJEUYVXtvnujMt+jqwhglJZM1NGVUcxAkIqrk1kT81BkZI7YE +yIA6B+ctOQKBgQDNUiomRCQNXozC6/6IwRR8h2CdHsoFibPZFHmfY1cBnU4Ygyo5 +ciS8vgW/TUcq7uxzDgbQwPb0tnxPUSRh9NmT20C1lVuKbr0drnbJC0t3BI2fk6fn +nbiXr7tv2NEA9KhiryEpwX76kPHt5fPRgTrEAE7w+5LtyrgDPHZSEYYFEQKBgBZA +n4CP3afzUF59t9TyOOcJeGptmF9M4R0q7qMpZ13PsbzxcGZAPmr0D7x1INzXNv4Y +1pDlOIs/c2GmeW+69sAsnuW/m1IFK/eBiakrwXKl5TQwkvX7QpPKLcfj7A+YBBbX +LsgyvYQVJ4+UnB7onAiGq3VSQNhC2GL/yQKrDlJBAoGAQlyTpRpZZ/s27dI9J4Tj +eVzcBdMVizt/vbnfCfmIGSahzmgOzIn2Zj76L9GSOvcgtRAd+sU2JXZLaKFBnS5P +iXxq1OfKLZK7fwjC4Up4lYJ7vNqpYbSTR8a5HlMgKcV1ZJiHG/ThlZe1qyFqvdq4 +4hpG3DYVv7mEwtgMa516a0E= +-----END PRIVATE KEY----- diff --git a/src/components/audio.js b/src/components/audio.js index b91fbd0..f518086 100644 --- a/src/components/audio.js +++ b/src/components/audio.js @@ -5,7 +5,7 @@ import icons from './icons' const { string } = PropTypes function getAudioURL(word, type = 1) { - return `http://dict.youdao.com/dictvoice?audio=${word}&type=${type}` + return `https://dict.youdao.com/dictvoice?audio=${word}&type=${type}` } class Audio extends Component { diff --git a/src/event_page.js b/src/event_page.js index d738f0f..04b0c87 100644 --- a/src/event_page.js +++ b/src/event_page.js @@ -38,8 +38,12 @@ async function addWordToShanbay(data, sendRes) { sendRes({ success: true }) } catch (err) { - sendRes({ success: false, msg: 'Invalid Token!' }) + if (err.msg == "单词没找到") { + sendRes({ success: false, msg: 'Shabay: Word Not Found!' }) + return + } + sendRes({ success: false, msg: 'Invalid Token!' }) notify({ title: '扇贝认证失败!', message: '登录后才能使用生词本功能。\n点击此消息前往扇贝登录',