]> git.sesse.net Git - skvidarsync/blobdiff - bin/sync.pl
Factor out %seen_names computation into a function.
[skvidarsync] / bin / sync.pl
index f0dc9a34e9bf14ea15e2ed2e129f80684c576fdd..0585df3bb186e6948ddd229251e45e21d2c125e2 100644 (file)
@@ -12,8 +12,8 @@ binmode STDERR, ':utf8';
 use utf8;
 
 # TODO:
-# - support non-fixed sheets
 # - detect moves between groups
+# - better daemon behavior
 
 require '../include/config.pm';
 
@@ -54,7 +54,7 @@ sub get_spreadsheet_name {
        my $cell = shift;
        my $name = $cell->{'userEnteredValue'}{'stringValue'};
        return undef if (!defined($name));
-       return undef if ($name =~ /^G[1-4]\.[1-4]/);
+       return undef if ($name =~ /^G[1-4]\.[1-5]/);
        $name =~ s/šŸ†•//;
        $name =~ s/\(.*\)//g;
        $name =~ s/\[.*\]//g;
@@ -137,6 +137,48 @@ sub sheet_batch_update {
        die $response->decoded_content if !$response->is_success;
 }
 
+sub get_spreadsheet_with_title {
+       my ($ua, $token, $wanted_sheet_title) = @_;
+
+       # See if we have any spreadsheets that match this title.
+       my $response = $ua->get('https://sheets.googleapis.com/v4/spreadsheets/' . $config::sheet_id . '?key=' . $config::gsheets_api_key . '&fields=sheets/properties',
+               Authorization => 'Bearer ' . $token
+       );
+       my $sheets_json = JSON::XS::decode_json($response->decoded_content);
+       my ($tab_name, $tab_id);
+       for my $sheet (@{$sheets_json->{'sheets'}}) {
+               my $title = $sheet->{'properties'}{'title'};
+               my $sheet_id = $sheet->{'properties'}{'sheetId'};
+               if ($title =~ /\Q$wanted_sheet_title\E/) {
+                       # skv_log("Synkroniserer ($config::invitation_channel, $invitation_ts) mot arket ā€œ$titleā€ (fane-ID $sheet_id).");
+                       return ($title, $sheet_id);
+               }
+       }
+       return (undef, undef);
+}
+
+# Make a mapping of lowercase name -> list of [canonical name, row number, column number]
+sub find_where_each_name_is {
+       my $json = shift;
+
+       my %seen_names = ();
+       my $rows = $json->{'sheets'}[0]{'data'}[0]{'rowData'};
+       my $rowno = 4;
+       for my $row (@$rows) {
+               my $colno = 0;
+               for my $val (@{$row->{'values'}}) {
+                       my $name = get_spreadsheet_name($val);
+                       if (defined($name)) {
+                               push @{$seen_names{lc $name}}, [$name, $rowno, $colno];
+                       }
+                       ++$colno;
+               }
+               ++$rowno;
+       }
+
+       return %seen_names;
+}
+
 skv_log("Siste sync startet: " . POSIX::ctime(time));
 
 # Initialize the handles we need for communication.
@@ -154,22 +196,7 @@ my $invitation_ts = $linkref->{'ts'};
 my $wanted_sheet_title = $linkref->{'sheet_title'};
 die "Could not get newest sheet title" if (!defined($wanted_sheet_title));
 
-# See if we have any spreadsheets that match this title.
-my $response = $ua->get('https://sheets.googleapis.com/v4/spreadsheets/' . $config::sheet_id . '?key=' . $config::gsheets_api_key . '&fields=sheets/properties',
-       Authorization => 'Bearer ' . $token
-);
-my $sheets_json = JSON::XS::decode_json($response->decoded_content);
-my ($tab_name, $tab_id);
-for my $sheet (@{$sheets_json->{'sheets'}}) {
-       my $title = $sheet->{'properties'}{'title'};
-       my $sheet_id = $sheet->{'properties'}{'sheetId'};
-       if ($title =~ /\Q$wanted_sheet_title\E/) {
-               # skv_log("Synkroniserer ($config::invitation_channel, $invitation_ts) mot arket ā€œ$titleā€ (fane-ID $sheet_id).");
-               $tab_name = $title;
-               $tab_id = $sheet_id;
-               last;
-       }
-}
+my ($tab_name, $tab_id) = get_spreadsheet_with_title($ua, $token, $wanted_sheet_title);
 if (!defined($tab_name)) {
        skv_log("Fant ikke noen fane med ā€œ$wanted_sheet_titleā€ i navnet; kan ikke synkronisere.\n");
        sheet_batch_update($ua, $token, [ serialize_skv_log_to_sheet() ]);
@@ -185,33 +212,19 @@ while (my $ref = $q->fetchrow_hashref) {
 }
 
 # Get the list of all people in the sheet (we're going to need them soon anyway).
-$response = $ua->get('https://sheets.googleapis.com/v4/spreadsheets/' . $config::sheet_id . '?key=' . $config::gsheets_api_key . '&ranges=' . $tab_name . '!A9:Z5000&fields=sheets/data/rowData/values/userEnteredValue',
+my $response = $ua->get('https://sheets.googleapis.com/v4/spreadsheets/' . $config::sheet_id . '?key=' . $config::gsheets_api_key . '&ranges=' . $tab_name . '!A4:Z5000&fields=sheets/data/rowData/values/userEnteredValue',
        Authorization => 'Bearer ' . $token
 );
 my $main_sheet_json = JSON::XS::decode_json($response->decoded_content);
 
-# Duplicate detection
-my %seen_names = ();
-{
-       my $main_sheet_rows = $main_sheet_json->{'sheets'}[0]{'data'}[0]{'rowData'};
-       my $rowno = 9;
-       for my $row (@$main_sheet_rows) {
-               my $colno = 0;
-               for my $val (@{$row->{'values'}}) {
-                       my $name = get_spreadsheet_name($val);
-                       if (defined($name)) {
-                               push @{$seen_names{lc $name}}, [$name, $rowno, $colno];
-                       }
-                       ++$colno;
-               }
-               ++$rowno;
-       }
-       for my $name (sort keys %seen_names) {
-               my $seen = $seen_names{$name};
-               if (scalar @$seen >= 2) {
-                       my $exemplar = $seen->[0][0];
-                       skv_log("Duplikat: $exemplar (" . format_cell_names_for_seen($seen) . ")");
-               }
+my %seen_names = find_where_each_name_is($main_sheet_json);
+
+# Find duplicates.
+for my $name (sort keys %seen_names) {
+       my $seen = $seen_names{$name};
+       if (scalar @$seen >= 2) {
+               my $exemplar = $seen->[0][0];
+               skv_log("Duplikat: $exemplar (" . format_cell_names_for_seen($seen) . ")");
        }
 }
 
@@ -326,6 +339,7 @@ for my $userid (@attending_userids) {
 
        # See if we can find them in the spreadsheet.
        if (!exists($seen_names{lc $real_name})) {
+               # TODO: Perhaps move this logic further down, for consistency?
                skv_log("$slack_name ($userid) er pĆ„meldt pĆ„ Slack, og er mappet til $real_name, men var ikke i noen gruppe.");
        } else {
                my $seen = $seen_names{lc $real_name};
@@ -368,20 +382,25 @@ for my $real_name (keys %want_names) {
 }
 for my $real_name (keys %have_names) {
        next if (exists($want_names{$real_name}));
-       skv_log("Fjerner at $real_name skal pĆ„ trening.");
-       push @diffs, [
-               $real_name,
-               {
-                       backgroundColor => {
-                               red => 1,
-                               green => 1,
-                               blue => 1,
-                               alpha => 0
+       if (!exists($seen_names{lc $real_name})) {
+               # TODO: This can somehow come if we try to add someone who's not in the sheet, too?
+               skv_log("Ƙnsket Ć„ fjerne at $real_name skulle pĆ„ trening, men de var ikke i regnearket lenger.");
+       } else {
+               skv_log("Fjerner at $real_name skal pĆ„ trening.");
+               push @diffs, [
+                       $real_name,
+                       {
+                               backgroundColor => {
+                                       red => 1,
+                                       green => 1,
+                                       blue => 1,
+                                       alpha => 0
+                               }
                        }
-               }
-       ];
-       $dbh->do('DELETE FROM applied WHERE channel=? AND ts=? AND name=?', undef,
-               $config::invitation_channel, $invitation_ts, $real_name);
+               ];
+               $dbh->do('DELETE FROM applied WHERE channel=? AND ts=? AND name=?', undef,
+                       $config::invitation_channel, $invitation_ts, $real_name);
+       }
 }
 
 my @yellow_updates = ();
@@ -391,42 +410,27 @@ if (scalar @diffs > 0) {
                my $real_name = $diff->[0];
 
                # See if we can find them in the spreadsheet.
-               # FIXME use seen_names
-               my $rowno = 8;  # zero-indexed
-               my $found = 0;
-               for my $row (@$main_sheet_rows) {
-                       my $colno = 0;
-                       for my $val (@{$row->{'values'}}) {
-                               my $name = get_spreadsheet_name($val);
-                               if (defined($name) && $real_name eq $name) {
-                                       push @yellow_updates, {
-                                               updateCells => {
-                                                       rows => [{
-                                                               values => [{
-                                                                       userEnteredFormat => $diff->[1]
-                                                               }]
-                                                       }],
-                                                       fields => 'userEnteredFormat.backgroundColor',
-                                                       range => {
-                                                               sheetId => $tab_id,
-                                                               startRowIndex => $rowno,
-                                                               endRowIndex => $rowno + 1,
-                                                               startColumnIndex => $colno,
-                                                               endColumnIndex => $colno + 1
-                                                       }
-                                               }
-                                       };
-                                       $found = 1;
+               my $seen = $seen_names{lc $real_name};
+               die if (!defined($seen) || scalar @$seen > 1);
+               my $rowno = $seen->[0][1];
+               my $colno = $seen->[0][2];
+               push @yellow_updates, {
+                       updateCells => {
+                               rows => [{
+                                       values => [{
+                                               userEnteredFormat => $diff->[1]
+                                       }]
+                               }],
+                               fields => 'userEnteredFormat.backgroundColor',
+                               range => {
+                                       sheetId => $tab_id,
+                                       startRowIndex => $rowno,
+                                       endRowIndex => $rowno + 1,
+                                       startColumnIndex => $colno,
+                                       endColumnIndex => $colno + 1
                                }
-                               ++$colno;
                        }
-                       ++$rowno;
-               }
-
-               if ($found) {
-               } else {
-                       skv_log("Ƙnsket Ć„ fjerne at $real_name skulle pĆ„ trening, men de var ikke i regnearket lenger.");
-               }
+               };
        }
 }