2 # pdt: post to FSF social media via command line
3 # Copyright (C) 2021 Ian Kelling
4 # SPDX-License-Identifier: AGPL-3.0-or-later
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU Affero General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU Affero General Public License for more details.
16 # You should have received a copy of the GNU Affero General Public License
17 # along with this program. If not, see <https://www.gnu.org/licenses/>.
19 # This is meant to be sourced.
21 PATH
="$HOME/.local/bin:$PATH"
24 _pdtsh_file
="$(readlink -f -- "${BASH_SOURCE[0]}")"
25 _pdtsh_dir
="${_pdtsh_file%/*}"
26 _pdtsh_tweet
="$_pdtsh_dir/t.py"
28 # usage: tweet [-PROFILE_NAME] [POST...]
29 # Uses variables as input:
30 # $media for image file path.
31 # $alt_text for image alt text.
34 oath
=$HOME/.rainbow_oauth
35 if [[ $1 == -* ]]; then
40 source ~
/src
/twitter
/venv
/bin
/activate
44 printf "%s\n" "$media"
45 if [[ $alt_text ]]; then
46 printf "%s\n" "$alt_text"
53 # usage: rbow [-PROFILE_NAME] [COMMAND]
55 # Wrapper for rainbowstream to use multiple logins and tweet directly
56 # from the command line. PROFILE_NAME can be anything you want.
59 oath
=$HOME/.rainbow_oauth
60 if [[ $1 == -* ]]; then
65 source ~
/src
/rainbowstream
/venv
/bin
/activate
69 # adds a short delay after each send for more reliable operation
70 set force_conservative 1
73 expect -nocase timeout {exit 1} "@*]: "
74 set cmd [lindex $argv 0];
76 expect -nocase timeout {exit 1} "@*]: "
77 # this may not be needed. didnt test
82 expect
$f "$*" ||
{ echo error
: expect failed
; deactivate
; rm -f $f; return 1; }
91 # usage: toot [-PROFILE_NAME] [TOOT_ARGS]
94 source ~
/src
/toot
/venv
/bin
/activate
95 if [[ $1 == -* ]]; then
98 command toot activate
--quiet $mast_profile ||
{ deactivate
; return 1; }
100 command toot
"$@" ||
{ deactivate
; return 1; }
105 # post to mastodon + twitter + gnu social post
107 # If posting video, it only goes to twitter. Other accounts can be
108 # posted to manually with free software.
110 # Alt text only goes to mastodon.
112 # usage: pdt [-s mastodon|twitter|gnusocial] [--dbd] [-m IMAGE_FILE] [-a ALT_TEXT] [-v VIDEO_PATH] [POST]
113 # -s mastodon|twitter|gnusocial = post to a single social network.
114 # -m IMAGE_FILE = Uploads IMAGE_FILE. if MEDIA_FILE.txt exists, the last line of that file will be used as ALT_TEXT
115 # unless -a has been used.
117 local video media twitter_account gs_account mastodon_account video gs_arg network
118 local do_mastodon do_twitter do_gnusocial
120 if [[ $pdttest ]]; then
123 mastodon_account
=fsftest@hostux.social
127 mastodon_account
=fsf@hostux.social
131 # no twitter by default.
135 while [[ $1 == -* ]]; do
153 echo "pdt: error: expected -s mastodon|twitter|gnusocial"
166 toot_args
+=(--media "$media" )
167 gs_arg
="-F media=@$media"
172 mastodon_account
=endDRM@hostux.social
182 if [[ $media ]]; then
183 if [[ ! -e $media ]]; then
184 echo "error: file not found $media"
187 if [[ $media == *\
* ]]; then
188 echo "error: file path contains a space. move it to non-space path"
191 if [[ ! $alt_text && -r $media.txt
&& -s $media.txt
]]; then
192 alt_text
=$
(tail -n1 $media.txt
)
194 if [[ $alt_text ]]; then
195 toot_args
+=(--description "$alt_text" )
198 # if we have no argument
200 read -r -p "input PDT text: " input
203 if [[ $
- == *i
* ]]; then
204 echo "About to PDT the following line. Press enter to confirm or ctrl-c to quit:"
210 oath
=$HOME/.rainbow_oauth
212 ln -s ${oath}-$twitter_account $oath
213 python3 ~
/src
/video-tweet
/async-upload.py
"$media" "$*"
218 if ! tweet
-$twitter_account "$*"; then
222 if $do_mastodon; then
223 if ! toot
-$mastodon_account post
"$*" "${toot_args[@]}"; then
227 if $do_gnusocial; then
228 # https://gnusocial.net/doc/twitterapi
229 if ! curl
-o /dev
/null
-sS -u "$gs_account:$(cat ~/.gnusocial_login-$gs_account)" \
230 $gs_arg -F "status=$*" https
://status.fsf.org
/api
/statuses
/update.xml
; then
234 if (( ${#fails[@]} )); then
235 printf "$(tput setaf 5)█$(tput sgr0)%.0s" $
(eval echo "{1..${COLUMNS:-60}}"); echo
236 echo "FSF ERROR: ${fails[*]} might not have posted" >&2
242 # Only run manually for testing.
244 # this expects pdt-pip-setup has been run already, and it doesn't setup
247 # note: auth info is stored at ~/.config/toot/config.json
249 local -a twitter_accounts mastodon_accounts
250 if [[ $pdttest ]]; then
251 twitter_accounts
=(iank
)
252 mastodon_accounts
=(fsftest
)
254 twitter_accounts
=(fsf dbd
)
255 mastodon_accounts
=(fsf endDRM
)
261 # on t11, got myself into a situation where when doing pip install virtualenv,
262 # it gave an error that /usr/bin/pip didn't exist, so i did
263 # sudo ln -s /home/iank/.local/bin/pip /usr/bin
265 python3
-m virtualenv
-p python3 venv
266 source venv
/bin
/activate
267 # pip freeze after a pip install, as of 2022-11-28
268 cat >requirements.txt
<<'EOF'
269 beautifulsoup4==4.11.1
271 charset-normalizer==2.1.1
274 soupsieve==2.3.2.post1
281 # new 2022-11 packages
282 # beautifulsoup4==4.11.1
284 # charset-normalizer==2.1.1
287 # soupsieve==2.3.2.post1
294 # beautifulsoup4==4.8.2
295 # certifi==2019.11.28
305 # i mixed in some old packages to get newer toot working on t9.
307 python3
-m pip
install -r requirements.txt
310 for account
in ${mastodon_accounts[@]}; do
311 if ! toot activate
$account@hostux.social
&>/dev
/null
; then
312 printf "$(tput setaf 5)█$(tput sgr0)%.0s" $
(eval echo "{1..${COLUMNS:-60}}");
313 echo "Please login to the account named \"$account\" on https://hostux.social in your main browser then press enter."
314 echo "WARNING: if you log into an account other than \"$account\", this won't work"
316 toot login
-i hostux.social
321 # Usage: pdt-pip-setup
323 if [[ ! -e ~
/.local
/bin
/pip
]]; then
325 pyver
=$
(python3
--version |
sed -r 's/.*(3\.[0-9]+).*/\1/')
326 echo fyi
: detected pyver
: $pyver. this should
look something like
3.6
328 if dpkg
--compare-versions 3.6 ge
$pyver; then
329 # The bootstrap script at https://bootstrap.pypa.io/get-pip.py required 3.7+
331 wget
-O$tmp https
://bootstrap.pypa.io
/pip
/$pyver/get-pip.py
333 wget
-O$tmp https
://bootstrap.pypa.io
/get-pip.py
338 python3
-m pip
install --user -U virtualenv
341 # generally only meant to be called internally from pdt-setup
342 pdt-twitter-setup
() {
344 mkdir
-p ~
/src
/twitter
346 python3
-m virtualenv
-p python3 venv
347 source venv
/bin
/activate
349 cat >requirements.txt
<<'EOF'
353 python3
-m pip
install -r requirements.txt
357 # note: we could ditch rainbowstream altogether and just pass around
358 # oath api key string in a password file or something if we learned
359 # how to get it from the new twitter client im using. I'm just keeping
360 # this because it works and I like the format of how it stores its
362 cd ~
/src
/rainbowstream
363 python3
-m virtualenv
-p python3 venv
364 source venv
/bin
/activate
365 python3
-m pip
install -r requirements.txt
366 python3
-m pip
install -e .
369 for account
in ${twitter_accounts[@]}; do
370 if [[ ! -s ~
/.rainbow_oauth-
$account ]]; then
371 printf "$(tput setaf 5)█$(tput sgr0)%.0s" $
(eval echo "{1..${COLUMNS:-60}}");
372 echo "Please login to the account named \"$account\" on twitter in your main browser then press enter. After rainbowstream prompt loads, quit by typing q then enter"
377 for account
in ${twitter_accounts[@]}; do
378 if [[ ! -s $HOME/.rainbow_oauth-
$account ]]; then
379 echo "pdt-setup error: expected non-empty file at $HOME/.rainbow_oauth-$account by this point. try reruning pdt-setup and logging in to the correct twitter account in browser or contact ian"
383 if [[ ! $pdttest ]] && diff -q $HOME/.rainbow_oauth-fsf
$HOME/.rainbow_oauth-dbd
&>/dev
/null
; then
384 echo "pdt-setup error: error, $HOME/.rainbow_oauth-fsf $HOME/.rainbow_oauth-dbd are the same. Did you follow the instructions closely and log into fsf and then dbd when prompted? try reruning pdt-setup and doing that"
397 for repo
in errhandle rainbowstream video-tweet
; do
398 if [[ -e $repo ]]; then
401 git
reset --hard origin
/master
405 git clone https
://vcs.fsf.org
/git
/$repo.git
409 source ~
/src
/errhandle
/err
410 cp ~
/src
/rainbowstream
/rainbowstream
/colorset
/config ~
/.rainbow_config.json
419 for account
in dbd fsf
; do
420 if [[ ! -s ~
/.gnusocial_login-
$account ]]; then
421 printf "$(tput setaf 5)█$(tput sgr0)%.0s" $
(eval echo "{1..${COLUMNS:-60}}");
422 read -r -p "please enter the password for $account@status.fsf.org > " pass
423 touch ~
/.gnusocial_login-
$account
424 chmod 600 ~
/.gnusocial_login-
$account
425 printf "%s\n" "$pass" > ~
/.gnusocial_login-
$account
430 echo "pdt-setup complete"