Skip to content

Instantly share code, notes, and snippets.

@icelander
Created August 13, 2020 21:13
Show Gist options
  • Save icelander/13540e6916dbd58c80fbf883a773d57c to your computer and use it in GitHub Desktop.
Save icelander/13540e6916dbd58c80fbf883a773d57c to your computer and use it in GitHub Desktop.
members_to_csv.rb is a Ruby script that generates a CSV file containing the users who are members of a team or channel
#!/bin/ruby
require 'csv'
require 'yaml'
require 'httparty'
require 'uri'
# ## members_to_csv.rb
#
# ### About
#
# members_to_csv.rb is a Ruby script that generates a CSV file containing the
# users who are members of a team or channel
#
# ### File Format
#
# The file created will be named `team-name-YYYY-MM-DD.csv` or
# `team-name-channel-name-YYYY-MM-DD.csv` and will contain the following fields,
# repeated for each different team:
#
# - Team Name
# - Channel Name
# - First Name
# - Last Name
# - Username
# - Email Address
# - Date Channel Last Viewed
#
# ### Usage:
#
# **Dependencies:** This script requires that you install Ruby -
# https://www.ruby-lang.org/en/documentation/installation/ - and install the
# required gems:
#
# - csv
# - yaml
# - uri
# - httparty
#
# Once you have Ruby installed, install them with this command:
#
# gem install csv yaml uri httparty
#
#
# 1. Create a file named `conf.yaml` with this format:
#
# ```yaml
# server_name:
# url: https://<Mattermost Server URL>/ <- INCLUDE TRAILING SLASH
# login_id: <Mattermost admin username>
# auth_token: <Auth Token>
# ```
#
# OR
#
# ```yaml
# server_name:
# url: https://<Mattermost Server URL>/ <- INCLUDE TRAILING SLASH
# login_id: <Mattermost admin username>
# password: <Password>
# ```
#
# 2. Run it through Ruby: `ruby members_to_csv.rb team-name[:channel-name]`
#
# If you want to get all the users for a team, provide just the team name, e.g.
#
# ruby members_to_csv.rb team-name
#
# If you want a specific channel, include the channel name:
#
# ruby members_to_csv.rb team-name:channel-name
#
# CSV files are generated in the current working directory.
$config = YAML.load(
File.open('conf.yaml').read
)
class MattermostApi
include HTTParty
format :json
# UNCOMMENT NEXT LINE TO DEBUG REQUESTS
# debug_output $stdout
def initialize(config)
# Default Options
@options = {
headers: {
'Content-Type' => 'application/json',
'User-Agent' => 'Mattermost-HTTParty'
},
# TODO Make this more secure
verify: false
}
# check the config for mattermost_url
if ! (config.key?("url") && url_valid?(config['url']))
raise 'url is required in configuration'
end
@base_uri = config['url'] + 'api/v4/'
token = nil
if config.key?('auth_token')
token = config['auth_token']
else
# Use password login
if (config.key?('login_id') && config.key?('password'))
token = get_login_token(config['login_id'], config['password'])
end
end
if token.nil?
raise 'token not set, check for token or login_id and password'
end
@options[:headers]['Authorization'] = "Bearer #{token}"
@options[:body] = nil
end
def url_valid?(url)
url = URI.parse(url) rescue false
end
def get_team_members(team_name)
puts "Getting channels for team: #{team_name}"
team = get_url("/teams/name/#{team_name}")
# Return Values
# - "id": "string",
# - "create_at": 0,
# - "update_at": 0,
# - "delete_at": 0,
# - "display_name": "string",
# - "name": "string",
# - "description": "string",
# - "email": "string",
# - "type": "string",
# - "allowed_domains": "string",
# - "invite_id": "string",
# - "allow_open_invite": true
return false if team.nil?
channels = get_url("/channels")
# Return value:
# - "id": "string",
# - "create_at": 0,
# - "update_at": 0,
# - "delete_at": 0,
# - "team_id": "string",
# - "type": "string",
# - "display_name": "string",
# - "name": "string",
# - "header": "string",
# - "purpose": "string",
# - "last_post_at": 0,
# - "total_msg_count": 0,
# - "extra_update_at": 0,
# - "creator_id": "string"
output = []
channels.each_with_index do |channel, index|
if channel['team_id'] == team['id']
output = output + get_channel_members(team_name, channel['name'])
end
end
return output
end
def get_channel_members(team_name, channel_name)
puts " - Getting members of channel: #{channel_name}"
channel = get_url("/teams/name/#{team_name}/channels/name/#{channel_name}")
members = get_url("/channels/#{channel['id']}/members")
# Return Values:
# - "channel_id": "string",
# - "user_id": "string",
# - "roles": "string",
# - "last_viewed_at": 0,
# - "msg_count": 0,
# - "mention_count": 0,
# - "notify_props":
# {},
# "last_update_at": 0
# }
output = []
csv_fields = [
"Team Name",
"Channel Name",
"First Name",
"Last Name",
"Username",
"Email Address",
"Date Channel Last Viewed"
]
output << csv_fields
members.each_with_index do |member, index|
# - Team Name
# - Channel Name
# - First Name
# - Last Name
# - Username
# - Email Address
# - Date Channel Last Viewed
# Build the CSV Row
user = get_url("/users/#{member['user_id']}")
last_viewed = "never"
if member['last_viewed_at'] != 0
last_viewed = Date.strptime((member['last_viewed_at']/1000).to_s, '%s').to_s
end
csv_row = []
csv_row = [team_name,
channel_name,
user['first_name'],
user['last_name'],
user['username'],
user['email'],
last_viewed
]
output << csv_row
end
return output
end
def get_all_users
get_url('users')
end
def get_url(url)
# TODO: Make this handle pagination
JSON.parse(self.class.get("#{@base_uri}#{url}", @options).to_s)
end
end
$mm = MattermostApi.new($config['test_server'])
# If it contains a colon, get just that channel
if ARGV[0].include? ":"
team_name, channel_name = ARGV[0].split(':')
filename = "./#{team_name}-#{channel_name}-#{Time.now.strftime("%Y-%m-%d")}.csv"
puts "Outputting channel members of #{team_name}:#{channel_name} to #{filename}"
output = $mm.get_channel_members(team_name, channel_name)
else # get all channels for that team
team_name = ARGV[0]
filename = "./#{team_name}-#{Time.now.strftime("%Y-%m-%d")}.csv"
puts "Outputting team members of #{team_name} to #{filename}"
output = $mm.get_team_members(ARGV[0])
end
CSV.open(filename, "wb") do |csv|
output.each do |o|
csv << o
end
end
puts "File output complete"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment