add more documentation
[pdt.git] / pdt.sh
CommitLineData
c0e2704f 1#!/bin/bash
f22362c9
IK
2# pdt: post to FSF social media via command line
3# Copyright (C) 2021 Ian Kelling
c0e2704f
IK
4# SPDX-License-Identifier: AGPL-3.0-or-later
5
f22362c9
IK
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.
10
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.
15
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/>.
18
19# This is meant to be sourced.
c0e2704f
IK
20
21PATH="$HOME/.local/bin:$PATH"
22
23# usage: rbow [-PROFILE_NAME] [COMMAND]
24#
25# Wrapper for rainbowstream to use multiple logins and tweet directly
26# from the command line. PROFILE_NAME can be anything you want.
27rbow() {
b62d284c 28 local oath f
c0e2704f
IK
29 oath=$HOME/.rainbow_oauth
30 if [[ $1 == -* ]]; then
31 rm -f $oath
32 ln -s $oath$1 $oath
33 shift
34 fi
35 source ~/src/rainbowstream/venv/bin/activate
36 if (($#)); then
37 f=$(mktemp)
38 cat >$f <<'EOF'
39# adds a short delay after each send for more reliable operation
1d6422a8 40set force_conservative 1
c0e2704f
IK
41spawn "rainbowstream"
42# wait for prompt
43expect -nocase timeout {exit 1} "@*]: "
44set cmd [lindex $argv 0];
1d6422a8
IK
45send "$cmd\r\r"
46expect -nocase timeout {exit 1} "@*]: "
47# this may not be needed. didnt test
48sleep 2
49send "q\r"
c0e2704f
IK
50interact
51EOF
1d6422a8 52 expect $f "$*" || { echo error: expect failed; deactivate; rm -f $f; return 1; }
c0e2704f
IK
53 rm -f $f
54 else
55 rainbowstream
56 fi
57 deactivate
58}
59
60diaspora() {
61 source ~/src/diaspy/venv/bin/activate
62 python3 ~/src/jan-pona-mute/jan-pona-mute.py "$@" || { deactivate; return 1; }
63 deactivate
64}
65
66# usage: toot [-PROFILE_NAME] [TOOT_ARGS]
67toot() {
b62d284c 68 local account
c0e2704f
IK
69 source ~/src/toot/venv/bin/activate
70 if [[ $1 == -* ]]; then
71 account=${1#-}
72 shift
73 command toot activate --quiet $account || { deactivate; return 1; }
74 fi
75 command toot "$@" || { deactivate; return 1; }
76 deactivate
77}
78
79
80# post to mastodon + twitter + gnu social post + diaspora
81#
0d7441e0
IK
82# Diaspora is skipped if posting to dbd accounts.
83#
84# If posting video, it only goes to twitter. Other accounts can be
85# posted to manually with free software.
86#
9c8eb6e7 87# usage: pdt [--dbd] [-m MEDIA_FILE] [-v VIDEO_PATH] [POST]
c0e2704f 88pdt() {
b62d284c 89 local video media rbow_account gs_account mastodon_account dbd video rbow_arg toot_arg dia_arg gs_arg
c0e2704f
IK
90 if [[ $pdttest ]]; then
91 rbow_account=iank
92 gs_account=fsfes
93 mastodon_account=iank@hostux.social
94 else
95 rbow_account=fsf
96 gs_account=fsf
97 mastodon_account=fsf@hostux.social
98 fi
99 dbd=false
9c8eb6e7 100 video=false
c0e2704f
IK
101 while [[ $1 == -* ]]; do
102 case $1 in
103 -m)
104 media="$2"
105 shift 2
c0e2704f
IK
106 rbow_arg=" --i $media"
107 toot_arg="--media $media"
108 dia_arg="-p $media "
109 gs_arg="-F media=@$media"
110 ;;
111 --dbd)
112 dbd=true
113 rbow_account=dbd
114 gs_account=dbd
115 mastodon_account=endDRM@hostux.social
116 shift
117 ;;
9c8eb6e7
IK
118 -v)
119 video=true
120 media="$2"
121 shift 2
122 ;;
c0e2704f
IK
123 esac
124 done
9c8eb6e7
IK
125 if [[ $media ]]; then
126 if [[ ! -e $media ]]; then
127 echo "error: file not found $media"
128 return 1
129 fi
130 if [[ $media == *\ * ]]; then
131 echo "error: file path contains a space. move it to non-space path"
132 return 1
133 fi
134 fi
c0e2704f
IK
135 # if we have no argument
136 if (( ! $# )); then
137 read -r -p "input PDT text: " input
138 set -- "$input"
139 fi
140 if [[ $- == *i* ]]; then
141 echo "About to PDT the following line. Press enter to confirm or ctrl-c to quit:"
142 echo "$input"
143 read
144 fi
9c8eb6e7
IK
145 if $video; then
146 local oath
147 oath=$HOME/.rainbow_oauth
148 account=fsf
149 if $dbd; then
150 account=dbd
151 fi
152 rm -f $oath
153 ln -s ${oath}-$account $oath
4b26c43d 154 python3 ~/src/video-tweet/async-upload.py "$media" "$*"
9c8eb6e7
IK
155 return
156 fi
c0e2704f
IK
157 fails=()
158 if ! rbow -$rbow_account t "$*" $rbow_arg; then
159 fails+=(tweet)
160 fi
161 if ! toot -$mastodon_account post "$*" $toot_arg; then
162 fails+=(toot)
163 fi
c5176a05 164 if ! $dbd; then
c0e2704f
IK
165 if ! printf "post %s\n" "${dia_arg}$*" | diaspora; then
166 fails+=(diaspora)
167 fi
168 fi
169 # https://gnusocial.net/doc/twitterapi
170 if ! curl -o /dev/null -sS -u "$gs_account:$(cat ~/.gnusocial_login-$gs_account)" \
171 $gs_arg -F "status=$*" https://status.fsf.org/api/statuses/update.xml; then
172 fails+=(gnu-social)
173 fi
174 if (( ${#fails[@]} )); then
175 printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(eval echo "{1..${COLUMNS:-60}}"); echo
176 echo "FSF ERROR: ${fails[*]} might not have posted" >&2
177 fi
178}
179
0d7441e0 180# Usage: pdt-setup
c0e2704f 181pdt-setup() {
c0e2704f
IK
182 if [[ $pdttest ]]; then
183 mastodon_accounts=(iank)
184 else
185 mastodon_accounts=(fsf endDRM)
186 fi
187
188 mkdir -p ~/src
189 cd ~/src
9c8eb6e7 190 for repo in errhandle rainbowstream diaspy jan-pona-mute video-tweet; do
c0e2704f
IK
191 if [[ -e $repo ]]; then
192 cd $repo
193 git fetch
194 git reset --hard origin/master
195 git clean -xfffd
196 cd ..
197 else
198 git clone https://vcs.fsf.org/git/$repo.git
199 fi
200 done
201 source ~/src/errhandle/err
202 cp ~/src/rainbowstream/rainbowstream/colorset/config ~/.rainbow_config.json
203
204 if [[ ! -e ~/.local/bin/pip ]]; then
205 tmp=$(mktemp)
206 wget -O$tmp https://bootstrap.pypa.io/get-pip.py
207 python3 $tmp --user
208 hash -r
209 fi
210
211
212 if [[ ! -e ~/.local/bin/virtualenv ]]; then
213 python3 -m pip install --user virtualenv
214 fi
215
216 cd ~/src/rainbowstream
217 python3 -m virtualenv -p python3 venv
218 source venv/bin/activate
219 python3 -m pip install -r requirements.txt
220 python3 -m pip install -e .
221 deactivate
222
223
224 # This repo's upstream is https://alexschroeder.ch/cgit/diaspy which is
225 # recommended in the install instructions here:
226 # https://alexschroeder.ch/cgit/jan-pona-mute/about/
227 cd ~/src/diaspy
228 python3 -m virtualenv -p python3 venv
229 source venv/bin/activate
230 python3 -m pip install -r requirements.txt
231 python3 -m pip install -e .
232 deactivate
233
234 rm -rf ~/src/toot
235 mkdir -p ~/src/toot
236 cd ~/src/toot
237 python3 -m virtualenv -p python3 venv
238 source venv/bin/activate
239 # pip freeze after a pip install.
240 cat >requirements.txt <<'EOF'
241beautifulsoup4==4.8.2
242certifi==2019.11.28
243chardet==3.0.4
244idna==2.8
245requests==2.22.0
246soupsieve==1.9.5
247toot==0.25.2
248urllib3==1.25.8
249urwid==2.1.0
250wcwidth==0.1.8
251EOF
252 python3 -m pip install -r requirements.txt
253 deactivate
254
255
256 if [[ ! -s ~/.config/jan-pona-mute/login ]]; then
257 mkdir ~/.config/jan-pona-mute
258 account=fsf@framasphere.org
259 read -r -p "enter the password for $account > " pass
260 # background: format for this found using the save command
261 cat >~/.config/jan-pona-mute/login <<EOF
262account $account
263password $pass
264login
265EOF
266 fi
267
268 for account in dbd fsf; do
269 if [[ ! -s ~/.rainbow_oauth-$account ]]; then
270 printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(eval echo "{1..${COLUMNS:-60}}");
271 echo "Please login to $account on twitter in your main browser then press enter. After rainbowstream prompt loads, quit with command q"
272 read -r
273 rbow -$account
274 fi
275 if [[ ! -s ~/.gnusocial_login-$account ]]; then
276 printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(eval echo "{1..${COLUMNS:-60}}");
277 read -r -p "please enter the password for $account@status.fsf.org > " pass
278 touch ~/.gnusocial_login-$account
279 chmod 600 ~/.gnusocial_login-$account
280 printf "%s\n" "$pass" > ~/.gnusocial_login-$account
281 fi
282 done
283
284 for account in ${mastodon_accounts[@]}; do
285 if ! toot activate $account@hostux.social &>/dev/null; then
286 printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(eval echo "{1..${COLUMNS:-60}}");
287 echo "Please login to $account on https://hostux.social in your main browser then press enter."
288 read -r
289 toot login -i hostux.social
290 fi
291 done
292 err-allow
293}