Ruby gem for ingesting ATProto repo data from a Tap service (extension of Skyfall gem)
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

adding/removing repos

+116
+73
lib/tapfall/api.rb
··· 1 + require 'json' 2 + require 'net/http' 3 + require 'uri' 4 + 5 + module Tapfall 6 + class API 7 + def initialize(server) 8 + @root_url = build_root_url(server) 9 + end 10 + 11 + def add_repo(did) 12 + add_repos([did]) 13 + end 14 + 15 + def add_repos(dids) 16 + post_request('/repos/add', { dids: dids }) 17 + end 18 + 19 + def remove_repo(did) 20 + remove_repos([did]) 21 + end 22 + 23 + def remove_repos(dids) 24 + post_request('/repos/remove', { dids: dids }) 25 + end 26 + 27 + private 28 + 29 + def build_root_url(server) 30 + if !server.is_a?(String) 31 + raise ArgumentError, "Server parameter should be a string" 32 + end 33 + 34 + if server.include?('://') 35 + uri = URI(server) 36 + 37 + if uri.scheme != 'http' && uri.scheme != 'https' 38 + raise ArgumentError, "Server parameter should be a hostname or a http:// or https:// URL" 39 + elsif uri.path != '' 40 + raise ArgumentError, "Server URL should only include a hostname, without path" 41 + end 42 + 43 + uri.to_s 44 + else 45 + server = "https://#{server}" 46 + uri = URI(server) # raises if invalid 47 + server 48 + end 49 + end 50 + 51 + def post_request(path, json_data) 52 + uri = URI(@root_url + path) 53 + 54 + request = Net::HTTP::Post.new(uri) 55 + request.body = JSON.generate(json_data) 56 + request.content_type = "application/json" 57 + 58 + response = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => (uri.scheme == 'https')) do |http| 59 + http.request(request) 60 + end 61 + 62 + status = response.code.to_i 63 + message = response.message 64 + response_body = (response.content_type == 'application/json') ? JSON.parse(response.body) : response.body 65 + 66 + if response.is_a?(Net::HTTPSuccess) 67 + response_body 68 + else 69 + raise BadResponseError.new(status, message, response_body) 70 + end 71 + end 72 + end 73 + end
+25
lib/tapfall/errors.rb
··· 1 1 module Tapfall 2 + class BadResponseError < StandardError 3 + attr_reader :status, :data 4 + 5 + def initialize(status, status_message, data) 6 + @status = status 7 + @data = data 8 + 9 + message = if error_message 10 + "#{status} #{status_message}: #{error_message}" 11 + else 12 + "#{status} #{status_message}" 13 + end 14 + 15 + super(message) 16 + end 17 + 18 + def error_type 19 + @data['error'] if @data.is_a?(Hash) 20 + end 21 + 22 + def error_message 23 + @data['message'] if @data.is_a?(Hash) 24 + end 25 + end 26 + 2 27 class ConfigError < StandardError 3 28 end 4 29
+18
lib/tapfall/stream.rb
··· 1 + require 'forwardable' 1 2 require 'skyfall/stream' 3 + 4 + require_relative 'api' 5 + require_relative 'errors' 2 6 require_relative 'messages/tap_message' 3 7 require_relative 'version' 4 8 5 9 module Tapfall 6 10 class Tapfall::Stream < Skyfall::Stream 11 + extend Forwardable 12 + 13 + def_delegators :@api, :add_repo, :add_repos, :remove_repo, :remove_repos 14 + 7 15 def initialize(server, options = {}) 8 16 super(server) 9 17 10 18 @options = options 11 19 @root_url = ensure_empty_path(@root_url) 12 20 @ack = true unless options[:ack] == false 21 + 22 + @api = API.new(build_api_url) 13 23 end 14 24 15 25 def connect ··· 40 50 41 51 def build_websocket_url 42 52 @root_url + "/channel" 53 + end 54 + 55 + def build_api_url 56 + if @root_url.start_with?('ws://') 57 + @root_url.gsub(/^ws:/, 'http:') 58 + else 59 + @root_url.gsub(/^wss:/, 'https:') 60 + end 43 61 end 44 62 end 45 63 end