Integrate audible API draft 1. incomplete

This commit is contained in:
Robert McRackan 2019-10-21 16:27:28 -04:00
parent 37708bece1
commit cecbea1e9f
30 changed files with 1313 additions and 226 deletions

View File

@ -5,7 +5,9 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Dinah.Core\Dinah.Core\Dinah.Core.csproj" /> <ProjectReference Include="..\..\audible api\AudibleApi\AudibleApi\AudibleApi.csproj" />
<ProjectReference Include="..\FileManager\FileManager.csproj" />
<ProjectReference Include="..\ScrapingDomainServices\ScrapingDomainServices.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,19 +1,122 @@
using System; using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using AudibleApi;
using AudibleApi.Authentication;
using AudibleApi.Authorization;
using Newtonsoft.Json.Linq;
namespace AudibleApiDomainService namespace AudibleApiDomainService
{ {
public class AudibleApiLibationClient public class AudibleApiLibationClient
{ {
private Settings settings; private Api _api;
public AudibleApiLibationClient(Settings settings)
=> this.settings = settings ?? throw new ArgumentNullException(nameof(settings)); #region initialize api
private AudibleApiLibationClient() { }
public async static Task<AudibleApiLibationClient> CreateClientAsync(Settings settings, IAudibleApiResponder responder)
{
Localization.SetLocale(settings.LocaleCountryCode);
Api api;
try
{
api = await EzApiCreator.GetApiAsync(settings.IdentityFilePath);
}
catch
{
var inMemoryIdentity = await loginAsync(responder);
api = await EzApiCreator.GetApiAsync(settings.IdentityFilePath, inMemoryIdentity);
}
return new AudibleApiLibationClient { _api = api };
}
// LOGIN PATTERN
// - Start with Authenticate. Submit email + pw
// - Each step in the login process will return a LoginResult
// - Each result which has required user input has a SubmitAsync method
// - The final LoginComplete result returns "Identity" -- in-memory authorization items
private static async Task<IIdentity> loginAsync(IAudibleApiResponder responder)
{
var login = new Authenticate();
var (email, password) = responder.GetLogin();
var loginResult = await login.SubmitCredentialsAsync(email, password);
while (true)
{
switch (loginResult)
{
case CredentialsPage credentialsPage:
var (emailInput, pwInput) = responder.GetLogin();
loginResult = await credentialsPage.SubmitAsync(emailInput, pwInput);
break;
case CaptchaPage captchaResult:
var imageBytes = await downloadImageAsync(captchaResult.CaptchaImage);
var guess = responder.GetCaptchaAnswer(imageBytes);
loginResult = await captchaResult.SubmitAsync(guess);
break;
case TwoFactorAuthenticationPage _2fa:
var _2faCode = responder.Get2faCode();
loginResult = await _2fa.SubmitAsync(_2faCode);
break;
case LoginComplete final:
return final.Identity;
default:
throw new Exception("Unknown LoginResult");
}
}
}
private static async Task<byte[]> downloadImageAsync(Uri imageUri)
{
using var client = new HttpClient();
using var contentStream = await client.GetStreamAsync(imageUri);
using var localStream = new MemoryStream();
await contentStream.CopyToAsync(localStream);
return localStream.ToArray();
}
#endregion
public async Task<JObject> TestGetLibraryAsync()
{
var x = await _api.GetLibraryAsync();
return x;
}
//public async Task DownloadBookAsync(string asinToDownload)
//{
// // console example
// using var progressBar = new Dinah.Core.ConsoleLib.ProgressBar();
// var progress = new Progress<Dinah.Core.Net.Http.DownloadProgress>();
// progress.ProgressChanged += (_, e) => progressBar.Report(Math.Round((double)(100 * e.BytesReceived) / e.TotalFileSize.Value) / 100);
// logger.WriteLine("Download book");
// var finalFile = await _api.DownloadAaxWorkaroundAsync(asinToDownload, "downloadExample.xyz", progress);
// logger.WriteLine(" Done!");
// logger.WriteLine("final file: " + Path.GetFullPath(finalFile));
// // benefit of this small delay:
// // - if you try to delete a file too soon after it's created, the OS isn't done with the creation and you can get an unexpected error
// // - give progressBar's internal timer time to finish. if timer is disposed before the final message is processed, "100%" will never get a chance to be displayed
// await Task.Delay(100);
// File.Delete(finalFile);
//}
public async Task ImportLibraryAsync() public async Task ImportLibraryAsync()
{ {
// call api // json = api.GetLibrary
// translate to DTOs // json => DTOs
// update database // indexer.update(DTOs)
} }
} }
} }

View File

@ -1,205 +0,0 @@
//using System;
//using System.IO;
//using System.Net.Http;
//using System.Threading.Tasks;
//using AudibleApi;
//using AudibleApi.Authentication;
//using AudibleApi.Authorization;
//using Dinah.Core.Net.Http;
//using Newtonsoft.Json;
//namespace AudibleApiDomainService
//{
// public class AudibleApiClient
// {
// #region initialize api
// public const string APP_SETTINGS = "appsettings.json";
// private Api _api;
// private static ClientSettings settings;
// private AudibleApiClient() { }
// public async static Task<AudibleApiClient> CreateClientAsync()
// {
// settings = ClientSettings.FromFile(APP_SETTINGS);
// restoreLocale();
// Api api;
// try
// {
// api = await EzApiCreator.GetApiAsync(settings.IdentityFilePath);
// }
// catch
// {
// var inMemoryIdentity = await loginAsync(email, password);
// api = await EzApiCreator.GetApiAsync(settings.IdentityFilePath, inMemoryIdentity);
// }
// return new AudibleApiClient { _api = api };
// }
// private static void restoreLocale()
// {
// if (settings.LocaleCountryCode != null)
// Localization.SetLocale(settings.LocaleCountryCode);
// }
// // LOGIN PATTERN
// // - Start with Authenticate. Submit email + pw
// // - Each step in the login process will return a LoginResult
// // - Each result which has required user input has a SubmitAsync method
// // - The final LoginComplete result returns "Identity" -- in-memory authorization items
// private static async Task<IIdentity> loginAsync(string email, string pw)
// {
// var login = new Authenticate();
// var loginResult = await login.SubmitCredentialsAsync(email, pw);
// while (true)
// {
// switch (loginResult)
// {
// case CredentialsPage credentialsPage:
// Console.WriteLine("Email:");
// var emailInput = Console.ReadLine();
// Console.WriteLine("Password:");
// var pwInput = Dinah.Core.ConsoleLib.ConsoleExt.ReadPassword();
// loginResult = await credentialsPage.SubmitAsync(emailInput, pwInput);
// break;
// case CaptchaPage captchaResult:
// var imageBytes = await downloadImageAsync(captchaResult.CaptchaImage);
// var guess = getUserCaptchaGuess(imageBytes);
// loginResult = await captchaResult.SubmitAsync(guess);
// break;
// case TwoFactorAuthenticationPage _2fa:
// Console.WriteLine("Two-Step Verification code:");
// var _2faCode = Console.ReadLine();
// loginResult = await _2fa.SubmitAsync(_2faCode);
// break;
// case LoginComplete final:
// return final.Identity;
// default:
// throw new Exception("Unknown LoginResult");
// }
// }
// }
// private static async Task<byte[]> downloadImageAsync(Uri imageUri)
// {
// using var client = new HttpClient();
// using var contentStream = await client.GetStreamAsync(imageUri);
// using var localStream = new MemoryStream();
// await contentStream.CopyToAsync(localStream);
// return localStream.ToArray();
// }
// private static string getUserCaptchaGuess(byte[] captchaImage)
// {
// var tempFileName = Path.Combine(Path.GetTempPath(), "audible_api_captcha_" + Guid.NewGuid() + ".jpg");
// try
// {
// File.WriteAllBytes(tempFileName, captchaImage);
// var processStartInfo = new System.Diagnostics.ProcessStartInfo
// {
// Verb = string.Empty,
// UseShellExecute = true,
// CreateNoWindow = true,
// FileName = tempFileName
// };
// System.Diagnostics.Process.Start(processStartInfo);
// Console.WriteLine("CAPTCHA answer: ");
// var guess = Console.ReadLine();
// return guess;
// }
// finally
// {
// if (File.Exists(tempFileName))
// File.Delete(tempFileName);
// }
// }
// #endregion
// #region api call examples
// // Mimi's Adventure (3m)
// public const string TINY_BOOK_ASIN = "B079DZ8YMP";
// // Harry Potter 1 (8h 33m)
// public const string MEDIUM_BOOK_ASIN = "B017V4IM1G";
// // Sherlock Holmes (62h 52m)
// public const string HUGE_BOOK_ASIN = "B06WLMWF2S";
// public Task PrintLibraryAsync() => wrapCallAsync(printLibraryAsync);
// private async Task printLibraryAsync()
// {
// // test ad hoc api calls
// string url;
// string allGroups;
// url
// = "/1.0/library"
// + "?purchaseAfterDate=01/01/1970&page=23";
// url = "/1.0/library/" +
// //TINY_BOOK_ASIN
// MEDIUM_BOOK_ASIN
// //HUGE_BOOK_ASIN
// ;
// url += url.Contains("?") ? "&" : "?";
// //allGroups = "response_groups=badge_types,category_ladders,claim_code_url,contributors,is_downloaded,is_returnable,media,origin_asin,pdf_url,percent_complete,price,product_attrs,product_desc,product_extended_attrs,product_plan_details,product_plans,provided_review,rating,relationships,review_attrs,reviews,sample,series,sku";
// allGroups = "response_groups=series,category_ladders,contributors";
// url += allGroups;
// var responseMsg = await _api.AdHocAuthenticatedGetAsync(url);
// var jObj = await responseMsg.Content.ReadAsJObjectAsync();
// var str = jObj.ToString(Formatting.Indented);
// Console.WriteLine(str);
// }
// public Task DownloadBookAsync() => wrapCallAsync(downloadBookAsync);
// private async Task downloadBookAsync()
// {
// using var progressBar = new Dinah.Core.ConsoleLib.ProgressBar();
// var progress = new Progress<DownloadProgress>();
// progress.ProgressChanged += (_, e) => progressBar.Report(Math.Round((double)(100 * e.BytesReceived) / e.TotalFileSize.Value) / 100);
// Console.Write("Download book");
// var finalFile = await _api.DownloadAaxWorkaroundAsync(TINY_BOOK_ASIN, "downloadExample.xyz", progress);
// Console.WriteLine(" Done!");
// Console.WriteLine("final file: " + Path.GetFullPath(finalFile));
// // benefit of this small delay:
// // - if you try to delete a file too soon after it's created, the OS isn't done with the creation and you can get an unexpected error
// // - give progressBar's internal timer time to finish. if timer is disposed before the final message is processed, "100%" will never get a chance to be displayed
// await Task.Delay(100);
// File.Delete(finalFile);
// }
// private async Task wrapCallAsync(Func<Task> fn)
// {
// try
// {
// await fn();
// }
// catch (AudibleApiException aex)
// {
// Console.WriteLine("ERROR:");
// Console.WriteLine(aex.Message);
// Console.WriteLine(aex.JsonMessage.ToString());
// Console.WriteLine(aex.RequestUri.ToString());
// }
// }
// #endregion
// }
//}

View File

@ -0,0 +1,9 @@
namespace AudibleApiDomainService
{
public interface IAudibleApiResponder
{
(string email, string password) GetLogin();
string GetCaptchaAnswer(byte[] captchaImage);
string Get2faCode();
}
}

View File

@ -1,10 +1,17 @@
namespace AudibleApiDomainService using System.IO;
using FileManager;
namespace AudibleApiDomainService
{ {
public class Settings public class Settings
{ {
// identityTokens.json public string IdentityFilePath { get; }
public string IdentityFilePath { get; set; } public string LocaleCountryCode { get; }
public string LocaleCountryCode { get; set; } public Settings(Configuration config)
{
IdentityFilePath = Path.Combine(config.LibationFiles, "identityTokens.json");
LocaleCountryCode = config.LocaleCountryCode;
}
} }
} }

View File

@ -11,7 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Solution Items", "_Solutio
REFERENCE.txt = REFERENCE.txt REFERENCE.txt = REFERENCE.txt
EndProjectSection EndProjectSection
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3.2 Domain Utilities (post database)", "3.2 Domain Utilities (post database)", "{41CDCC73-9B81-49DD-9570-C54406E852AF}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3.2 Domain Utilities (database aware)", "3.2 Domain Utilities (database aware)", "{41CDCC73-9B81-49DD-9570-C54406E852AF}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "4 Application", "4 Application", "{8679CAC8-9164-4007-BDD2-F004810EDA14}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "4 Application", "4 Application", "{8679CAC8-9164-4007-BDD2-F004810EDA14}"
EndProject EndProject
@ -83,7 +83,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LuceneNet303r2.Tests", "..\
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DTOs", "DTOs\DTOs.csproj", "{5FDA62B1-55FD-407A-BECA-38A969235541}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DTOs", "DTOs\DTOs.csproj", "{5FDA62B1-55FD-407A-BECA-38A969235541}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AudibleApiDomainService", "AudibleApiDomainService\AudibleApiDomainService.csproj", "{A1AB4B4B-6855-4BD0-BC54-C2FFDB20E050}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AudibleApiDomainService", "AudibleApiDomainService\AudibleApiDomainService.csproj", "{A1AB4B4B-6855-4BD0-BC54-C2FFDB20E050}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@ -0,0 +1,113 @@
namespace LibationWinForm.Dialogs.Login
{
partial class AudibleLoginDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.passwordLbl = new System.Windows.Forms.Label();
this.emailLbl = new System.Windows.Forms.Label();
this.passwordTb = new System.Windows.Forms.TextBox();
this.emailTb = new System.Windows.Forms.TextBox();
this.submitBtn = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// passwordLbl
//
this.passwordLbl.AutoSize = true;
this.passwordLbl.Location = new System.Drawing.Point(12, 41);
this.passwordLbl.Name = "passwordLbl";
this.passwordLbl.Size = new System.Drawing.Size(53, 13);
this.passwordLbl.TabIndex = 2;
this.passwordLbl.Text = "Password";
//
// emailLbl
//
this.emailLbl.AutoSize = true;
this.emailLbl.Location = new System.Drawing.Point(12, 15);
this.emailLbl.Name = "emailLbl";
this.emailLbl.Size = new System.Drawing.Size(32, 13);
this.emailLbl.TabIndex = 0;
this.emailLbl.Text = "Email";
//
// passwordTb
//
this.passwordTb.Location = new System.Drawing.Point(71, 38);
this.passwordTb.Name = "passwordTb";
this.passwordTb.PasswordChar = '*';
this.passwordTb.Size = new System.Drawing.Size(200, 20);
this.passwordTb.TabIndex = 3;
//
// emailTb
//
this.emailTb.Location = new System.Drawing.Point(71, 12);
this.emailTb.Name = "emailTb";
this.emailTb.Size = new System.Drawing.Size(200, 20);
this.emailTb.TabIndex = 1;
//
// submitBtn
//
this.submitBtn.Location = new System.Drawing.Point(196, 64);
this.submitBtn.Name = "submitBtn";
this.submitBtn.Size = new System.Drawing.Size(75, 23);
this.submitBtn.TabIndex = 4;
this.submitBtn.Text = "Submit";
this.submitBtn.UseVisualStyleBackColor = true;
this.submitBtn.Click += new System.EventHandler(this.submitBtn_Click);
//
// AudibleLoginDialog
//
this.AcceptButton = this.submitBtn;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(283, 99);
this.Controls.Add(this.submitBtn);
this.Controls.Add(this.passwordLbl);
this.Controls.Add(this.emailLbl);
this.Controls.Add(this.passwordTb);
this.Controls.Add(this.emailTb);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "AudibleLoginDialog";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Audible Login";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label passwordLbl;
private System.Windows.Forms.Label emailLbl;
private System.Windows.Forms.TextBox passwordTb;
private System.Windows.Forms.TextBox emailTb;
private System.Windows.Forms.Button submitBtn;
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Windows.Forms;
namespace LibationWinForm.Dialogs.Login
{
public partial class AudibleLoginDialog : Form
{
public string Email { get; private set; }
public string Password { get; private set; }
public AudibleLoginDialog()
{
InitializeComponent();
}
private void submitBtn_Click(object sender, EventArgs e)
{
Email = this.emailTb.Text;
Password = this.passwordTb.Text;
DialogResult = DialogResult.OK;
}
}
}

View File

@ -0,0 +1,103 @@
namespace LibationWinForm.Dialogs.Login
{
partial class CaptchaDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.captchaPb = new System.Windows.Forms.PictureBox();
this.answerTb = new System.Windows.Forms.TextBox();
this.submitBtn = new System.Windows.Forms.Button();
this.answerLbl = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.captchaPb)).BeginInit();
this.SuspendLayout();
//
// captchaPb
//
this.captchaPb.Location = new System.Drawing.Point(12, 12);
this.captchaPb.Name = "captchaPb";
this.captchaPb.Size = new System.Drawing.Size(429, 186);
this.captchaPb.TabIndex = 0;
this.captchaPb.TabStop = false;
//
// answerTb
//
this.answerTb.Location = new System.Drawing.Point(118, 206);
this.answerTb.Name = "answerTb";
this.answerTb.Size = new System.Drawing.Size(100, 20);
this.answerTb.TabIndex = 1;
//
// submitBtn
//
this.submitBtn.Location = new System.Drawing.Point(366, 204);
this.submitBtn.Name = "submitBtn";
this.submitBtn.Size = new System.Drawing.Size(75, 23);
this.submitBtn.TabIndex = 2;
this.submitBtn.Text = "Submit";
this.submitBtn.UseVisualStyleBackColor = true;
this.submitBtn.Click += new System.EventHandler(this.submitBtn_Click);
//
// answerLbl
//
this.answerLbl.AutoSize = true;
this.answerLbl.Location = new System.Drawing.Point(12, 209);
this.answerLbl.Name = "answerLbl";
this.answerLbl.Size = new System.Drawing.Size(100, 13);
this.answerLbl.TabIndex = 0;
this.answerLbl.Text = "CAPTCHA answer: ";
//
// CaptchaDialog
//
this.AcceptButton = this.submitBtn;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(453, 239);
this.Controls.Add(this.answerLbl);
this.Controls.Add(this.submitBtn);
this.Controls.Add(this.answerTb);
this.Controls.Add(this.captchaPb);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "CaptchaDialog";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "CAPTCHA";
((System.ComponentModel.ISupportInitialize)(this.captchaPb)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.PictureBox captchaPb;
private System.Windows.Forms.TextBox answerTb;
private System.Windows.Forms.Button submitBtn;
private System.Windows.Forms.Label answerLbl;
}
}

View File

@ -0,0 +1,38 @@
using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
namespace LibationWinForm.Dialogs.Login
{
public partial class CaptchaDialog : Form
{
public string Answer { get; private set; }
private MemoryStream ms { get; }
private Image image { get; }
public CaptchaDialog(byte[] captchaImage)
{
InitializeComponent();
this.FormClosed += (_, __) => { ms?.Dispose(); image?.Dispose(); };
ms = new MemoryStream(captchaImage);
image = Image.FromStream(ms);
this.captchaPb.Image = image;
var h1 = captchaPb.Height;
var w1 = captchaPb.Width;
var h2 = captchaPb.Image.Height;
var w2 = captchaPb.Image.Width;
}
private void submitBtn_Click(object sender, EventArgs e)
{
Answer = this.answerTb.Text;
DialogResult = DialogResult.OK;
}
}
}

View File

@ -0,0 +1,32 @@
using System;
using LibationWinForm.Dialogs.Login;
namespace LibationWinForm.Login
{
public class WinformResponder : AudibleApiDomainService.IAudibleApiResponder
{
public string Get2faCode()
{
using var dialog = new _2faCodeDialog();
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
return dialog.Code;
return null;
}
public string GetCaptchaAnswer(byte[] captchaImage)
{
using var dialog = new CaptchaDialog(captchaImage);
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
return dialog.Answer;
return null;
}
public (string email, string password) GetLogin()
{
using var dialog = new AudibleLoginDialog();
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
return (dialog.Email, dialog.Password);
return (null, null);
}
}
}

View File

@ -0,0 +1,90 @@
namespace LibationWinForm.Dialogs.Login
{
partial class _2faCodeDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.submitBtn = new System.Windows.Forms.Button();
this.codeTb = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// submitBtn
//
this.submitBtn.Location = new System.Drawing.Point(15, 51);
this.submitBtn.Name = "SaveBtn";
this.submitBtn.Size = new System.Drawing.Size(79, 23);
this.submitBtn.TabIndex = 1;
this.submitBtn.Text = "Submit";
this.submitBtn.UseVisualStyleBackColor = true;
this.submitBtn.Click += new System.EventHandler(this.submitBtn_Click);
//
// codeTb
//
this.codeTb.Location = new System.Drawing.Point(15, 25);
this.codeTb.Name = "newTagsTb";
this.codeTb.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.codeTb.Size = new System.Drawing.Size(79, 20);
this.codeTb.TabIndex = 0;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(82, 13);
this.label1.TabIndex = 2;
this.label1.Text = "Enter 2FA Code";
//
// _2faCodeDialog
//
this.AcceptButton = this.submitBtn;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(106, 86);
this.Controls.Add(this.label1);
this.Controls.Add(this.codeTb);
this.Controls.Add(this.submitBtn);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "_2faCodeDialog";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "2FA Code";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button submitBtn;
private System.Windows.Forms.TextBox codeTb;
private System.Windows.Forms.Label label1;
}
}

View File

@ -0,0 +1,21 @@
using System;
using System.Windows.Forms;
namespace LibationWinForm.Dialogs.Login
{
public partial class _2faCodeDialog : Form
{
public string Code { get; private set; }
public _2faCodeDialog()
{
InitializeComponent();
}
private void submitBtn_Click(object sender, EventArgs e)
{
Code = this.codeTb.Text;
DialogResult = DialogResult.OK;
}
}
}

View File

@ -358,8 +358,11 @@ namespace LibationWinForm
private async void scanLibraryToolStripMenuItem_Click(object sender, EventArgs e) private async void scanLibraryToolStripMenuItem_Click(object sender, EventArgs e)
{ {
// audible api // audible api
//var client = new AudibleApiDomainService.AudibleApiLibationClient(config.); var settings = new AudibleApiDomainService.Settings(config);
//await client.ImportLibraryAsync(); var responder = new Login.WinformResponder();
var client = await AudibleApiDomainService.AudibleApiLibationClient.CreateClientAsync(settings, responder);
var testResult = await client.TestGetLibraryAsync();
await client.ImportLibraryAsync();
// scrape // scrape
await indexDialog(new ScanLibraryDialog()); await indexDialog(new ScanLibraryDialog());

View File

@ -0,0 +1,112 @@
namespace LibationWinForm_Framework.Dialogs.Login
{
partial class AudibleLoginDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.passwordLbl = new System.Windows.Forms.Label();
this.emailLbl = new System.Windows.Forms.Label();
this.passwordTb = new System.Windows.Forms.TextBox();
this.emailTb = new System.Windows.Forms.TextBox();
this.submitBtn = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// passwordLbl
//
this.passwordLbl.AutoSize = true;
this.passwordLbl.Location = new System.Drawing.Point(12, 41);
this.passwordLbl.Name = "passwordLbl";
this.passwordLbl.Size = new System.Drawing.Size(53, 13);
this.passwordLbl.TabIndex = 2;
this.passwordLbl.Text = "Password";
//
// emailLbl
//
this.emailLbl.AutoSize = true;
this.emailLbl.Location = new System.Drawing.Point(12, 15);
this.emailLbl.Name = "emailLbl";
this.emailLbl.Size = new System.Drawing.Size(32, 13);
this.emailLbl.TabIndex = 0;
this.emailLbl.Text = "Email";
//
// passwordTb
//
this.passwordTb.Location = new System.Drawing.Point(71, 38);
this.passwordTb.Name = "passwordTb";
this.passwordTb.PasswordChar = '*';
this.passwordTb.Size = new System.Drawing.Size(200, 20);
this.passwordTb.TabIndex = 3;
//
// emailTb
//
this.emailTb.Location = new System.Drawing.Point(71, 12);
this.emailTb.Name = "emailTb";
this.emailTb.Size = new System.Drawing.Size(200, 20);
this.emailTb.TabIndex = 1;
//
// submitBtn
//
this.submitBtn.Location = new System.Drawing.Point(196, 64);
this.submitBtn.Name = "submitBtn";
this.submitBtn.Size = new System.Drawing.Size(75, 23);
this.submitBtn.TabIndex = 4;
this.submitBtn.Text = "Submit";
this.submitBtn.UseVisualStyleBackColor = true;
//
// AudibleLoginDialog
//
this.AcceptButton = this.submitBtn;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(283, 99);
this.Controls.Add(this.submitBtn);
this.Controls.Add(this.passwordLbl);
this.Controls.Add(this.emailLbl);
this.Controls.Add(this.passwordTb);
this.Controls.Add(this.emailTb);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "AudibleLoginDialog";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Audible Login";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label passwordLbl;
private System.Windows.Forms.Label emailLbl;
private System.Windows.Forms.TextBox passwordTb;
private System.Windows.Forms.TextBox emailTb;
private System.Windows.Forms.Button submitBtn;
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LibationWinForm_Framework.Dialogs.Login
{
public partial class AudibleLoginDialog : Form
{
public AudibleLoginDialog()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,102 @@
namespace LibationWinForm_Framework.Dialogs.Login
{
partial class CaptchaDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.captchaPb = new System.Windows.Forms.PictureBox();
this.answerTb = new System.Windows.Forms.TextBox();
this.submitBtn = new System.Windows.Forms.Button();
this.answerLbl = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.captchaPb)).BeginInit();
this.SuspendLayout();
//
// captchaPb
//
this.captchaPb.Location = new System.Drawing.Point(12, 12);
this.captchaPb.Name = "captchaPb";
this.captchaPb.Size = new System.Drawing.Size(429, 186);
this.captchaPb.TabIndex = 0;
this.captchaPb.TabStop = false;
//
// answerTb
//
this.answerTb.Location = new System.Drawing.Point(118, 206);
this.answerTb.Name = "answerTb";
this.answerTb.Size = new System.Drawing.Size(100, 20);
this.answerTb.TabIndex = 1;
//
// submitBtn
//
this.submitBtn.Location = new System.Drawing.Point(366, 204);
this.submitBtn.Name = "submitBtn";
this.submitBtn.Size = new System.Drawing.Size(75, 23);
this.submitBtn.TabIndex = 2;
this.submitBtn.Text = "Submit";
this.submitBtn.UseVisualStyleBackColor = true;
//
// answerLbl
//
this.answerLbl.AutoSize = true;
this.answerLbl.Location = new System.Drawing.Point(12, 209);
this.answerLbl.Name = "answerLbl";
this.answerLbl.Size = new System.Drawing.Size(100, 13);
this.answerLbl.TabIndex = 0;
this.answerLbl.Text = "CAPTCHA answer: ";
//
// CaptchaDialog
//
this.AcceptButton = this.submitBtn;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(453, 239);
this.Controls.Add(this.answerLbl);
this.Controls.Add(this.submitBtn);
this.Controls.Add(this.answerTb);
this.Controls.Add(this.captchaPb);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "CaptchaDialog";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "CAPTCHA";
((System.ComponentModel.ISupportInitialize)(this.captchaPb)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.PictureBox captchaPb;
private System.Windows.Forms.TextBox answerTb;
private System.Windows.Forms.Button submitBtn;
private System.Windows.Forms.Label answerLbl;
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LibationWinForm_Framework.Dialogs.Login
{
public partial class CaptchaDialog : Form
{
public CaptchaDialog()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,89 @@
namespace WinFormsDesigner.Dialogs.Login
{
partial class _2faCodeDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.submitBtn = new System.Windows.Forms.Button();
this.codeTb = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// submitBtn
//
this.submitBtn.Location = new System.Drawing.Point(15, 51);
this.submitBtn.Name = "submitBtn";
this.submitBtn.Size = new System.Drawing.Size(79, 23);
this.submitBtn.TabIndex = 1;
this.submitBtn.Text = "Submit";
this.submitBtn.UseVisualStyleBackColor = true;
//
// codeTb
//
this.codeTb.Location = new System.Drawing.Point(15, 25);
this.codeTb.Name = "codeTb";
this.codeTb.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.codeTb.Size = new System.Drawing.Size(79, 20);
this.codeTb.TabIndex = 0;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(82, 13);
this.label1.TabIndex = 2;
this.label1.Text = "Enter 2FA Code";
//
// _2faCodeDialog
//
this.AcceptButton = this.submitBtn;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(106, 86);
this.Controls.Add(this.label1);
this.Controls.Add(this.codeTb);
this.Controls.Add(this.submitBtn);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "_2faCodeDialog";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "2FA Code";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button submitBtn;
private System.Windows.Forms.TextBox codeTb;
private System.Windows.Forms.Label label1;
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Windows.Forms;
namespace WinFormsDesigner.Dialogs.Login
{
public partial class _2faCodeDialog : Form
{
public string NewTags { get; private set; }
public _2faCodeDialog()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -41,8 +41,10 @@
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" /> <Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="BookLiberation\AutomatedBackupsForm.cs"> <Compile Include="BookLiberation\AutomatedBackupsForm.cs">
@ -75,22 +77,40 @@
<Compile Include="Dialogs\EditQuickFilters.Designer.cs"> <Compile Include="Dialogs\EditQuickFilters.Designer.cs">
<DependentUpon>EditQuickFilters.cs</DependentUpon> <DependentUpon>EditQuickFilters.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Dialogs\Login\AudibleLoginDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Dialogs\Login\AudibleLoginDialog.Designer.cs">
<DependentUpon>AudibleLoginDialog.cs</DependentUpon>
</Compile>
<Compile Include="Dialogs\Login\CaptchaDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Dialogs\Login\CaptchaDialog.Designer.cs">
<DependentUpon>CaptchaDialog.cs</DependentUpon>
</Compile>
<Compile Include="Dialogs\Login\_2faCodeDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Dialogs\Login\_2faCodeDialog.Designer.cs">
<DependentUpon>_2faCodeDialog.cs</DependentUpon>
</Compile>
<Compile Include="Dialogs\EditTagsDialog.cs"> <Compile Include="Dialogs\EditTagsDialog.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
<Compile Include="Dialogs\EditTagsDialog.Designer.cs"> <Compile Include="Dialogs\EditTagsDialog.Designer.cs">
<DependentUpon>EditTagsDialog.cs</DependentUpon> <DependentUpon>EditTagsDialog.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="IndexDialogs\ScanLibraryDialog.cs"> <Compile Include="Dialogs\IndexDialogs\ScanLibraryDialog.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
<Compile Include="IndexDialogs\ScanLibraryDialog.Designer.cs"> <Compile Include="Dialogs\IndexDialogs\ScanLibraryDialog.Designer.cs">
<DependentUpon>ScanLibraryDialog.cs</DependentUpon> <DependentUpon>ScanLibraryDialog.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="IndexDialogs\WebsiteProcessorControl.cs"> <Compile Include="Dialogs\IndexDialogs\WebsiteProcessorControl.cs">
<SubType>UserControl</SubType> <SubType>UserControl</SubType>
</Compile> </Compile>
<Compile Include="IndexDialogs\WebsiteProcessorControl.Designer.cs"> <Compile Include="Dialogs\IndexDialogs\WebsiteProcessorControl.Designer.cs">
<DependentUpon>WebsiteProcessorControl.cs</DependentUpon> <DependentUpon>WebsiteProcessorControl.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Dialogs\SearchSyntaxDialog.cs"> <Compile Include="Dialogs\SearchSyntaxDialog.cs">
@ -137,10 +157,19 @@
<EmbeddedResource Include="Dialogs\EditTagsDialog.resx"> <EmbeddedResource Include="Dialogs\EditTagsDialog.resx">
<DependentUpon>EditTagsDialog.cs</DependentUpon> <DependentUpon>EditTagsDialog.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="IndexDialogs\ScanLibraryDialog.resx"> <EmbeddedResource Include="Dialogs\Login\AudibleLoginDialog.resx">
<DependentUpon>AudibleLoginDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Dialogs\Login\CaptchaDialog.resx">
<DependentUpon>CaptchaDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Dialogs\Login\_2faCodeDialog.resx">
<DependentUpon>_2faCodeDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Dialogs\IndexDialogs\ScanLibraryDialog.resx">
<DependentUpon>ScanLibraryDialog.cs</DependentUpon> <DependentUpon>ScanLibraryDialog.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="IndexDialogs\WebsiteProcessorControl.resx"> <EmbeddedResource Include="Dialogs\IndexDialogs\WebsiteProcessorControl.resx">
<DependentUpon>WebsiteProcessorControl.cs</DependentUpon> <DependentUpon>WebsiteProcessorControl.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Dialogs\SearchSyntaxDialog.resx"> <EmbeddedResource Include="Dialogs\SearchSyntaxDialog.resx">
@ -157,6 +186,7 @@
</EmbeddedResource> </EmbeddedResource>
<None Include="Properties\DataSources\LibationWinForm_Framework.ProductGrids.GridEntry.datasource" /> <None Include="Properties\DataSources\LibationWinForm_Framework.ProductGrids.GridEntry.datasource" />
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\System.Data.SQLite.Core.1.0.111.0\build\net46\System.Data.SQLite.Core.targets" Condition="Exists('..\packages\System.Data.SQLite.Core.1.0.111.0\build\net46\System.Data.SQLite.Core.targets')" /> <Import Project="..\packages\System.Data.SQLite.Core.1.0.111.0\build\net46\System.Data.SQLite.Core.targets" Condition="Exists('..\packages\System.Data.SQLite.Core.1.0.111.0\build\net46\System.Data.SQLite.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">