--- /dev/null
+#! /usr/bin/perl
+use strict;
+use warnings;
+no warnings qw(once);
+use Crypt::JWT;
+use JSON::XS;
+use LWP::UserAgent;
+use DBI;
+use POSIX;
+use Time::HiRes;
+use IO::Select;
+use Unicode::Collate;
+use IO::Socket::SSL;
+binmode STDOUT, ':utf8';
+binmode STDERR, ':utf8';
+use utf8;
+
+require '../include/config.pm';
+
+my $global_ctx = IO::Socket::SSL::SSL_Context->new(
+ SSL_session_cache_size => 100, # Probably overkill.
+);
+IO::Socket::SSL::set_default_context($global_ctx);
+
+sub get_slack_name {
+ my ($ua, $userid) = @_;
+ my $req = HTTP::Request->new('GET', 'https://slack.com/api/users.info?user=' . $userid, [
+ 'Authorization' => 'Bearer ' . $config::slack_oauth_token
+ ]);
+ my $start = [Time::HiRes::gettimeofday];
+ my $response = $ua->request($req);
+ log_timing($start, '/users.info');
+ die $response->status_line if !$response->is_success;
+
+ my $user_json = JSON::XS::decode_json($response->decoded_content);
+ die "Something went wrong: " . $response->decoded_content if (!defined($user_json) || !$user_json->{'ok'});
+
+ return $user_json->{'user'}{'real_name'};
+}
+
+sub db_connect {
+ my $dbh = DBI->connect("dbi:Pg:dbname=$config::dbname;host=127.0.0.1", $config::dbuser, $config::dbpass, {RaiseError => 1})
+ or warn "Could not connect to Postgres: " . DBI->errstr;
+ if (!defined($dbh)) {
+ return undef;
+ }
+ $dbh->{AutoCommit} = 0;
+ $dbh->do('LISTEN skvupdate') or return undef;
+ return $dbh;
+}
+
+my $channel = $ARGV[1] // 'C06C34L2R6G';
+my $ts = $ARGV[2] // '1712686401.430939';
+
+my $dbh = db_connect() or die;
+my $ua = LWP::UserAgent->new(agent => 'SKVidarLang/1.0', keep_alive => 50);
+$dbh->do('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE');
+
+my $req = HTTP::Request->new('GET', 'https://slack.com/api/reactions.get?channel=' . $channel . '×tamp=' . $ts . '&full=true', [
+ 'Authorization' => 'Bearer ' . $config::slack_oauth_token
+]);
+my $start = [Time::HiRes::gettimeofday];
+my $response = $ua->request($req);
+die $response->status_line if !$response->is_success;
+
+my $user_json = JSON::XS::decode_json($response->decoded_content);
+die "Something went wrong: " . $response->decoded_content if (!defined($user_json) || !$user_json->{'ok'});
+
+#print $response->decoded_content, "\n";
+
+my $q = $dbh->prepare('SELECT COUNT(*) AS num FROM current_reactions WHERE channel=? AND ts=? AND userid=? AND reaction=?');
+for my $reaction (@{$user_json->{'message'}{'reactions'}}) {
+ my $name = $reaction->{'name'};
+ for my $user (@{$reaction->{'users'}}) {
+ $q->execute($channel, $ts, $user, $name);
+ my $ref = $q->fetchrow_hashref;
+ if ($ref->{'num'} == 0) {
+ $dbh->do('INSERT INTO reaction_log (userid, channel, ts, event_type, event_ts, reaction) VALUES (?, ?, ?, ?, ?, ?)',
+ undef, $user, $channel, $ts, 'reaction_added', time, $name);
+ print "$name $user\n";
+ }
+ }
+}
+
+$dbh->commit;
+$dbh->do('NOTIFY skvupdate');
+$dbh->commit;
# for each user; earlier ones are irrelevant and don't count. But it
# doesn't deduplicate across reactions. Meh.)
sub create_reaction_log {
- my ($dbh, $invitation_ts, $slack_userid_to_real_name, $slack_userid_to_slack_name) = @_;
+ my ($dbh, $channel, $invitation_ts, $interval, $slack_userid_to_real_name, $slack_userid_to_slack_name) = @_;
- my $q = $dbh->prepare('select userid,event_type,reaction,to_char(event_ts,\'YYYY-mm-dd HH24:MI\') as event_ts from ( select distinct on (channel,ts,userid,reaction) userid,event_type,reaction,timestamptz \'1970-01-01 utc\' + event_ts::float * interval \'1 second\' as event_ts from reaction_log where channel=? and ts=? and reaction in (\'heart\',\'open_mouth\',\'blue_heart\',\'orange_heart\') order by channel,ts,userid,reaction,event_ts desc ) t1 where event_ts > current_timestamp - interval \'8 hours\' order by event_ts desc limit 50');
- $q->execute($config::invitation_channel, $invitation_ts);
+ my $q = $dbh->prepare('select userid,event_type,reaction,to_char(event_ts,\'YYYY-mm-dd HH24:MI\') as event_ts from ( select distinct on (channel,ts,userid,reaction) userid,event_type,reaction,timestamptz \'1970-01-01 utc\' + event_ts::float * interval \'1 second\' as event_ts from reaction_log where channel=? and ts=? and reaction in (\'heart\',\'open_mouth\',\'blue_heart\',\'orange_heart\') order by channel,ts,userid,reaction,event_ts desc ) t1 where event_ts > current_timestamp - ?::interval order by event_ts desc limit 50');
+ $q->execute($channel, $invitation_ts, $interval);
my @recent_changes = ();
while (my $ref = $q->fetchrow_hashref) {
my $msg = $ref->{'event_ts'};
}
}
}
- # LOCAL CHANGE FOR HKS 2024
- # Piece together HKS users.
- $q = $dbh->prepare('SELECT userid, TO_CHAR(last_added, \'YYYY-mm-dd HH24:MI\') AS last_added FROM current_reactions_with_ts WHERE channel=? and ts=? and reaction=? ORDER BY current_reactions_with_ts.last_added;');
- $q->execute('C06C34L2R6G', '1712686401.430939', 'heart'); # #hks-2024-05-04
- my @hks_runners = ();
- while (my $ref = $q->fetchrow_hashref) {
- my $userid = $ref->{'userid'};
- if (!exists($slack_userid_to_real_name{$userid}) && !exists($slack_userid_to_slack_name{$userid})) {
- my $slack_name = get_slack_name($ua, $userid);
- my $write_row = $cur_row++;
- push @slack_mapping_updates, {
- range => "Slack-mapping!A$write_row:A$write_row",
- values => [ [ $userid ]]
- };
- push @slack_mapping_updates, {
- range => "Slack-mapping!B$write_row:B$write_row",
- values => [ [ $slack_name ]]
- };
- $slack_userid_to_slack_name{$userid} = $slack_name;
- }
- my $name = $slack_userid_to_real_name{$userid} // $slack_userid_to_slack_name{$userid} // $userid;
- push @hks_runners, {
- values => [
- { userEnteredValue => { stringValue => $name } },
- { userEnteredValue => { stringValue => $ref->{'last_added'} } },
- ]
- };
- }
- push @hks_runners, { values => [{ userEnteredValue => { stringValue => '' } }, { userEnteredValue => { stringValue => '' } }] };
- push @hks_runners, { values => [{ userEnteredValue => { stringValue => '' } }, { userEnteredValue => { stringValue => '' } }] };
- push @hks_runners, { values => [{ userEnteredValue => { stringValue => '' } }, { userEnteredValue => { stringValue => '' } }] };
- # END LOCAL CHANGE FOR HKS 2024
if (scalar @slack_mapping_updates > 0) {
my $update = {
valueInputOption => 'USER_ENTERED',
}
}
- my @recent_changes = create_reaction_log($dbh, $invitation_ts, \%slack_userid_to_real_name, \%slack_userid_to_slack_name);
+ my @recent_changes = create_reaction_log($dbh, $config::invitation_channel, $invitation_ts, '8 hours', \%slack_userid_to_real_name, \%slack_userid_to_slack_name);
push @yellow_updates, {
updateCells => {
rows => \@recent_changes,
fields => 'userEnteredValue.stringValue',
range => {
sheetId => $config::log_tab_id,
- startRowIndex => 4,
- endRowIndex => 4 + scalar @recent_changes,
+ startRowIndex => 3,
+ endRowIndex => 3 + scalar @recent_changes,
startColumnIndex => 0,
endColumnIndex => 1
}
}
};
- # LOCAL CHANGE FOR HKS 2024
- push @yellow_updates, {
- updateCells => {
- rows => \@hks_runners,
- fields => 'userEnteredValue.stringValue',
- range => {
- sheetId => $config::hks_tab_id,
- startRowIndex => 1,
- endRowIndex => 1 + scalar @hks_runners,
- startColumnIndex => 0,
- endColumnIndex => 2
- }
- }
- };
- # END LOCAL CHANGE FOR HKS 2024
-
# Push the final set of updates (including the log).
skv_log("Ferdig.");
push @yellow_updates, serialize_skv_log_to_sheet();