# frozen_string_literal: true namespace :dev do desc 'Populate database with test data. Can be run multiple times. Should not be run in production environments' task populate_sample_data: :environment do # Create a valid account to showcase multiple post types showcase_account = Account.create_with(username: 'showcase_account').find_or_create_by!(id: 10_000_000) showcase_user = User.create_with( account_id: showcase_account.id, agreement: true, password: SecureRandom.hex, email: ENV.fetch('TEST_DATA_SHOWCASE_EMAIL', 'showcase_account@joinmastodon.org'), confirmed_at: Time.now.utc, approved: true, bypass_registration_checks: true ).find_or_create_by!(id: 10_000_000) showcase_user.mark_email_as_confirmed! showcase_user.approve! french_post = Status.create_with( text: 'Ceci est un sondage public écrit en Français', language: 'fr', account: showcase_account, visibility: :public, poll_attributes: { voters_count: 0, account: showcase_account, expires_at: 1.day.from_now, options: ['ceci est un choix', 'ceci est un autre choix'], multiple: false, } ).find_or_create_by!(id: 10_000_000) private_mentionless = Status.create_with( text: 'This is a private message written in English', language: 'en', account: showcase_account, visibility: :private ).find_or_create_by!(id: 10_000_001) public_self_reply_with_cw = Status.create_with( text: 'This is a public self-reply written in English; it has a CW and a multi-choice poll', spoiler_text: 'poll (CW example)', language: 'en', account: showcase_account, visibility: :public, thread: french_post, poll_attributes: { voters_count: 0, account: showcase_account, expires_at: 1.day.from_now, options: ['this is a choice', 'this is another choice', 'you can chose any number of them'], multiple: true, } ).find_or_create_by!(id: 10_000_002) ProcessHashtagsService.new.call(public_self_reply_with_cw) unlisted_self_reply_with_cw_tag_mention = Status.create_with( text: 'This is an unlisted (Quiet Public) self-reply written in #English; it has a CW, mentions @showcase_account, and uses an emoji 🦣', spoiler_text: 'CW example', language: 'en', account: showcase_account, visibility: :unlisted, thread: public_self_reply_with_cw ).find_or_create_by!(id: 10_000_003) Mention.find_or_create_by!(status: unlisted_self_reply_with_cw_tag_mention, account: showcase_account) ProcessHashtagsService.new.call(unlisted_self_reply_with_cw_tag_mention) media_attachment = MediaAttachment.create_with( account: showcase_account, file: File.open('spec/fixtures/files/600x400.png'), description: 'Mastodon logo' ).find_or_create_by!(id: 10_000_000) status_with_media = Status.create_with( text: "This is a public status with a picture and tags. The attached picture has an alt text\n\n#Mastodon #Logo #English #Test", ordered_media_attachment_ids: [media_attachment.id], account: showcase_account, visibility: :public ).find_or_create_by!(id: 10_000_004) media_attachment.update(status_id: status_with_media.id) ProcessHashtagsService.new.call(status_with_media) media_attachment = MediaAttachment.create_with( account: showcase_account, file: File.open('spec/fixtures/files/600x400.png'), description: 'Mastodon logo' ).find_or_create_by!(id: 10_000_001) status_with_sensitive_media = Status.create_with( text: "This is the same public status with a picture and tags, but it is marked as sensitive. The attached picture has an alt text\n\n#Mastodon #Logo #English #Test", ordered_media_attachment_ids: [media_attachment.id], account: showcase_account, visibility: :public, sensitive: true, thread: status_with_media ).find_or_create_by!(id: 10_000_005) media_attachment.update(status_id: status_with_sensitive_media.id) ProcessHashtagsService.new.call(status_with_sensitive_media) media_attachment = MediaAttachment.create_with( account: showcase_account, file: File.open('spec/fixtures/files/600x400.png'), description: 'Mastodon logo' ).find_or_create_by!(id: 10_000_002) status_with_cw_media = Status.create_with( text: "This is the same public status with a picture and tags, but it is behind a CW. The attached picture has an alt text\n\n#Mastodon #Logo #English #Test", spoiler_text: 'Mastodon logo', ordered_media_attachment_ids: [media_attachment.id], account: showcase_account, visibility: :public, sensitive: true, thread: status_with_sensitive_media ).find_or_create_by!(id: 10_000_006) media_attachment.update(status_id: status_with_cw_media.id) ProcessHashtagsService.new.call(status_with_cw_media) media_attachment = MediaAttachment.create_with( account: showcase_account, file: File.open('spec/fixtures/files/boop.ogg'), description: 'Mastodon boop' ).find_or_create_by!(id: 10_000_003) status_with_audio = Status.create_with( text: "This is the same public status with an audio file and tags. The attached picture has an alt text\n\n#Mastodon #English #Test", ordered_media_attachment_ids: [media_attachment.id], account: showcase_account, visibility: :public, thread: status_with_cw_media ).find_or_create_by!(id: 10_000_007) media_attachment.update(status_id: status_with_audio.id) ProcessHashtagsService.new.call(status_with_audio) media_attachment = MediaAttachment.create_with( account: showcase_account, file: File.open('spec/fixtures/files/boop.ogg'), description: 'Mastodon boop' ).find_or_create_by!(id: 10_000_004) status_with_sensitive_audio = Status.create_with( text: "This is the same public status with an audio file and tags, but it is marked as sensitive. The attached picture has an alt text\n\n#Mastodon #English #Test", ordered_media_attachment_ids: [media_attachment.id], account: showcase_account, visibility: :public, sensitive: true, thread: status_with_audio ).find_or_create_by!(id: 10_000_008) media_attachment.update(status_id: status_with_sensitive_audio.id) ProcessHashtagsService.new.call(status_with_sensitive_audio) media_attachment = MediaAttachment.create_with( account: showcase_account, file: File.open('spec/fixtures/files/boop.ogg'), description: 'Mastodon boop' ).find_or_create_by!(id: 10_000_005) status_with_cw_audio = Status.create_with( text: "This is the same public status with an audio file and tags, but it is behind a CW. The attached picture has an alt text\n\n#Mastodon #English #Test", spoiler_text: 'Mastodon boop', ordered_media_attachment_ids: [media_attachment.id], account: showcase_account, visibility: :public, sensitive: true, thread: status_with_sensitive_audio ).find_or_create_by!(id: 10_000_009) media_attachment.update(status_id: status_with_cw_audio.id) ProcessHashtagsService.new.call(status_with_cw_audio) media_attachments = [ MediaAttachment.create_with( account: showcase_account, file: File.open('spec/fixtures/files/600x400.png'), description: 'Mastodon logo' ).find_or_create_by!(id: 10_000_006), MediaAttachment.create_with( account: showcase_account, file: File.open('spec/fixtures/files/attachment.jpg') ).find_or_create_by!(id: 10_000_007), MediaAttachment.create_with( account: showcase_account, file: File.open('spec/fixtures/files/avatar-high.gif'), description: 'Walking cartoon cat' ).find_or_create_by!(id: 10_000_008), MediaAttachment.create_with( account: showcase_account, file: File.open('spec/fixtures/files/text.png'), description: 'Text saying “Hello Mastodon”' ).find_or_create_by!(id: 10_000_009), ] status_with_multiple_attachments = Status.create_with( text: "This is a post with multiple attachments, not all of which have a description\n\n#Mastodon #English #Test", spoiler_text: 'multiple attachments', ordered_media_attachment_ids: media_attachments.pluck(:id), account: showcase_account, visibility: :public, sensitive: true, thread: status_with_cw_audio ).find_or_create_by!(id: 10_000_010) media_attachments.each { |attachment| attachment.update!(status_id: status_with_multiple_attachments.id) } ProcessHashtagsService.new.call(status_with_multiple_attachments) remote_account = Account.create_with( username: 'fake.example', domain: 'example.org', uri: 'https://example.org/foo/bar', url: 'https://example.org/foo/bar', locked: true ).find_or_create_by!(id: 10_000_001) remote_formatted_post = Status.create_with( text: <<~HTML,

