Skip to content

Commit

Permalink
nostrList entities, models
Browse files Browse the repository at this point in the history
  • Loading branch information
leo-lox committed Nov 22, 2024
1 parent 44bbc47 commit 87b95ae
Show file tree
Hide file tree
Showing 4 changed files with 393 additions and 0 deletions.
119 changes: 119 additions & 0 deletions lib/data_layer/models/nostr_lists_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import '../../domain_layer/entities/nostr_list.dart';
import 'package:ndk/entities.dart' as ndk_entities;

class NostrListModel extends NostrList {
NostrListModel({
required super.pubKey,
required super.kind,
required super.createdAt,
required super.elements,
});

// Convert from Nip51List (NDK) to NostrListModel
static NostrListModel fromNDK(ndk_entities.Nip51List ndkList) {
return NostrListModel(
pubKey: ndkList.pubKey,
kind: ndkList.kind,
createdAt: ndkList.createdAt,
elements: ndkList.elements
.map((e) => NostrListElementModel.fromNDK(e))
.toList(),
)..id = ndkList.id;
}

// Convert from NostrListModel to Nip51List (NDK)
ndk_entities.Nip51List toNDK() {
return ndk_entities.Nip51List(
pubKey: pubKey,
kind: kind,
createdAt: createdAt,
elements: elements
.map((e) => NostrListElementModel(
tag: e.tag,
value: e.value,
private: e.private,
).toNDK())
.toList(),
)..id = id;
}
}

class NostrSetModel extends NostrSet {
//String name;
//String? title;
String? description;
String? image;

NostrSetModel({
required super.pubKey,
required super.name,
required super.createdAt,
required super.elements,
super.kind = NostrList.FOLLOW_SET,
super.title,
this.description,
this.image,
});

// Convert from Nip51Set (NDK) to NostrSetModel
static NostrSetModel fromNDK(ndk_entities.Nip51Set ndkSet) {
return NostrSetModel(
pubKey: ndkSet.pubKey,
name: ndkSet.name,
createdAt: ndkSet.createdAt,
elements:
ndkSet.elements.map((e) => NostrListElementModel.fromNDK(e)).toList(),
title: ndkSet.title,
description: ndkSet.description,
image: ndkSet.image,
)..id = ndkSet.id;
}

// Convert from NostrSetModel to Nip51Set (NDK)
@override
ndk_entities.Nip51Set toNDK() {
return ndk_entities.Nip51Set(
pubKey: pubKey,
name: name,
createdAt: createdAt,
elements: elements
.map((e) => NostrListElementModel(
tag: e.tag,
value: e.value,
private: e.private,
).toNDK())
.toList(),
title: title,
)
..id = id
..description = description
..image = image;
}
}

class NostrListElementModel extends NostrListElement {
NostrListElementModel({
required super.tag,
required super.value,
required super.private,
});

// Convert from Nip51ListElement (NDK) to Nip51ListElementModel
static NostrListElementModel fromNDK(
ndk_entities.Nip51ListElement ndkElement) {
return NostrListElementModel(
tag: ndkElement.tag,
value: ndkElement.value,
private: ndkElement.private,
);
}

// Convert from Nip51ListElementModel to Nip51ListElement (NDK)
ndk_entities.Nip51ListElement toNDK() {
return ndk_entities.Nip51ListElement(
tag: tag,
value: value,
private: private,
);
}
}
53 changes: 53 additions & 0 deletions lib/data_layer/repositories/nostr_list_repository_impl.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import 'dart:developer';

import 'package:camelus/domain_layer/entities/nostr_list.dart';
import 'package:ndk/entities.dart' as ndk_entities;
import 'package:ndk/ndk.dart' as ndk;
import 'package:rxdart/rxdart.dart';

import '../../domain_layer/entities/nostr_note.dart';
import '../../domain_layer/repositories/nostr_list_repository.dart';
import '../data_sources/dart_ndk_source.dart';
import '../models/nostr_lists_model.dart';
import '../models/nostr_note_model.dart';

