about summary refs log tree commit diff
path: root/app/helpers/blocklist_helper.rb
blob: 7437ccf37a5a3fbabdfdafc191a95c0a8c8adb87 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
module BlocklistHelper
  FEDIVERSE_SPACE_URLS = ["https://fediverse.network/mastodon?build=gab"]
  VULPINE_CLUB_URL = "https://raw.githubusercontent.com/vulpineclub/vulpineclub.github.io/master/_data/blocks.yml"

  def merged_blocklist
    # ordered by preference
    # prefer vulpine b/c they have easy-to-parse reason text
    blocklist = vulpine_club_blocks | dialup_express_blocks | ten_forward_blocks | fediverse_space_blocks
    blocklist.uniq { |entry| entry[:domain] }
  end

  def domain_map(domains, reason)
    domains.map! do |domain|
      {domain: domain, severity: :suspend, reason: reason}
    end
  end

  def dialup_express_blocks
    admin_id = Account.find_remote('xenon', 'sleeping.town')&.id
    return [] if admin_id.nil?

    domains = ActiveRecord::Base.connection.select_values("SELECT unnest(regexp_matches(text, '\\m[\\w\\-]+\\.[\\w\-]+(?:\\.[\\w\\-]+)*', 'g')) FROM statuses WHERE account_id = #{admin_id.to_i} AND NOT reply AND created_at >= (NOW() - INTERVAL '2 days') AND tsv @@ to_tsquery('new <-> dialup <-> express <2> block') EXCEPT SELECT domain FROM domain_blocks")

    domain_map(domains, "Imported from <https://dialup.express>.")
  end

  def ten_forward_blocks
    admin_id = Account.find_remote('guinan', 'tenforward.social')&.id
    return [] if admin_id.nil?

    domains = ActiveRecord::Base.connection.select_values("SELECT unnest(regexp_matches(text, '\\m[\\w\\-]+\\.[\\w\-]+(?:\\.[\\w\\-]+)*', 'g')) FROM statuses WHERE account_id = #{admin_id.to_i} AND NOT reply AND created_at >= (NOW() - INTERVAL '2 days') AND tsv @@ to_tsquery('ten <-> forward <-> moderation <-> announcement') EXCEPT SELECT domain FROM domain_blocks")

    domain_map(domains, "Imported from <https://ten.forward>.")
  end

  def vulpine_club_blocks
    body = Request.new(:get, VULPINE_CLUB_URL).perform do |response|
      response.code != 200 ? nil : response.body_with_limit(66.kilobytes)
    end

    return [] unless body.present?

    yaml = YAML::load(body)
    yaml.map! do |entry|
      domain = entry['domain']
      next if domain.blank?
      severity = entry['severity'].split('/')
      reject_media = 'nomedia'.in?(severity)
      severity = (severity[0].nil? || severity[0] == 'nomedia') ? 'noop' : severity[0]

      reason = "Imported from <https://vulpine.club>: \"#{entry['reason']}\"#{entry['link'].present? ? " (#{entry['link']})" : ''}".rstrip
      {domain: domain, severity: severity.to_sym, reject_media: reject_media, reason: reason}
    end
  end

  # shamelessly adapted from @zac@computerfox.xyz's `silence` tool
  # <https://github.com/theZacAttacks/silence/blob/master/silence>
  # which you'll find useful if you're a non-monsterfork mastoadmin
  def fediverse_space_fetch_domains(url)
    body = Request.new(:get, url).perform do |response|
      response.code != 200 ? nil : response.body_with_limit(66.kilobytes)
    end

    return [] unless body.present?

    document = Nokogiri::HTML(body)
    document.css('table.table-condensed td a').collect { |link| link.content.strip }
  end

  def fediverse_space_blocks
    domains = FEDIVERSE_SPACE_URLS.flat_map { |url| fediverse_space_fetch_domains(url) }
    domains.uniq!

    domain_map(domains, "Imported from <https://fediverse.space>.")
  end
end