[Python Patterns] Get Slack users from a channel

Fun times working with the Slack API

Sometimes you need to export the users in a particular Slack channel for 'business reasons'.  This script will help you.

You need to get an API token for your workspace, and the channel ID from the channel's link.  After that this will push out a nifty little CSV for you to do you bidding with.

At some point I'd like to refactor with Async, but this one works now.

import argparse
import requests
import os
import sys
import csv

# Get your Slack API token and drop it into a ENV Var
# export SLACK_TOKEN="xoxb-my_token"
SLACK_TOKEN = os.getenv('SLACK_TOKEN')

# Example command:
# python get_slack_users.py -c CABCD123456 -n My_Cool_Channel
#
# Get the channel ID by opening a link to a channel in a web browser
# Example:  https://workspace.slack.com/messages/CABCD123456 <--
#
# Set the name of the file output with the -n argument


def get_user_info(user_id):
    """ Get User email from Slack API """
    url = 'https://slack.com/api/users.info'
    querystring = {
      'token': SLACK_TOKEN,
      'user': user_id
    }
    payload = ''
    response = requests.get(
        url,
        data=payload,
        params=querystring
    )

    data = response.json()
    # Check for bots, then return real users
    if data['user']['is_bot'] is False:
        return data['user']['profile']['email']
    else:
        return 'is_bot@example.com'


def get_channel_users(channel):
    """ Get channel user ids for channel members """
    # Slack holds users as IDs in the API, 
    # So we need to get the users, then run get_user_info()

    # To get their email
    url = 'https://slack.com/api/channels.info'
    querystring = {
      'token': SLACK_TOKEN,
      'channel': channel
    }
    payload = ''
    response = requests.get(
        url,
        data=payload,
        params=querystring
    )

    data = response.json()
    # print(data)
    return data['channel']['members']


def main(**kwargs):
    """ Take the entered channel get the members,
    then output to CSV """
    channel_id = kwargs['channel']
    channel_name = kwargs['channel_name']
    user_emails = []

    # TODO make this faster with async/await
    user_ids = get_channel_users(channel_id)
    for uid in user_ids:
        user = get_user_info(uid)
        user_emails.append(user)

    print(f'There are {len(user_emails)} users in {channel_name}')

    # We export a CSV 
    with open(f'{channel_name}-slack-users.csv', 'w') as f:
        writer = csv.writer(f)
        count = 0
        for x in user_emails:
            if count == 0:
                writer.writerow(['Email'])
                count += 1
            else:
                writer.writerow([x])
                count += 1
    # We can return the user email array to be user in other scripts later
    return user_emails


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '-c', 
        dest='channel',
        help='Enter the slack channel ID', 
        required=True
    )
    parser.add_argument(
        '-n',
        dest='channel_name',
        help='Enter name for your output file', 
        required=False
    )

    args = parser.parse_args()

    # Convert the argparse.Namespace to a dictionary: vars(args)
    arg_dict = vars(args)
    # pass dictionary to main
    main(**arg_dict)
    sys.exit(0)

My blog posts tagged with "Python Patterns" are designed to be a quick look reference for some Python code snippets I use a lot.  They are written to be a quick starting point for future projects so I do not need to type as much.