improved ln qr generation. added --qrln flag

This commit is contained in:
Vishal
2022-12-25 13:51:28 +05:30
parent 85515771d5
commit d79b14ebee
7 changed files with 127 additions and 30 deletions

View File

@@ -29,10 +29,11 @@ const String translateArg = "translate";
const String colorArg = "color";
const String overWriteFlag = "overwrite";
const String locationArg = "location";
const String lnQrFlag = "qrln";
Future<void> main(List<String> arguments) async {
final parser = ArgParser()..addOption(requestArg, abbr: 'q') ..addOption(pubkeyArg, abbr:"p")..addOption(prikeyArg, abbr:"k")
final parser = ArgParser()..addOption(requestArg) ..addOption(pubkeyArg, abbr:"p")..addOption(prikeyArg, abbr:"k")
..addOption(lastdaysArg, abbr:"d") ..addOption(relayArg, abbr:"r")
..addFlag(helpArg, abbr:"h", defaultsTo: false)
..addFlag(versionArg, abbr:"v", defaultsTo: false)
@@ -44,7 +45,8 @@ Future<void> main(List<String> arguments) async {
..addOption(difficultyArg, abbr:"y")
..addFlag(overWriteFlag, abbr:"e", defaultsTo: false)
..addOption(locationArg, abbr:"l")
..addFlag("debug");
..addFlag("debug")
..addFlag(lnQrFlag, abbr:"q", defaultsTo: false);
try {
ArgResults argResults = parser.parse(arguments);
if( argResults[helpArg]) {
@@ -146,6 +148,7 @@ Future<void> main(List<String> arguments) async {
gNumLastDays = int.parse(argResults[lastdaysArg]);
print("Going to show posts for last $gNumLastDays days");
}
if( argResults[widthArg] != null) {
int tempTextWidth = int.parse(argResults[widthArg]);
if( tempTextWidth < gMinValidTextWidth ) {
@@ -155,8 +158,17 @@ Future<void> main(List<String> arguments) async {
print("Going to use $gTextWidth columns for text on screen.");
}
}
try {
// 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;
if( stdout.hasTerminal )
terminalColumns = stdout.terminalColumns;
@@ -330,7 +342,7 @@ Future<void> main(List<String> arguments) async {
stdout.write("...done\n");//received $numUserPosts new posts made by the user\n");
Set<String> userEvents = getOnlyUserEvents(initialEvents, userPublicKey);
print('Total events fetched till now: ${initialEvents.length}. Total user events fetched: ${userEvents.length}');
//print('Total events fetched till now: ${initialEvents.length}. Total user events fetched: ${userEvents.length}');
// get events from channels of user; gets public as well as encrypted channels
Set<String> userChannels = getUserChannels(initialEvents, userPublicKey);

View File

@@ -384,7 +384,9 @@ class EventData {
case 1:
case 42:
evaluatedContent = expandMentions(content, tempChildEventsMap);
//evaluatedContent = expandLNInvoices(evaluatedContent);
if( gShowLnInvoicesAsQr) {
evaluatedContent = expandLNInvoices(evaluatedContent);
}
if( translator != null && gTranslate && !evaluatedContent.isEnglish()) {
if( gDebug > 0) print("found that this comment is non-English: $evaluatedContent");

View File

@@ -175,6 +175,10 @@ int gMenuWidth = 36;
int gNameLenDisplayed = 12;
String gValidCheckMark = "✔️";
bool gShowLnInvoicesAsQr = false;
int gMinWidthForLnQr = 150;
// https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html#8-colors
// Color related settings
const String defaultTextColor = "green";
@@ -297,7 +301,7 @@ usage: $exename [OPTIONS]
-r, --relay <relay urls> The comma separated relay urls that are used as main relays. If given, these are used
rather than the default relays.
-d, --days <N as num> The latest number of days for which events are shown. Default is $gDefaultNumLastDays.
-q, --request <REQ string> This request is sent verbatim to the default relay. It can be used to recieve all events
--request <REQ string> This request is sent verbatim to the default relay. It can be used to recieve all events
from a relay. If not provided, then events for default or given user are shown.
-f, --file <filename> Read from given file, if it is present, and at the end of the program execution, write
to it all the events (including the ones read, and any new received). Even if not given,

View File

@@ -414,6 +414,11 @@ class Tree {
event.printEvent(depth, topPost);
// sort children by time
if( children.length > 1) {
children.sort(sortTreeNewestReply);
}
bool leftShifted = false;
for( int i = 0; i < children.length; i++) {

View File

@@ -3,6 +3,9 @@ import 'package:qr/qr.dart';
enum enumRoomType { kind4, kind40, kind140, RoomLocationTag, RoomTTag}
int gMinLnInvoiceLength = 20; // TODO put real value
int gMaxStrLenForQrCode = 600; // in bytes, maximum acceptable length of string that is converted to qr code. for lnbc1 invoices
String getPostKindFrom(enumRoomType eType) {
switch (eType) {
case enumRoomType.kind4:
@@ -250,44 +253,73 @@ int isInRange( int n, List<List<int>> ranges ) {
return 0;
}
List<int> getTypeAndModule(String str) {
int type = 14, module = 73;
// https://jpgraph.net/download/manuals/chunkhtml/ch27.html
// both go from 1 to 20 inclusive. index is type.
List<int> qrMaxDataBits = [152, 272, 440, 640, 864, 1088, 1248, 1552, 1856, 2192, 2592, 2960, 3424, 3688, 4184, 4712, 5176, 5768, 6360, 6888];
List<int> qrModules = [21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97];
if( str.length > 3688 /~ 8) {
type = 16;
module = 81;
// return type and module as entries in a list
List<int>? getTypeAndModule(String str) {
if( qrMaxDataBits.length != qrModules.length) {
//print("ret null 1");
return null;
}
// 5 for padding which it seems to need, otherwise it gives error like 'QrInputTooLongException: Input too long. 2212 > 2192' for a str which is exactly 2192
int strLen = str.length + 5;
for( int i = 0; i < qrModules.length; i++) {
//print("checking $strLen, ${strLen * 8} and ${qrMaxDataBits[i]}");
if( strLen * 8 <= qrMaxDataBits[i]) {
return [i+1, qrModules[i]];
}
}
if( str.length > 4712 /~ 8) {
type = 18;
module = 89;
}
return [type, module];
//print("ret null 2 strLen = $strLen");
return null;
}
int gMaxStrLenForQrCode = 600; // in bytes, maximum acceptable length of string that is converted to qr code. for lnbc1 invoices
bool sanityChecked(String lnInvoice) {
//for( int i = 0 ; i < lnInvoice.length; i++) {
//}
if( lnInvoice.length < gMinLnInvoiceLength)
return false;
if( lnInvoice.substring(0, 4).toLowerCase() != "lnbc")
return false;
return true;
}
String expandLNInvoices(String content) {
String regexp1 = '(lnbc1[a-zA-Z0-9]+)';
String regexp1 = '(lnbc[a-zA-Z0-9]+)';
RegExp httpRegExp = RegExp(regexp1);
for( var match in httpRegExp.allMatches(content) ) {
for( var match in httpRegExp.allMatches(content.toLowerCase()) ) {
String lnInvoice = content.substring(match.start, match.end);
if( !sanityChecked(lnInvoice)) {
continue;
}
if( lnInvoice.length > gMaxStrLenForQrCode) {
continue;
}
//print(lnInvoice);
String qrStr = "";
List<int> typeAndModule = getTypeAndModule(lnInvoice);
//print(typeAndModule);
//print("\nqr code len: ${lnInvoice.length}");
List<int>? typeAndModule = getTypeAndModule(lnInvoice);
if( typeAndModule == null) {
continue;
}
//print("\nqr code len: ${lnInvoice.length}"); print(typeAndModule); print("--");
qrStr = getPubkeyAsQrString(lnInvoice, typeAndModule[0], typeAndModule[1], "");
//print(qrStr);
//print(lnInvoice); print(qrStr);
content = content.substring(0, match.start) + "\n\n" + qrStr + "\n\n" + content.substring(match.end);
}
@@ -296,6 +328,7 @@ String expandLNInvoices(String content) {
}
// https://www.sproutqr.com/blog/qr-code-types
// https://jpgraph.net/download/manuals/chunkhtml/ch27.html
// default 4 and 33 work for pubkey
String getPubkeyAsQrString(String str, [int typeNumber = 4, moduleCount = 33, String leftPadding = " "]) {
String output = "";

View File

@@ -1,12 +1,15 @@
name: nostr_console
description: A multi-platform nostr client built for terminal/console
version: 0.3.0-testing
version: 0.3.0-beta
homepage: https://github.com/vishalxl/nostr_console
# added check marks
# 0.3.0
# added check marks; added more default users
# changed fetch logic: after fetching all friends contacts etc, then reset the relays, and fetched ALL the events in last 2 hours. but not closing connection right now of old relays.
# 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
#0.2.9
# improved fetching logic

View File

@@ -262,7 +262,7 @@ String expectedResult =
expect(3046, node.getNumMessagesInChannel('25e5c82273a271cb1a840d0060391a0bf4965cafeb029d5ab55350b418953fbb'),
reason:'verify a public channel has correct number of messages');
String qrCodeResult1 =
String pubkeyQrCodeResult1 =
""" █▀▀▀▀▀█ ██▄▄▀ ▄▄ █ ▄▀ █▀▀▀▀▀█
█ ███ █ █▄█ ██▄ ▄▄ ██▀▀ █ ███ █
█ ▀▀▀ █ ▀ ▀ █▀▄█▄███ ██ █ ▀▀▀ █
@@ -282,7 +282,45 @@ String expectedResult =
▀▀▀▀▀▀▀ ▀▀▀ ▀▀ ▀ ▀▀ ▀ ▀ \n""";
String profilePubkey1 = "add06b88bd78c5cbb2cd990e873adfba3eaf8e0217d3208be2be770eb506d430";
expect (qrCodeResult1, getPubkeyAsQrString(profilePubkey1), reason: "testing qr code function");
expect (pubkeyQrCodeResult1, getPubkeyAsQrString(profilePubkey1), reason: "testing qr code function");
String lnQrCodeResult1 = """\n\n█▀▀▀▀▀█ █▀▄█▄▄█▀ █ ▄▄ ▀▄ ▀ ▀█▀ ▀▄▀ ██ █▀ ▄█▀███ █▀ ▀▄ █▀▀▀▀▀█
█ ███ █ ▄ ▀ ▄▀█▄▄▄▀▀ ▀▀▄▄██▄▄██▄▄█▄▄ ▄▀▄▀ ▀ █████▄▀ █ ███ █
█ ▀▀▀ █ ▀▀█▄█▄▄▀▀▀█▀ ▀ █▄█▄██▀▀▀█ ▄▀▀ ███ █▄▄ ▄▀▀▄█▄ ▀ █ ▀▀▀ █
▀▀▀▀▀▀▀ █ ▀▄█▄▀ ▀ █ █ █ ▀ ▀ ▀▄█ ▀ █ ▀ ▀ █ ▀▄▀ ▀ ▀ █▄█▄▀ ▀ ▀▀▀▀▀▀▀
▄█▀ ██▀█▄▄ █ ▄██▀▀█▄▀▀ ▄ ▄ ██ █▀█▀█▀ █ ▀▀██▄▄█ █▄▀██▀██ ▀█ ▀▄█▀
█▄ ▀██▀ █▀ ▄▄▀▄█▀█▀▀ ▀██▄ █▄█ ▄█▄██ ▀▄█▀ ▀█▀▀▀ █ ▄█ ▄▄█▀█▀▄▄▄▄█
█ ▄ ▄▀ ▄ ▄▀▀█▄▄▀█▀ █▀▀ █▀██▀▀▄▄▄▄▄▄▄▀▀██▄█▀▀█▀█▄██ █ ▄ █ █▀ █▄▄
█▄ ▀▀▀▀██▀▄█ ▄██▀█ █▄█▄▄▄▀ ▀▀▄▀ ▀▀███ ▄█▄▄▄▄▄ ▄ ▄▄ ▀▀▀ ▀▄
▀ ▄ ▄▀██▀▄▀ ▀█ ▀█ ▄▄▄█▀ ▄▀▄ ▄▄ ▄█ ▄▀▄▀▀▀▄▄ ▄▀▄▀▀▄▀▀▄ ▄█ ▄██
▄█▄▀█▄▀ ██▀ █▀█▄▀█▀▄█▄▀▀███▀█▀▀█▀▀▄█▄▄▀▀█▀▀███▀▄███ ▀ ▀▀▀▀▀ ▀█▀▀█
▀ ▀▀▀▀ █ █▀█ ▄▄▄█▀ ▀ █ ▄▀ ▀█▄█▄▄▄█ ▄▀▄█▄ █▀▄▄▀ ▀ ▄█▄▀▄▀▀█▀▄
▄ ▄█▄▄▀▀▀▀ █▀▄▀▀ █▀▀▀▄ ▄▀ █▄▄▀█▄▀▀▀▀ ▀▀▀▄██ ▀█▄▀█▄█ ▄▀▄▀█▀ █
█▀▄▀▀ ▀▄▄ ▄▄█▄▀▄▄ ▄ ▄▄▄▀ ▄ ▄ █ ▄ ▀▀ █ ▄ █ ▄▄▀ ▄▀ ▄ █▄ ▄█▄
▄ ▀▀█▄▀▀██▀ ▀█ ▀ ▄▀▀▀█▀ ▄█▄▀▀▄████▀▄██▄ ▄██▀█▀▀ █ ▀▄ ▀▄▀▀▀ ▄▀
█▄██ █▀▀ ▄▄▄ █▀ █▄▄▀ ▄█▄▄▀ ▄█ ██▄ ▄▀▄█▀▄█ █▄▄▄▄ ▄█▀▀▀ █ ▄▄ ▀▄▀▄▀█
▀▀▄▀█▀▀▀█ ▄▄▄▄▄▄ █▀▄▄ ▀ ▄ ▄▄█▀▀▀█▀▄█▀█▄ ▄▄▄ ▄█▄█▀▀ █▀▀▀██▀▀█
██▀ █ ▀ █ ▄█ ▄██ ▄▀ ▀▀ █ ██ █ ▀ █▀ █▄ ██▄█ ▄▀ ▄▄▄▄▀▄▀█ ▀ ██▄ ▀
█▄▀▀█▀▀█▀ ▀ ▄▀ █▄ ▀▄█▀ ▄▄ ▀▀▀▀▀██ █▀▀██ ▀ ▀█▀█▀ ██ ▀█▀▀█ ▄ ▀
▀▄▄ ▀█▀█▀ ▀██▄▄█▀▀███▄▀█▀▄██▀▀█▀▀▀▄█▀▄ █▀▀█▀█▀▀███▀▀▀▀▀▀█▀▄███ ▀█
▀█▄▀█▄▀ █ ▄▀▀▄▀▄▄█ ▄ █ █ ▀█ ▄▄▄ ▀▄ ▀ ▀█▄ ▄▄▄ ▀ █▀ ▀▄▄▄ █▄█▀
█ ▄▄▄ ▀▄▀█▄▀█▀▀█ █ ▄█▄▄▀▀▀▀█▄▄█ ▀ █▀▀▀██ ▄█▄▀▀▄██▀▄█ ▄▀▄▀█▄▀█ ▀█
██▄▀▀█▀▄ ▄ █ ▀█ ▄█▄ ▄██ █ ▄ ▄ ▄▄ ▀█ ▄█ ▀▀ ██▄ ▄█▄ ▀▀
█▄█▄██▀▀ ▀▀▄█▀ █▀▀██ ▄█▄▀█▄██▀▄█▄▀█▄▀ ▀█▀██▄ █▄▀▄▄▀▀▀██▄ ▀▄█ ██▀
█▄▀▄ ▀▀▀ ▄▀▄ ▀ ▀ ▄ ▄▀ ▀██▀▄ █ ▄ █▄▀██▀▄ ▄▄ █▀ ▀▄ █▄▀▄▄ █▀ █ ██ █
▄ ▄ █▀█▀▀▄█▀▄▀▀▀███▀ █▀█▄ █▀ ███▀▀▀ ██████▀▀█▀██▀▀█████▄▀▀▀████
▀▀▄▀▀▄▀ █▄ ▄█ ▀▄ ▄ ▄▀ ▀ ██▄ █▄ ▄▄▄█▀▄▀ ▄▄▄▄▀█▄█ ▀█ ▀ ██▄
▀█▄▄▄█▀▄█ ▀▀█▀█▀▄▀█ █▀▄█▀▀ ▀▄█▀▄█ █▀█ ▀▀ ▄ ▀ ▀█▀▀█ ▀▄ ▀▀▄██▀█▀▄
▄ ▀█ ▀▀ ▀ ▀▄ ▄▀ ▀ █▄ ▀ ▀█▄ ▄ █▄▄▄ ▄ █ █▀▄ ▀▄▄▄▄
▀▀ ▀ ▀▀▀ ██▄ █▀ ▀▀ █ ▀▄ ██ ██▀▀▀█ ▀ █▄█▀▀▀▀▄ ▀ ▀ ▄▄ █▀▀▀██
█▀▀▀▀▀█ █ ▀ ██▄▄▄ ▀▄▄██▄█▄ █ ▀ ██▄ ▀▀ █▀▄█▀ ██ ██▀▄█▄█ ▀ █ █ ▀
█ ███ █ ▀▄█▀█▄▀█▀ █▀▀ ▀▀ ▄▀██▀▀███ █ ▄ ▀▄▄▄█▄▄ ▄█ ▄█▀█▀▀▀▀█▀▀
█ ▀▀▀ █ █▀██▄▄▄▄▄ ▄█ ▄█ ▄ ██ █▄▄█ █▄▄▄▄▄█ █▀ █▄ ▀ ▀▄▄█ ▄▀▄▄
▀▀▀▀▀▀▀ ▀ ▀ ▀ ▀▀▀ ▀ ▀ ▀ ▀▀ ▀ ▀ ▀ ▀▀ ▀ ▀ ▀▀▀ ▀ ▀ ▀▀
\n\n""";
String lnInvoice1 = "lnbc30n1p3689h4sp54ft7dn46clu4h8lyey2zj2hfvp07e2ekcrmceeq4gxmw9ml2pwuspp5zfup7rmneu47f34qznatwcmkexdkl78ppntms9y8vgj75cyzvh5qdq2f38xy6t5wvxqyjw5qcqpjrzjqvhxqvs0ulx0mf5gp6x2vw047capck4pxqnsjv0gg8a4zaegej6gxzadnsqqj3cqqqqqqqqqqqqqqqqqyg9qyysgqv5cg4cly6sr2q4n0vkfcgmgxd5egdrztt8pn4003thqzr8sn5e8swdxw4g75jr233hyr2p655xgwh98jh3pkn3kranjkg0ysrwze44qpqmeq35";
expect (expandLNInvoices(lnInvoice1),lnQrCodeResult1, reason: "testing ln qr code function");
});