# frozen_string_literal: true # client-server post '/' do # TODO protected! Time.now.strftime('%Y-%m-%dT%H:%M:%S.%N') 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(SOCIAL_URL, 'tags', name.sub('#', '')) tag << { 'type' => 'Hashtag', 'href' => href, 'name' => name } line.gsub!(name, "") 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 } outbox 'Create', object, recipients, true 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! selection(params).each { |f| FileUtils.mv f, f.sub(%r{/inbox/}, '/shared/') } outbox 'Announce', params['id'], public 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', '/shared', '/outbox'].each do |path| get path, provides: 'html' do protected! @dir = path.sub('/', '') collection = JSON.parse(File.read(Kernel.const_get(@dir.upcase)))['orderedItems'].uniq @threads = [] collection.each do |object| object['indent'] = 0 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| object['indent'] = o['indent'] + 2 o['replies'] << object end end 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