about summary refs log tree commit diff stats
path: root/lib/Lacerta/CLI.rakumod
blob: d6b80bca6719589feb4d182cea89860d92bc5b7b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use Terminal::Table;
use Terminal::Spinners;

# Parses the WhatsApp logs.
grammar WhatsApp {
    token TOP {
        || <Text>
        || <Notice>
    }

    token Notice { <date> ', ' <time> ' - ' <message> }
    token Text { <date> ', ' <time> ' - ' <name> ': ' <message> }

    token date { (\d+) ** 3 % '/' }
    token time { (\d+) ** 2 % ':' }
    token name { [[\w|\s]+ | '+' \d+ [\d+|\s]+] }
    token number { '+' \d+ [\d+|\s]+ }
    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;

        put "\n" ~ "Parsed {@logs.elems} logs in " ~ (now - ENTER now) ~ "s";
    }

    {
        my @data;
        my @given-data;
        push @data, <Name Messages Words Deleted Media MostActiveHour Left>;
        push @given-data, <Name FucksGiven>;
        for @logs.grep(*<Text>).map(*<Text>).map(*<name>.Str).unique -> $name {
            with @logs.grep(*<Text>).map(*<Text>).grep(*<name>.Str 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,
                    )
                );
            }
        }
        put "Generated data in " ~ (now - ENTER now) ~ "s";
        print-table(@data, :style<single>);
        print-table(@given-data, :style<single>);
    }
}