testing..

This commit is contained in:
openaudible 2018-09-13 12:49:43 -07:00
parent 037a75836b
commit b6e81920c6
14 changed files with 293 additions and 135 deletions

View file

@ -26,11 +26,11 @@ import java.net.URL;
import java.util.*; import java.util.*;
// audible.com web page scraper // audible.com web page scraper
// Not thread safe, run single instance at a time. // a singleton class..
public class AudibleScraper { public class AudibleScraper {
final static String cookiesFileName = "cookies.json"; final static String cookiesFileName = "cookies.json";
private static final Log LOG = LogFactory.getLog(AudibleScraper.class); private static final Log LOG = LogFactory.getLog(AudibleScraper.class);
static int maxLoginAttempts = 2; static int maxLoginAttempts = 1;
final AudibleAccountPrefs account; final AudibleAccountPrefs account;
private final AudibleClient webClient; private final AudibleClient webClient;
public HtmlPage page; public HtmlPage page;
@ -43,11 +43,7 @@ public class AudibleScraper {
public AudibleScraper(AudibleAccountPrefs account) { public AudibleScraper(AudibleAccountPrefs account) {
webClient = new AudibleClient(); webClient = new AudibleClient();
this.account = account; this.account = account;
try {
loadCookies(); loadCookies();
} catch (IOException e) {
e.printStackTrace();
}
} }
public static void deleteCookies() { public static void deleteCookies() {
@ -55,7 +51,6 @@ public class AudibleScraper {
if (cookiesFile.exists()) { if (cookiesFile.exists()) {
cookiesFile.delete(); cookiesFile.delete();
} }
} }
public HtmlPage getPage() { public HtmlPage getPage() {
@ -65,8 +60,7 @@ public class AudibleScraper {
public void setPage(HtmlPage page) { public void setPage(HtmlPage page) {
assert (page != null); assert (page != null);
this.page = page; this.page = page;
LOG.info("pageLoaded:" + page.getUrl() + " " + page.getTitleText()); LOG.info("pageLoaded:'" + page.getTitleText()+"' "+page.getUrl());
} }
public boolean isLoggedIn() { public boolean isLoggedIn() {
@ -92,15 +86,15 @@ public class AudibleScraper {
} else { } else {
if (page != null) { if (page != null) {
String u = page.getUrl().toString(); String u = page.getUrl().toString();
ConnectionNotifier.getInstance().loginFailed(u, page.asXml());
} }
} }
} }
} }
private void loadCookies() throws IOException { private void loadCookies() {
try {
CookieManager cm = getWebClient().getCookieManager(); CookieManager cm = getWebClient().getCookieManager();
File cookiesFile = Directories.META.getDir(cookiesFileName); File cookiesFile = Directories.META.getDir(cookiesFileName);
@ -118,11 +112,14 @@ public class AudibleScraper {
} }
LOG.info("Loaded " + list.size() + " cookies"); LOG.info("Loaded " + list.size() + " cookies");
} }
} catch(Throwable th)
{
LOG.error("error loading cookies...", th);
}
} }
public void logout() { public void logout() {
ConnectionNotifier.getInstance().signout();
try { try {
setURL("/signout", "Signing out"); setURL("/signout", "Signing out");
@ -136,6 +133,7 @@ public class AudibleScraper {
if (cookiesFile.exists()) { if (cookiesFile.exists()) {
cookiesFile.delete(); cookiesFile.delete();
} }
ConnectionNotifier.getInstance().signout();
} }
@ -185,7 +183,15 @@ public class AudibleScraper {
if (getProgress() != null) if (getProgress() != null)
getProgress().setTask("Logging on to audible..."); getProgress().setTask("Logging on to audible...");
HtmlForm login = page.getFormByName("signIn"); HtmlForm login;
try {
login = page.getFormByName("signIn");
}catch(Throwable th)
{
HTMLUtil.debugNode(page, "login");
return false;
}
if (login == null) { if (login == null) {
// TODO: find sign-in anchor and click it.. // TODO: find sign-in anchor and click it..
@ -240,9 +246,12 @@ public class AudibleScraper {
if (!ok) { if (!ok) {
HTMLUtil.debugNode(page, "login failed"); HTMLUtil.debugNode(page, "login failed");
LOG.info(page.getUrl());
LOG.info("Login failed, see html files at:" + HTMLUtil.debugFile("submitting-credentials").getAbsolutePath() + " and " + HTMLUtil.debugFile("login failed").getAbsolutePath()); LOG.info("Login failed, see html files at:" + HTMLUtil.debugFile("submitting-credentials").getAbsolutePath() + " and " + HTMLUtil.debugFile("login failed").getAbsolutePath());
ConnectionNotifier.getInstance().loginFailed(page.getUrl().toString(), page.getTitleText(), page.asXml());
if (attempt < maxLoginAttempts) { if (attempt < maxLoginAttempts) {
login(attempt + 1); login(attempt + 1);
} }
@ -362,6 +371,11 @@ public class AudibleScraper {
setURL(u); setURL(u);
if (!checkLoggedIn()) { if (!checkLoggedIn()) {
String url = page.getUrl().toString();
String title = page.getTitleText();
LOG.info("not logged in after going to:" + u); LOG.info("not logged in after going to:" + u);
// trouble.. try again // trouble.. try again
login(); login();
@ -373,16 +387,19 @@ public class AudibleScraper {
public void lib() throws Exception { public void lib() throws Exception {
String browserURL = ConnectionNotifier.instance.getLastURL(); String browserURL = ConnectionNotifier.instance.getLastURL();
/*
if (browserURL.startsWith(getAudibleBase())) { if (browserURL.startsWith(getAudibleBase())) {
// a bit of a hack.. try to log in using library URL in browser. // a bit of a hack.. try to log in using library URL in browser.
LOG.info("Using library location from browser: " + browserURL); LOG.info("Using library location from browser: " + browserURL);
try { try {
if (setURLAndLogIn(browserURL)) if (setURLAndLogIn(browserURL))
return; return;
} catch (IOException e) { } catch (Throwable e) {
LOG.error(e); LOG.error(e);
} }
} }
*/
if (!setURLAndLogIn("/lib")) if (!setURLAndLogIn("/lib"))
throw new Exception("Unable to access your library. Try logging in with Browser (Cmd-B) to view your library page and try again.. \n\nThere may also be a change in audible's web site that has broken this code."); throw new Exception("Unable to access your library. Try logging in with Browser (Cmd-B) to view your library page and try again.. \n\nThere may also be a change in audible's web site that has broken this code.");

View file

@ -10,5 +10,5 @@ public interface ConnectionListener {
AudibleAccountPrefs getAccountPrefs(AudibleAccountPrefs in); AudibleAccountPrefs getAccountPrefs(AudibleAccountPrefs in);
void loginFailed(String url, String html); void loginFailed(String url, String title, String html);
} }

View file

@ -35,6 +35,9 @@ public class ConnectionNotifier extends EventNotifier<ConnectionListener> implem
} }
public String lastErrorURL = "";
public String lastErrorTitle = "";
public boolean isConnected() { public boolean isConnected() {
return getState() == State.Connected; return getState() == State.Connected;
} }
@ -52,6 +55,7 @@ public class ConnectionNotifier extends EventNotifier<ConnectionListener> implem
public void signout() { public void signout() {
state = State.SignedOut; state = State.SignedOut;
ConnectionNotifier.getInstance().connectionChanged(false);
} }
public State getState() { public State getState() {
@ -78,6 +82,11 @@ public class ConnectionNotifier extends EventNotifier<ConnectionListener> implem
LOG.info("Setting lastURL to:" + lastURL); LOG.info("Setting lastURL to:" + lastURL);
} }
public void pageLoaded(String url, String html)
{
LOG.info("browser loaded:"+url);
}
// not connected is unknown. // not connected is unknown.
// connected means in account // connected means in account
@ -88,11 +97,14 @@ public class ConnectionNotifier extends EventNotifier<ConnectionListener> implem
@Override @Override
public void loginFailed(String url, String html) { public void loginFailed(String url, String title, String xml) {
lastErrorTitle = title;
lastErrorURL = url;
if (state != State.SignedOut) { if (state != State.SignedOut) {
for (ConnectionListener l : getListeners()) { for (ConnectionListener l : getListeners()) {
l.loginFailed(url, html); l.loginFailed(url, title, xml);
} }
} }

View file

@ -1,10 +1,23 @@
package org.openaudible.desktop; package org.openaudible.desktop;
import org.openaudible.desktop.swt.manager.AppLoader; import org.openaudible.desktop.swt.manager.AppLoader;
import org.openaudible.desktop.swt.manager.Version;
import org.openaudible.desktop.swt.util.shop.BuildInstaller;
public class Application { public class Application {
public static void main(String[] args) { public static void main(String[] args) throws Exception {
if (args.length==1 && "--version".equals(args[0]))
{
System.out.println(Version.appVersion);
return;
}
if (args.length>0 && "--install".equals(args[0]))
{
BuildInstaller.main(args);
}
AppLoader.main(args); AppLoader.main(args);
} }
} }

View file

@ -139,76 +139,6 @@ public class AudibleGUI implements BookListener, ConnectionListener {
return in; return in;
} }
/*
public void fetchDecryptionKeyOld() {
try {
if (!audible.getAccount().audibleKey.isEmpty())
throw new Exception("Audible key already set.");
String key = audible.getScraper(true).fetchDecrpytionKey();
audible.getAccount().audibleKey = key;
audible.save();
} catch (Throwable th) {
LOG.info("Error getting key.", th);
MessageBoxFactory.showError(null, "Unable to get Key\nError:" + th);
}
}
public void fetchDecryptionKey() {
try {
File aax = null;
for (Book b:getSelected())
{
}
if (!audible.getAccount().audibleKey.isEmpty())
throw new Exception("Audible key already set.");
String key = audible.getScraper(true).fetchDecrpytionKey();
audible.getAccount().audibleKey = key;
audible.save();
} catch (Throwable th) {
LOG.info("Error getting key.", th);
MessageBoxFactory.showError(null, "Unable to get Key\nError:" + th);
}
}
public String lookupKey(final File aaxFile) {
class LookupTask extends ProgressTask {
LookupTask() {
super("Look up encrpytion key...");
}
String result = null;
String err = null;
public void run() {
try {
result = LookupKey.instance.getKeyFromAAX(aaxFile, this);
} catch (Exception e) {
err = e.getMessage();
}
}
}
;
LookupTask task = new LookupTask();
ProgressDialog.doProgressTask(task);
if (task.err != null) {
MessageBoxFactory.showError(null, "Unable to get Key\nError:" + task.err);
return null;
} else {
return task.result;
}
}
*/
public int selectedAAXCount() { public int selectedAAXCount() {
int count = 0; int count = 0;
for (Book b : getSelected()) { for (Book b : getSelected()) {
@ -263,8 +193,8 @@ public class AudibleGUI implements BookListener, ConnectionListener {
LOG.info("Error connecting", e); LOG.info("Error connecting", e);
if (!wasCanceled()) // if (!wasCanceled()) showError(e, "Error connecting. Last page was "+ConnectionNotifier.getInstance().lastErrorURL);
showError(e, "refreshing book information");
} finally { } finally {
audible.setProgress(null); audible.setProgress(null);
if (scraper != null) { if (scraper != null) {
@ -860,11 +790,15 @@ public class AudibleGUI implements BookListener, ConnectionListener {
public boolean logout() { public boolean logout() {
SWTAsync.assertGUI(); SWTAsync.assertGUI();
if (browser != null && !browser.isDisposed()) { if (browser != null && !browser.isDisposed() && userPass!=null) {
try {
String url = userPass.audibleRegion.getBaseURL() + "/signout"; String url = userPass.audibleRegion.getBaseURL() + "/signout";
browser.setUrl(url); browser.setUrl(url);
browser.close(); browser.close();
}catch(Throwable th)
{
LOG.error("ignoring log out error", th);
}
} }
@ -1151,12 +1085,13 @@ public class AudibleGUI implements BookListener, ConnectionListener {
} }
@Override @Override
public void loginFailed(String url, String html) { public void loginFailed(String url, String title, String html) {
SWTAsync.slow(new SWTAsync("Need to open browser...") { SWTAsync.slow(new SWTAsync("Need to open browser...") {
public void task() { public void task() {
String message = "Unable to automatically log in... \n\nPlease use the OpenAudible web browser to log onto your audible account and navigate to your library (list of books) and try to connect again." + String message = "Unable to automatically log in... \n\nLast Page:"+title+"\nPlease use the OpenAudible web browser to log onto your audible account and navigate to your library (list of books) and try to connect again." +
"\n\nOpen OpenAudible Browser Now?"; "\n\nOpen OpenAudible Browser Now?\n"+url;
boolean ok = MessageBoxFactory.showGeneralYesNo(null, "Log in to your audible account", message); boolean ok = MessageBoxFactory.showGeneralYesNo(null, "Log in to your audible account", message);
if (ok) if (ok)
browse(url); browse(url);

View file

@ -7,5 +7,6 @@ public interface Version {
boolean appDebug = false; boolean appDebug = false;
String appLink = "http://openaudible.org"; String appLink = "http://openaudible.org";
String versionLink = "http://openaudible.org/swt_version.json"; String versionLink = "http://openaudible.org/swt_version.json";
String news = "test news here\nok!"; // latest features go here.
} }

View file

@ -33,7 +33,7 @@ public class AppMenu implements ITranslatable, SelectionListener {
private final Command[] actionCommands = {Command.ViewInAudible, Command.Show_MP3, Command.Play, Command.Download, private final Command[] actionCommands = {Command.ViewInAudible, Command.Show_MP3, Command.Play, Command.Download,
Command.Convert, Command.Refresh_Book_Info, Command.Ignore_Book}; Command.Convert, Command.Refresh_Book_Info, Command.Ignore_Book};
private final Command[] controlCommands = {Command.Connect, Command.Quick_Refresh, Command.Rescan_Library, Command.Download_All, Command.Convert_All, private final Command[] controlCommands = {Command.Connect, Command.Quick_Refresh, Command.Rescan_Library, Command.Download_All, Command.Convert_All,
Command.MenuSeparator, Command.Browser, Command.Logout}; // , Command.MenuSeparator, Command.Logout}; Command.MenuSeparator, Command.Browser, Command.Logout_and_Clear_Cookies}; // , Command.MenuSeparator, Command.Logout_and_Clear_Cookies};
private final Command[] aboutCommands = {Command.Help, Command.AppWebPage, Command.Check_For_Update, Command.About}; private final Command[] aboutCommands = {Command.Help, Command.AppWebPage, Command.Check_For_Update, Command.About};

View file

@ -29,7 +29,7 @@ public enum Command {
Browser, Browser,
Check_For_Update, Check_For_Update,
AppWebPage, AppWebPage,
Logout, Logout_and_Clear_Cookies,
Test1, Test1,
MenuSeparator, MenuSeparator,
Ignore_Book; Ignore_Book;
@ -90,7 +90,7 @@ public enum Command {
case Browser: case Browser:
cmd = 'B'; cmd = 'B';
break; break;
case Logout: case Logout_and_Clear_Cookies:
case Console: case Console:
break; break;
} }

View file

@ -259,7 +259,7 @@ public class CommandCenter {
case Console: case Console:
LogWindow.show(); LogWindow.show();
break; break;
case Logout: case Logout_and_Clear_Cookies:
AudibleGUI.instance.logout(); AudibleGUI.instance.logout();
break; break;
case Ignore_Book: case Ignore_Book:
@ -315,8 +315,8 @@ public class CommandCenter {
return AudibleGUI.instance.canDownloadAll(); return AudibleGUI.instance.canDownloadAll();
case Convert_All: case Convert_All:
return AudibleGUI.instance.canConvertAll(); return AudibleGUI.instance.canConvertAll();
case Logout: case Logout_and_Clear_Cookies:
return ConnectionNotifier.getInstance().isConnected(); return true; // ConnectionNotifier.getInstance().isConnected();
case Preferences: case Preferences:
case Quit: case Quit:
case About: case About:

View file

@ -56,6 +56,18 @@ public class AudibleBrowser {
browser = new Browser(parent, style); browser = new Browser(parent, style);
browser.addTitleListener(event -> getShell().setText(event.title)); browser.addTitleListener(event -> getShell().setText(event.title));
browser.addProgressListener( new ProgressAdapter() {
@Override
public void completed( ProgressEvent event ) {
String text = browser.getText();
ConnectionNotifier.instance.pageLoaded(browser.getUrl(), browser.getText());
// here, text will contain the full page source
}
} );
Object t = browser.getWebBrowser(); Object t = browser.getWebBrowser();
customHeader = new String[1]; customHeader = new String[1];
@ -470,4 +482,8 @@ public class AudibleBrowser {
if (!isDisposed()) browser.close(); if (!isDisposed()) browser.close();
browser = null; browser = null;
} }
} }

View file

@ -201,7 +201,7 @@ public class StatusPanel extends GridComposite implements BookListener, Connecti
} }
@Override @Override
public void loginFailed(String url, String html) { public void loginFailed(String url, String title, String html) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }

View file

@ -0,0 +1,164 @@
package org.openaudible.desktop.swt.util.shop;
import org.apache.commons.io.FileUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.openaudible.desktop.swt.manager.Version;
import org.openaudible.util.EventTimer;
import org.openaudible.util.SimpleProcess;
import org.openaudible.util.Util;
import java.io.File;
import java.util.ArrayList;
public class BuildInstaller {
public static void main(String[] args) throws Exception {
JSONObject json = build();
}
public static JSONObject build() throws Exception {
EventTimer evt=new EventTimer();
File d = new File(".." + File.separator + "install4j");
if (!d.isDirectory())
d = new File("install4j");
if (!d.isDirectory()) throw new Exception("Expected install4j dir:" + d.getAbsolutePath());
File installDir = new File(d, "installers");
if (!installDir.isDirectory())
throw new Exception("Expected dir:" + d.getAbsolutePath());
boolean ok;
for (File f : installDir.listFiles()) {
ok = f.delete();
if (!ok) throw new Exception("Unable to delete installer file: " + f.getAbsolutePath());
}
if (installDir.list().length != 0) {
throw new Exception("expected empty dir:" + installDir.list());
}
FileUtils.writeByteArrayToFile(new File(installDir, "version.txt"), Version.appVersion.getBytes());
ArrayList<String> cmd = new ArrayList<>();
cmd.add("install4jc");
cmd.add("-v");
cmd.add("-r");
cmd.add(Version.appVersion);
File f = new File(d, "openaudible.install4j");
if (!f.exists())
throw new Exception("File not found: " + f.getAbsolutePath());
cmd.add(f.getAbsolutePath());
SimpleProcess simpleProcess = new SimpleProcess(cmd);
SimpleProcess.Results r = simpleProcess.getResults();
if (false)
System.out.println(r.getOutputString());
System.err.println(r.getErrorString());
if (installDir.list().length == 0)
throw new Exception("Expected installers:");
String md5text = FileUtils.readFileToString(new File(installDir, "md5sums"), "utf-8");
System.out.println(md5text);
md5text = md5text.replace("*", "");
JSONObject json = new JSONObject();
json.put("version", Version.appVersion);
// JSONArray platforms = new JSONArray();
JSONObject platforms = new JSONObject();
String downloadDir = "https://github.com/openaudible/openaudible/releases/download/v" + Version.appVersion + "/";
for (String line : md5text.split("\n")) {
String md5 = line.split(" ")[0].trim();
String fn = line.split(" ")[1].trim();
// if (fn.startsWith("*")) fn = fn.substring(1);
fn = fn.trim();
System.out.println(line);
System.out.println(fn + "=" + md5);
File installerFile = new File(installDir, fn);
if (!installerFile.exists())
throw new Exception("Expected file:" + fn + " at " + installerFile.getAbsolutePath());
String kind = "";
String ext = fn.substring(fn.lastIndexOf("."));
String kind2 = "";
switch (ext) {
case ".sh":
kind = "liunx";
kind2 ="Linux GTK";
break;
case ".exe":
kind = "win";
kind2 ="Windows 64x";
break;
case ".dmg":
kind = "mac";
kind2 ="Mac OS X";
break;
default:
throw new Exception("invalid ext:"+fn);
}
String newName = "OpenAudible_"+kind+"_"+Version.appVersion+ext;
File newFile = new File(installDir, newName);
ok = installerFile.renameTo(newFile);
if (!ok) throw new Exception("rename failed");
installerFile = newFile;
JSONObject platform = new JSONObject();
platform.put("file", newName);
platform.put("md5", md5);
platform.put("url", downloadDir+newName);
platform.put("size", installerFile.length());
platform.put("mb", Util.instance.byteCountToString(installerFile.length())+"b");
platform.put("version", Version.appVersion);
platform.put("platform", kind2);
platforms.put(kind, platform);
}
json.put("platforms", platforms);
json.put("download_dir", downloadDir);
json.put("old_news", Version.news);
json.put("pre_release_news", ""); // normally blank
json.put("current_news", ""); // normally blank
System.err.println(evt.toString());
System.out.println(json.toString(2));
File jsonFile = new File(installDir, "swt_version.json");
new File(installDir, "output.txt").delete();
FileUtils.writeByteArrayToFile(jsonFile, json.toString(1).getBytes());
return json;
}
public static JSONObject newReleaseJSON()
{
JSONObject json = new JSONObject();
json.put("tag_name", "v"+Version.appVersion);
json.put("name", "v"+Version.appVersion);
json.put("target_commitish", "master");
json.put("body", "OpenAudible release version "+Version.appVersion+".");
json.put("draft", false);
json.put("prerelease", false);
return json;
}
// POST https://<upload_url>/repos/:owner/:repo/releases/:release_id/assets?name=foo.zip
public JSONObject addAssetJSON(File f, String contentType)
{
JSONObject json = new JSONObject();
return json;
}
}

View file

@ -6,7 +6,6 @@ import java.io.*;
public class CopyWithProgress { public class CopyWithProgress {
final static int bufSize = 64 * 1024; final static int bufSize = 64 * 1024;
public static String byteCountToString(long l) { public static String byteCountToString(long l) {
long k = l / 1024; long k = l / 1024;
long m = l / (1024 * 1024); long m = l / (1024 * 1024);
@ -29,6 +28,7 @@ public class CopyWithProgress {
return "" + k + "K"; return "" + k + "K";
} }
public static long copyWithProgress(final IProgressTask p, final File in, final File out) throws IOException { public static long copyWithProgress(final IProgressTask p, final File in, final File out) throws IOException {
final String totalBytes = byteCountToString(in.length()); final String totalBytes = byteCountToString(in.length());