Skip to content

Instantly share code, notes, and snippets.

@lackac
Created November 19, 2009 16:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lackac/238863 to your computer and use it in GitHub Desktop.
Save lackac/238863 to your computer and use it in GitHub Desktop.
Migrates a blog's comments from the Typo blog engine to Disqus
#!/usr/bin/env ruby
# Author: László Bácsi <lackac@lackac.hu>
require 'rubygems'
require 'httparty'
require 'json'
require 'sequel'
require 'htmlentities'
$KCODE = 'u'
class String
def decode_entities
coder = HTMLEntities.new
coder.decode(self)
end
end
class Disqus
include HTTParty
base_uri "http://disqus.com/api"
POST_METHODS = %w{create_post thread_by_identifier update_thread}
GET_METHODS = %w{get_forum_list get_forum_api_key get_thread_list
get_num_posts get_thread_by_url get_thread_posts}
class RequestUnsuccessful < RuntimeError; end
def initialize(api_key)
@api_key = api_key
end
def method_missing method, *args
query = args.last.is_a?(Hash) ? args.last : {}
unless query.has_key?(:forum_api_key) or query.has_key?('forum_api_key')
query.merge! :user_api_key => @api_key
end
if POST_METHODS.include?(method.to_s)
resp = self.class.post "/#{method}/", :body => query
elsif GET_METHODS.include?(method.to_s)
resp = self.class.get "/#{method}/", :query => query
else
return super
end
if resp['succeeded']
resp['message']
else
raise RequestUnsuccessful.new("#{resp['code']}: #{resp['message']}")
end
end
class Typo
SQL = <<-EOS
SELECT f.id id,
f.type type,
f.author author,
f.email email,
f.url url,
f.ip ip,
f.body body,
f.created_at created_at,
c.permalink post_slug,
c.published_at post_date,
c.title post_title
FROM feedback f
LEFT OUTER JOIN contents c
ON f.article_id = c.id
EOS
class << self
private :new
def process db, disqus_api_key, forum_shortname
dq = Disqus.new(disqus_api_key)
forums = dq.get_forum_list
forum_id = forums.detect {|f| f['shortname'] == forum_shortname}['id']
forum_key = dq.get_forum_api_key :forum_id => forum_id
db[SQL].each do |comment|
# TODO: Change this next line to match the uri pattern your blog will be using
post_uri = "http://lackac.hu/#{comment[:post_date].strftime("%Y/%m/%d")}/#{comment[:post_slug]}.html"
puts "---"
puts "POST: #{post_uri}"
puts comment.inspect
thread = dq.get_thread_by_url :forum_api_key => forum_key, :url => post_uri
# If a Disqus thread is not found with the current url, create a new thread and add the url.
if thread.nil?
# TODO: Change this next line to whatever title patter your blog posts will have
title = "#{comment[:post_title]} – lackac.hu"
thread = dq.thread_by_identifier(:forum_api_key => forum_key,
:identifier => title, :title => title)['thread']
# Update the Disqus thread with the current post_uri
dq.update_thread :forum_api_key => forum_key, :thread_id => thread['id'], :url => post_uri
end
# Import comment
begin
comment_args = {
:message => comment[:body],
:author_name => comment[:author],
:author_email => comment[:email],
:created_at => comment[:created_at].utc.strftime("%Y-%m-%dT%H:%M")
}
unless comment[:url].nil? or comment[:url] == ""
comment_args.merge! :author_url => comment[:url]
end
unless comment[:ip].nil? or comment[:ip] == ""
comment_args.merge! :ip_address => comment[:ip]
end
comment = dq.create_post({:forum_api_key => forum_key, :thread_id => thread['id']}.merge(comment_args))
rescue RequestUnsuccessful => e
puts "FAILED: #{e.message}"
else
puts "SUCCESS"
end
end
end
end
end
end
if __FILE__ == $PROGRAM_NAME
unless ARGV.size < 5
api_key, forum, typo_db, db_user, db_pass, db_host = ARGV
db = Sequel.mysql typo_db, :user => db_user, :password => db_pass, :host => (db_host || "localhost")
Disqus::Typo.process(db, api_key, forum)
else
puts "Usage: #{__FILE__} api_key forum typo_db db_user db_pass [db_host]"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment