From 9239e4ce4d4e958e62552d4a01183d0295c020f5 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 14 Sep 2017 00:04:30 +0200 Subject: Uploads for admin site settings (#4913) * Improve OpenGraph tags for about pages * Add thumbnail admin setting * Fix error * Fix up --- db/migrate/20170913000752_create_site_uploads.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 db/migrate/20170913000752_create_site_uploads.rb (limited to 'db/migrate') diff --git a/db/migrate/20170913000752_create_site_uploads.rb b/db/migrate/20170913000752_create_site_uploads.rb new file mode 100644 index 000000000..2246e48cd --- /dev/null +++ b/db/migrate/20170913000752_create_site_uploads.rb @@ -0,0 +1,10 @@ +class CreateSiteUploads < ActiveRecord::Migration[5.1] + def change + create_table :site_uploads do |t| + t.string :var, default: '', null: false, index: { unique: true } + t.attachment :file + t.json :meta + t.timestamps + end + end +end -- cgit From 81cec35dbf1b348d23363559e3f4e6b1ec3415c5 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 19 Sep 2017 02:42:40 +0200 Subject: Custom emoji (#4988) * Custom emoji - In OStatus: `` - In ActivityPub: `{ type: "Emoji", name: ":coolcat:", href: "http://..." }` - In REST API: Status object includes `emojis` array (`shortcode`, `url`) - Domain blocks with reject media stop emojis - Emoji file up to 50KB - Web UI handles custom emojis - Static pages render custom emojis as `` tags Side effects: - Undo #4500 optimization, as I needed to modify it to restore shortcode handling in emojify() - Formatter#plaintext should now make sure stripped out line-breaks and paragraphs are replaced with newlines * Fix emoji at the start not being converted --- app/javascript/mastodon/emoji.js | 60 ++++++++++------ app/javascript/mastodon/reducers/statuses.js | 9 ++- app/lib/activitypub/activity/create.rb | 13 ++++ app/lib/formatter.rb | 54 +++++++++++++- app/lib/ostatus/activity/creation.rb | 20 ++++++ app/lib/ostatus/atom_serializer.rb | 4 ++ app/models/custom_emoji.rb | 38 ++++++++++ app/models/status.rb | 4 ++ app/serializers/activitypub/note_serializer.rb | 20 +++++- app/serializers/rest/status_serializer.rb | 11 +++ .../stream_entries/_detailed_status.html.haml | 2 +- app/views/stream_entries/_simple_status.html.haml | 2 +- db/migrate/20170917153509_create_custom_emojis.rb | 13 ++++ db/schema.rb | 14 +++- spec/fabricators/custom_emoji_fabricator.rb | 5 ++ spec/fixtures/files/emojo.png | Bin 0 -> 29814 bytes spec/lib/activitypub/activity/create_spec.rb | 25 +++++++ spec/lib/formatter_spec.rb | 78 +++++++++++++++++++++ spec/lib/ostatus/atom_serializer_spec.rb | 16 ++++- spec/models/custom_emoji_spec.rb | 25 +++++++ 20 files changed, 382 insertions(+), 31 deletions(-) create mode 100644 app/models/custom_emoji.rb create mode 100644 db/migrate/20170917153509_create_custom_emojis.rb create mode 100644 spec/fabricators/custom_emoji_fabricator.rb create mode 100644 spec/fixtures/files/emojo.png create mode 100644 spec/models/custom_emoji_spec.rb (limited to 'db/migrate') diff --git a/app/javascript/mastodon/emoji.js b/app/javascript/mastodon/emoji.js index a41dfdd1d..865b85b61 100644 --- a/app/javascript/mastodon/emoji.js +++ b/app/javascript/mastodon/emoji.js @@ -3,28 +3,48 @@ import Trie from 'substring-trie'; const trie = new Trie(Object.keys(unicodeMapping)); -const emojify = str => { - let rtn = ''; - for (;;) { - let match, i = 0; - while (i < str.length && str[i] !== '<' && !(match = trie.search(str.slice(i)))) { - i += str.codePointAt(i) < 65536 ? 1 : 2; - } - if (i === str.length) - break; - else if (str[i] === '<') { - let tagend = str.indexOf('>', i + 1) + 1; - if (!tagend) - break; - rtn += str.slice(0, tagend); - str = str.slice(tagend); - } else { - const [filename, shortCode] = unicodeMapping[match]; - rtn += str.slice(0, i) + `${match}`; - str = str.slice(i + match.length); +const emojify = (str, customEmojis = {}) => { + // This walks through the string from start to end, ignoring any tags (

,
, etc.) + // and replacing valid unicode strings + // that _aren't_ within tags with an version. + // The goal is to be the same as an emojione.regUnicode replacement, but faster. + let i = -1; + let insideTag = false; + let insideShortname = false; + let shortnameStartIndex = -1; + let match; + while (++i < str.length) { + const char = str.charAt(i); + if (insideShortname && char === ':') { + const shortname = str.substring(shortnameStartIndex, i + 1); + if (shortname in customEmojis) { + const replacement = `${shortname}`; + str = str.substring(0, shortnameStartIndex) + replacement + str.substring(i + 1); + i += (replacement.length - shortname.length - 1); // jump ahead the length we've added to the string + } else { + i--; + } + insideShortname = false; + } else if (insideTag && char === '>') { + insideTag = false; + } else if (char === '<') { + insideTag = true; + insideShortname = false; + } else if (!insideTag && char === ':') { + insideShortname = true; + shortnameStartIndex = i; + } else if (!insideTag && (match = trie.search(str.substring(i)))) { + const unicodeStr = match; + if (unicodeStr in unicodeMapping) { + const [filename, shortCode] = unicodeMapping[unicodeStr]; + const alt = unicodeStr; + const replacement = `${alt}`; + str = str.substring(0, i) + replacement + str.substring(i + unicodeStr.length); + i += (replacement.length - unicodeStr.length); // jump ahead the length we've added to the string + } } } - return rtn + str; + return str; }; export default emojify; diff --git a/app/javascript/mastodon/reducers/statuses.js b/app/javascript/mastodon/reducers/statuses.js index 7f906bef6..38b23504e 100644 --- a/app/javascript/mastodon/reducers/statuses.js +++ b/app/javascript/mastodon/reducers/statuses.js @@ -58,9 +58,14 @@ const normalizeStatus = (state, status) => { } const searchContent = [status.spoiler_text, status.content].join(' ').replace(/
/g, '\n').replace(/<\/p>

/g, '\n\n'); + const emojiMap = normalStatus.emojis.reduce((obj, emoji) => { + obj[`:${emoji.shortcode}:`] = emoji.url; + return obj; + }, {}); + normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent; - normalStatus.contentHtml = emojify(normalStatus.content); - normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(normalStatus.spoiler_text || '')); + normalStatus.contentHtml = emojify(normalStatus.content, emojiMap); + normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(normalStatus.spoiler_text || ''), emojiMap); return state.update(status.id, ImmutableMap(), map => map.mergeDeep(fromJS(normalStatus))); }; diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 894759d9a..41f2b0bad 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -61,6 +61,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity process_hashtag tag, status when 'Mention' process_mention tag, status + when 'Emoji' + process_emoji tag, status end end end @@ -79,6 +81,17 @@ class ActivityPub::Activity::Create < ActivityPub::Activity account.mentions.create(status: status) end + def process_emoji(tag, _status) + shortcode = tag['name'].delete(':') + emoji = CustomEmoji.find_by(shortcode: shortcode, domain: @account.domain) + + return if !emoji.nil? || skip_download? + + emoji = CustomEmoji.new(domain: @account.domain, shortcode: shortcode) + emoji.image_remote_url = tag['href'] + emoji.save + end + def process_attachments(status) return unless @object['attachment'].is_a?(Array) diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index 575830190..29fea27de 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -9,7 +9,7 @@ class Formatter include ActionView::Helpers::TextHelper - def format(status) + def format(status, options = {}) if status.reblog? prepend_reblog = status.reblog.account.acct status = status.proper @@ -19,7 +19,11 @@ class Formatter raw_content = status.text - return reformat(raw_content) unless status.local? + unless status.local? + html = reformat(raw_content) + html = encode_custom_emojis(html, status.emojis) if options[:custom_emojify] + return html + end linkable_accounts = status.mentions.map(&:account) linkable_accounts << status.account @@ -27,6 +31,7 @@ class Formatter html = raw_content html = "RT @#{prepend_reblog} #{html}" if prepend_reblog html = encode_and_link_urls(html, linkable_accounts) + html = encode_custom_emojis(html, status.emojis) if options[:custom_emojify] html = simple_format(html, {}, sanitize: false) html = html.delete("\n") @@ -39,7 +44,9 @@ class Formatter def plaintext(status) return status.text if status.local? - strip_tags(status.text) + + text = status.text.gsub(/(
|
|<\/p>)+/) { |match| "#{match}\n" } + strip_tags(text) end def simplified_format(account) @@ -76,6 +83,47 @@ class Formatter end end + def encode_custom_emojis(html, emojis) + return html if emojis.empty? + + emoji_map = emojis.map { |e| [e.shortcode, full_asset_url(e.image.url)] }.to_h + + i = -1 + inside_tag = false + inside_shortname = false + shortname_start_index = -1 + + while i + 1 < html.size + i += 1 + + if inside_shortname && html[i] == ':' + shortcode = html[shortname_start_index + 1..i - 1] + emoji = emoji_map[shortcode] + + if emoji + replacement = "\":#{shortcode}:\"" + before_html = shortname_start_index.positive? ? html[0..shortname_start_index - 1] : '' + html = before_html + replacement + html[i + 1..-1] + i += replacement.size - (shortcode.size + 2) - 1 + else + i -= 1 + end + + inside_shortname = false + elsif inside_tag && html[i] == '>' + inside_tag = false + elsif html[i] == '<' + inside_tag = true + inside_shortname = false + elsif !inside_tag && html[i] == ':' + inside_shortname = true + shortname_start_index = i + end + end + + html + end + def rewrite(text, entities) chars = text.to_s.to_char_a diff --git a/app/lib/ostatus/activity/creation.rb b/app/lib/ostatus/activity/creation.rb index 1a23c9efa..d3f1629c4 100644 --- a/app/lib/ostatus/activity/creation.rb +++ b/app/lib/ostatus/activity/creation.rb @@ -42,6 +42,7 @@ class OStatus::Activity::Creation < OStatus::Activity::Base save_mentions(status) save_hashtags(status) save_media(status) + save_emojis(status) end if thread? && status.thread.nil? @@ -150,6 +151,25 @@ class OStatus::Activity::Creation < OStatus::Activity::Base end end + def save_emojis(parent) + do_not_download = DomainBlock.find_by(domain: parent.account.domain)&.reject_media? + + return if do_not_download + + @xml.xpath('./xmlns:link[@rel="emoji"]', xmlns: TagManager::XMLNS).each do |link| + next unless link['href'] && link['name'] + + shortcode = link['name'].delete(':') + emoji = CustomEmoji.find_by(shortcode: shortcode, domain: parent.account.domain) + + next unless emoji.nil? + + emoji = CustomEmoji.new(shortcode: shortcode, domain: parent.account.domain) + emoji.image_remote_url = link['href'] + emoji.save + end + end + def account_from_href(href) url = Addressable::URI.parse(href).normalize diff --git a/app/lib/ostatus/atom_serializer.rb b/app/lib/ostatus/atom_serializer.rb index b8e22a381..a6a5cb0c4 100644 --- a/app/lib/ostatus/atom_serializer.rb +++ b/app/lib/ostatus/atom_serializer.rb @@ -368,5 +368,9 @@ class OStatus::AtomSerializer end append_element(entry, 'mastodon:scope', status.visibility) + + status.emojis.each do |emoji| + append_element(entry, 'link', nil, rel: :emoji, href: full_asset_url(emoji.image.url), name: emoji.shortcode) + end end end diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb new file mode 100644 index 000000000..f4d3b16a0 --- /dev/null +++ b/app/models/custom_emoji.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true +# == Schema Information +# +# Table name: custom_emojis +# +# id :integer not null, primary key +# shortcode :string default(""), not null +# domain :string +# image_file_name :string +# image_content_type :string +# image_file_size :integer +# image_updated_at :datetime +# created_at :datetime not null +# updated_at :datetime not null +# + +class CustomEmoji < ApplicationRecord + SHORTCODE_RE_FRAGMENT = '[a-zA-Z0-9_]{2,}' + + SCAN_RE = /(?<=[^[:alnum:]:]|\n|^) + :(#{SHORTCODE_RE_FRAGMENT}): + (?=[^[:alnum:]:]|$)/x + + has_attached_file :image + + validates_attachment :image, content_type: { content_type: 'image/png' }, presence: true, size: { in: 0..50.kilobytes } + validates :shortcode, uniqueness: { scope: :domain }, format: { with: /\A#{SHORTCODE_RE_FRAGMENT}\z/ }, length: { minimum: 2 } + + include Remotable + + class << self + def from_text(text, domain) + return [] if text.blank? + shortcodes = text.scan(SCAN_RE).map(&:first) + where(shortcode: shortcodes, domain: domain) + end + end +end diff --git a/app/models/status.rb b/app/models/status.rb index 2a2cdcf6e..326d128d6 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -131,6 +131,10 @@ class Status < ApplicationRecord !sensitive? && media_attachments.any? end + def emojis + CustomEmoji.from_text(text, account.domain) + end + after_create :store_uri, if: :local? before_validation :prepare_contents, if: :local? diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb index 166214eee..e5d8e3f03 100644 --- a/app/serializers/activitypub/note_serializer.rb +++ b/app/serializers/activitypub/note_serializer.rb @@ -57,7 +57,7 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer end def virtual_tags - object.mentions + object.tags + object.mentions + object.tags + object.emojis end def atom_uri @@ -137,4 +137,22 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer "##{object.name}" end end + + class CustomEmojiSerializer < ActiveModel::Serializer + include RoutingHelper + + attributes :type, :href, :name + + def type + 'Emoji' + end + + def href + full_asset_url(object.image.url) + end + + def name + ":#{object.shortcode}:" + end + end end diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index 298a3bb40..d8efa8e60 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -17,6 +17,7 @@ class REST::StatusSerializer < ActiveModel::Serializer has_many :media_attachments, serializer: REST::MediaAttachmentSerializer has_many :mentions has_many :tags + has_many :emojis def current_user? !current_user.nil? @@ -106,4 +107,14 @@ class REST::StatusSerializer < ActiveModel::Serializer tag_url(object) end end + + class CustomEmojiSerializer < ActiveModel::Serializer + include RoutingHelper + + attributes :shortcode, :url + + def url + full_asset_url(object.image.url) + end + end end diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index dd9456260..692d5a6d5 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -17,7 +17,7 @@ %p{ style: 'margin-bottom: 0' }< %span.p-summary> #{status.spoiler_text}  %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') - .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status) + .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true) - if !status.media_attachments.empty? - if status.media_attachments.first.video? diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml index 55aa97f32..f9a530d38 100644 --- a/app/views/stream_entries/_simple_status.html.haml +++ b/app/views/stream_entries/_simple_status.html.haml @@ -18,7 +18,7 @@ %p{ style: 'margin-bottom: 0' }< %span.p-summary> #{status.spoiler_text}  %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') - .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status) + .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true) - unless status.media_attachments.empty? - if status.media_attachments.first.video? diff --git a/db/migrate/20170917153509_create_custom_emojis.rb b/db/migrate/20170917153509_create_custom_emojis.rb new file mode 100644 index 000000000..4040c8312 --- /dev/null +++ b/db/migrate/20170917153509_create_custom_emojis.rb @@ -0,0 +1,13 @@ +class CreateCustomEmojis < ActiveRecord::Migration[5.1] + def change + create_table :custom_emojis do |t| + t.string :shortcode, null: false, default: '' + t.string :domain + t.attachment :image + + t.timestamps + end + + add_index :custom_emojis, [:shortcode, :domain], unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index f2ca2af69..9f42d46dd 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170913000752) do +ActiveRecord::Schema.define(version: 20170917153509) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -89,6 +89,18 @@ ActiveRecord::Schema.define(version: 20170913000752) do t.index ["uri"], name: "index_conversations_on_uri", unique: true end + create_table "custom_emojis", force: :cascade do |t| + t.string "shortcode", default: "", null: false + t.string "domain" + t.string "image_file_name" + t.string "image_content_type" + t.integer "image_file_size" + t.datetime "image_updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["shortcode", "domain"], name: "index_custom_emojis_on_shortcode_and_domain", unique: true + end + create_table "domain_blocks", id: :serial, force: :cascade do |t| t.string "domain", default: "", null: false t.datetime "created_at", null: false diff --git a/spec/fabricators/custom_emoji_fabricator.rb b/spec/fabricators/custom_emoji_fabricator.rb new file mode 100644 index 000000000..18a7d23dc --- /dev/null +++ b/spec/fabricators/custom_emoji_fabricator.rb @@ -0,0 +1,5 @@ +Fabricator(:custom_emoji) do + shortcode 'coolcat' + domain nil + image { File.open(Rails.root.join('spec', 'fixtures', 'files', 'emojo.png')) } +end diff --git a/spec/fixtures/files/emojo.png b/spec/fixtures/files/emojo.png new file mode 100644 index 000000000..cb5993499 Binary files /dev/null and b/spec/fixtures/files/emojo.png differ diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index fcb044ebc..1a9520f04 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -17,6 +17,7 @@ RSpec.describe ActivityPub::Activity::Create do before do stub_request(:get, 'http://example.com/attachment.png').to_return(request_fixture('avatar.txt')) + stub_request(:get, 'http://example.com/emoji.png').to_return(body: attachment_fixture('emojo.png')) end describe '#perform' do @@ -217,5 +218,29 @@ RSpec.describe ActivityPub::Activity::Create do expect(status.tags.map(&:name)).to include('test') end end + + context 'with emojis' do + let(:object_json) do + { + id: 'bar', + type: 'Note', + content: 'Lorem ipsum :tinking:', + tag: [ + { + type: 'Emoji', + href: 'http://example.com/emoji.png', + name: 'tinking', + }, + ], + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.emojis.map(&:shortcode)).to include('tinking') + end + end end end diff --git a/spec/lib/formatter_spec.rb b/spec/lib/formatter_spec.rb index b714b317a..71b6b78d2 100644 --- a/spec/lib/formatter_spec.rb +++ b/spec/lib/formatter_spec.rb @@ -223,6 +223,45 @@ RSpec.describe Formatter do include_examples 'encode and link URLs' end + + context 'with custom_emojify option' do + let!(:emoji) { Fabricate(:custom_emoji) } + let(:status) { Fabricate(:status, account: local_account, text: text) } + + subject { Formatter.instance.format(status, custom_emojify: true) } + + context 'with emoji at the start' do + let(:text) { ':coolcat: Beep boop' } + + it 'converts shortcode to image tag' do + is_expected.to match(/

:coolcat::coolcat: Beep boop
' } + + it 'converts shortcode to image tag' do + is_expected.to match(/

:coolcat:Beep :coolcat: boop

' } + + it 'converts shortcode to image tag' do + is_expected.to match(/Beep :coolcat::coolcat::coolcat:

' } + + it 'does not touch the shortcodes' do + is_expected.to match(/

:coolcat::coolcat:<\/p>/) + end + end + + context 'with emoji at the end' do + let(:text) { '

Beep boop
:coolcat:

' } + + it 'converts shortcode to image tag' do + is_expected.to match(/
:coolcat:Hello :coolcat:

' } + + it 'returns records used via shortcodes in text' do + is_expected.to include(emojo) + end + end + end +end -- cgit From dd4ef69839c78e4220cd821bc3ad369eb6e41fa7 Mon Sep 17 00:00:00 2001 From: aschmitz Date: Fri, 22 Sep 2017 06:20:04 -0500 Subject: Hardcode IdToBigints migration columns (#5039) This addresses a comment during review: https://github.com/tootsuite/mastodon/pull/4801#discussion_r139337452 This means we'll need to make sure that all _id columns going forward are bigints, but that should happen automatically in most cases. --- db/migrate/20170918125918_ids_to_bigints.rb | 127 ++++++++++++++++++++++++++++ db/schema.rb | 122 +++++++++++++------------- 2 files changed, 188 insertions(+), 61 deletions(-) create mode 100644 db/migrate/20170918125918_ids_to_bigints.rb (limited to 'db/migrate') diff --git a/db/migrate/20170918125918_ids_to_bigints.rb b/db/migrate/20170918125918_ids_to_bigints.rb new file mode 100644 index 000000000..9c81ecc05 --- /dev/null +++ b/db/migrate/20170918125918_ids_to_bigints.rb @@ -0,0 +1,127 @@ +class IdsToBigints < ActiveRecord::Migration[5.1] + def up + change_column :account_domain_blocks, :account_id, :bigint + change_column :account_domain_blocks, :id, :bigint + change_column :accounts, :id, :bigint + change_column :blocks, :account_id, :bigint + change_column :blocks, :id, :bigint + change_column :blocks, :target_account_id, :bigint + change_column :conversation_mutes, :account_id, :bigint + change_column :conversation_mutes, :id, :bigint + change_column :deprecated_preview_cards, :id, :bigint + change_column :domain_blocks, :id, :bigint + change_column :favourites, :account_id, :bigint + change_column :favourites, :id, :bigint + change_column :favourites, :status_id, :bigint + change_column :follow_requests, :account_id, :bigint + change_column :follow_requests, :id, :bigint + change_column :follow_requests, :target_account_id, :bigint + change_column :follows, :account_id, :bigint + change_column :follows, :id, :bigint + change_column :follows, :target_account_id, :bigint + change_column :imports, :account_id, :bigint + change_column :imports, :id, :bigint + change_column :media_attachments, :account_id, :bigint + change_column :media_attachments, :id, :bigint + change_column :mentions, :account_id, :bigint + change_column :mentions, :id, :bigint + change_column :mutes, :account_id, :bigint + change_column :mutes, :id, :bigint + change_column :mutes, :target_account_id, :bigint + change_column :notifications, :account_id, :bigint + change_column :notifications, :from_account_id, :bigint + change_column :notifications, :id, :bigint + change_column :oauth_access_grants, :application_id, :bigint + change_column :oauth_access_grants, :id, :bigint + change_column :oauth_access_grants, :resource_owner_id, :bigint + change_column :oauth_access_tokens, :application_id, :bigint + change_column :oauth_access_tokens, :id, :bigint + change_column :oauth_access_tokens, :resource_owner_id, :bigint + change_column :oauth_applications, :id, :bigint + change_column :oauth_applications, :owner_id, :bigint + change_column :reports, :account_id, :bigint + change_column :reports, :action_taken_by_account_id, :bigint + change_column :reports, :id, :bigint + change_column :reports, :target_account_id, :bigint + change_column :session_activations, :access_token_id, :bigint + change_column :session_activations, :user_id, :bigint + change_column :session_activations, :web_push_subscription_id, :bigint + change_column :settings, :id, :bigint + change_column :settings, :thing_id, :bigint + change_column :statuses, :account_id, :bigint + change_column :statuses, :application_id, :bigint + change_column :statuses, :in_reply_to_account_id, :bigint + change_column :stream_entries, :account_id, :bigint + change_column :stream_entries, :id, :bigint + change_column :subscriptions, :account_id, :bigint + change_column :subscriptions, :id, :bigint + change_column :tags, :id, :bigint + change_column :users, :account_id, :bigint + change_column :users, :id, :bigint + change_column :web_settings, :id, :bigint + change_column :web_settings, :user_id, :bigint + end + + def down + change_column :account_domain_blocks, :account_id, :integer + change_column :account_domain_blocks, :id, :integer + change_column :accounts, :id, :integer + change_column :blocks, :account_id, :integer + change_column :blocks, :id, :integer + change_column :blocks, :target_account_id, :integer + change_column :conversation_mutes, :account_id, :integer + change_column :conversation_mutes, :id, :integer + change_column :deprecated_preview_cards, :id, :integer + change_column :domain_blocks, :id, :integer + change_column :favourites, :account_id, :integer + change_column :favourites, :id, :integer + change_column :favourites, :status_id, :integer + change_column :follow_requests, :account_id, :integer + change_column :follow_requests, :id, :integer + change_column :follow_requests, :target_account_id, :integer + change_column :follows, :account_id, :integer + change_column :follows, :id, :integer + change_column :follows, :target_account_id, :integer + change_column :imports, :account_id, :integer + change_column :imports, :id, :integer + change_column :media_attachments, :account_id, :integer + change_column :media_attachments, :id, :integer + change_column :mentions, :account_id, :integer + change_column :mentions, :id, :integer + change_column :mutes, :account_id, :integer + change_column :mutes, :id, :integer + change_column :mutes, :target_account_id, :integer + change_column :notifications, :account_id, :integer + change_column :notifications, :from_account_id, :integer + change_column :notifications, :id, :integer + change_column :oauth_access_grants, :application_id, :integer + change_column :oauth_access_grants, :id, :integer + change_column :oauth_access_grants, :resource_owner_id, :integer + change_column :oauth_access_tokens, :application_id, :integer + change_column :oauth_access_tokens, :id, :integer + change_column :oauth_access_tokens, :resource_owner_id, :integer + change_column :oauth_applications, :id, :integer + change_column :oauth_applications, :owner_id, :integer + change_column :reports, :account_id, :integer + change_column :reports, :action_taken_by_account_id, :integer + change_column :reports, :id, :integer + change_column :reports, :target_account_id, :integer + change_column :session_activations, :access_token_id, :integer + change_column :session_activations, :user_id, :integer + change_column :session_activations, :web_push_subscription_id, :integer + change_column :settings, :id, :integer + change_column :settings, :thing_id, :integer + change_column :statuses, :account_id, :integer + change_column :statuses, :application_id, :integer + change_column :statuses, :in_reply_to_account_id, :integer + change_column :stream_entries, :account_id, :integer + change_column :stream_entries, :id, :integer + change_column :subscriptions, :account_id, :integer + change_column :subscriptions, :id, :integer + change_column :tags, :id, :integer + change_column :users, :account_id, :integer + change_column :users, :id, :integer + change_column :web_settings, :id, :integer + change_column :web_settings, :user_id, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 9f42d46dd..cf4edf9e5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,20 +10,20 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170917153509) do +ActiveRecord::Schema.define(version: 20170918125918) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - create_table "account_domain_blocks", id: :serial, force: :cascade do |t| - t.integer "account_id" + create_table "account_domain_blocks", force: :cascade do |t| + t.bigint "account_id" t.string "domain" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["account_id", "domain"], name: "index_account_domain_blocks_on_account_id_and_domain", unique: true end - create_table "accounts", id: :serial, force: :cascade do |t| + create_table "accounts", force: :cascade do |t| t.string "username", default: "", null: false t.string "domain" t.string "secret", default: "", null: false @@ -68,16 +68,16 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.index ["username", "domain"], name: "index_accounts_on_username_and_domain", unique: true end - create_table "blocks", id: :serial, force: :cascade do |t| - t.integer "account_id", null: false - t.integer "target_account_id", null: false + create_table "blocks", force: :cascade do |t| + t.bigint "account_id", null: false + t.bigint "target_account_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["account_id", "target_account_id"], name: "index_blocks_on_account_id_and_target_account_id", unique: true end - create_table "conversation_mutes", id: :serial, force: :cascade do |t| - t.integer "account_id", null: false + create_table "conversation_mutes", force: :cascade do |t| + t.bigint "account_id", null: false t.bigint "conversation_id", null: false t.index ["account_id", "conversation_id"], name: "index_conversation_mutes_on_account_id_and_conversation_id", unique: true end @@ -101,7 +101,7 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.index ["shortcode", "domain"], name: "index_custom_emojis_on_shortcode_and_domain", unique: true end - create_table "domain_blocks", id: :serial, force: :cascade do |t| + create_table "domain_blocks", force: :cascade do |t| t.string "domain", default: "", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -110,9 +110,9 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.index ["domain"], name: "index_domain_blocks_on_domain", unique: true end - create_table "favourites", id: :serial, force: :cascade do |t| - t.integer "account_id", null: false - t.integer "status_id", null: false + create_table "favourites", force: :cascade do |t| + t.bigint "account_id", null: false + t.bigint "status_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["account_id", "id"], name: "index_favourites_on_account_id_and_id" @@ -120,24 +120,24 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.index ["status_id"], name: "index_favourites_on_status_id" end - create_table "follow_requests", id: :serial, force: :cascade do |t| - t.integer "account_id", null: false - t.integer "target_account_id", null: false + create_table "follow_requests", force: :cascade do |t| + t.bigint "account_id", null: false + t.bigint "target_account_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["account_id", "target_account_id"], name: "index_follow_requests_on_account_id_and_target_account_id", unique: true end - create_table "follows", id: :serial, force: :cascade do |t| - t.integer "account_id", null: false - t.integer "target_account_id", null: false + create_table "follows", force: :cascade do |t| + t.bigint "account_id", null: false + t.bigint "target_account_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["account_id", "target_account_id"], name: "index_follows_on_account_id_and_target_account_id", unique: true end - create_table "imports", id: :serial, force: :cascade do |t| - t.integer "account_id", null: false + create_table "imports", force: :cascade do |t| + t.bigint "account_id", null: false t.integer "type", null: false t.boolean "approved", default: false, null: false t.datetime "created_at", null: false @@ -148,14 +148,14 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.datetime "data_updated_at" end - create_table "media_attachments", id: :serial, force: :cascade do |t| + create_table "media_attachments", force: :cascade do |t| t.bigint "status_id" t.string "file_file_name" t.string "file_content_type" t.integer "file_file_size" t.datetime "file_updated_at" t.string "remote_url", default: "", null: false - t.integer "account_id" + t.bigint "account_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "shortcode" @@ -166,8 +166,8 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.index ["status_id"], name: "index_media_attachments_on_status_id" end - create_table "mentions", id: :serial, force: :cascade do |t| - t.integer "account_id" + create_table "mentions", force: :cascade do |t| + t.bigint "account_id" t.bigint "status_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -175,29 +175,29 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.index ["status_id"], name: "index_mentions_on_status_id" end - create_table "mutes", id: :serial, force: :cascade do |t| - t.integer "account_id", null: false - t.integer "target_account_id", null: false + create_table "mutes", force: :cascade do |t| + t.bigint "account_id", null: false + t.bigint "target_account_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["account_id", "target_account_id"], name: "index_mutes_on_account_id_and_target_account_id", unique: true end - create_table "notifications", id: :serial, force: :cascade do |t| - t.integer "account_id" + create_table "notifications", force: :cascade do |t| + t.bigint "account_id" t.bigint "activity_id" t.string "activity_type" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.integer "from_account_id" + t.bigint "from_account_id" t.index ["account_id", "activity_id", "activity_type"], name: "account_activity", unique: true t.index ["activity_id", "activity_type"], name: "index_notifications_on_activity_id_and_activity_type" t.index ["id", "account_id", "activity_type"], name: "index_notifications_on_id_and_account_id_and_activity_type", order: { id: :desc } end - create_table "oauth_access_grants", id: :serial, force: :cascade do |t| - t.integer "resource_owner_id", null: false - t.integer "application_id", null: false + create_table "oauth_access_grants", force: :cascade do |t| + t.bigint "resource_owner_id", null: false + t.bigint "application_id", null: false t.string "token", null: false t.integer "expires_in", null: false t.text "redirect_uri", null: false @@ -207,9 +207,9 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true end - create_table "oauth_access_tokens", id: :serial, force: :cascade do |t| - t.integer "resource_owner_id" - t.integer "application_id" + create_table "oauth_access_tokens", force: :cascade do |t| + t.bigint "resource_owner_id" + t.bigint "application_id" t.string "token", null: false t.string "refresh_token" t.integer "expires_in" @@ -221,7 +221,7 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true end - create_table "oauth_applications", id: :serial, force: :cascade do |t| + create_table "oauth_applications", force: :cascade do |t| t.string "name", null: false t.string "uid", null: false t.string "secret", null: false @@ -231,7 +231,7 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.datetime "updated_at" t.boolean "superapp", default: false, null: false t.string "website" - t.integer "owner_id" + t.bigint "owner_id" t.string "owner_type" t.index ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type" t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true @@ -264,37 +264,37 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.index ["status_id", "preview_card_id"], name: "index_preview_cards_statuses_on_status_id_and_preview_card_id" end - create_table "reports", id: :serial, force: :cascade do |t| - t.integer "account_id", null: false - t.integer "target_account_id", null: false + create_table "reports", force: :cascade do |t| + t.bigint "account_id", null: false + t.bigint "target_account_id", null: false t.bigint "status_ids", default: [], null: false, array: true t.text "comment", default: "", null: false t.boolean "action_taken", default: false, null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.integer "action_taken_by_account_id" + t.bigint "action_taken_by_account_id" t.index ["account_id"], name: "index_reports_on_account_id" t.index ["target_account_id"], name: "index_reports_on_target_account_id" end create_table "session_activations", force: :cascade do |t| - t.integer "user_id", null: false + t.bigint "user_id", null: false t.string "session_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "user_agent", default: "", null: false t.inet "ip" - t.integer "access_token_id" - t.integer "web_push_subscription_id" + t.bigint "access_token_id" + t.bigint "web_push_subscription_id" t.index ["session_id"], name: "index_session_activations_on_session_id", unique: true t.index ["user_id"], name: "index_session_activations_on_user_id" end - create_table "settings", id: :serial, force: :cascade do |t| + create_table "settings", force: :cascade do |t| t.string "var", null: false t.text "value" t.string "thing_type" - t.integer "thing_id" + t.bigint "thing_id" t.datetime "created_at" t.datetime "updated_at" t.index ["thing_type", "thing_id", "var"], name: "index_settings_on_thing_type_and_thing_id_and_var", unique: true @@ -322,7 +322,7 @@ ActiveRecord::Schema.define(version: 20170917153509) do create_table "statuses", force: :cascade do |t| t.string "uri" - t.integer "account_id", null: false + t.bigint "account_id", null: false t.text "text", default: "", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -331,8 +331,8 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.string "url" t.boolean "sensitive", default: false, null: false t.integer "visibility", default: 0, null: false - t.integer "in_reply_to_account_id" - t.integer "application_id" + t.bigint "in_reply_to_account_id" + t.bigint "application_id" t.text "spoiler_text", default: "", null: false t.boolean "reply", default: false, null: false t.integer "favourites_count", default: 0, null: false @@ -349,13 +349,13 @@ ActiveRecord::Schema.define(version: 20170917153509) do create_table "statuses_tags", id: false, force: :cascade do |t| t.bigint "status_id", null: false - t.integer "tag_id", null: false + t.bigint "tag_id", null: false t.index ["status_id"], name: "index_statuses_tags_on_status_id" t.index ["tag_id", "status_id"], name: "index_statuses_tags_on_tag_id_and_status_id", unique: true end - create_table "stream_entries", id: :serial, force: :cascade do |t| - t.integer "account_id" + create_table "stream_entries", force: :cascade do |t| + t.bigint "account_id" t.bigint "activity_id" t.string "activity_type" t.datetime "created_at", null: false @@ -365,12 +365,12 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.index ["activity_id", "activity_type"], name: "index_stream_entries_on_activity_id_and_activity_type" end - create_table "subscriptions", id: :serial, force: :cascade do |t| + create_table "subscriptions", force: :cascade do |t| t.string "callback_url", default: "", null: false t.string "secret" t.datetime "expires_at" t.boolean "confirmed", default: false, null: false - t.integer "account_id", null: false + t.bigint "account_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.datetime "last_successful_delivery_at" @@ -378,7 +378,7 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.index ["account_id", "callback_url"], name: "index_subscriptions_on_account_id_and_callback_url", unique: true end - create_table "tags", id: :serial, force: :cascade do |t| + create_table "tags", force: :cascade do |t| t.string "name", default: "", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -386,9 +386,9 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.index ["name"], name: "index_tags_on_name", unique: true end - create_table "users", id: :serial, force: :cascade do |t| + create_table "users", force: :cascade do |t| t.string "email", default: "", null: false - t.integer "account_id", null: false + t.bigint "account_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "encrypted_password", default: "", null: false @@ -430,8 +430,8 @@ ActiveRecord::Schema.define(version: 20170917153509) do t.datetime "updated_at", null: false end - create_table "web_settings", id: :serial, force: :cascade do |t| - t.integer "user_id" + create_table "web_settings", force: :cascade do |t| + t.bigint "user_id" t.json "data" t.datetime "created_at", null: false t.datetime "updated_at", null: false -- cgit From dcfc9b220462533c8bcdebc7ca25a68fa23aaf5f Mon Sep 17 00:00:00 2001 From: nullkal Date: Sat, 23 Sep 2017 02:32:57 +0900 Subject: Fix the migration error when deprecated_preview_cards has been deleted (#5043) * Fix the migration error when deprecated_preview_cards has deleted * Re-run Travis CI --- db/migrate/20170918125918_ids_to_bigints.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'db/migrate') diff --git a/db/migrate/20170918125918_ids_to_bigints.rb b/db/migrate/20170918125918_ids_to_bigints.rb index 9c81ecc05..7483dd77a 100644 --- a/db/migrate/20170918125918_ids_to_bigints.rb +++ b/db/migrate/20170918125918_ids_to_bigints.rb @@ -8,7 +8,7 @@ class IdsToBigints < ActiveRecord::Migration[5.1] change_column :blocks, :target_account_id, :bigint change_column :conversation_mutes, :account_id, :bigint change_column :conversation_mutes, :id, :bigint - change_column :deprecated_preview_cards, :id, :bigint + change_column :deprecated_preview_cards, :id, :bigint if table_exists?(:deprecated_preview_cards) change_column :domain_blocks, :id, :bigint change_column :favourites, :account_id, :bigint change_column :favourites, :id, :bigint @@ -71,7 +71,7 @@ class IdsToBigints < ActiveRecord::Migration[5.1] change_column :blocks, :target_account_id, :integer change_column :conversation_mutes, :account_id, :integer change_column :conversation_mutes, :id, :integer - change_column :deprecated_preview_cards, :id, :integer + change_column :deprecated_preview_cards, :id, :integer if table_exists?(:deprecated_preview_cards) change_column :domain_blocks, :id, :integer change_column :favourites, :account_id, :integer change_column :favourites, :id, :integer -- cgit From b2820c3913266711716c6d91b2198d964881dbba Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 24 Sep 2017 05:58:07 +0200 Subject: Forgotten in #5039, change statuses_tags tag_id to bigint (#5070) --- db/migrate/20170924022025_ids_to_bigints2.rb | 9 +++++++++ db/schema.rb | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20170924022025_ids_to_bigints2.rb (limited to 'db/migrate') diff --git a/db/migrate/20170924022025_ids_to_bigints2.rb b/db/migrate/20170924022025_ids_to_bigints2.rb new file mode 100644 index 000000000..db8ccd919 --- /dev/null +++ b/db/migrate/20170924022025_ids_to_bigints2.rb @@ -0,0 +1,9 @@ +class IdsToBigints2 < ActiveRecord::Migration[5.1] + def up + change_column :statuses_tags, :tag_id, :bigint + end + + def down + change_column :statuses_tags, :tag_id, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index cf4edf9e5..e16599d32 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170918125918) do +ActiveRecord::Schema.define(version: 20170924022025) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" -- cgit