diff --git a/ext/bg/js/ankiweb.js b/ext/bg/js/ankiweb.js deleted file mode 100644 index 69a1b44d..00000000 --- a/ext/bg/js/ankiweb.js +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2016 Alex Yatskov - * Author: Alex Yatskov - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -class AnkiWeb { - constructor(username, password) { - this.username = username; - this.password = password; - this.noteInfo = null; - - chrome.webRequest.onBeforeSendHeaders.addListener( - details => { - details.requestHeaders.push({name: 'Origin', value: 'https://ankiweb.net'}); - return {requestHeaders: details.requestHeaders}; - }, - {urls: ['https://ankiweb.net/*']}, - ['blocking', 'requestHeaders'] - ); - } - - addNote(note) { - return this.retrieve().then(info => { - const model = info.models.find(m => m.name === note.modelName); - if (!model) { - return Promise.reject('cannot add note model provided'); - } - - const fields = []; - for (const field of model.fields) { - fields.push(note.fields[field]); - } - - const data = { - data: JSON.stringify([fields, note.tags.join(' ')]), - mid: model.id, - deck: note.deckName, - csrf_token: info.token - }; - - return AnkiWeb.loadAccountPage('https://ankiweb.net/edit/save', data, this.username, this.password); - }).then(response => response !== '0'); - } - - canAddNotes(notes) { - return Promise.resolve(new Array(notes.length).fill(true)); - } - - getDeckNames() { - return this.retrieve().then(info => info.deckNames); - } - - getModelNames() { - return this.retrieve().then(info => info.models.map(m => m.name)); - } - - getModelFieldNames(modelName) { - return this.retrieve().then(info => { - const model = info.models.find(m => m.name === modelName); - return model ? model.fields : []; - }); - } - - retrieve() { - if (this.noteInfo !== null) { - return Promise.resolve(this.noteInfo); - } - - return AnkiWeb.scrape(this.username, this.password).then(({deckNames, models, token}) => { - this.noteInfo = {deckNames, models, token}; - return this.noteInfo; - }); - } - - logout() { - return AnkiWeb.loadPage('https://ankiweb.net/account/logout', null); - } - - static scrape(username, password) { - return AnkiWeb.loadAccountPage('https://ankiweb.net/edit/', null, username, password).then(response => { - const modelsMatch = /editor\.models = (.*}]);/.exec(response); - if (modelsMatch === null) { - return Promise.reject('failed to scrape model data'); - } - - const decksMatch = /editor\.decks = (.*}});/.exec(response); - if (decksMatch === null) { - return Promise.reject('failed to scrape deck data'); - } - - const tokenMatch = /editor\.csrf_token = \'(.*)\';/.exec(response); - if (tokenMatch === null) { - return Promise.reject('failed to acquire csrf_token'); - } - - const modelsJson = JSON.parse(modelsMatch[1]); - const decksJson = JSON.parse(decksMatch[1]); - const token = tokenMatch[1]; - - const deckNames = Object.keys(decksJson).map(d => decksJson[d].name); - const models = []; - for (const modelJson of modelsJson) { - models.push({ - name: modelJson.name, - id: modelJson.id, - fields: modelJson.flds.map(f => f.name) - }); - } - - return {deckNames, models, token}; - }); - } - - static login(username, password, token) { - if (username.length === 0 || password.length === 0) { - return Promise.reject('login credentials not specified'); - } - - const data = {username, password, csrf_token: token, submitted: 1}; - return AnkiWeb.loadPage('https://ankiweb.net/account/login', data).then(response => { - if (!response.includes('class="mitem"')) { - return Promise.reject('failed to authenticate'); - } - }); - } - - static loadAccountPage(url, data, username, password) { - return AnkiWeb.loadPage(url, data).then(response => { - if (response.includes('name="password"')) { - const tokenMatch = /name="csrf_token" value="(.*)"/.exec(response); - if (tokenMatch === null) { - return Promise.reject('failed to acquire csrf_token'); - } - - return AnkiWeb.login(username, password, tokenMatch[1]).then(() => AnkiWeb.loadPage(url, data)); - } else { - return response; - } - }); - } - - static loadPage(url, data) { - return new Promise((resolve, reject) => { - let dataEnc = null; - if (data) { - const params = []; - for (const key in data) { - params.push(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`); - } - - dataEnc = params.join('&'); - } - - const xhr = new XMLHttpRequest(); - xhr.addEventListener('error', () => reject('failed to execute network request')); - xhr.addEventListener('load', () => resolve(xhr.responseText)); - if (dataEnc) { - xhr.open('POST', url); - xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); - xhr.send(dataEnc); - } else { - xhr.open('GET', url); - xhr.send(); - } - }); - } -}