Skip to content

Instantly share code, notes, and snippets.

@snapcase
Last active August 29, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save snapcase/8a0f0f86c8bb24ef9c6a to your computer and use it in GitHub Desktop.
Save snapcase/8a0f0f86c8bb24ef9c6a to your computer and use it in GitHub Desktop.
subscribe to maps
#!/bin/bash
#
# subscribe to files from reflexfiles.com
# snapcase 2015
#
# variables
BASE_URL="http://reflexfiles.com"
maps_path="${HOME}/reflex/base/internal/maps"
verbose=true
update=false
list=false
message() {
cat << EOF
Usage: $0 [-p path] [-l | -u] [-a id] [-r id]
Options:
-p, --path <directory>
maps are located in <directory>
-l, --list display subscribed maps
-a, --add <id> add map
-r, --remove <id> remove map
-u, --update update all subscribed maps
-q, --quiet do not write messages on standard output
-h, --help display this
EOF
}
parse_options() {
while [[ $1 ]]; do
case $1 in
-p | --path ) shift; maps_path=$1 ;;
-u | --update ) update=true ;;
-a | --add ) shift; add=${1//[^0-9]/} ;;
-r | --remove ) shift; remove=${1//[^0-9]/} ;;
-l | --list ) list=true; ;;
-q | --quiet ) verbose=false ;;
-h | --help ) message; exit ;;
* ) message; exit 1 ;;
esac
shift
done
}
die() { error "$*"; exit 1; }
error() { printf "error: $*\n" >&2; }
info() { printf ":: $*\n"; }
validate_path() {
# make sure path exists
if [[ -d $maps_path ]]; then
cd "$maps_path"
else
die "Path not found"
fi
}
unixtime() {
# seconds since the Unix epoch
date -d "$1" +%s
}
timestamp() {
# return timestamp
local released="$1" updated="$2"
if [[ $updated = "---" ]]; then
printf "%d\n" "$(unixtime $released)"
else
printf "%d\n" "$(unixtime $updated)"
fi
}
dlmap() {
# download map and create symlink
local id="$1" file ts uid
typeset -a arr
# 0=released, 1=uid, 2=updated (optional)
IFS=$'\n' read -d '' -r -a arr < \
<(wget -qO- "${BASE_URL}/file/${id}" | \
sed -n 's|hrs|hours|g
/<b>Released:/s|.*</b>\([^<]*\).*|\1|p
/<b>Last Revised:/h
/piwik_download/s|.*/download/\([^/]*\).*|\1|p
${x;s|.*Revised: </b>\([^<]*\).*|\1|p}')
[[ ! ${#arr[@]} -ge 2 ]] && die "Map (id:${id}) not found"
uid="${arr[1]}"
# update requested
[[ $# -eq 2 && -f ".sub_${id}_${lfiles[$id]%-*}-${uid}" ]] && return 2
ts="$(timestamp "${arr[0]}" "${arr[2]:----}")"
file=$(wget -qO- "${BASE_URL}/download/${uid}/latest" | \
bsdtar -s ',.*/,,' -xvf - \*.map 2>&1 | awk '{print $2}')
if [[ $? -eq 0 ]]; then
ln -s "$file" ".sub_${id}_${ts}-${uid}"
$verbose && info "Downloaded $file (id:${id})"
fi
}
add() {
# add new file
local id=$1
if [[ ${lfiles[$id]} ]]; then
die "File already exists"
else
dlmap $id
fi
}
remove() {
# remove file
local id=$1 symlink file
if [[ ${lfiles[$id]} ]]; then
symlink=".sub_${id}_${lfiles[$id]}"
file="$(readlink $symlink)"
rm -- "$symlink"
rm -- "$file"
$verbose && info "Removed ${file} (id:${id})"
else
die "File to be removed does not exist"
fi
}
update() {
local i=0 ts
[[ ${#lfiles[@]} -eq 0 ]] && die "No files to update"
parse_files
for id in "${!lfiles[@]}"; do
ts="${lfiles[$id]%-*}"
uid="${lfiles[$id]##*-}"
if (( ${files[$id]} - $ts > 120 )); then
if dlmap "$id" "$uid"; then
rm ".sub_${id}_${ts}-${uid}"
(( ++i ))
fi
fi
done
if [[ i -eq 0 ]] && $verbose; then
info "Nothing to do"
fi
}
list() {
# list local files
[[ ${#lfiles[@]} -eq 0 ]] && die "There's no files"
for id in "${!lfiles[@]}"; do
printf "%5d -> %s\n" $id "$(readlink .sub_${id}_*)"
done
exit 0
}
local_files() {
# construct an array of local files
typeset -a arr
while IFS=_ read -r -a arr; do
lfiles[${arr[1]}]=${arr[2]}
done < <(find . -maxdepth 1 -name '.sub_[0-9]*_[0-9]*-S*')
}
parse_files() {
# "parse" /files using sed and populate the $files array
typeset -a arr
while IFS=$'\t' read -r -a arr; do
# 0=id, 1=released, 2=updated
ts="$(timestamp "${arr[1]}" "${arr[2]}")"
files[${arr[0]}]=$ts
done < \
<(wget -qO- "${BASE_URL}/files" | \
sed -n \
'/filetablerow1/{
s|^[ ]*||
s|</td>|&\n|g
s|</tr>|&\t|g
s|hrs|hours|g
s|[^/]*/file/\([0-9]\+\)">\([^<]*\)\([^\n]*\n\)\{3\}<td>\([^<]*\)</td>\n<td>\([^<]*\)[^\t]*\t|\1\t\4\t\5\n|g
s|</table>\r||
s|\n$||
p
}')
}
declare -A files # id->timestamp
declare -A lfiles # id->timestamp
parse_options "$@"
validate_path
local_files
$list && list
[[ $add ]] && add $add
[[ $remove ]] && remove $remove
$update && update
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment