namespace eval feed {
proc ::feed::serve_skeleton {feeds publisher _ sock path query headers} {
if ![dict exists $query feed] {
puts $sock "HTTP/1.0 400 Bad Request"
puts $sock "Content-Type: text/plain"
puts $sock ""
puts $sock "Missing 'feed' query parameter."
puts $sock ""
close $sock
return
}
if ![dict exists $query cursor] {
dict set query cursor 0
}
if ![dict exists $query limit] {
dict set query limit 50
}
if [catch {
set feed [dict get $query feed]
set cursor [expr {max(0, [dict get $query cursor])}]
set limit [expr {max(1, min(100, [dict get $query limit]))}]
}] {
puts $sock "HTTP/1.0 400 Bad Request"
puts $sock "Content-Type: text/plain"
puts $sock ""
puts $sock "Check your parameter syntax, IDK."
puts $sock ""
close $sock
return
}
set feed [::at::uri $feed]
if {[llength $feed] != 6 ||
[dict get $feed authority] != $publisher ||
[dict get $feed collection] != "app.bsky.feed.generator"} {
puts $sock "HTTP/1.0 400 Bad Request"
puts $sock "Content-Type: text/plain"
puts $sock ""
puts $sock "Invalid at:// URI."
puts $sock ""
close $sock
return
}
set feed [dict get $feed rkey]
if {[lsearch -exact $feeds $feed] == -1} {
puts $sock "HTTP/1.0 404 Not Found"
puts $sock "Content-Type: text/plain"
puts $sock ""
puts $sock "Not a feed."
puts $sock ""
close $sock
return
}
set feed_data {}
foreach uri [db eval "SELECT uri FROM $feed ORDER BY ord DESC LIMIT $limit OFFSET $cursor;"] {
lappend feed_data [::json::write object \
post [::json::write string $uri]]
}
set feed_data_arr [::json::write array {*}$feed_data]
set feed_contents [::json::write object \
cursor [expr {$cursor + min([llength $feed_data], $limit)}] \
feed $feed_data_arr]
puts $sock "HTTP/1.0 200 OK"
puts $sock "Content-Type: application/json"
puts $sock "Content-Length: [string length $feed_contents]"
puts $sock ""
fconfigure $sock -translation binary
puts -nonewline $sock $feed_contents
close $sock
return
}
proc ::feed::generator_description {feeds publisher self_host} {
set feed_uris {}
foreach feed $feeds {
lappend feed_uris [::json::write object \
uri [::json::write string "at://$publisher/app.bsky.feed.generator/$feed"]]
}
set feed_uris [::json::write array {*}$feed_uris]
set description [::json::write object \
did [::json::write string "did:web:$self_host"] \
feeds $feed_uris]
return $description
}
proc ::feed::well_known {feeds self_host} {
::json::write object \
@context {["https://www.w3.org/ns/did/v1"]} \
id [::json::write string did:web:$self_host] \
service [::json::write array \
[::json::write object \
id {"#bsky_fg"} \
serviceEndpoint [::json::write string https://$self_host] \
type {"BskyFeedGenerator"}]]
}
}