| 1 | # vim:sw=2:sts=2: |
| 2 | TODO |
| 3 | ==== |
| 4 | |
| 5 | Legend: |
| 6 | - [ ] not started |
| 7 | - [-] in-progress |
| 8 | - [x] done |
| 9 | - [~] cancelled |
| 10 | |
| 11 | In-progress |
| 12 | ----------- |
| 13 | |
| 14 | - [x] Prevent redundant downloads |
| 15 | - [x] Check ETag |
| 16 | - [ ] Check Last-Modified if no ETag was provided |
| 17 | - [ ] Parse rfc2822 timestamps |
| 18 | - [-] Convert to Typed Racket |
| 19 | - [x] build executable (otherwise too-slow) |
| 20 | - [-] add signatures |
| 21 | - [x] top-level |
| 22 | - [ ] inner |
| 23 | - [ ] imports |
| 24 | - [-] commands: |
| 25 | - [x] r | read |
| 26 | - see timeline ops above |
| 27 | - [ ] w | write |
| 28 | - arg or stdin |
| 29 | - nick expand to URI |
| 30 | - Watch FIFO for lines, then read, timestamp and append [+ upload]. |
| 31 | Can be part of a "live" mode, along with background polling and |
| 32 | incremental printing. Sort of an ii-like IRC experience. |
| 33 | - [ ] q | query |
| 34 | - see timeline ops above |
| 35 | - see hashtag and channels above |
| 36 | - [x] d | download |
| 37 | - [ ] options: |
| 38 | - [ ] all - use all known peers |
| 39 | - [ ] fast - all except peers known to be slow or unavailable |
| 40 | REQUIRES: stats |
| 41 | - [x] u | upload |
| 42 | - calls user-configured command to upload user's own timeline file to their server |
| 43 | Looks like a better CLI parser than "racket/cmdline": https://docs.racket-lang.org/natural-cli/ |
| 44 | But it is no longer necessary now that I've figured out how to chain (command-line ..) calls. |
| 45 | - [-] Output formats: |
| 46 | - [x] text long |
| 47 | - [x] text short |
| 48 | - [ ] HTML |
| 49 | - [ ] JSON |
| 50 | - [-] Peer discovery |
| 51 | - [-] parse peer refs from peer timelines |
| 52 | - [x] mentions from timeline messages |
| 53 | - [x] @<source.nick source.url> |
| 54 | - [x] @<source.url> |
| 55 | - [x] "following" from timeline comments: # following = <nick> <uri> |
| 56 | - [ ] Parse User-Agent web access logs. |
| 57 | - [ ] Update peer ref file(s) |
| 58 | Rough sketch from late 2019: |
| 59 | let read file = |
| 60 | ... |
| 61 | let write file peers = |
| 62 | ... |
| 63 | let fetch peer = |
| 64 | (* Fetch could mean either or both of: |
| 65 | * - fetch peer's we-are-twtxt.txt |
| 66 | * - fetch peer's twtxt.txt and extract mentioned peer URIs |
| 67 | * *) |
| 68 | ... |
| 69 | let test peers = |
| 70 | ... |
| 71 | let rec discover peers_old = |
| 72 | let peers_all = |
| 73 | Set.fold peers_old ~init:peers_old ~f:(fun peers p -> |
| 74 | match fetch p with |
| 75 | | Error _ -> |
| 76 | (* TODO: Should p be moved to down set here? *) |
| 77 | log_warning ...; |
| 78 | peers |
| 79 | | Ok peers_fetched -> |
| 80 | Set.union peers peers_fetched |
| 81 | ) |
| 82 | in |
| 83 | if Set.empty (Set.diff peers_old peers_all) then |
| 84 | peers_all |
| 85 | else |
| 86 | discover peers_all |
| 87 | let rec loop interval peers_old = |
| 88 | let peers_all = discover peers_old in |
| 89 | let (peers_up, peers_down) = test peers_all in |
| 90 | write "peers-all.txt" peers_all; |
| 91 | write "peers-up.txt" peers_up; |
| 92 | write "peers-down.txt" peers_down; |
| 93 | sleep interval; |
| 94 | loop interval peers_all |
| 95 | let () = |
| 96 | loop (Sys.argv.(1)) (read "peers-all.txt") |
| 97 | |
| 98 | Backlog |
| 99 | ------- |
| 100 | - [ ] Check for peer duplicates: |
| 101 | - [ ] same nick for N>1 URIs |
| 102 | - [ ] same URI for N>1 nicks |
| 103 | - [ ] Background polling and incremental timeline updates. |
| 104 | We can mark which messages have already been printed and print new ones as |
| 105 | they come in. |
| 106 | REQUIRES: polling |
| 107 | - [ ] Polling mode/command, where tt periodically polls peer timelines |
| 108 | - [ ] nick tiebreaker(s) |
| 109 | - [ ] some sort of a hash of URI? |
| 110 | - [ ] angry-purple-tiger kind if thingie? |
| 111 | - [ ] P2P nick registration? |
| 112 | - [ ] Peers vote by claiming to have seen a nick->uri mapping? |
| 113 | The inherent race condition would be a feature, since all user name |
| 114 | registrations are races. |
| 115 | REQUIRES: blockchain |
| 116 | - [ ] stats |
| 117 | - [ ] download times per peer |
| 118 | - [ ] Support redirects |
| 119 | - should permanent redirects update the peer ref somehow? |
| 120 | - [ ] Support time ranges (i.e. reading the timeline between given time points) |
| 121 | - [ ] optional text wrap |
| 122 | - [ ] write |
| 123 | - [ ] timeline limits |
| 124 | - [ ] peer refs set operations (perhaps better done externally?) |
| 125 | - [ ] timeline as a result of a query (peer ref set op + filter expressions) |
| 126 | - [ ] config files |
| 127 | - [ ] highlight mentions |
| 128 | - [ ] filter on mentions |
| 129 | - [ ] highlight hashtags |
| 130 | - [ ] filter on hashtags |
| 131 | - [ ] hashtags as channels? initial hashtag special? |
| 132 | - [ ] query language |
| 133 | - [ ] console logger colors by level ('error) |
| 134 | - [ ] file logger ('debug) |
| 135 | - [ ] Suport immutable timelines |
| 136 | - store individual messages |
| 137 | - where? |
| 138 | - something like DBM or SQLite - faster |
| 139 | - filesystem - transparent, easily published - probably best |
| 140 | - [ ] block(chain/tree) of twtxts |
| 141 | - distributed twtxt.db |
| 142 | - each twtxt.txt is a ledger |
| 143 | - peers can verify states of ledgers |
| 144 | - peers can publish known nick->url mappings |
| 145 | - peers can vote on nick->url mappings |
| 146 | - we could break time periods into blocks |
| 147 | - how to handle the facts that many(most?) twtxt are unseen by peers |
| 148 | - longest X wins? |
| 149 | |
| 150 | Done |
| 151 | ---- |
| 152 | - [x] caching (use cache by default, unless explicitly asked for update) |
| 153 | - [x] value --> cache |
| 154 | - [x] value <-- cache |
| 155 | REQUIRES: d command |
| 156 | - [x] Logger sync before exit. |
| 157 | - [x] Implement rfc3339->epoch |
| 158 | - [x] Remove dependency on rfc3339-old |
| 159 | - [x] remove dependency on http-client |
| 160 | - [x] Build executable |
| 161 | Implies fix of "collection not found" when executing the built executable |
| 162 | outside the source directory: |
| 163 | |
| 164 | collection-path: collection not found |
| 165 | collection: "tt" |
| 166 | in collection directories: |
| 167 | context...: |
| 168 | /usr/share/racket/collects/racket/private/collect.rkt:11:53: fail |
| 169 | /usr/share/racket/collects/setup/getinfo.rkt:17:0: get-info |
| 170 | /usr/share/racket/collects/racket/contract/private/arrow-val-first.rkt:555:3 |
| 171 | /usr/share/racket/collects/racket/cmdline.rkt:191:51 |
| 172 | '|#%mzc:p |
| 173 | |
| 174 | |
| 175 | Cancelled |
| 176 | --------- |
| 177 | - [~] named timelines/peer-sets |
| 178 | REASON: That is basically files of peers, which we already support. |