# slack_profile.pl
#
# Get user profile information from the Slack API.
#
# Note:
# Before using this script, a Slack API token must be added:
#
# /set slack_profile_token TOKEN
#
# Tokens can be created here: https://api.slack.com/docs/oauth-test-tokens
#
# Usage:
#
# /swhois nick
# /swhois @nick
#
#
# Copyright (c) 2016 Teddy Wing
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
use strict;
use 5.010;
use JSON;
use HTTP::Tiny;
use Mozilla::CA;
use Storable;
use URI;
use vars qw($VERSION %IRSSI);
use Irssi;
$VERSION = '1.00';
%IRSSI = {
authors => 'Teddy Wing',
contact => 'irssi@teddywing.com',
name => 'Slack Profile',
description => 'Update and retrieve user profile information from Slack.',
license => 'GPL',
};
my @users_list;
sub help {
my ($args) = @_;
return unless $args =~ /^swhois\s*$/;
my $help = <]
%9Description:%9
Displays WHOIS-style profile information from Slack for the given nick. If
no nick argument is provided, the current nick is used.
%9Examples:%9
/SWHOIS
/SWHOIS farnsworth
/SWHOIS \@farnsworth
HELP
Irssi::print($help, MSGLEVEL_CLIENTCRAP);
Irssi::signal_stop();
}
sub users_list_cache {
Irssi::get_irssi_dir() . '/scripts/slack_profile-users.list.plstore';
}
sub slack_api {
my $token = Irssi::settings_get_str('slack_profile_token');
die 'Requires a Slack API token. Generate one from ' .
'https://api.slack.com/docs/oauth-test-tokens. ' .
'Set it with `/set slack_profile_token TOKEN`.' if !$token;
my ($method, $args) = @_;
$args ||= {};
$args->{'token'} = $token;
my $url = URI->new("https://slack.com/api/$method");
$url->query_form($args);
my $http = HTTP::Tiny->new(
default_headers => {
'content-type' => 'application/json',
},
verify_SSL => 1,
);
my $resp = $http->get($url);
if ($resp->{'success'}) {
my $payload = decode_json($resp->{'content'});
if ($payload->{'ok'}) {
return $payload;
}
else {
Irssi::print("Error from the Slack API: $payload->{'error'}");
}
}
else {
Irssi::print("Error calling the Slack API: ($resp->{'status'}) $resp->{'reason'} | $resp->{'content'}");
}
}
sub fetch_users_list {
Irssi::print('Fetching users list from Slack. This could take a while...');
my $resp = slack_api('users.list') or
die 'Unable to retrieve users from the Slack API';
@users_list = @{$resp->{'members'}};
store \@users_list, users_list_cache;
}
# Re-fetch the users list for the most up-to-date information
sub sync {
fetch_users_list();
Irssi::print('Done.');
}
sub fetch_user_profile {
my ($user) = @_;
my $resp = slack_api('users.profile.get', {
user => $user->{'id'},
include_labels => 1
});
return $resp->{'profile'};
}
sub fetch_user_presence {
my ($user) = @_;
my $resp = slack_api('users.getPresence', {
user => $user->{'id'}
});
return $resp->{'presence'};
}
sub underscorize {
my ($string) = @_;
my $result = lc $string;
$result =~ s/ /_/g;
$result =~ s/[^a-z_]//g;
return $result;
}
sub update_user_profile {
my ($key, $value) = @_;
my $user = find_user($server->{'nick'});
my @profile_fields = qw(first_name last_name email phone skype title);
# If $key is a custom field, find the custom field's id and use
# that as the key instead.
unless ($key ~~ @profile_fields) {
# Find key in custom field labels
for my $custom_field (keys %{$user->{'fields'}}) {
if (underscorize($user->{'fields'}->{$custom_field}->{'label'})
eq $key) {
$key = $custom_field;
last;
}
}
}
my $resp = slack_api('users.profile.set', {
user => $user->{'id'},
name => $key,
value => $value,
});
}
sub cmd_set {
my ($data) = @_;
my ($key, $value) = split /\s+/, $data, 2;
update_user_profile($key, $value);
}
sub find_user {
my ($username) = @_;
if (!@users_list) {
if (!-s users_list_cache) {
fetch_users_list();
}
@users_list = retrieve(users_list_cache);
}
for my $user (@{@users_list[0]}) {
if ($user->{'name'} eq $username) {
return $user;
}
}
}
sub print_whois {
my ($user) = @_;
sub maybe_print_field {
my ($name, $value) = @_;
if ($value) {
Irssi::print(" $name : $value");
}
}
my $bot = '';
if ($user->{'is_bot'}) {
$bot = ' (bot)';
}
Irssi::print($user->{'name'} . $bot);
maybe_print_field('name ', $user->{'real_name'});
maybe_print_field('title', $user->{'profile'}->{'title'});
maybe_print_field('email', $user->{'profile'}->{'email'});
maybe_print_field('phone', $user->{'profile'}->{'phone'});
maybe_print_field('skype', $user->{'profile'}->{'skype'});
maybe_print_field('tz ', $user->{'tz_label'});
foreach my $key (keys %{$user->{'fields'}}) {
my $label = $user->{'fields'}->{$key}->{'label'};
my $value = $user->{'fields'}->{$key}->{'value'};
maybe_print_field($label, $value);
}
maybe_print_field('status', $user->{'presence'});
Irssi::print('End of SWHOIS');
}
sub swhois {
my ($username, $server, $window_item) = @_;
if (!$username) {
if (!$server || !$server->{connected}) {
Irssi::print("Not connected to server");
return;
}
$username = $server->{'nick'};
}
# If $username starts with @, strip it
$username =~ s/^@//;
if (my $user = find_user($username)) {
my $profile = fetch_user_profile($user);
$user->{'fields'} = $profile->{'fields'};
my $presence = fetch_user_presence($user);
$user->{'presence'} = $presence;
print_whois($user);
}
}
Irssi::command_bind('swhois', 'swhois');
Irssi::command_bind('slack_profile_sync', 'sync');
Irssi::command_bind('slack_profile_set', 'cmd_set');
Irssi::command_bind('help', 'help');
Irssi::settings_add_str('slack_profile', 'slack_profile_token', '');