~aleteoryx/tclfeed-bsky

ref: dd19de9860747c84b40cfbce04302383ae759d40 tclfeed-bsky/src/feed.tcl -rw-r--r-- 3.0 KiB
dd19de98Aleteoryx fixes 29 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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"}]]
  }
}