Created
August 9, 2013 23:26
-
-
Save roseleaf/6198165 to your computer and use it in GitHub Desktop.
This script solves the complex problem of setting all phone numbers on "real" user profiles to direct_line, while disabling direct lines on all "dummy" profiles that have the same number. working around the issue of direct lines being unique, and of each user being required to have at least one valid "identity" (such as a direct_line phone numbe…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This script solves the complex problem of setting all phone numbers on | |
# "real" user profiles to direct_line, while disabling direct lines on all | |
# "dummy" profiles that have the same number. working around the issue of | |
# direct lines being unique, and of each user being required to have at least | |
# one valid "identity" (such as a direct_line phone number or an email address) | |
# by: 1) finding all users who do not have profiles but who do have phone | |
# numbers and setting their emails to dummy values associated with those | |
# numbers in order to un-set the "direct_line" property on their numbers. | |
# 2) setting aside all users that do have profiles and setting their numbers | |
# to direct_line. | |
# ASSUMPTION: the account does not use Twitter/Google/Facebook user auth. Modify | |
# the criteria for setting of the user_profile flag on ln. 105 if this is not the case. | |
# PREPARATION: the acount's API limit should be raised by setting it to 'import mode' | |
# prior to running this script to minimize http induced exceptions | |
# This script is to be run in your terminal/command line shell. | |
# cd into this folder, and type "ruby enable_direct_lines.rb > out.txt" to run. | |
require 'open-uri' | |
require 'httparty' | |
require 'thread' | |
# Pool's been done http://burgestrand.se/code/ruby-thread-pool/ | |
class Pool | |
def initialize(size) | |
@size = size | |
@jobs = Queue.new | |
@pool = Array.new(@size) do |i| | |
Thread.new do | |
Thread.current[:id] = i | |
catch(:exit) do | |
loop do | |
job, args = @jobs.pop | |
job.call(*args) | |
end | |
end | |
end | |
end | |
end | |
def schedule(*args, &block) | |
@jobs << [block, args] | |
end | |
def shutdown | |
@size.times do | |
schedule { throw :exit } | |
end | |
@pool.map(&:join) | |
end | |
end | |
class PhoneSetter | |
include HTTParty | |
# un-comment to enable http output : | |
# debug_output $stdout | |
base_uri '' | |
attr_accessor :auth, :options | |
def initialize(u, p) | |
@auth = { :username => u + '/token', :password => p } | |
@options = {} | |
end | |
MAX_ATTEMPTS = 4 | |
def get_users() | |
@options.merge!({ basic_auth: @auth }) | |
allUsers = [] | |
userBatch = self.class.get("/users.json", options) | |
pageCount = 0 | |
while userBatch.count > 0 | |
userBatch = self.class.get("/users.json?page=#{pageCount}", @options) | |
allUsers.concat userBatch | |
pageCount += 1 | |
end | |
puts "+++++++++" | |
puts allUsers.count | |
puts "+++++++++" | |
divide_processes(allUsers) | |
end | |
def divide_processes(allUsers) | |
users_with_profiles = [] | |
p = Pool.new(5) | |
allUsers.each_with_index do |user, i| | |
num_attempts = 0 | |
p.schedule do | |
begin | |
if user.class != Hash | |
user = user.parsed_response | |
end | |
user_id = user['id'] | |
user_phone = user['phone'] | |
user_email = user['email'] | |
if user.has_key? 'profile_flag' | |
puts "updating user profile #{user_id} with #{user_phone}" | |
update_phone( user_id, user_phone, 1) | |
elsif user_phone | |
if user_email | |
if !user_email.include? "email.com" | |
user["profile_flag"] = true | |
puts "found user with profile, #{user}" | |
users_with_profiles << user | |
puts "right now uwp is a #{users_with_profiles.class}" | |
end | |
else | |
puts "found user #{user_id} with no profile. updating email." | |
update_email( user_id, user_phone) | |
end | |
end | |
rescue | |
puts "Exception Found:" | |
puts $!, $@ | |
if num_attempts <= MAX_ATTEMPTS | |
sleep(60) | |
puts "retrying now..." | |
retry | |
else | |
raise | |
end | |
rescue Exception | |
puts $!, $@ | |
end | |
end | |
end | |
at_exit do | |
p.shutdown | |
puts "divide_processes has completed an iteration." | |
puts "users with profiles: #{users_with_profiles.count} which is a #{users_with_profiles.class}" | |
if users_with_profiles.count > 0 | |
divide_processes( users_with_profiles ) | |
end | |
end | |
end | |
def update_email( user_id, phone_number) | |
email_options = { body: { identity: { type: "email", value: "#{phone_number}@email.com", primary: true }}, basic_auth: @auth, headers: { 'ContentType' => 'application/json'} } | |
self.class.post("/api/v2/users/#{user_id}/identities.json", email_options) | |
update_phone( user_id, phone_number, 0 ) | |
end | |
def update_phone( user_id, user_phone, val) | |
user_options = { body: "number=#{user_phone}&direct_line=#{val}", basic_auth: @auth, headers: { 'ContentType' => 'application/x-www-form-urlencoded'}} | |
puts "updated phone for: #{user_id}" | |
self.class.post("/users/#{user_id}/update_number", user_options) | |
end | |
end | |
class PhoneClient | |
def run | |
puts "" | |
puts "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" | |
puts "Welcome to the Zendesk PhoneSetter Command Line Interface!" | |
puts "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" | |
puts "" | |
puts "Enter your zendesk username:" | |
username = gets.chomp | |
puts "Enter your zendesk API token:" | |
token = gets.chomp | |
attachmentGetter = PhoneSetter.new(username, token) | |
puts "One last thing. Please enter your Zendesk subdomain:" | |
subdomain = gets.chomp | |
puts "thank you" | |
newUrl = "https://#{subdomain}.zendesk.com/" | |
PhoneSetter.base_uri newUrl | |
attachmentGetter.get_users | |
puts "Done! Your users have been updated. Goodbye." | |
end | |
end | |
# You can use the default prompt-based interface above or, | |
# alternatively, you can un-comment the below and put in your | |
# credentials to run instantly during testing: | |
# class PhoneClient | |
# def run | |
# username = _AGENT_EMAIL_HERE_ | |
# token = _ACCT_TOKEN_HERE_ | |
# attachmentGetter = PhoneSetter.new(username, token) | |
# subdomain = _SUBDOMAIN_HERE_ | |
# puts "thank you" | |
# newUrl = "https://#{subdomain}.zendesk.com/" | |
# PhoneSetter.base_uri newUrl | |
# attachmentGetter.get_users | |
# end | |
# end | |
myCLient = PhoneClient.new | |
myCLient.run |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment