Files
Teti/Teti/ViewModels/TargetsViewModel.cs
Alberto Balbo d4e38ec8fc Aggiungi InstagramScraperService e modello ricerca utenti
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.
2026-01-08 14:53:27 +01:00

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();
}
}