latest shown for only 6 hours

* notifications shown for minimum 24 hours
* other minor improvements related to qr code, tree ui in menu function,

* added :- with ln qr so qr is printed on next line, otherwise it wasn't due to some whitespace trim

* --width will override LN qr width change
This commit is contained in:
Vishal 2022-12-25 20:25:08 +05:30
parent 2d3533509e
commit 6e05556513
8 changed files with 98 additions and 61 deletions

View File

@ -82,7 +82,11 @@ usage: dart run bin/nostr_console.dart [OPTIONS]
-s, --disable-file When turned on, even the default file is not read from.
-t, --translate Translate some of the recent posts using Google translate site ( and not api). Google
is accessed for any translation request only if this flag is present, and not otherwise.
-l, --location The given value is added as a 'location' tag with every kind 1 post made
-l, --lnqr If set any LN invoices starting with LNBC will be printed as a QR code. Will set
width to 140, which can be reset if needed with the --width argument. Wider space is
needed for some qr codes.
-g, --location The given value is added as a 'location' tag with every kind 1 post made. Shortcut g for
geographic location.
-h, --help Print help/usage message and exit.
-v, --version Print version and exit.

View File

@ -16,7 +16,7 @@ const String pubkeyArg = "pubkey";
const String prikeyArg = "prikey";
const String lastdaysArg = "days";
const String relayArg = "relay";
const String requestArg = "request";
const String requestArg = "request"; // no abbreviation
const String helpArg = "help";
const String versionArg = "version";
const String alignArg = "align"; // can only be "left"
@ -29,7 +29,7 @@ const String translateArg = "translate";
const String colorArg = "color";
const String overWriteFlag = "overwrite";
const String locationArg = "location";
const String lnQrFlag = "qrln";
const String lnQrFlag = "lnqr";
Future<void> main(List<String> arguments) async {
@ -44,9 +44,9 @@ Future<void> main(List<String> arguments) async {
..addOption(colorArg, abbr:"c")
..addOption(difficultyArg, abbr:"y")
..addFlag(overWriteFlag, abbr:"e", defaultsTo: false)
..addOption(locationArg, abbr:"l")
..addOption(locationArg, abbr:"g")
..addFlag("debug")
..addFlag(lnQrFlag, abbr:"q", defaultsTo: false);
..addFlag(lnQrFlag, abbr:"l", defaultsTo: false);
try {
ArgResults argResults = parser.parse(arguments);
if( argResults[helpArg]) {
@ -142,13 +142,23 @@ Future<void> main(List<String> arguments) async {
}
}
printSet( gListRelayUrls1, "Primary relays that will be used: ", ",");
print("From among them, default relay: $defaultServerUrl");
//print("From among them, default relay: $defaultServerUrl");
if( argResults[lastdaysArg] != null) {
gNumLastDays = int.parse(argResults[lastdaysArg]);
print("Going to show posts for last $gNumLastDays days");
}
// lnqr will adjust width if needed; but it can be reset with --width because latter is processed afterwards
if( argResults[lnQrFlag]) {
gShowLnInvoicesAsQr = true;
if( gTextWidth < gMinWidthForLnQr) {
gTextWidth = gMinWidthForLnQr;
}
print("Going to show LN invoices as QR code");
}
// process --width argument
if( argResults[widthArg] != null) {
int tempTextWidth = int.parse(argResults[widthArg]);
if( tempTextWidth < gMinValidTextWidth ) {
@ -159,14 +169,6 @@ Future<void> main(List<String> arguments) async {
}
}
// lnqr will adjust width if needed
if( argResults[lnQrFlag] != null) {
gShowLnInvoicesAsQr = true;
if( gTextWidth < gMinWidthForLnQr) {
gTextWidth = gMinWidthForLnQr;
}
print("Going to show LN invoices as QR code");
}
try {
var terminalColumns = gDefaultTextWidth;
@ -303,7 +305,7 @@ Future<void> main(List<String> arguments) async {
Store node = getTree(initialEvents);
clearEvents();
if( gDebug > 0) stdout.write("Total events of kind 1 in created tree: ${node.count()} events\n");
if( gDebug > 0) stdout.write("Total events all kind in created tree: ${node.count()} events\n");
gStore = node;
mainMenuUi(node);
});
@ -320,15 +322,12 @@ Future<void> main(List<String> arguments) async {
// get event for user
if( userPublicKey!= "") {
//getIdAndMentionEvents(gListRelayUrls1, {userPublicKey}, limitPerSubscription, 0, getSecondsDaysAgo(limitSelfEvents), "#p", "authors");
//getIdAndMentionEvents(gListRelayUrls2, {userPublicKey}, limitPerSubscription, getSecondsDaysAgo(limitSelfEvents), getSecondsDaysAgo(limitSelfEvents), "#p", "authors");
getUserEvents(gListRelayUrls1, userPublicKey, limitPerSubscription, getSecondsDaysAgo(limitSelfEvents));
getMentionEvents(gListRelayUrls1, {userPublicKey}, limitPerSubscription, getSecondsDaysAgo(limitSelfEvents), "#p");
}
// get default users; remove user from default list if user exists in it. because theyv'e already been fetched.
//getMultiUserEvents(gListRelayUrls1, gDefaultFollows.difference({userPublicKey}), 4 * limitPerSubscription, getSecondsDaysAgo(limitOthersEvents));
Set<String> usersFetched = {userPublicKey};
stdout.write('Waiting for user posts to come in.....');
@ -418,10 +417,10 @@ Future<void> main(List<String> arguments) async {
//resetRelays();
relays = Relays({}, {}, {}); // reset relay value
String req = '["REQ","cn",{"limit":40000,"kinds":[0,1,3,4,5,6,7,40,41,42,104,140,141,142],"since":${getTimeSecondsAgo(2*3600).toString()}}]';
String req = '["REQ","latest_live_all",{"limit":40000,"kinds":[0,1,3,4,5,6,7,40,41,42,104,140,141,142],"since":${getTimeSecondsAgo(gSecsLatestLive).toString()}}]';
sendRequest(gListRelayUrls1, req);
// Creat tree from all events read form file
// Create tree from all events that's have yet been received/accumulated
Store node = getTree(initialEvents);
gStore = node;

View File

@ -294,7 +294,7 @@ void reAdjustAlignment() {
void printProfile(Store node, String profilePubkey) {
bool onlyUserPostAndLike (Tree t) => t.treeSelectorUserPostAndLike(profilePubkey);
node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), onlyUserPostAndLike);
node.printTree(0, DateTime.now().subtract(Duration(hours:gHoursDefaultPrint)), onlyUserPostAndLike);
// if contact list was found, get user's feed, and keep the contact list for later use
String authorName = getAuthorName(profilePubkey, 0);
@ -505,7 +505,7 @@ Future<void> otherOptionsMenuUi(Store node) async {
String clientName = $tempWords??"";
if( clientName != "") {
bool fromClient (Tree t) => t.treeSelectorClientName(clientName);
node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), fromClient); // search for last gNumLastDays only
node.printTree(0, DateTime.now().subtract(Duration(hours:gHoursDefaultPrint)), fromClient); // search for last gHoursDefaultPrint hours only
}
break;
@ -1236,13 +1236,13 @@ Future<void> socialMenuUi(Store node) async {
'Search word(s) or event id', // 7
'Follow new contact', // 8
'Show user profile', // 9
'Change number of days printed', // 10
'Change # of hours printed', // 10
'E(x)it to main menu'], // 11
"Social Network Menu");
switch(option) {
case 1:
node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), selectorTrees_all);
node.printTree(0, DateTime.now().subtract(Duration(hours:gHoursDefaultPrint)), selectorTrees_all);
break;
case 2:
@ -1284,7 +1284,8 @@ Future<void> socialMenuUi(Store node) async {
case 3:
clearScreen();
bool selectorTrees_userNotifications (Tree t) => t.treeSelectorRepliesAndLikes(userPublicKey);
Point numPrinted = node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), selectorTrees_userNotifications);
int notificationHours = gHoursDefaultPrint>24? gHoursDefaultPrint: 24; // minimum 24
Point numPrinted = node.printTree(0, DateTime.now().subtract(Duration(hours:notificationHours)), selectorTrees_userNotifications);
if( numPrinted.y > 0) {
print("Showed ${numPrinted.y.toInt()} notifications.\n");
} else {
@ -1293,29 +1294,29 @@ Future<void> socialMenuUi(Store node) async {
break;
case 4:
clearScreen();
Point numPrinted = node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), selectorTrees_selfPosts);
Point numPrinted = node.printTree(0, DateTime.now().subtract(Duration(hours:gHoursDefaultPrint)), selectorTrees_selfPosts);
if( numPrinted.x > 0) {
print("Showed ${numPrinted.x.toInt()} posts made by you in last $gNumLastDays days.\n");
print("Showed ${numPrinted.x.toInt()} posts made by you in last $gHoursDefaultPrint hours.\n");
} else {
print("No posts made by you in last $gNumLastDays days.");
print("No posts made by you in last $gHoursDefaultPrint hours.");
}
break;
case 5:
clearScreen();
Point numPrinted = node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), selectorTrees_userRepliesLikes);
Point numPrinted = node.printTree(0, DateTime.now().subtract(Duration(hours:gHoursDefaultPrint)), selectorTrees_userRepliesLikes);
if( numPrinted.x > 0) {
print("Showed ${numPrinted.x.toInt()} thread where you replied or liked in in last $gNumLastDays days.\n");
print("Showed ${numPrinted.x.toInt()} thread where you replied or liked in in last $gHoursDefaultPrint hours.\n");
} else {
print("No replies/likes made by you in last $gNumLastDays days.");
print("No replies/likes made by you in last $gHoursDefaultPrint hours.");
}
break;
case 6:
clearScreen();
Point numPrinted = node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), selectorTrees_followsPosts);
Point numPrinted = node.printTree(0, DateTime.now().subtract(Duration(hours:gHoursDefaultPrint)), selectorTrees_followsPosts);
if( numPrinted.x > 0) {
print("Showed ${numPrinted.x.toInt()} threads where your follows/freiends participated.\n");
} else {
print("No threads to show where your follows/friends participated in last $gNumLastDays days. To see some users to follow, check out https://nostr.io/stats or astral.ninja global feed.");
print("No threads to show where your follows/friends or other users participated in last $gHoursDefaultPrint hours.");
}
break;
case 7: // search word or event id
@ -1325,9 +1326,9 @@ Future<void> socialMenuUi(Store node) async {
String words = $tempWords??"";
if( words != "") {
bool onlyWords (Tree t) => t.treeSelectorHasWords(words.toLowerCase());
Point numPrinted = node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), onlyWords); // search for last gNumLastDays only
Point numPrinted = node.printTree(0, DateTime.now().subtract(Duration(hours:gHoursDefaultPrint)), onlyWords); // search for last default hours only
if( numPrinted.x.toInt() == 0) {
print("\nNot found in the last $gNumLastDays day(s). Try increasing the number of days printed, from social network options to search further back into history.\n");
print("\nNot found in the last $gHoursDefaultPrint hours. Try increasing the number of days printed, from social network options to search further back into history.\n");
}
} else printWarning("Blank word entered. Try again.");
break;
@ -1449,13 +1450,13 @@ Future<void> socialMenuUi(Store node) async {
case 10: // change number of days printed
clearScreen();
stdout.write("Enter number of days for which you want to see posts: ");
String? $tempNumDays = stdin.readLineSync();
String newNumDays = $tempNumDays??"";
stdout.write("Enter number of hours for which you want to see latest posts: ");
String? $tempHoursDefaultPrint = stdin.readLineSync();
String strHoursDefaultPrint = $tempHoursDefaultPrint??"";
try {
gNumLastDays = int.parse(newNumDays);
print("Changed number of days printed to $gNumLastDays");
gHoursDefaultPrint = int.parse(strHoursDefaultPrint);
print("Changed number of hours printed to $gHoursDefaultPrint");
} on FormatException catch (e) {
printWarning("Invalid input. Kindly try again.");
if( gDebug > 0) print(" ${e.message}");
@ -1480,7 +1481,7 @@ void showAllNotifications(Store node, [int x = 0, int y = 0]) {
Point numPrinted = Point(x, y);
bool hasNotifications (Tree t) => t.treeSelectorNotifications();
numPrinted += node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), hasNotifications);
numPrinted += node.printTree(0, DateTime.now().subtract(Duration(hours:gHoursDefaultPrint)), hasNotifications);
int numNotificationsPrinted = numPrinted.y.toInt();
bool showNotifications (ScrollableMessages room) => room.selectorNotifications();
@ -1525,7 +1526,8 @@ Future<void> mainMenuUi(Store node) async {
switch(option) {
case 1:
node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), selectorTrees_all);
node.printTree(0, DateTime.now().subtract(Duration(hours:gHoursDefaultPrint)), selectorTrees_all);
break;
case 2:

View File

@ -198,7 +198,7 @@ class Relays {
return;
}
},
onError: (err) { printWarning("Warning: Error in creating connection to $relayUrl. Kindly check your internet connection. Or maybe only this relay is down."); },
onError: (err) { if(gDebug > 0) printWarning("Warning: Error in creating connection to $relayUrl. Kindly check your internet connection. Or maybe only this relay is down."); },
onDone: () { if( gDebug > 0) print('Info: In onDone'); }
);
} on WebSocketException {

View File

@ -44,6 +44,10 @@ int gDefaultNumWaitSeconds = 12000; // is used in main()
const int gMaxAuthorsInOneRequest = 300; // number of author requests to send in one request
const int gMaxPtagsToGet = 100; // maximum number of p tags that are taken from the comments of feed ( the top most, most frequent)
const int gSecsLatestLive = 2 * 3600; // the lastst seconds for which to get the latest event in main
int gHoursDefaultPrint = 6; // print latest given hours only
// global counters of total events read or processed
int numFileEvents = 0, numFilePosts = 0, numUserPosts = 0, numFeedPosts = 0, numOtherPosts = 0;
@ -101,15 +105,15 @@ Set<String> gDefaultFollows = {
"c49d52a573366792b9a6e4851587c28042fb24fa5625c6d67b8c95c8751aca15", // hodlonaut
"1577e4599dd10c863498fe3c20bd82aafaf829a595ce83c5cf8ac3463531b09b", // yegorPetrov
"be1d89794bf92de5dd64c1e60f6a2c70c140abac9932418fee30c5c637fe9479", // walletofsatoshi
"3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24", // derek ross
"edcd20558f17d99327d841e4582f9b006331ac4010806efa020ef0d40078e6da", // Natalie Brunell
"eaf27aa104833bcd16f671488b01d65f6da30163b5848aea99677cc947dd00aa", // grubles
"b9003833fabff271d0782e030be61b7ec38ce7d45a1b9a869fbdb34b9e2d2000", // brockm
"51b826cccd92569a6582e20982fd883fccfa78ad03e0241f7abec1830d7a2565", // Jonas Schnelli
"92de68b21302fa2137b1cbba7259b8ba967b535a05c6d2b0847d9f35ff3cf56a", // Susie bdds
"c48e29f04b482cc01ca1f9ef8c86ef8318c059e0e9353235162f080f26e14c11", // walker
"a9b9525992a486aa16b3c1d3f9d3604bca08f3c15b712d70711b9aecd8c3dc44", // Alana
"b5db1aacc067a056350c4fcaaa0f445c8f2acbb3efc2079c51aaba1f35cd8465", // Nostrich
"6e1534f56fc9e937e06237c8ba4b5662bcacc4e1a3cfab9c16d89390bec4fca3", // Jesse Powell
"24e37c1e5b0c8ba8dde2754bcffc63b5b299f8064f8fb928bcf315b9c4965f3b", // lunaticoin
"4523be58d395b1b196a9b8c82b038b6895cb02b683d0c253a955068dba1facd0", // martii malmi
@ -127,7 +131,6 @@ Set<String> gDefaultFollows = {
"46fcbe3065eaf1ae7811465924e48923363ff3f526bd6f73d7c184b16bd8ce4d", // Giszmo
"8c0da4862130283ff9e67d889df264177a508974e2feb96de139804ea66d6168", // monlovesmango
"c5072866b41d6b88ab2ffee16ad7cb648f940867371a7808aaa94cf7d01f4188", // randymcmillan
"2183e94758481d0f124fbd93c56ccaa45e7e545ceeb8d52848f98253f497b975", // Brill
"00000000827ffaa94bfea288c3dfce4422c794fbb96625b6b31e9049f729d700", // cameri
"dd81a8bacbab0b5c3007d1672fb8301383b4e9583d431835985057223eb298a5", // plantimals
"1c6b3be353041dd9e09bb568a4a92344e240b39ef5eb390f5e9e821273f0ae6f", // johnonchain
@ -176,7 +179,7 @@ int gNameLenDisplayed = 12;
String gValidCheckMark = "✔️";
bool gShowLnInvoicesAsQr = false;
int gMinWidthForLnQr = 150;
const int gMinWidthForLnQr = 140;
// https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html#8-colors
@ -310,13 +313,17 @@ usage: $exename [OPTIONS]
-s, --disable-file When turned on, even the default filename is not read from.
-t, --translate Translate some of the recent posts using Google translate site ( and not api). Google
is accessed for any translation request only if this flag is present, and not otherwise.
-l, --location The given value is added as a 'location' tag with every kind 1 post made
-l, --lnqr Flag, if set any LN invoices starting with LNBC will be printed as a QR code. Will set
width to $gMinWidthForLnQr, which can be reset if needed with the --width argument. Wider
space is needed for some qr codes.
-g, --location <location> The given value is added as a 'location' tag with every kind 1 post made. g in shortcut
standing for geographic location.
-h, --help Print help/usage message and exit.
-v, --version Print version and exit.
UI Options
-a, --align <left> When "left" is given as option to this argument, then the text is aligned to left. By default
the posts or text is aligned to the center of the terminal.
UI Options
-a, --align <left> When "left" is given as option to this argument, then the text is aligned to left. By
default the posts or text is aligned to the center of the terminal.
-w, --width <width as num> This specifies how wide you want the text to be, in number of columns. Default is $gDefaultTextWidth.
Cant be less than $gMinValidTextWidth.
-m, --maxdepth <depth as num> The maximum depth to which the threads can be displayed. Minimum is $gMinimumDepthAllowed and
@ -324,12 +331,12 @@ usage: $exename [OPTIONS]
-c, --color <color> Color option can be green, cyan, white, black, red and blue.
Advanced
-y, --difficulty <number> The difficulty number in bits, only for kind 1 messages. Tne next larger number divisible by 4 is
taken as difficulty. Can't be more than 24 bits, because otherwise it typically takes too much
time. Minimum and default is 0, which means no difficulty.
-e, --overwrite Will over write the file with all the events that were read from file, and all newly received. Is
useful when the file has to be cleared of old unused events. A backup should be made just in case
of original file before invoking.
-y, --difficulty <number> The difficulty number in bits, only for kind 1 messages. Tne next larger number divisible
by 4 is taken as difficulty. Can't be more than 24 bits, because otherwise it typically
takes too much time. Minimum and default is 0, which means no difficulty.
-e, --overwrite Will over write the file with all the events that were read from file, and all newly
received. Is useful when the file has to be cleared of old unused events. A backup should
be made just in case of original file before invoking.
""";
const String helpAndAbout =

View File

@ -416,7 +416,7 @@ class Tree {
// sort children by time
if( children.length > 1) {
children.sort(sortTreeNewestReply);
children.sort(sortTreeByItsTime);
}
bool leftShifted = false;
@ -1579,8 +1579,16 @@ class Store {
numPrinted += printTopPost(topPosts[i], depth, newerThan);
}
int printedNumHours = DateTime.now().difference(newerThan).inHours;
String strTime = "";
if(printedNumHours > 24) {
strTime = "${printedNumHours ~/ 24} days";
} else {
strTime = "$printedNumHours hours";
}
if( numPrinted.x > 0) {
print("\nTotal threads printed: ${numPrinted.x} for last $gNumLastDays days.\n");
print("\nTotal threads printed: ${numPrinted.x} for last $strTime.");
}
return numPrinted;
@ -2498,6 +2506,23 @@ int sortTreeNewestReply(Tree a, Tree b) {
}
}
// sorter function that looks at the latest event in the whole tree including the/its children
int sortTreeByItsTime(Tree a, Tree b) {
int aTime = a.event.eventData.createdAt;
int bTime = b.event.eventData.createdAt;
if(aTime < bTime) {
return -1;
} else {
if( aTime == bTime) {
return 0;
} else {
return 1;
}
}
}
/*
* @function getTree Creates a Tree out of these received List of events.
* Will remove duplicate events( which should not ideally exists because we have a set),

View File

@ -321,7 +321,7 @@ String expandLNInvoices(String content) {
qrStr = getPubkeyAsQrString(lnInvoice, typeAndModule[0], typeAndModule[1], "");
//print(lnInvoice); print(qrStr);
content = content.substring(0, match.start) + "\n\n" + qrStr + "\n\n" + content.substring(match.end);
content = content.substring(0, match.start) + ":-\n\n" + qrStr + "\n\n" + content.substring(match.end);
}
return content;

View File

@ -9,7 +9,7 @@ homepage: https://github.com/vishalxl/nostr_console
# fixed URI exception for NIP05
# sorted lists printed in profile ( radixrat)
# sorted tree children - now posts get printed in sorted order
# --qrln print LNBC invoices as qr code
# --lnqr print LNBC invoices as qr code
#0.2.9
# improved fetching logic