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="Opacity" Value="0.6" />
|
||||
</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}">
|
||||
<Setter Property="Background" Value="#0EA5E9" /> <!-- blue -->
|
||||
<Setter Property="Height" Value="30" />
|
||||
@@ -77,68 +81,91 @@
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" /> <!-- Start -->
|
||||
<RowDefinition Height="Auto" /> <!-- Pause -->
|
||||
<RowDefinition Height="Auto" /> <!-- Stop -->
|
||||
<RowDefinition Height="Auto" /> <!-- Back/Refresh -->
|
||||
<RowDefinition Height="Auto" /> <!-- Back/Refresh/Clear -->
|
||||
<RowDefinition Height="Auto" /> <!-- Site -->
|
||||
<RowDefinition Height="Auto" /> <!-- Stats -->
|
||||
<RowDefinition Height="Auto" /> <!-- Settings -->
|
||||
<RowDefinition Height="Auto" /> <!-- Price -->
|
||||
<RowDefinition Height="Auto" /> <!-- Bidders label -->
|
||||
<RowDefinition Height="Auto" /> <!-- Bidders grid -->
|
||||
<RowDefinition Height="Auto" /> <!-- Log label -->
|
||||
<RowDefinition Height="*" /> <!-- Log box expands -->
|
||||
</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="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="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>
|
||||
<Button x:Name="PauseBidButton" Grid.Row="1" Style="{StaticResource PauseButtonStyle}" Click="PauseBidButton_Click" Margin="12,8,12,0">Pausa</Button>
|
||||
|
||||
<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 x:Name="SiteLinkText" Text="https://it.bidoo.com" TextWrapping="Wrap" FontWeight="Bold" />
|
||||
</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 x:Name="ClickCountText" Text="0" FontWeight="Bold" Margin="0,0,12,0" />
|
||||
<TextBlock Text="Resets:" Margin="0,0,8,0" />
|
||||
<TextBlock x:Name="ResetCountText" Text="0" FontWeight="Bold" />
|
||||
</StackPanel>
|
||||
|
||||
<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>
|
||||
<TextBlock Text="Prezzo corrente:" Margin="12,0,6,0" VerticalAlignment="Center" />
|
||||
<TextBlock x:Name="CurrentPriceText" Text="-" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
|
||||
<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">
|
||||
<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 Orientation="Vertical" Margin="12,0,0,0">
|
||||
<TextBlock>Max Price</TextBlock>
|
||||
<TextBox x:Name="MaxPriceBox" Style="{StaticResource NumericBoxStyle}" Text="0" ToolTip="0 = nessun limite" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Vertical" Margin="12,0,0,0">
|
||||
<TextBlock>Prezzo corrente</TextBlock>
|
||||
<TextBlock x:Name="CurrentPriceText" Text="-" FontWeight="Bold" />
|
||||
<TextBox x:Name="MaxPriceBox" Style="{StaticResource NumericBoxStyle}" Text="0" ToolTip="0 = nessun limite" TextChanged="MaxPriceBox_TextChanged" />
|
||||
</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>
|
||||
</Border>
|
||||
|
||||
|
||||
@@ -1,26 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private CancellationTokenSource? _cts;
|
||||
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()
|
||||
{
|
||||
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
|
||||
{
|
||||
const int size = 64;
|
||||
@@ -35,157 +53,98 @@ namespace AutoBidder
|
||||
}
|
||||
var rtb = new RenderTargetBitmap(size, size, 96, 96, PixelFormats.Pbgra32);
|
||||
rtb.Render(dv);
|
||||
this.Icon = rtb; // set window and taskbar icon
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore icon errors
|
||||
this.Icon = rtb;
|
||||
}
|
||||
catch { }
|
||||
|
||||
// initial visual states: start is primary action
|
||||
// UI initial state
|
||||
StartButton.IsEnabled = true;
|
||||
StartButton.Opacity = 1.0;
|
||||
StopButton.IsEnabled = false;
|
||||
StopButton.Opacity = 0.5;
|
||||
BackButton.IsEnabled = false;
|
||||
|
||||
// navigation completed -> update back button state
|
||||
webView.NavigationCompleted += WebView_NavigationCompleted;
|
||||
UpdatePauseButtonContent();
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
BackButton.IsEnabled = webView.CoreWebView2 != null && webView.CoreWebView2.CanGoBack;
|
||||
try
|
||||
{
|
||||
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 { }
|
||||
var btn = FindName("PauseBidButton") as Button;
|
||||
if (btn != null) btn.Content = _pauseBids ? "Riprendi" : "Pausa";
|
||||
});
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private async void StartButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
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)
|
||||
private void UpdateBiddersGrid()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (webView.CoreWebView2 == null)
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
// if not initialized, try ensuring
|
||||
_ = webView.EnsureCoreWebView2Async();
|
||||
}
|
||||
|
||||
if (webView.CoreWebView2 != null && webView.CoreWebView2.CanGoBack)
|
||||
var grid = FindName("BiddersGrid") as DataGrid;
|
||||
if (grid != null)
|
||||
{
|
||||
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 { }
|
||||
}
|
||||
|
||||
StartButton.Dispatcher.Invoke(() =>
|
||||
private void SetCurrentPriceText(string text)
|
||||
{
|
||||
StartButton.IsEnabled = true;
|
||||
StopButton.IsEnabled = false;
|
||||
// reset visual states: start primary
|
||||
StartButton.Opacity = 1.0;
|
||||
StopButton.Opacity = 0.5;
|
||||
try
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
var tb = FindName("CurrentPriceText") as TextBlock;
|
||||
if (tb != null) tb.Text = text;
|
||||
});
|
||||
|
||||
Log("STOP: " + reason);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void Log(string message)
|
||||
@@ -200,120 +159,72 @@ namespace AutoBidder
|
||||
LogBox.AppendText(entry);
|
||||
LogBox.ScrollToEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
// fallback: buffer if LogBox not ready
|
||||
try { _pendingLogs.Add(entry); } 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)
|
||||
{
|
||||
int clickCount = 0;
|
||||
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)
|
||||
int clickCount = 0; int resetCount = 0; string? previousTimer = null;
|
||||
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; } }
|
||||
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}); })();";
|
||||
|
||||
// find price
|
||||
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){}
|
||||
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 to find a bid button that might say PUNTA or INIZIA
|
||||
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
|
||||
}
|
||||
}
|
||||
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'}); })();";
|
||||
|
||||
// Prefer direct countdown element by known class
|
||||
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 */ }
|
||||
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; })();";
|
||||
|
||||
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)
|
||||
{
|
||||
string? result = null;
|
||||
@@ -323,10 +234,7 @@ namespace AutoBidder
|
||||
var innerTask = await op.Task.ConfigureAwait(false);
|
||||
result = await innerTask.ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
catch (OperationCanceledException) { break; }
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log("Errore JS/interop: " + ex.Message);
|
||||
@@ -334,11 +242,19 @@ namespace AutoBidder
|
||||
return;
|
||||
}
|
||||
|
||||
string json = result ?? "";
|
||||
if (json.Length >= 2 && json[0] == '"' && json[^1] == '"')
|
||||
string json = result ?? string.Empty;
|
||||
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
|
||||
{
|
||||
@@ -346,117 +262,66 @@ namespace AutoBidder
|
||||
var root = doc.RootElement;
|
||||
var status = root.GetProperty("status").GetString();
|
||||
|
||||
// price may be present
|
||||
string? priceStr = null;
|
||||
double? priceVal = null;
|
||||
// price update
|
||||
if (root.TryGetProperty("price", out var priceEl) && priceEl.ValueKind != JsonValueKind.Null)
|
||||
{
|
||||
priceStr = priceEl.GetString();
|
||||
if (!string.IsNullOrEmpty(priceStr))
|
||||
var priceStr = priceEl.GetString();
|
||||
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))
|
||||
{
|
||||
priceVal = pval;
|
||||
Dispatcher.Invoke(() => CurrentPriceText.Text = pval.ToString("0.##") + " €");
|
||||
}
|
||||
SetCurrentPriceText(pval.ToString("0.##") + " €");
|
||||
}
|
||||
}
|
||||
|
||||
if (status == "soon")
|
||||
{
|
||||
Log("Stato: INIZIA TRA POCO. In attesa che appaia il pulsante PUNTA...");
|
||||
// poll until PUNTA button appears (or cancellation)
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
string? chk = null;
|
||||
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 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);
|
||||
chk = await inner2.ConfigureAwait(false);
|
||||
}
|
||||
catch { chk = null; }
|
||||
|
||||
var chk = await inner2.ConfigureAwait(false);
|
||||
if (!string.IsNullOrEmpty(chk))
|
||||
{
|
||||
if (chk.Length >= 2 && chk[0] == '"' && chk[^1] == '"') chk = JsonSerializer.Deserialize<string>(chk) ?? chk;
|
||||
if (chk == "yes")
|
||||
{
|
||||
Log("Pulsante PUNTA trovato. Riprendo esecuzione.");
|
||||
break;
|
||||
if (chk == "yes") { Log("Pulsante PUNTA trovato. Riprendo esecuzione."); break; }
|
||||
}
|
||||
}
|
||||
|
||||
await Task.Delay(700, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
continue; // next main loop iteration
|
||||
}
|
||||
|
||||
if (status == "no-button")
|
||||
{
|
||||
Log("Nessun pulsante PUNTA trovato; arresto");
|
||||
StopAutomation("Nessun pulsante PUNTA trovato; arresto");
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
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")
|
||||
{
|
||||
// Pause: wait until timer reappears
|
||||
Log("Timer non trovato: pausa in corso, verrà ripreso quando il timer ricompare");
|
||||
bool resumed = false;
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
string? pollResult = null;
|
||||
try
|
||||
{
|
||||
var op3 = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(findScript));
|
||||
var inner3 = await op3.Task.ConfigureAwait(false);
|
||||
pollResult = await inner3.ConfigureAwait(false);
|
||||
}
|
||||
catch { pollResult = null; }
|
||||
|
||||
if (!string.IsNullOrEmpty(pollResult))
|
||||
{
|
||||
if (pollResult.Length >= 2 && pollResult[0] == '"' && pollResult[^1] == '"') pollResult = JsonSerializer.Deserialize<string>(pollResult) ?? pollResult;
|
||||
var pollResult = await inner3.ConfigureAwait(false);
|
||||
var pollStr = pollResult ?? string.Empty;
|
||||
if (pollStr.Length >= 2 && pollStr[0] == '"' && pollStr[^1] == '"') pollStr = JsonSerializer.Deserialize<string>(pollStr) ?? pollStr;
|
||||
try
|
||||
{
|
||||
using var doc2 = JsonDocument.Parse(pollResult);
|
||||
using var doc2 = JsonDocument.Parse(pollStr);
|
||||
var st2 = doc2.RootElement.GetProperty("status").GetString();
|
||||
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;
|
||||
}
|
||||
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; }
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
await Task.Delay(800, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!resumed) break;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (status == "found")
|
||||
{
|
||||
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
|
||||
{
|
||||
if (previousTimer != null && int.TryParse(previousTimer, out var prev) && int.TryParse(timerValue, out var curr))
|
||||
@@ -464,36 +329,58 @@ namespace AutoBidder
|
||||
if (curr > prev)
|
||||
{
|
||||
resetCount++;
|
||||
Dispatcher.Invoke(() => ResetCountText.Text = resetCount.ToString());
|
||||
Log("Timer resettato (contatore): " + resetCount);
|
||||
// stop if reached limit
|
||||
if (resetCount >= maxResets)
|
||||
ResetCountText.Dispatcher.Invoke(() => ResetCountText.Text = resetCount.ToString());
|
||||
|
||||
// Attempt to read current winner from page and update bidders list
|
||||
try
|
||||
{
|
||||
StopAutomation($"Limite reset raggiunto: {resetCount}");
|
||||
return;
|
||||
var opWin = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(getLastBidderScript));
|
||||
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 { }
|
||||
|
||||
previousTimer = timerValue;
|
||||
}
|
||||
|
||||
// price check: if price available, enforce min/max bounds
|
||||
if (priceVal.HasValue)
|
||||
// price bounds handling
|
||||
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.");
|
||||
// wait until price >= minPrice
|
||||
Log($"Prezzo {pcur:0.##}€ sotto limite minimo ({minPrice:0.##}). Pausa.");
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
// poll price only
|
||||
string? pricePoll = null;
|
||||
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);
|
||||
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 (double.TryParse(pricePoll.Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var pp))
|
||||
{
|
||||
Dispatcher.Invoke(() => CurrentPriceText.Text = pp.ToString("0.##") + " €");
|
||||
if (pp >= minPrice)
|
||||
{
|
||||
Log("Prezzo salito sopra il minimo; ripresa esecuzione.");
|
||||
break;
|
||||
}
|
||||
SetCurrentPriceText(pp.ToString("0.##") + " €");
|
||||
if (pp >= minPrice) { 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)
|
||||
{
|
||||
string? pricePoll = null;
|
||||
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);
|
||||
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 (double.TryParse(pricePoll.Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var pp))
|
||||
{
|
||||
Dispatcher.Invoke(() => CurrentPriceText.Text = pp.ToString("0.##") + " €");
|
||||
if (pp <= maxPrice)
|
||||
{
|
||||
Log("Prezzo sceso sotto il massimo; ripresa esecuzione.");
|
||||
break;
|
||||
}
|
||||
SetCurrentPriceText(pp.ToString("0.##") + " €");
|
||||
if (pp <= maxPrice) { Log("Prezzo sceso sotto il massimo; ripresa esecuzione."); break; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,79 +431,74 @@ namespace AutoBidder
|
||||
|
||||
if (timerValue == "0")
|
||||
{
|
||||
// immediate click when timer reaches 0 (extreme test)
|
||||
string clickResult;
|
||||
// get last bidder name from page
|
||||
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
|
||||
{
|
||||
var op2 = Dispatcher.InvokeAsync(() => webView.ExecuteScriptAsync(clickScript));
|
||||
var inner2 = await op2.Task.ConfigureAwait(false);
|
||||
clickResult = await inner2.ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log("Errore durante click JS: " + ex.Message);
|
||||
StopAutomation("Errore durante click JS: " + ex.Message);
|
||||
return;
|
||||
}
|
||||
catch { clickResult = null; }
|
||||
|
||||
if (clickResult.Length >= 2 && clickResult[0] == '"' && clickResult[^1] == '"')
|
||||
{
|
||||
clickResult = JsonSerializer.Deserialize<string>(clickResult) ?? clickResult;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(clickResult) && clickResult.Length >= 2 && clickResult[0] == '"' && clickResult[^1] == '"') clickResult = JsonSerializer.Deserialize<string>(clickResult) ?? clickResult;
|
||||
|
||||
// increment click counter and update UI
|
||||
clickCount++;
|
||||
Dispatcher.Invoke(() => ClickCountText.Text = clickCount.ToString());
|
||||
|
||||
Log("Click eseguito: " + clickResult + " (totale: " + clickCount + ")");
|
||||
|
||||
// stop if reached max clicks
|
||||
if (clickCount >= maxClicks)
|
||||
try
|
||||
{
|
||||
StopAutomation($"Limite click raggiunto: {clickCount}");
|
||||
return;
|
||||
var id = !string.IsNullOrEmpty(bidderName) ? bidderName : "AutoBidder";
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
await Task.Delay(200, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await Task.Delay(200, token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
Log("Errore parsing JSON: " + ex.Message);
|
||||
await Task.Delay(300, token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
catch (OperationCanceledException) { break; }
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log("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)
|
||||
|
||||
@@ -1,20 +1,74 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.36511.14 d17.14
|
||||
VisualStudioVersion = 17.14.36511.14
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mimante", "Mimante.csproj", "{9BBAEF93-DF66-432C-9349-459E272D6538}"
|
||||
EndProject
|
||||
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Template", "..\Template\Template.wapproj", "{1D9DB6F9-BD2B-4B14-9F2E-104060FAAD1E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
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|ARM = Release|ARM
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{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|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.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
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
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>
|
||||