#!/usr/bin/env ruby # By trythil@member.fsf.org # Dedicated to the public domain. require 'xmlrpc/client' require 'md5' IDs = # entry IDs here as array of Integers; you can use logjam to download your entries as XML, at which point you can use your favorite XML parsing library to pull out the IDs class Redactor URL = 'http://www.livejournal.com/interface/xmlrpc' HashedPassword = 'YOUR_MD5_HASHED_PASSWORD_HERE' Username = 'YOUR_USERNAME' def redact pool = ThreadPool.new(4) IDs.each { |id| puts "processing #{id}"; pool.process { redact_one(id) } } pool.join end def redact_one(entry_id) client = XMLRPC::Client.new2(URL) challenge = client.call('LJ.XMLRPC.getchallenge') response = MD5.hexdigest(challenge['challenge'] + HashedPassword) begin ret = client.call('LJ.XMLRPC.editevent', { :username => Username, :auth_method => 'challenge', :auth_challenge => challenge['challenge'], :auth_response => response, :itemid => entry_id, :lineendings => 'unix', :subject => 'Entry removed.', :event => 'Entry removed.', :security => 'usemask', :allowmask => '1' # friends only }) sleep(1) rescue end end end # from http://snippets.dzone.com/posts/show/3276 class ThreadPool class Worker def initialize @mutex = Mutex.new @thread = Thread.new do while true sleep 0.001 block = get_block if block block.call reset_block end end end end def get_block @mutex.synchronize {@block} end def set_block(block) @mutex.synchronize do raise RuntimeError, "Thread already busy." if @block @block = block end end def reset_block @mutex.synchronize {@block = nil} end def busy? @mutex.synchronize {!@block.nil?} end end attr_accessor :max_size attr_reader :workers def initialize(max_size = 10) @max_size = max_size @workers = [] @mutex = Mutex.new end def size @mutex.synchronize {@workers.size} end def busy? @mutex.synchronize {@workers.any? {|w| w.busy?}} end def join sleep 0.01 while busy? end def process(&block) while true @mutex.synchronize do worker = find_available_worker if worker return worker.set_block(block) end end sleep 0.01 end end def find_available_worker free_worker || create_worker end def wait_for_worker while true worker = find_available_worker return worker if worker sleep 0.01 end end def free_worker @workers.each {|w| return w unless w.busy?}; nil end def create_worker return nil if @workers.size >= @max_size worker = Worker.new @workers << worker worker end end Redactor.new.redact