aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndinus <andinus@nand.sh>2021-07-29 19:54:30 +0530
committerAndinus <andinus@nand.sh>2021-07-29 19:54:30 +0530
commitc8ab90bf8dcba5fe44a04fdcf121c57a4944f27d (patch)
tree0e0dc5ac6ccda6f66c53bd2fc1b972c126995826
parent26bdd23908890052271aace2db77980d7e27c354 (diff)
downloadlacerta-c8ab90bf8dcba5fe44a04fdcf121c57a4944f27d.tar.gz
Add latest implementation
- Switched to Text::Table::Simple. - Faster and simpler than Terminal::Table. - Uses Promises/race to process data.
-rw-r--r--lib/Lacerta/CLI.rakumod113
1 files changed, 62 insertions, 51 deletions
diff --git a/lib/Lacerta/CLI.rakumod b/lib/Lacerta/CLI.rakumod
index d6b80bc..3ce42b0 100644
--- a/lib/Lacerta/CLI.rakumod
+++ b/lib/Lacerta/CLI.rakumod
@@ -1,12 +1,15 @@
-use Terminal::Table;
use Terminal::Spinners;
+use Text::Table::Simple;
-# Parses the WhatsApp logs.
+#| parses WhatsApp export
+unit sub MAIN (
+ Str $input where *.IO.f = "input", #= input log file to parse
+ Str $profile-name = "Andinus", #= your WhatsApp profile name
+);
+
+#| Parses the WhatsApp logs.
grammar WhatsApp {
- token TOP {
- || <Text>
- || <Notice>
- }
+ token TOP { <Text> || <Notice> }
token Notice { <date> ', ' <time> ' - ' <message> }
token Text { <date> ', ' <time> ' - ' <name> ': ' <message> }
@@ -18,61 +21,69 @@ grammar WhatsApp {
token message { .* }
}
-#| parses WhatsApp export
-sub MAIN (
- Str $profile-name = "Andinus", #= WhatsApp profile name
- Str $input where *.IO.f = "input", #= input log file to parse
-
-) {
- my WhatsApp @logs;
- {
- my $bar = Bar.new: :type<equals>;
- $bar.show: 0;
-
- my Int $count = 0;
- my Int $total = $input.IO.lines.elems; # Roughly the number of messages.
- my Int $interval = $total div 40; # Interval for update.
-
- @logs = gather for $input.IO.lines -> $line {
- if WhatsApp.parse($line) -> $m { take $m }
- $bar.show: $count / $total * 100 if $count++ %% $interval;
- }
- $bar.show: 100;
+my WhatsApp @logs;
- put "\n" ~ "Parsed {@logs.elems} logs in " ~ (now - ENTER now) ~ "s";
+{
+ Spinner.new(:type<bounce2>).await: Promise.start: {
+ @logs = $input.IO.lines.race.map({WhatsApp.parse($_)}).grep(so *);
}
+ put "Parsed {@logs.elems} logs in " ~ (now - ENTER now) ~ "s";
+}
+
+{
+ my List @data;
+ my List @given-data;
+ my List @most-spoken-data;
+ my Int $no-of-spoken = 8;
- {
- my @data;
- my @given-data;
- push @data, <Name Messages Words Deleted Media MostActiveHour Left>;
- push @given-data, <Name FucksGiven>;
+ Spinner.new(:type<bounce>).await: Promise.start: {
+ my Promise @promises;
for @logs.grep(*<Text>).map(*<Text>).map(*<name>.Str).unique -> $name {
- with @logs.grep(*<Text>).map(*<Text>).grep(*<name>.Str eq $name) {
+ next if $name eq "ERROR";
+ push @promises, start with @logs.grep(*<Text>).map(*<Text>).grep(*<name> eq $name) {
@data.push(
(
$name,
- .elems.Str,
- .map(*<message>.words).sum.Str,
- .grep(*<message> eq "You deleted this message"|"This message was deleted").elems.Str,
- .grep(*<message> eq "<Media omitted>").elems.Str,
- .map(*<time>[0][0].Int).Bag.max(*.values).key.Str,
- $name eq $profile-name
- ?? @logs.grep(*<Notice>).grep(*<Notice><message> eq "You left").elems.Str
- !! @logs.grep(*<Notice>).grep(*<Notice><message> eq "{$name} left").elems.Str,
- )
- );
-
- @given-data.push(
- (
- $name,
- .grep(*<message>.lc.contains("fuck")).elems.Str,
+ .elems,
+ .map(*<message>.words).sum,
+ .grep(*<message> eq ($name eq $profile-name
+ ?? "You deleted this message"
+ !! "This message was deleted")).elems,
+ .grep(*<message> eq "<Media omitted>").elems,
+ .map(*<time>[0][0].Int).Bag.max(*.values).key,
+ @logs.grep(*<Notice>).grep(
+ *<Notice><message>
+ eq ($name eq $profile-name ?? "You left" !! "$name left")
+ ).elems,
)
);
+ with .map(*<message>).map(*.lc).cache {
+ @given-data.push(
+ (
+ $name,
+ .grep(*.contains: "fuck").elems,
+ )
+ );
+ @most-spoken-data.push(
+ (
+ $name,
+ .grep(* ne "<media omitted>")
+ .grep(* ne ($name eq $profile-name
+ ?? "you deleted this message"
+ !! "this message was deleted")
+ ).map(*.words).Bag.grep(*.key.chars >= 4)
+ .sort(*.values).reverse.map({"{$_.key} ({$_.value})"}).head($no-of-spoken).Slip,
+ )
+ );
+ }
}
}
- put "Generated data in " ~ (now - ENTER now) ~ "s";
- print-table(@data, :style<single>);
- print-table(@given-data, :style<single>);
+ await @promises;
}
+ put "Generated data in " ~ (now - ENTER now) ~ "s" ~ "\n";
+
+ my List %options = headers => (corner_marker => "*", bottom_border => "-");
+ .say for lol2table(<Name Messages Words Deleted Media ActiveHour Left>, @data, |%options);
+ .say for lol2table(<Name FucksGiven>, @given-data, |%options);
+ .say for lol2table((|<Name MostSpoken-#1>, |("#" X~ (2..$no-of-spoken))), @most-spoken-data, |%options);
}