mirror of
https://github.com/zapstore/zapstore.git
synced 2026-10-05 12:38:24 +00:00
Also delete by a tags
This commit is contained in:
@@ -3,6 +3,60 @@ import 'package:purplebase/purplebase.dart';
|
|||||||
import 'package:zapstore/constants/app_constants.dart';
|
import 'package:zapstore/constants/app_constants.dart';
|
||||||
import 'package:zapstore/services/settings_service.dart';
|
import 'package:zapstore/services/settings_service.dart';
|
||||||
|
|
||||||
|
/// Deletes events by their coordinates (a tags: kind:pubkey:d-tag).
|
||||||
|
///
|
||||||
|
/// For authority deletions, ignores the pubkey in the coordinate and deletes
|
||||||
|
/// ANY event matching the kind and d-tag, regardless of author.
|
||||||
|
/// Queries for events matching the coordinates and deletes them by ID.
|
||||||
|
Future<void> _deleteByCoordinates(
|
||||||
|
PurplebaseStorageNotifier storage,
|
||||||
|
Set<String> coordinates,
|
||||||
|
) async {
|
||||||
|
if (coordinates.isEmpty) return;
|
||||||
|
|
||||||
|
// Parse coordinates and build filters
|
||||||
|
final filters = <RequestFilter<Model>>[];
|
||||||
|
for (final coord in coordinates) {
|
||||||
|
final parts = coord.split(':');
|
||||||
|
if (parts.length < 2) continue;
|
||||||
|
|
||||||
|
final kind = int.tryParse(parts[0]);
|
||||||
|
if (kind == null) continue;
|
||||||
|
|
||||||
|
// For authority deletions, we ignore the pubkey in the coordinate
|
||||||
|
// and delete ANY event with matching kind and d-tag
|
||||||
|
|
||||||
|
if (parts.length >= 3 && parts[2].isNotEmpty) {
|
||||||
|
// Parameterized replaceable event with d-tag
|
||||||
|
// NOTE: No authors filter - delete regardless of who published it
|
||||||
|
filters.add(RequestFilter<Model>(
|
||||||
|
kinds: {kind},
|
||||||
|
tags: {'#d': {parts[2]}},
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
// Replaceable event without d-tag
|
||||||
|
// NOTE: No authors filter - delete regardless of who published it
|
||||||
|
filters.add(RequestFilter<Model>(
|
||||||
|
kinds: {kind},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filters.isEmpty) return;
|
||||||
|
|
||||||
|
// Query for matching events
|
||||||
|
final events = await storage.query(
|
||||||
|
Request(filters),
|
||||||
|
source: const LocalSource(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Delete by event IDs
|
||||||
|
final eventIds = events.map((e) => e.id).toSet();
|
||||||
|
if (eventIds.isNotEmpty) {
|
||||||
|
await storage.delete(eventIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Fetches NIP-09 kind-5 deletion events from the AppCatalog relay since the
|
/// Fetches NIP-09 kind-5 deletion events from the AppCatalog relay since the
|
||||||
/// last sync cursor, applies them to local storage, and advances the cursor.
|
/// last sync cursor, applies them to local storage, and advances the cursor.
|
||||||
///
|
///
|
||||||
@@ -43,16 +97,26 @@ Future<void> processDeletions({
|
|||||||
if (deletionRequests.isEmpty) return;
|
if (deletionRequests.isEmpty) return;
|
||||||
|
|
||||||
const trustedAuthorities = {kZapstorePubkey, kZapstoreCommunityPubkey};
|
const trustedAuthorities = {kZapstorePubkey, kZapstoreCommunityPubkey};
|
||||||
final authorityTargetIds = deletionRequests
|
final authorityDeletions = deletionRequests
|
||||||
.where((dr) => trustedAuthorities.contains(dr.event.pubkey))
|
.where((dr) => trustedAuthorities.contains(dr.event.pubkey))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
final authorityTargetIds = authorityDeletions
|
||||||
.expand((dr) => dr.deletedEventIds)
|
.expand((dr) => dr.deletedEventIds)
|
||||||
.toSet();
|
.toSet();
|
||||||
|
|
||||||
|
final authorityTargetCoordinates = authorityDeletions
|
||||||
|
.expand((dr) => dr.event.getTagSetValues('a'))
|
||||||
|
.toSet();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await storage.delete(deletionRequests.map((d) => d.id).toSet());
|
await storage.delete(deletionRequests.map((d) => d.id).toSet());
|
||||||
if (authorityTargetIds.isNotEmpty) {
|
if (authorityTargetIds.isNotEmpty) {
|
||||||
await storage.delete(authorityTargetIds);
|
await storage.delete(authorityTargetIds);
|
||||||
}
|
}
|
||||||
|
if (authorityTargetCoordinates.isNotEmpty) {
|
||||||
|
await _deleteByCoordinates(storage, authorityTargetCoordinates);
|
||||||
|
}
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// Orphaned kind-5 rows are harmless; referenced events are
|
// Orphaned kind-5 rows are harmless; referenced events are
|
||||||
// already removed by the DB layer during save.
|
// already removed by the DB layer during save.
|
||||||
|
|||||||
Reference in New Issue
Block a user