Things got a little backed up - we're processing the data and things should be back to normal within the hour.

This post has been de-listed

It is no longer included in search results and normal feeds (front page, hot posts, subreddit posts, etc). It remains visible only via the author's post history.

9
[bash] xh: xhamster tool
Author Summary
smorrow is in bash
Post Body

xh:

#!/usr/bin/env bash

# xh: xhamster tool
# intended usage:
# xh save <todo
# or:
# xh user 𝘨𝘪𝘳𝘭 | xh save

# license: public domain
# requires: correctly-set-up edbrowse

# bugs:
# stdout/stderr separation very poor
# redownloads preexisting files
# exit status does not reflect outcome
# verbose and no control over verbosity

# bug reports to https://redd.it/3uw10d or /u/smorrow

function xh_usage
{
    usage="""\
    xh user [-v] [-p] [-u] [-f] 𝘶𝘴𝘦𝘳𝘯𝘢𝘮𝘦|𝘜𝘙𝘓  # print out URLs of [u]ploaded and/or
                                            # [f]avourite [v]ideos and/or [p]hotos
                                            # of given user.  in case of URL, be it
                                            # a /user/𝘶𝘴𝘦𝘳𝘯𝘢𝘮𝘦 URL or a /movies/...
                                            # URL, 𝘶𝘴𝘦𝘳𝘯𝘢𝘮𝘦 is derived from 𝘜𝘙𝘓.
    xh save [𝘜𝘙𝘓 [...]]  # save photo/gallery/videos if 𝘜𝘙𝘓 is given,
                         # else read 𝘜𝘙𝘓 from stdin.
    xh login  # authenticate to xhamster.com
    """

    echo "$usage" |
    sed -E "s/ {4}//" | 
    sed -n "/^xh $1/,/^xh/ p" | sed \$d

    exit 64  # from <sysexits.h>
}
export -f xh_usage

# `xh login` uses edbrowse, `xh user` uses curl.
# we set curl up to use cookie jar created by edbrowse.
jar=$(sed -n '/jar = / s///p' ~/.ebrc)
if [ ! -z "$jar" ]
then
  function curl
  {
    command curl --cookie "$jar" "$@"
  }
  export -f curl
fi

#if [[ "$1" =~ '^(user|save|login)$' ]]
if [ "$1" = user -o\
     "$1" = save -o\
     "$1" = login\
   ]
then
    cmd="$0_$1"  # like "xh_$1" but also works if $0 not in $PATH
    shift
    $cmd "$@"
    exit
else
    # subshells protect us from xh_usage's exit call
    (xh_usage user)
    (xh_usage save)
    xh_usage login
fi

xh_save:

#!/bin/sh

if [ $# = 0 ]
then
    # URLs from stdin
    set -- `cat`
    [ $# = 0 ] && exit
fi

e(){ echo $*; }

# normalise URL
N()
{
    xh=xhamster.com/
    e $1 |
    sed -E "s_://(.*)${xh}_://en.m.${xh}_" |
    sed    's_\?.*__'
}

# dest filename
rename()
{
    n=`e $1 | egrep -o [0-9]  | sed q`
    e ${n}_$(basename $1 .html).mp4
}


for url
do
    source=`N $url`
    target=`rename $source`
    e  b $source  # browse to $source
    e  /{MP4}/g   # click on link "MP4"
    e  w $target  # save to $target
done | edbrowse -d0

xh_user:

#!/usr/bin/env bash

set -e

### part one
### parse -opts, set corresponding globals

eval set -- `getopt -o vpuf -- "$@"`

uploaded=new  # peculiarity of xh URLs

# comma-separated lists-to-be
nouns=
adjs=

# $var  = ","   str;  $1 is var, $2 is str
function  = { eval $1='$'$1,$2; }

# build our lists from args
while [ $1 != -- ]
do
    case $1 in
        -v)   = nouns video ;;
        -p)   = nouns photo ;;

        -u)   = adjs $uploaded ;;
        -f)   = adjs favorite ;;

         *)  xh_usage user ;;  # exit
    esac
    shift  # walk $@
done

# clean up edge case
[[ $nouns =~ ^, ]] &&
    nouns=${nouns/,/}
[[ $adjs =~ ^, ]] &&
    adjs=${adjs/,/}

# make bash {1,2,3} expansions
[[ $nouns =~ , ]] &&
    nouns={$nouns}
[[ $adjs =~ , ]] &&
    adjs={$adjs}

# otherwise, sensible defaults
: ${nouns:=video}
: ${adjs:=$uploaded}

shift  # skip over "--"

# there should be precisely one arg remaining which is an
# URL or username.

if [ $# != 1 ]
then
    xh_usage user  # exit
fi

### part two
### determine username from $1

# if !is-url
if [[ ! "$1" =~ / ]]
then
    username=$1
    proto=http
else
    # normalise URL
    function N
    {
        xh=xhamster.com/
        echo $1 |
        sed -E "s_://(.*)${xh}_://en.${xh}_" |
        sed    's_\?.*__'
    }

    proto=$(sed<<<$1 's_://.*__')

    case "$1" in
        */user/*)
            username=$(sed<<<"$1" 's_.*/__') ;;
        *)
            tag="<[^>]*>"
            added="(Added|Posted) by"
            link="<a href"
            username=$(
                # "Added by ..." pattern won't occur if we don't use `N`
                curl -s `N $1` | 
                sed -n -E "/$added/,/$link/ {/user/p}" |
                sed "s/$tag//g"  |  tr -d " \t"
            ) ;;
    esac
fi

### part three
### do download based on username/nouns/adjs,  print out target URLs

# use eval to get at {,} expansions in substituted vars
eval curl -s $proto://en.xhamster.com/user/$nouns/$username/$adjs-{1..100}.html |
egrep -o 'https?://([^>]*)xhamster.com/(photos/(view|gallery)|movies)/([^>]*).html'

xh_login:

#!/usr/bin/env bash

# doesn't actually work.  saved as reminder/todo.

# if !isatty(stdin)
if [ ! -t 0 ]
then
    # no-ops
    stty(){ return; }
    echo(){ return; }
fi


echo -n 'username: '

username="""\
/Username:/ 
# fill in form field from stdin
i=$(sed -u q)\
"""

echo -n 'password: '
stty -echo

password="""\
/Password:/ 
# as before
i=$(sed -u q)\
"""

stty echo

more="""\
/Remember Me:/
# check checkbox (or else other edbrowse/curl instances won't be authed)
i= 
# focus <Login> button
/<Login>/
# click
i*
qt
"""

{
   # use `builtin echo` so $password will not be visible in argv of /bin/echo process
   builtin echo "$username"
   builtin echo "$password"
   unset password  # in case bash is running with allexport
   builtin echo "$more"
} | edbrowse >/dev/null -d0 https://m.xhamster.com/login.html?light=1

Author
Account Strength
100%
Account Age
11 years
Verified Email
Yes
Verified Flair
No
Total Karma
15,770
Link Karma
4,145
Comment Karma
11,597
Profile updated: 3 days ago
Posts updated: 11 months ago

Subreddit

Post Details

Location
We try to extract some basic information from the post title. This is not always successful or accurate, please use your best judgement and compare these values to the post title and body for confirmation.
Posted
8 years ago