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.*;
// audible.com web page scraper
// Not thread safe, run single instance at a time.
// a singleton class..
public class AudibleScraper {
final static String cookiesFileName = "cookies.json";
private static final Log LOG = LogFactory.getLog(AudibleScraper.class);
static int maxLoginAttempts = 2;
static int maxLoginAttempts = 1;
final AudibleAccountPrefs account;
private final AudibleClient webClient;
public HtmlPage page;
@ -38,16 +38,12 @@ public class AudibleScraper {
boolean loggedIn = false;
String clickToDownload = "Click to download ";
private IProgressTask progress;
public AudibleScraper(AudibleAccountPrefs account) {
webClient = new AudibleClient();
this.account = account;
try {
loadCookies();
} catch (IOException e) {
e.printStackTrace();
}
loadCookies();
}
public static void deleteCookies() {
@ -55,7 +51,6 @@ public class AudibleScraper {
if (cookiesFile.exists()) {
cookiesFile.delete();
}
}
public HtmlPage getPage() {
@ -65,8 +60,7 @@ public class AudibleScraper {
public void setPage(HtmlPage page) {
assert (page != null);
this.page = page;
LOG.info("pageLoaded:" + page.getUrl() + " " + page.getTitleText());
LOG.info("pageLoaded:'" + page.getTitleText()+"' "+page.getUrl());
}
public boolean isLoggedIn() {
@ -92,37 +86,40 @@ public class AudibleScraper {
} else {
if (page != null) {
String u = page.getUrl().toString();
ConnectionNotifier.getInstance().loginFailed(u, page.asXml());
}
}
}
}
private void loadCookies() throws IOException {
CookieManager cm = getWebClient().getCookieManager();
File cookiesFile = Directories.META.getDir(cookiesFileName);
if (cookiesFile.exists()) {
String content = HTMLUtil.readFile(cookiesFile);
List<BasicClientCookie> list = new Gson().fromJson(content, new TypeToken<List<BasicClientCookie>>() {
}.getType());
for (BasicClientCookie bc : list) {
Cookie c = new Cookie(bc.getDomain(), bc.getName(), bc.getValue());
cm.addCookie(c);
// LOG.info("Cookie: "+c);
private void loadCookies() {
try {
CookieManager cm = getWebClient().getCookieManager();
File cookiesFile = Directories.META.getDir(cookiesFileName);
if (cookiesFile.exists()) {
String content = HTMLUtil.readFile(cookiesFile);
List<BasicClientCookie> list = new Gson().fromJson(content, new TypeToken<List<BasicClientCookie>>() {
}.getType());
for (BasicClientCookie bc : list) {
Cookie c = new Cookie(bc.getDomain(), bc.getName(), bc.getValue());
cm.addCookie(c);
// LOG.info("Cookie: "+c);
}
LOG.info("Loaded " + list.size() + " cookies");
}
LOG.info("Loaded " + list.size() + " cookies");
} catch(Throwable th)
{
LOG.error("error loading cookies...", th);
}
}
public void logout() {
ConnectionNotifier.getInstance().signout();
try {
setURL("/signout", "Signing out");
@ -136,6 +133,7 @@ public class AudibleScraper {
if (cookiesFile.exists()) {
cookiesFile.delete();
}
ConnectionNotifier.getInstance().signout();
}
@ -167,7 +165,7 @@ public class AudibleScraper {
}
protected boolean login(int attempt) throws IOException {
AudibleAccountPrefs copy = account;
if (account.audibleUser.length() == 0 || account.audiblePassword.length() == 0) {
@ -184,8 +182,16 @@ public class AudibleScraper {
if (getProgress() != null)
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) {
// TODO: find sign-in anchor and click it..
@ -240,9 +246,12 @@ public class AudibleScraper {
if (!ok) {
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());
ConnectionNotifier.getInstance().loginFailed(page.getUrl().toString(), page.getTitleText(), page.asXml());
if (attempt < maxLoginAttempts) {
login(attempt + 1);
}
@ -362,6 +371,11 @@ public class AudibleScraper {
setURL(u);
if (!checkLoggedIn()) {
String url = page.getUrl().toString();
String title = page.getTitleText();
LOG.info("not logged in after going to:" + u);
// trouble.. try again
login();
@ -373,17 +387,20 @@ public class AudibleScraper {
public void lib() throws Exception {
String browserURL = ConnectionNotifier.instance.getLastURL();
/*
if (browserURL.startsWith(getAudibleBase())) {
// a bit of a hack.. try to log in using library URL in browser.
LOG.info("Using library location from browser: " + browserURL);
try {
if (setURLAndLogIn(browserURL))
return;
} catch (IOException e) {
} catch (Throwable e) {
LOG.error(e);
}
}
*/
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.");

View file

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

View file

@ -34,7 +34,10 @@ public class ConnectionNotifier extends EventNotifier<ConnectionListener> implem
}
}
public String lastErrorURL = "";
public String lastErrorTitle = "";
public boolean isConnected() {
return getState() == State.Connected;
}
@ -52,6 +55,7 @@ public class ConnectionNotifier extends EventNotifier<ConnectionListener> implem
public void signout() {
state = State.SignedOut;
ConnectionNotifier.getInstance().connectionChanged(false);
}
public State getState() {
@ -77,8 +81,13 @@ public class ConnectionNotifier extends EventNotifier<ConnectionListener> implem
}
LOG.info("Setting lastURL to:" + lastURL);
}
public void pageLoaded(String url, String html)
{
LOG.info("browser loaded:"+url);
}
// not connected is unknown.
// connected means in account
// disconnected means a password is being asked for.
@ -88,11 +97,14 @@ public class ConnectionNotifier extends EventNotifier<ConnectionListener> implem
@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) {
for (ConnectionListener l : getListeners()) {
l.loginFailed(url, html);
l.loginFailed(url, title, xml);
}
}

View file

@ -1,10 +1,23 @@
package org.openaudible.desktop;
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 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);
}
}

View file

@ -139,76 +139,6 @@ public class AudibleGUI implements BookListener, ConnectionListener {
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() {
int count = 0;
for (Book b : getSelected()) {
@ -263,8 +193,8 @@ public class AudibleGUI implements BookListener, ConnectionListener {
LOG.info("Error connecting", e);
if (!wasCanceled())
showError(e, "refreshing book information");
// if (!wasCanceled()) showError(e, "Error connecting. Last page was "+ConnectionNotifier.getInstance().lastErrorURL);
} finally {
audible.setProgress(null);
if (scraper != null) {
@ -860,11 +790,15 @@ public class AudibleGUI implements BookListener, ConnectionListener {
public boolean logout() {
SWTAsync.assertGUI();
if (browser != null && !browser.isDisposed()) {
String url = userPass.audibleRegion.getBaseURL() + "/signout";
browser.setUrl(url);
browser.close();
if (browser != null && !browser.isDisposed() && userPass!=null) {
try {
String url = userPass.audibleRegion.getBaseURL() + "/signout";
browser.setUrl(url);
browser.close();
}catch(Throwable th)
{
LOG.error("ignoring log out error", th);
}
}
@ -1151,12 +1085,13 @@ public class AudibleGUI implements BookListener, ConnectionListener {
}
@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...") {
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." +
"\n\nOpen OpenAudible Browser Now?";
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"+url;
boolean ok = MessageBoxFactory.showGeneralYesNo(null, "Log in to your audible account", message);
if (ok)
browse(url);

View file

@ -7,5 +7,6 @@ public interface Version {
boolean appDebug = false;
String appLink = "http://openaudible.org";
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,
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,
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};

View file

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

View file

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

View file

@ -56,6 +56,18 @@ public class AudibleBrowser {
browser = new Browser(parent, style);
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();
customHeader = new String[1];
@ -470,4 +482,8 @@ public class AudibleBrowser {
if (!isDisposed()) browser.close();
browser = null;
}
}

View file

@ -201,7 +201,7 @@ public class StatusPanel extends GridComposite implements BookListener, Connecti
}
@Override
public void loginFailed(String url, String html) {
public void loginFailed(String url, String title, String html) {
// 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 {
final static int bufSize = 64 * 1024;
public static String byteCountToString(long l) {
long k = l / 1024;
long m = l / (1024 * 1024);
@ -29,6 +28,7 @@ public class CopyWithProgress {
return "" + k + "K";
}
public static long copyWithProgress(final IProgressTask p, final File in, final File out) throws IOException {
final String totalBytes = byteCountToString(in.length());

View file

@ -27,5 +27,5 @@ public abstract class EventNotifier<T> {
protected Object getLock() {
return listeners;
}
}