README (9001B)
1 _ 2 (_) ___ _ __ _ __ _ _ 3 | |/ _ \ '_ \| '_ \| | | | 4 | | __/ | | | | | | |_| | 5 _/ |\___|_| |_|_| |_|\__, | 6 |__/ |___/ 7 https://uninformativ.de/git/jenny 8 https://uninformativ.de/bugs.html 9 10 11 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12 13 14 jenny is a twtxt client. One core feature is that all twts are stored in 15 a maildir which can be viewed using a programm like mutt. 16 17 Supports the following Yarn.social extensions: 18 19 https://twtxt.dev/exts/twt-hash.html 20 https://twtxt.dev/exts/twt-subject.html 21 22 The name "jenny" comes from "the spinning jenny", because, you know, 23 you're working with yarn and threads and stuff: 24 25 https://en.wikipedia.org/wiki/Spinning_jenny 26 27 28 Installation 29 ------------ 30 31 You need: 32 33 - Python 3 34 - dateutil 35 - requests 36 37 In general, the programs have only been tested on GNU/Linux. Patches for 38 more portability are welcome! 39 40 41 Configuration 42 ------------- 43 44 You need a file called ~/.config/jenny/conf.json. A minimal example: 45 46 { 47 "maildir_target": "~/Mail/twt", 48 "local_twtxt_dir": "~/web/my.server.com", 49 "publish_command": "some-rsync-script" 50 } 51 52 (The program will prefer $XDG_CONFIG_HOME over a plain ~/.config.) 53 54 `maildir_target` is the path to a local, pre-existing maildir 55 directory (including the subdirectories "cur", "new", and "tmp"). All 56 twts -- your own and those written by others -- will be stored here. 57 58 You will probably run jenny on your workstation (as opposed to directly 59 on your server). This means that we must transfer the files created in 60 `local_twtxt_dir` to the server after writing entries. jenny cannot know 61 how to do this, so you are expected to specify a custom script of your 62 own to do this job. This is `publish_command`. (`publish_command` is 63 optional.) 64 65 Complete config reference: 66 67 - `announce_me`: Unless you have set `announce_me` to `false` (the 68 default is `true`), your identity will be announced to those other 69 feeds when they are fetched. The flags `DONT_ANNOUNCE_ME` or 70 `ANNOUNCE_ME` can be added to individual lines in your `follow` 71 file to override that global setting. 72 - `editor`: Defaults to $VISUAL, or $EDITOR if that is unset, or 73 `vi` if both are unset. This command is run through `sh -c ...`. 74 If present, a literal "{}" will be replaced with the filename 75 (shell-quote), otherwise that path is simply appended. 76 - `local_twtxt_dir` (REQUIRED): Path to directory where twtxt files 77 will be stored. 78 - `local_twtxt_filename_format`: Defaults to `twtxt{}.txt`. The `{}` 79 will be replaced by an appropriate suffix when your feed gets 80 rotated. 81 - `maildir_target` (REQUIRED): Path to maildir directory. 82 - `max_twts_per_rotation`: Once your main feed ("twtxt.txt") reaches 83 this many twts, they will be moved to an Archive Feed. Defaults to 84 1000. Set to 0 to disable feed rotation. 85 - `mention_marker`: When someone mentions you in their twtxt file, 86 jenny will put a marker in the mail's "Subject:" line. You can 87 customize this by setting `mention_marker` to a string of your 88 liking. 89 - `publish_command`: Script to run to publish your twtxt file. 90 - `subject_maxlen`: Truncate the `Subject:` line of mail headers to 91 this many characters. Defaults to 0, i.e. no truncation. 92 - `yarn_pods_for_discovery`: When using `--fetch-context` (see Alt+C 93 in the mutt example), jenny will try to retrieve the missing twt 94 from the original feeds. If that fails, it can try to retrieve the 95 twt from some Yarn pods. `yarn_pods_for_discovery` is a list of 96 strings, e.g.: `"yarn_pods_for_discovery": ["https://twtxt.net"]`. 97 98 Also note that the filename will always be `jenny-posting.eml`. This 99 allows you to configure your editor to behave differently just for 100 twtxt postings, e.g. you can do this in Vim: 101 102 au BufRead,BufNewFile jenny-posting.eml setl wrap tw=0 fo-=t nu 103 104 Initially, you must create your "twtxt.txt" manually in 105 `local_twtxt_dir`. jenny expects some metadata in that file: 106 107 # nick = my-name 108 # url = https://my.server.com/twtxt.txt 109 # avatar = https://my.server.com/avatar.png 110 # 111 # These are aliases: 112 # nick_alias = my-old-name-that-I-no-longer-use 113 # url = gopher://my.server.com/0/twtxt.txt 114 # 115 2020-10-11T10:40:48+02:00 hello world 116 117 It will read your own nickname and the URLs under which your twtxt is 118 available. The "nick =" line will be used to detect mentions. The 119 "nick =" line together with the first "url =" line will be used to 120 construct the user agent, which identifies you to other users. 121 122 If other feeds contain "nick =" metadata as well, jenny will show it. 123 124 "nick_alias =" and multiple "url =" lines can be used when you're 125 transitioning from one name/URL to another. jenny will use them all to 126 detect mentions, but it will only ever advertise "nick =" and "url =" to 127 other servers. 128 129 (An "avatar =" line is optional and not used by jenny, but it's good 130 practice and might be used by other implementations.) 131 132 For each twt, it will create one file in the configured maildir. The 133 idea is that you run this as a cron job to create pseudo mail files. 134 (Either on your workstation or on a server.) The goal is to create a 135 pseudo mailbox of twts, which you can read using something like 136 mutt. 137 138 To follow other people, create ~/.config/jenny/follow: 139 140 buckket https://buckket.org/twtxt.txt 141 dilbert https://twtxt.net/user/dilbert/twtxt.txt DONT_ANNOUNCE_ME 142 movq https://www.uninformativ.de/twtxt.txt ANNOUNCE_ME 143 144 HTTP, HTTPS, Gopher, and Gemini are supported. 145 146 Note that other people will have no idea that you're following them if 147 you turn off announcing. 148 149 150 Running 151 ------- 152 153 Run without arguments to compose a new twt: 154 155 $ jenny 156 157 To reply to an already existing twt, provide the mail file on stdin (for 158 mutt integration, see below): 159 160 $ cat ~/Mail/twt/cur/zvvdala:2,S | jenny 161 162 In both these cases, `publish_command` will be run once you've left the 163 editor. However, if you wish to cancel and not publish your new twt, you 164 have three options: 165 166 1. Save an empty twt. 167 2. Quit the editor without ever saving anything to the file. 168 3. Quit the editor with an exit code other than 0 (":cq!" in Vim). 169 170 To edit your twtxt file, run one of the following (`publish_command` 171 will be run after this): 172 173 $ jenny -e 174 $ jenny --edit 175 176 To fetch new twts from all the feeds you're following, run either of 177 those: 178 179 $ jenny -f 180 $ jenny --fetch 181 182 jenny will take note when a feed was last retrieved. You can show this 183 database by running: 184 185 $ jenny -l 186 $ jenny --last-seen 187 188 Or show the dates of the last twt of each feed: 189 190 $ jenny -L 191 $ jenny --last-twt 192 193 This allows you to spot dead feeds. 194 195 196 mutt integration 197 ---------------- 198 199 Here is a full configuration file for mutt: 200 201 # Strictly necessary or highly recommended. 202 set mbox_type = Maildir 203 set sort = threads 204 set sort_aux = date-sent 205 set strict_threads = yes 206 207 # Optional styling. 208 color index yellow default ~P 209 set index_format = "%Z│%-15.15F│%3M│%s %* │%[%Y-%m-%d %H:%M]" 210 211 # To highlight messages sent by you. 212 alternates cathy 213 214 # Key binds for jenny: Alt+T to write a new twt, Alt+R to reply to 215 # thread, Alt+F to reply in a forked thread. Alt+C tries to fetch a 216 # missing root twt (see explanation below). 217 macro index,pager <esc>T "<shell-escape> jenny<Enter>" "Write new twt" 218 macro index,pager <esc>R "\ 219 <enter-command> set my_pipe_decode=\$pipe_decode nopipe_decode<Enter>\ 220 <pipe-message> jenny<Enter>\ 221 <enter-command> set pipe_decode=\$my_pipe_decode; unset my_pipe_decode<Enter>" \ 222 "Reply to current twt" 223 macro index,pager <esc>F "\ 224 <enter-command> set my_pipe_decode=\$pipe_decode nopipe_decode<Enter>\ 225 <pipe-message> jenny -t<Enter>\ 226 <enter-command> set pipe_decode=\$my_pipe_decode; unset my_pipe_decode<Enter>" \ 227 "Reply to current twt (fork conversation)" 228 macro index,pager <esc>C "\ 229 <enter-command> set my_pipe_decode=\$pipe_decode nopipe_decode<Enter>\ 230 <pipe-message> jenny -c<Enter>\ 231 <enter-command> set pipe_decode=\$my_pipe_decode; unset my_pipe_decode<Enter>" \ 232 "Try to fetch context of current twt, like a missing root twt" 233 234 Regarding Alt+C: It is relatively common that you follow some user and 235 that user posts a reply to someone else -- but you don't follow that 236 other person. That results in a broken thread. This function tries to 237 fetch just that one missing twt, without you having to follow the entire 238 feed. (See also: `yarn_pods_for_discovery`.) 239 240 If you don't want to change your existing mutt setup (or if you don't 241 have one yet), you can save this to a new file and launch mutt like 242 this: 243 244 $ mutt -F ~/.muttrc-jenny -f ~/Mail/twt 245 246 247 Running the tests 248 ----------------- 249 250 You need pytest: https://docs.pytest.org/en/stable/index.html 251 252 Just run: 253 254 $ pytest tests/