#!/bin/bash # pdt: post to FSF social media via command line # Copyright (C) 2021 Ian Kelling # SPDX-License-Identifier: AGPL-3.0-or-later # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # This is meant to be sourced. PATH="$HOME/.local/bin:$PATH" # usage: rbow [-PROFILE_NAME] [COMMAND] # # Wrapper for rainbowstream to use multiple logins and tweet directly # from the command line. PROFILE_NAME can be anything you want. rbow() { local oath f oath=$HOME/.rainbow_oauth if [[ $1 == -* ]]; then rm -f $oath ln -s $oath$1 $oath shift fi source ~/src/rainbowstream/venv/bin/activate if (($#)); then f=$(mktemp) cat >$f <<'EOF' # adds a short delay after each send for more reliable operation set force_conservative 1 spawn "rainbowstream" # wait for prompt expect -nocase timeout {exit 1} "@*]: " set cmd [lindex $argv 0]; send "$cmd\r\r" expect -nocase timeout {exit 1} "@*]: " # this may not be needed. didnt test sleep 2 send "q\r" interact EOF expect $f "$*" || { echo error: expect failed; deactivate; rm -f $f; return 1; } rm -f $f else rainbowstream fi deactivate } # usage: toot [-PROFILE_NAME] [TOOT_ARGS] toot() { local account source ~/src/toot/venv/bin/activate if [[ $1 == -* ]]; then account=${1#-} shift command toot activate --quiet $account || { deactivate; return 1; } fi command toot "$@" || { deactivate; return 1; } deactivate } # post to mastodon + twitter + gnu social post # # If posting video, it only goes to twitter. Other accounts can be # posted to manually with free software. # # usage: pdt [--dbd] [-m MEDIA_FILE] [-v VIDEO_PATH] [POST] pdt() { local video media rbow_account gs_account mastodon_account dbd video rbow_arg toot_arg dia_arg gs_arg if [[ $pdttest ]]; then rbow_account=iank gs_account=fsfes mastodon_account=iank@hostux.social else rbow_account=fsf gs_account=fsf mastodon_account=fsf@hostux.social fi dbd=false video=false while [[ $1 == -* ]]; do case $1 in -m) media="$2" shift 2 rbow_arg=" --i $media" toot_arg="--media $media" dia_arg="-p $media " gs_arg="-F media=@$media" ;; --dbd) dbd=true rbow_account=dbd gs_account=dbd mastodon_account=endDRM@hostux.social shift ;; -v) video=true media="$2" shift 2 ;; esac done if [[ $media ]]; then if [[ ! -e $media ]]; then echo "error: file not found $media" return 1 fi if [[ $media == *\ * ]]; then echo "error: file path contains a space. move it to non-space path" return 1 fi fi # if we have no argument if (( ! $# )); then read -r -p "input PDT text: " input set -- "$input" fi if [[ $- == *i* ]]; then echo "About to PDT the following line. Press enter to confirm or ctrl-c to quit:" echo "$input" read fi if $video; then local oath oath=$HOME/.rainbow_oauth account=fsf if $dbd; then account=dbd fi rm -f $oath ln -s ${oath}-$account $oath python3 ~/src/video-tweet/async-upload.py "$media" "$*" return fi fails=() if ! rbow -$rbow_account t "$*" $rbow_arg; then fails+=(tweet) fi if ! toot -$mastodon_account post "$*" $toot_arg; then fails+=(toot) fi # https://gnusocial.net/doc/twitterapi if ! curl -o /dev/null -sS -u "$gs_account:$(cat ~/.gnusocial_login-$gs_account)" \ $gs_arg -F "status=$*" https://status.fsf.org/api/statuses/update.xml; then fails+=(gnu-social) fi if (( ${#fails[@]} )); then printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(eval echo "{1..${COLUMNS:-60}}"); echo echo "FSF ERROR: ${fails[*]} might not have posted" >&2 fi } # Usage: pdt-setup pdt-setup() { if [[ $pdttest ]]; then mastodon_accounts=(iank) else mastodon_accounts=(fsf endDRM) fi mkdir -p ~/src cd ~/src for repo in errhandle rainbowstream video-tweet; do if [[ -e $repo ]]; then cd $repo git fetch git reset --hard origin/master git clean -xfffd cd .. else git clone https://vcs.fsf.org/git/$repo.git fi done source ~/src/errhandle/err cp ~/src/rainbowstream/rainbowstream/colorset/config ~/.rainbow_config.json if [[ ! -e ~/.local/bin/pip ]]; then tmp=$(mktemp) pyver=$(python3 --version | sed -r 's/.*(3\.[0-9]+).*/\1/') echo fyi: detected pyver: $pyver. this should look something like 3.6 # the bootstrap script at https://bootstrap.pypa.io/get-pip.py requires 3.7+ # as I write this. wget -O$tmp https://bootstrap.pypa.io/pip/$pyver/get-pip.py python3 $tmp --user hash -r fi python3 -m pip install --user -U virtualenv cd ~/src/rainbowstream python3 -m virtualenv -p python3 venv source venv/bin/activate python3 -m pip install -r requirements.txt python3 -m pip install -e . deactivate rm -rf ~/src/toot mkdir -p ~/src/toot cd ~/src/toot python3 -m virtualenv -p python3 venv source venv/bin/activate # pip freeze after a pip install. cat >requirements.txt <<'EOF' beautifulsoup4==4.8.2 certifi==2019.11.28 chardet==3.0.4 idna==2.8 requests==2.22.0 soupsieve==1.9.5 toot==0.25.2 urllib3==1.25.8 urwid==2.1.0 wcwidth==0.1.8 EOF python3 -m pip install -r requirements.txt deactivate for account in dbd fsf; do if [[ ! -s ~/.rainbow_oauth-$account ]]; then printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(eval echo "{1..${COLUMNS:-60}}"); echo "Please login to $account on twitter in your main browser then press enter. After rainbowstream prompt loads, quit with command q" read -r rbow -$account fi for account in dbd fsf; do if [[ ! -s $HOME/.rainbow_oauth-$account ]]; then echo "pdt-setup error: expected non-empty file at $HOME/.rainbow_oauth-$account by this point. please fix and rerun pdt-setup or contact ian" return 1 fi done if diff -q $HOME/.rainbow_oauth-fsf $HOME/.rainbow_oauth-dbd &>/dev/null; then 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" return 1 fi if [[ ! -s ~/.gnusocial_login-$account ]]; then printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(eval echo "{1..${COLUMNS:-60}}"); read -r -p "please enter the password for $account@status.fsf.org > " pass touch ~/.gnusocial_login-$account chmod 600 ~/.gnusocial_login-$account printf "%s\n" "$pass" > ~/.gnusocial_login-$account fi done for account in ${mastodon_accounts[@]}; do if ! toot activate $account@hostux.social &>/dev/null; then printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(eval echo "{1..${COLUMNS:-60}}"); echo "Please login to $account on https://hostux.social in your main browser then press enter." read -r toot login -i hostux.social fi done err-allow echo "pdt-setup complete" }