Implementato servizio avanzato per scraping e ricerca utenti Instagram con gestione completa dei cookie, headers browser (21 headers da HAR), logging dettagliato e simulazione Chrome 143. Aggiunta classe modello InstagramSearchResult per risultati ricerca, con supporto MVVM. Risolti definitivamente problemi di autenticazione e passaggio cookie alle richieste.
309 lines
9.3 KiB
C#
309 lines
9.3 KiB
C#
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using InstaArchive.Models;
|
|
using InstaArchive.Services;
|
|
using System;
|
|
|
|
namespace InstaArchive.ViewModels;
|
|
|
|
public partial class TargetsViewModel : ObservableObject
|
|
{
|
|
private readonly UserManagementService _userManagement;
|
|
private readonly InstagramScraperService _scraperService;
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<InstagramUser> users = new();
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<InstagramUser> filteredUsers = new();
|
|
|
|
[ObservableProperty]
|
|
private InstagramUser? selectedUser;
|
|
|
|
[ObservableProperty]
|
|
private long newUserId;
|
|
|
|
[ObservableProperty]
|
|
private string newUsername = string.Empty;
|
|
|
|
[ObservableProperty]
|
|
private string searchQuery = string.Empty;
|
|
|
|
// Nuove proprietà per la ricerca Instagram
|
|
[ObservableProperty]
|
|
private string instagramSearchQuery = string.Empty;
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<InstagramSearchResult> searchResults = new();
|
|
|
|
[ObservableProperty]
|
|
private bool isSearching = false;
|
|
|
|
[ObservableProperty]
|
|
private bool hasSearchResults = false;
|
|
|
|
[ObservableProperty]
|
|
private string searchMessage = string.Empty;
|
|
|
|
public TargetsViewModel(
|
|
UserManagementService userManagement,
|
|
InstagramScraperService scraperService)
|
|
{
|
|
_userManagement = userManagement;
|
|
_scraperService = scraperService;
|
|
|
|
_ = LoadUsersAsync();
|
|
}
|
|
|
|
partial void OnSearchQueryChanged(string value)
|
|
{
|
|
FilterUsers();
|
|
}
|
|
|
|
partial void OnInstagramSearchQueryChanged(string value)
|
|
{
|
|
// RIMOSSO: Ricerca automatica
|
|
// La ricerca viene eseguita solo tramite pulsante SearchInstagramUsersCommand
|
|
}
|
|
|
|
private void FilterUsers()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(SearchQuery))
|
|
{
|
|
FilteredUsers.Clear();
|
|
foreach (var user in Users)
|
|
{
|
|
FilteredUsers.Add(user);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var query = SearchQuery.ToLower().Trim();
|
|
var filtered = Users.Where(u =>
|
|
u.CurrentUsername.ToLower().Contains(query) ||
|
|
u.UserId.ToString().Contains(query)
|
|
).ToList();
|
|
|
|
FilteredUsers.Clear();
|
|
foreach (var user in filtered)
|
|
{
|
|
FilteredUsers.Add(user);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Cerca utenti Instagram tramite API
|
|
/// </summary>
|
|
[RelayCommand]
|
|
private async Task SearchInstagramUsersAsync()
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] Ricerca Instagram avviata: '{InstagramSearchQuery}'");
|
|
|
|
if (string.IsNullOrWhiteSpace(InstagramSearchQuery))
|
|
{
|
|
SearchResults.Clear();
|
|
HasSearchResults = false;
|
|
SearchMessage = string.Empty;
|
|
System.Diagnostics.Debug.WriteLine("[TargetsViewModel] Query vuota, pulizia risultati");
|
|
return;
|
|
}
|
|
|
|
IsSearching = true;
|
|
SearchResults.Clear();
|
|
SearchMessage = "Ricerca in corso...";
|
|
System.Diagnostics.Debug.WriteLine("[TargetsViewModel] Inizio ricerca...");
|
|
|
|
try
|
|
{
|
|
var results = await _scraperService.SearchUsersAsync(InstagramSearchQuery);
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] Ricevuti {results.Count} risultati");
|
|
|
|
// Verifica quali utenti sono già monitorati
|
|
var existingUserIds = Users.Select(u => u.UserId).ToHashSet();
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] Utenti già monitorati: {existingUserIds.Count}");
|
|
|
|
foreach (var result in results)
|
|
{
|
|
if (long.TryParse(result.UserId, out var userId))
|
|
{
|
|
result.IsAlreadyMonitored = existingUserIds.Contains(userId);
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] @{result.Username} - Già monitorato: {result.IsAlreadyMonitored}");
|
|
}
|
|
SearchResults.Add(result);
|
|
}
|
|
|
|
HasSearchResults = SearchResults.Any();
|
|
SearchMessage = HasSearchResults
|
|
? $"Trovati {SearchResults.Count} risultati"
|
|
: "Nessun risultato trovato";
|
|
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] {SearchMessage}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SearchMessage = $"Errore durante la ricerca: {ex.Message}";
|
|
HasSearchResults = false;
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] ERRORE ricerca: {ex.Message}");
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] Stack trace: {ex.StackTrace}");
|
|
}
|
|
finally
|
|
{
|
|
IsSearching = false;
|
|
System.Diagnostics.Debug.WriteLine("[TargetsViewModel] Ricerca completata");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiunge gli utenti selezionati dai risultati di ricerca
|
|
/// </summary>
|
|
[RelayCommand]
|
|
private async Task AddSelectedUsersAsync()
|
|
{
|
|
System.Diagnostics.Debug.WriteLine("[TargetsViewModel] Aggiunta utenti selezionati");
|
|
|
|
var selectedResults = SearchResults.Where(r => r.IsSelected && !r.IsAlreadyMonitored).ToList();
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] {selectedResults.Count} utenti selezionati");
|
|
|
|
if (selectedResults.Count == 0)
|
|
{
|
|
SearchMessage = "Seleziona almeno un utente da aggiungere";
|
|
System.Diagnostics.Debug.WriteLine("[TargetsViewModel] Nessun utente selezionato");
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
int addedCount = 0;
|
|
|
|
foreach (var result in selectedResults)
|
|
{
|
|
if (!long.TryParse(result.UserId, out var userId))
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] UserId non valido per @{result.Username}: {result.UserId}");
|
|
continue;
|
|
}
|
|
|
|
try
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] Aggiunta utente: @{result.Username} (ID: {userId})");
|
|
var user = await _userManagement.AddUserAsync(userId, result.Username);
|
|
Users.Add(user);
|
|
|
|
result.IsAlreadyMonitored = true;
|
|
result.IsSelected = false;
|
|
addedCount++;
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] Utente @{result.Username} aggiunto correttamente");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] ERRORE aggiunta @{result.Username}: {ex.Message}");
|
|
// Continua con il prossimo utente
|
|
}
|
|
}
|
|
|
|
FilterUsers();
|
|
SearchMessage = $"{addedCount} utenti aggiunti con successo";
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] {SearchMessage}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SearchMessage = $"Errore durante l'aggiunta: {ex.Message}";
|
|
System.Diagnostics.Debug.WriteLine($"[TargetsViewModel] ERRORE aggiunta batch: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pulisce i risultati di ricerca
|
|
/// </summary>
|
|
[RelayCommand]
|
|
private void ClearSearchResults()
|
|
{
|
|
SearchResults.Clear();
|
|
InstagramSearchQuery = string.Empty;
|
|
HasSearchResults = false;
|
|
SearchMessage = string.Empty;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Toggle selezione di un risultato di ricerca
|
|
/// </summary>
|
|
[RelayCommand]
|
|
private void ToggleSearchResultSelection(InstagramSearchResult result)
|
|
{
|
|
if (result != null && !result.IsAlreadyMonitored)
|
|
{
|
|
result.IsSelected = !result.IsSelected;
|
|
}
|
|
}
|
|
|
|
[RelayCommand]
|
|
private async Task AddUserAsync()
|
|
{
|
|
if (NewUserId <= 0 || string.IsNullOrWhiteSpace(NewUsername))
|
|
{
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
var user = await _userManagement.AddUserAsync(NewUserId, NewUsername);
|
|
Users.Add(user);
|
|
FilterUsers();
|
|
|
|
NewUserId = 0;
|
|
NewUsername = string.Empty;
|
|
}
|
|
catch
|
|
{
|
|
// Show error to user
|
|
}
|
|
}
|
|
|
|
[RelayCommand]
|
|
private async Task DeleteUserAsync(InstagramUser user)
|
|
{
|
|
if (user == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
await _userManagement.DeleteUserAsync(user.UserId);
|
|
Users.Remove(user);
|
|
FilterUsers();
|
|
}
|
|
|
|
[RelayCommand]
|
|
private async Task SaveUserAsync()
|
|
{
|
|
if (SelectedUser == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
await _userManagement.UpdateUserAsync(SelectedUser);
|
|
}
|
|
|
|
[RelayCommand]
|
|
private async Task RefreshAsync()
|
|
{
|
|
await LoadUsersAsync();
|
|
}
|
|
|
|
private async Task LoadUsersAsync()
|
|
{
|
|
var userList = await _userManagement.GetAllUsersAsync();
|
|
|
|
Users.Clear();
|
|
foreach (var user in userList)
|
|
{
|
|
Users.Add(user);
|
|
}
|
|
|
|
FilterUsers();
|
|
}
|
|
}
|