mirror of
https://github.com/vishalxl/nostr_console.git
synced 2025-04-02 17:08:12 +02:00
improved channel logic
fix: put messages in order in channels improved dm menu. encryption etc still todo.
This commit is contained in:
parent
582c422792
commit
74541890b4
@ -88,6 +88,27 @@ Future<void> sendChatMessage(Store node, String channelId, String messageToSend)
|
||||
sendRequest( gListRelayUrls, toSendMessage);
|
||||
}
|
||||
|
||||
// is same as above. remove it TODO
|
||||
Future<void> sendDirectMessage(Store node, String otherPubkey, String messageToSend) async {
|
||||
print("TBD");
|
||||
return;
|
||||
// TODO implement
|
||||
|
||||
String replyKind = "4";
|
||||
|
||||
String strTags = node.getTagStr(otherPubkey, exename);
|
||||
int createdAt = DateTime.now().millisecondsSinceEpoch ~/1000;
|
||||
|
||||
String id = getShaId(userPublicKey, createdAt, replyKind, strTags, messageToSend);
|
||||
String sig = sign(userPrivateKey, id, "12345612345612345612345612345612");
|
||||
|
||||
String toSendMessage = '["EVENT",{"id":"$id","pubkey":"$userPublicKey","created_at":$createdAt,"kind":$replyKind,"tags":[$strTags],"content":"$messageToSend","sig":"$sig"}]';
|
||||
//relays.sendRequest(defaultServerUrl, toSendMessage);
|
||||
|
||||
sendRequest( gListRelayUrls, toSendMessage);
|
||||
}
|
||||
|
||||
|
||||
// sends event e; used to send kind 3 event
|
||||
Future<void> sendEvent(Store node, Event e) async {
|
||||
String strTags = "";
|
||||
@ -436,7 +457,7 @@ Future<void> channelMenuUI(Store node) async {
|
||||
int option = showMenu([ 'Show public channels', // 1
|
||||
'Enter a public channel', // 2
|
||||
'See personal Inbox',
|
||||
'Send a direct message',
|
||||
'Reply or Send a direct message',
|
||||
'Go back to main menu'], // 5
|
||||
"Channel Menu"); // name of menu
|
||||
print('You picked: $option');
|
||||
@ -493,9 +514,58 @@ Future<void> channelMenuUI(Store node) async {
|
||||
break;
|
||||
|
||||
case 3:
|
||||
print("total direct rooms = ${node.directRooms.length}");
|
||||
//print("total direct rooms = ${node.directRooms.length}");
|
||||
node.printDirectRoomInfo();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// in case the program was invoked with --pubkey, then user can't send messages
|
||||
if( userPrivateKey == "") {
|
||||
print("Since no private key has been supplied, messages and replies can't be sent. Invoke with --prikey \n");
|
||||
break;
|
||||
}
|
||||
|
||||
bool showChannelOption = true;
|
||||
stdout.write("\nType user public key, or its 1st few letters; or type 'x' to go to menu: ");
|
||||
String? $tempUserInput = stdin.readLineSync();
|
||||
String directRoomId = $tempUserInput??"";
|
||||
|
||||
if( directRoomId == "x") {
|
||||
showChannelOption = false;
|
||||
}
|
||||
int pageNum = 1;
|
||||
while(showChannelOption) {
|
||||
String fullChannelId = node.showDirectRoom(directRoomId, pageNum);
|
||||
if( fullChannelId == "") {
|
||||
print("Could not find the given direct room.");
|
||||
showChannelOption = false;
|
||||
break;
|
||||
}
|
||||
|
||||
stdout.write("\nType message; or type 'x' to exit, or press <enter> to refresh: ");
|
||||
$tempUserInput = stdin.readLineSync(encoding: utf8);
|
||||
String messageToSend = $tempUserInput??"";
|
||||
|
||||
if( messageToSend != "") {
|
||||
if( messageToSend == 'x') {
|
||||
showChannelOption = false;
|
||||
} else {
|
||||
if( messageToSend.isChannelPageNumber(gMaxChannelPagesDisplayed) ) {
|
||||
pageNum = (int.tryParse(messageToSend))??1;
|
||||
} else {
|
||||
// send message to the given room
|
||||
await sendChatMessage(node, fullChannelId, messageToSend);
|
||||
pageNum = 1; // reset it
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print("Refreshing...");
|
||||
}
|
||||
|
||||
await processNotifications(node);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 5:
|
||||
continueChatMenu = false;
|
||||
@ -513,7 +583,7 @@ Future<void> mainMenuUi(Store node) async {
|
||||
// at the very beginning, show the tree as it is, and then show the options menu
|
||||
|
||||
bool hasRepliesAndLikes (Tree t) => t.hasRepliesAndLikes(userPublicKey);
|
||||
//node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), hasRepliesAndLikes);
|
||||
node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), hasRepliesAndLikes);
|
||||
|
||||
bool userContinue = true;
|
||||
while(userContinue) {
|
||||
@ -542,7 +612,7 @@ Future<void> mainMenuUi(Store node) async {
|
||||
print('You picked: $option');
|
||||
switch(option) {
|
||||
case 1:
|
||||
//node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), selectAll);
|
||||
node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), selectAll);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
@ -5,7 +5,21 @@ import 'package:translator/translator.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:nostr_console/settings.dart';
|
||||
|
||||
int gDebug = 1;
|
||||
import 'package:kepler/kepler.dart';
|
||||
|
||||
import "dart:typed_data";
|
||||
import "dart:math";
|
||||
import 'dart:convert' as convert;
|
||||
import "package:pointycastle/export.dart";
|
||||
import 'package:hex/hex.dart';
|
||||
import 'package:base58check/base58.dart';
|
||||
import 'package:pointycastle/src/impl/secure_random_base.dart';
|
||||
import "package:pointycastle/src/registry/registry.dart";
|
||||
import "package:pointycastle/src/ufixnum.dart";
|
||||
import "package:pointycastle/export.dart";
|
||||
|
||||
|
||||
int gDebug = 0;
|
||||
|
||||
// translate
|
||||
final translator = GoogleTranslator();
|
||||
@ -125,12 +139,9 @@ class EventData {
|
||||
}
|
||||
}
|
||||
|
||||
if(gDebug >= 2 ) {
|
||||
print("----------------------------------------Creating EventData with content: ${json['content']}");
|
||||
}
|
||||
|
||||
if( json['id'] == gCheckEventId) {
|
||||
if(gDebug > 0) print("In Event fromJson: got message: $gCheckEventId");
|
||||
print("\n----------------------------------------Creating EventData with content: ${json['content']}");
|
||||
print("In Event fromJson: got message: $gCheckEventId");
|
||||
}
|
||||
|
||||
return EventData(json['id'] as String, json['pubkey'] as String,
|
||||
@ -168,13 +179,19 @@ class EventData {
|
||||
}
|
||||
|
||||
void translateAndExpandMentions() {
|
||||
|
||||
|
||||
if (content == "") {
|
||||
return;
|
||||
}
|
||||
|
||||
if( evaluatedContent == "") {
|
||||
evaluatedContent = expandMentions(content);
|
||||
if( evaluatedContent != "") {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(kind) {
|
||||
case 1:
|
||||
evaluatedContent = expandMentions(content);
|
||||
if( gTranslate && !evaluatedContent.isEnglish()) {
|
||||
if( gDebug > 0) print("found that this comment is non-English: $evaluatedContent");
|
||||
//final input = "Здравствуйте. Ты в порядке?";
|
||||
@ -187,14 +204,84 @@ class EventData {
|
||||
.translate(content, to: 'en')
|
||||
//.catchError( (error, stackTrace) => null )
|
||||
.then( (result) => { evaluatedContent = "$evaluatedContent\n\nTranslation: ${result.toString()}" , if( gDebug > 0) print("Google translate returned successfully for one call.")}
|
||||
);
|
||||
);
|
||||
} on Exception catch(err) {
|
||||
if( gDebug >= 0) print("Info: Error in trying to use google translate: $err");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
break;
|
||||
// not implemented yet. has issues.
|
||||
if(!isUserDirectMessage(this)) {
|
||||
break;
|
||||
}
|
||||
printEventData(0);
|
||||
|
||||
print("\n\n");
|
||||
|
||||
{ // sample from kepler
|
||||
|
||||
var alice = Kepler.generateKeyPair();
|
||||
|
||||
print(
|
||||
"alice private key: " +
|
||||
Kepler.strinifyPrivateKey(alice.privateKey as ECPrivateKey),
|
||||
);
|
||||
print(
|
||||
"alice public key: " +
|
||||
Kepler.strinifyPublicKey(alice.publicKey as ECPublicKey),
|
||||
);
|
||||
|
||||
// Create Bob's keypair
|
||||
var bob = Kepler.generateKeyPair();
|
||||
|
||||
// This is what alice wants to say to bob
|
||||
var rawStr = 'Encrypt and decrypt data using secp256k1';
|
||||
|
||||
// use alic's privatekey and bob's publickey means alice says to bob
|
||||
var encMap = Kepler.pubkeyEncrypt(
|
||||
Kepler.strinifyPrivateKey(alice.privateKey as ECPrivateKey),
|
||||
Kepler.strinifyPublicKey(bob.publicKey as ECPublicKey),
|
||||
rawStr,
|
||||
);
|
||||
|
||||
// Get encrypted base64 string
|
||||
var encStr = encMap['enc'];
|
||||
print("encrypted text: " + encStr!);
|
||||
|
||||
// Get random IV
|
||||
var iv = encMap['iv'];
|
||||
print("iv: " + iv!);
|
||||
// Now, you can send enc_str and IV to Bob
|
||||
|
||||
// Use bob's privatekey and alice's publickey to decrypt alices message, for Bob to read.
|
||||
var decryptd = Kepler.privateDecrypt(
|
||||
Kepler.strinifyPrivateKey(bob.privateKey as ECPrivateKey),
|
||||
Kepler.strinifyPublicKey(alice.publicKey as ECPublicKey),
|
||||
encStr,
|
||||
iv,
|
||||
);
|
||||
print('decrypted text: $decryptd');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
print("in translateAndExpandMentions() for a dm pubkey = $pubkey content = $content");
|
||||
print("tags = $tags");
|
||||
|
||||
|
||||
int ivIndex = content.indexOf("?iv=");
|
||||
var enc_str = content.substring(0, ivIndex);
|
||||
var iv = content.substring( ivIndex + 4, content.length);
|
||||
print("enc_str = $enc_str ; iv = $iv");
|
||||
var decryptd = myPrivateDecrypt( userPrivateKey, "03" + pubkey, enc_str, iv); // use bob's privatekey and alic's publickey means bob can read message from alic
|
||||
print('they say:${decryptd}');
|
||||
|
||||
break;
|
||||
} // end switch
|
||||
} // end translateAndExpandMentions
|
||||
|
||||
// only applicable for kind 42 event
|
||||
String getChatRoomId() {
|
||||
@ -394,14 +481,18 @@ Set<Event> readEventsFromFile(String filename) {
|
||||
try {
|
||||
List<String> lines = file.readAsLinesSync();
|
||||
for( int i = 0; i < lines.length; i++ ) {
|
||||
Event e = Event.fromJson(lines[i], "");
|
||||
events.add(e);
|
||||
Event e = Event.fromJson(lines[i], "");
|
||||
if( e.eventData.id == gCheckEventId) {
|
||||
print("read $gCheckEventId from file");
|
||||
}
|
||||
events.add(e);
|
||||
}
|
||||
} on Exception catch(e) {
|
||||
//print("cannot open file $gEventsFilename");
|
||||
if( gDebug > 0) print("Could not open file. error = $e");
|
||||
}
|
||||
|
||||
if( gDebug > 0) print("In readEventsFromFile: returning ${events.length} total events");
|
||||
return events;
|
||||
}
|
||||
|
||||
@ -532,7 +623,7 @@ String getAuthorName(String pubkey) {
|
||||
Set<String> getPublicKeyFromName(String userName) {
|
||||
Set<String> pubkeys = {};
|
||||
|
||||
if(gDebug > 0) print("In getPublicKeyFromName: doing lookup for $userName len of gKindONames= ${gKindONames.length}");
|
||||
if(gDebug >= 0) print("In getPublicKeyFromName: doing lookup for $userName len of gKindONames= ${gKindONames.length}");
|
||||
|
||||
gKindONames.forEach((pk, value) {
|
||||
// check both the user name, and the pubkey to search for the user
|
||||
@ -710,3 +801,57 @@ String getPrintableDate(int createdAt) {
|
||||
strDate += " ${df2.format(DateTime.fromMillisecondsSinceEpoch(createdAt*1000))}";
|
||||
return strDate;
|
||||
}
|
||||
|
||||
bool isUserDirectMessage(EventData directMessageData) {
|
||||
if( directMessageData.pubkey == userPublicKey) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sentToUser = false;
|
||||
directMessageData.tags.forEach((tag) {
|
||||
if( tag.length < 2 )
|
||||
return;
|
||||
if( tag[0] == "p" && tag[1] == userPublicKey) {
|
||||
//print("in isUserDirectMessage ${tag[1]}");
|
||||
sentToUser = true;
|
||||
}
|
||||
});
|
||||
|
||||
return sentToUser;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Decrypt data using self private key
|
||||
String myPrivateDecrypt(
|
||||
String privateString, String publicString, String b64encoded,
|
||||
[String b64IV = ""]) {
|
||||
|
||||
Uint8List encdData = convert.base64.decode(b64encoded);
|
||||
final rawData = myPrivateDecryptRaw(privateString, publicString, encdData, b64IV);
|
||||
convert.Utf8Decoder decode = const convert.Utf8Decoder();
|
||||
return decode.convert(rawData.toList());
|
||||
}
|
||||
|
||||
Uint8List myPrivateDecryptRaw(
|
||||
String privateString, String publicString, Uint8List encdData,
|
||||
[String b64IV = ""]) {
|
||||
final secretIV = Kepler.byteSecret(privateString, publicString);
|
||||
final secret = Uint8List.fromList(secretIV[0]);
|
||||
|
||||
final iv = b64IV.length > 6
|
||||
? convert.base64.decode(b64IV)
|
||||
: Uint8List.fromList(secretIV[1]);
|
||||
|
||||
ChaCha20Engine _cipher = ChaCha20Engine();
|
||||
|
||||
_cipher.reset();
|
||||
_cipher.init(false, buildParams(secret, iv));
|
||||
return _cipher.process(encdData);
|
||||
}
|
||||
|
||||
ParametersWithIV<KeyParameter> buildParams(
|
||||
Uint8List key, Uint8List iv) {
|
||||
return ParametersWithIV<KeyParameter>(KeyParameter(key), iv);
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ import 'package:logging/logging.dart';
|
||||
final log = Logger('ExampleLogger');
|
||||
|
||||
// for debugging
|
||||
String gCheckEventId = "15d86a36a620fc1f735f2322f31366b2adde786361f568faf6a0dc8368f7e534";
|
||||
String gCheckEventId = ""; //"1763016774ceaa8c135dce01e77923994c5afad4cd3e126704a1292ebb1a577e"; //"15d86a36a620fc1f735f2322f31366b2adde786361f568faf6a0dc8368f7e534";
|
||||
|
||||
const int gDefaultNumWaitSeconds = 3000; // is used in main()
|
||||
|
||||
|
138
lib/tree_ds.dart
138
lib/tree_ds.dart
@ -1,6 +1,5 @@
|
||||
import 'dart:io';
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
import 'package:nostr_console/event_ds.dart';
|
||||
import 'package:nostr_console/settings.dart';
|
||||
|
||||
@ -32,7 +31,7 @@ class ScrollableMessages {
|
||||
page = 1;
|
||||
}
|
||||
|
||||
print(topHeader);
|
||||
//print(topHeader);
|
||||
|
||||
String displayName = topHeader;
|
||||
|
||||
@ -79,7 +78,7 @@ class ChatRoom extends ScrollableMessages {
|
||||
String about;
|
||||
String picture;
|
||||
|
||||
ChatRoom(this.chatRoomId, this.internalChatRoomName, this.about, this.picture, messageIds) :
|
||||
ChatRoom(this.chatRoomId, this.internalChatRoomName, this.about, this.picture, List<String> messageIds) :
|
||||
super ( "${internalChatRoomName} ( ${chatRoomId.substring(0, 6)}", messageIds);
|
||||
|
||||
String get chatRoomName {
|
||||
@ -374,21 +373,21 @@ class Store {
|
||||
switch(eKind) {
|
||||
case 42:
|
||||
{
|
||||
//numKind42Events++;
|
||||
if( gCheckEventId == ce.eventData.id) print("In handleChannelEvents: processing $gCheckEventId ");
|
||||
String chatRoomId = ce.eventData.getChatRoomId();
|
||||
if( chatRoomId != "") {
|
||||
if( chatRoomId != "") { // sometimes people may forget to give e tags or give wrong tags like #e
|
||||
if( rooms.containsKey(chatRoomId)) {
|
||||
//if( gDebug > 0) print("Adding new message $key to a chat room $chatRoomId. ");
|
||||
if( gDebug > 0) print("chat room already exists = $chatRoomId adding event to it" );
|
||||
|
||||
if( gCheckEventId == ce.eventData.id) print("Adding new message $eId to a chat room $chatRoomId. ");
|
||||
|
||||
addMessageToChannel(chatRoomId, eId, tempChildEventsMap, rooms);
|
||||
|
||||
} 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. ");
|
||||
if( gCheckEventId == ce.eventData.id) print("Adding new message $eId to NEW chat room $chatRoomId. ");
|
||||
rooms[chatRoomId] = ChatRoom(chatRoomId, "", "", "", []);
|
||||
addMessageToChannel(chatRoomId, eId, tempChildEventsMap, rooms);
|
||||
}
|
||||
} else {
|
||||
//if( gDebug > 0) print("Could not get chat room id for event $eId, its original json: ");
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -427,28 +426,11 @@ class Store {
|
||||
} // end switch
|
||||
}
|
||||
|
||||
static bool isUserDirectMessage(Event directMessage) {
|
||||
if( directMessage.eventData.pubkey == userPublicKey) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sentToUser = false;
|
||||
directMessage.eventData.tags.forEach((tag) {
|
||||
if( tag.length < 2 )
|
||||
return;
|
||||
if( tag[0] == "p" && tag[1] == userPublicKey) {
|
||||
sentToUser = true;
|
||||
}
|
||||
});
|
||||
|
||||
return sentToUser;
|
||||
}
|
||||
|
||||
static void handleDirectMessages( Map<String, DirectMessageRoom> directRooms, Map<String, Tree> tempChildEventsMap, Event ce) {
|
||||
String eId = ce.eventData.id;
|
||||
int eKind = ce.eventData.kind;
|
||||
|
||||
if( !isUserDirectMessage(ce)) {
|
||||
if( !isUserDirectMessage(ce.eventData)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -458,17 +440,17 @@ class Store {
|
||||
String directRoomId = getDirectRoomId(ce.eventData);
|
||||
if( directRoomId != "") {
|
||||
if( directRooms.containsKey(directRoomId)) {
|
||||
if( gDebug >= 0) print("Adding new message ${ce.eventData.id} to a direct room $directRoomId. ");
|
||||
if( gDebug > 0) print("Adding new message ${ce.eventData.id} to a direct room $directRoomId sender pubkey = ${ce.eventData.pubkey}. ");
|
||||
addMessageToDirectRoom(directRoomId, eId, tempChildEventsMap, directRooms);
|
||||
} else {
|
||||
List<String> temp = [];
|
||||
temp.add(eId);
|
||||
DirectMessageRoom newDirectRoom= DirectMessageRoom(directRoomId, temp);
|
||||
directRooms[directRoomId] = newDirectRoom;
|
||||
if( gDebug >= 0) print("Adding new message ${ce.eventData.id} to NEW direct room $directRoomId. ");
|
||||
if( gDebug > 0) print("Adding new message ${ce.eventData.id} to NEW direct room $directRoomId. sender pubkey = ${ce.eventData.pubkey}.");
|
||||
}
|
||||
} else {
|
||||
if( gDebug > 0) print("Could not get chat room id for event ${ce.eventData.id}, its original json: ");
|
||||
if( gDebug > 0) print("Could not get chat room id for event ${ce.eventData.id} sender pubkey = ${ce.eventData.pubkey}.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -528,7 +510,7 @@ class Store {
|
||||
// is not a parent, find its parent and then add this element to that parent Tree
|
||||
String parentId = tree.event.eventData.getParent();
|
||||
if( tree.event.eventData.id == gCheckEventId) {
|
||||
if(gDebug > 0) print("In Tree FromEvents: got id: $gCheckEventId");
|
||||
if(gDebug >= 0) print("In Tree FromEvents: got id: $gCheckEventId");
|
||||
}
|
||||
|
||||
if(tempChildEventsMap.containsKey( parentId)) {
|
||||
@ -600,7 +582,7 @@ class Store {
|
||||
return;
|
||||
}
|
||||
|
||||
if( !isUserDirectMessage(newEvent)) { // direct message not relevant to user are ignored
|
||||
if( !isUserDirectMessage(newEvent.eventData)) { // direct message not relevant to user are ignored
|
||||
return;
|
||||
}
|
||||
|
||||
@ -611,7 +593,8 @@ class Store {
|
||||
}
|
||||
|
||||
// expand mentions ( and translate if flag is set) and then add event to main event map
|
||||
newEvent.eventData.translateAndExpandMentions();
|
||||
newEvent.eventData.translateAndExpandMentions(); // this also handles dm decryption for kind 4 messages, for kind 1 will do translation/expansion;
|
||||
|
||||
eventsNotReadFromFile.add(newEvent.eventData.id); // used later so that only these events are appended to the file
|
||||
|
||||
// add them to the main store of the Tree object
|
||||
@ -651,31 +634,37 @@ class Store {
|
||||
case 4:
|
||||
// add kind 4 direct chat message event to its direct massage room
|
||||
String directRoomId = getDirectRoomId(newTree.event.eventData);
|
||||
print("in insert events: got directRoomId = ${directRoomId}");
|
||||
//print("in insert events: got directRoomId = ${directRoomId}");
|
||||
if( directRoomId != "") {
|
||||
if( directRooms.containsKey(directRoomId)) {
|
||||
if( gDebug > 0) print("added event to chat room in insert event");
|
||||
if( gDebug > 0) print("added event to direct room in insert event");
|
||||
addMessageToDirectRoom(directRoomId, newTree.event.eventData.id, allChildEventsMap, directRooms);
|
||||
newTree.event.eventData.isNotification = true; // highlight it too in next printing
|
||||
print(" in from event: added it to a direct room");
|
||||
//print(" in from event: added it to a direct room");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
print(" in insert events, could not find parent/channel id");
|
||||
}
|
||||
|
||||
List<String> temp = [];
|
||||
temp.add(newTree.event.eventData.id);
|
||||
directRooms[directRoomId] = DirectMessageRoom(directRoomId, temp); // TODO sort it
|
||||
|
||||
break;
|
||||
|
||||
case 42:
|
||||
newTree.event.eventData.isNotification = true; // highlight it too in next printing
|
||||
// add 42 chat message event id to its chat room
|
||||
String channelId = newTree.event.eventData.getParent();
|
||||
if( channelId != "") {
|
||||
if( chatRooms.containsKey(channelId)) {
|
||||
if( gDebug > 0) print("added event to chat room in insert event");
|
||||
addMessageToChannel(channelId, newTree.event.eventData.id, allChildEventsMap, chatRooms); // adds in order
|
||||
break;
|
||||
} else {
|
||||
chatRooms[channelId] = ChatRoom(channelId, "", "", "", []);
|
||||
addMessageToChannel(channelId, newTree.event.eventData.id, allChildEventsMap, chatRooms);
|
||||
newTree.event.eventData.isNotification = true; // highlight it too in next printing
|
||||
}
|
||||
} else {
|
||||
print("info: in insert events, could not find parent/channel id");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -852,13 +841,8 @@ class Store {
|
||||
print("\n\nDirect messages inbox:");
|
||||
printUnderlined(" From Num of Messages Latest Message ");
|
||||
directRooms.forEach((key, value) {
|
||||
String name = "direct room name";
|
||||
/* if( value.chatRoomName == "") {
|
||||
name = value.chatRoomId.substring(0, 6);
|
||||
} else {
|
||||
name = "${value.chatRoomName} ( ${value.chatRoomId.substring(0, 6)})";
|
||||
}
|
||||
*/
|
||||
String name = getAuthorName(key);
|
||||
|
||||
int numMessages = value.messageIds.length;
|
||||
stdout.write("${name} ${getNumSpaces(32-name.length)} $numMessages${getNumSpaces(12- numMessages.toString().length)}");
|
||||
List<String> messageIds = value.messageIds;
|
||||
@ -875,6 +859,28 @@ class Store {
|
||||
});
|
||||
}
|
||||
|
||||
// shows the given directRoomId, where directRoomId is prefix-id or pubkey of the other user. returns full id of other user.
|
||||
String showDirectRoom(String directRoomId, [int page = 1]) {
|
||||
if( !directRooms.containsKey(directRoomId)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if( directRoomId.length != 64) {
|
||||
return "";
|
||||
}
|
||||
|
||||
for( String key in directRooms.keys) {
|
||||
if( key == directRoomId ) {
|
||||
DirectMessageRoom? room = directRooms[key];
|
||||
if( room != null) {
|
||||
printDirectMessageRoom(room, page);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void printChannel(ChatRoom room, [int page = 1]) {
|
||||
if( page < 1) {
|
||||
@ -897,6 +903,9 @@ class Store {
|
||||
|
||||
// shows the given channelId, where channelId is prefix-id or channel name as mentioned in room.name. returns full id of channel.
|
||||
String showChannel(String channelId, [int page = 1]) {
|
||||
if( channelId.length > 64 ) {
|
||||
return "";
|
||||
}
|
||||
|
||||
for( String key in chatRooms.keys) {
|
||||
if( key.substring(0, channelId.length) == channelId ) {
|
||||
@ -1173,28 +1182,33 @@ class Store {
|
||||
|
||||
void addMessageToChannel(String channelId, String messageId, Map<String, Tree> tempChildEventsMap, var chatRooms) {
|
||||
int newEventTime = (tempChildEventsMap[messageId]?.event.eventData.createdAt??0);
|
||||
if( gCheckEventId == messageId) {
|
||||
print("In addMessageToChannel: newEventTime= $newEventTime");
|
||||
//gDebug = 1;
|
||||
}
|
||||
|
||||
if( chatRooms.containsKey(channelId)) {
|
||||
ChatRoom? room = chatRooms[channelId];
|
||||
if( room != null ) {
|
||||
if( room.messageIds.isEmpty) {
|
||||
//if(gDebug> 0) print("room is empty. adding new message and returning. ");
|
||||
if(gDebug> 0 || gCheckEventId == messageId) print("room is empty. adding new message and returning. ");
|
||||
room.messageIds.add(messageId);
|
||||
return;
|
||||
}
|
||||
|
||||
if(gDebug> 0) print("room has ${room.messageIds.length} messages already. adding new one to it. ");
|
||||
if(gDebug> 0 || gCheckEventId == messageId) print("room has ${room.messageIds.length} messages already. adding new one to it. ");
|
||||
|
||||
for(int i = 0; i < room.messageIds.length; i++) {
|
||||
int eventTime = (tempChildEventsMap[room.messageIds[i]]?.event.eventData.createdAt??0);
|
||||
if( newEventTime < eventTime) {
|
||||
// shift current i and rest one to the right, and put event Time here
|
||||
if(gDebug> 0) print("In addMessageToChannel: inserted in middle to channel ${room.chatRoomId} ");
|
||||
if(gDebug> 0 || gCheckEventId == messageId )
|
||||
print("In addMessageToChannel: inserted event $messageId at position $i to channel ${room.chatRoomId} ");
|
||||
room.messageIds.insert(i, messageId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(gDebug> 0) print("In addMessageToChannel: added to channel ${room.chatRoomId} ");
|
||||
if(gDebug> 0 || gCheckEventId == messageId) print("In addMessageToChannel: added to channel ${room.chatRoomId} at end");
|
||||
|
||||
// insert at end
|
||||
room.messageIds.add(messageId);
|
||||
@ -1377,8 +1391,8 @@ Store getTree(Set<Event> events) {
|
||||
|
||||
// sort all participants by id; then create a large string with them together, thats the unique id for now
|
||||
String getDirectRoomId(EventData eventData) {
|
||||
|
||||
List<String> participantIds = [];
|
||||
String roomId = "";
|
||||
eventData.tags.forEach((tag) {
|
||||
if( tag.length < 2)
|
||||
return;
|
||||
@ -1391,5 +1405,11 @@ String getDirectRoomId(EventData eventData) {
|
||||
participantIds.sort();
|
||||
String uniqueId = "";
|
||||
participantIds.forEach((element) {uniqueId += element;});
|
||||
return uniqueId;
|
||||
|
||||
if( eventData.pubkey == userPublicKey) {
|
||||
return uniqueId;
|
||||
} else {
|
||||
return eventData.pubkey;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,3 +21,5 @@ dependencies:
|
||||
translator: ^0.1.7
|
||||
web_socket_channel: ^2.2.0
|
||||
logging: ^1.0.2
|
||||
kepler: ^1.0.3
|
||||
# secp256k1cipher: ^0.2.7
|
||||
|
Loading…
x
Reference in New Issue
Block a user