# frozen_string_literal: true # client-server post '/' do # TODO protected! recipients = public recipients << params[:to] content = [] attachment = [] tag = [] extensions = { image: %w[jpeg png], audio: %w[flac wav mp3 ogg], video: %w[mp4 webm] } params[:content].lines.each do |line| line.chomp! if line.match(/^http/) ext = File.extname(line).sub('.', '') media_type = extensions.select { |_k, v| v.include? ext }.keys[0].to_s + '/' + ext attachment << { 'type' => 'Document', 'mediaType' => media_type, 'url' => line } else tags = line.split(/\s+/).grep(/^#\w+$/) tags.each do |name| # href = File.join(TAGS_URL, name.sub('#', '')) tag_url = File.join(TAGS_URL, name.sub('#', '')) tag << { 'type' => 'Hashtag', 'href' => tag_url, 'name' => name } end mentions = line.split(/\s+/).grep(/^@\w+@\S+$/) mentions.each do |mention| actor = actor(mention) tag << { 'type' => 'Mention', 'href' => actor, 'name' => mention } end content << line end end object = { 'type' => 'Note', 'attributedTo' => ACTOR, 'inReplyTo' => params[:inReplyTo], 'content' => "

\n#{content.join("\n
")}\n

", 'attachment' => attachment, 'tag' => tag, 'to' => recipients } activity = outbox 'Create', object, recipients, true activity['object']['tag'].each do |tag| next unless tag['type'] == 'Hashtag' tag_path = File.join(TAGS_DIR, tag['name'].sub('#', '')) + '.json' unless File.exist? tag_path File.open(tag_path, 'w+') do |f| tag_collection = { '@context' => 'https://www.w3.org/ns/activitystreams', 'id' => tag['href'], 'type' => 'OrderedCollection', 'totalItems' => 0, 'orderedItems' => [] } f.puts tag_collection.to_json end end update_collection tag_path, activity['object']['id'] end redirect(params['anchor'] || '/inbox') end post '/delete' do protected! collection = Kernel.const_get(params['dir'].upcase) if params['id'] update_collection collection, params, true else update_collection collection, JSON.parse(File.read(collection))['orderedItems'], true end redirect(params['anchor'] || '/inbox') end post '/follow' do protected! actor, = parse_follow params['follow'] outbox 'Follow', actor, [actor] redirect(params['anchor'] || '/inbox') end post '/unfollow' do protected! actor, mention = parse_follow params['follow'] Dir[File.join(OUTBOX_DIR, 'follow', '*.json')].each do |f| activity = JSON.parse(File.read(f)) if activity['object'] == actor outbox 'Undo', activity, [actor] update_collection FOLLOWING, actor, true end end redirect(params['anchor'] || '/inbox') end post '/share' do # TODO protected! # inbox = JSON.parse File.read(INBOX) # object = inbox['orderedItems'].find { |i| i['id'] == params['id'] } # update_collection SHARED, object # update_collection INBOX, object, true recipients = public recipients << object['attributedTo'] outbox 'Announce', params['id'], recipients redirect(params['anchor'] || '/inbox') end post '/login' do session['client'] = (OpenSSL::Digest::SHA256.base64digest(params['secret']) == File.read('.digest').chomp) redirect '/inbox' end get '/' do protected! redirect '/inbox' end ['/inbox', '/outbox'].each do |path| get path, provides: 'html' do protected! @box = path.sub('/', '') collection = Dir[File.join(@box, 'object', '*', '*.json')].collect { |f| JSON.parse(File.read(f)) } @threads = [] collection.collect! do |object| object = fetch(object) if object.is_a?(String) && object.match(/^http/) object end collection.each do |object| object['replies'] = [] @threads << object if object['inReplyTo'].nil? || collection.select { |o| o['id'] == object['inReplyTo'] }.empty? end collection.each do |object| collection.select { |o| o['id'] == object['inReplyTo'] }.each do |o| o['replies'] << object end end @threads.sort_by! { |t| t['published'] } erb :collection end end helpers do def protected! halt 403 unless session['client'] end def selection(params) selection = Dir[File.join(SOCIAL_DIR, params['dir'], '*', '*.json')] params['id'] ? selection.select { |f| JSON.parse(File.read(f))['id'] == params['id'] } : selection end def public recipients = ['https://www.w3.org/ns/activitystreams#Public'] recipients += Dir[File.join(FOLLOWERS, '*.json')].collect { |f| JSON.parse(File.read(f))['actor'] } recipients.delete ACTOR recipients.uniq end def parse_follow(follow) case follow when /^#/ actor = "https://relay.fedi.buzz/tag/#{follow.sub(/^#/, '')}" mention = follow when /^http/ actor = follow mention = mention(actor) when /^@*\w+@\w+/ mention = follow actor = actor(follow) return 502 unless actor end [actor, mention] end end