loadEvents method

  1. @override
Future<List<Nip01Event>> loadEvents({
  1. List<String>? ids,
  2. List<String>? pubKeys,
  3. List<int>? kinds,
  4. Map<String, List<String>>? tags,
  5. int? since,
  6. int? until,
  7. String? search,
  8. int? limit,
})
override

Load events from cache with flexible filtering
ids - list of event ids
pubKeys - list of authors pubKeys
kinds - list of kinds
tags - map of tags (e.g. {'p': 'pubkey1', 'e': 'eventid1'})
since - timestamp
until - timestamp
search - search string to match against content
limit - limit of results
returns list of events

Implementation

@override
Future<List<Nip01Event>> loadEvents({
  List<String>? ids,
  List<String>? pubKeys,
  List<int>? kinds,
  Map<String, List<String>>? tags,
  int? since,
  int? until,
  String? search,
  int? limit,
}) async {
  // Build filter conditions
  final filters = <sembast.Filter>[];

  // Filter by event IDs
  if (ids != null && ids.isNotEmpty) {
    filters.add(sembast.Filter.inList('id', ids));
  }

  // Filter by authors (pubkeys)
  if (pubKeys != null && pubKeys.isNotEmpty) {
    filters.add(sembast.Filter.inList('pubkey', pubKeys));
  }

  // Filter by kinds
  if (kinds != null && kinds.isNotEmpty) {
    filters.add(sembast.Filter.inList('kind', kinds));
  }

  // Filter by time range
  if (since != null) {
    filters.add(sembast.Filter.greaterThanOrEquals('created_at', since));
  }

  if (until != null) {
    filters.add(sembast.Filter.lessThanOrEquals('created_at', until));
  }

  // Filter by content search
  if (search != null && search.isNotEmpty) {
    filters.add(sembast.Filter.matches('content', search));
  }

  final finder = sembast.Finder(
    filter: filters.isNotEmpty ? sembast.Filter.and(filters) : null,
    limit: limit,
    sortOrders: [sembast.SortOrder('created_at', false)],
  );

  final records = await _eventsStore.find(_database, finder: finder);
  final events = records
      .map((record) => Nip01EventExtension.fromJsonStorage(record.value))
      .toList();

  // Filter by tags if specified (done in memory since Sembast doesn't support complex tag filtering)
  if (tags != null && tags.isNotEmpty) {
    return events.where((event) {
      return tags.entries.every((tagEntry) {
        var tagName = tagEntry.key;
        final tagValues = tagEntry.value;

        // Handle the special case where tag key starts with '#'
        if (tagName.startsWith('#') && tagName.length > 1) {
          tagName = tagName.substring(1);
        }

        final eventTags = event.getTags(tagName);

        if (tagValues.isEmpty &&
            event.tags.where((e) => e[0] == tagName).isNotEmpty) {
          return true;
        }

        return tagValues.any(
          (value) => eventTags.contains(value.toLowerCase()),
        );
      });
    }).toList();
  }

  return events;
}