From f9ace6061208acf9200fb5d8794e52fe4217c131 Mon Sep 17 00:00:00 2001 From: Ian Kelling Date: Thu, 1 Dec 2022 03:09:46 -0500 Subject: [PATCH] add alt text for twitter --- pdt.sh | 132 ++++++++++++++++++++++++++++++++++++++++++--------------- t.py | 59 ++++++++++++++++++++++++++ 2 files changed, 157 insertions(+), 34 deletions(-) create mode 100755 t.py diff --git a/pdt.sh b/pdt.sh index bc388cc..d4952eb 100644 --- a/pdt.sh +++ b/pdt.sh @@ -20,6 +20,36 @@ PATH="$HOME/.local/bin:$PATH" + +_pdtsh_file="$(readlink -f -- "${BASH_SOURCE[0]}")" +_pdtsh_dir="${_pdtsh_file%/*}" +_pdtsh_tweet="$_pdtsh_dir/t.py" + +# usage: tweet [-PROFILE_NAME] [POST...] +# Uses variables as input: +# $media for image file path. +# $alt_text for image alt text. +tweet() { + local oath + oath=$HOME/.rainbow_oauth + if [[ $1 == -* ]]; then + rm -f $oath + ln -s $oath$1 $oath + shift + fi + source ~/src/twitter/venv/bin/activate + { + printf "%s\n" "$*" + if [[ $media ]]; then + printf "%s\n" "$media" + if [[ $alt_text ]]; then + printf "%s\n" "$alt_text" + fi + fi + } | $_pdtsh_tweet + deactivate +} + # usage: rbow [-PROFILE_NAME] [COMMAND] # # Wrapper for rainbowstream to use multiple logins and tweet directly @@ -57,6 +87,7 @@ EOF deactivate } + # usage: toot [-PROFILE_NAME] [TOOT_ARGS] toot() { local mast_profile @@ -79,18 +110,19 @@ toot() { # Alt text only goes to mastodon. # # usage: pdt [-s mastodon|twitter|gnusocial] [--dbd] [-m IMAGE_FILE] [-a ALT_TEXT] [-v VIDEO_PATH] [POST] -# -s = post to single social network supplied by argument. +# -s mastodon|twitter|gnusocial = post to a single social network. # -m IMAGE_FILE = Uploads IMAGE_FILE. if MEDIA_FILE.txt exists, the last line of that file will be used as ALT_TEXT # unless -a has been used. pdt() { - local video media rbow_account gs_account mastodon_account dbd video rbow_arg gs_arg alt_text + local video media twitter_account gs_account mastodon_account video gs_arg alt_text network + local do_mastodon do_twitter do_gnusocial local -a toot_args if [[ $pdttest ]]; then - rbow_account=iank + twitter_account=iank gs_account=fsfes mastodon_account=fsftest@hostux.social else - rbow_account=fsf + twitter_account=fsf gs_account=fsf mastodon_account=fsf@hostux.social fi @@ -130,12 +162,11 @@ pdt() { -m) media="$2" shift 2 - rbow_arg=" --i $media" toot_args+=(--media "$media" ) gs_arg="-F media=@$media" ;; --dbd) - rbow_account=dbd + twitter_account=dbd gs_account=dbd mastodon_account=endDRM@hostux.social shift @@ -174,13 +205,13 @@ pdt() { local oath oath=$HOME/.rainbow_oauth rm -f $oath - ln -s ${oath}-$rbow_account $oath + ln -s ${oath}-$twitter_account $oath python3 ~/src/video-tweet/async-upload.py "$media" "$*" return fi fails=() if $do_twitter; then - if ! rbow -$rbow_account t "$*" $rbow_arg; then + if ! tweet -$twitter_account "$*"; then fails+=(tweet) fi fi @@ -210,10 +241,13 @@ pdt() { # errhandle. # # note: auth info is stored at ~/.config/toot/config.json -toot-setup() { +pdt-toot-setup() { + local -a twitter_accounts mastodon_accounts if [[ $pdttest ]]; then + twitter_accounts=(iank) mastodon_accounts=(fsftest) else + twitter_accounts=(fsf dbd) mastodon_accounts=(fsf endDRM) fi @@ -267,6 +301,7 @@ EOF # i mixed in some old packages to get newer toot working on t9. python3 -m pip install -r requirements.txt + cd - deactivate for account in ${mastodon_accounts[@]}; do if ! toot activate $account@hostux.social &>/dev/null; then @@ -299,9 +334,60 @@ pdt-pip-setup() { python3 -m pip install --user -U virtualenv } +# generally only meant to be called internally from pdt-setup +pdt-twitter-setup() { + # twitter setup + mkdir -p ~/src/twitter + cd ~/src/twitter + python3 -m virtualenv -p python3 venv + source venv/bin/activate + # as of 2022-11-30 + cat >requirements.txt <<'EOF' +certifi==2022.9.24 +twitter==1.19.6 +EOF + python3 -m pip install -r requirements.txt + deactivate + cd - + + # note: we could ditch rainbowstream altogether and just pass around + # oath api key string in a password file or something if we learned + # how to get it from the new twitter client im using. I'm just keeping + # this because it works and I like the format of how it stores its + # auth secrets. + 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 + + for account in ${twitter_accounts[@]}; do + if [[ ! -s ~/.rainbow_oauth-$account ]]; then + printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(eval echo "{1..${COLUMNS:-60}}"); + 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" + read -r + rbow -$account + fi + done + for account in ${twitter_accounts[@]}; do + if [[ ! -s $HOME/.rainbow_oauth-$account ]]; then + 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" + return 1 + fi + done + if [[ ! $pdttest ]] && 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 + cd - +} + + # Usage: pdt-setup pdt-setup() { + start_dir="$PWD" mkdir -p ~/src cd ~/src for repo in errhandle rainbowstream video-tweet; do @@ -315,38 +401,16 @@ pdt-setup() { git clone https://vcs.fsf.org/git/$repo.git fi done + cd "$start_dir" source ~/src/errhandle/err cp ~/src/rainbowstream/rainbowstream/colorset/config ~/.rainbow_config.json pdt-pip-setup - toot-setup + pdt-toot-setup - 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 + pdt-twitter-setup - 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 - done - 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. try reruning pdt-setup and logging in to the correct twitter account in browser 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 for account in dbd fsf; do if [[ ! -s ~/.gnusocial_login-$account ]]; then diff --git a/t.py b/t.py new file mode 100755 index 0000000..b7f9504 --- /dev/null +++ b/t.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 + +# based on +# https://github.com/python-twitter-tools/twitter + +import sys +import os +from twitter import * +import fileinput + +# if needed for development, just hardcode +#oauth_token = "" +#oauth_secret = "" + + +first = True +with fileinput.input(files=(os.environ.get('HOME') + os.sep + '.rainbow_oauth'), encoding="utf-8") as f: + # ok, this is dumb, but it works + for line in f: + if first: + oauth_token = line.rstrip() + first = False + else: + oauth_secret = line.rstrip() + +CONSUMER_KEY = 'hJHyPhuU7nSVHrKTVsGVDM4Lw' +CONSUMER_SECRET = '8UCYePqc1y9DY6mg0yQzLoTuq57AIysype2Si63714uACGMCbO' + +t = Twitter(auth=OAuth(oauth_token, oauth_secret, CONSUMER_KEY, CONSUMER_SECRET)) + +tweet_text = input() +have_image = False +try: + image_path = input() + have_image = True +except: + pass + +have_alt = False +try: + alt = input() + have_alt = True +except: + pass + +if have_image: + with open(image_path, "rb") as imagefile: + imagedata = imagefile.read() + t_upload = Twitter(domain='upload.twitter.com', + auth=OAuth(oauth_token, oauth_secret, CONSUMER_KEY, CONSUMER_SECRET)) + id_img = t_upload.media.upload(media=imagedata)["media_id_string"] + +if have_alt: + t_upload.media.metadata.create(media_id=id_img, text=alt) + +if have_image: + t.statuses.update(status=tweet_text, media_ids=id_img) +else: + t.statuses.update(status=tweet_text) -- 2.25.1