This is a post with a variety of HTML in it

For instance, this text is bold and this one as well, while this text is stricken through and this one as well.

This thing, here, is a block quote
with some bold as well

// And this is some code
        // with two lines of comments
        

And this is inline code

Finally, please observe this Ruby element: 明日 (Ashita)

HTML account: remote_account, uri: 'https://example.org/foo/bar/baz', url: 'https://example.org/foo/bar/baz' ).find_or_create_by!(id: 10_000_011) Status.create_with(account: showcase_account, reblog: remote_formatted_post).find_or_create_by!(id: 10_000_012) unattached_quote_post = Status.create_with( text: 'This is a quote of a post that does not exist', account: showcase_account, visibility: :public ).find_or_create_by!(id: 10_000_013) Quote.create_with( status: unattached_quote_post, quoted_status: nil ).find_or_create_by!(id: 10_000_000) self_quote = Status.create_with( text: 'This is a quote of a public self-post', account: showcase_account, visibility: :public ).find_or_create_by!(id: 10_000_014) Quote.create_with( status: self_quote, quoted_status: status_with_media, state: :accepted ).find_or_create_by!(id: 10_000_001) nested_self_quote = Status.create_with( text: 'This is a quote of a public self-post which itself is a self-quote', account: showcase_account, visibility: :public ).find_or_create_by!(id: 10_000_015) Quote.create_with( status: nested_self_quote, quoted_status: self_quote, state: :accepted ).find_or_create_by!(id: 10_000_002) recursive_self_quote = Status.create_with( text: 'This is a recursive self-quote; no real reason for it to exist, but just to make sure we handle them gracefuly', account: showcase_account, visibility: :public ).find_or_create_by!(id: 10_000_016) Quote.create_with( status: recursive_self_quote, quoted_status: recursive_self_quote, state: :accepted ).find_or_create_by!(id: 10_000_003) self_private_quote = Status.create_with( text: 'This is a public post of a private self-post: the quoted post should not be visible to non-followers', account: showcase_account, visibility: :public ).find_or_create_by!(id: 10_000_017) Quote.create_with( status: self_private_quote, quoted_status: private_mentionless, state: :accepted ).find_or_create_by!(id: 10_000_004) uncwed_quote_cwed = Status.create_with( text: 'This is a quote without CW of a quoted post that has a CW', account: showcase_account, visibility: :public ).find_or_create_by!(id: 10_000_018) Quote.create_with( status: uncwed_quote_cwed, quoted_status: public_self_reply_with_cw, state: :accepted ).find_or_create_by!(id: 10_000_005) cwed_quote_cwed = Status.create_with( text: 'This is a quote with a CW of a quoted post that itself has a CW', spoiler_text: 'Quote post with a CW', account: showcase_account, visibility: :public ).find_or_create_by!(id: 10_000_019) Quote.create_with( status: cwed_quote_cwed, quoted_status: public_self_reply_with_cw, state: :accepted ).find_or_create_by!(id: 10_000_006) pending_quote_post = Status.create_with( text: 'This quote post is pending', account: showcase_account, visibility: :public ).find_or_create_by!(id: 10_000_020) Quote.create_with( status: pending_quote_post, quoted_status: remote_formatted_post, activity_uri: 'https://foo/bar', state: :pending ).find_or_create_by!(id: 10_000_007) rejected_quote_post = Status.create_with( text: 'This quote post is rejected', account: showcase_account, visibility: :public ).find_or_create_by!(id: 10_000_021) Quote.create_with( status: rejected_quote_post, quoted_status: remote_formatted_post, activity_uri: 'https://foo/foo', state: :rejected ).find_or_create_by!(id: 10_000_008) revoked_quote_post = Status.create_with( text: 'This quote post is revoked', account: showcase_account, visibility: :public ).find_or_create_by!(id: 10_000_022) Quote.create_with( status: revoked_quote_post, quoted_status: remote_formatted_post, activity_uri: 'https://foo/baz', state: :revoked ).find_or_create_by!(id: 10_000_009) StatusPin.create_with(account: showcase_account, status: public_self_reply_with_cw).find_or_create_by!(id: 10_000_000) StatusPin.create_with(account: showcase_account, status: private_mentionless).find_or_create_by!(id: 10_000_001) showcase_account.update!( display_name: 'Mastodon test/showcase account', note: 'Test account to showcase many Mastodon features. Most of its posts are public, but some are private!' ) remote_quote = Status.create_with( text: <<~HTML,

This is a self-quote of a remote formatted post

RE: https://example.org/foo/bar/baz

HTML account: remote_account, uri: 'https://example.org/foo/bar/quote', url: 'https://example.org/foo/bar/quote' ).find_or_create_by!(id: 10_000_023) Quote.create_with( status: remote_quote, quoted_status: remote_formatted_post, state: :accepted ).find_or_create_by!(id: 10_000_010) Status.create_with( account: showcase_account, reblog: remote_quote ).find_or_create_by!(id: 10_000_024) media_attachment = MediaAttachment.create_with( account: showcase_account, file: File.open('spec/fixtures/files/attachment.jpg') ).find_or_create_by!(id: 10_000_010) quote_post_with_media = Status.create_with( text: "This is a status with a picture and tags which also quotes a status with a picture.\n\n#Mastodon #Test", ordered_media_attachment_ids: [media_attachment.id], account: showcase_account, visibility: :public ).find_or_create_by!(id: 10_000_025) media_attachment.update(status_id: quote_post_with_media.id) ProcessHashtagsService.new.call(quote_post_with_media) Quote.create_with( status: quote_post_with_media, quoted_status: status_with_media, state: :accepted ).find_or_create_by!(id: 10_000_011) showcase_sidekick_account = Account.create_with(username: 'showcase_sidekick').find_or_create_by!(id: 10_000_002) sidekick_user = User.create_with( account_id: showcase_sidekick_account.id, agreement: true, password: SecureRandom.hex, email: ENV.fetch('TEST_DATA_SHOWCASE_SIDEKICK_EMAIL', 'showcase_sidekick@joinmastodon.org'), confirmed_at: Time.now.utc, approved: true, bypass_registration_checks: true ).find_or_create_by!(id: 10_000_001) sidekick_user.mark_email_as_confirmed! sidekick_user.approve! sidekick_post = Status.create_with( text: 'This post only exists to be quoted.', account: showcase_sidekick_account, visibility: :public ).find_or_create_by!(id: 10_000_026) sidekick_quote_post = Status.create_with( text: 'This is a quote of a different user.', account: showcase_account, visibility: :public ).find_or_create_by!(id: 10_000_027) Quote.create_with( status: sidekick_quote_post, quoted_status: sidekick_post, activity_uri: 'https://foo/cross-account-quote', state: :accepted ).find_or_create_by!(id: 10_000_012) end end