Skip to content

Instantly share code, notes, and snippets.

@lukaszraczylo
Last active July 13, 2021 15:43
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save lukaszraczylo/11309053 to your computer and use it in GitHub Desktop.
Save lukaszraczylo/11309053 to your computer and use it in GitHub Desktop.
Delete hipchat 1:1 history (WORKING)
#!/usr/bin/env ruby
# To make it work:
# - change account details to yours ( obviously ;) )
# - install mechanize gem in version 1.0.0 ( gem install mechanize -v '1.0.0' )
# - look for !!HERE!! comments in code in case you'd like to change default behavior
# - for best results run this script few times as hipchat / ruby openssl don't play together that well and
# there might be an exception thrown from time to time. Script should retry then but hey.. Nobody is perfect.
# .. and finally. Remember that other part should run this script as well to make history clean.
require 'rubygems'
require 'mechanize' # for making everything work
require 'chronic' # for parsing weird timestamps from hipchat
require 'awesome_print'
agent = Mechanize.new
agent.redirect_ok = true
agent.keep_alive = false
agent.agent.http.verify_mode = OpenSSL::SSL::VERIFY_NONE
prepSite = agent.get("https://www.hipchat.com/sign_in")
xsrf_token = prepSite.forms[0].fields[0]
account = {
:email => "potato",
:password => "banana"
}
form = prepSite.form_with :name => 'signin'
form.email = account[:email]
form.password = account[:password]
v = form.submit
site = v.uri.host
# Get our user id
member_id = agent.get("https://#{site}/account").search('img[alt="Your photo"]').first["src"].match(%r{photos/(\d+)})[1]
# Determine our Signup date and the actual date
registered_around = agent.get("https://#{site}/people/show/#{member_id}").
search('li:contains("Signed up")').text.sub(/Signed up: /, '')
registered_on = Date.parse(Chronic.parse(registered_around).to_s)
# !!HERE!!
# You can change behaviour to 'remove only messages since...' by changing registered_on
# variable to specific date, like:
# registered_on = Date.parse("01-01-2014")
# registered_on = Date.parse("01-12-2015")
puts "Found registration date: #{registered_on}"
intervals = (registered_on..Date.today).map { |d| d.strftime("/%Y/%m/%d") }
# Identify all users ids
members = agent.get("https://#{site}/people").search("ul.members").children.search("a").
map { |m| m.attributes["href"].value.to_s.split('/')[3] }.
reject { |m| m =~ /#{member_id}/ }
# !!HERE!!
# Instead of removing all the private chats, with everyone in your organisation
# you might define single user or user ids just like this:
# members = [ "666" , "777" ]
max_process = 20
# !!HERE!!
# I _don't_ recommend going above 20 as it makes hipchat devops cry and their servers suffer.
# Just leave default '20' and leave script for the night or weekend ;)
processing_pids = {}
# I'll just leave it here
def process_all_pages(day_history = nil, member = nil, processing_pids = nil, max_process = nil)
day_history.forms.each do |f|
begin
if f.action =~ /history\/member\/#{member}/
puts ">> QUEUE >> #{processing_pids.size}"
while processing_pids.size < max_process
pid_starting = Process.fork {
puts "Deleting.."
f.submit
}
processing_pids[pid_starting] = "1"
end
end
if processing_pids.size != 0
if pid_done = Process.wait(0, Process::WNOHANG)
if job_finished = processing_pids.delete(pid_done)
puts "Deleted"
end
else
sleep(2)
# raise an exception to get a retry
raise "Force retry"
end
end
rescue
puts "Retrying"
retry
end
end
end
# deleting all the history
members.each do |member|
intervals.each do |interval|
last_history_page = nil
# Added some level of verbosity in checks.
puts "Looking for chats with user #{member} on #{interval.gsub(/^\//, '')}"
day_history_base = agent.get("https://#{site}/history/member/#{member.to_i}#{interval}")
# Listing pages of conversation
day_history_base.links.each do |p|
if p.uri.to_s =~ /history\/member\/#{member}#{interval}\?p\=/ && p.text =~ /Last/
last_history_page = p.uri.to_s.split('=')[1]
end
end
if last_history_page != nil
(1..last_history_page.to_i).each do |page|
puts "\tCleaning subpage #{page}"
day_history_base = agent.get("https://#{site}/history/member/#{member.to_i}#{interval}/?p=#{page}")
process_all_pages(day_history_base, member, processing_pids, max_process)
end
else
process_all_pages(day_history_base, member, processing_pids, max_process)
end
end
end
@Intecpsp
Copy link

Intecpsp commented Feb 6, 2015

Adding:

agent.keep_alive = false
agent.agent.http.verify_mode = OpenSSL::SSL::VERIFY_NONE

Below:

agent.redirect_ok = true

Resolved getting:

Net::HTTP::Persistent::Error: too many connection resets (due to Connection reset by peer - Errno::ECONNRESET) 

@giskarda
Copy link

giskarda commented Jun 9, 2016

In order to delete all the 'paginated' conversationI would suggest to update the gist with the below.

# deleting all the history
members.each do |member|
  intervals.each do |interval|
    last_history_page = nil
    # Added some level of verbosity in checks.
    puts "Looking for chats with user #{member} on #{interval.gsub(/^\//, '')}"
    day_history_base = agent.get("https://#{site}/history/member/#{member.to_i}#{interval}")
    # Listing pages of conversation
    last_history_page = 1
    day_history_base.links.each do |p|
      if p.uri.to_s =~ /\/history\/member\/#{member}#{interval}\?p\=/
        last_history_page += 1
      end
    end

    if last_history_page > 1
      (1..last_history_page.to_i).each do |page|
        puts "\tCleaning subpage #{page}"
        day_history_base = agent.get("https://#{site}/history/member/#{member.to_i}#{interval}/?p=#{page}")
        process_all_pages(day_history_base, member, processing_pids, max_process)
      end
    else
      process_all_pages(day_history_base, member, processing_pids, max_process)
    end
  end
end

@pwebb-home
Copy link

Unfortunatly seems to throw and error now with Mechanize:
screen shot 2016-07-25 at 11 06 23 am

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment