#!perl use strict; use warnings; use autodie; use JSON qw(decode_json encode_json); use LWP::UserAgent qw(); use Path::Tiny qw(path); $| = 1; my $gitlab_group_path = $ENV{GITLAB_GROUP_PATH} or die "GITLAB_GROUP_PATH is not set"; my $gitlab_url = $ENV{GITLAB_URL} or die "GITLAB_URL is not set"; my $gitlab_token = $ENV{GITLAB_TOKEN} or die "GITLAB_TOKEN is not set"; my $slack_workspace = $ENV{SLACK_WORKSPACE} or die "SLACK_WORKSPACE is not set"; my $slack_logs_dir = $ENV{SLACK_LOGS_DIR} // q{}; my $gitlab_graphql_api = "${gitlab_url}/api/graphql"; die "Usage: $0 " if scalar @ARGV != 1; my $filter = qr/$ARGV[0]/; my %slack_emojis; my %gitlab_emojis; my $ua = LWP::UserAgent->new(timeout => 5); $ua->default_header('Authorization' => "Bearer $gitlab_token"); $ua->default_header('Content-Type' => 'application/json; charset=utf-8'); if (!$slack_logs_dir) { if ($^O eq "darwin") { my $username = $ENV{LOGNAME} || $ENV{USER} || getpwuid($<); $slack_logs_dir = "/Users/$username/Library/Application Support/Slack/logs/default"; } else { die "SLACK_LOGS_DIR is not set"; } } if (!path($slack_logs_dir)->exists or !path($slack_logs_dir)->is_dir) { die "Slack logs directory not found: $slack_logs_dir"; } foreach (path($slack_logs_dir)->children(qr/\.log$/)) { open my ($log_file), $_; foreach (<$log_file>) { if (m{fetch (https://emoji\.slack-edge\.com/$slack_workspace/([a-zA-Z-_0-9]+)\/\w+\.(png|gif|jpg))}gm) { $slack_emojis{$2} = $1; } } close $log_file; } { my $next_cursor = ""; my $has_next_page = 1; while($has_next_page) { my $content = encode_json({ query => qq{ { group(fullPath: "$gitlab_group_path") { customEmoji(first: 50, after: "$next_cursor") { nodes { id name url } pageInfo { endCursor hasNextPage } } } } } }); my $res = $ua->post( $gitlab_graphql_api, Content => $content ); die "failed" if $res->is_error or $res->code != 200; my $data = decode_json($res->decoded_content); $next_cursor = $data->{data}{group}{customEmoji}{pageInfo}{endCursor}; $has_next_page = $data->{data}{group}{customEmoji}{pageInfo}{hasNextPage}; foreach(@{$data->{data}{group}{customEmoji}{nodes}}) { $gitlab_emojis{$_->{name}} = { url => $_->{url}, id => $_->{id}, }; } } } foreach (sort keys %slack_emojis) { next if $_ !~ $filter; print "Emoji: $_\n"; if (exists $gitlab_emojis{$_}) { print " - already exists in GitLab\n"; if ($slack_emojis{$_} eq $gitlab_emojis{$_}{url}) { print " - skipping, URL is the same\n"; next; } my $content = encode_json({ query => qq{ mutation { destroyCustomEmoji(input: { id: "$gitlab_emojis{$_}{id}" }) { errors } } } }); my $res = $ua->post( $gitlab_graphql_api, Content => $content ); if ($res->is_error or $res->code != 200) { print " - failed to delete\n"; next; } my $data = decode_json($res->decoded_content); if ($data->{errors}) { print " - failed to delete\n"; next; } } my $content = encode_json({ query => qq{ mutation { createCustomEmoji(input: { groupPath: "$gitlab_group_path", name: "$_", url: "$slack_emojis{$_}" }) { errors } } } }); my $res = $ua->post( $gitlab_graphql_api, Content => $content ); if ($res->is_error or $res->code != 200) { print " - failed to create\n"; } else { my $data = decode_json($res->decoded_content); if ($data->{errors}) { print " - failed to create\n"; } else { print " - created\n"; } } }