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