diff options
-rw-r--r-- | lib/Lacerta/CLI.rakumod | 113 |
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); } |