tangled_issue_tracker.rb
Example: show 10 most recent issues in a Tangled repo.
Tangled is a git hosting site (GitHub alternative) built on the AT Protocol.
rb
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