mirror of
https://github.com/vishalxl/nostr_console.git
synced 2025-09-21 11:10:30 +02:00
fixed json decode issue. added more profile info including distance. added search by client
This commit is contained in:
@@ -132,20 +132,23 @@ Future<void> main(List<String> arguments) async {
|
|||||||
//stdout.write("Got argument request: ${argResults[requestArg]}");
|
//stdout.write("Got argument request: ${argResults[requestArg]}");
|
||||||
stdout.write('Sending request and waiting for events...');
|
stdout.write('Sending request and waiting for events...');
|
||||||
|
|
||||||
sendRequest(defaultServerUrl, argResults[requestArg]);
|
sendRequest(gListRelayUrls, argResults[requestArg]);
|
||||||
Future.delayed(const Duration(milliseconds: 6000), () {
|
Future.delayed(const Duration(milliseconds: 6000), () {
|
||||||
List<Event> receivedEvents = getRecievedEvents();
|
List<Event> receivedEvents = getRecievedEvents();
|
||||||
stdout.write("received ${receivedEvents.length - numFileEvents} events from $defaultServerUrl\n");
|
stdout.write("received ${receivedEvents.length - numFileEvents} events\n");
|
||||||
|
|
||||||
// remove bots
|
// remove bots
|
||||||
receivedEvents.removeWhere((e) => gBots.contains(e.eventData.pubkey));
|
receivedEvents.removeWhere((e) => gBots.contains(e.eventData.pubkey));
|
||||||
|
|
||||||
// create tree
|
// create tree
|
||||||
Tree node = getTree(getRecievedEvents());
|
Future<Tree> node = getTree(getRecievedEvents());
|
||||||
clearEvents(); // cause we have consumed them above
|
//clearEvents(); // cause we have consumed them above
|
||||||
|
node.then((value) {
|
||||||
|
clearEvents();
|
||||||
|
mainMenuUi(value, []);
|
||||||
|
});
|
||||||
// call main menu
|
// call main menu
|
||||||
mainMenuUi(node, []);
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -216,11 +219,14 @@ Future<void> main(List<String> arguments) async {
|
|||||||
stdout.write("received $numOtherEvents other posts\n");
|
stdout.write("received $numOtherEvents other posts\n");
|
||||||
|
|
||||||
// get all events in Tree form
|
// get all events in Tree form
|
||||||
Tree node = getTree(getRecievedEvents());
|
Future<Tree> node = getTree(getRecievedEvents());
|
||||||
clearEvents();
|
|
||||||
|
|
||||||
// call the mein UI function
|
// call the mein UI function
|
||||||
mainMenuUi(node, contactList);
|
node.then((value) {
|
||||||
|
clearEvents();
|
||||||
|
mainMenuUi(value, contactList);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -120,7 +120,8 @@ Future<void> otherMenuUi(Tree node, var contactList) async {
|
|||||||
'Rebroadcast an event', // 6
|
'Rebroadcast an event', // 6
|
||||||
'Applicatoin stats', // 7
|
'Applicatoin stats', // 7
|
||||||
'Help and About', // 8
|
'Help and About', // 8
|
||||||
'Go back to main menu'], // 9
|
'Go back to main menu', // 9
|
||||||
|
'Search by client'],
|
||||||
"Other Menu"); // menu name
|
"Other Menu"); // menu name
|
||||||
print('You picked: $option');
|
print('You picked: $option');
|
||||||
switch(option) {
|
switch(option) {
|
||||||
@@ -237,9 +238,19 @@ Future<void> otherMenuUi(Tree node, var contactList) async {
|
|||||||
// if contact list was found, get user's feed, and keep the contact list for later use
|
// if contact list was found, get user's feed, and keep the contact list for later use
|
||||||
String authorName = getAuthorName(pubkey.first);
|
String authorName = getAuthorName(pubkey.first);
|
||||||
List<String> contactList = [];
|
List<String> contactList = [];
|
||||||
print("\nShowing the profile page for ${pubkey.first} ($authorName), whose contact list has ${ (contactEvent?.eventData.contactList.length)??0} profiles.\n ");
|
print("\nShowing the profile page for ${pubkey.first} ($authorName).\n");
|
||||||
if (contactEvent != null ) {
|
if (contactEvent != null ) {
|
||||||
|
print("The account follows ${contactEvent.eventData.contactList.length} accounts:");
|
||||||
|
|
||||||
contactEvent.eventData.contactList.forEach((x) => stdout.write("${getAuthorName(x.id)}, "));
|
contactEvent.eventData.contactList.forEach((x) => stdout.write("${getAuthorName(x.id)}, "));
|
||||||
|
List<String> followers = node.getFollowers(pubkey.first);
|
||||||
|
|
||||||
|
print("\n\nThe account has ${followers.length} followers: ");
|
||||||
|
|
||||||
|
followers.forEach((x) => stdout.write("${getAuthorName(x)}, "));
|
||||||
|
|
||||||
|
// print social distance info.
|
||||||
|
node.printSocialDistance(pubkey.first, authorName);
|
||||||
}
|
}
|
||||||
print("");
|
print("");
|
||||||
}
|
}
|
||||||
@@ -255,6 +266,7 @@ Future<void> otherMenuUi(Tree node, var contactList) async {
|
|||||||
node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), onlyWords); // search for last gNumLastDays only
|
node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), onlyWords); // search for last gNumLastDays only
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
print("TBD");
|
print("TBD");
|
||||||
break;
|
break;
|
||||||
@@ -286,6 +298,16 @@ Future<void> otherMenuUi(Tree node, var contactList) async {
|
|||||||
continueOtherMenu = false;
|
continueOtherMenu = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
stdout.write("Enter client name whose events you want to see: ");
|
||||||
|
String? $tempWords = stdin.readLineSync();
|
||||||
|
String clientName = $tempWords??"";
|
||||||
|
if( clientName != "") {
|
||||||
|
bool fromClient (Tree t) => t.fromClientSelector(clientName);
|
||||||
|
node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), fromClient); // search for last gNumLastDays only
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -301,7 +301,7 @@ class EventData {
|
|||||||
int n = 4;
|
int n = 4;
|
||||||
String maxN(String v) => v.length > n? v.substring(0,n) : v.substring(0, v.length);
|
String maxN(String v) => v.length > n? v.substring(0,n) : v.substring(0, v.length);
|
||||||
void printInColor(String s, String commentColor) => stdout.supportsAnsiEscapes ?stdout.write("$commentColor$s$colorEndMarker"):stdout.write(s);
|
void printInColor(String s, String commentColor) => stdout.supportsAnsiEscapes ?stdout.write("$commentColor$s$colorEndMarker"):stdout.write(s);
|
||||||
|
|
||||||
DateTime dTime = DateTime.fromMillisecondsSinceEpoch(createdAt *1000);
|
DateTime dTime = DateTime.fromMillisecondsSinceEpoch(createdAt *1000);
|
||||||
|
|
||||||
// TODO do it in one call
|
// TODO do it in one call
|
||||||
@@ -592,3 +592,4 @@ Set<String> getPublicKeyFromName(String userName) {
|
|||||||
|
|
||||||
return pubkeys;
|
return pubkeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -263,8 +263,10 @@ void getMultiUserEvents(serverUrl, List<String> publicKeys, numUserEvents) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendRequest(serverUrl, request) {
|
void sendRequest(List<String> serverUrls, request) {
|
||||||
relays.sendRequest(serverUrl, request);
|
for(int i = 0; i < serverUrls.length; i++) {
|
||||||
|
relays.sendRequest(serverUrls[i], request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Event> getRecievedEvents() {
|
List<Event> getRecievedEvents() {
|
||||||
@@ -273,6 +275,7 @@ List<Event> getRecievedEvents() {
|
|||||||
|
|
||||||
void clearEvents() {
|
void clearEvents() {
|
||||||
relays.rEvents = [];
|
relays.rEvents = [];
|
||||||
|
if( gDebug > 0) print("clearEvents(): returning");
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRelaysIntialEvents(eventsFromFile) {
|
void setRelaysIntialEvents(eventsFromFile) {
|
||||||
|
152
lib/tree_ds.dart
152
lib/tree_ds.dart
@@ -34,6 +34,7 @@ class Tree {
|
|||||||
events.forEach((event) {
|
events.forEach((event) {
|
||||||
// only add in map those kinds that are supported or supposed to be added ( 0 1 3 7 40)
|
// only add in map those kinds that are supported or supposed to be added ( 0 1 3 7 40)
|
||||||
//if( event.eventData.kind == 40 || event.eventData.kind == 42) if( gDebug > 0) print("in from Events: got a kind 40/42 event of id ${event.eventData.id} and kind ${event.eventData.kind}" );
|
//if( event.eventData.kind == 40 || event.eventData.kind == 42) if( gDebug > 0) print("in from Events: got a kind 40/42 event of id ${event.eventData.id} and kind ${event.eventData.kind}" );
|
||||||
|
//event.printEvent(0);
|
||||||
if( typesInEventMap.contains(event.eventData.kind)) {
|
if( typesInEventMap.contains(event.eventData.kind)) {
|
||||||
tempChildEventsMap[event.eventData.id] = Tree(event, [], {}, [], false, {});
|
tempChildEventsMap[event.eventData.id] = Tree(event, [], {}, [], false, {});
|
||||||
}
|
}
|
||||||
@@ -45,6 +46,8 @@ class Tree {
|
|||||||
List<String> tempWithoutParent = [];
|
List<String> tempWithoutParent = [];
|
||||||
Map<String, ChatRoom> rooms = {};
|
Map<String, ChatRoom> rooms = {};
|
||||||
|
|
||||||
|
if( gDebug > 0) print("In from Events: size of tempChildEventsMap = ${tempChildEventsMap.length} ");
|
||||||
|
|
||||||
tempChildEventsMap.forEach((key, value) {
|
tempChildEventsMap.forEach((key, value) {
|
||||||
String eId = value.e.eventData.id;
|
String eId = value.e.eventData.id;
|
||||||
int eKind = value.e.eventData.kind;
|
int eKind = value.e.eventData.kind;
|
||||||
@@ -71,20 +74,42 @@ class Tree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(eKind == 40) {
|
if(eKind == 40) {
|
||||||
|
//print("Processing type 40");
|
||||||
String chatRoomId = eId;
|
String chatRoomId = eId;
|
||||||
dynamic json = jsonDecode(value.e.eventData.content);
|
try {
|
||||||
|
//print("Processing type 40 json");
|
||||||
|
dynamic json = jsonDecode(value.e.eventData.content);
|
||||||
|
//print("Processed type 40 json");
|
||||||
|
|
||||||
if( rooms.containsKey(chatRoomId)) {
|
if( rooms.containsKey(chatRoomId)) {
|
||||||
if( rooms[chatRoomId]?.name == "") {
|
//print("in if chatRoomId key in rooms");
|
||||||
if( gDebug > 0) print('Added room name = ${json['name']} for $chatRoomId' );
|
if( rooms[chatRoomId]?.name == "") {
|
||||||
rooms[chatRoomId]?.name = json['name'];
|
if( gDebug > 0) print('Added room name = ${json['name']} for $chatRoomId' );
|
||||||
|
rooms[chatRoomId]?.name = json['name'];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
List<String> temp = [];
|
||||||
|
//temp.add(eId);
|
||||||
|
//print("in else");
|
||||||
|
//print("json = $json");
|
||||||
|
|
||||||
|
String roomName = "", roomAbout = "";
|
||||||
|
|
||||||
|
if( json.containsKey('name') ) {
|
||||||
|
roomName = json['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if( json.containsKey('about')) {
|
||||||
|
roomAbout = json['about'];
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatRoom room = ChatRoom(chatRoomId, roomName, roomAbout, "", []);
|
||||||
|
rooms[chatRoomId] = room;
|
||||||
|
if( gDebug > 0) print("Added new chat room $chatRoomId with name ${json['name']} .");
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
List<String> temp = [];
|
} on Exception catch(e) {
|
||||||
//temp.add(eId);
|
if( gDebug > 0) print("In From Event. Event type 40. Json Decode error for event id ${value.e.eventData.id}");
|
||||||
ChatRoom room = ChatRoom(chatRoomId, json['name'], json['about'], "", []);
|
|
||||||
rooms[chatRoomId] = room;
|
|
||||||
if( gDebug > 0) print("Added new chat room $chatRoomId with name ${json['name']} .");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,14 +696,13 @@ class Tree {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for( int i = 0; i < children.length; i++ ) {
|
for( int i = 0; i < children.length; i++ ) {
|
||||||
if( children[i].hasUserPost(pubkey)) {
|
if( children[i].hasUserPostAndLike(pubkey)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// returns true if the given words exists in it or its children
|
// returns true if the given words exists in it or its children
|
||||||
bool hasWords(String word) {
|
bool hasWords(String word) {
|
||||||
//if(gDebug > 0) print("In tree selector hasWords: this id = ${e.eventData.id} word = $word");
|
//if(gDebug > 0) print("In tree selector hasWords: this id = ${e.eventData.id} word = $word");
|
||||||
@@ -689,6 +713,7 @@ class Tree {
|
|||||||
if( e.eventData.content.toLowerCase().contains(word)) {
|
if( e.eventData.content.toLowerCase().contains(word)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( int i = 0; i < children.length; i++ ) {
|
for( int i = 0; i < children.length; i++ ) {
|
||||||
//if(gDebug > 0) print("this id = ${e.eventData.id} word = $word i = $i ");
|
//if(gDebug > 0) print("this id = ${e.eventData.id} word = $word i = $i ");
|
||||||
|
|
||||||
@@ -697,13 +722,38 @@ class Tree {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( children[i].e.eventData.content.toLowerCase().contains(word)) {
|
if( children[i].hasWords(word)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns true if the event or any of its children were made from the given client, and they are marked for notification
|
||||||
|
bool fromClientSelector(String clientName) {
|
||||||
|
//if(gDebug > 0) print("In tree selector hasWords: this id = ${e.eventData.id} word = $word");
|
||||||
|
|
||||||
|
List<List<String>> tags = e.eventData.tags;
|
||||||
|
for( int i = 0; i < tags.length; i++) {
|
||||||
|
if( tags[i].length < 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( tags[i][0] == "client" && tags[i][1].contains(clientName)) {
|
||||||
|
e.eventData.isNotification = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int i = 0; i < children.length; i++ ) {
|
||||||
|
if( children[i].fromClientSelector(clientName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Event? getContactEvent(String pkey) {
|
Event? getContactEvent(String pkey) {
|
||||||
|
|
||||||
// get the latest kind 3 event for the user, which lists his 'follows' list
|
// get the latest kind 3 event for the user, which lists his 'follows' list
|
||||||
@@ -729,6 +779,77 @@ class Tree {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//void create
|
||||||
|
|
||||||
|
List<String> getFollowers(String pubkey) {
|
||||||
|
if( gDebug > 0) print("Finding followrs for $pubkey");
|
||||||
|
List<String> followers = [];
|
||||||
|
|
||||||
|
Set<String> usersWithContactList = {};
|
||||||
|
allChildEventsMap.forEach((key, value) {
|
||||||
|
if( value.e.eventData.kind == 3) {
|
||||||
|
usersWithContactList.add(value.e.eventData.pubkey);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
usersWithContactList.forEach((x) {
|
||||||
|
Event? contactEvent = getContactEvent(x);
|
||||||
|
|
||||||
|
if( contactEvent != null) {
|
||||||
|
List<Contact> contacts = contactEvent.eventData.contactList;
|
||||||
|
for(int i = 0; i < contacts.length; i ++) {
|
||||||
|
if( contacts[i].id == pubkey) {
|
||||||
|
followers.add(x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return followers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printSocialDistance(String otherPubkey, String otherName) {
|
||||||
|
String otherName = getAuthorName(otherPubkey);
|
||||||
|
|
||||||
|
List<String> contactList = [];
|
||||||
|
Event? contactEvent = this.getContactEvent(userPublicKey);
|
||||||
|
bool isFollow = false;
|
||||||
|
int numSecond = 0; // number of your follows who follow the other
|
||||||
|
|
||||||
|
int numContacts = 0;
|
||||||
|
if( contactEvent != null) {
|
||||||
|
List<Contact> contacts = contactEvent.eventData.contactList;
|
||||||
|
numContacts = contacts.length;
|
||||||
|
for(int i = 0; i < contacts.length; i ++) {
|
||||||
|
// check if you follow the other account
|
||||||
|
if( contacts[i].id == otherPubkey) {
|
||||||
|
isFollow = true;
|
||||||
|
}
|
||||||
|
// count the number of your contacts who know or follow the other account
|
||||||
|
List<Contact> followContactList = [];
|
||||||
|
Event? followContactEvent = this.getContactEvent(contacts[i].id);
|
||||||
|
if( followContactEvent != null) {
|
||||||
|
followContactList = followContactEvent.eventData.contactList;
|
||||||
|
for(int j = 0; j < followContactList.length; j++) {
|
||||||
|
if( followContactList[j].id == otherPubkey) {
|
||||||
|
numSecond++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}// end for loop through users contacts
|
||||||
|
print("\n\n");
|
||||||
|
if( isFollow) {
|
||||||
|
print("* You follow $otherName ");
|
||||||
|
}
|
||||||
|
|
||||||
|
print("* Of the $numContacts people you follow, $numSecond follow $otherName");
|
||||||
|
|
||||||
|
} // end if contact event was found
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // end Tree
|
} // end Tree
|
||||||
|
|
||||||
void addMessageToChannel(String channelId, String messageId, var tempChildEventsMap, var chatRooms) {
|
void addMessageToChannel(String channelId, String messageId, var tempChildEventsMap, var chatRooms) {
|
||||||
@@ -829,10 +950,11 @@ void processReactions(List<Event> events) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @function getTree Creates a Tree out of these received List of events.
|
* @function getTree Creates a Tree out of these received List of events.
|
||||||
*/
|
*/
|
||||||
Tree getTree(List<Event> events) {
|
Future<Tree> getTree(List<Event> events) async {
|
||||||
if( events.isEmpty) {
|
if( events.isEmpty) {
|
||||||
print("Warning: In printEventsAsTree: events length = 0");
|
print("Warning: In printEventsAsTree: events length = 0");
|
||||||
return Tree(Event("","",EventData("non","", 0, 0, "", [], [], [], [[]], {}), [""], "[json]"), [], {}, [], true, {});
|
return Tree(Event("","",EventData("non","", 0, 0, "", [], [], [], [[]], {}), [""], "[json]"), [], {}, [], true, {});
|
||||||
|
Reference in New Issue
Block a user