Aggiunto pulsante "Pausa" e progetto Template
- Aggiunto pulsante "Pausa" con stile dedicato e logica. - Riorganizzata la griglia in `MainWindow.xaml` per nuovi elementi. - Aggiunta griglia per visualizzare gli offerenti (`BiddersGrid`). - Introdotti limiti di prezzo e gestione dei reset nel ciclo. - Aggiunto progetto `Template` per il packaging dell'app. - Aggiunti file di risorse grafiche per loghi e icone. - Aggiornato `Mimante.sln` per supportare nuove piattaforme. - Ottimizzazioni e correzioni di stabilità.
@@ -33,6 +33,10 @@
|
|||||||
<Setter Property="Background" Value="#DC2626" /> <!-- red -->
|
<Setter Property="Background" Value="#DC2626" /> <!-- red -->
|
||||||
<Setter Property="Opacity" Value="0.6" />
|
<Setter Property="Opacity" Value="0.6" />
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style x:Key="PauseButtonStyle" TargetType="Button" BasedOn="{StaticResource PrimaryButtonStyle}">
|
||||||
|
<Setter Property="Background" Value="#F59E0B" /> <!-- yellow -->
|
||||||
|
<Setter Property="Height" Value="40" />
|
||||||
|
</Style>
|
||||||
<Style x:Key="RefreshButtonStyle" TargetType="Button" BasedOn="{StaticResource PrimaryButtonStyle}">
|
<Style x:Key="RefreshButtonStyle" TargetType="Button" BasedOn="{StaticResource PrimaryButtonStyle}">
|
||||||
<Setter Property="Background" Value="#0EA5E9" /> <!-- blue -->
|
<Setter Property="Background" Value="#0EA5E9" /> <!-- blue -->
|
||||||
<Setter Property="Height" Value="30" />
|
<Setter Property="Height" Value="30" />
|
||||||
@@ -77,68 +81,91 @@
|
|||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" /> <!-- Start -->
|
<RowDefinition Height="Auto" /> <!-- Start -->
|
||||||
|
<RowDefinition Height="Auto" /> <!-- Pause -->
|
||||||
<RowDefinition Height="Auto" /> <!-- Stop -->
|
<RowDefinition Height="Auto" /> <!-- Stop -->
|
||||||
<RowDefinition Height="Auto" /> <!-- Back/Refresh -->
|
<RowDefinition Height="Auto" /> <!-- Back/Refresh/Clear -->
|
||||||
<RowDefinition Height="Auto" /> <!-- Site -->
|
<RowDefinition Height="Auto" /> <!-- Site -->
|
||||||
<RowDefinition Height="Auto" /> <!-- Stats -->
|
<RowDefinition Height="Auto" /> <!-- Stats -->
|
||||||
<RowDefinition Height="Auto" /> <!-- Settings -->
|
<RowDefinition Height="Auto" /> <!-- Settings -->
|
||||||
<RowDefinition Height="Auto" /> <!-- Price -->
|
<RowDefinition Height="Auto" /> <!-- Price -->
|
||||||
|
<RowDefinition Height="Auto" /> <!-- Bidders label -->
|
||||||
|
<RowDefinition Height="Auto" /> <!-- Bidders grid -->
|
||||||
<RowDefinition Height="Auto" /> <!-- Log label -->
|
<RowDefinition Height="Auto" /> <!-- Log label -->
|
||||||
<RowDefinition Height="*" /> <!-- Log box expands -->
|
<RowDefinition Height="*" /> <!-- Log box expands -->
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Button x:Name="StartButton" Grid.Row="0" Style="{StaticResource StartButtonStyle}" Click="StartButton_Click" Margin="12,12,12,0">Avvia</Button>
|
<Button x:Name="StartButton" Grid.Row="0" Style="{StaticResource StartButtonStyle}" Click="StartButton_Click" Margin="12,12,12,0">Avvia</Button>
|
||||||
<Button x:Name="StopButton" Grid.Row="1" Style="{StaticResource StopButtonStyle}" Click="StopButton_Click" IsEnabled="False" Margin="12,8,12,0">Stop</Button>
|
|
||||||
|
|
||||||
<StackPanel Grid.Row="2" Orientation="Horizontal" Margin="12,8,12,0">
|
<Button x:Name="PauseBidButton" Grid.Row="1" Style="{StaticResource PauseButtonStyle}" Click="PauseBidButton_Click" Margin="12,8,12,0">Pausa</Button>
|
||||||
<Button x:Name="BackButton" Style="{StaticResource RefreshButtonStyle}" Click="BackButton_Click" Width="80" Height="30">Indietro</Button>
|
|
||||||
<Button x:Name="RefreshButton" Style="{StaticResource RefreshButtonStyle}" Click="RefreshButton_Click" Width="80" Height="30" Margin="8,0,0,0">Aggiorna</Button>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<StackPanel Grid.Row="3" Orientation="Vertical" Margin="12,12,12,0">
|
<Button x:Name="StopButton" Grid.Row="2" Style="{StaticResource StopButtonStyle}" Click="StopButton_Click" IsEnabled="False" Margin="12,8,12,0">Stop</Button>
|
||||||
|
|
||||||
|
<!-- Back / Refresh / ClearStats on same line -->
|
||||||
|
<Grid Grid.Row="3" Margin="12,8,12,0">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="8" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="8" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Button x:Name="BackButton" Grid.Column="0" Style="{StaticResource RefreshButtonStyle}" Click="BackButton_Click" Height="40">Indietro</Button>
|
||||||
|
<Button x:Name="RefreshButton" Grid.Column="2" Style="{StaticResource RefreshButtonStyle}" Click="RefreshButton_Click" Height="40">Aggiorna</Button>
|
||||||
|
<Button x:Name="ClearStatsButton" Grid.Column="4" Style="{StaticResource RefreshButtonStyle}" Click="ClearStatsButton_Click" Height="40">Pulisci</Button>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="4" Orientation="Vertical" Margin="12,12,12,0">
|
||||||
<TextBlock Text="Sito:" />
|
<TextBlock Text="Sito:" />
|
||||||
<TextBlock x:Name="SiteLinkText" Text="https://it.bidoo.com" TextWrapping="Wrap" FontWeight="Bold" />
|
<TextBlock x:Name="SiteLinkText" Text="https://it.bidoo.com" TextWrapping="Wrap" FontWeight="Bold" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel Grid.Row="4" Orientation="Horizontal" Margin="12,8,12,0">
|
<StackPanel Grid.Row="5" Orientation="Horizontal" Margin="12,8,12,0">
|
||||||
<TextBlock Text="Auto-click:" Margin="0,0,8,0" />
|
<TextBlock Text="Auto-click:" Margin="0,0,8,0" />
|
||||||
<TextBlock x:Name="ClickCountText" Text="0" FontWeight="Bold" Margin="0,0,12,0" />
|
<TextBlock x:Name="ClickCountText" Text="0" FontWeight="Bold" Margin="0,0,12,0" />
|
||||||
<TextBlock Text="Resets:" Margin="0,0,8,0" />
|
<TextBlock Text="Resets:" Margin="0,0,8,0" />
|
||||||
<TextBlock x:Name="ResetCountText" Text="0" FontWeight="Bold" />
|
<TextBlock x:Name="ResetCountText" Text="0" FontWeight="Bold" />
|
||||||
</StackPanel>
|
<TextBlock Text="Prezzo corrente:" Margin="12,0,6,0" VerticalAlignment="Center" />
|
||||||
|
<TextBlock x:Name="CurrentPriceText" Text="-" FontWeight="Bold" VerticalAlignment="Center" />
|
||||||
<StackPanel Grid.Row="5" Orientation="Horizontal" Margin="12,8,12,0">
|
|
||||||
<StackPanel Orientation="Vertical">
|
|
||||||
<TextBlock>Max Clicks</TextBlock>
|
|
||||||
<TextBox x:Name="MaxClicksBox" Style="{StaticResource NumericBoxStyle}" Text="0" ToolTip="0 = nessun limite" />
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<StackPanel Orientation="Vertical" Margin="12,0,0,0">
|
|
||||||
<TextBlock>Max Resets</TextBlock>
|
|
||||||
<TextBox x:Name="MaxResetsBox" Style="{StaticResource NumericBoxStyle}" Text="0" ToolTip="0 = nessun limite" />
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel Grid.Row="6" Orientation="Horizontal" Margin="12,8,12,0">
|
<StackPanel Grid.Row="6" Orientation="Horizontal" Margin="12,8,12,0">
|
||||||
|
<StackPanel Orientation="Vertical">
|
||||||
|
<TextBlock>Max Clicks</TextBlock>
|
||||||
|
<TextBox x:Name="MaxClicksBox" Style="{StaticResource NumericBoxStyle}" Text="0" ToolTip="0 = nessun limite" TextChanged="MaxClicksBox_TextChanged" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Vertical" Margin="12,0,0,0">
|
||||||
|
<TextBlock>Max Resets</TextBlock>
|
||||||
|
<TextBox x:Name="MaxResetsBox" Style="{StaticResource NumericBoxStyle}" Text="0" ToolTip="0 = nessun limite" TextChanged="MaxResetsBox_TextChanged" />
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Move price as its own row under settings -->
|
||||||
|
<StackPanel Grid.Row="7" Orientation="Horizontal" Margin="12,8,12,0">
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<TextBlock>Min Price</TextBlock>
|
<TextBlock>Min Price</TextBlock>
|
||||||
<TextBox x:Name="MinPriceBox" Style="{StaticResource NumericBoxStyle}" Text="0" ToolTip="0 = nessun limite" />
|
<TextBox x:Name="MinPriceBox" Style="{StaticResource NumericBoxStyle}" Text="0" ToolTip="0 = nessun limite" TextChanged="MinPriceBox_TextChanged" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel Orientation="Vertical" Margin="12,0,0,0">
|
<StackPanel Orientation="Vertical" Margin="12,0,0,0">
|
||||||
<TextBlock>Max Price</TextBlock>
|
<TextBlock>Max Price</TextBlock>
|
||||||
<TextBox x:Name="MaxPriceBox" Style="{StaticResource NumericBoxStyle}" Text="0" ToolTip="0 = nessun limite" />
|
<TextBox x:Name="MaxPriceBox" Style="{StaticResource NumericBoxStyle}" Text="0" ToolTip="0 = nessun limite" TextChanged="MaxPriceBox_TextChanged" />
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<StackPanel Orientation="Vertical" Margin="12,0,0,0">
|
|
||||||
<TextBlock>Prezzo corrente</TextBlock>
|
|
||||||
<TextBlock x:Name="CurrentPriceText" Text="-" FontWeight="Bold" />
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<TextBlock Grid.Row="7" Margin="12,12,12,6" Text="Log operazioni:" />
|
<TextBlock Grid.Row="8" Margin="12,12,12,6" Text="Elenco scommettitori (per numero scommesse):" />
|
||||||
|
|
||||||
<TextBox x:Name="LogBox" Grid.Row="8" Margin="12" IsReadOnly="True" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" AcceptsReturn="True" Style="{StaticResource LogBoxStyle}" />
|
<DataGrid x:Name="BiddersGrid" Grid.Row="9" Margin="12,0,12,0" AutoGenerateColumns="False" HeadersVisibility="Column" CanUserAddRows="False" IsReadOnly="True" Height="120" Background="#091018" RowBackground="#0B1220" AlternatingRowBackground="#081016">
|
||||||
|
<DataGrid.Columns>
|
||||||
|
<DataGridTextColumn Header="Utente" Binding="{Binding Name}" Width="*" />
|
||||||
|
<DataGridTextColumn Header="Scommesse" Binding="{Binding Count}" Width="120" />
|
||||||
|
</DataGrid.Columns>
|
||||||
|
</DataGrid>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="10" Margin="12,12,12,6" Text="Log operazioni:" />
|
||||||
|
|
||||||
|
<TextBox x:Name="LogBox" Grid.Row="11" Margin="12" IsReadOnly="True" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" AcceptsReturn="True" Style="{StaticResource LogBoxStyle}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,44 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using Microsoft.Web.WebView2.Core;
|
using Microsoft.Web.WebView2.Core;
|
||||||
|
|
||||||
namespace AutoBidder
|
namespace AutoBidder
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Interaction logic for MainWindow.xaml
|
|
||||||
/// </summary>
|
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
private CancellationTokenSource? _cts;
|
private CancellationTokenSource? _cts;
|
||||||
private Task? _automationTask;
|
private Task? _automationTask;
|
||||||
|
private volatile bool _pauseBids = false;
|
||||||
|
private readonly Dictionary<string, int> _bidders = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
private readonly List<string> _pendingLogs = new();
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
// create a simple programmatic icon (circle with AB) and assign to window
|
|
||||||
|
// flush any pending logs that may have been recorded during XAML initialization
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (LogBox != null && _pendingLogs.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var e in _pendingLogs)
|
||||||
|
{
|
||||||
|
try { LogBox.AppendText(e); } catch { }
|
||||||
|
}
|
||||||
|
try { LogBox.ScrollToEnd(); } catch { }
|
||||||
|
_pendingLogs.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const int size = 64;
|
const int size = 64;
|
||||||
@@ -35,157 +53,98 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
var rtb = new RenderTargetBitmap(size, size, 96, 96, PixelFormats.Pbgra32);
|
var rtb = new RenderTargetBitmap(size, size, 96, 96, PixelFormats.Pbgra32);
|
||||||
rtb.Render(dv);
|
rtb.Render(dv);
|
||||||
this.Icon = rtb; // set window and taskbar icon
|
this.Icon = rtb;
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignore icon errors
|
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
// initial visual states: start is primary action
|
// UI initial state
|
||||||
StartButton.IsEnabled = true;
|
StartButton.IsEnabled = true;
|
||||||
StartButton.Opacity = 1.0;
|
StartButton.Opacity = 1.0;
|
||||||
StopButton.IsEnabled = false;
|
StopButton.IsEnabled = false;
|
||||||
StopButton.Opacity = 0.5;
|
StopButton.Opacity = 0.5;
|
||||||
BackButton.IsEnabled = false;
|
BackButton.IsEnabled = false;
|
||||||
|
|
||||||
// navigation completed -> update back button state
|
|
||||||
webView.NavigationCompleted += WebView_NavigationCompleted;
|
webView.NavigationCompleted += WebView_NavigationCompleted;
|
||||||
|
UpdatePauseButtonContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WebView_NavigationCompleted(object? sender, CoreWebView2NavigationCompletedEventArgs e)
|
private void WebView_NavigationCompleted(object? sender, CoreWebView2NavigationCompletedEventArgs e)
|
||||||
{
|
{
|
||||||
UpdateBackButton();
|
try
|
||||||
|
{
|
||||||
|
BackButton.IsEnabled = webView.CoreWebView2 != null && webView.CoreWebView2.CanGoBack;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var url = webView.CoreWebView2?.Source ?? webView.Source?.ToString();
|
||||||
|
if (!string.IsNullOrEmpty(url)) SiteLinkText.Text = url!;
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateBackButton()
|
private void MaxClicksBox_TextChanged(object sender, TextChangedEventArgs e) => Log("Impostazione Max Clicks cambiata: " + MaxClicksBox.Text);
|
||||||
|
private void MaxResetsBox_TextChanged(object sender, TextChangedEventArgs e) => Log("Impostazione Max Resets cambiata: " + MaxResetsBox.Text);
|
||||||
|
private void MinPriceBox_TextChanged(object sender, TextChangedEventArgs e) => Log("Impostazione Min Price cambiata: " + MinPriceBox.Text);
|
||||||
|
private void MaxPriceBox_TextChanged(object sender, TextChangedEventArgs e) => Log("Impostazione Max Price cambiata: " + MaxPriceBox.Text);
|
||||||
|
|
||||||
|
private void ClearStatsButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
ClickCountText.Text = "0";
|
||||||
|
ResetCountText.Text = "0";
|
||||||
|
Log("Statistiche resettate dall'utente");
|
||||||
|
_bidders.Clear();
|
||||||
|
UpdateBiddersGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PauseBidButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
_pauseBids = !_pauseBids;
|
||||||
|
UpdatePauseButtonContent();
|
||||||
|
Log(_pauseBids ? "Modalità pausa puntata attivata" : "Modalità pausa puntata disattivata");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatePauseButtonContent()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Dispatcher.Invoke(() =>
|
Dispatcher.Invoke(() =>
|
||||||
{
|
{
|
||||||
BackButton.IsEnabled = webView.CoreWebView2 != null && webView.CoreWebView2.CanGoBack;
|
var btn = FindName("PauseBidButton") as Button;
|
||||||
try
|
if (btn != null) btn.Content = _pauseBids ? "Riprendi" : "Pausa";
|
||||||
{
|
|
||||||
string? url = null;
|
|
||||||
if (webView.CoreWebView2 != null)
|
|
||||||
{
|
|
||||||
url = webView.CoreWebView2.Source;
|
|
||||||
}
|
|
||||||
else if (webView.Source != null)
|
|
||||||
{
|
|
||||||
url = webView.Source.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(url)) SiteLinkText.Text = url;
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void StartButton_Click(object sender, RoutedEventArgs e)
|
private void UpdateBiddersGrid()
|
||||||
{
|
|
||||||
StartButton.IsEnabled = false;
|
|
||||||
StopButton.IsEnabled = true;
|
|
||||||
// visual feedback: running -> stop is primary
|
|
||||||
StartButton.Opacity = 0.5;
|
|
||||||
StopButton.Opacity = 1.0;
|
|
||||||
|
|
||||||
Log("Inizializzazione web...");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Ensure WebView2 is initialized
|
|
||||||
if (webView.CoreWebView2 == null)
|
|
||||||
{
|
|
||||||
await webView.EnsureCoreWebView2Async();
|
|
||||||
}
|
|
||||||
UpdateBackButton();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
var msg = "Errore inizializzazione WebView2: " + ex.Message;
|
|
||||||
Log(msg);
|
|
||||||
StartButton.IsEnabled = true;
|
|
||||||
StopButton.IsEnabled = false;
|
|
||||||
StartButton.Opacity = 1.0;
|
|
||||||
StopButton.Opacity = 0.5;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log("Avviato: WebView inizializzato. Avvio monitoraggio pagina.");
|
|
||||||
|
|
||||||
_cts = new CancellationTokenSource();
|
|
||||||
var token = _cts.Token;
|
|
||||||
_automationTask = Task.Run(async () => await AutomationLoop(token), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StopButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
// visual feedback: stopped -> start is primary
|
|
||||||
StartButton.Opacity = 1.0;
|
|
||||||
StopButton.Opacity = 0.5;
|
|
||||||
StopAutomation("Arrestato dall'utente");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BackButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (webView.CoreWebView2 == null)
|
Dispatcher.Invoke(() =>
|
||||||
{
|
{
|
||||||
// if not initialized, try ensuring
|
var grid = FindName("BiddersGrid") as DataGrid;
|
||||||
_ = webView.EnsureCoreWebView2Async();
|
if (grid != null)
|
||||||
}
|
|
||||||
|
|
||||||
if (webView.CoreWebView2 != null && webView.CoreWebView2.CanGoBack)
|
|
||||||
{
|
{
|
||||||
webView.CoreWebView2.GoBack();
|
var list = _bidders.Select(kvp => new { Name = kvp.Key, Count = kvp.Value }).OrderByDescending(x => x.Count).ToList();
|
||||||
|
grid.ItemsSource = list;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log("Errore navigazione indietro: " + ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void RefreshButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (webView.CoreWebView2 == null)
|
|
||||||
{
|
|
||||||
await webView.EnsureCoreWebView2Async();
|
|
||||||
}
|
|
||||||
webView.CoreWebView2?.Reload();
|
|
||||||
Log("Pagina aggiornata");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log("Errore aggiornamento pagina: " + ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StopAutomation(string reason)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_cts?.Cancel();
|
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
StartButton.Dispatcher.Invoke(() =>
|
private void SetCurrentPriceText(string text)
|
||||||
{
|
{
|
||||||
StartButton.IsEnabled = true;
|
try
|
||||||
StopButton.IsEnabled = false;
|
{
|
||||||
// reset visual states: start primary
|
Dispatcher.Invoke(() =>
|
||||||
StartButton.Opacity = 1.0;
|
{
|
||||||
StopButton.Opacity = 0.5;
|
var tb = FindName("CurrentPriceText") as TextBlock;
|
||||||
|
if (tb != null) tb.Text = text;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
Log("STOP: " + reason);
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Log(string message)
|
private void Log(string message)
|
||||||
@@ -200,120 +159,72 @@ namespace AutoBidder
|
|||||||
LogBox.AppendText(entry);
|
LogBox.AppendText(entry);
|
||||||
LogBox.ScrollToEnd();
|
LogBox.ScrollToEnd();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// fallback: buffer if LogBox not ready
|
||||||
|
try { _pendingLogs.Add(entry); } catch { }
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// ignore logging errors
|
try { _pendingLogs.Add(entry); } catch { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void StartButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
StartButton.IsEnabled = false;
|
||||||
|
StopButton.IsEnabled = true;
|
||||||
|
StartButton.Opacity = 0.5;
|
||||||
|
StopButton.Opacity = 1.0;
|
||||||
|
|
||||||
|
Log("Inizializzazione web...");
|
||||||
|
try { if (webView.CoreWebView2 == null) await webView.EnsureCoreWebView2Async(); }
|
||||||
|
catch (Exception ex) { Log("Errore inizializzazione WebView2: " + ex.Message); StartButton.IsEnabled = true; StopButton.IsEnabled = false; return; }
|
||||||
|
|
||||||
|
Log("Avviato: WebView inizializzato. Avvio monitoraggio pagina.");
|
||||||
|
_cts = new CancellationTokenSource();
|
||||||
|
_automationTask = Task.Run(() => AutomationLoop(_cts.Token));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
StartButton.Opacity = 1.0; StopButton.Opacity = 0.5; StopAutomation("Arrestato dall'utente");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BackButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
try { if (webView.CoreWebView2 == null) _ = webView.EnsureCoreWebView2Async(); if (webView.CoreWebView2 != null && webView.CoreWebView2.CanGoBack) webView.CoreWebView2.GoBack(); }
|
||||||
|
catch (Exception ex) { Log("Errore navigazione indietro: " + ex.Message); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void RefreshButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
try { if (webView.CoreWebView2 == null) await webView.EnsureCoreWebView2Async(); webView.CoreWebView2?.Reload(); Log("Pagina aggiornata"); }
|
||||||
|
catch (Exception ex) { Log("Errore aggiornamento pagina: " + ex.Message); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopAutomation(string reason)
|
||||||
|
{
|
||||||
|
try { _cts?.Cancel(); } catch { }
|
||||||
|
StartButton.IsEnabled = true; StopButton.IsEnabled = false; StartButton.Opacity = 1.0; StopButton.Opacity = 0.5;
|
||||||
|
Log("STOP: " + reason);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task AutomationLoop(CancellationToken token)
|
private async Task AutomationLoop(CancellationToken token)
|
||||||
{
|
{
|
||||||
int clickCount = 0;
|
int clickCount = 0; int resetCount = 0; string? previousTimer = null;
|
||||||
int resetCount = 0;
|
|
||||||
string? previousTimer = null;
|
|
||||||
|
|
||||||
// read limits from UI
|
|
||||||
int maxClicks = 0;
|
|
||||||
int maxResets = 0;
|
|
||||||
double minPrice = 0.0;
|
|
||||||
double maxPrice = double.MaxValue;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Dispatcher.Invoke(() =>
|
|
||||||
{
|
|
||||||
int.TryParse(MaxClicksBox.Text, out maxClicks);
|
|
||||||
int.TryParse(MaxResetsBox.Text, out maxResets);
|
|
||||||
if (maxClicks <= 0) maxClicks = int.MaxValue;
|
|
||||||
if (maxResets <= 0) maxResets = int.MaxValue;
|
|
||||||
|
|
||||||
// price bounds: 0 = no limit
|
|
||||||
if (!double.TryParse(MinPriceBox.Text.Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out minPrice)) minPrice = 0.0;
|
|
||||||
if (!double.TryParse(MaxPriceBox.Text.Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var tmpMax)) tmpMax = 0.0;
|
|
||||||
if (tmpMax <= 0) maxPrice = double.MaxValue; else maxPrice = tmpMax;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch { maxClicks = int.MaxValue; maxResets = int.MaxValue; minPrice = 0.0; maxPrice = double.MaxValue; }
|
|
||||||
|
|
||||||
// post-click delay to avoid duplicate actions
|
|
||||||
// increased delay to click as late as possible (milliseconds)
|
|
||||||
const int postClickDelayMs = 1200;
|
const int postClickDelayMs = 1200;
|
||||||
|
|
||||||
// Improved JS snippet: find PUNTA anchor/button by class or text, find nearby numeric timer elements (including svg text) and price
|
const string findScript = @"(function(){ function isVisible(el){ if(!el) return false; try{ var r=el.getBoundingClientRect(); var s=window.getComputedStyle(el); return r.width>0 && r.height>0 && s.visibility!=='hidden' && s.display!=='none'; }catch(e){ return false; } } var priceText=''; try{ var p=document.querySelector('.auction-action-price strong, .auction-action-price'); if(p) priceText=(p.textContent||p.innerText||'').trim(); }catch(e){} var priceVal=null; try{ if(priceText){ var p=priceText.replace('€','').replace(/\./g,'').replace(',','.').match(/\d+(?:\.\d+)?/); if(p) priceVal=p[0]; } }catch(e){} var btn=document.querySelector('a.auction-btn-bid, a.bid-button, .auction-btn-bid'); if(btn && isVisible(btn)){ var txt=(btn.textContent||btn.innerText||'').trim(); if(/\bINIZIA\b/i.test(txt)) return JSON.stringify({status:'soon', debug:txt, price: priceVal}); } try{ var direct=document.querySelector('.text-countdown-progressbar'); if(direct && isVisible(direct)){ var t=(direct.textContent||'').trim(); var m=t.match(/\d+/); if(m) return JSON.stringify({status:'found', timer:m[0], price: priceVal, debug: direct.outerHTML}); } }catch(e){} if(!btn || !isVisible(btn)){ var candidates=Array.from(document.querySelectorAll('a, button, div, span')).filter(e=> e && (e.innerText||e.textContent) && /\bPUNTA\b/i.test((e.innerText||e.textContent)) && isVisible(e)); if(candidates.length>0) btn=candidates[0]; } if(!btn) return JSON.stringify({status:'no-button', price: priceVal}); var nodeList=Array.from(document.querySelectorAll('div, span, p, strong, b, i, em, label, small, a, svg text')); var nums=nodeList.map(e=>{ try{return {el:e, text:(e.textContent||'').trim(), rect:e.getBoundingClientRect(), html:(e.outerHTML||'')}; }catch(err){ return null; }}).filter(x=> x && /\d+/.test(x.text)).map(x=>({el:x.el, text:x.text, rect:x.rect, html:x.html})); if(nums.length==0) return JSON.stringify({status:'no-timer', price: priceVal}); function distanceRect(a,b){ var ax=(a.left+a.right)/2, ay=(a.top+a.bottom)/2; var bx=(b.left+b.right)/2, by=(b.top+b.bottom)/2; return Math.hypot(ax-bx, ay-by); } var btnRect; try{ btnRect = btn.getBoundingClientRect(); }catch(e){ btnRect = {top:0,left:0,right:0,bottom:0,width:0,height:0}; } nums.sort(function(a,b){ var da = distanceRect(a.rect, btnRect); var db = distanceRect(b.rect, btnRect); var ya = btnRect.top - a.rect.bottom; var yb = btnRect.top - b.rect.bottom; var pref = (ya>=0?0:200) - (yb>=0?0:200); return (da - db) + pref; }); var best=nums[0]; var m=(best.text||'').match(/\d+/); if(!m) return JSON.stringify({status:'no-timer-extracted', debug: best.html, price: priceVal}); return JSON.stringify({status:'found', timer:m[0], price: priceVal, debug: best.html}); })();";
|
||||||
const string findScript = @"(function(){
|
|
||||||
function isVisible(el){ if(!el) return false; try{ var r=el.getBoundingClientRect(); var s=window.getComputedStyle(el); return r.width>0 && r.height>0 && s.visibility!=='hidden' && s.display!=='none'; }catch(e){ return false; } }
|
|
||||||
|
|
||||||
// find price
|
const string clickScript = @"(function(){ var btn=document.querySelector('a.auction-btn-bid, a.bid-button, .auction-btn-bid'); if(!btn){ var candidates=Array.from(document.querySelectorAll('a, button, div, span')).filter(e=> e && (e.innerText||e.textContent) && /\bPUNTA\b/i.test((e.innerText||e.textContent))); if(candidates.length>0) btn=candidates[0]; } if(!btn) return 'no-button'; try{ btn.click(); return 'clicked'; }catch(e){ try{ var evt=document.createEvent('MouseEvents'); evt.initEvent('click', true, true); btn.dispatchEvent(evt); return 'dispatched'; }catch(ex){ return 'error:'+ (ex && ex.message?ex.message:ex); } } })();";
|
||||||
var priceText = '';
|
|
||||||
try{ var pEl = document.querySelector('.auction-action-price strong, .auction-action-price'); if(pEl) priceText = (pEl.textContent||pEl.innerText||'').trim(); }catch(e){}
|
|
||||||
var priceVal = null;
|
|
||||||
try{ if(priceText){ var p = priceText.replace('€','').replace(/\./g,'').replace(',','.').match(/\d+(?:\.\d+)?/); if(p) priceVal = p[0]; } }catch(e){}
|
|
||||||
|
|
||||||
// Try to find a bid button that might say PUNTA or INIZIA
|
const string getLastBidderScript = @"(function(){ try{ var el=document.querySelector('.auction-current-winner'); if(el){ var name=(el.textContent||el.innerText||'').trim(); if(name) return JSON.stringify({status:'found', bidder:name}); } }catch(e){} return JSON.stringify({status:'not-found'}); })();";
|
||||||
var btn = document.querySelector('a.auction-btn-bid, a.bid-button, .auction-btn-bid');
|
|
||||||
if(btn && isVisible(btn)){
|
|
||||||
var txt = (btn.textContent||btn.innerText||'').trim();
|
|
||||||
if(/\bINIZIA\b/i.test(txt)){
|
|
||||||
return JSON.stringify({status:'soon', debug: txt, price: priceVal});
|
|
||||||
}
|
|
||||||
if(/\bPUNTA\b/i.test(txt)){
|
|
||||||
// continue to find timer normally
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prefer direct countdown element by known class
|
const string pricePollScript = @"(function(){ var p=document.querySelector('.auction-action-price strong, .auction-action-price'); if(!p) return null; var t=(p.textContent||p.innerText||'').trim(); var num=t.replace('€','').replace(/\./g,'').replace(',','.').match(/\d+(?:\.\d+)?/); return num?num[0]:null; })();";
|
||||||
try{
|
|
||||||
var direct = document.querySelector('.text-countdown-progressbar');
|
|
||||||
if(direct && isVisible(direct)){
|
|
||||||
var t = (direct.textContent||'').trim();
|
|
||||||
var m = t.match(/\d+/);
|
|
||||||
if(m) return JSON.stringify({status:'found', timer:m[0], price: priceVal, debug: direct.outerHTML});
|
|
||||||
// if no digits, continue to fallback
|
|
||||||
}
|
|
||||||
}catch(err){ /* ignore */ }
|
|
||||||
|
|
||||||
if(!btn || !isVisible(btn)){
|
|
||||||
var candidates = Array.from(document.querySelectorAll('a, button, div, span')).filter(e=> e && (e.innerText||e.textContent) && /\bPUNTA\b/i.test((e.innerText||e.textContent)) && isVisible(e));
|
|
||||||
if(candidates.length>0) btn = candidates[0];
|
|
||||||
}
|
|
||||||
if(!btn) return JSON.stringify({status:'no-button', price: priceVal});
|
|
||||||
|
|
||||||
var btnRect; try{ btnRect = btn.getBoundingClientRect(); }catch(e){ btnRect = {top:0,left:0,right:0,bottom:0,width:0,height:0}; }
|
|
||||||
|
|
||||||
// collect possible numeric-containing elements, including svg text
|
|
||||||
var nodeList = Array.from(document.querySelectorAll('div, span, p, strong, b, i, em, label, small, a, svg text'));
|
|
||||||
var nums = nodeList.map(e=>{ try{return {el:e, text:(e.textContent||'').trim(), rect:e.getBoundingClientRect(), html:(e.outerHTML||'')}; }catch(err){ return null; }}).filter(x=> x && /\d+/.test(x.text)).map(x=>({el:x.el, text:x.text, rect:x.rect, html:x.html}));
|
|
||||||
|
|
||||||
if(nums.length==0) return JSON.stringify({status:'no-timer', price: priceVal});
|
|
||||||
|
|
||||||
// prefer elements that are visually near and above the button
|
|
||||||
function distanceRect(a,b){ var ax=(a.left+a.right)/2, ay=(a.top+a.bottom)/2; var bx=(b.left+b.right)/2, by=(b.top+b.bottom)/2; return Math.hypot(ax-bx, ay-by); }
|
|
||||||
|
|
||||||
nums.sort(function(a,b){
|
|
||||||
var da = distanceRect(a.rect, btnRect);
|
|
||||||
var db = distanceRect(b.rect, btnRect);
|
|
||||||
var ya = btnRect.top - a.rect.bottom;
|
|
||||||
var yb = btnRect.top - b.rect.bottom;
|
|
||||||
var pref = (ya>=0?0:200) - (yb>=0?0:200);
|
|
||||||
return (da - db) + pref;
|
|
||||||
});
|
|
||||||
|
|
||||||
var best = nums[0];
|
|
||||||
var m = (best.text||'').match(/\d+/);
|
|
||||||
if(!m) return JSON.stringify({status:'no-timer-extracted', debug: best.html, price: priceVal});
|
|
||||||
return JSON.stringify({status:'found', timer:m[0], price: priceVal, debug: best.html});
|
|
||||||
})();";
|
|
||||||
|
|
||||||
const string clickScript = @"(function(){
|
|
||||||
var btn = document.querySelector('a.auction-btn-bid, a.bid-button, .auction-btn-bid');
|
|
||||||
if(!btn){ var candidates = Array.from(document.querySelectorAll('a, button, div, span')).filter(e=> e && (e.innerText||e.textContent) && /\bPUNTA\b/i.test((e.innerText||e.textContent))); if(candidates.length>0) btn=candidates[0]; }
|
|
||||||
if(!btn) return 'no-button';
|
|
||||||
try{ btn.click(); return 'clicked'; }catch(e){ try{ var evt = document.createEvent('MouseEvents'); evt.initEvent('click', true, true); btn.dispatchEvent(evt); return 'dispatched'; }catch(ex){ return 'error:'+ (ex && ex.message?ex.message:ex); } }
|
|
||||||
})();";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (!token.IsCancellationRequested)
|
while (!token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
string? result = null;
|
string? result = null;
|
||||||
@@ -323,10 +234,7 @@ namespace AutoBidder
|
|||||||
var innerTask = await op.Task.ConfigureAwait(false);
|
var innerTask = await op.Task.ConfigureAwait(false);
|
||||||
result = await innerTask.ConfigureAwait(false);
|
result = await innerTask.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException) { break; }
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log("Errore JS/interop: " + ex.Message);
|
Log("Errore JS/interop: " + ex.Message);
|
||||||
@@ -334,11 +242,19 @@ namespace AutoBidder
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string json = result ?? "";
|
string json = result ?? string.Empty;
|
||||||
if (json.Length >= 2 && json[0] == '"' && json[^1] == '"')
|
if (json.Length >= 2 && json[0] == '"' && json[^1] == '"') json = JsonSerializer.Deserialize<string>(json) ?? json;
|
||||||
|
|
||||||
|
// read limits each iteration
|
||||||
|
int maxClicks = int.MaxValue, maxResets = int.MaxValue; double minPrice = 0.0, maxPrice = double.MaxValue;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
json = System.Text.Json.JsonSerializer.Deserialize<string>(result) ?? json;
|
if (int.TryParse(MaxClicksBox.Text, out var mc) && mc > 0) maxClicks = mc;
|
||||||
|
if (int.TryParse(MaxResetsBox.Text, out var mr) && mr > 0) maxResets = mr;
|
||||||
|
if (double.TryParse(MinPriceBox.Text.Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var mp)) minPrice = mp;
|
||||||
|
if (double.TryParse(MaxPriceBox.Text.Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var mxa)) maxPrice = mxa > 0 ? mxa : double.MaxValue;
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -346,117 +262,66 @@ namespace AutoBidder
|
|||||||
var root = doc.RootElement;
|
var root = doc.RootElement;
|
||||||
var status = root.GetProperty("status").GetString();
|
var status = root.GetProperty("status").GetString();
|
||||||
|
|
||||||
// price may be present
|
// price update
|
||||||
string? priceStr = null;
|
|
||||||
double? priceVal = null;
|
|
||||||
if (root.TryGetProperty("price", out var priceEl) && priceEl.ValueKind != JsonValueKind.Null)
|
if (root.TryGetProperty("price", out var priceEl) && priceEl.ValueKind != JsonValueKind.Null)
|
||||||
{
|
{
|
||||||
priceStr = priceEl.GetString();
|
var priceStr = priceEl.GetString();
|
||||||
if (!string.IsNullOrEmpty(priceStr))
|
if (!string.IsNullOrEmpty(priceStr) && double.TryParse(priceStr.Replace(',', '.').Trim(), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var pval))
|
||||||
{
|
{
|
||||||
if (double.TryParse(priceStr.Replace(',', '.').Trim(), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var pval))
|
SetCurrentPriceText(pval.ToString("0.##") + " €");
|
||||||
{
|
|
||||||
priceVal = pval;
|
|
||||||
Dispatcher.Invoke(() => CurrentPriceText.Text = pval.ToString("0.##") + " €");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == "soon")
|
if (status == "soon")
|
||||||
{
|
{
|
||||||
Log("Stato: INIZIA TRA POCO. In attesa che appaia il pulsante PUNTA...");
|
Log("Stato: INIZIA TRA POCO. In attesa che appaia il pulsante PUNTA...");
|
||||||
// poll until PUNTA button appears (or cancellation)
|
|
||||||
while (!token.IsCancellationRequested)
|
while (!token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
string? chk = null;
|
var op2 = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(@"(function(){ var b=document.querySelector('a.auction-btn-bid, a.bid-button'); if(!b) return 'no'; var t=(b.textContent||b.innerText||'').trim(); return /PUNTA/i.test(t)?'yes':'no'; })();"));
|
||||||
try
|
|
||||||
{
|
|
||||||
var op2 = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync("(function(){ var b=document.querySelector('a.auction-btn-bid, a.bid-button'); if(!b) return 'no'; var t=(b.textContent||b.innerText||'').trim(); return /PUNTA/i.test(t)?'yes':'no'; })();"));
|
|
||||||
var inner2 = await op2.Task.ConfigureAwait(false);
|
var inner2 = await op2.Task.ConfigureAwait(false);
|
||||||
chk = await inner2.ConfigureAwait(false);
|
var chk = await inner2.ConfigureAwait(false);
|
||||||
}
|
|
||||||
catch { chk = null; }
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(chk))
|
if (!string.IsNullOrEmpty(chk))
|
||||||
{
|
{
|
||||||
if (chk.Length >= 2 && chk[0] == '"' && chk[^1] == '"') chk = JsonSerializer.Deserialize<string>(chk) ?? chk;
|
if (chk.Length >= 2 && chk[0] == '"' && chk[^1] == '"') chk = JsonSerializer.Deserialize<string>(chk) ?? chk;
|
||||||
if (chk == "yes")
|
if (chk == "yes") { Log("Pulsante PUNTA trovato. Riprendo esecuzione."); break; }
|
||||||
{
|
|
||||||
Log("Pulsante PUNTA trovato. Riprendo esecuzione.");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay(700, token).ConfigureAwait(false);
|
await Task.Delay(700, token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue; // next main loop iteration
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (status == "no-button")
|
|
||||||
{
|
|
||||||
Log("Nessun pulsante PUNTA trovato; arresto");
|
|
||||||
StopAutomation("Nessun pulsante PUNTA trovato; arresto");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (status == "no-button") { Log("Nessun pulsante PUNTA trovato; arresto"); StopAutomation("Nessun pulsante PUNTA trovato; arresto"); return; }
|
||||||
if (status == "no-timer" || status == "no-timer-extracted")
|
if (status == "no-timer" || status == "no-timer-extracted")
|
||||||
{
|
{
|
||||||
// Pause: wait until timer reappears
|
|
||||||
Log("Timer non trovato: pausa in corso, verrà ripreso quando il timer ricompare");
|
Log("Timer non trovato: pausa in corso, verrà ripreso quando il timer ricompare");
|
||||||
bool resumed = false;
|
bool resumed = false;
|
||||||
while (!token.IsCancellationRequested)
|
while (!token.IsCancellationRequested)
|
||||||
{
|
|
||||||
string? pollResult = null;
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var op3 = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(findScript));
|
var op3 = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(findScript));
|
||||||
var inner3 = await op3.Task.ConfigureAwait(false);
|
var inner3 = await op3.Task.ConfigureAwait(false);
|
||||||
pollResult = await inner3.ConfigureAwait(false);
|
var pollResult = await inner3.ConfigureAwait(false);
|
||||||
}
|
var pollStr = pollResult ?? string.Empty;
|
||||||
catch { pollResult = null; }
|
if (pollStr.Length >= 2 && pollStr[0] == '"' && pollStr[^1] == '"') pollStr = JsonSerializer.Deserialize<string>(pollStr) ?? pollStr;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(pollResult))
|
|
||||||
{
|
|
||||||
if (pollResult.Length >= 2 && pollResult[0] == '"' && pollResult[^1] == '"') pollResult = JsonSerializer.Deserialize<string>(pollResult) ?? pollResult;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using var doc2 = JsonDocument.Parse(pollResult);
|
using var doc2 = JsonDocument.Parse(pollStr);
|
||||||
var st2 = doc2.RootElement.GetProperty("status").GetString();
|
var st2 = doc2.RootElement.GetProperty("status").GetString();
|
||||||
if (st2 == "found" || st2 == "soon")
|
if (st2 == "found" || st2 == "soon") { Log("Timer ricomparso, ripresa."); resumed = true; break; }
|
||||||
{
|
if (st2 == "no-button") { Log("Nessun pulsante durante pausa; arresto"); StopAutomation("Nessun pulsante durante pausa"); return; }
|
||||||
Log("Timer ricomparso, ripresa.");
|
|
||||||
resumed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (st2 == "no-button")
|
|
||||||
{
|
|
||||||
Log("Nessun pulsante durante pausa; arresto");
|
|
||||||
StopAutomation("Nessun pulsante durante pausa");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay(800, token).ConfigureAwait(false);
|
await Task.Delay(800, token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!resumed) break;
|
if (!resumed) break;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == "found")
|
if (status == "found")
|
||||||
{
|
{
|
||||||
var timerValue = root.GetProperty("timer").GetString();
|
var timerValue = root.GetProperty("timer").GetString();
|
||||||
|
if (timerValue != previousTimer) { Log("Timer rilevato: " + timerValue); }
|
||||||
|
|
||||||
// only log when timer value actually changes
|
|
||||||
if (timerValue != previousTimer)
|
|
||||||
{
|
|
||||||
Log("Timer rilevato: " + timerValue);
|
|
||||||
|
|
||||||
// detect resets: if price available, enforce min/max bounds
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (previousTimer != null && int.TryParse(previousTimer, out var prev) && int.TryParse(timerValue, out var curr))
|
if (previousTimer != null && int.TryParse(previousTimer, out var prev) && int.TryParse(timerValue, out var curr))
|
||||||
@@ -464,36 +329,58 @@ namespace AutoBidder
|
|||||||
if (curr > prev)
|
if (curr > prev)
|
||||||
{
|
{
|
||||||
resetCount++;
|
resetCount++;
|
||||||
Dispatcher.Invoke(() => ResetCountText.Text = resetCount.ToString());
|
ResetCountText.Dispatcher.Invoke(() => ResetCountText.Text = resetCount.ToString());
|
||||||
Log("Timer resettato (contatore): " + resetCount);
|
|
||||||
// stop if reached limit
|
// Attempt to read current winner from page and update bidders list
|
||||||
if (resetCount >= maxResets)
|
try
|
||||||
{
|
{
|
||||||
StopAutomation($"Limite reset raggiunto: {resetCount}");
|
var opWin = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(getLastBidderScript));
|
||||||
return;
|
var innerWin = await opWin.Task.ConfigureAwait(false);
|
||||||
|
var lastWinRaw = await innerWin.ConfigureAwait(false);
|
||||||
|
if (!string.IsNullOrEmpty(lastWinRaw))
|
||||||
|
{
|
||||||
|
if (lastWinRaw.Length >= 2 && lastWinRaw[0] == '"' && lastWinRaw[^1] == '"') lastWinRaw = JsonSerializer.Deserialize<string>(lastWinRaw) ?? lastWinRaw;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var docW = JsonDocument.Parse(lastWinRaw);
|
||||||
|
var rootW = docW.RootElement;
|
||||||
|
if (rootW.GetProperty("status").GetString() == "found")
|
||||||
|
{
|
||||||
|
var winnerName = rootW.GetProperty("bidder").GetString();
|
||||||
|
if (!string.IsNullOrEmpty(winnerName))
|
||||||
|
{
|
||||||
|
if (_bidders.ContainsKey(winnerName)) _bidders[winnerName]++; else _bidders[winnerName] = 1;
|
||||||
|
UpdateBiddersGrid();
|
||||||
|
Log("Offerente registrato/reset: " + winnerName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
Log("Timer resettato (contatore): " + resetCount);
|
||||||
|
if (resetCount >= maxResets) { StopAutomation($"Limite reset raggiunto: {resetCount}"); return; }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
|
||||||
previousTimer = timerValue;
|
previousTimer = timerValue;
|
||||||
}
|
|
||||||
|
|
||||||
// price check: if price available, enforce min/max bounds
|
// price bounds handling
|
||||||
if (priceVal.HasValue)
|
if (root.TryGetProperty("price", out var pEl2) && pEl2.ValueKind != JsonValueKind.Null && double.TryParse((pEl2.GetString() ?? "").Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var pcur))
|
||||||
{
|
{
|
||||||
if (priceVal.Value < minPrice)
|
if (pcur < minPrice)
|
||||||
{
|
{
|
||||||
Log($"Prezzo {priceVal.Value:0.##}€ sotto limite minimo ({minPrice:0.##}). Pausa.");
|
Log($"Prezzo {pcur:0.##}€ sotto limite minimo ({minPrice:0.##}). Pausa.");
|
||||||
// wait until price >= minPrice
|
|
||||||
while (!token.IsCancellationRequested)
|
while (!token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
// poll price only
|
|
||||||
string? pricePoll = null;
|
string? pricePoll = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var opP = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(@"(function(){ var p=document.querySelector('.auction-action-price strong, .auction-action-price'); if(!p) return null; var t=(p.textContent||p.innerText||'').trim(); var num = t.replace('€','').replace(/\./g,'').replace(',','.').match(/\d+(?:\.\d+)?/); return num?num[0]:null; })();"));
|
var opP = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(pricePollScript));
|
||||||
var innerP = await opP.Task.ConfigureAwait(false);
|
var innerP = await opP.Task.ConfigureAwait(false);
|
||||||
pricePoll = await innerP.ConfigureAwait(false);
|
pricePoll = await innerP.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -504,12 +391,8 @@ namespace AutoBidder
|
|||||||
if (pricePoll.Length >= 2 && pricePoll[0] == '"' && pricePoll[^1] == '"') pricePoll = JsonSerializer.Deserialize<string>(pricePoll) ?? pricePoll;
|
if (pricePoll.Length >= 2 && pricePoll[0] == '"' && pricePoll[^1] == '"') pricePoll = JsonSerializer.Deserialize<string>(pricePoll) ?? pricePoll;
|
||||||
if (double.TryParse(pricePoll.Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var pp))
|
if (double.TryParse(pricePoll.Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var pp))
|
||||||
{
|
{
|
||||||
Dispatcher.Invoke(() => CurrentPriceText.Text = pp.ToString("0.##") + " €");
|
SetCurrentPriceText(pp.ToString("0.##") + " €");
|
||||||
if (pp >= minPrice)
|
if (pp >= minPrice) { Log("Prezzo salito sopra il minimo; ripresa esecuzione."); break; }
|
||||||
{
|
|
||||||
Log("Prezzo salito sopra il minimo; ripresa esecuzione.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,15 +400,15 @@ namespace AutoBidder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priceVal.Value > maxPrice)
|
if (pcur > maxPrice)
|
||||||
{
|
{
|
||||||
Log($"Prezzo {priceVal.Value:0.##}€ sopra limite massimo ({maxPrice:0.##}). Pausa.");
|
Log($"Prezzo {pcur:0.##}€ sopra limite massimo ({maxPrice:0.##}). Pausa.");
|
||||||
while (!token.IsCancellationRequested)
|
while (!token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
string? pricePoll = null;
|
string? pricePoll = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var opP = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(@"(function(){ var p=document.querySelector('.auction-action-price strong, .auction-action-price'); if(!p) return null; var t=(p.textContent||p.innerText||'').trim(); var num = t.replace('€','').replace(/\./g,'').replace(',','.').match(/\d+(?:\.\d+)?/); return num?num[0]:null; })();"));
|
var opP = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(pricePollScript));
|
||||||
var innerP = await opP.Task.ConfigureAwait(false);
|
var innerP = await opP.Task.ConfigureAwait(false);
|
||||||
pricePoll = await innerP.ConfigureAwait(false);
|
pricePoll = await innerP.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -536,12 +419,8 @@ namespace AutoBidder
|
|||||||
if (pricePoll.Length >= 2 && pricePoll[0] == '"' && pricePoll[^1] == '"') pricePoll = JsonSerializer.Deserialize<string>(pricePoll) ?? pricePoll;
|
if (pricePoll.Length >= 2 && pricePoll[0] == '"' && pricePoll[^1] == '"') pricePoll = JsonSerializer.Deserialize<string>(pricePoll) ?? pricePoll;
|
||||||
if (double.TryParse(pricePoll.Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var pp))
|
if (double.TryParse(pricePoll.Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var pp))
|
||||||
{
|
{
|
||||||
Dispatcher.Invoke(() => CurrentPriceText.Text = pp.ToString("0.##") + " €");
|
SetCurrentPriceText(pp.ToString("0.##") + " €");
|
||||||
if (pp <= maxPrice)
|
if (pp <= maxPrice) { Log("Prezzo sceso sotto il massimo; ripresa esecuzione."); break; }
|
||||||
{
|
|
||||||
Log("Prezzo sceso sotto il massimo; ripresa esecuzione.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,79 +431,74 @@ namespace AutoBidder
|
|||||||
|
|
||||||
if (timerValue == "0")
|
if (timerValue == "0")
|
||||||
{
|
{
|
||||||
// immediate click when timer reaches 0 (extreme test)
|
// get last bidder name from page
|
||||||
string clickResult;
|
string? lastBidderResult = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var op3 = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(getLastBidderScript));
|
||||||
|
var inner3 = await op3.Task.ConfigureAwait(false);
|
||||||
|
lastBidderResult = await inner3.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch { lastBidderResult = null; }
|
||||||
|
|
||||||
|
string? bidderName = null;
|
||||||
|
if (!string.IsNullOrEmpty(lastBidderResult))
|
||||||
|
{
|
||||||
|
if (lastBidderResult.Length >= 2 && lastBidderResult[0] == '"' && lastBidderResult[^1] == '"') lastBidderResult = JsonSerializer.Deserialize<string>(lastBidderResult) ?? lastBidderResult;
|
||||||
|
try { using var d3 = JsonDocument.Parse(lastBidderResult); var r3 = d3.RootElement; if (r3.GetProperty("status").GetString() == "found") bidderName = r3.GetProperty("bidder").GetString(); }
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_pauseBids)
|
||||||
|
{
|
||||||
|
string? clickResult = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var op2 = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(clickScript));
|
var op2 = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(clickScript));
|
||||||
var inner2 = await op2.Task.ConfigureAwait(false);
|
var inner2 = await op2.Task.ConfigureAwait(false);
|
||||||
clickResult = await inner2.ConfigureAwait(false);
|
clickResult = await inner2.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch { clickResult = null; }
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log("Errore durante click JS: " + ex.Message);
|
|
||||||
StopAutomation("Errore durante click JS: " + ex.Message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clickResult.Length >= 2 && clickResult[0] == '"' && clickResult[^1] == '"')
|
if (!string.IsNullOrEmpty(clickResult) && clickResult.Length >= 2 && clickResult[0] == '"' && clickResult[^1] == '"') clickResult = JsonSerializer.Deserialize<string>(clickResult) ?? clickResult;
|
||||||
{
|
|
||||||
clickResult = JsonSerializer.Deserialize<string>(clickResult) ?? clickResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
// increment click counter and update UI
|
|
||||||
clickCount++;
|
clickCount++;
|
||||||
Dispatcher.Invoke(() => ClickCountText.Text = clickCount.ToString());
|
Dispatcher.Invoke(() => ClickCountText.Text = clickCount.ToString());
|
||||||
|
|
||||||
Log("Click eseguito: " + clickResult + " (totale: " + clickCount + ")");
|
Log("Click eseguito: " + clickResult + " (totale: " + clickCount + ")");
|
||||||
|
|
||||||
// stop if reached max clicks
|
try
|
||||||
if (clickCount >= maxClicks)
|
|
||||||
{
|
{
|
||||||
StopAutomation($"Limite click raggiunto: {clickCount}");
|
var id = !string.IsNullOrEmpty(bidderName) ? bidderName : "AutoBidder";
|
||||||
return;
|
if (_bidders.ContainsKey(id)) _bidders[id]++; else _bidders[id] = 1;
|
||||||
|
UpdateBiddersGrid();
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
if (clickCount >= maxClicks) { StopAutomation($"Limite click raggiunto: {clickCount}"); return; }
|
||||||
|
|
||||||
await Task.Delay(postClickDelayMs, token).ConfigureAwait(false);
|
await Task.Delay(postClickDelayMs, token).ConfigureAwait(false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(200, token).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
await Task.Delay(200, token).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
catch (JsonException ex)
|
catch (JsonException ex)
|
||||||
{
|
{
|
||||||
Log("Errore parsing JSON: " + ex.Message);
|
Log("Errore parsing JSON: " + ex.Message);
|
||||||
await Task.Delay(300, token).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
catch (OperationCanceledException) { break; }
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log("Errore loop: " + ex.Message);
|
Log("Errore loop: " + ex.Message);
|
||||||
StopAutomation("Errore loop: " + ex.Message);
|
StopAutomation("Errore loop: " + ex.Message);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
StartButton.Dispatcher.Invoke(() =>
|
|
||||||
{
|
|
||||||
StartButton.IsEnabled = true;
|
|
||||||
StopButton.IsEnabled = false;
|
|
||||||
StartButton.Opacity = 1.0;
|
|
||||||
StopButton.Opacity = 0.5;
|
|
||||||
});
|
|
||||||
|
|
||||||
Log("Automazione terminata");
|
await Task.Delay(200, token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dispatcher.Invoke(() => { StartButton.IsEnabled = true; StopButton.IsEnabled = false; StartButton.Opacity = 1.0; StopButton.Opacity = 0.5; });
|
||||||
|
Log("Automazione terminata");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnClosed(EventArgs e)
|
protected override void OnClosed(EventArgs e)
|
||||||
|
|||||||
@@ -1,20 +1,74 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.14.36511.14 d17.14
|
VisualStudioVersion = 17.14.36511.14
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mimante", "Mimante.csproj", "{9BBAEF93-DF66-432C-9349-459E272D6538}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mimante", "Mimante.csproj", "{9BBAEF93-DF66-432C-9349-459E272D6538}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Template", "..\Template\Template.wapproj", "{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Debug|ARM = Debug|ARM
|
||||||
|
Debug|ARM64 = Debug|ARM64
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
|
Release|ARM = Release|ARM
|
||||||
|
Release|ARM64 = Release|ARM64
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|Any CPU.Build.0 = Release|Any CPU
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|ARM64.Build.0 = Release|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|ARM.Build.0 = Debug|ARM
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|x64.Deploy.0 = Debug|x64
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Debug|x86.Deploy.0 = Debug|x86
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Release|ARM.ActiveCfg = Release|ARM
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Release|ARM.Build.0 = Release|ARM
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Release|ARM.Deploy.0 = Release|ARM
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Release|x64.Build.0 = Release|x64
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Release|x64.Deploy.0 = Release|x64
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Release|x86.Build.0 = Release|x86
|
||||||
|
{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}.Release|x86.Deploy.0 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
BIN
Template/Images/LockScreenLogo.scale-200.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
Template/Images/SplashScreen.scale-200.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
Template/Images/Square150x150Logo.scale-200.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Template/Images/Square44x44Logo.scale-200.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Template/Images/StoreLogo.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
Template/Images/Wide310x150Logo.scale-200.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
49
Template/Package.appxmanifest
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<Package
|
||||||
|
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||||
|
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||||
|
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||||
|
IgnorableNamespaces="uap rescap">
|
||||||
|
|
||||||
|
<Identity
|
||||||
|
Name="55384605-a0dd-4668-b437-24b02ffdb719"
|
||||||
|
Publisher="CN=balbo"
|
||||||
|
Version="1.0.0.0" />
|
||||||
|
|
||||||
|
<Properties>
|
||||||
|
<DisplayName>Template</DisplayName>
|
||||||
|
<PublisherDisplayName>balbo</PublisherDisplayName>
|
||||||
|
<Logo>Images\StoreLogo.png</Logo>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
|
<Dependencies>
|
||||||
|
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||||
|
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14393.0" MaxVersionTested="10.0.14393.0" />
|
||||||
|
</Dependencies>
|
||||||
|
|
||||||
|
<Resources>
|
||||||
|
<Resource Language="x-generate"/>
|
||||||
|
</Resources>
|
||||||
|
|
||||||
|
<Applications>
|
||||||
|
<Application Id="App"
|
||||||
|
Executable="$targetnametoken$.exe"
|
||||||
|
EntryPoint="$targetentrypoint$">
|
||||||
|
<uap:VisualElements
|
||||||
|
DisplayName="Template"
|
||||||
|
Description="Template"
|
||||||
|
BackgroundColor="transparent"
|
||||||
|
Square150x150Logo="Images\Square150x150Logo.png"
|
||||||
|
Square44x44Logo="Images\Square44x44Logo.png">
|
||||||
|
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" />
|
||||||
|
<uap:SplashScreen Image="Images\SplashScreen.png" />
|
||||||
|
</uap:VisualElements>
|
||||||
|
</Application>
|
||||||
|
</Applications>
|
||||||
|
|
||||||
|
<Capabilities>
|
||||||
|
<Capability Name="internetClient" />
|
||||||
|
<rescap:Capability Name="runFullTrust" />
|
||||||
|
</Capabilities>
|
||||||
|
</Package>
|
||||||
82
Template/Template.wapproj
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup Condition="'$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '15.0'">
|
||||||
|
<VisualStudioVersion>15.0</VisualStudioVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|x86">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x86</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x86">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x86</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|ARM">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>ARM</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|ARM">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>ARM</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|ARM64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>ARM64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|ARM64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>ARM64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|AnyCPU">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>AnyCPU</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|AnyCPU">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>AnyCPU</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<WapProjPath Condition="'$(WapProjPath)'==''">$(MSBuildExtensionsPath)\Microsoft\DesktopBridge\</WapProjPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.props" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<ProjectGuid>1d9db6f9-bd2b-4b14-9f2e-104060faad1e</ProjectGuid>
|
||||||
|
<TargetPlatformVersion>10.0.26100.0</TargetPlatformVersion>
|
||||||
|
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||||
|
<DefaultLanguage>it-IT</DefaultLanguage>
|
||||||
|
<AppxPackageSigningEnabled>false</AppxPackageSigningEnabled>
|
||||||
|
<NoWarn>$(NoWarn);NU1702</NoWarn>
|
||||||
|
<EntryPointProjectUniqueName>..\Mimante\Mimante.csproj</EntryPointProjectUniqueName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AppxManifest Include="Package.appxmanifest">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</AppxManifest>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Images\SplashScreen.scale-200.png" />
|
||||||
|
<Content Include="Images\LockScreenLogo.scale-200.png" />
|
||||||
|
<Content Include="Images\Square150x150Logo.scale-200.png" />
|
||||||
|
<Content Include="Images\Square44x44Logo.scale-200.png" />
|
||||||
|
<Content Include="Images\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
||||||
|
<Content Include="Images\StoreLogo.png" />
|
||||||
|
<Content Include="Images\Wide310x150Logo.scale-200.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" />
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1742" PrivateAssets="all" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Mimante\Mimante.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||