| 1 | # vim:sw=2:sts=2: |
| 2 | - [ ] stats |
| 3 | - [ ] download times per peer |
| 4 | - [ ] Output formats: |
| 5 | - [x] text long |
| 6 | - [x] text short |
| 7 | - [ ] HTML |
| 8 | - [ ] JSON |
| 9 | - [ ] Convert to Typed Racket |
| 10 | - requires: build executable (otherwise too slow) |
| 11 | - [x] Build executable |
| 12 | Implies fix of "collection not found" when executing the built executable |
| 13 | outside the source directory: |
| 14 | |
| 15 | collection-path: collection not found |
| 16 | collection: "tt" |
| 17 | in collection directories: |
| 18 | context...: |
| 19 | /usr/share/racket/collects/racket/private/collect.rkt:11:53: fail |
| 20 | /usr/share/racket/collects/setup/getinfo.rkt:17:0: get-info |
| 21 | /usr/share/racket/collects/racket/contract/private/arrow-val-first.rkt:555:3 |
| 22 | /usr/share/racket/collects/racket/cmdline.rkt:191:51 |
| 23 | '|#%mzc:p |
| 24 | |
| 25 | - [ ] Support redirects |
| 26 | - should permanent redirects update the feed somehow? |
| 27 | - [ ] Support time ranges (i.e. reading the timeline between given time points) |
| 28 | - [x] Implement rfc3339->epoch |
| 29 | - [x] Remove dependency on rfc3339-old |
| 30 | - [x] remove dependency on http-client |
| 31 | - [ ] optional text wrap |
| 32 | - [ ] write |
| 33 | - [x] caching (use cache by default, unless explicitly asked for update) |
| 34 | - [x] value --> cache |
| 35 | - [x] value <-- cache |
| 36 | requires: d command |
| 37 | - [ ] timeline limits |
| 38 | - [ ] feed set operations (perhaps better done externally?) |
| 39 | - [ ] timeline as a result of a query (feed set op + filter expressions) |
| 40 | - [ ] named timelines |
| 41 | - [ ] config files |
| 42 | - [ ] parse "following" from feed |
| 43 | - following = <nick> <uri> |
| 44 | - [x] parse mentions: |
| 45 | - [x] @<source.nick source.url> |
| 46 | - [x] @<source.url> |
| 47 | - [ ] highlight mentions |
| 48 | - [ ] filter on mentions |
| 49 | - [ ] highlight hashtags |
| 50 | - [ ] filter on hashtags |
| 51 | - [ ] hashtags as channels? initial hashtag special? |
| 52 | - [ ] query language |
| 53 | - [ ] console logger colors by level ('error) |
| 54 | - [ ] file logger ('debug) |
| 55 | - [-] commands: |
| 56 | - [x] r | read |
| 57 | - see timeline ops above |
| 58 | - [ ] w | write |
| 59 | - arg or stdin |
| 60 | - nick expand to URI |
| 61 | - [ ] q | query |
| 62 | - see timeline ops above |
| 63 | - see hashtag and channels above |
| 64 | - [x] d | download |
| 65 | - [x] u | upload |
| 66 | - calls user-configured command to upload user's own feed file to their server |
| 67 | Looks like a better CLI parser than "racket/cmdline": https://docs.racket-lang.org/natural-cli/ |
| 68 | But it is no longer necessary now that I've figured out how to chain (command-line ..) calls. |
| 69 | - [ ] Suport immutable timelines |
| 70 | - store individual messages |
| 71 | - where? |
| 72 | - something like DBM or SQLite - faster |
| 73 | - filesystem - transparent, easily published - probably best |
| 74 | - [ ] block(chain/tree) of twtxts |
| 75 | - distributed twtxt.db |
| 76 | - each twtxt.txt is a ledger |
| 77 | - peers can verify states of ledgers |
| 78 | - peers can publish known nick->url mappings |
| 79 | - peers can vote on nick->url mappings |
| 80 | - we could break time periods into blocks |
| 81 | - how to handle the facts that many(most?) twtxt are unseen by peers |
| 82 | - longest X wins? |
| 83 | - [ ] Peer discovery |
| 84 | requires: |
| 85 | - parse mentions |
| 86 | - parse following |
| 87 | rough sketch from late 2019: |
| 88 | |
| 89 | let read file = |
| 90 | ... |
| 91 | let write file peers = |
| 92 | ... |
| 93 | let fetch peer = |
| 94 | (* Fetch could mean either or both of: |
| 95 | * - fetch peer's we-are-twtxt.txt |
| 96 | * - fetch peer's twtxt.txt and extract mentioned peer URIs |
| 97 | * *) |
| 98 | ... |
| 99 | let test peers = |
| 100 | ... |
| 101 | let rec discover peers_old = |
| 102 | let peers_all = |
| 103 | Set.fold peers_old ~init:peers_old ~f:(fun peers p -> |
| 104 | match fetch p with |
| 105 | | Error _ -> |
| 106 | (* TODO: Should p be moved to down set here? *) |
| 107 | log_warning ...; |
| 108 | peers |
| 109 | | Ok peers_fetched -> |
| 110 | Set.union peers peers_fetched |
| 111 | ) |
| 112 | in |
| 113 | if Set.empty (Set.diff peers_old peers_all) then |
| 114 | peers_all |
| 115 | else |
| 116 | discover peers_all |
| 117 | let rec loop interval peers_old = |
| 118 | let peers_all = discover peers_old in |
| 119 | let (peers_up, peers_down) = test peers_all in |
| 120 | write "peers-all.txt" peers_all; |
| 121 | write "peers-up.txt" peers_up; |
| 122 | write "peers-down.txt" peers_down; |
| 123 | sleep interval; |
| 124 | loop interval peers_all |
| 125 | let () = |
| 126 | loop (Sys.argv.(1)) (read "peers-all.txt") |