class NostrListRepositoryImpl implements NostrListRepository {
final DartNdkSource dartNdkSource;
final ndk.EventVerifier eventVerifier;

NostrListRepositoryImpl(
{required this.dartNdkSource, required this.eventVerifier, r});

@override
Stream<NostrNote> getAllNotes() {
ndk.Filter filter = ndk.Filter(
authors: [],
kinds: [ndk_entities.Nip01Event.TEXT_NODE_KIND],
);

final response = dartNdkSource.dartNdk.requests
.query(filters: [filter], name: 'getAllNotes-');

return response.stream.map(
(event) => NostrNoteModel.fromNDKEvent(event),
);
}

@override
Future<NostrSet?> getNostrFollowSet({
required String pubKey,
required String name,
}) async {
final ndkSet =
await dartNdkSource.dartNdk.lists.getSinglePublicNip51RelaySet(
name: name,
publicKey: pubKey,
);

if (ndkSet == null) {
return null;
}
final listSet = NostrSetModel.fromNDK(ndkSet);
return listSet;
}
}
213 changes: 213 additions & 0 deletions lib/domain_layer/entities/nostr_list.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
class NostrList {
static const int MUTE = 10000;
static const int PIN = 10001;
static const int BOOKMARKS = 10003;
static const int COMMUNITIES = 10004;
static const int PUBLIC_CHATS = 10005;
static const int BLOCKED_RELAYS = 10006;
static const int SEARCH_RELAYS = 10007;
static const int INTERESTS = 10015;
static const int EMOJIS = 10030;

static const int FOLLOW_SET = 30000;
static const int RELAY_SET = 30002;
static const int BOOKMARKS_SET = 30003;
static const int CURATION_SET = 30004;
static const int INTERESTS_SET = 30015;
static const int EMOJIS_SET = 30030;

static const String RELAY = "relay";
static const String PUB_KEY = "p";
static const String HASHTAG = "t";
static const String WORD = "word";
static const String THREAD = "e";
static const String RESOURCE = "r";
static const String EMOJI = "emoji";
static const String A = "a";

static const List<int> POSSIBLE_KINDS = [
MUTE,
PIN,
BOOKMARKS,
COMMUNITIES,
PUBLIC_CHATS,
BLOCKED_RELAYS,
SEARCH_RELAYS,
INTERESTS,
EMOJIS,
FOLLOW_SET,
RELAY_SET,
BOOKMARKS_SET,
CURATION_SET,
INTERESTS_SET,
EMOJIS_SET
];

static const List<String> POSSIBLE_TAGS = [
RELAY,
PUB_KEY,
HASHTAG,
WORD,
THREAD,
RESOURCE,
EMOJI,
A
];

late String id;
late String pubKey;
late int kind;

List<NostrListElement> elements = [];

List<NostrListElement> byTag(String tag) =>
elements.where((element) => element.tag == tag).toList();

List<NostrListElement> get relays => byTag(RELAY);
List<NostrListElement> get pubKeys => byTag(PUB_KEY);
List<NostrListElement> get hashtags => byTag(HASHTAG);
List<NostrListElement> get words => byTag(WORD);
List<NostrListElement> get threads => byTag(THREAD);

List<String> get publicRelays =>
relays.where((element) => !element.private).map((e) => e.value).toList();
List<String> get privateRelays =>
relays.where((element) => !element.private).map((e) => e.value).toList();

set privateRelays(List<String> list) {
elements.removeWhere((element) => element.tag == RELAY && element.private);
elements.addAll(list
.map((url) => NostrListElement(tag: RELAY, value: url, private: true)));
}

set publicRelays(List<String> list) {
elements.removeWhere((element) => element.tag == RELAY && !element.private);
elements.addAll(list.map(
(url) => NostrListElement(tag: RELAY, value: url, private: false)));
}

late int createdAt;

@override
// coverage:ignore-start
String toString() {
return 'Nip51List { $kind}';
}
// coverage:ignore-end

String get displayTitle {
if (kind == NostrList.SEARCH_RELAYS) {
return "Search";
}
if (kind == NostrList.BLOCKED_RELAYS) {
return "Blocked";
}
if (kind == NostrList.MUTE) {
return "Mute";
}
return "kind $kind";
}

List<String> get allRelays => relays.map((e) => e.value).toList();

NostrList({
required this.pubKey,
required this.kind,
required this.createdAt,
required this.elements,
});

void parseTags(List tags, {required bool private}) {
for (var tag in tags) {
if (tag is! List<dynamic>) continue;
final length = tag.length;
if (length <= 1) continue;
final tagName = tag[0];
final value = tag[1];
if (POSSIBLE_TAGS.contains(tagName)) {
elements.add(
NostrListElement(tag: tagName, value: value, private: private));
}
}
}

void addRelay(String relayUrl, bool private) {
elements
.add(NostrListElement(tag: RELAY, value: relayUrl, private: private));
}

void addElement(String tag, String value, bool private) {
elements.add(NostrListElement(tag: tag, value: value, private: private));
}

void removeRelay(String relayUrl) {
elements.removeWhere(
(element) => element.tag == RELAY && element.value == relayUrl);
}

void removeElement(String tag, String value) {
elements
.removeWhere((element) => element.tag == tag && element.value == value);
}
}

class NostrListElement {
bool private;
String tag;
String value;

NostrListElement({
required this.tag,
required this.value,
required this.private,
});
}

class NostrSet extends NostrList {
late String name;
String? title;
String? description;
String? image;

@override
String toString() {
return 'Nip51Set { $name}';
}

/// Create a new Nip51Set
/// default kind is Nip51List.FOLLOW_SET
NostrSet({
required super.pubKey,
required this.name,
required super.createdAt,
required super.elements,
this.title,
super.kind = NostrList.FOLLOW_SET,
});

void parseSetTags(List tags) {
for (var tag in tags) {
if (tag is! List<dynamic>) continue;
final length = tag.length;
if (length <= 1) continue;
final tagName = tag[0];
final value = tag[1];
if (tagName == "d") {
name = value;
continue;
}
if (tagName == "title") {
title = value;
continue;
}
if (tagName == "description") {
description = value;
continue;
}
if (tagName == "image") {
image = value;
continue;
}
}
}
}
8 changes: 8 additions & 0 deletions lib/domain_layer/repositories/nostr_list_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import '../entities/nostr_list.dart';

abstract class NostrListRepository {
Future<NostrSet?> getNostrFollowSet({
required String pubKey,
required String name,
});
}

0 comments on commit 87b95ae

Please sign in to comment.