#!/usr/bin/env ruby # Example: show 10 most recent issues in a Tangled repo. # # Tangled is a git hosting site (GitHub alternative) built on the AT Protocol. require 'bundler/setup' require 'didkit' require 'minisky' $url = ARGV[0] if $url.nil? puts "Usage: #{$PROGRAM_NAME} https://tangled.org/user.handle/repo-name" exit 1 elsif !$url.start_with?('https://tangled.org/') puts "Invalid Tangled URL: #{$url.inspect}" exit 1 end # try e.g.: # https://tangled.org/microcosm.blue/microcosm-rs # https://tangled.org/nonbinary.computer/jacquard # https://tangled.org/tangled.org/core # first, let's convert the URL to an at:// URI handle, repo_name = $url.split('/')[3..4] did = DID.resolve_handle(handle) if did.nil? puts "User not found: #{handle}" exit 1 end # let's search the user's PDS repo for "Tangled repo" records pds = did.document.pds_host all_repos = Minisky.new(pds, nil).fetch_all('com.atproto.repo.listRecords', { repo: did, collection: 'sh.tangled.repo', limit: 100 }, field: 'records') selected_repo = all_repos.detect { |x| x['value']['name'] == repo_name } if selected_repo.nil? puts "Repo not found: #{handle}/#{repo_name}" exit 1 end repo_uri = selected_repo['uri'] # Now, we want to list all issues reported on this Tangled repo. # # The problem is, an issue record is saved on the PDS of the reporting person, so # the issues connected to a given Tangled repo can be spread across many different # PDSes and ATProto repos - kind of like the follow records of your Bluesky # followers are spread across many ATProto repos. # # But unlike follow records, we can't use the Bluesky AppView to look up those, # because the Bluesky AppView doesn't track non-Bluesky data like Tangled or # Leaflet records! # # Instead, we'll use a service called Constellation, part of an independent # "Microcosm" project. It collects "backlinks" for all records on the network, # i.e. all links to a given URI from other records, and lets you search for them. constellation = Minisky.new('constellation.microcosm.blue', nil) # look up all backlinks to the repo's at-URI from 'sh.tangled.repo.issue' records: issues = constellation.get_request('blue.microcosm.links.getBacklinks', { subject: repo_uri, source: 'sh.tangled.repo.issue:repo', limit: 10 })['records'] # the backlinks are returned as did + collection + rkey # now, for each issue, take those and look up the record on the relevant PDS: issues.each do |i| repo, collection, rkey = i.values_at('did', 'collection', 'rkey') did = DID.new(repo) author_pds = did.document.pds_host record = Minisky.new(author_pds, nil).get_request('com.atproto.repo.getRecord', { repo: repo, collection: collection, rkey: rkey }) handle = did.document.handles.first time = Time.parse(record['value']['createdAt']) puts "#{time} (@#{handle})" p record['value']['title'] puts body = record['value']['body'] lines = body.lines if lines.length > 5 body = lines[0...5].join + "(...)" end puts body puts puts '-' * 60 puts end