Skip to content

Instantly share code, notes, and snippets.

View mackuba's full-sized avatar
🦋
Building things for Bluesky with ATProto

Kuba Suder mackuba

🦋
Building things for Bluesky with ATProto
View GitHub Profile
@mackuba
mackuba / bsky_user_stats_home.rb
Created January 23, 2025 20:23
Script to print statistics of your home timeline - how much each followed user contributes to it on average
#!/usr/bin/env ruby
require 'time'
require 'yaml'
['minisky', 'didkit'].each do |lib|
begin
require(lib)
rescue LoadError
puts "Install #{lib}: '[sudo] gem install #{lib}'"
@mackuba
mackuba / bsky_silence_notifs.js
Last active January 21, 2025 20:18
Bluesky browser bookmarklet to silence notifications in the sidebar (and on the arrow-up button)
/* Create a bookmark and copy-paste this whole line as the URL: */
javascript:(function(){s=document.getElementById('disable_notif_style');if(s){s.remove()}else{s=document.createElement('style');s.id='disable_notif_style';s.innerText='nav[role=navigation] a[aria-label="Notifications"] { opacity: 0.33 !important; } nav[role=navigation] div[aria-label*="unread item"], button[aria-label^="Load new"] svg + div[style*="border-color"] { display: none; }';document.head.appendChild(s);}})()
/* Expanded code: */
function toggleNotifications() {
let s = document.getElementById('disable_notif_style');
if (s) {
@mackuba
mackuba / follow_hashtag.rb
Created October 24, 2024 01:18
Script for following hashtags for my hashtag feed
#!/usr/bin/env ruby
# make sure you have Ruby installed, should be installed by default on macOS & Linux
# install Minisky lib with: [sudo] gem install minisky
# then run with: ruby follow_hashtag.rb somehashtag
require 'minisky'
if !File.exist?('config.yml')
puts "Create a config.yml file with contents like this:"
@mackuba
mackuba / bsky_user_stats.rb
Created September 6, 2024 22:40
Script to check how much given Bluesky users post daily on average
#!/usr/bin/env ruby
begin
require 'minisky'
rescue LoadError
puts "Install minisky: '[sudo] gem install minisky'"
exit 1
end
require 'time'
@mackuba
mackuba / delete_list_items.rb
Created July 4, 2024 14:14
Script for deleting all items from a list (even if the list itself was deleted)
#!/usr/bin/env ruby
# to install minisky: `gem install minisky`
require 'minisky'
list_id = ARGV[0]
if list_id.nil?
puts "Usage: #{$PROGRAM_NAME} <list_rkey>"
@mackuba
mackuba / munin-cgi.service
Created June 4, 2024 23:06
Munin CGI configuration to allow zooming in charts
[Unit]
Description=Munin graph CGI
After=network.target syslog.target
[Service]
Type=simple
User=root
ExecStart=/usr/bin/spawn-fcgi -n -s /var/run/munin/fastcgi-graph.sock -u www-data /usr/lib/munin/cgi/munin-cgi-graph
TimeoutSec=15
Restart=on-failure
@mackuba
mackuba / joes_bridgy.rb
Created May 22, 2024 21:53
Find Joe's follows who opted in to Bridgy
#!/usr/bin/env ruby
## gem install minisky
require 'minisky'
sky = Minisky.new('api.bsky.app', nil, progress: '.')
joe_follows = sky.fetch_all('app.bsky.graph.getFollows', { actor: 'mergesort.me', limit: 100 }, field: 'follows')
ap_followers = sky.fetch_all('app.bsky.graph.getFollowers', { actor: 'ap.brid.gy', limit: 100 }, field: 'followers')
@mackuba
mackuba / bluesky_events
Last active January 28, 2024 22:09
Munin configuration files
#!/bin/sh
if [ "$1" = "config" ]; then
echo "graph_title Bluesky firehose events"
echo "graph_category bluesky"
echo "graph_vlabel Events per second"
echo "graph_args --base 1000 -l 0"
echo "events.label Events"
echo "events.type DERIVE"
echo "events.min 0"
@mackuba
mackuba / firehose.rake
Created January 4, 2024 15:46
Downloading bsky firehose events to a file and streaming them from a mock server
require 'skyfall'
AVG_EVENTS_PER_SEC = 50
desc "Download a part of the firehose cache to a file"
task :fetch do
current_head = nil
sky = Skyfall::Stream.new(ENV['FIREHOSE'] || 'bsky.network', :subscribe_repos)
sky.on_message do |m|
@mackuba
mackuba / proper_way.rb
Created November 11, 2023 23:45
Bluesky login with federation
# "proper" way, more future- and federation-proof
handle = form.get('handle')
password = form.get('password')
if dns_record = lookup_dns("_atproto.#{handle}")
did = did_from_dns(dns_record)
elsif res = open_url("https://#{handle}/.well-known/atproto-did")
did = did_from_well_known(res)
else