diff options
Diffstat (limited to 'app/lib')
-rw-r--r-- | app/lib/application_extension.rb | 9 | ||||
-rw-r--r-- | app/lib/feed_manager.rb | 10 | ||||
-rw-r--r-- | app/lib/formatter.rb | 15 | ||||
-rw-r--r-- | app/lib/hash_object.rb | 10 | ||||
-rw-r--r-- | app/lib/settings/extend.rb | 11 | ||||
-rw-r--r-- | app/lib/settings/scoped_settings.rb | 14 | ||||
-rw-r--r-- | app/lib/status_length_validator.rb | 10 | ||||
-rw-r--r-- | app/lib/url_validator.rb | 14 |
8 files changed, 90 insertions, 3 deletions
diff --git a/app/lib/application_extension.rb b/app/lib/application_extension.rb new file mode 100644 index 000000000..93c0f42f0 --- /dev/null +++ b/app/lib/application_extension.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module ApplicationExtension + extend ActiveSupport::Concern + + included do + validates :website, url: true, unless: 'website.blank?' + end +end diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 0056321fa..cdd26e69c 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -43,12 +43,22 @@ class FeedManager timeline_key = key(:home, into_account.id) from_account.statuses.limit(MAX_ITEMS).each do |status| + next if filter?(:home, status, into_account) redis.zadd(timeline_key, status.id, status.id) end trim(:home, into_account.id) end + def unmerge_from_timeline(from_account, into_account) + timeline_key = key(:home, into_account.id) + + from_account.statuses.select('id').find_each do |status| + redis.zrem(timeline_key, status.id) + redis.zremrangebyscore(timeline_key, status.id, status.id) + end + end + def inline_render(target_account, template, object) rabl_scope = Class.new do include RoutingHelper diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index 04386d295..ff2a16f1b 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -14,7 +14,7 @@ class Formatter html = status.text html = encode(html) - html = simple_format(html, sanitize: false) + html = simple_format(html, {}, sanitize: false) html = html.gsub(/\n/, '') html = link_urls(html) html = link_mentions(html, status.mentions) @@ -32,6 +32,7 @@ class Formatter html = encode(account.note) html = link_urls(html) + html = link_hashtags(html) html.html_safe # rubocop:disable Rails/OutputSafety end @@ -43,8 +44,8 @@ class Formatter end def link_urls(html) - auto_link(html, link: :urls, html: { rel: 'nofollow noopener', target: '_blank' }) do |text| - truncate(text.gsub(/\Ahttps?:\/\/(www\.)?/, ''), length: 30) + html.gsub(URI.regexp(%w(http https))) do |match| + link_html(match) end end @@ -63,6 +64,14 @@ class Formatter end end + def link_html(url) + prefix = url.match(/\Ahttps?:\/\/(www\.)?/).to_s + text = url[prefix.length, 30] + suffix = url[prefix.length + 30..-1] + + "<a rel=\"nofollow noopener\" target=\"_blank\" href=\"#{url}\"><span class=\"invisible\">#{prefix}</span><span class=\"ellipsis\">#{text}</span><span class=\"invisible\">#{suffix}</span></a>" + end + def hashtag_html(match) prefix, affix = match.split('#') "#{prefix}<a href=\"#{tag_url(affix.downcase)}\" class=\"mention hashtag\">#<span>#{affix}</span></a>" diff --git a/app/lib/hash_object.rb b/app/lib/hash_object.rb new file mode 100644 index 000000000..274c020ad --- /dev/null +++ b/app/lib/hash_object.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class HashObject + def initialize(hash) + hash.each do |k, v| + instance_variable_set("@#{k}", v) + self.class.send(:define_method, k, proc { instance_variable_get("@#{k}") }) + end + end +end diff --git a/app/lib/settings/extend.rb b/app/lib/settings/extend.rb new file mode 100644 index 000000000..407c3480f --- /dev/null +++ b/app/lib/settings/extend.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Settings + module Extend + extend ActiveSupport::Concern + + def settings + ScopedSettings.for_thing(self) + end + end +end diff --git a/app/lib/settings/scoped_settings.rb b/app/lib/settings/scoped_settings.rb new file mode 100644 index 000000000..82b70d128 --- /dev/null +++ b/app/lib/settings/scoped_settings.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Settings + class ScopedSettings < ::Setting + def self.for_thing(object) + @object = object + self + end + + def self.thing_scoped + unscoped.where(thing_type: @object.class.base_class.to_s, thing_id: @object.id) + end + end +end diff --git a/app/lib/status_length_validator.rb b/app/lib/status_length_validator.rb new file mode 100644 index 000000000..55135a598 --- /dev/null +++ b/app/lib/status_length_validator.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class StatusLengthValidator < ActiveModel::Validator + MAX_CHARS = 500 + + def validate(status) + return unless status.local? && !status.reblog? + status.errors.add(:text, I18n.t('statuses.over_character_limit', max: MAX_CHARS)) if [status.text, status.spoiler_text].join.length > MAX_CHARS + end +end diff --git a/app/lib/url_validator.rb b/app/lib/url_validator.rb new file mode 100644 index 000000000..4a5c4ef3f --- /dev/null +++ b/app/lib/url_validator.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class UrlValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + record.errors.add(attribute, I18n.t('applications.invalid_url')) unless compliant?(value) + end + + private + + def compliant?(url) + parsed_url = Addressable::URI.parse(url) + !parsed_url.nil? && %w(http https).include?(parsed_url.scheme) && parsed_url.host + end +end |