Compare commits

...

9 Commits

Author SHA1 Message Date
Robert McRackan
b1f92343cf increm version 2020-09-10 09:07:04 -04:00
Robert McRackan
9e1d657f60 Config setting to retain aax file after decrypt 2020-09-10 09:06:34 -04:00
Robert McRackan
389761355d New version. Failed attempt to fix publish error 2020-09-07 15:45:08 -04:00
Robert McRackan
69054afaa0 update version # 2020-09-01 09:54:55 -04:00
Robert McRackan
aacdcea1e1 Merge branch 'master' of https://github.com/rmcrackan/Libation 2020-09-01 09:35:38 -04:00
Robert McRackan
0beb3bf437 Add logging 2020-09-01 09:35:13 -04:00
rmcrackan
e925b57f7f Update README.md 2020-08-31 23:03:28 -04:00
rmcrackan
5deaa06d78 Update README.md 2020-08-31 22:57:47 -04:00
Robert McRackan
eda62975ba Screenshots 2020-08-31 22:57:27 -04:00
10 changed files with 89 additions and 12 deletions

View File

@@ -62,9 +62,21 @@ namespace FileLiberator
if (outputAudioFilename == null)
return new StatusHandler { "Decrypt failed" };
moveFilesToBooksDir(libraryBook.Book, outputAudioFilename);
var destinationDir = moveFilesToBooksDir(libraryBook.Book, outputAudioFilename);
Dinah.Core.IO.FileExt.SafeDelete(aaxFilename);
var config = Configuration.Instance;
if (config.RetainAaxFiles)
{
var newAaxFilename = FileUtility.GetValidFilename(
destinationDir,
Path.GetFileNameWithoutExtension(aaxFilename),
"aax");
File.Move(aaxFilename, newAaxFilename);
}
else
{
Dinah.Core.IO.FileExt.SafeDelete(aaxFilename);
}
var statusHandler = new StatusHandler();
var finalAudioExists = AudibleFileStorage.Audio.Exists(libraryBook.Book.AudibleProductId);
@@ -120,7 +132,7 @@ namespace FileLiberator
}
}
private static void moveFilesToBooksDir(Book product, string outputAudioFilename)
private static string moveFilesToBooksDir(Book product, string outputAudioFilename)
{
// create final directory. move each file into it. MOVE AUDIO FILE LAST
// new dir: safetitle_limit50char + " [" + productId + "]"
@@ -142,7 +154,9 @@ namespace FileLiberator
File.Move(f.FullName, dest);
}
}
return destinationDir;
}
private static string getDestDir(Book product)
{

View File

@@ -83,6 +83,13 @@ namespace FileManager
set => persistentDictionary.Set(nameof(DecryptInProgressEnum), value);
}
[Description("Retain .aax files after decrypting?")]
public bool RetainAaxFiles
{
get => persistentDictionary.Get<bool>(nameof(RetainAaxFiles));
set => persistentDictionary.Set(nameof(RetainAaxFiles), value);
}
// note: any potential file manager static ctors can't compensate if storage dir is changed at run time via settings. this is partly bad architecture. but the side effect is desirable. if changing LibationFiles location: restart app
// singleton stuff

View File

@@ -40,8 +40,13 @@ namespace FileManager
return stringCache[propertyName];
}
public T Get<T>(string propertyName) where T : class
=> GetObject(propertyName) is T obj ? obj : default;
public T Get<T>(string propertyName)
{
var o = GetObject(propertyName);
if (o is null) return default;
if (o is JToken jt) return jt.Value<T>();
return (T)o;
}
public object GetObject(string propertyName)
{

View File

@@ -13,19 +13,33 @@ namespace InternalUtilities
{
/// <summary>USE THIS from within Libation. It wraps the call with correct JSONPath</summary>
public static Task<Api> GetApiAsync(string username, string localeName, ILoginCallback loginCallback = null)
=> EzApiCreator.GetApiAsync(
{
Serilog.Log.Logger.Information("GetApiAsync. {@DebugInfo}", new
{
username,
LocaleName = localeName,
});
return EzApiCreator.GetApiAsync(
Localization.Get(localeName),
AudibleApiStorage.AccountsSettingsFile,
AudibleApiStorage.GetIdentityTokensJsonPath(username, localeName),
loginCallback);
}
/// <summary>USE THIS from within Libation. It wraps the call with correct JSONPath</summary>
public static Task<Api> GetApiAsync(ILoginCallback loginCallback, Account account)
=> EzApiCreator.GetApiAsync(
{
Serilog.Log.Logger.Information("GetApiAsync. {@DebugInfo}", new
{
AccountId = account?.AccountId ?? "[empty]",
LocaleName = account?.Locale?.Name
});
return EzApiCreator.GetApiAsync(
account.Locale,
AudibleApiStorage.AccountsSettingsFile,
account.GetIdentityTokensJsonPath(),
loginCallback);
}
private static AsyncRetryPolicy policy { get; }
= Policy.Handle<Exception>()

View File

@@ -13,7 +13,7 @@
<!-- <PublishSingleFile>true</PublishSingleFile> -->
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<Version>4.0.0.1</Version>
<Version>4.0.3.1</Version>
</PropertyGroup>
<ItemGroup>

View File

@@ -27,7 +27,8 @@ namespace LibationLauncher
AudibleApiStorage.EnsureAccountsSettingsFileExists();
migrate_v3_to_v4();
migrate_to_v4_0_0();
migrate_to_v4_0_3(); // add setting for whether to delete/retain aax
ensureLoggingConfig();
ensureSerilogConfig();
@@ -83,7 +84,7 @@ namespace LibationLauncher
#region v3 => v4 migration
static string AccountsSettingsFileLegacy30 => Path.Combine(Configuration.Instance.LibationFiles, "IdentityTokens.json");
private static void migrate_v3_to_v4()
private static void migrate_to_v4_0_0()
{
migrateLegacyIdentityFile();
@@ -205,6 +206,27 @@ namespace LibationLauncher
}
#endregion
#region migrate_to_v4_0_3 add setting for whether to delete/retain aax
private static void migrate_to_v4_0_3()
{
if (!File.Exists(Configuration.Instance.SettingsFilePath))
return;
// use JObject to remove decrypt key and locale from Settings.json
var settingsContents = File.ReadAllText(Configuration.Instance.SettingsFilePath);
var jObj = JObject.Parse(settingsContents);
var jRetainAaxFiles = jObj.Property("RetainAaxFiles");
if (jRetainAaxFiles is null)
{
jObj.Add("RetainAaxFiles", false);
var newContents = jObj.ToString(Formatting.Indented);
File.WriteAllText(Configuration.Instance.SettingsFilePath, newContents);
}
}
#endregion
private static string defaultLoggingLevel { get; } = "Information";
private static void ensureLoggingConfig()
{

View File

@@ -1,6 +1,6 @@
# Libation: Liberate your Library
## [Download Libation](https://github.com/rmcrackan/Libation/releases)
## [Download Libation](https://github.com/rmcrackan/Libation/releases/latest)
# Table of Contents
@@ -9,6 +9,7 @@
- [The bad](#the-bad)
- [The ugly](#the-ugly)
2. [Getting started](#getting-started)
- [Create Accounts](#create-accounts)
- [Import your library](#import-your-library)
- [Download your books -- DRM-free!](#download-your-books----drm-free)
- [Download PDF attachments](#download-pdf-attachments)
@@ -57,12 +58,26 @@ I made this for myself and I want to share it with the great programming and aud
#### [Download Libation](https://github.com/rmcrackan/Libation/releases)
### Create Accounts
Create your account(s):
![Create your accounts, menu](images/v40_accounts.png)
New locale options include many more regions including old audible accounts which pre-date the amazon acquisition
![Choose your account locales](images/v40_locales.png)
### Import your library
Select Import > Scan Library:
![Import step 1](images/Import1.png)
Or if you have multiple accounts, you'll get to choose whether to scan all accounts or just the ones you select:
![Import which accounts](images/v40_import.png)
You'll see this window while it's scanning:
![Import step 2](images/Import2.png)

BIN
images/v40_accounts.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
images/v40_import.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
images/v40_locales.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB