Add API key management. #10
No files matched your search
@@ -1,12 +1,9 @@
|
|||||||
using System;
|
|
||||||
using System.Data.Entity.Migrations.Model;
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using PcgsInvUi.Services;
|
using PcgsInvUi.Services;
|
||||||
using PcgsInvUi.ViewModels;
|
using PcgsInvUi.ViewModels;
|
||||||
using PcgsInvUi.Views;
|
using PcgsInvUi.Views;
|
||||||
using PcgsInvUi.Models;
|
|
||||||
|
|
||||||
namespace PcgsInvUi;
|
namespace PcgsInvUi;
|
||||||
|
|
||||||
@@ -20,17 +17,15 @@ public partial class App : Application {
|
|||||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) {
|
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) {
|
||||||
var coins = new CoinDatabase();
|
var coins = new CoinDatabase();
|
||||||
desktop.MainWindow = new MainWindow {
|
desktop.MainWindow = new MainWindow {
|
||||||
DataContext = new MainWindowViewModel(coins),
|
DataContext = new MainWindowViewModel(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Allow the application to save the database when it exits.
|
||||||
|
// The issue is that this will break if the database is not initialized here.
|
||||||
desktop.Exit += (sender, args) => {
|
desktop.Exit += (sender, args) => {
|
||||||
coins.UpdateCollection("CollectionTable");
|
coins.UpdateCollection("CollectionTable");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
base.OnFrameworkInitializationCompleted();
|
base.OnFrameworkInitializationCompleted();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public void OnExit(object sender, ControlledApplicationLifetimeExitEventArgs e) {
|
|
||||||
// Save the database?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,15 +16,40 @@ public class CoinDatabase {
|
|||||||
public CoinDatabase() {
|
public CoinDatabase() {
|
||||||
// Create a connection to SQLite
|
// Create a connection to SQLite
|
||||||
Connection = CreateConnection();
|
Connection = CreateConnection();
|
||||||
// Create a client to access the API.
|
|
||||||
_pcgsClient = new PcgsClient(
|
|
||||||
"eAb8gS0I2XAvT_5gJeiGJaglMia1Tk-oB4kJUK6kuafyrny_S61vIJY-Ikl4nCQM67wrdxzUqLVWTV2kBSxD3d5XNBHxHnYBhcSS6dOPug0hZaF3qAv56df3gYSzOGh9Tif5y0eP3Iw0LrqKDr1Hj-dk6SV6GKog2IIqCPQhhHH8FMTWBTYO-_O8cx7qLdM5GM8KlTsic6g3VRUhM8EA_4OO04dCfmNLGhqINRl3jGZ0Q4ziI8fng2bVWsIyteqiPzUn10rIQ3-OPpqVZG_DxeOmOejj4GzbUNyqUOajy-nr5rYY");
|
|
||||||
// Create a base table.
|
// Create a base table.
|
||||||
CreateCollection("CollectionTable");
|
CreateCollection("CollectionTable");
|
||||||
|
CreateApiTable();
|
||||||
Console.WriteLine("Connected to database.");
|
Console.WriteLine("Connected to database.");
|
||||||
Collection = new ObservableCollection<Coin>();
|
Collection = new ObservableCollection<Coin>();
|
||||||
GetCollection("CollectionTable");
|
GetCollection("CollectionTable");
|
||||||
Console.WriteLine("Got collection.");
|
Console.WriteLine("Got collection.");
|
||||||
|
|
||||||
|
// Initialize the PCGS client. Must get the API key from the database.
|
||||||
|
// Check the database for an API key.
|
||||||
|
SQLiteCommand cmd = Connection.CreateCommand();
|
||||||
|
cmd.CommandText = "SELECT API_KEY FROM ApiTable";
|
||||||
|
using (var reader = cmd.ExecuteReader()) {
|
||||||
|
// If there's no API key, we need to get one from the user.
|
||||||
|
// Eventually there will be a window that pops up adking for the API key.
|
||||||
|
var apiKey = "";
|
||||||
|
if (reader.Read()) {
|
||||||
|
// Initialize the client.
|
||||||
|
apiKey = reader.GetString(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Get the API key from the user.
|
||||||
|
// TODO Create and open a window that asks for the API key.
|
||||||
|
// Since this needs to build before the main window is created, we can't do that yet.
|
||||||
|
Console.WriteLine("No API key found. Using default...");
|
||||||
|
do {
|
||||||
|
// Console.Write("Enter a valid API key: ");
|
||||||
|
// apiKey = Console.ReadLine();
|
||||||
|
// Eventually we actually want to throw an error here.
|
||||||
|
apiKey = "E8xivTVN_k4Q8ubk8Xv_uU11U91WX0wDht4S4m4BAf2HPmKnGrZ0J2f9nccM7Ns1VkGoT1SXYR74I7aNaMKqXlJGEy3oobseKV0nGiqu1IKvFkOTVjhV37SWUVExSDFMC6FLzs7xJQIHwkcxr5JFOQNmc4ZytEh_-hmCN3NL-z0fEk98tzBmPJ_F7bq_xNru86QMD2A9yalu_dWe-lCysfyE2bCA2EDqwvWenRYf-0XnNtp6qlxxCMlCd-TDqqRKLC3qefCwpXSemwBiNSP5gbC9pwcKrZugkruuJ0nyxxThZymm";
|
||||||
|
} while (apiKey == "" || apiKey == null);
|
||||||
|
}
|
||||||
|
_pcgsClient = new PcgsClient(apiKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~CoinDatabase() {
|
~CoinDatabase() {
|
||||||
@@ -38,9 +63,9 @@ public class CoinDatabase {
|
|||||||
private SQLiteConnection CreateConnection() {
|
private SQLiteConnection CreateConnection() {
|
||||||
// Check if database exists.
|
// Check if database exists.
|
||||||
if (!System.IO.File.Exists("coin_collection")) {
|
if (!System.IO.File.Exists("coin_collection")) {
|
||||||
// Create the database.
|
// If not, create the database.
|
||||||
Console.Write("Creating database... ");
|
Console.Write("Creating database... ");
|
||||||
SQLiteConnection.CreateFile("coin_collection");
|
SQLiteConnection.CreateFile("coin_collection.sqlite");
|
||||||
Console.WriteLine("Done.");
|
Console.WriteLine("Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +85,27 @@ public class CoinDatabase {
|
|||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CreateApiTable() {
|
||||||
|
// Create a table to store the API key and the number of requests remaining.
|
||||||
|
if (!IsConnected) {
|
||||||
|
// TODO Create a NotConnectedToDatabaseException
|
||||||
|
Console.WriteLine("Not connected to database.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a SQL command.
|
||||||
|
SQLiteCommand cmd = Connection.CreateCommand();
|
||||||
|
cmd.CommandText =
|
||||||
|
"CREATE TABLE IF NOT EXISTS ApiTable (" +
|
||||||
|
"API_KEY TEXT, " +
|
||||||
|
"REQUESTS_REMAINING INTEGER, " +
|
||||||
|
"PRIMARY KEY(API_KEY))";
|
||||||
|
|
||||||
|
// Execute the command
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
Console.WriteLine("API table initialized.");
|
||||||
|
}
|
||||||
|
|
||||||
public void CreateCollection(string collectionName) {
|
public void CreateCollection(string collectionName) {
|
||||||
// Create a table to store the collection.
|
// Create a table to store the collection.
|
||||||
if (!IsConnected) {
|
if (!IsConnected) {
|
||||||
@@ -93,6 +139,7 @@ public class CoinDatabase {
|
|||||||
|
|
||||||
// Execute the command.
|
// Execute the command.
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
|
Console.WriteLine("Collection table initialized.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InsertCoin(Coin coin) {
|
public void InsertCoin(Coin coin) {
|
||||||
@@ -297,4 +344,4 @@ public class CoinDatabase {
|
|||||||
Console.WriteLine($"Grade is {actualGrade}");
|
Console.WriteLine($"Grade is {actualGrade}");
|
||||||
return actualGrade;
|
return actualGrade;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using PcgsInvUi.Models;
|
using PcgsInvUi.Models;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using DynamicData.Kernel;
|
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace PcgsInvUi.Services;
|
namespace PcgsInvUi.Services;
|
||||||
@@ -28,9 +26,8 @@ public class PcgsClient : ReactiveObject {
|
|||||||
private int _numApiRequests;
|
private int _numApiRequests;
|
||||||
|
|
||||||
public PcgsClient(string apiKey) {
|
public PcgsClient(string apiKey) {
|
||||||
// _apiKey = apiKey;
|
_apiKey = apiKey;
|
||||||
_apiKey =
|
// "E8xivTVN_k4Q8ubk8Xv_uU11U91WX0wDht4S4m4BAf2HPmKnGrZ0J2f9nccM7Ns1VkGoT1SXYR74I7aNaMKqXlJGEy3oobseKV0nGiqu1IKvFkOTVjhV37SWUVExSDFMC6FLzs7xJQIHwkcxr5JFOQNmc4ZytEh_-hmCN3NL-z0fEk98tzBmPJ_F7bq_xNru86QMD2A9yalu_dWe-lCysfyE2bCA2EDqwvWenRYf-0XnNtp6qlxxCMlCd-TDqqRKLC3qefCwpXSemwBiNSP5gbC9pwcKrZugkruuJ0nyxxThZymm";
|
||||||
"E8xivTVN_k4Q8ubk8Xv_uU11U91WX0wDht4S4m4BAf2HPmKnGrZ0J2f9nccM7Ns1VkGoT1SXYR74I7aNaMKqXlJGEy3oobseKV0nGiqu1IKvFkOTVjhV37SWUVExSDFMC6FLzs7xJQIHwkcxr5JFOQNmc4ZytEh_-hmCN3NL-z0fEk98tzBmPJ_F7bq_xNru86QMD2A9yalu_dWe-lCysfyE2bCA2EDqwvWenRYf-0XnNtp6qlxxCMlCd-TDqqRKLC3qefCwpXSemwBiNSP5gbC9pwcKrZugkruuJ0nyxxThZymm";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(ErrorType, Coin?)> GetCoinFactsByGrade(int pcgsNumber, string grade, bool plusGrade = false) {
|
public async Task<(ErrorType, Coin?)> GetCoinFactsByGrade(int pcgsNumber, string grade, bool plusGrade = false) {
|
||||||
@@ -86,4 +83,4 @@ class CoinNotFoundException : Exception {
|
|||||||
public CoinNotFoundException() { }
|
public CoinNotFoundException() { }
|
||||||
public CoinNotFoundException(string message) : base(message) { }
|
public CoinNotFoundException(string message) : base(message) { }
|
||||||
public CoinNotFoundException(string message, Exception inner) : base(message, inner) { }
|
public CoinNotFoundException(string message, Exception inner) : base(message, inner) { }
|
||||||
}
|
}
|
||||||
@@ -10,18 +10,6 @@ using ReactiveUI;
|
|||||||
|
|
||||||
namespace PcgsInvUi.ViewModels;
|
namespace PcgsInvUi.ViewModels;
|
||||||
|
|
||||||
// TODO Create proper sums for total value.
|
|
||||||
// TODO Error handling for API calls.
|
|
||||||
// TODO Manual handling of API key.
|
|
||||||
// TODO Use CoinFacts link.
|
|
||||||
// TODO Splash screen during startup.
|
|
||||||
// TODO Take giant sheet of coins to integrate into the application.
|
|
||||||
// TODO Update all coins. Choose those that are older first.
|
|
||||||
// TODO API request tracker (1000 per day)
|
|
||||||
// TODO Ok button greys out while request is happening.
|
|
||||||
// TODO Track when coins were last updated.
|
|
||||||
// TODO Image for coin in notes view.
|
|
||||||
|
|
||||||
public class MainWindowViewModel : ViewModelBase {
|
public class MainWindowViewModel : ViewModelBase {
|
||||||
public ViewModelBase SidebarContent {
|
public ViewModelBase SidebarContent {
|
||||||
get => _sideContent;
|
get => _sideContent;
|
||||||
@@ -48,7 +36,7 @@ public class MainWindowViewModel : ViewModelBase {
|
|||||||
private Coin? _selectedCoin;
|
private Coin? _selectedCoin;
|
||||||
private double _totalValue;
|
private double _totalValue;
|
||||||
|
|
||||||
public MainWindowViewModel(CoinDatabase coins) {
|
public MainWindowViewModel(CoinDatabase coins, bool askForApiKey) {
|
||||||
ConnectedCoinDatabase = coins;
|
ConnectedCoinDatabase = coins;
|
||||||
var newViewModel = new NewViewModel();
|
var newViewModel = new NewViewModel();
|
||||||
_sideContent = newViewModel;
|
_sideContent = newViewModel;
|
||||||
@@ -126,4 +114,11 @@ public class MainWindowViewModel : ViewModelBase {
|
|||||||
TotalValue = ConnectedCoinDatabase.Collection.Sum(x => x.TotalPrice);
|
TotalValue = ConnectedCoinDatabase.Collection.Sum(x => x.TotalPrice);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create destructor to save the database when the application exits.
|
||||||
|
// This is necessary because the database is initialized in this class.
|
||||||
|
~MainWindowViewModel() {
|
||||||
|
Console.WriteLine("Running MainWindowViewModel destructor.");
|
||||||
|
ConnectedCoinDatabase.UpdateCollection("CollectionTable");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user