mirror of
https://github.com/vishalxl/nostr_console.git
synced 2025-03-29 19:21:49 +01:00
added support for kind 40/42 messages, and displayed if any chat room are there. Messages not displayed yet
This commit is contained in:
parent
1fa49b8251
commit
dff3ff70b0
@ -56,7 +56,8 @@ Future<void> otherMenuUi(Tree node, var contactList) async {
|
||||
'Change number of days printed', // 2
|
||||
'Show a user profile', // 3
|
||||
'Show tweets containg word', // 4
|
||||
'Go back to main menu'], // 5
|
||||
'Chat rooms', // 5
|
||||
'Go back to main menu'], // 6
|
||||
"Other Menu");
|
||||
print('You picked: $option');
|
||||
switch(option) {
|
||||
@ -132,6 +133,10 @@ Future<void> otherMenuUi(Tree node, var contactList) async {
|
||||
break;
|
||||
|
||||
case 5:
|
||||
node.showChatRooms();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
continueOtherMenu = false;
|
||||
break;
|
||||
|
||||
|
@ -34,10 +34,6 @@ const String notificationColor = "\x1b[36m"; // cyan
|
||||
const String warningColor = "\x1B[31m"; // red
|
||||
const String colorEndMarker = "\x1B[0m";
|
||||
|
||||
// translate flag
|
||||
const int gNumTranslateDays = 4;
|
||||
bool gTranslate = false;
|
||||
|
||||
//String defaultServerUrl = 'wss://relay.damus.io';
|
||||
String defaultServerUrl = 'wss://nostr-relay.untethr.me';
|
||||
|
||||
@ -60,6 +56,9 @@ Map< String, List<List<String>> > gReactions = {};
|
||||
// is updated as kind 3 events are received
|
||||
Map< String, List<Contact>> gContactLists = {};
|
||||
|
||||
// chat rooms , mappint from chat room kind 40 event to its information as list where even = key, odd = value
|
||||
Map<String, List<String>> gChatRooms = {};
|
||||
|
||||
// bots ignored to reduce spam
|
||||
List<String> gBots = [ "3b57518d02e6acfd5eb7198530b2e351e5a52278fb2499d14b66db2b5791c512", // robosats orderbook
|
||||
"887645fef0ce0c3c1218d2f5d8e6132a19304cdc57cd20281d082f38cfea0072", // bestofhn
|
||||
@ -70,11 +69,9 @@ List<String> gBots = [ "3b57518d02e6acfd5eb7198530b2e351e5a52278fb2499d14b66db2
|
||||
//const String gDefaultEventsFilename = "events_store_nostr.txt";
|
||||
String gEventsFilename = ""; // is set in arguments, and if set, then file is read from and written to
|
||||
|
||||
// translate for this number of days
|
||||
const int gTranslateForDays = 2;
|
||||
|
||||
final translator = GoogleTranslator();
|
||||
|
||||
const int gNumTranslateDays = 4;// translate for this number of days
|
||||
bool gTranslate = false; // translate flag
|
||||
|
||||
int gDebug = 0;
|
||||
|
||||
@ -221,7 +218,7 @@ class EventData {
|
||||
contactList.add(c);
|
||||
}
|
||||
} else {
|
||||
if ( json['kind'] == 1 || json['kind'] == 7) {
|
||||
if ( json['kind'] == 1 || json['kind'] == 7 || json['kind'] == 42 ) {
|
||||
for( int i = 0; i < numTags; i++) {
|
||||
var tag = jsonTags[i];
|
||||
//stdout.write(tag);
|
||||
@ -307,7 +304,7 @@ class EventData {
|
||||
//final input = "Здравствуйте. Ты в порядке?";
|
||||
|
||||
// Using the Future API
|
||||
if( DateTime.fromMillisecondsSinceEpoch(createdAt *1000).compareTo( DateTime.now().subtract(Duration(days:gTranslateForDays)) ) > 0 ) {
|
||||
if( DateTime.fromMillisecondsSinceEpoch(createdAt *1000).compareTo( DateTime.now().subtract(Duration(days:gNumTranslateDays)) ) > 0 ) {
|
||||
if( gDebug > 0) print("Sending google request: translating $content");
|
||||
try {
|
||||
translator
|
||||
@ -322,6 +319,19 @@ class EventData {
|
||||
}
|
||||
}
|
||||
|
||||
// only applicable for kind 42 event
|
||||
String getChatRoomId() {
|
||||
if( kind != 42) {
|
||||
return "";
|
||||
}
|
||||
for(int i = 0; i < tags.length; i++) {
|
||||
if( tags[i][0] == "#e") {
|
||||
return tags[i][1];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// prints event data in the format that allows it to be shown in tree form by the Tree class
|
||||
void printEventData(int depth) {
|
||||
int n = 3;
|
||||
@ -434,6 +444,19 @@ class Event {
|
||||
}
|
||||
}
|
||||
|
||||
class ChatRoom {
|
||||
String chatRoomId; // id of the kind 40 start event
|
||||
String name;
|
||||
String about;
|
||||
String picture;
|
||||
List<String> messageIds; // all the 42 kind events in this
|
||||
|
||||
ChatRoom(this.chatRoomId, this.name, this.about, this.picture, this.messageIds);
|
||||
void insertMessage(String msg) {
|
||||
messageIds.add(msg);
|
||||
}
|
||||
}
|
||||
|
||||
List<String> getpTags(List<Event> events) {
|
||||
List<String> pTags = [];
|
||||
for(int i = 0; i < events.length; i++) {
|
||||
@ -492,6 +515,7 @@ List<Event> readEventsFromFile(String filename) {
|
||||
return events;
|
||||
}
|
||||
|
||||
// From the list of events provided, lookup the lastst contact information for the given user/pubkey
|
||||
Event? getContactEvent(List<Event> events, String pubkey) {
|
||||
|
||||
// get the latest kind 3 event for the user, which lists his 'follows' list
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'dart:io';
|
||||
import 'dart:convert';
|
||||
import 'package:nostr_console/event_ds.dart';
|
||||
|
||||
|
||||
@ -15,23 +16,25 @@ class Tree {
|
||||
Map<String, Tree> allChildEventsMap;
|
||||
List<String> eventsWithoutParent;
|
||||
bool whetherTopMost;
|
||||
Tree(this.e, this.children, this.allChildEventsMap, this.eventsWithoutParent, this.whetherTopMost);
|
||||
Map<String, ChatRoom> chatRooms = {};
|
||||
Tree(this.e, this.children, this.allChildEventsMap, this.eventsWithoutParent, this.whetherTopMost, this.chatRooms);
|
||||
|
||||
static const List<int> typesInEventMap = [0, 1, 3, 7]; // 0 meta, 1 post, 3 follows list, 7 reactions
|
||||
static const List<int> typesInEventMap = [0, 1, 3, 7, 40, 42]; // 0 meta, 1 post, 3 follows list, 7 reactions
|
||||
|
||||
// @method create top level Tree from events.
|
||||
// first create a map. then process each element in the map by adding it to its parent ( if its a child tree)
|
||||
factory Tree.fromEvents(List<Event> events) {
|
||||
if( events.isEmpty) {
|
||||
return Tree(Event("","",EventData("non","", 0, 0, "", [], [], [], [[]], {}), [""], "[json]"), [], {}, [], false);
|
||||
return Tree(Event("","",EventData("non","", 0, 0, "", [], [], [], [[]], {}), [""], "[json]"), [], {}, [], false, {});
|
||||
}
|
||||
|
||||
// create a map from list of events, key is eventId and value is event itself
|
||||
Map<String, Tree> allChildEventsMap = {};
|
||||
events.forEach((event) {
|
||||
// only add in map those kinds that are supported or supposed to be added ( 0 1 3 7)
|
||||
// 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( typesInEventMap.contains(event.eventData.kind)) {
|
||||
allChildEventsMap[event.eventData.id] = Tree(event, [], {}, [], false);
|
||||
allChildEventsMap[event.eventData.id] = Tree(event, [], {}, [], false, {});
|
||||
}
|
||||
});
|
||||
|
||||
@ -39,10 +42,49 @@ class Tree {
|
||||
List<Tree> topLevelTrees = [];
|
||||
|
||||
List<String> tempWithoutParent = [];
|
||||
allChildEventsMap.forEach((key, value) {
|
||||
Map<String, ChatRoom> rooms = {};
|
||||
|
||||
// only posts areadded to this tree structure
|
||||
if( value.e.eventData.kind != 1) {
|
||||
allChildEventsMap.forEach((key, value) {
|
||||
String eId = value.e.eventData.id;
|
||||
int eKind = value.e.eventData.kind;
|
||||
if(eKind == 42) {
|
||||
String chatRoomId = value.e.eventData.getChatRoomId();
|
||||
if( chatRoomId != "") {
|
||||
if( rooms.containsKey(chatRoomId)) {
|
||||
rooms[chatRoomId]?.insertMessage(eId);
|
||||
if( gDebug > 0) print("Added new message to a chat room $chatRoomId. ");
|
||||
} else {
|
||||
List<String> temp = [];
|
||||
temp.add(eId);
|
||||
ChatRoom room = ChatRoom(chatRoomId, "", "", "", temp);
|
||||
rooms[chatRoomId] = room;
|
||||
if( gDebug > 0) print("Added new chat room object $chatRoomId and added message to it. ");
|
||||
}
|
||||
} else {
|
||||
if( gDebug > 0) print("Could not get chat room id for event $eId, its original json: ");
|
||||
if( gDebug > 0) print(value.e.originalJson);
|
||||
}
|
||||
}
|
||||
|
||||
if(eKind == 40) {
|
||||
String chatRoomId = eId;
|
||||
if( rooms.containsKey(chatRoomId)) {
|
||||
if( rooms[chatRoomId]?.name == "") {
|
||||
dynamic json = jsonDecode(value.e.eventData.content);
|
||||
if( gDebug > 0) print('Added room name = ${json['name']} for $chatRoomId' );
|
||||
rooms[chatRoomId]?.name = json['name'];
|
||||
}
|
||||
} else {
|
||||
List<String> temp = [];
|
||||
temp.add(eId);
|
||||
ChatRoom room = ChatRoom(chatRoomId, "", "", "", temp);
|
||||
rooms[chatRoomId] = room;
|
||||
if( gDebug > 0) print("Added new chat room $chatRoomId.");
|
||||
}
|
||||
}
|
||||
|
||||
// only posts, of kind 1, are added to the main tree structure
|
||||
if( eKind != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -64,7 +106,10 @@ class Tree {
|
||||
} else {
|
||||
// in case where the parent of the new event is not in the pool of all events,
|
||||
// then we create a dummy event and put it at top ( or make this a top event?) TODO handle so that this can be replied to, and is fetched
|
||||
Tree dummyTopNode = Tree(Event("","",EventData("Unk" ,gDummyAccountPubkey, value.e.eventData.createdAt , 1, "Unknown parent event", [], [], [], [[]], {}), [""], "[json]"), [], {}, [], false);
|
||||
Tree dummyTopNode = Tree(Event("","",
|
||||
EventData("Unk" ,gDummyAccountPubkey, value.e.eventData.createdAt , 1, "Unknown parent event", [], [], [], [[]], {}),
|
||||
[""], "[json]"),
|
||||
[], {}, [], false, {});
|
||||
dummyTopNode.addChildNode(value);
|
||||
tempWithoutParent.add(value.e.eventData.id);
|
||||
|
||||
@ -82,10 +127,12 @@ class Tree {
|
||||
}
|
||||
}
|
||||
|
||||
if( gDebug != 0) print("at end of tree from events: Total number of chat rooms: ${rooms.length}");
|
||||
if(gDebug != 0) print("number of events without parent in fromEvents = ${tempWithoutParent.length}");
|
||||
|
||||
// create a dummy top level tree and then create the main Tree object
|
||||
Event dummy = Event("","", EventData("non","", 0, 1, "Dummy Top event. Should not be printed.", [], [], [], [[]], {}), [""], "[json]");
|
||||
return Tree( dummy, topLevelTrees, allChildEventsMap, tempWithoutParent, true); // TODO remove events[0]
|
||||
return Tree( dummy, topLevelTrees, allChildEventsMap, tempWithoutParent, true, rooms);
|
||||
} // end fromEvents()
|
||||
|
||||
/*
|
||||
@ -125,7 +172,7 @@ class Tree {
|
||||
newEvent.eventData.translateAndExpandMentions();
|
||||
|
||||
if( gDebug > 0) print("In insertEvents: adding event to main children map");
|
||||
allChildEventsMap[newEvent.eventData.id] = Tree(newEvent, [], {}, [], false);
|
||||
allChildEventsMap[newEvent.eventData.id] = Tree(newEvent, [], {}, [], false, {});
|
||||
newEventsId.add(newEvent.eventData.id);
|
||||
});
|
||||
|
||||
@ -317,6 +364,27 @@ class Tree {
|
||||
print("\n");
|
||||
}
|
||||
|
||||
void showChatRooms() {
|
||||
print("\n\nChat Rooms:");
|
||||
printChatRoomInfo();
|
||||
}
|
||||
|
||||
void printChatRoomInfo() {
|
||||
chatRooms.forEach((key, value) {
|
||||
String name = "";
|
||||
if( value.name == "") {
|
||||
name = value.chatRoomId;
|
||||
} else {
|
||||
name = value.name;
|
||||
}
|
||||
int numMessages = value.messageIds.length;
|
||||
|
||||
print("-----------$name---------");
|
||||
print("Total number of messages: $numMessages");
|
||||
print("\n\n");
|
||||
});
|
||||
}
|
||||
|
||||
// Write the tree's events to file as one event's json per line
|
||||
Future<void> writeEventsToFile(String filename) async {
|
||||
//print("opening $filename to write to");
|
||||
@ -420,7 +488,7 @@ class Tree {
|
||||
|
||||
void addChild(Event child) {
|
||||
Tree node;
|
||||
node = Tree(child, [], {}, [], false);
|
||||
node = Tree(child, [], {}, [], false, {});
|
||||
children.add(node);
|
||||
}
|
||||
|
||||
@ -622,7 +690,7 @@ void processReactions(List<Event> events) {
|
||||
Tree getTree(List<Event> events) {
|
||||
if( events.isEmpty) {
|
||||
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, {});
|
||||
}
|
||||
|
||||
// populate the global with display names which can be later used by Event print
|
||||
@ -631,7 +699,7 @@ Tree getTree(List<Event> events) {
|
||||
// process NIP 25, or event reactions by adding them to a global map
|
||||
processReactions(events);
|
||||
|
||||
// remove all events other than kind 0, 1, 3 and 7
|
||||
// remove all events other than kind 0, 1, 3, 7 and 40 (chat rooms)
|
||||
events.removeWhere( (item) => !Tree.typesInEventMap.contains(item.eventData.kind));
|
||||
|
||||
// remove bot events
|
||||
|
@ -9,8 +9,8 @@ EventData exampleEdataChild = EventData("id2", "pubkey", 1111111, 1, "content ch
|
||||
Event exampleEvent = Event('event', 'id3', exampleEdata, ['relay name'], "[json]");
|
||||
Event exampleEventChild = Event('event', 'id4', exampleEdataChild, ['relay name'], "[json]");
|
||||
|
||||
Tree exampleNode = Tree(exampleEvent, [], {}, [], false);
|
||||
Tree exampleNodeChild = Tree(exampleEventChild, [], {}, [], false);
|
||||
Tree exampleNode = Tree(exampleEvent, [], {}, [], false, {});
|
||||
Tree exampleNodeChild = Tree(exampleEventChild, [], {}, [], false, {});
|
||||
|
||||
void main() {
|
||||
test('PrintEmptyEvent', () {
|
||||
|
Loading…
x
Reference in New Issue
Block a user