Rimuovi export settings, aggiungi filtro livello log
- Rimossa la sezione "Impostazioni Export" dalla UI e dal code-behind, inclusi controlli, eventi e file legacy di export. - Aggiunta configurazione del livello minimo di log (ErrorOnly, Normal, Informational, Debug, Trace) con guida e legenda colori. - La funzione di log ora filtra i messaggi in base al livello selezionato. - Aggiornati modelli di impostazioni e enum LogLevel per supportare i nuovi livelli. - Refactoring commenti e uniformità sezioni impostazioni. - Migliorata la chiarezza del log di avvio applicazione.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
using System.Configuration;
|
using System.Configuration;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
|
|||||||
@@ -89,79 +89,7 @@
|
|||||||
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto">
|
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto">
|
||||||
<StackPanel Margin="30,20">
|
<StackPanel Margin="30,20">
|
||||||
|
|
||||||
<!-- SEZIONE 1: Impostazioni Export -->
|
<!-- SEZIONE 1: Impostazioni Predefinite Aste -->
|
||||||
<Border Background="#252526"
|
|
||||||
BorderBrush="#3E3E42"
|
|
||||||
BorderThickness="1"
|
|
||||||
CornerRadius="4"
|
|
||||||
Padding="20"
|
|
||||||
Margin="0,0,0,20">
|
|
||||||
<StackPanel>
|
|
||||||
<TextBlock Text="Impostazioni Export"
|
|
||||||
Style="{StaticResource SectionHeader}"/>
|
|
||||||
|
|
||||||
<TextBlock Text="Percorso di Export"
|
|
||||||
Style="{StaticResource FieldLabel}"/>
|
|
||||||
|
|
||||||
<Grid Margin="0,0,0,20">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
|
|
||||||
<TextBox Grid.Column="0"
|
|
||||||
x:Name="ExportPathTextBox"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Margin="0,0,10,0"/>
|
|
||||||
|
|
||||||
<Button Grid.Column="1"
|
|
||||||
x:Name="ExportBrowseButton"
|
|
||||||
Content="Sfoglia"
|
|
||||||
Background="#007ACC"
|
|
||||||
Style="{StaticResource ModernButton}"
|
|
||||||
Click="ExportBrowseButton_Click"/>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<TextBlock Text="Formato File"
|
|
||||||
Style="{StaticResource FieldLabel}"/>
|
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,20">
|
|
||||||
<RadioButton x:Name="ExtCsv"
|
|
||||||
Content="CSV"
|
|
||||||
GroupName="ExportFormat"
|
|
||||||
IsChecked="True"/>
|
|
||||||
<RadioButton x:Name="ExtJson"
|
|
||||||
Content="JSON"
|
|
||||||
GroupName="ExportFormat"/>
|
|
||||||
<RadioButton x:Name="ExtXml"
|
|
||||||
Content="XML"
|
|
||||||
GroupName="ExportFormat"/>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<TextBlock Text="Opzioni di Export"
|
|
||||||
Style="{StaticResource FieldLabel}"/>
|
|
||||||
|
|
||||||
<StackPanel>
|
|
||||||
<CheckBox x:Name="IncludeUsedBids"
|
|
||||||
Content="Includi solo puntate utilizzate"
|
|
||||||
IsChecked="True"/>
|
|
||||||
<CheckBox x:Name="IncludeLogs"
|
|
||||||
Content="Includi log delle aste"/>
|
|
||||||
<CheckBox x:Name="IncludeUserBids"
|
|
||||||
Content="Includi storico puntate utenti"
|
|
||||||
IsChecked="True"/>
|
|
||||||
<CheckBox x:Name="IncludeMetadata"
|
|
||||||
Content="Includi metadata delle aste"
|
|
||||||
IsChecked="True"/>
|
|
||||||
<CheckBox x:Name="RemoveAfterExport"
|
|
||||||
Content="Rimuovi aste dopo l'export"/>
|
|
||||||
<CheckBox x:Name="OverwriteExisting"
|
|
||||||
Content="Sovrascrivi file esistenti"/>
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
</Border>
|
|
||||||
|
|
||||||
<!-- SEZIONE 2: Impostazioni Predefinite Aste -->
|
|
||||||
<Border Background="#252526"
|
<Border Background="#252526"
|
||||||
BorderBrush="#3E3E42"
|
BorderBrush="#3E3E42"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
@@ -194,7 +122,7 @@
|
|||||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Anticipo Puntata (millisecondi)" Foreground="#CCCCCC" Margin="0,10" VerticalAlignment="Center" ToolTip="Millisecondi prima della scadenza per puntare"/>
|
<TextBlock Grid.Row="0" Grid.Column="0" Text="Anticipo Puntata (millisecondi)" Foreground="#CCCCCC" Margin="0,10" VerticalAlignment="Center" ToolTip="Millisecondi prima della scadenza per puntare"/>
|
||||||
<TextBox Grid.Row="0" Grid.Column="1" x:Name="DefaultBidBeforeDeadlineMsTextBox" Text="200" Margin="10,10"/>
|
<TextBox Grid.Row="0" Grid.Column="1" x:Name="DefaultBidBeforeDeadlineMsTextBox" Text="200" Margin="10,10"/>
|
||||||
|
|
||||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Verifica Stato Prima di Puntare" Foreground="#CCCCCC" Margin="0,10" VerticalAlignment="Center" ToolTip="Controlla che l'asta sia ancora aperta prima di puntare"/>
|
<TextBlock Grid.Row="1" Grid.Column="0" Text="Verifica Stato Prima Di Puntare" Foreground="#CCCCCC" Margin="0,10" VerticalAlignment="Center" ToolTip="Controlla che l'asta sia ancora aperta prima di puntare"/>
|
||||||
<CheckBox Grid.Row="1" Grid.Column="1" x:Name="DefaultCheckAuctionOpenCheckBox" Margin="10,10" VerticalAlignment="Center"/>
|
<CheckBox Grid.Row="1" Grid.Column="1" x:Name="DefaultCheckAuctionOpenCheckBox" Margin="10,10" VerticalAlignment="Center"/>
|
||||||
|
|
||||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Prezzo Minimo (€)" Foreground="#CCCCCC" Margin="0,10" VerticalAlignment="Center"/>
|
<TextBlock Grid.Row="2" Grid.Column="0" Text="Prezzo Minimo (€)" Foreground="#CCCCCC" Margin="0,10" VerticalAlignment="Center"/>
|
||||||
@@ -209,7 +137,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!-- SEZIONE 3: Stato Iniziale Aste -->
|
<!-- SEZIONE 2: Stato Iniziale Aste -->
|
||||||
<Border Background="#252526"
|
<Border Background="#252526"
|
||||||
BorderBrush="#3E3E42"
|
BorderBrush="#3E3E42"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
@@ -294,7 +222,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!-- SEZIONE 4: Protezione Account -->
|
<!-- SEZIONE 3: Protezione Account -->
|
||||||
<Border Background="#252526"
|
<Border Background="#252526"
|
||||||
BorderBrush="#3E3E42"
|
BorderBrush="#3E3E42"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
@@ -357,7 +285,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!-- SEZIONE 5: Limiti Log -->
|
<!-- SEZIONE 4: Limiti Log -->
|
||||||
<Border Background="#252526"
|
<Border Background="#252526"
|
||||||
BorderBrush="#3E3E42"
|
BorderBrush="#3E3E42"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
@@ -439,6 +367,131 @@
|
|||||||
</Border>
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
|
<!-- SEZIONE 5: Livello di Dettaglio Log -->
|
||||||
|
<Border Background="#252526"
|
||||||
|
BorderBrush="#3E3E42"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="4"
|
||||||
|
Padding="20"
|
||||||
|
Margin="0,20,0,0">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock Text="Livello di Dettaglio Log"
|
||||||
|
Style="{StaticResource SectionHeader}"/>
|
||||||
|
|
||||||
|
<TextBlock Text="Configura il livello minimo dei messaggi da visualizzare nel log. Livelli più bassi mostrano solo messaggi critici, livelli più alti mostrano tutti i dettagli (utile per debug)."
|
||||||
|
Foreground="#999999"
|
||||||
|
FontSize="12"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Margin="0,0,0,20"/>
|
||||||
|
|
||||||
|
<!-- Radio Buttons per livello log -->
|
||||||
|
<StackPanel>
|
||||||
|
<RadioButton x:Name="LogLevelErrorOnly"
|
||||||
|
Content="Solo Errori"
|
||||||
|
GroupName="LogLevel"
|
||||||
|
Margin="0,5"
|
||||||
|
ToolTip="Mostra solo errori critici (uso minimo per produzione)"/>
|
||||||
|
|
||||||
|
<RadioButton x:Name="LogLevelNormal"
|
||||||
|
Content="Normale (Errori + Avvisi)"
|
||||||
|
GroupName="LogLevel"
|
||||||
|
IsChecked="True"
|
||||||
|
Margin="0,5"
|
||||||
|
ToolTip="Mostra errori e avvisi (uso giornaliero raccomandato)"/>
|
||||||
|
|
||||||
|
<RadioButton x:Name="LogLevelInformational"
|
||||||
|
Content="Informativo (Include operazioni completate)"
|
||||||
|
GroupName="LogLevel"
|
||||||
|
Margin="0,5"
|
||||||
|
ToolTip="Mostra anche messaggi informativi e conferme (uso dettagliato)"/>
|
||||||
|
|
||||||
|
<RadioButton x:Name="LogLevelDebug"
|
||||||
|
Content="Debug (Include dettagli tecnici)"
|
||||||
|
GroupName="LogLevel"
|
||||||
|
Margin="0,5"
|
||||||
|
ToolTip="Mostra anche messaggi di debug per sviluppo"/>
|
||||||
|
|
||||||
|
<RadioButton x:Name="LogLevelTrace"
|
||||||
|
Content="Trace (Tutto - molto verboso)"
|
||||||
|
GroupName="LogLevel"
|
||||||
|
Margin="0,5"
|
||||||
|
ToolTip="Mostra ogni singola operazione (debug avanzato)"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Info Box -->
|
||||||
|
<Border Style="{StaticResource InfoBox}" Margin="0,15,0,0">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock Text="🔍 Guida alla Scelta"
|
||||||
|
FontWeight="Bold"
|
||||||
|
Foreground="#FFB700"
|
||||||
|
Margin="0,0,0,10"/>
|
||||||
|
<TextBlock Foreground="#CCCCCC"
|
||||||
|
FontSize="12"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Margin="0,0,0,5">
|
||||||
|
<Run>Solo Errori: Usa in produzione per vedere solo problemi critici.</Run>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Foreground="#CCCCCC"
|
||||||
|
FontSize="12"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Margin="0,0,0,5">
|
||||||
|
<Run>Normale: Raccomandato per uso giornaliero. Mostra errori e avvisi importanti.</Run>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Foreground="#CCCCCC"
|
||||||
|
FontSize="12"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Margin="0,0,0,5">
|
||||||
|
<Run>Informativo: Utile per seguire le operazioni principali (aggiunte aste, puntate).</Run>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Foreground="#CCCCCC"
|
||||||
|
FontSize="12"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Margin="0,0,0,5">
|
||||||
|
<Run>Debug: Per sviluppo. Mostra parametri chiamate API e valori interni.</Run>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Foreground="#CCCCCC"
|
||||||
|
FontSize="12"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Margin="0,0,0,10">
|
||||||
|
<Run>Trace: Debug avanzato. Mostra ogni singola chiamata (molto verboso).</Run>
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
|
<TextBlock Foreground="#CCCCCC"
|
||||||
|
FontSize="12"
|
||||||
|
FontWeight="Bold"
|
||||||
|
Margin="0,5,0,5">Legenda colori log:</TextBlock>
|
||||||
|
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock FontSize="11" Margin="0,2">
|
||||||
|
<Run Foreground="#E81123">■ ROSSO</Run>
|
||||||
|
<Run Foreground="#CCCCCC"> = Errori critici</Run>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock FontSize="11" Margin="0,2">
|
||||||
|
<Run Foreground="#FFB700">■ ARANCIONE</Run>
|
||||||
|
<Run Foreground="#CCCCCC"> = Avvisi</Run>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock FontSize="11" Margin="0,2">
|
||||||
|
<Run Foreground="#64B4FF">■ BLU</Run>
|
||||||
|
<Run Foreground="#CCCCCC"> = Informazioni</Run>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock FontSize="11" Margin="0,2">
|
||||||
|
<Run Foreground="#00D800">■ VERDE</Run>
|
||||||
|
<Run Foreground="#CCCCCC"> = Operazioni riuscite</Run>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock FontSize="11" Margin="0,2">
|
||||||
|
<Run Foreground="#FF8CFF">■ MAGENTA</Run>
|
||||||
|
<Run Foreground="#CCCCCC"> = Debug</Run>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock FontSize="11" Margin="0,2">
|
||||||
|
<Run Foreground="#A0A0A0">■ GRIGIO</Run>
|
||||||
|
<Run Foreground="#CCCCCC"> = Trace</Run>
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|
||||||
|
|||||||
@@ -25,26 +25,6 @@ namespace AutoBidder.Controls
|
|||||||
// ?? NUOVO: Proprietà per limite storia puntate
|
// ?? NUOVO: Proprietà per limite storia puntate
|
||||||
public TextBox MaxBidHistoryEntries => MaxBidHistoryEntriesTextBox;
|
public TextBox MaxBidHistoryEntries => MaxBidHistoryEntriesTextBox;
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// NOTA: Eventi cookie RIMOSSI
|
|
||||||
// Gestione automatica tramite browser
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
private void ExportBrowseButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
RaiseEvent(new RoutedEventArgs(ExportBrowseClickedEvent, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveSettingsButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
RaiseEvent(new RoutedEventArgs(SaveSettingsClickedEvent, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CancelSettingsButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
RaiseEvent(new RoutedEventArgs(CancelSettingsClickedEvent, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveDefaultsButton_Click(object sender, RoutedEventArgs e)
|
private void SaveDefaultsButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
RaiseEvent(new RoutedEventArgs(SaveDefaultsClickedEvent, this));
|
RaiseEvent(new RoutedEventArgs(SaveDefaultsClickedEvent, this));
|
||||||
@@ -60,10 +40,7 @@ namespace AutoBidder.Controls
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 1. Salva impostazioni export
|
// Salva impostazioni predefinite aste (export rimosso)
|
||||||
RaiseEvent(new RoutedEventArgs(SaveSettingsClickedEvent, this));
|
|
||||||
|
|
||||||
// 2. Salva impostazioni predefinite aste
|
|
||||||
RaiseEvent(new RoutedEventArgs(SaveDefaultsClickedEvent, this));
|
RaiseEvent(new RoutedEventArgs(SaveDefaultsClickedEvent, this));
|
||||||
|
|
||||||
// UNICO MessageBox di conferma
|
// UNICO MessageBox di conferma
|
||||||
@@ -88,44 +65,16 @@ namespace AutoBidder.Controls
|
|||||||
private void CancelAllSettings_Click(object sender, RoutedEventArgs e)
|
private void CancelAllSettings_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
// Annulla tutte le modifiche
|
// Annulla tutte le modifiche
|
||||||
RaiseEvent(new RoutedEventArgs(CancelSettingsClickedEvent, this));
|
|
||||||
RaiseEvent(new RoutedEventArgs(CancelDefaultsClickedEvent, this));
|
RaiseEvent(new RoutedEventArgs(CancelDefaultsClickedEvent, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routed Events (cookie events RIMOSSI)
|
// Routed Events
|
||||||
public static readonly RoutedEvent ExportBrowseClickedEvent = EventManager.RegisterRoutedEvent(
|
|
||||||
"ExportBrowseClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SettingsControl));
|
|
||||||
|
|
||||||
public static readonly RoutedEvent SaveSettingsClickedEvent = EventManager.RegisterRoutedEvent(
|
|
||||||
"SaveSettingsClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SettingsControl));
|
|
||||||
|
|
||||||
public static readonly RoutedEvent CancelSettingsClickedEvent = EventManager.RegisterRoutedEvent(
|
|
||||||
"CancelSettingsClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SettingsControl));
|
|
||||||
|
|
||||||
public static readonly RoutedEvent SaveDefaultsClickedEvent = EventManager.RegisterRoutedEvent(
|
public static readonly RoutedEvent SaveDefaultsClickedEvent = EventManager.RegisterRoutedEvent(
|
||||||
"SaveDefaultsClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SettingsControl));
|
"SaveDefaultsClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SettingsControl));
|
||||||
|
|
||||||
public static readonly RoutedEvent CancelDefaultsClickedEvent = EventManager.RegisterRoutedEvent(
|
public static readonly RoutedEvent CancelDefaultsClickedEvent = EventManager.RegisterRoutedEvent(
|
||||||
"CancelDefaultsClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SettingsControl));
|
"CancelDefaultsClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SettingsControl));
|
||||||
|
|
||||||
public event RoutedEventHandler ExportBrowseClicked
|
|
||||||
{
|
|
||||||
add { AddHandler(ExportBrowseClickedEvent, value); }
|
|
||||||
remove { RemoveHandler(ExportBrowseClickedEvent, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public event RoutedEventHandler SaveSettingsClicked
|
|
||||||
{
|
|
||||||
add { AddHandler(SaveSettingsClickedEvent, value); }
|
|
||||||
remove { RemoveHandler(SaveSettingsClickedEvent, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public event RoutedEventHandler CancelSettingsClicked
|
|
||||||
{
|
|
||||||
add { AddHandler(CancelSettingsClickedEvent, value); }
|
|
||||||
remove { RemoveHandler(CancelSettingsClickedEvent, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public event RoutedEventHandler SaveDefaultsClicked
|
public event RoutedEventHandler SaveDefaultsClicked
|
||||||
{
|
{
|
||||||
add { AddHandler(SaveDefaultsClickedEvent, value); }
|
add { AddHandler(SaveDefaultsClickedEvent, value); }
|
||||||
|
|||||||
@@ -1,351 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
using AutoBidder.Utilities;
|
|
||||||
|
|
||||||
namespace AutoBidder
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Export functionality event handlers
|
|
||||||
/// </summary>
|
|
||||||
public partial class MainWindow
|
|
||||||
{
|
|
||||||
private CancellationTokenSource? _exportCts;
|
|
||||||
|
|
||||||
private void LoadExportSettings()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var s = SettingsManager.Load();
|
|
||||||
if (s != null)
|
|
||||||
{
|
|
||||||
ExportPathTextBox.Text = s.ExportPath ?? string.Empty;
|
|
||||||
if (!string.IsNullOrEmpty(s.LastExportExt))
|
|
||||||
{
|
|
||||||
var ext = s.LastExportExt.ToLowerInvariant();
|
|
||||||
if (ext == ".json") ExtJson.IsChecked = true;
|
|
||||||
else if (ext == ".xml") ExtXml.IsChecked = true;
|
|
||||||
else ExtCsv.IsChecked = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ExtCsv.IsChecked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try { var cbOpen = this.FindName("ExportOpenToolbar") as System.Windows.Controls.CheckBox; if (cbOpen != null) cbOpen.IsChecked = s.ExportOpen; } catch { }
|
|
||||||
try { var cbClosed = this.FindName("ExportClosedToolbar") as System.Windows.Controls.CheckBox; if (cbClosed != null) cbClosed.IsChecked = s.ExportClosed; } catch { }
|
|
||||||
try { var cbUnknown = this.FindName("ExportUnknownToolbar") as System.Windows.Controls.CheckBox; if (cbUnknown != null) cbUnknown.IsChecked = s.ExportUnknown; } catch { }
|
|
||||||
|
|
||||||
try { IncludeUsedBids.IsChecked = s.IncludeOnlyUsedBids; } catch { }
|
|
||||||
try { IncludeLogs.IsChecked = s.IncludeLogs; } catch { }
|
|
||||||
try { IncludeUserBids.IsChecked = s.IncludeUserBids; } catch { }
|
|
||||||
try { IncludeMetadata.IsChecked = s.IncludeMetadata; } catch { }
|
|
||||||
try { RemoveAfterExport.IsChecked = s.RemoveAfterExport; } catch { }
|
|
||||||
try { OverwriteExisting.IsChecked = s.OverwriteExisting; } catch { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void ExportAllButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var settings = SettingsManager.Load();
|
|
||||||
string ext = ExtJson.IsChecked == true ? ".json" : ExtXml.IsChecked == true ? ".xml" : ".csv";
|
|
||||||
var dlg = new Microsoft.Win32.SaveFileDialog() { FileName = "auctions_export" + ext, Filter = "CSV files|*.csv|JSON files|*.json|XML files|*.xml|All files|*.*" };
|
|
||||||
if (dlg.ShowDialog(this) != true) return;
|
|
||||||
var path = dlg.FileName;
|
|
||||||
|
|
||||||
var all = _auctionMonitor.GetAuctions();
|
|
||||||
var includeOpen = (this.FindName("ExportOpenToolbar") as System.Windows.Controls.CheckBox)?.IsChecked == true;
|
|
||||||
var includeClosed = (this.FindName("ExportClosedToolbar") as System.Windows.Controls.CheckBox)?.IsChecked == true;
|
|
||||||
var includeUnknown = (this.FindName("ExportUnknownToolbar") as System.Windows.Controls.CheckBox)?.IsChecked == true;
|
|
||||||
|
|
||||||
var selection = all.Where(a =>
|
|
||||||
(includeOpen && a.IsActive) ||
|
|
||||||
(includeClosed && !a.IsActive) ||
|
|
||||||
(includeUnknown && ((a.BidHistory == null || a.BidHistory.Count == 0) && (a.BidderStats == null || a.BidderStats.Count == 0)))
|
|
||||||
).ToList();
|
|
||||||
|
|
||||||
if (selection.Count == 0)
|
|
||||||
{
|
|
||||||
MessageBox.Show(this, "Nessuna asta da esportare.", "Esporta Aste", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log("[INFO] Esportazione in corso...", LogLevel.Info);
|
|
||||||
|
|
||||||
await Task.Run(() =>
|
|
||||||
{
|
|
||||||
if (path.EndsWith(".json", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
var json = System.Text.Json.JsonSerializer.Serialize(selection, new System.Text.Json.JsonSerializerOptions { WriteIndented = true });
|
|
||||||
File.WriteAllText(path, json, Encoding.UTF8);
|
|
||||||
}
|
|
||||||
else if (path.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
var doc = new XDocument(new XElement("Auctions",
|
|
||||||
from a in selection
|
|
||||||
select new XElement("Auction",
|
|
||||||
new XElement("AuctionId", a.AuctionId),
|
|
||||||
new XElement("Name", a.Name),
|
|
||||||
new XElement("OriginalUrl", a.OriginalUrl ?? string.Empty)
|
|
||||||
)
|
|
||||||
));
|
|
||||||
doc.Save(path);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CsvExporter.ExportAllAuctions(selection, path);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
try { ExportPreferences.SaveLastExportExtension(Path.GetExtension(path)); } catch { }
|
|
||||||
|
|
||||||
MessageBox.Show(this, "Esportazione completata.", "Esporta Aste", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
||||||
Log($"[EXPORT] Aste esportate -> {path}", LogLevel.Success);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log($"[ERRORE] Esportazione massiva: {ex.Message}", LogLevel.Error);
|
|
||||||
MessageBox.Show(this, "Errore durante esportazione: " + ex.Message, "Esporta Aste", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void ExportToolbarButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var settings = SettingsManager.Load();
|
|
||||||
var chosenExt = ExtJson.IsChecked == true ? ".json" : ExtXml.IsChecked == true ? ".xml" : ".csv";
|
|
||||||
|
|
||||||
var includeOpen = (this.FindName("ExportOpenToolbar") as System.Windows.Controls.CheckBox)?.IsChecked == true;
|
|
||||||
var includeClosed = (this.FindName("ExportClosedToolbar") as System.Windows.Controls.CheckBox)?.IsChecked == true;
|
|
||||||
var includeUnknown = (this.FindName("ExportUnknownToolbar") as System.Windows.Controls.CheckBox)?.IsChecked == true;
|
|
||||||
|
|
||||||
var all = _auctionMonitor.GetAuctions();
|
|
||||||
var selection = all.Where(a =>
|
|
||||||
(includeOpen && a.IsActive) ||
|
|
||||||
(includeClosed && !a.IsActive) ||
|
|
||||||
(includeUnknown && ((a.BidHistory == null || a.BidHistory.Count == 0) && (a.BidderStats == null || a.BidderStats.Count == 0)))
|
|
||||||
).ToList();
|
|
||||||
|
|
||||||
if (selection.Count == 0)
|
|
||||||
{
|
|
||||||
MessageBox.Show(this, "Nessuna asta da esportare.", "Esporta Aste", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string folder;
|
|
||||||
if (!string.IsNullOrWhiteSpace(settings?.ExportPath) && Directory.Exists(settings.ExportPath))
|
|
||||||
{
|
|
||||||
folder = settings.ExportPath!;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show(this, "Percorso export non configurato o non valido.\nConfigura il percorso nelle Impostazioni.", "Percorso Export", MessageBoxButton.OK, MessageBoxImage.Warning);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var confirm = MessageBox.Show(this, $"Esportare {selection.Count} asta/e in:\n{folder}\n\nFormato: {chosenExt.ToUpperInvariant()}\n(Un file separato per ogni asta)", "Conferma Esportazione", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
|
||||||
if (confirm != MessageBoxResult.Yes) return;
|
|
||||||
|
|
||||||
Log("[INFO] Esportazione in corso...", LogLevel.Info);
|
|
||||||
|
|
||||||
int exported = 0;
|
|
||||||
int skipped = 0;
|
|
||||||
|
|
||||||
await Task.Run(() =>
|
|
||||||
{
|
|
||||||
foreach (var a in selection)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var filename = $"auction_{a.AuctionId}{chosenExt}";
|
|
||||||
var path = Path.Combine(folder, filename);
|
|
||||||
|
|
||||||
if (File.Exists(path) && settings != null && settings.OverwriteExisting != true)
|
|
||||||
{
|
|
||||||
skipped++;
|
|
||||||
Log($"[SKIP] File già esistente: {filename}", LogLevel.Warn);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosenExt.Equals(".json", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
// JSON EXPORT - AGGIORNATO
|
|
||||||
var obj = new
|
|
||||||
{
|
|
||||||
AuctionId = a.AuctionId,
|
|
||||||
Name = a.Name,
|
|
||||||
OriginalUrl = a.OriginalUrl,
|
|
||||||
MinPrice = a.MinPrice,
|
|
||||||
MaxPrice = a.MaxPrice,
|
|
||||||
BidBeforeDeadlineMs = a.BidBeforeDeadlineMs,
|
|
||||||
CheckAuctionOpenBeforeBid = a.CheckAuctionOpenBeforeBid,
|
|
||||||
IsActive = a.IsActive,
|
|
||||||
IsPaused = a.IsPaused,
|
|
||||||
BidHistory = a.BidHistory,
|
|
||||||
Bidders = a.BidderStats.Values.ToList(),
|
|
||||||
AuctionLog = a.AuctionLog.ToList()
|
|
||||||
};
|
|
||||||
var json = System.Text.Json.JsonSerializer.Serialize(obj, new System.Text.Json.JsonSerializerOptions { WriteIndented = true });
|
|
||||||
File.WriteAllText(path, json, Encoding.UTF8);
|
|
||||||
}
|
|
||||||
else if (chosenExt.Equals(".xml", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
// XML EXPORT - AGGIORNATO
|
|
||||||
var doc = new XDocument(
|
|
||||||
new XElement("AuctionExport",
|
|
||||||
new XElement("Metadata",
|
|
||||||
new XElement("AuctionId", a.AuctionId),
|
|
||||||
new XElement("Name", a.Name ?? string.Empty),
|
|
||||||
new XElement("OriginalUrl", a.OriginalUrl ?? string.Empty),
|
|
||||||
new XElement("MinPrice", a.MinPrice),
|
|
||||||
new XElement("MaxPrice", a.MaxPrice),
|
|
||||||
new XElement("BidBeforeDeadlineMs", a.BidBeforeDeadlineMs),
|
|
||||||
new XElement("CheckAuctionOpenBeforeBid", a.CheckAuctionOpenBeforeBid),
|
|
||||||
new XElement("IsActive", a.IsActive),
|
|
||||||
new XElement("IsPaused", a.IsPaused)
|
|
||||||
),
|
|
||||||
new XElement("FinalPrice", a.BidHistory?.LastOrDefault()?.Price.ToString("F2", CultureInfo.InvariantCulture) ?? string.Empty),
|
|
||||||
new XElement("TotalBids", a.BidHistory?.Count ?? 0),
|
|
||||||
new XElement("Bidders",
|
|
||||||
from b in a.BidderStats.Values.Where(x => x.BidCount > 0)
|
|
||||||
select new XElement("Bidder",
|
|
||||||
new XAttribute("Username", b.Username ?? string.Empty),
|
|
||||||
new XAttribute("BidCount", b.BidCount),
|
|
||||||
new XElement("LastBidTime", b.LastBidTimeDisplay ?? string.Empty)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
new XElement("AuctionLog",
|
|
||||||
from l in a.AuctionLog
|
|
||||||
select new XElement("Entry", l)
|
|
||||||
),
|
|
||||||
new XElement("BidHistory",
|
|
||||||
from bh in a.BidHistory
|
|
||||||
select new XElement("Entry",
|
|
||||||
new XElement("Timestamp", bh.Timestamp.ToString("o")),
|
|
||||||
new XElement("EventType", bh.EventType),
|
|
||||||
new XElement("Bidder", bh.Bidder),
|
|
||||||
new XElement("Price", bh.Price.ToString("F2", CultureInfo.InvariantCulture)),
|
|
||||||
new XElement("Timer", bh.Timer.ToString("F2", CultureInfo.InvariantCulture)),
|
|
||||||
new XElement("LatencyMs", bh.LatencyMs),
|
|
||||||
new XElement("Success", bh.Success),
|
|
||||||
new XElement("Notes", bh.Notes)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
doc.Save(path);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// CSV EXPORT - AGGIORNATO
|
|
||||||
using var sw = new StreamWriter(path, false, Encoding.UTF8);
|
|
||||||
sw.WriteLine("Field,Value");
|
|
||||||
sw.WriteLine($"AuctionId,{a.AuctionId}");
|
|
||||||
sw.WriteLine($"Name,\"{EscapeCsv(a.Name)}\"");
|
|
||||||
sw.WriteLine($"OriginalUrl,\"{EscapeCsv(a.OriginalUrl)}\"");
|
|
||||||
sw.WriteLine($"MinPrice,{a.MinPrice}");
|
|
||||||
sw.WriteLine($"MaxPrice,{a.MaxPrice}");
|
|
||||||
sw.WriteLine($"BidBeforeDeadlineMs,{a.BidBeforeDeadlineMs}");
|
|
||||||
sw.WriteLine($"CheckAuctionOpenBeforeBid,{a.CheckAuctionOpenBeforeBid}");
|
|
||||||
sw.WriteLine($"IsActive,{a.IsActive}");
|
|
||||||
sw.WriteLine($"IsPaused,{a.IsPaused}");
|
|
||||||
sw.WriteLine();
|
|
||||||
sw.WriteLine("--Auction Log--");
|
|
||||||
sw.WriteLine("Message");
|
|
||||||
foreach (var l in a.AuctionLog)
|
|
||||||
{
|
|
||||||
sw.WriteLine($"\"{EscapeCsv(l)}\"");
|
|
||||||
}
|
|
||||||
sw.WriteLine();
|
|
||||||
sw.WriteLine("--Bidders--");
|
|
||||||
sw.WriteLine("Username,BidCount,LastBidTime");
|
|
||||||
foreach (var b in a.BidderStats.Values)
|
|
||||||
{
|
|
||||||
sw.WriteLine($"\"{EscapeCsv(b.Username)}\",{b.BidCount},\"{EscapeCsv(b.LastBidTimeDisplay)}\"");
|
|
||||||
}
|
|
||||||
sw.WriteLine();
|
|
||||||
sw.WriteLine("--BidHistory--");
|
|
||||||
sw.WriteLine("Timestamp,EventType,Bidder,Price,Timer,LatencyMs,Success,Notes");
|
|
||||||
foreach (var bh in a.BidHistory)
|
|
||||||
{
|
|
||||||
sw.WriteLine($"\"{EscapeCsv(bh.Timestamp.ToString("o"))}\",{bh.EventType},\"{EscapeCsv(bh.Bidder)}\",{bh.Price:F2},{bh.Timer:F2},{bh.LatencyMs},{bh.Success},\"{EscapeCsv(bh.Notes)}\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exported++;
|
|
||||||
Log($"[EXPORT] Asta esportata -> {path}", LogLevel.Success);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log($"[ERRORE] Export asta {a.AuctionId}: {ex.Message}", LogLevel.Error);
|
|
||||||
skipped++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
try { ExportPreferences.SaveLastExportExtension(chosenExt); } catch { }
|
|
||||||
|
|
||||||
MessageBox.Show(this, $"Esportazione completata.\n\nEsportate: {exported}\nIgnorate: {skipped}\nPercorso: {folder}", "Esporta Aste", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
||||||
Log($"[EXPORT] Completato: {exported} esportate, {skipped} ignorate -> {folder}", LogLevel.Success);
|
|
||||||
|
|
||||||
if ((this.FindName("RemoveAfterExport") as System.Windows.Controls.CheckBox)?.IsChecked == true && selection.Count > 0)
|
|
||||||
{
|
|
||||||
Dispatcher.Invoke(() =>
|
|
||||||
{
|
|
||||||
foreach (var a in selection)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_auctionMonitor.RemoveAuction(a.AuctionId);
|
|
||||||
var vm = _auctionViewModels.FirstOrDefault(x => x.AuctionId == a.AuctionId);
|
|
||||||
if (vm != null)
|
|
||||||
{
|
|
||||||
_auctionViewModels.Remove(vm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log($"[WARN] Errore rimozione asta {a.AuctionId}: {ex.Message}", LogLevel.Warn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SaveAuctions();
|
|
||||||
UpdateTotalCount();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log($"[ERRORE] Esportazione toolbar: {ex.Message}", LogLevel.Error);
|
|
||||||
MessageBox.Show(this, "Errore durante esportazione: " + ex.Message, "Esporta Aste", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExportBrowseButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
var dlg = new Microsoft.Win32.SaveFileDialog() { FileName = "export.csv", Filter = "CSV files|*.csv|All files|*.*" };
|
|
||||||
if (dlg.ShowDialog(this) == true)
|
|
||||||
{
|
|
||||||
ExportPathTextBox.Text = Path.GetDirectoryName(dlg.FileName) ?? string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string EscapeCsv(string? value)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(value)) return string.Empty;
|
|
||||||
return value.Replace("\"", "\"\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -36,6 +36,33 @@ namespace AutoBidder
|
|||||||
// ?? NUOVO: Carica limite minimo puntate
|
// ?? NUOVO: Carica limite minimo puntate
|
||||||
MinimumRemainingBidsTextBox.Text = settings.MinimumRemainingBids.ToString();
|
MinimumRemainingBidsTextBox.Text = settings.MinimumRemainingBids.ToString();
|
||||||
|
|
||||||
|
// ?? NUOVO: Carica livello log
|
||||||
|
var logLevelErrorOnly = Settings.FindName("LogLevelErrorOnly") as System.Windows.Controls.RadioButton;
|
||||||
|
var logLevelNormal = Settings.FindName("LogLevelNormal") as System.Windows.Controls.RadioButton;
|
||||||
|
var logLevelInformational = Settings.FindName("LogLevelInformational") as System.Windows.Controls.RadioButton;
|
||||||
|
var logLevelDebug = Settings.FindName("LogLevelDebug") as System.Windows.Controls.RadioButton;
|
||||||
|
var logLevelTrace = Settings.FindName("LogLevelTrace") as System.Windows.Controls.RadioButton;
|
||||||
|
|
||||||
|
switch (settings.MinLogLevel)
|
||||||
|
{
|
||||||
|
case "ErrorOnly":
|
||||||
|
if (logLevelErrorOnly != null) logLevelErrorOnly.IsChecked = true;
|
||||||
|
break;
|
||||||
|
case "Informational":
|
||||||
|
if (logLevelInformational != null) logLevelInformational.IsChecked = true;
|
||||||
|
break;
|
||||||
|
case "Debug":
|
||||||
|
if (logLevelDebug != null) logLevelDebug.IsChecked = true;
|
||||||
|
break;
|
||||||
|
case "Trace":
|
||||||
|
if (logLevelTrace != null) logLevelTrace.IsChecked = true;
|
||||||
|
break;
|
||||||
|
case "Normal":
|
||||||
|
default:
|
||||||
|
if (logLevelNormal != null) logLevelNormal.IsChecked = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Aggiorna indicatore visivo
|
// Aggiorna indicatore visivo
|
||||||
UpdateMinBidsIndicator(settings.MinimumRemainingBids);
|
UpdateMinBidsIndicator(settings.MinimumRemainingBids);
|
||||||
|
|
||||||
@@ -85,67 +112,6 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveSettingsButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// ? Carica le impostazioni esistenti per non perdere gli altri valori
|
|
||||||
var settings = Utilities.SettingsManager.Load() ?? new Utilities.AppSettings();
|
|
||||||
|
|
||||||
// === SEZIONE EXPORT: Percorso e Formato ===
|
|
||||||
settings.ExportPath = ExportPathTextBox.Text;
|
|
||||||
settings.LastExportExt = ExtJson.IsChecked == true ? ".json" : ExtXml.IsChecked == true ? ".xml" : ".csv";
|
|
||||||
|
|
||||||
// === SEZIONE EXPORT: Scope (Aste da esportare) ===
|
|
||||||
var cbClosed = this.FindName("ExportClosedToolbar") as System.Windows.Controls.CheckBox;
|
|
||||||
var cbUnknown = this.FindName("ExportUnknownToolbar") as System.Windows.Controls.CheckBox;
|
|
||||||
var cbOpen = this.FindName("ExportOpenToolbar") as System.Windows.Controls.CheckBox;
|
|
||||||
|
|
||||||
var scope = "All";
|
|
||||||
if (cbClosed != null && cbClosed.IsChecked == true) scope = "Closed";
|
|
||||||
else if (cbUnknown != null && cbUnknown.IsChecked == true) scope = "Unknown";
|
|
||||||
else if (cbOpen != null && cbOpen.IsChecked == true) scope = "Open";
|
|
||||||
|
|
||||||
settings.ExportScope = scope;
|
|
||||||
settings.ExportOpen = cbOpen?.IsChecked ?? true;
|
|
||||||
settings.ExportClosed = cbClosed?.IsChecked ?? true;
|
|
||||||
settings.ExportUnknown = cbUnknown?.IsChecked ?? true;
|
|
||||||
|
|
||||||
// === SEZIONE EXPORT: Opzioni ? FIX: Aggiunte le 3 checkbox mancanti ===
|
|
||||||
settings.IncludeOnlyUsedBids = IncludeUsedBids.IsChecked == true;
|
|
||||||
settings.IncludeLogs = IncludeLogs.IsChecked == true;
|
|
||||||
settings.IncludeUserBids = IncludeUserBids.IsChecked == true;
|
|
||||||
settings.IncludeMetadata = IncludeMetadata.IsChecked == true; // ? AGGIUNTO
|
|
||||||
settings.RemoveAfterExport = RemoveAfterExport.IsChecked == true; // ? AGGIUNTO
|
|
||||||
settings.OverwriteExisting = OverwriteExisting.IsChecked == true; // ? AGGIUNTO
|
|
||||||
|
|
||||||
SettingsManager.Save(settings);
|
|
||||||
ExportPreferences.SaveLastExportExtension(settings.LastExportExt);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log($"[ERRORE] Salvataggio impostazioni export: {ex.Message}", LogLevel.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CancelSettingsButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Ricarica impostazioni export
|
|
||||||
LoadExportSettings();
|
|
||||||
|
|
||||||
// NOTA: Reload cookie RIMOSSO - ora automatico tramite browser
|
|
||||||
|
|
||||||
MessageBox.Show(this, "Impostazioni ripristinate alle ultime salvate.", "Annulla", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log($"[ERRORE] Ripristino impostazioni: {ex.Message}", LogLevel.Error);
|
|
||||||
MessageBox.Show(this, "Errore durante ripristino: " + ex.Message, "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveDefaultsButton_Click(object sender, RoutedEventArgs e)
|
private void SaveDefaultsButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -239,6 +205,29 @@ namespace AutoBidder
|
|||||||
Log("[ERRORE] Valore limite minimo puntate non valido (deve essere >= 0)", LogLevel.Error);
|
Log("[ERRORE] Valore limite minimo puntate non valido (deve essere >= 0)", LogLevel.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ?? NUOVO: Salva livello log
|
||||||
|
var logLevelErrorOnly = Settings.FindName("LogLevelErrorOnly") as System.Windows.Controls.RadioButton;
|
||||||
|
var logLevelNormal = Settings.FindName("LogLevelNormal") as System.Windows.Controls.RadioButton;
|
||||||
|
var logLevelInformational = Settings.FindName("LogLevelInformational") as System.Windows.Controls.RadioButton;
|
||||||
|
var logLevelDebug = Settings.FindName("LogLevelDebug") as System.Windows.Controls.RadioButton;
|
||||||
|
var logLevelTrace = Settings.FindName("LogLevelTrace") as System.Windows.Controls.RadioButton;
|
||||||
|
|
||||||
|
string selectedLogLevel = "Normal"; // Default
|
||||||
|
if (logLevelErrorOnly?.IsChecked == true)
|
||||||
|
selectedLogLevel = "ErrorOnly";
|
||||||
|
else if (logLevelInformational?.IsChecked == true)
|
||||||
|
selectedLogLevel = "Informational";
|
||||||
|
else if (logLevelDebug?.IsChecked == true)
|
||||||
|
selectedLogLevel = "Debug";
|
||||||
|
else if (logLevelTrace?.IsChecked == true)
|
||||||
|
selectedLogLevel = "Trace";
|
||||||
|
else if (logLevelNormal?.IsChecked == true)
|
||||||
|
selectedLogLevel = "Normal";
|
||||||
|
|
||||||
|
settings.MinLogLevel = selectedLogLevel;
|
||||||
|
|
||||||
|
Log($"[LOG] Livello log impostato: {selectedLogLevel}", LogLevel.Info);
|
||||||
|
|
||||||
// === SEZIONE DEFAULTS: Stati Iniziali Aste ===
|
// === SEZIONE DEFAULTS: Stati Iniziali Aste ===
|
||||||
var loadAuctionsRemember = Settings.FindName("LoadAuctionsRemember") as System.Windows.Controls.RadioButton;
|
var loadAuctionsRemember = Settings.FindName("LoadAuctionsRemember") as System.Windows.Controls.RadioButton;
|
||||||
var loadAuctionsActive = Settings.FindName("LoadAuctionsActive") as System.Windows.Controls.RadioButton;
|
var loadAuctionsActive = Settings.FindName("LoadAuctionsActive") as System.Windows.Controls.RadioButton;
|
||||||
@@ -290,5 +279,43 @@ namespace AutoBidder
|
|||||||
MessageBox.Show(this, "Errore durante ripristino: " + ex.Message, "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
MessageBox.Show(this, "Errore durante ripristino: " + ex.Message, "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === HANDLER PER PULSANTI UNIFICATI ===
|
||||||
|
|
||||||
|
private void SaveAllSettings_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Salva tutte le impostazioni (ora solo defaults, export rimosso)
|
||||||
|
SaveDefaultsButton_Click(sender, e);
|
||||||
|
|
||||||
|
MessageBox.Show(
|
||||||
|
"Tutte le impostazioni sono state salvate con successo.\n\nLe nuove impostazioni verranno applicate alle aste future.",
|
||||||
|
"Impostazioni Salvate",
|
||||||
|
MessageBoxButton.OK,
|
||||||
|
MessageBoxImage.Information
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log($"[ERRORE] Salvataggio impostazioni: {ex.Message}", LogLevel.Error);
|
||||||
|
MessageBox.Show(this, "Errore durante salvataggio: " + ex.Message, "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CancelAllSettings_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Annulla tutte le modifiche
|
||||||
|
LoadDefaultSettings();
|
||||||
|
MessageBox.Show(this, "Impostazioni ripristinate alle ultime salvate.", "Annulla", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log($"[ERRORE] Ripristino impostazioni: {ex.Message}", LogLevel.Error);
|
||||||
|
MessageBox.Show(this, "Errore durante ripristino: " + ex.Message, "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using AutoBidder.Models;
|
using AutoBidder.Models;
|
||||||
using AutoBidder.ViewModels;
|
using AutoBidder.ViewModels;
|
||||||
using AutoBidder.Utilities;
|
using AutoBidder.Utilities;
|
||||||
using AutoBidder.Services; // ✅ AGGIUNTO per RequestPriority e HtmlResponse
|
using AutoBidder.Services; // ? AGGIUNTO per RequestPriority e HtmlResponse
|
||||||
|
|
||||||
namespace AutoBidder
|
namespace AutoBidder
|
||||||
{
|
{
|
||||||
@@ -28,10 +28,10 @@ namespace AutoBidder
|
|||||||
string? productName = null;
|
string? productName = null;
|
||||||
string originalUrl;
|
string originalUrl;
|
||||||
|
|
||||||
// Verifica se è un URL o solo un ID
|
// Verifica se è un URL o solo un ID
|
||||||
if (input.Contains("bidoo.com") || input.Contains("http"))
|
if (input.Contains("bidoo.com") || input.Contains("http"))
|
||||||
{
|
{
|
||||||
// È un URL - estrai ID e nome prodotto dall'URL stesso
|
// È un URL - estrai ID e nome prodotto dall'URL stesso
|
||||||
originalUrl = input.Trim();
|
originalUrl = input.Trim();
|
||||||
auctionId = ExtractAuctionId(originalUrl);
|
auctionId = ExtractAuctionId(originalUrl);
|
||||||
if (string.IsNullOrEmpty(auctionId))
|
if (string.IsNullOrEmpty(auctionId))
|
||||||
@@ -44,7 +44,7 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// È solo un ID numerico - costruisci URL generico
|
// È solo un ID numerico - costruisci URL generico
|
||||||
auctionId = input.Trim();
|
auctionId = input.Trim();
|
||||||
originalUrl = $"https://it.bidoo.com/auction.php?a=asta_{auctionId}";
|
originalUrl = $"https://it.bidoo.com/auction.php?a=asta_{auctionId}";
|
||||||
}
|
}
|
||||||
@@ -52,11 +52,11 @@ namespace AutoBidder
|
|||||||
// Verifica duplicati
|
// Verifica duplicati
|
||||||
if (_auctionViewModels.Any(a => a.AuctionId == auctionId))
|
if (_auctionViewModels.Any(a => a.AuctionId == auctionId))
|
||||||
{
|
{
|
||||||
MessageBox.Show("Asta già monitorata!", "Duplicato", MessageBoxButton.OK, MessageBoxImage.Information);
|
MessageBox.Show("Asta già monitorata!", "Duplicato", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ MODIFICATO: Nome senza ID (già nella colonna separata)
|
// ? MODIFICATO: Nome senza ID (già nella colonna separata)
|
||||||
var displayName = string.IsNullOrEmpty(productName)
|
var displayName = string.IsNullOrEmpty(productName)
|
||||||
? $"Asta {auctionId}"
|
? $"Asta {auctionId}"
|
||||||
: DecodeAllHtmlEntities(productName);
|
: DecodeAllHtmlEntities(productName);
|
||||||
@@ -64,7 +64,7 @@ namespace AutoBidder
|
|||||||
// CARICA IMPOSTAZIONI PREDEFINITE SALVATE
|
// CARICA IMPOSTAZIONI PREDEFINITE SALVATE
|
||||||
var settings = Utilities.SettingsManager.Load();
|
var settings = Utilities.SettingsManager.Load();
|
||||||
|
|
||||||
// ✅ Determina stato iniziale dalla configurazione
|
// ? Determina stato iniziale dalla configurazione
|
||||||
bool isActive = false;
|
bool isActive = false;
|
||||||
bool isPaused = false;
|
bool isPaused = false;
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ namespace AutoBidder
|
|||||||
};
|
};
|
||||||
_auctionViewModels.Add(vm);
|
_auctionViewModels.Add(vm);
|
||||||
|
|
||||||
// ✅ Auto-start del monitoraggio se l'asta è attiva e il monitoraggio è fermo
|
// ? Auto-start del monitoraggio se l'asta è attiva e il monitoraggio è fermo
|
||||||
if (isActive && !_isAutomationActive)
|
if (isActive && !_isAutomationActive)
|
||||||
{
|
{
|
||||||
_auctionMonitor.Start();
|
_auctionMonitor.Start();
|
||||||
@@ -124,7 +124,7 @@ namespace AutoBidder
|
|||||||
var stateText = isActive ? (isPaused ? "Paused" : "Active") : "Stopped";
|
var stateText = isActive ? (isPaused ? "Paused" : "Active") : "Stopped";
|
||||||
Log($"[ADD] Asta aggiunta con stato={stateText}, Anticipo={settings.DefaultBidBeforeDeadlineMs}ms", Utilities.LogLevel.Info);
|
Log($"[ADD] Asta aggiunta con stato={stateText}, Anticipo={settings.DefaultBidBeforeDeadlineMs}ms", Utilities.LogLevel.Info);
|
||||||
|
|
||||||
// ✅ NUOVO: Se il nome non è stato estratto, recuperalo in background DOPO l'aggiunta
|
// ? NUOVO: Se il nome non è stato estratto, recuperalo in background DOPO l'aggiunta
|
||||||
if (string.IsNullOrEmpty(productName))
|
if (string.IsNullOrEmpty(productName))
|
||||||
{
|
{
|
||||||
_ = FetchAuctionNameInBackgroundAsync(auction, vm);
|
_ = FetchAuctionNameInBackgroundAsync(auction, vm);
|
||||||
@@ -144,7 +144,7 @@ namespace AutoBidder
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// ✅ USA IL SERVIZIO CENTRALIZZATO invece di HttpClient diretto
|
// ? USA IL SERVIZIO CENTRALIZZATO invece di HttpClient diretto
|
||||||
var response = await _htmlCacheService.GetHtmlAsync(
|
var response = await _htmlCacheService.GetHtmlAsync(
|
||||||
auction.OriginalUrl,
|
auction.OriginalUrl,
|
||||||
RequestPriority.Normal,
|
RequestPriority.Normal,
|
||||||
@@ -153,7 +153,7 @@ namespace AutoBidder
|
|||||||
|
|
||||||
if (!response.Success)
|
if (!response.Success)
|
||||||
{
|
{
|
||||||
Log($"[WARN] Impossibile recuperare nome per asta {auction.AuctionId}: {response.Error}", LogLevel.Warn);
|
Log($"[WARN] Impossibile recuperare nome per asta {auction.AuctionId}: {response.Error}", LogLevel.Warning);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,9 +163,9 @@ namespace AutoBidder
|
|||||||
if (match.Success)
|
if (match.Success)
|
||||||
{
|
{
|
||||||
var productName = match.Groups[1].Value.Trim().Replace(" - Bidoo", "");
|
var productName = match.Groups[1].Value.Trim().Replace(" - Bidoo", "");
|
||||||
// ✅ Decodifica entity HTML (incluse quelle non standard)
|
// ? Decodifica entity HTML (incluse quelle non standard)
|
||||||
productName = DecodeAllHtmlEntities(productName);
|
productName = DecodeAllHtmlEntities(productName);
|
||||||
// ✅ MODIFICATO: Nome senza ID
|
// ? MODIFICATO: Nome senza ID
|
||||||
var newName = productName;
|
var newName = productName;
|
||||||
|
|
||||||
// Aggiorna il nome su thread UI
|
// Aggiorna il nome su thread UI
|
||||||
@@ -182,12 +182,12 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log($"[WARN] Nome non trovato nell'HTML per asta {auction.AuctionId}", LogLevel.Warn);
|
Log($"[WARN] Nome non trovato nell'HTML per asta {auction.AuctionId}", LogLevel.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log($"[WARN] Errore recupero nome per asta {auction.AuctionId}: {ex.Message}", LogLevel.Warn);
|
Log($"[WARN] Errore recupero nome per asta {auction.AuctionId}: {ex.Message}", LogLevel.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,16 +202,16 @@ namespace AutoBidder
|
|||||||
// Prima decodifica entity standard
|
// Prima decodifica entity standard
|
||||||
var decoded = System.Net.WebUtility.HtmlDecode(text);
|
var decoded = System.Net.WebUtility.HtmlDecode(text);
|
||||||
|
|
||||||
// ✅ Poi sostituisci entity non standard che WebUtility.HtmlDecode non gestisce
|
// ? Poi sostituisci entity non standard che WebUtility.HtmlDecode non gestisce
|
||||||
decoded = decoded.Replace("+", "+");
|
decoded = decoded.Replace("+", "+");
|
||||||
decoded = decoded.Replace("=", "=");
|
decoded = decoded.Replace("=", "=");
|
||||||
decoded = decoded.Replace("−", "-");
|
decoded = decoded.Replace("−", "-");
|
||||||
decoded = decoded.Replace("×", "×");
|
decoded = decoded.Replace("×", "×");
|
||||||
decoded = decoded.Replace("÷", "÷");
|
decoded = decoded.Replace("÷", "÷");
|
||||||
decoded = decoded.Replace("%", "%");
|
decoded = decoded.Replace("%", "%");
|
||||||
decoded = decoded.Replace("$", "$");
|
decoded = decoded.Replace("$", "$");
|
||||||
decoded = decoded.Replace("€", "€");
|
decoded = decoded.Replace("€", "€");
|
||||||
decoded = decoded.Replace("£", "£");
|
decoded = decoded.Replace("£", "£");
|
||||||
|
|
||||||
return decoded;
|
return decoded;
|
||||||
}
|
}
|
||||||
@@ -236,7 +236,7 @@ namespace AutoBidder
|
|||||||
// Verifica duplicati
|
// Verifica duplicati
|
||||||
if (_auctionViewModels.Any(a => a.AuctionId == auctionId))
|
if (_auctionViewModels.Any(a => a.AuctionId == auctionId))
|
||||||
{
|
{
|
||||||
MessageBox.Show("Asta già monitorata!", "Duplicato", MessageBoxButton.OK, MessageBoxImage.Information);
|
MessageBox.Show("Asta già monitorata!", "Duplicato", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ namespace AutoBidder
|
|||||||
var name = $"Asta {auctionId}";
|
var name = $"Asta {auctionId}";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// ✅ USA IL SERVIZIO CENTRALIZZATO
|
// ? USA IL SERVIZIO CENTRALIZZATO
|
||||||
var response = await _htmlCacheService.GetHtmlAsync(url, RequestPriority.Normal);
|
var response = await _htmlCacheService.GetHtmlAsync(url, RequestPriority.Normal);
|
||||||
|
|
||||||
if (response.Success)
|
if (response.Success)
|
||||||
@@ -261,7 +261,7 @@ namespace AutoBidder
|
|||||||
// CARICA IMPOSTAZIONI PREDEFINITE SALVATE
|
// CARICA IMPOSTAZIONI PREDEFINITE SALVATE
|
||||||
var settings = Utilities.SettingsManager.Load();
|
var settings = Utilities.SettingsManager.Load();
|
||||||
|
|
||||||
// ✅ Determina stato iniziale dalla configurazione
|
// ? Determina stato iniziale dalla configurazione
|
||||||
bool isActive = false;
|
bool isActive = false;
|
||||||
bool isPaused = false;
|
bool isPaused = false;
|
||||||
|
|
||||||
@@ -306,7 +306,7 @@ namespace AutoBidder
|
|||||||
};
|
};
|
||||||
_auctionViewModels.Add(vm);
|
_auctionViewModels.Add(vm);
|
||||||
|
|
||||||
// ✅ Auto-start del monitoraggio se l'asta è attiva e il monitoraggio è fermo
|
// ? Auto-start del monitoraggio se l'asta è attiva e il monitoraggio è fermo
|
||||||
if (isActive && !_isAutomationActive)
|
if (isActive && !_isAutomationActive)
|
||||||
{
|
{
|
||||||
_auctionMonitor.Start();
|
_auctionMonitor.Start();
|
||||||
@@ -353,12 +353,12 @@ namespace AutoBidder
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Aspetta 30 secondi prima di ritentare (dà tempo alle altre richieste di completare)
|
// Aspetta 30 secondi prima di ritentare (dà tempo alle altre richieste di completare)
|
||||||
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(30));
|
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(30));
|
||||||
|
|
||||||
// Trova aste con nomi generici "Asta XXXX"
|
// Trova aste con nomi generici "Asta XXXX"
|
||||||
var auctionsWithGenericNames = _auctionViewModels
|
var auctionsWithGenericNames = _auctionViewModels
|
||||||
.Where(vm => vm.Name.StartsWith("Asta ") && !vm.Name.Contains("Shop") && !vm.Name.Contains("€"))
|
.Where(vm => vm.Name.StartsWith("Asta ") && !vm.Name.Contains("Shop") && !vm.Name.Contains("€"))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (auctionsWithGenericNames.Count > 0)
|
if (auctionsWithGenericNames.Count > 0)
|
||||||
@@ -375,7 +375,7 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log($"[WARN] Errore retry nomi aste: {ex.Message}", LogLevel.Warn);
|
Log($"[WARN] Errore retry nomi aste: {ex.Message}", LogLevel.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,7 +396,7 @@ namespace AutoBidder
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// ✅ Carica impostazioni
|
// ? Carica impostazioni
|
||||||
var settings = Utilities.SettingsManager.Load();
|
var settings = Utilities.SettingsManager.Load();
|
||||||
|
|
||||||
// Ottieni username corrente dalla sessione per ripristinare IsMyBid
|
// Ottieni username corrente dalla sessione per ripristinare IsMyBid
|
||||||
@@ -409,10 +409,10 @@ namespace AutoBidder
|
|||||||
// Protezione: rimuovi eventuali BidHistory null
|
// Protezione: rimuovi eventuali BidHistory null
|
||||||
auction.BidHistory = auction.BidHistory?.Where(b => b != null).ToList() ?? new System.Collections.Generic.List<BidHistory>();
|
auction.BidHistory = auction.BidHistory?.Where(b => b != null).ToList() ?? new System.Collections.Generic.List<BidHistory>();
|
||||||
|
|
||||||
// ✅ Decode HTML entities (incluse quelle non standard)
|
// ? Decode HTML entities (incluse quelle non standard)
|
||||||
try { auction.Name = DecodeAllHtmlEntities(auction.Name ?? string.Empty); } catch { }
|
try { auction.Name = DecodeAllHtmlEntities(auction.Name ?? string.Empty); } catch { }
|
||||||
|
|
||||||
// ✅ Ripristina IsMyBid per tutte le puntate in RecentBids
|
// ? Ripristina IsMyBid per tutte le puntate in RecentBids
|
||||||
if (auction.RecentBids != null && auction.RecentBids.Count > 0 && !string.IsNullOrEmpty(currentUsername))
|
if (auction.RecentBids != null && auction.RecentBids.Count > 0 && !string.IsNullOrEmpty(currentUsername))
|
||||||
{
|
{
|
||||||
foreach (var bid in auction.RecentBids)
|
foreach (var bid in auction.RecentBids)
|
||||||
@@ -422,11 +422,11 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ✅ NUOVO: Gestione stato in base a RememberAuctionStates
|
// ? NUOVO: Gestione stato in base a RememberAuctionStates
|
||||||
if (settings.RememberAuctionStates)
|
if (settings.RememberAuctionStates)
|
||||||
{
|
{
|
||||||
// MODO 1: Ripristina lo stato salvato di ogni asta (IsActive e IsPaused vengono dal file salvato)
|
// MODO 1: Ripristina lo stato salvato di ogni asta (IsActive e IsPaused vengono dal file salvato)
|
||||||
// Non serve fare nulla, lo stato è già quello salvato nel file
|
// Non serve fare nulla, lo stato è già quello salvato nel file
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -455,7 +455,7 @@ namespace AutoBidder
|
|||||||
_auctionViewModels.Add(vm);
|
_auctionViewModels.Add(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Avvia monitoraggio se ci sono aste in stato Active O Paused
|
// ? Avvia monitoraggio se ci sono aste in stato Active O Paused
|
||||||
bool hasActiveOrPausedAuctions = auctions.Any(a => a.IsActive);
|
bool hasActiveOrPausedAuctions = auctions.Any(a => a.IsActive);
|
||||||
|
|
||||||
if (hasActiveOrPausedAuctions && auctions.Count > 0)
|
if (hasActiveOrPausedAuctions && auctions.Count > 0)
|
||||||
@@ -538,7 +538,7 @@ namespace AutoBidder
|
|||||||
// Aggiorna Valore (Compra Subito)
|
// Aggiorna Valore (Compra Subito)
|
||||||
if (auction.BuyNowPrice.HasValue)
|
if (auction.BuyNowPrice.HasValue)
|
||||||
{
|
{
|
||||||
AuctionMonitor.ProductBuyNowPriceText.Text = $"{auction.BuyNowPrice.Value:F2}€";
|
AuctionMonitor.ProductBuyNowPriceText.Text = $"{auction.BuyNowPrice.Value:F2}€";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -548,7 +548,7 @@ namespace AutoBidder
|
|||||||
// Aggiorna Spese di Spedizione
|
// Aggiorna Spese di Spedizione
|
||||||
if (auction.ShippingCost.HasValue)
|
if (auction.ShippingCost.HasValue)
|
||||||
{
|
{
|
||||||
AuctionMonitor.ProductShippingCostText.Text = $"{auction.ShippingCost.Value:F2}€";
|
AuctionMonitor.ProductShippingCostText.Text = $"{auction.ShippingCost.Value:F2}€";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -579,28 +579,28 @@ namespace AutoBidder
|
|||||||
{
|
{
|
||||||
bool hasGenericName = auction.Name.StartsWith("Asta ") &&
|
bool hasGenericName = auction.Name.StartsWith("Asta ") &&
|
||||||
!auction.Name.Contains("Shop") &&
|
!auction.Name.Contains("Shop") &&
|
||||||
!auction.Name.Contains("€") &&
|
!auction.Name.Contains("€") &&
|
||||||
!auction.Name.Contains("Buono") &&
|
!auction.Name.Contains("Buono") &&
|
||||||
!auction.Name.Contains("Carburante");
|
!auction.Name.Contains("Carburante");
|
||||||
|
|
||||||
Log($"[PRODUCT INFO] Caricamento automatico per: {auction.Name}{(hasGenericName ? " (+ nome generico)" : "")}", Utilities.LogLevel.Info);
|
Log($"[PRODUCT INFO] Caricamento automatico per: {auction.Name}{(hasGenericName ? " (+ nome generico)" : "")}", Utilities.LogLevel.Info);
|
||||||
|
|
||||||
// ✅ USA IL SERVIZIO CENTRALIZZATO
|
// ? USA IL SERVIZIO CENTRALIZZATO
|
||||||
var response = await _htmlCacheService.GetHtmlAsync(
|
var response = await _htmlCacheService.GetHtmlAsync(
|
||||||
auction.OriginalUrl,
|
auction.OriginalUrl,
|
||||||
RequestPriority.High, // Priorità alta per info prodotto
|
RequestPriority.High, // Priorità alta per info prodotto
|
||||||
bypassCache: false
|
bypassCache: false
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!response.Success)
|
if (!response.Success)
|
||||||
{
|
{
|
||||||
Log($"[PRODUCT INFO] Errore caricamento: {response.Error}", Utilities.LogLevel.Warn);
|
Log($"[PRODUCT INFO] Errore caricamento: {response.Error}", Utilities.LogLevel.Warning);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
|
|
||||||
// 1. ✅ Se nome generico, estrai nome reale dal <title>
|
// 1. ? Se nome generico, estrai nome reale dal <title>
|
||||||
if (hasGenericName)
|
if (hasGenericName)
|
||||||
{
|
{
|
||||||
var matchTitle = System.Text.RegularExpressions.Regex.Match(response.Html, @"<title>([^<]+)</title>");
|
var matchTitle = System.Text.RegularExpressions.Regex.Match(response.Html, @"<title>([^<]+)</title>");
|
||||||
@@ -608,7 +608,7 @@ namespace AutoBidder
|
|||||||
{
|
{
|
||||||
var productName = matchTitle.Groups[1].Value.Trim().Replace(" - Bidoo", "");
|
var productName = matchTitle.Groups[1].Value.Trim().Replace(" - Bidoo", "");
|
||||||
productName = DecodeAllHtmlEntities(productName);
|
productName = DecodeAllHtmlEntities(productName);
|
||||||
// ✅ MODIFICATO: Nome senza ID
|
// ? MODIFICATO: Nome senza ID
|
||||||
var newName = productName;
|
var newName = productName;
|
||||||
|
|
||||||
auction.Name = newName;
|
auction.Name = newName;
|
||||||
@@ -617,15 +617,15 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ✅ Estrai informazioni prodotto (prezzo, spedizione, limiti)
|
// 2. ? Estrai informazioni prodotto (prezzo, spedizione, limiti)
|
||||||
var extracted = Utilities.ProductValueCalculator.ExtractProductInfo(response.Html, auction);
|
var extracted = Utilities.ProductValueCalculator.ExtractProductInfo(response.Html, auction);
|
||||||
if (extracted)
|
if (extracted)
|
||||||
{
|
{
|
||||||
updated = true;
|
updated = true;
|
||||||
Log($"[PRODUCT INFO] Valore={auction.BuyNowPrice:F2}€, Spedizione={auction.ShippingCost:F2}€{(response.FromCache ? " (cached)" : "")}", Utilities.LogLevel.Success);
|
Log($"[PRODUCT INFO] Valore={auction.BuyNowPrice:F2}€, Spedizione={auction.ShippingCost:F2}€{(response.FromCache ? " (cached)" : "")}", Utilities.LogLevel.Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. ✅ Salva e aggiorna UI solo se qualcosa è cambiato
|
// 3. ? Salva e aggiorna UI solo se qualcosa è cambiato
|
||||||
if (updated)
|
if (updated)
|
||||||
{
|
{
|
||||||
SaveAuctions();
|
SaveAuctions();
|
||||||
@@ -650,7 +650,7 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log($"[PRODUCT INFO] Errore caricamento: {ex.Message}", Utilities.LogLevel.Warn);
|
Log($"[PRODUCT INFO] Errore caricamento: {ex.Message}", Utilities.LogLevel.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
@@ -41,7 +41,7 @@ namespace AutoBidder
|
|||||||
Log("[START ALL] Tutte le aste avviate/riprese", LogLevel.Info);
|
Log("[START ALL] Tutte le aste avviate/riprese", LogLevel.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Salva gli stati aggiornati su disco
|
// ? Salva gli stati aggiornati su disco
|
||||||
SaveAuctions();
|
SaveAuctions();
|
||||||
UpdateGlobalControlButtons();
|
UpdateGlobalControlButtons();
|
||||||
}
|
}
|
||||||
@@ -69,13 +69,13 @@ namespace AutoBidder
|
|||||||
_isAutomationActive = false;
|
_isAutomationActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Salva gli stati aggiornati su disco
|
// ? Salva gli stati aggiornati su disco
|
||||||
SaveAuctions();
|
SaveAuctions();
|
||||||
UpdateGlobalControlButtons();
|
UpdateGlobalControlButtons();
|
||||||
|
|
||||||
if (sender != null) // Solo se chiamato dall'utente
|
if (sender != null) // Solo se chiamato dall'utente
|
||||||
{
|
{
|
||||||
Log("[STOP ALL] Monitoraggio fermato e tutte le aste arrestate", LogLevel.Warn);
|
Log("[STOP ALL] Monitoraggio fermato e tutte le aste arrestate", LogLevel.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -93,13 +93,13 @@ namespace AutoBidder
|
|||||||
vm.IsPaused = true;
|
vm.IsPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Salva gli stati aggiornati su disco
|
// ? Salva gli stati aggiornati su disco
|
||||||
SaveAuctions();
|
SaveAuctions();
|
||||||
UpdateGlobalControlButtons();
|
UpdateGlobalControlButtons();
|
||||||
|
|
||||||
if (sender != null) // Solo se chiamato dall'utente
|
if (sender != null) // Solo se chiamato dall'utente
|
||||||
{
|
{
|
||||||
Log("[PAUSE ALL] Tutte le aste in pausa", LogLevel.Warn);
|
Log("[PAUSE ALL] Tutte le aste in pausa", LogLevel.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -166,7 +166,7 @@ namespace AutoBidder
|
|||||||
|
|
||||||
MessageBox.Show(summary, "Aggiunta aste", MessageBoxButton.OK, MessageBoxImage.Information);
|
MessageBox.Show(summary, "Aggiunta aste", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
|
|
||||||
// ✅ RIMOSSO: Retry automatico ora avviene alla selezione on-demand
|
// ? RIMOSSO: Retry automatico ora avviene alla selezione on-demand
|
||||||
// Le aste con nome generico vengono aggiornate automaticamente quando l'utente le seleziona
|
// Le aste con nome generico vengono aggiornate automaticamente quando l'utente le seleziona
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,7 +187,7 @@ namespace AutoBidder
|
|||||||
|
|
||||||
// Conferma rimozione
|
// Conferma rimozione
|
||||||
var result = MessageBox.Show(
|
var result = MessageBox.Show(
|
||||||
$"Rimuovere l'asta dal monitoraggio?\n\n{auctionName}\n(ID: {auctionId})\n\nL'asta verrà eliminata dalla lista e non sarà più monitorata.",
|
$"Rimuovere l'asta dal monitoraggio?\n\n{auctionName}\n(ID: {auctionId})\n\nL'asta verrà eliminata dalla lista e non sarà più monitorata.",
|
||||||
"Conferma Rimozione",
|
"Conferma Rimozione",
|
||||||
MessageBoxButton.YesNo,
|
MessageBoxButton.YesNo,
|
||||||
MessageBoxImage.Question);
|
MessageBoxImage.Question);
|
||||||
@@ -213,10 +213,10 @@ namespace AutoBidder
|
|||||||
|
|
||||||
Log($"[REMOVE] Asta rimossa: {auctionName} (ID: {auctionId})", LogLevel.Success);
|
Log($"[REMOVE] Asta rimossa: {auctionName} (ID: {auctionId})", LogLevel.Success);
|
||||||
|
|
||||||
// ✅ NUOVO: Sposta il focus sulla riga successiva
|
// ? NUOVO: Sposta il focus sulla riga successiva
|
||||||
if (_auctionViewModels.Count > 0)
|
if (_auctionViewModels.Count > 0)
|
||||||
{
|
{
|
||||||
// Se c'è ancora almeno un'asta nella lista
|
// Se c'è ancora almeno un'asta nella lista
|
||||||
int newIndex;
|
int newIndex;
|
||||||
|
|
||||||
if (currentIndex >= _auctionViewModels.Count)
|
if (currentIndex >= _auctionViewModels.Count)
|
||||||
@@ -234,7 +234,7 @@ namespace AutoBidder
|
|||||||
MultiAuctionsGrid.SelectedIndex = newIndex;
|
MultiAuctionsGrid.SelectedIndex = newIndex;
|
||||||
_selectedAuction = _auctionViewModels[newIndex];
|
_selectedAuction = _auctionViewModels[newIndex];
|
||||||
|
|
||||||
// ✅ FIX: Salva il nome della NUOVA asta selezionata per il log
|
// ? FIX: Salva il nome della NUOVA asta selezionata per il log
|
||||||
var newAuctionName = _selectedAuction?.Name ?? "Sconosciuta";
|
var newAuctionName = _selectedAuction?.Name ?? "Sconosciuta";
|
||||||
|
|
||||||
// Forza il focus sulla griglia dopo un breve delay per permettere alla UI di aggiornarsi
|
// Forza il focus sulla griglia dopo un breve delay per permettere alla UI di aggiornarsi
|
||||||
@@ -248,7 +248,7 @@ namespace AutoBidder
|
|||||||
MultiAuctionsGrid.ScrollIntoView(MultiAuctionsGrid.SelectedItem);
|
MultiAuctionsGrid.ScrollIntoView(MultiAuctionsGrid.SelectedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ FIX: Usa la variabile locale invece di _selectedAuction.Name
|
// ? FIX: Usa la variabile locale invece di _selectedAuction.Name
|
||||||
Log($"[FOCUS] Focus spostato su: {newAuctionName}", LogLevel.Info);
|
Log($"[FOCUS] Focus spostato su: {newAuctionName}", LogLevel.Info);
|
||||||
}), System.Windows.Threading.DispatcherPriority.Background);
|
}), System.Windows.Threading.DispatcherPriority.Background);
|
||||||
}
|
}
|
||||||
@@ -278,7 +278,7 @@ namespace AutoBidder
|
|||||||
|
|
||||||
// Conferma rimozione
|
// Conferma rimozione
|
||||||
var result = MessageBox.Show(
|
var result = MessageBox.Show(
|
||||||
$"Rimuovere TUTTE le aste dal monitoraggio?\n\nSono presenti {count} aste monitorate.\n\nTutte le aste verranno eliminate dalla lista e non saranno più monitorate.",
|
$"Rimuovere TUTTE le aste dal monitoraggio?\n\nSono presenti {count} aste monitorate.\n\nTutte le aste verranno eliminate dalla lista e non saranno più monitorate.",
|
||||||
"Conferma Rimozione Totale",
|
"Conferma Rimozione Totale",
|
||||||
MessageBoxButton.YesNo,
|
MessageBoxButton.YesNo,
|
||||||
MessageBoxImage.Warning);
|
MessageBoxImage.Warning);
|
||||||
@@ -368,7 +368,7 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ultimo tentativo fallito
|
// Ultimo tentativo fallito
|
||||||
Log($"[WARN] Clipboard temporaneamente occupato. Il testo potrebbe essere stato copiato.", LogLevel.Warn);
|
Log($"[WARN] Clipboard temporaneamente occupato. Il testo potrebbe essere stato copiato.", LogLevel.Warning);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -405,8 +405,8 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log($"[WARN] Browser interno non ancora inizializzato", LogLevel.Warn);
|
Log($"[WARN] Browser interno non ancora inizializzato", LogLevel.Warning);
|
||||||
MessageBox.Show("Il browser interno non è ancora pronto.\nRiprova tra qualche secondo.", "Browser", MessageBoxButton.OK, MessageBoxImage.Warning);
|
MessageBox.Show("Il browser interno non è ancora pronto.\nRiprova tra qualche secondo.", "Browser", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -456,12 +456,12 @@ namespace AutoBidder
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
MessageBox.Show(
|
MessageBox.Show(
|
||||||
$"Esportazione singola asta:\n\n{_selectedAuction.Name}\n(ID: {_selectedAuction.AuctionId})\n\nFunzionalità in sviluppo.\nUsa 'Esporta' dalla toolbar per esportare tutte le aste.",
|
$"Esportazione singola asta:\n\n{_selectedAuction.Name}\n(ID: {_selectedAuction.AuctionId})\n\nFunzionalità in sviluppo.\nUsa 'Esporta' dalla toolbar per esportare tutte le aste.",
|
||||||
"Export Asta",
|
"Export Asta",
|
||||||
MessageBoxButton.OK,
|
MessageBoxButton.OK,
|
||||||
MessageBoxImage.Information);
|
MessageBoxImage.Information);
|
||||||
|
|
||||||
Log($"[INFO] Richiesto export singolo per asta: {_selectedAuction.Name} (funzionalità in sviluppo)", LogLevel.Info);
|
Log($"[INFO] Richiesto export singolo per asta: {_selectedAuction.Name} (funzionalità in sviluppo)", LogLevel.Info);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -503,12 +503,12 @@ namespace AutoBidder
|
|||||||
double shippingCost = auction.ShippingCost ?? 0;
|
double shippingCost = auction.ShippingCost ?? 0;
|
||||||
double totalValue = buyNowPrice + shippingCost;
|
double totalValue = buyNowPrice + shippingCost;
|
||||||
|
|
||||||
// Max EUR = 40% del valore TOTALE (più conservativo del 50%)
|
// Max EUR = 40% del valore TOTALE (più conservativo del 50%)
|
||||||
double suggestedMaxPrice = totalValue * 0.40;
|
double suggestedMaxPrice = totalValue * 0.40;
|
||||||
suggestedMaxPrice = Math.Round(suggestedMaxPrice, 2);
|
suggestedMaxPrice = Math.Round(suggestedMaxPrice, 2);
|
||||||
|
|
||||||
// CALCOLA MAX CLICKS (numero massimo puntate conservativo)
|
// CALCOLA MAX CLICKS (numero massimo puntate conservativo)
|
||||||
// Formula: (Valore Totale - Max EUR) / 0.20€ per puntata
|
// Formula: (Valore Totale - Max EUR) / 0.20€ per puntata
|
||||||
// Poi riduciamo del 20% per maggiore margine di sicurezza
|
// Poi riduciamo del 20% per maggiore margine di sicurezza
|
||||||
int maxClicksTheoretical = (int)Math.Floor((totalValue - suggestedMaxPrice) / 0.20);
|
int maxClicksTheoretical = (int)Math.Floor((totalValue - suggestedMaxPrice) / 0.20);
|
||||||
int suggestedMaxClicks = (int)Math.Floor(maxClicksTheoretical * 0.80); // 80% del teorico
|
int suggestedMaxClicks = (int)Math.Floor(maxClicksTheoretical * 0.80); // 80% del teorico
|
||||||
@@ -516,12 +516,12 @@ namespace AutoBidder
|
|||||||
// Minimo 10 puntate per dare comunque una chance
|
// Minimo 10 puntate per dare comunque una chance
|
||||||
if (suggestedMaxClicks < 10) suggestedMaxClicks = 10;
|
if (suggestedMaxClicks < 10) suggestedMaxClicks = 10;
|
||||||
|
|
||||||
Log($"[LIMITI] Valore={buyNowPrice:F2}€ + Extra={shippingCost:F2}€ = Tot={totalValue:F2}€ → MaxEUR={suggestedMaxPrice:F2}€ (40%), MaxClicks={suggestedMaxClicks}", LogLevel.Info);
|
Log($"[LIMITI] Valore={buyNowPrice:F2}€ + Extra={shippingCost:F2}€ = Tot={totalValue:F2}€ ? MaxEUR={suggestedMaxPrice:F2}€ (40%), MaxClicks={suggestedMaxClicks}", LogLevel.Info);
|
||||||
|
|
||||||
// CHIEDI CONFERMA
|
// CHIEDI CONFERMA
|
||||||
var result = MessageBox.Show(
|
var result = MessageBox.Show(
|
||||||
$"Limiti suggeriti (conservativi):\n\n" +
|
$"Limiti suggeriti (conservativi):\n\n" +
|
||||||
$"Max EUR: {suggestedMaxPrice:F2}€\n" +
|
$"Max EUR: {suggestedMaxPrice:F2}€\n" +
|
||||||
$"Max Clicks: {suggestedMaxClicks}\n\n" +
|
$"Max Clicks: {suggestedMaxClicks}\n\n" +
|
||||||
$"Applicare questi valori?",
|
$"Applicare questi valori?",
|
||||||
"Conferma Limiti",
|
"Conferma Limiti",
|
||||||
@@ -544,7 +544,7 @@ namespace AutoBidder
|
|||||||
// SALVA
|
// SALVA
|
||||||
SaveAuctions();
|
SaveAuctions();
|
||||||
|
|
||||||
Log($"[LIMITI] Applicati: MaxEUR={suggestedMaxPrice:F2}€, MaxClicks={suggestedMaxClicks}", LogLevel.Success);
|
Log($"[LIMITI] Applicati: MaxEUR={suggestedMaxPrice:F2}€, MaxClicks={suggestedMaxClicks}", LogLevel.Success);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -574,8 +574,8 @@ namespace AutoBidder
|
|||||||
|
|
||||||
if (currentIndex <= 0)
|
if (currentIndex <= 0)
|
||||||
{
|
{
|
||||||
// Già in cima o non trovata
|
// Già in cima o non trovata
|
||||||
Log($"[MOVE] L'asta è già in cima alla lista", LogLevel.Info);
|
Log($"[MOVE] L'asta è già in cima alla lista", LogLevel.Info);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,8 +615,8 @@ namespace AutoBidder
|
|||||||
|
|
||||||
if (currentIndex < 0 || currentIndex >= _auctionViewModels.Count - 1)
|
if (currentIndex < 0 || currentIndex >= _auctionViewModels.Count - 1)
|
||||||
{
|
{
|
||||||
// Già in fondo o non trovata
|
// Già in fondo o non trovata
|
||||||
Log($"[MOVE] L'asta è già in fondo alla lista", LogLevel.Info);
|
Log($"[MOVE] L'asta è già in fondo alla lista", LogLevel.Info);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -324,23 +324,6 @@ namespace AutoBidder
|
|||||||
|
|
||||||
// ===== SETTINGS CONTROL EVENTS =====
|
// ===== SETTINGS CONTROL EVENTS =====
|
||||||
|
|
||||||
// NOTA: Handler cookie RIMOSSI - gestione automatica tramite browser
|
|
||||||
|
|
||||||
private void Settings_ExportBrowseClicked(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
ExportBrowseButton_Click(sender, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Settings_SaveSettingsClicked(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
SaveSettingsButton_Click(sender, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Settings_CancelSettingsClicked(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
CancelSettingsButton_Click(sender, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Settings_SaveDefaultsClicked(object sender, RoutedEventArgs e)
|
private void Settings_SaveDefaultsClicked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
SaveDefaultsButton_Click(sender, e);
|
SaveDefaultsButton_Click(sender, e);
|
||||||
|
|||||||
@@ -6,27 +6,63 @@ using AutoBidder.Utilities;
|
|||||||
namespace AutoBidder
|
namespace AutoBidder
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logging functionality with color-coded severity levels
|
/// Logging functionality with color-coded severity levels and configurable minimum level filtering
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class MainWindow
|
public partial class MainWindow
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Scrive un messaggio nel log globale con filtraggio basato sul livello minimo configurato
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">Messaggio da loggare</param>
|
||||||
|
/// <param name="level">Livello di severità del messaggio</param>
|
||||||
private void Log(string message, LogLevel level = LogLevel.Info)
|
private void Log(string message, LogLevel level = LogLevel.Info)
|
||||||
{
|
{
|
||||||
Dispatcher.BeginInvoke(() =>
|
Dispatcher.BeginInvoke(() =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// Carica impostazioni per ottenere livello minimo e limite righe
|
||||||
|
var settings = SettingsManager.Load();
|
||||||
|
|
||||||
|
// Filtra messaggi in base al livello minimo configurato
|
||||||
|
MinimumLogLevel minLevel = MinimumLogLevel.Normal; // Default
|
||||||
|
if (Enum.TryParse<MinimumLogLevel>(settings.MinLogLevel, out var parsedLevel))
|
||||||
|
{
|
||||||
|
minLevel = parsedLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Se il livello del messaggio è maggiore del minimo configurato, ignora
|
||||||
|
if ((int)level > (int)minLevel)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
||||||
var logEntry = $"[{timestamp}] {message}";
|
|
||||||
|
// Prefisso in base al livello per chiarezza
|
||||||
|
string prefix = level switch
|
||||||
|
{
|
||||||
|
LogLevel.Error => "[ERROR]",
|
||||||
|
LogLevel.Warning => "[WARN]",
|
||||||
|
LogLevel.Info => "[INFO]",
|
||||||
|
LogLevel.Success => "[OK]",
|
||||||
|
LogLevel.Debug => "[DEBUG]",
|
||||||
|
LogLevel.Trace => "[TRACE]",
|
||||||
|
_ => "[LOG]"
|
||||||
|
};
|
||||||
|
|
||||||
|
var logEntry = $"[{timestamp}] {prefix} {message}";
|
||||||
|
|
||||||
// Color coding based on severity for dark theme
|
// Color coding based on severity for dark theme
|
||||||
var color = level switch
|
var color = level switch
|
||||||
{
|
{
|
||||||
LogLevel.Error => new SolidColorBrush(Color.FromRgb(232, 17, 35)), // #E81123 (Red)
|
LogLevel.Error => new SolidColorBrush(Color.FromRgb(232, 17, 35)), // #E81123 (Red)
|
||||||
LogLevel.Warn => new SolidColorBrush(Color.FromRgb(255, 183, 0)), // #FFB700 (Yellow/Orange)
|
LogLevel.Warning => new SolidColorBrush(Color.FromRgb(255, 191, 0)), // #FFBF00 (Yellow)
|
||||||
LogLevel.Success => new SolidColorBrush(Color.FromRgb(0, 216, 0)), // #00D800 (Green)
|
LogLevel.Success => new SolidColorBrush(Color.FromRgb(0, 216, 0)), // #00D800 (Green)
|
||||||
LogLevel.Info => new SolidColorBrush(Color.FromRgb(100, 180, 255)), // #64B4FF (Light Blue - più chiaro e leggibile)
|
LogLevel.Info => new SolidColorBrush(Color.FromRgb(100, 180, 255)), // #64B4FF (Light Blue)
|
||||||
_ => new SolidColorBrush(Color.FromRgb(204, 204, 204)) // #CCCCCC (Light Gray)
|
LogLevel.Debug => new SolidColorBrush(Color.FromRgb(255, 140, 255)), // #FF8CFF (Magenta)
|
||||||
|
LogLevel.Trace => new SolidColorBrush(Color.FromRgb(160, 160, 160)), // #A0A0A0 (Gray)
|
||||||
|
_ => new SolidColorBrush(Color.FromRgb(204, 204, 204)) // #CCCCCC (Light Gray)
|
||||||
};
|
};
|
||||||
|
|
||||||
var p = new System.Windows.Documents.Paragraph { Margin = new Thickness(0, 2, 0, 2) };
|
var p = new System.Windows.Documents.Paragraph { Margin = new Thickness(0, 2, 0, 2) };
|
||||||
@@ -34,8 +70,7 @@ namespace AutoBidder
|
|||||||
p.Inlines.Add(r);
|
p.Inlines.Add(r);
|
||||||
LogBox.Document.Blocks.Add(p);
|
LogBox.Document.Blocks.Add(p);
|
||||||
|
|
||||||
// ? Mantieni solo gli ultimi N paragrafi (configurabile dalle impostazioni)
|
// Mantieni solo gli ultimi N paragrafi (configurabile dalle impostazioni)
|
||||||
var settings = SettingsManager.Load();
|
|
||||||
int maxLogLines = settings.MaxGlobalLogLines;
|
int maxLogLines = settings.MaxGlobalLogLines;
|
||||||
|
|
||||||
if (LogBox.Document.Blocks.Count > maxLogLines)
|
if (LogBox.Document.Blocks.Count > maxLogLines)
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ namespace AutoBidder
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetUserBanner(string.Empty, 0);
|
SetUserBanner(string.Empty, 0);
|
||||||
Log("[SESSION] Sessione scaduta", LogLevel.Warn);
|
Log("[SESSION] Sessione scaduta", LogLevel.Warning);
|
||||||
CheckBrowserCookieAfterWebViewReady();
|
CheckBrowserCookieAfterWebViewReady();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -194,7 +194,7 @@ namespace AutoBidder
|
|||||||
Dispatcher.Invoke(() =>
|
Dispatcher.Invoke(() =>
|
||||||
{
|
{
|
||||||
SetUserBanner(string.Empty, 0);
|
SetUserBanner(string.Empty, 0);
|
||||||
Log($"[SESSION] Errore verifica sessione: {ex.Message}", LogLevel.Warn);
|
Log($"[SESSION] Errore verifica sessione: {ex.Message}", LogLevel.Warning);
|
||||||
CheckBrowserCookieAfterWebViewReady();
|
CheckBrowserCookieAfterWebViewReady();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -231,7 +231,7 @@ namespace AutoBidder
|
|||||||
{
|
{
|
||||||
await Dispatcher.InvokeAsync(() =>
|
await Dispatcher.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
Log("[WARN] WebView non inizializzata dopo 60 secondi", LogLevel.Warn);
|
Log("[WARN] WebView non inizializzata dopo 60 secondi", LogLevel.Warning);
|
||||||
Log("[INFO] Per accedere:", LogLevel.Info);
|
Log("[INFO] Per accedere:", LogLevel.Info);
|
||||||
Log("[INFO] 1. Click su 'Non connesso' nella sidebar", LogLevel.Info);
|
Log("[INFO] 1. Click su 'Non connesso' nella sidebar", LogLevel.Info);
|
||||||
Log("[INFO] 2. Si aprirà la scheda Browser", LogLevel.Info);
|
Log("[INFO] 2. Si aprirà la scheda Browser", LogLevel.Info);
|
||||||
@@ -263,7 +263,7 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log($"[WARN] Errore verifica cookie: {ex.Message}", LogLevel.Warn);
|
Log($"[WARN] Errore verifica cookie: {ex.Message}", LogLevel.Warning);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace AutoBidder
|
|||||||
{
|
{
|
||||||
if (EmbeddedWebView == null)
|
if (EmbeddedWebView == null)
|
||||||
{
|
{
|
||||||
Log("[WARN] WebView2 non disponibile", LogLevel.Warn);
|
Log("[WARN] WebView2 non disponibile", LogLevel.Warning);
|
||||||
_webViewInitCompletionSource?.TrySetResult(false);
|
_webViewInitCompletionSource?.TrySetResult(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log($"[WARN] Verifica cookie fallita: {ex.Message}", LogLevel.Warn);
|
Log($"[WARN] Verifica cookie fallita: {ex.Message}", LogLevel.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ namespace AutoBidder
|
|||||||
|
|
||||||
if (completedTask == timeoutTask)
|
if (completedTask == timeoutTask)
|
||||||
{
|
{
|
||||||
Log("[WARN] Timeout attesa inizializzazione WebView2", LogLevel.Warn);
|
Log("[WARN] Timeout attesa inizializzazione WebView2", LogLevel.Warning);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +275,7 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log($"[WARN] Impossibile estrarre cookie da WebView: {ex.Message}", LogLevel.Warn);
|
Log($"[WARN] Impossibile estrarre cookie da WebView: {ex.Message}", LogLevel.Warning);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -289,7 +289,7 @@ namespace AutoBidder
|
|||||||
{
|
{
|
||||||
if (!_isWebViewInitialized || EmbeddedWebView?.CoreWebView2 == null)
|
if (!_isWebViewInitialized || EmbeddedWebView?.CoreWebView2 == null)
|
||||||
{
|
{
|
||||||
Log("[WARN] Browser non inizializzato - attendi qualche secondo e riprova", LogLevel.Warn);
|
Log("[WARN] Browser non inizializzato - attendi qualche secondo e riprova", LogLevel.Warning);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +299,7 @@ namespace AutoBidder
|
|||||||
|
|
||||||
if (string.IsNullOrEmpty(cookieString))
|
if (string.IsNullOrEmpty(cookieString))
|
||||||
{
|
{
|
||||||
Log("[WARN] Nessun cookie trovato nel browser - assicurati di aver effettuato il login su bidoo.com", LogLevel.Warn);
|
Log("[WARN] Nessun cookie trovato nel browser - assicurati di aver effettuato il login su bidoo.com", LogLevel.Warning);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -334,9 +334,6 @@
|
|||||||
<!-- Settings Panel -->
|
<!-- Settings Panel -->
|
||||||
<controls:SettingsControl x:Name="Settings"
|
<controls:SettingsControl x:Name="Settings"
|
||||||
Visibility="Collapsed"
|
Visibility="Collapsed"
|
||||||
ExportBrowseClicked="Settings_ExportBrowseClicked"
|
|
||||||
SaveSettingsClicked="Settings_SaveSettingsClicked"
|
|
||||||
CancelSettingsClicked="Settings_CancelSettingsClicked"
|
|
||||||
SaveDefaultsClicked="Settings_SaveDefaultsClicked"
|
SaveDefaultsClicked="Settings_SaveDefaultsClicked"
|
||||||
CancelDefaultsClicked="Settings_CancelDefaultsClicked"/>
|
CancelDefaultsClicked="Settings_CancelDefaultsClicked"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
@@ -19,7 +19,7 @@ namespace AutoBidder
|
|||||||
private readonly AuctionMonitor _auctionMonitor;
|
private readonly AuctionMonitor _auctionMonitor;
|
||||||
private readonly System.Collections.ObjectModel.ObservableCollection<AuctionViewModel> _auctionViewModels = new System.Collections.ObjectModel.ObservableCollection<AuctionViewModel>();
|
private readonly System.Collections.ObjectModel.ObservableCollection<AuctionViewModel> _auctionViewModels = new System.Collections.ObjectModel.ObservableCollection<AuctionViewModel>();
|
||||||
|
|
||||||
// ✅ NUOVO: Servizio centralizzato per HTTP requests con cache e rate limiting
|
// ? NUOVO: Servizio centralizzato per HTTP requests con cache e rate limiting
|
||||||
private readonly HtmlCacheService _htmlCacheService;
|
private readonly HtmlCacheService _htmlCacheService;
|
||||||
|
|
||||||
// UI State
|
// UI State
|
||||||
@@ -69,19 +69,6 @@ namespace AutoBidder
|
|||||||
public TextBox BrowserAddress => Browser.BrowserAddress;
|
public TextBox BrowserAddress => Browser.BrowserAddress;
|
||||||
|
|
||||||
// Properties to access UserControl elements - Settings
|
// Properties to access UserControl elements - Settings
|
||||||
public TextBox ExportPathTextBox => Settings.ExportPathTextBox;
|
|
||||||
public Button ExportBrowseButton => Settings.ExportBrowseButton;
|
|
||||||
public RadioButton ExtCsv => Settings.ExtCsv;
|
|
||||||
public RadioButton ExtJson => Settings.ExtJson;
|
|
||||||
public RadioButton ExtXml => Settings.ExtXml;
|
|
||||||
public CheckBox IncludeUsedBids => Settings.IncludeUsedBids;
|
|
||||||
public CheckBox IncludeLogs => Settings.IncludeLogs;
|
|
||||||
public CheckBox IncludeUserBids => Settings.IncludeUserBids;
|
|
||||||
public CheckBox IncludeMetadata => Settings.IncludeMetadata;
|
|
||||||
public CheckBox RemoveAfterExport => Settings.RemoveAfterExport;
|
|
||||||
public CheckBox OverwriteExisting => Settings.OverwriteExisting;
|
|
||||||
|
|
||||||
// Impostazioni predefinite aste - AGGIORNATO
|
|
||||||
public TextBox DefaultBidBeforeDeadlineMs => Settings.DefaultBidBeforeDeadlineMsTextBox;
|
public TextBox DefaultBidBeforeDeadlineMs => Settings.DefaultBidBeforeDeadlineMsTextBox;
|
||||||
public CheckBox DefaultCheckAuctionOpen => Settings.DefaultCheckAuctionOpenCheckBox;
|
public CheckBox DefaultCheckAuctionOpen => Settings.DefaultCheckAuctionOpenCheckBox;
|
||||||
public TextBox DefaultMinPrice => Settings.DefaultMinPriceTextBox;
|
public TextBox DefaultMinPrice => Settings.DefaultMinPriceTextBox;
|
||||||
@@ -94,7 +81,7 @@ namespace AutoBidder
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
// ✅ Inizializza HtmlCacheService con:
|
// ? Inizializza HtmlCacheService con:
|
||||||
// - Max 3 richieste concorrenti
|
// - Max 3 richieste concorrenti
|
||||||
// - Max 5 richieste al secondo
|
// - Max 5 richieste al secondo
|
||||||
// - Cache di 5 minuti
|
// - Cache di 5 minuti
|
||||||
@@ -110,13 +97,13 @@ namespace AutoBidder
|
|||||||
// Inizializza servizi
|
// Inizializza servizi
|
||||||
_auctionMonitor = new AuctionMonitor();
|
_auctionMonitor = new AuctionMonitor();
|
||||||
|
|
||||||
// ✅ NUOVO: Inizializza SessionService
|
// ? NUOVO: Inizializza SessionService
|
||||||
InitializeSessionService();
|
InitializeSessionService();
|
||||||
|
|
||||||
// Initialize commands (from MainWindow.Commands.cs)
|
// Initialize commands (from MainWindow.Commands.cs)
|
||||||
InitializeCommands();
|
InitializeCommands();
|
||||||
|
|
||||||
// ✅ NUOVO: Inizializza validazione campi numerici
|
// ? NUOVO: Inizializza validazione campi numerici
|
||||||
InitializeNumericInputValidation();
|
InitializeNumericInputValidation();
|
||||||
|
|
||||||
this.DataContext = this;
|
this.DataContext = this;
|
||||||
@@ -127,7 +114,7 @@ namespace AutoBidder
|
|||||||
_auctionMonitor.OnLog += AuctionMonitor_OnLog;
|
_auctionMonitor.OnLog += AuctionMonitor_OnLog;
|
||||||
_auctionMonitor.OnResetCountChanged += AuctionMonitor_OnResetCountChanged;
|
_auctionMonitor.OnResetCountChanged += AuctionMonitor_OnResetCountChanged;
|
||||||
|
|
||||||
// ✅ NUOVO: Registra evento stato connessione
|
// ? NUOVO: Registra evento stato connessione
|
||||||
AuctionMonitor.ConnectionStatusClicked += AuctionMonitor_ConnectionStatusClicked;
|
AuctionMonitor.ConnectionStatusClicked += AuctionMonitor_ConnectionStatusClicked;
|
||||||
|
|
||||||
// Bind griglia
|
// Bind griglia
|
||||||
@@ -136,24 +123,51 @@ namespace AutoBidder
|
|||||||
// Carica aste salvate (from MainWindow.AuctionManagement.cs)
|
// Carica aste salvate (from MainWindow.AuctionManagement.cs)
|
||||||
LoadSavedAuctions();
|
LoadSavedAuctions();
|
||||||
|
|
||||||
// Load export settings (from MainWindow.EventHandlers.Export.cs)
|
|
||||||
LoadExportSettings();
|
|
||||||
|
|
||||||
// CARICA IMPOSTAZIONI PREDEFINITE ASTE
|
// CARICA IMPOSTAZIONI PREDEFINITE ASTE
|
||||||
LoadDefaultSettings();
|
LoadDefaultSettings();
|
||||||
|
|
||||||
// Update initial button states
|
// Update initial button states
|
||||||
UpdateGlobalControlButtons();
|
UpdateGlobalControlButtons();
|
||||||
|
|
||||||
Log("[OK] AutoBidder v4.0 avviato", LogLevel.Success);
|
// === LOG AVVIO APPLICAZIONE ===
|
||||||
|
Log("???????????????????????????????????????????????", LogLevel.Info);
|
||||||
|
Log(" AutoBidder v4.0 - Multi-Auction Monitor", LogLevel.Info);
|
||||||
|
Log("???????????????????????????????????????????????", LogLevel.Info);
|
||||||
|
|
||||||
|
var settings = SettingsManager.Load();
|
||||||
|
Log($"Configurazione caricata:", LogLevel.Info);
|
||||||
|
Log($" • Livello log: {settings.MinLogLevel}", LogLevel.Info);
|
||||||
|
Log($" • Limite log globale: {settings.MaxGlobalLogLines} righe", LogLevel.Info);
|
||||||
|
Log($" • Limite log per asta: {settings.MaxLogLinesPerAuction} righe", LogLevel.Info);
|
||||||
|
Log($" • Puntate minime da mantenere: {(settings.MinimumRemainingBids > 0 ? settings.MinimumRemainingBids.ToString() : "nessun limite")}", LogLevel.Info);
|
||||||
|
Log($" • Anticipo puntata default: {settings.DefaultBidBeforeDeadlineMs}ms", LogLevel.Info);
|
||||||
|
|
||||||
|
var auctionCount = _auctionViewModels.Count;
|
||||||
|
if (auctionCount > 0)
|
||||||
|
{
|
||||||
|
Log($"Aste caricate: {auctionCount}", LogLevel.Success);
|
||||||
|
var activeCount = _auctionViewModels.Count(a => a.IsActive && !a.IsPaused);
|
||||||
|
var pausedCount = _auctionViewModels.Count(a => a.IsPaused);
|
||||||
|
var stoppedCount = _auctionViewModels.Count(a => !a.IsActive && !a.IsPaused);
|
||||||
|
if (activeCount > 0) Log($" • Attive: {activeCount}", LogLevel.Info);
|
||||||
|
if (pausedCount > 0) Log($" • In pausa: {pausedCount}", LogLevel.Info);
|
||||||
|
if (stoppedCount > 0) Log($" • Fermate: {stoppedCount}", LogLevel.Info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log("Nessuna asta caricata", LogLevel.Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log("[OK] Applicazione pronta", LogLevel.Success);
|
||||||
|
Log("???????????????????????????????????????????????", LogLevel.Info);
|
||||||
|
|
||||||
// Initialize user info timers (from MainWindow.UserInfo.cs)
|
// Initialize user info timers (from MainWindow.UserInfo.cs)
|
||||||
InitializeUserInfoTimers();
|
InitializeUserInfoTimers();
|
||||||
|
|
||||||
// ✅ NUOVO: Carica sessione salvata
|
// ? NUOVO: Carica sessione salvata
|
||||||
LoadSavedSession();
|
LoadSavedSession();
|
||||||
|
|
||||||
// ✅ NUOVO: Pre-carica WebView2 in background per renderla subito disponibile
|
// ? NUOVO: Pre-carica WebView2 in background per renderla subito disponibile
|
||||||
InitializeWebView2();
|
InitializeWebView2();
|
||||||
|
|
||||||
// Attach WebView2 context menu handler
|
// Attach WebView2 context menu handler
|
||||||
@@ -176,7 +190,7 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
|
||||||
// ✅ Timer per pulizia cache periodica (ogni 10 minuti)
|
// ? Timer per pulizia cache periodica (ogni 10 minuti)
|
||||||
var cacheCleanupTimer = new System.Windows.Threading.DispatcherTimer
|
var cacheCleanupTimer = new System.Windows.Threading.DispatcherTimer
|
||||||
{
|
{
|
||||||
Interval = TimeSpan.FromMinutes(10)
|
Interval = TimeSpan.FromMinutes(10)
|
||||||
@@ -222,7 +236,7 @@ namespace AutoBidder
|
|||||||
{
|
{
|
||||||
vm.UpdateState(state);
|
vm.UpdateState(state);
|
||||||
|
|
||||||
// ✅ NUOVO: Aggiorna storia puntate
|
// ? NUOVO: Aggiorna storia puntate
|
||||||
vm.RefreshBidHistory();
|
vm.RefreshBidHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
@@ -12,7 +12,7 @@ namespace AutoBidder.Services
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Servizio completo API Bidoo (polling, puntate, info utente)
|
/// Servizio completo API Bidoo (polling, puntate, info utente)
|
||||||
/// Solo HTTP, nessuna modalità, browser o multi-click
|
/// Solo HTTP, nessuna modalità, browser o multi-click
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BidooApiClient
|
public class BidooApiClient
|
||||||
{
|
{
|
||||||
@@ -90,7 +90,7 @@ namespace AutoBidder.Services
|
|||||||
if (!string.IsNullOrWhiteSpace(_session.CookieString))
|
if (!string.IsNullOrWhiteSpace(_session.CookieString))
|
||||||
{
|
{
|
||||||
request.Headers.Add("Cookie", _session.CookieString);
|
request.Headers.Add("Cookie", _session.CookieString);
|
||||||
// Log rimosso per ridurre verbosità
|
// Log rimosso per ridurre verbosità
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -130,13 +130,13 @@ namespace AutoBidder.Services
|
|||||||
request.Headers.Add("Referer", "https://it.bidoo.com/");
|
request.Headers.Add("Referer", "https://it.bidoo.com/");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log rimosso per ridurre verbosità - headers sempre aggiunti
|
// Log rimosso per ridurre verbosità - headers sempre aggiunti
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Estrae CSRF/Bid token dalla pagina asta
|
/// Estrae CSRF/Bid token dalla pagina asta
|
||||||
/// PASSO 1: Ottenere la pagina HTML dell'asta per estrarre il token di sicurezza
|
/// PASSO 1: Ottenere la pagina HTML dell'asta per estrarre il token di sicurezza
|
||||||
/// Il token può essere chiamato: bid_token, csrf_token, _token, etc.
|
/// Il token può essere chiamato: bid_token, csrf_token, _token, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<(string? tokenName, string? tokenValue)> ExtractBidTokenAsync(string auctionId, string? auctionUrl = null)
|
private async Task<(string? tokenName, string? tokenValue)> ExtractBidTokenAsync(string auctionId, string? auctionUrl = null)
|
||||||
{
|
{
|
||||||
@@ -187,12 +187,12 @@ namespace AutoBidder.Services
|
|||||||
if (match.Success)
|
if (match.Success)
|
||||||
{
|
{
|
||||||
var tokenValue = match.Groups[1].Value;
|
var tokenValue = match.Groups[1].Value;
|
||||||
Log($"[TOKEN] ✓ Token found: {pattern.name} = {tokenValue.Substring(0, Math.Min(20, tokenValue.Length))}...", auctionId);
|
Log($"[TOKEN] ? Token found: {pattern.name} = {tokenValue.Substring(0, Math.Min(20, tokenValue.Length))}...", auctionId);
|
||||||
return (pattern.name, tokenValue);
|
return (pattern.name, tokenValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log("[TOKEN] ⚠ No bid token found in HTML", auctionId);
|
Log("[TOKEN] ? No bid token found in HTML", auctionId);
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -309,7 +309,7 @@ namespace AutoBidder.Services
|
|||||||
state.IsMyBid = !string.IsNullOrEmpty(_session.Username) &&
|
state.IsMyBid = !string.IsNullOrEmpty(_session.Username) &&
|
||||||
state.LastBidder.Equals(_session.Username, StringComparison.OrdinalIgnoreCase);
|
state.LastBidder.Equals(_session.Username, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
// ✅ NUOVO: Parse storia puntate
|
// ? NUOVO: Parse storia puntate
|
||||||
// Formato: 42;fedekikka2323;3,42;fedekikka2323;1764068204;3|41;chamorro1984;1764068194;3|...
|
// Formato: 42;fedekikka2323;3,42;fedekikka2323;1764068204;3|41;chamorro1984;1764068194;3|...
|
||||||
if (!string.IsNullOrEmpty(historyData))
|
if (!string.IsNullOrEmpty(historyData))
|
||||||
{
|
{
|
||||||
@@ -317,7 +317,8 @@ namespace AutoBidder.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
state.ParsingSuccess = true;
|
state.ParsingSuccess = true;
|
||||||
Log($"[PARSE SUCCESS] Timer: {state.Timer:F2}s, Price: €{state.Price:F2}, Bidder: {state.LastBidder}, Status: {state.Status}, History: {state.RecentBidsHistory?.Count ?? 0} bids", auctionId);
|
// Log di successo rimosso - troppo verboso. Solo errori vengono loggati nel log asta.
|
||||||
|
// Per debug dettagliato, usare livello log "Debug" o "Trace" nelle impostazioni.
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -337,14 +338,14 @@ namespace AutoBidder.Services
|
|||||||
{
|
{
|
||||||
var entries = new List<BidHistoryEntry>();
|
var entries = new List<BidHistoryEntry>();
|
||||||
|
|
||||||
// Il primo record è spesso il prezzo corrente con dati duplicati, lo saltiamo
|
// Il primo record è spesso il prezzo corrente con dati duplicati, lo saltiamo
|
||||||
var records = historyData.Split('|');
|
var records = historyData.Split('|');
|
||||||
|
|
||||||
// Parsing prezzo corrente per calcolare i prezzi precedenti
|
// Parsing prezzo corrente per calcolare i prezzi precedenti
|
||||||
if (!int.TryParse(currentPriceStr, out var currentPriceIndex))
|
if (!int.TryParse(currentPriceStr, out var currentPriceIndex))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// 📊 NUOVO: Carica impostazione limite visualizzazione puntate
|
// ?? NUOVO: Carica impostazione limite visualizzazione puntate
|
||||||
var settings = Utilities.SettingsManager.Load();
|
var settings = Utilities.SettingsManager.Load();
|
||||||
var maxEntries = settings?.MaxBidHistoryEntries ?? 20; // Default 20 se non impostato
|
var maxEntries = settings?.MaxBidHistoryEntries ?? 20; // Default 20 se non impostato
|
||||||
|
|
||||||
@@ -353,7 +354,7 @@ namespace AutoBidder.Services
|
|||||||
if (string.IsNullOrWhiteSpace(record))
|
if (string.IsNullOrWhiteSpace(record))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// 📊 Limita il numero di puntate basandosi sulle impostazioni
|
// ?? Limita il numero di puntate basandosi sulle impostazioni
|
||||||
if (maxEntries > 0 && entries.Count >= maxEntries)
|
if (maxEntries > 0 && entries.Count >= maxEntries)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -523,7 +524,7 @@ namespace AutoBidder.Services
|
|||||||
if (creditMatch.Success && double.TryParse(creditMatch.Groups[1].Value, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out double credit))
|
if (creditMatch.Success && double.TryParse(creditMatch.Groups[1].Value, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out double credit))
|
||||||
{
|
{
|
||||||
_session.ShopCredit = credit;
|
_session.ShopCredit = credit;
|
||||||
Log($"[USER INFO PARSED] Shop credit: €{credit:F2}");
|
Log($"[USER INFO PARSED] Shop credit: €{credit:F2}");
|
||||||
foundData = true;
|
foundData = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -656,15 +657,15 @@ namespace AutoBidder.Services
|
|||||||
/// STATI API BIDOO:
|
/// STATI API BIDOO:
|
||||||
/// - ON: Asta attiva e in corso
|
/// - ON: Asta attiva e in corso
|
||||||
/// - OFF: Asta terminata definitivamente
|
/// - OFF: Asta terminata definitivamente
|
||||||
/// - STOP: Asta in pausa (tipicamente 00:00-10:00) - riprenderà più tardi
|
/// - STOP: Asta in pausa (tipicamente 00:00-10:00) - riprenderà più tardi
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private AuctionStatus DetermineAuctionStatus(string apiStatus, bool hasWinner, bool iAmWinner, ref AuctionState state)
|
private AuctionStatus DetermineAuctionStatus(string apiStatus, bool hasWinner, bool iAmWinner, ref AuctionState state)
|
||||||
{
|
{
|
||||||
// Gestione stato STOP (pausa notturna)
|
// Gestione stato STOP (pausa notturna)
|
||||||
if (apiStatus == "STOP")
|
if (apiStatus == "STOP")
|
||||||
{
|
{
|
||||||
// L'asta è iniziata ma è in pausa
|
// L'asta è iniziata ma è in pausa
|
||||||
// Controlla se c'è già un vincitore temporaneo
|
// Controlla se c'è già un vincitore temporaneo
|
||||||
if (hasWinner)
|
if (hasWinner)
|
||||||
{
|
{
|
||||||
state.LastBidder = state.LastBidder; // Mantieni il last bidder
|
state.LastBidder = state.LastBidder; // Mantieni il last bidder
|
||||||
@@ -689,12 +690,12 @@ namespace AutoBidder.Services
|
|||||||
// Asta attiva
|
// Asta attiva
|
||||||
if (hasWinner)
|
if (hasWinner)
|
||||||
{
|
{
|
||||||
// Ci sono già puntate → Running
|
// Ci sono già puntate ? Running
|
||||||
return AuctionStatus.Running;
|
return AuctionStatus.Running;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nessuna puntata ancora → Pending o Scheduled
|
// Nessuna puntata ancora ? Pending o Scheduled
|
||||||
// Se timer molto alto (> 30 minuti), è programmata per più tardi
|
// Se timer molto alto (> 30 minuti), è programmata per più tardi
|
||||||
if (state.Timer > 1800) // 30 minuti
|
if (state.Timer > 1800) // 30 minuti
|
||||||
{
|
{
|
||||||
return AuctionStatus.Scheduled;
|
return AuctionStatus.Scheduled;
|
||||||
@@ -899,7 +900,7 @@ namespace AutoBidder.Services
|
|||||||
Log($"[USER HTML ERROR] Puntate residue NON trovate nell'HTML");
|
Log($"[USER HTML ERROR] Puntate residue NON trovate nell'HTML");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ritorna dati solo se almeno username è stato trovato
|
// Ritorna dati solo se almeno username è stato trovato
|
||||||
if (foundUsername)
|
if (foundUsername)
|
||||||
{
|
{
|
||||||
Log($"[USER HTML SUCCESS] Dati estratti: {userData.Username}, {userData.RemainingBids} puntate");
|
Log($"[USER HTML SUCCESS] Dati estratti: {userData.Username}, {userData.RemainingBids} puntate");
|
||||||
|
|||||||
@@ -1,130 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using AutoBidder.Models;
|
|
||||||
|
|
||||||
namespace AutoBidder.Utilities
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Esporta statistiche aste in formato CSV
|
|
||||||
/// </summary>
|
|
||||||
public static class CsvExporter
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Esporta cronologia completa di un'asta in CSV
|
|
||||||
/// </summary>
|
|
||||||
public static void ExportAuctionHistory(AuctionInfo auction, string filePath)
|
|
||||||
{
|
|
||||||
var csv = new StringBuilder();
|
|
||||||
|
|
||||||
// Header
|
|
||||||
csv.AppendLine("Timestamp,Event Type,Bidder,Price,Timer,Latency (ms),Success,Notes");
|
|
||||||
|
|
||||||
// Data
|
|
||||||
foreach (var entry in auction.BidHistory.OrderBy(h => h.Timestamp))
|
|
||||||
{
|
|
||||||
csv.AppendLine($"{entry.Timestamp:yyyy-MM-dd HH:mm:ss.fff}," +
|
|
||||||
$"{entry.EventType}," +
|
|
||||||
$"\"{entry.Bidder}\"," +
|
|
||||||
$"{entry.Price:F2}," +
|
|
||||||
$"{entry.Timer:F2}," +
|
|
||||||
$"{entry.LatencyMs}," +
|
|
||||||
$"{entry.Success}," +
|
|
||||||
$"\"{entry.Notes}\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
File.WriteAllText(filePath, csv.ToString(), Encoding.UTF8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Esporta statistiche aggregate di un'asta in CSV
|
|
||||||
/// </summary>
|
|
||||||
public static void ExportAuctionStatistics(AuctionInfo auction, string filePath)
|
|
||||||
{
|
|
||||||
var stats = AuctionStatistics.Calculate(auction);
|
|
||||||
var csv = new StringBuilder();
|
|
||||||
|
|
||||||
// Informazioni asta
|
|
||||||
csv.AppendLine("=== AUCTION INFO ===");
|
|
||||||
csv.AppendLine($"Auction ID,{stats.AuctionId}");
|
|
||||||
csv.AppendLine($"Name,\"{stats.Name}\"");
|
|
||||||
csv.AppendLine($"Monitoring Started,{stats.MonitoringStarted:yyyy-MM-dd HH:mm:ss}");
|
|
||||||
csv.AppendLine($"Monitoring Duration,{stats.MonitoringDuration}");
|
|
||||||
csv.AppendLine();
|
|
||||||
|
|
||||||
// Contatori
|
|
||||||
csv.AppendLine("=== COUNTERS ===");
|
|
||||||
csv.AppendLine($"Total Bids,{stats.TotalBids}");
|
|
||||||
csv.AppendLine($"My Bids,{stats.MyBids}");
|
|
||||||
csv.AppendLine($"Opponent Bids,{stats.OpponentBids}");
|
|
||||||
csv.AppendLine($"Resets,{stats.Resets}");
|
|
||||||
csv.AppendLine($"Unique Bidders,{stats.UniqueBidders}");
|
|
||||||
csv.AppendLine();
|
|
||||||
|
|
||||||
// Prezzi
|
|
||||||
csv.AppendLine("=== PRICES ===");
|
|
||||||
csv.AppendLine($"Start Price,{stats.StartPrice:F2}");
|
|
||||||
csv.AppendLine($"Current Price,{stats.CurrentPrice:F2}");
|
|
||||||
csv.AppendLine($"Min Price,{stats.MinPrice:F2}");
|
|
||||||
csv.AppendLine($"Max Price,{stats.MaxPrice:F2}");
|
|
||||||
csv.AppendLine($"Avg Price,{stats.AvgPrice:F2}");
|
|
||||||
csv.AppendLine();
|
|
||||||
|
|
||||||
// Performance
|
|
||||||
csv.AppendLine("=== PERFORMANCE ===");
|
|
||||||
csv.AppendLine($"Avg Click Latency (ms),{stats.AvgClickLatencyMs}");
|
|
||||||
csv.AppendLine($"Min Click Latency (ms),{stats.MinClickLatencyMs}");
|
|
||||||
csv.AppendLine($"Max Click Latency (ms),{stats.MaxClickLatencyMs}");
|
|
||||||
csv.AppendLine($"Bids Per Minute,{stats.BidsPerMinute:F2}");
|
|
||||||
csv.AppendLine($"Resets Per Hour,{stats.ResetsPerHour:F2}");
|
|
||||||
csv.AppendLine($"My Bid Success Rate,{stats.MyBidSuccessRate:F1}%");
|
|
||||||
csv.AppendLine();
|
|
||||||
|
|
||||||
// Competitor ranking
|
|
||||||
csv.AppendLine("=== BIDDER RANKING ===");
|
|
||||||
csv.AppendLine("Bidder,Bids Count");
|
|
||||||
foreach (var bidder in stats.BidderRanking.OrderByDescending(b => b.Value))
|
|
||||||
{
|
|
||||||
csv.AppendLine($"\"{bidder.Key}\",{bidder.Value}");
|
|
||||||
}
|
|
||||||
|
|
||||||
File.WriteAllText(filePath, csv.ToString(), Encoding.UTF8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Esporta tutte le aste in un unico CSV
|
|
||||||
/// </summary>
|
|
||||||
public static void ExportAllAuctions(IEnumerable<AuctionInfo> auctions, string filePath)
|
|
||||||
{
|
|
||||||
var csv = new StringBuilder();
|
|
||||||
|
|
||||||
// Header AGGIORNATO
|
|
||||||
csv.AppendLine("Auction ID,Name,Bid Before Deadline (ms),Check Before Bid,Min Price,Max Price,My Bids,Resets,Total Bidders,Active,Paused,Added At,Last Click At");
|
|
||||||
|
|
||||||
// Data
|
|
||||||
foreach (var auction in auctions)
|
|
||||||
{
|
|
||||||
var totalBidders = auction.BidderStats?.Count ?? 0;
|
|
||||||
var myBids = auction.BidHistory.Count(h => h.EventType == BidEventType.MyBid);
|
|
||||||
|
|
||||||
csv.AppendLine($"{auction.AuctionId}," +
|
|
||||||
$"\"{auction.Name}\"," +
|
|
||||||
$"{auction.BidBeforeDeadlineMs}," +
|
|
||||||
$"{auction.CheckAuctionOpenBeforeBid}," +
|
|
||||||
$"{auction.MinPrice:F2}," +
|
|
||||||
$"{auction.MaxPrice:F2}," +
|
|
||||||
$"{myBids}," +
|
|
||||||
$"{auction.ResetCount}," +
|
|
||||||
$"{totalBidders}," +
|
|
||||||
$"{auction.IsActive}," +
|
|
||||||
$"{auction.IsPaused}," +
|
|
||||||
$"{auction.AddedAt:yyyy-MM-dd HH:mm:ss}," +
|
|
||||||
$"{(auction.LastClickAt?.ToString("yyyy-MM-dd HH:mm:ss") ?? "")}");
|
|
||||||
}
|
|
||||||
|
|
||||||
File.WriteAllText(filePath, csv.ToString(), Encoding.UTF8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace AutoBidder.Utilities
|
|
||||||
{
|
|
||||||
internal static class ExportPreferences
|
|
||||||
{
|
|
||||||
private class Prefs { public string? LastExportExt { get; set; } }
|
|
||||||
private static readonly string _folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "AutoBidder");
|
|
||||||
private static readonly string _file = Path.Combine(_folder, "exportprefs.json");
|
|
||||||
|
|
||||||
public static string? LoadLastExportExtension()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!File.Exists(_file)) return null;
|
|
||||||
var txt = File.ReadAllText(_file);
|
|
||||||
var p = JsonSerializer.Deserialize<Prefs>(txt);
|
|
||||||
if (p == null || string.IsNullOrEmpty(p.LastExportExt)) return null;
|
|
||||||
return p.LastExportExt;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SaveLastExportExtension(string? ext)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!Directory.Exists(_folder)) Directory.CreateDirectory(_folder);
|
|
||||||
var p = new Prefs { LastExportExt = ext };
|
|
||||||
var txt = JsonSerializer.Serialize(p);
|
|
||||||
File.WriteAllText(_file, txt);
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,82 @@
|
|||||||
namespace AutoBidder.Utilities
|
namespace AutoBidder.Utilities
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Livelli di log per differenziare la verbosità dei messaggi.
|
||||||
|
/// Permette di configurare il dettaglio desiderato tra uso normale e debug.
|
||||||
|
/// </summary>
|
||||||
internal enum LogLevel
|
internal enum LogLevel
|
||||||
{
|
{
|
||||||
Info,
|
/// <summary>
|
||||||
Success,
|
/// Errori critici che impediscono il funzionamento dell'applicazione o di una funzionalità.
|
||||||
Warn,
|
/// Sempre visibile. Esempi: errori di connessione, parsing fallito, eccezioni non gestite.
|
||||||
Error
|
/// </summary>
|
||||||
|
Error = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Avvisi per situazioni anomale ma non critiche.
|
||||||
|
/// Sempre visibile. Esempi: parametri mancanti, valori inaspettati, retry in corso.
|
||||||
|
/// </summary>
|
||||||
|
Warning = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Informazioni importanti sull'operatività dell'applicazione.
|
||||||
|
/// Visibile in modalità normale e debug. Esempi: asta aggiunta, stato cambiato, operazioni completate.
|
||||||
|
/// </summary>
|
||||||
|
Info = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Conferme di operazioni riuscite con successo.
|
||||||
|
/// Visibile in modalità normale e debug. Esempi: puntata effettuata, login riuscito, salvataggio completato.
|
||||||
|
/// </summary>
|
||||||
|
Success = 3,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Informazioni dettagliate per il debug dell'applicazione.
|
||||||
|
/// Visibile solo in modalità debug. Esempi: parametri chiamate API, valori variabili, flusso logico.
|
||||||
|
/// </summary>
|
||||||
|
Debug = 4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tracciamento estremamente dettagliato di ogni operazione.
|
||||||
|
/// Visibile solo in modalità trace. Esempi: ogni singola chiamata, timestamp precisi, dati raw HTTP.
|
||||||
|
/// </summary>
|
||||||
|
Trace = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Livello minimo di log da mostrare all'utente.
|
||||||
|
/// Controlla quali messaggi vengono effettivamente visualizzati nel log.
|
||||||
|
/// </summary>
|
||||||
|
internal enum MinimumLogLevel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Solo errori critici (uso giornaliero minimo).
|
||||||
|
/// Mostra: Error
|
||||||
|
/// </summary>
|
||||||
|
ErrorOnly = LogLevel.Error,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Errori e avvisi (uso giornaliero normale).
|
||||||
|
/// Mostra: Error, Warning
|
||||||
|
/// </summary>
|
||||||
|
Normal = LogLevel.Warning,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Informazioni operative standard (uso giornaliero dettagliato).
|
||||||
|
/// Mostra: Error, Warning, Info, Success
|
||||||
|
/// </summary>
|
||||||
|
Informational = LogLevel.Success,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Informazioni dettagliate per debug (sviluppo applicazione).
|
||||||
|
/// Mostra: Error, Warning, Info, Success, Debug
|
||||||
|
/// </summary>
|
||||||
|
Debug = LogLevel.Debug,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tracciamento completo di ogni operazione (debug avanzato).
|
||||||
|
/// Mostra: Error, Warning, Info, Success, Debug, Trace
|
||||||
|
/// </summary>
|
||||||
|
Trace = LogLevel.Trace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,21 +6,6 @@ namespace AutoBidder.Utilities
|
|||||||
{
|
{
|
||||||
internal class AppSettings
|
internal class AppSettings
|
||||||
{
|
{
|
||||||
public string? ExportPath { get; set; }
|
|
||||||
public string? LastExportExt { get; set; }
|
|
||||||
public string ExportScope { get; set; } = "All"; // All, Closed, Unknown
|
|
||||||
public bool IncludeOnlyUsedBids { get; set; } = true;
|
|
||||||
public bool IncludeLogs { get; set; } = false;
|
|
||||||
public bool IncludeUserBids { get; set; } = false;
|
|
||||||
|
|
||||||
// Added properties to match MainWindow expectations
|
|
||||||
public bool ExportOpen { get; set; } = true;
|
|
||||||
public bool ExportClosed { get; set; } = true;
|
|
||||||
public bool ExportUnknown { get; set; } = true;
|
|
||||||
public bool IncludeMetadata { get; set; } = true;
|
|
||||||
public bool RemoveAfterExport { get; set; } = false;
|
|
||||||
public bool OverwriteExisting { get; set; } = false;
|
|
||||||
|
|
||||||
// NUOVE IMPOSTAZIONI PREDEFINITE PER LE ASTE
|
// NUOVE IMPOSTAZIONI PREDEFINITE PER LE ASTE
|
||||||
public int DefaultBidBeforeDeadlineMs { get; set; } = 200;
|
public int DefaultBidBeforeDeadlineMs { get; set; } = 200;
|
||||||
public bool DefaultCheckAuctionOpenBeforeBid { get; set; } = false;
|
public bool DefaultCheckAuctionOpenBeforeBid { get; set; } = false;
|
||||||
@@ -74,6 +59,15 @@ namespace AutoBidder.Utilities
|
|||||||
/// Default: 20 (ultime 20 puntate)
|
/// Default: 20 (ultime 20 puntate)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int MaxBidHistoryEntries { get; set; } = 20;
|
public int MaxBidHistoryEntries { get; set; } = 20;
|
||||||
|
|
||||||
|
// ?? NUOVO: LIVELLO MINIMO LOG
|
||||||
|
/// <summary>
|
||||||
|
/// Livello minimo di log da visualizzare.
|
||||||
|
/// Valori: "ErrorOnly" (solo errori), "Normal" (errori e warning),
|
||||||
|
/// "Informational" (info standard), "Debug" (dettagli sviluppo), "Trace" (tutto).
|
||||||
|
/// Default: "Normal" (uso giornaliero - errori e warning)
|
||||||
|
/// </summary>
|
||||||
|
public string MinLogLevel { get; set; } = "Normal";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static class SettingsManager
|
internal static class SettingsManager
|
||||||
|
|||||||
Reference in New Issue
Block a user