# frozen_string_literal: true class DataExporter SECTIONS = %i[user ip_history interactions comments posts filters galleries reports conversations] USER_FIELDS = %w[id name slug email role secondary_role created_at updated_at last_renamed_at sign_in_count current_sign_in_at current_sign_in_ip last_sign_in_at last_sign_in_ip] USER_PROFILE_FIELDS = %w[personal_title description] USER_SETTING_FIELDS = %w[anonymous_by_default comments_always_jump_to_last comments_newest_first comments_per_page fancy_tag_field_on_edit fancy_tag_field_on_upload hide_comments hide_vote_counts images_per_page messages_newest_first no_spoilered_in_watched scale_large_images serve_webm show_large_thumbnails show_sidebar_and_watched_images spoiler_type theme use_centered_layout watch_on_new_topic watch_on_reply watch_on_upload watched_images_exclude_str watched_images_query_str watched_tag_ids] IP_FIELDS = %w[ip uses created_at updated_at] COMMENT_FIELDS = %w[id post_id created_at updated_at anonymous body destroyed_content hidden_from_users deletion_reason edit_reason edited_at ip referrer user_agent] POST_FIELDS = %w[id created_at updated_at anonymous media_type description destroyed_content hidden_from_users deletion_reason ip referrer user_agent] FILTER_FIELDS = %w[id name description public created_at updated_at hidden_complex_str hidden_tag_ids spoilered_complex_str spoilered_tag_ids user_count] GALLERY_FIELDS = %w[id title description spoiler_warning created_at updated_at thumbnail_id] REPORT_FIELDS = %w[id reportable_type reportable_id state created_at updated_at ip referrer user_agent] CONVERSATION_FIELDS = %w[id title slug from_id to_id created_at updated_at] MESSAGE_FIELDS = %w[id from_id body created_at updated_at] def initialize(user) @user = user end def data SECTIONS.map do |sec| [sec, { sec => unfuck_ips(self.send(sec)) }] end end private # Ruby serializes IPAddr weirdly def unfuck_ips(h) if h.is_a?(Array) h.map { |v| v.is_a?(Hash) ? unfuck_ips(v) : v } elsif h.is_a?(Hash) Hash[h.map { |k, v| [k, v.is_a?(IPAddr) ? v.to_s : v] }] else h end end def user user_attrs = @user.attributes user_attrs.slice(*USER_FIELDS) .merge({ profile: user_attrs.slice(*USER_PROFILE_FIELDS), settings: user_attrs.slice(*USER_SETTING_FIELDS) }) end def ip_history ips = UserIp.where(user: @user) ips.map { |i| i.attributes.slice(*IP_FIELDS) } end def interactions votes = Post::Vote.select(:post_id).where(user: @user) upvotes = votes.where(up: true) downvotes = votes.where(up: false) faves = Post::Fave.select(:post_id).where(user: @user) hides = Post::Hide.select(:post_id).where(user: @user) { upvoted: upvotes.pluck(:post_id), downvoted: downvotes.pluck(:post_id), faved: faves.pluck(:post_id), hidden: hides.pluck(:post_id) } end def comments comments = Comment.where(user: @user) comments.map { |c| c.attributes.slice(*COMMENT_FIELDS) } end def posts uploads = Post.select(*POST_FIELDS).where(user: @user) uploads.map { |u| u.attributes.slice(*POST_FIELDS).merge(url: u.media&.url('full')) } end def filters filters = Filter.where(user: @user) { current_filter_id: @user.current_filter_id, filters: filters.map { |f| f.attributes.slice(*FILTER_FIELDS) } } end def galleries galleries = Gallery.where(creator: @user) galleries.map { |g| g.attributes.slice(*GALLERY_FIELDS).merge(posts: g.posts.pluck(:id)) } # TODO: Order end def reports reports = Report.where(user: @user) reports.map { |g| g.attributes.slice(*REPORT_FIELDS) } end def conversations conversations = Conversation.where(from_id: @user.id).or(Conversation.where(to_id: @user.id)) conversations.map do |c| c.attributes .slice(*CONVERSATION_FIELDS) .merge(messages: c.messages.where(from_id: @user.id).map { |m| m.attributes.slice(*MESSAGE_FIELDS) }) end end end