Retrospring/lib/exporter.rb

252 lines
6.6 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
2016-01-05 10:44:20 -08:00
require 'json'
require 'yaml'
require 'httparty'
require 'securerandom'
class Exporter
EXPORT_ROLES = [:administrator, :moderator].freeze
2016-01-05 10:44:20 -08:00
def initialize(user)
@user = user
@obj = {}
2016-01-05 11:53:48 -08:00
@export_dirname = "export_#{@user.screen_name}_#{Time.now.to_i}_#{SecureRandom.base64.gsub(/[+=\/]/, '')}"
2016-01-05 10:44:20 -08:00
@export_filename = @user.screen_name
end
def export
@user.export_processing = true
@user.save validate: false
collect_user_info
collect_questions
collect_answers
collect_comments
collect_smiles
finalize
publish
2017-03-31 14:17:36 -07:00
rescue => e
2021-12-28 09:32:03 -08:00
Sentry.capture_exception(e)
2016-01-05 10:44:20 -08:00
@user.export_processing = false
@user.save validate: false
end
private
def collect_user_info
2021-12-21 15:02:26 -08:00
%i(answered_count asked_count ban_reason banned_until comment_smiled_count commented_count
confirmation_sent_at confirmed_at created_at profile_header profile_header_h profile_header_w profile_header_x profile_header_y
profile_picture_w profile_picture_h profile_picture_x profile_picture_y current_sign_in_at current_sign_in_ip
2021-12-21 15:02:26 -08:00
id last_sign_in_at last_sign_in_ip locale permanently_banned
2016-01-05 10:44:20 -08:00
privacy_allow_anonymous_questions privacy_allow_public_timeline privacy_allow_stranger_answers
privacy_show_in_search profile_header_file_name profile_picture_file_name
screen_name show_foreign_themes sign_in_count smiled_count updated_at).each do |f|
2016-01-05 10:44:20 -08:00
@obj[f] = @user.send f
end
2021-12-21 15:02:26 -08:00
@obj[:profile] = {}
%i(display_name motivation_header website location description).each do |f|
@obj[:profile][f] = @user.profile.send f
2021-12-21 15:02:26 -08:00
end
EXPORT_ROLES.each do |role|
@obj[role] = @user.has_role?(role)
end
2016-01-05 10:44:20 -08:00
end
def collect_questions
@obj[:questions] = []
@user.questions.each do |q|
@obj[:questions] << process_question(q, include_user: false)
end
end
def collect_answers
@obj[:answers] = []
@user.answers.each do |a|
@obj[:answers] << process_answer(a, include_user: false)
end
end
def collect_comments
@obj[:comments] = []
@user.comments.each do |c|
@obj[:comments] << process_comment(c, include_user: false, include_answer: true)
end
end
def collect_smiles
@obj[:smiles] = []
@user.smiles.each do |s|
@obj[:smiles] << process_smile(s)
end
end
def finalize
`mkdir -p "#{Rails.root.join "public", "export"}"`
`mkdir -p /tmp/rs_export/#{@export_dirname}/pictures`
if @user.profile_picture_file_name
%i(large medium small original).each do |s|
url = @user.profile_picture.url(s)
target_file = "/tmp/rs_export/#{@export_dirname}/pictures/picture_#{s}_#{@user.profile_picture_file_name}"
File.open target_file, 'wb' do |f|
f.binmode
2017-03-31 14:25:45 -07:00
data = if url.start_with?('/system')
2017-03-31 14:35:45 -07:00
File.read(Rails.root.join('public', url.sub(%r(\A/+), '')))
2017-03-31 14:25:45 -07:00
else
HTTParty.get(url).parsed_response
end
f.write data
2016-01-05 10:44:20 -08:00
end
end
end
if @user.profile_header_file_name
%i(web mobile retina original).each do |s|
url = @user.profile_header.url(s)
target_file = "/tmp/rs_export/#{@export_dirname}/pictures/header_#{s}_#{@user.profile_header_file_name}"
File.open target_file, 'wb' do |f|
f.binmode
2017-03-31 14:25:45 -07:00
data = if url.start_with?('/system')
2017-03-31 14:35:45 -07:00
File.read(Rails.root.join('public', url.sub(%r(\A/+), '')))
2017-03-31 14:25:45 -07:00
else
HTTParty.get(url).parsed_response
end
f.write data
2016-01-05 10:44:20 -08:00
end
end
end
File.open "/tmp/rs_export/#{@export_dirname}/#{@export_filename}.json", 'w' do |f|
f.puts @obj.to_json
end
File.open "/tmp/rs_export/#{@export_dirname}/#{@export_filename}.yml", 'w' do |f|
f.puts @obj.to_yaml
end
File.open "/tmp/rs_export/#{@export_dirname}/#{@export_filename}.xml", 'w' do |f|
f.puts @obj.to_xml
end
end
def publish
`tar czvf #{Rails.root.join "public", "export", "#{@export_dirname}.tar.gz"} -C /tmp/rs_export #{@export_dirname}`
url = "https://retrospring.net/export/#{@export_dirname}.tar.gz"
@user.export_processing = false
@user.export_url = url
@user.export_created_at = Time.now
@user.save validate: false
url
end
def process_question(question, options = {})
opts = {
include_user: true,
include_answers: true
}.merge(options)
qobj = {}
%i(answer_count author_is_anonymous content created_at id).each do |f|
2016-01-05 12:18:21 -08:00
qobj[f] = question.send f
2016-01-05 10:44:20 -08:00
end
if opts[:include_answers]
qobj[:answers] = []
2016-01-05 12:18:21 -08:00
question.answers.each do |a|
2016-01-05 10:44:20 -08:00
qobj[:answers] << process_answer(a, include_question: false)
end
end
if opts[:include_user]
qobj[:user] = question.author_is_anonymous ? nil : user_stub(question.user)
end
qobj
end
def process_answer(answer, options = {})
opts = {
include_question: true,
include_user: true,
include_comments: true
}.merge(options)
aobj = {}
%i(comment_count content created_at id smile_count).each do |f|
aobj[f] = answer.send f
end
if opts[:include_user]
aobj[:user] = user_stub(answer.user)
end
if opts[:include_question]
aobj[:question] = process_question(answer.question, include_user: true, include_answers: false)
end
if opts[:include_comments]
aobj[:comments] = []
answer.comments.each do |c|
aobj[:comments] << process_comment(c, include_user: true, include_answer: false)
end
end
aobj
end
def process_comment(comment, options = {})
opts = {
include_user: true,
include_answer: false
}.merge(options)
cobj = {}
%i(content created_at id).each do |f|
cobj[f] = comment.send f
end
if opts[:include_user]
cobj[:user] = user_stub(comment.user)
end
if opts[:include_answer]
cobj[:answer] = process_answer(comment.answer, include_comments: false)
end
cobj
end
def process_smile(smile)
sobj = {}
%i(id created_at).each do |f|
2016-01-05 12:23:43 -08:00
sobj[f] = smile.send f
2016-01-05 10:44:20 -08:00
end
2016-01-05 12:23:43 -08:00
sobj[:answer] = process_answer(smile.answer, include_comments: false)
2016-01-05 10:44:20 -08:00
sobj
end
def user_stub(user)
uobj = {}
%i(answered_count asked_count comment_smiled_count commented_count created_at
id permanently_banned screen_name smiled_count).each do |f|
2016-01-05 10:44:20 -08:00
uobj[f] = user.send f
end
2021-12-21 15:02:26 -08:00
uobj[:profile] = {}
%i(display_name motivation_header website location description).each do |f|
uobj[:profile][f] = user.profile.send f
2021-12-21 15:02:26 -08:00
end
EXPORT_ROLES.each do |role|
uobj[role] = user.has_role?(role)
end
2016-01-05 10:44:20 -08:00
uobj
end
end