gcgetics.sh - Extract cids and ics links from google embedded calendars
This commit is contained in:
6
.editorconfig
Normal file
6
.editorconfig
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*.sh]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
@@ -1,3 +1,5 @@
|
|||||||
# icsutils
|
# icsutils
|
||||||
|
|
||||||
Tools to work with ics files in bash.
|
Tools to work with ics files in bash.
|
||||||
|
|
||||||
|
* `gcgetics.sh` : Extract google calender IDs and ICS links from given embedded google calendar
|
||||||
|
165
gcgetics.sh
Executable file
165
gcgetics.sh
Executable file
@@ -0,0 +1,165 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Author: Martin Winkler
|
||||||
|
# License: Please refer to the repository
|
||||||
|
# Origin: https://winklerfamilie.eu/git/SmallThings/icsutils.git
|
||||||
|
|
||||||
|
# Exit on error. Append "|| true" if you expect an error.
|
||||||
|
set -o errexit
|
||||||
|
# Exit on error inside any functions or subshells.
|
||||||
|
set -o errtrace
|
||||||
|
# Do not allow use of undefined vars. Use ${VAR:-} to use an undefined VAR
|
||||||
|
set -o nounset
|
||||||
|
# Catch the error in case mysqldump fails (but gzip succeeds) in `mysqldump |gzip`
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
# gc = google calendar
|
||||||
|
gc::getIcsUsage() {
|
||||||
|
cat <<USAGE_END
|
||||||
|
Usage: ${0##*/} [OPTIONS] [URL/FILE]
|
||||||
|
|
||||||
|
Parses a google calendar embbeded URL content for any number
|
||||||
|
of containted google calendar id (cid).
|
||||||
|
|
||||||
|
[OPTIONS]
|
||||||
|
--file, -f : Input is a file containing a previous curl
|
||||||
|
of a google calendar embbeded link.
|
||||||
|
--help, -h : Show this help.
|
||||||
|
-- : End of Options.
|
||||||
|
|
||||||
|
[URL/FILE]
|
||||||
|
Such a URL usually starts with:
|
||||||
|
"https://calendar.google.com/calendar/../embed?"
|
||||||
|
Where ".." may be empty or a more specific reference.
|
||||||
|
|
||||||
|
If [URL/FILE] is empty or "-", standard input is used.
|
||||||
|
|
||||||
|
USAGE_END
|
||||||
|
}
|
||||||
|
|
||||||
|
gc::makeIcsUrl() {
|
||||||
|
# Exclude public holiday calendar
|
||||||
|
local rexHoliday='group\.v\.calendar'
|
||||||
|
[[ "${1:?}" =~ $rexHoliday ]] && return 1
|
||||||
|
echo "https://calendar.google.com/calendar/ical/${1}/public/basic.ics"
|
||||||
|
}
|
||||||
|
|
||||||
|
gc::findcid() {
|
||||||
|
local arg=""
|
||||||
|
local content=""
|
||||||
|
local file=0
|
||||||
|
local cids=()
|
||||||
|
local title=()
|
||||||
|
|
||||||
|
local color_green= ; [ -t 1 ] && color_green='\033[1;32m'
|
||||||
|
local color_blue= ; [ -t 1 ] && color_blue='\033[1;34m'
|
||||||
|
local color_red= ; [ -t 1 ] && color_red='\033[2;31m'
|
||||||
|
local color_less= ; [ -t 1 ] && color_less='\033[0m'
|
||||||
|
|
||||||
|
for arg in "${@}" ; do
|
||||||
|
case "$1" in
|
||||||
|
--file|-f)
|
||||||
|
file=1
|
||||||
|
shift 1 ;;
|
||||||
|
--)
|
||||||
|
shift && break ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "${1}" = "-" ]] || [ -z "${1}" ] ; then
|
||||||
|
file=1
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
if (( file )) ; then
|
||||||
|
content=$(<"${1:-"/dev/stdin"}")
|
||||||
|
else
|
||||||
|
# could grep for "cids", but unsure if result is always on one line
|
||||||
|
content="$(curl --silent -L "${1:-}")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
while IFS= read -r line || [[ "${line}" ]] ; do
|
||||||
|
cids+=("${line}")
|
||||||
|
done < <(grep -oP '(?<=")[^"]*@(group|group\.v)\.calendar\.google\.com(?=")' <<<"${content}")
|
||||||
|
|
||||||
|
while IFS= read -r line || [[ "${line}" ]] ; do
|
||||||
|
title+=("${line}")
|
||||||
|
done < <(grep -oP '(?<="title":")[^"]*(?=")' <<<"${content}")
|
||||||
|
|
||||||
|
for i in "${!cids[@]}" ; do
|
||||||
|
printf '%12s: %b%s%b\n' "Title" "${color_green}" "${title[$i]}" "${color_less}"
|
||||||
|
printf '%12s: %s\n' "Calendar ID" "${cids[$i]}"
|
||||||
|
printf '%12s: %b' "ICS Url" "${color_blue}"
|
||||||
|
gc::makeIcsUrl "${cids[$i]}" || printf '%b\n' "${color_red}No ics file for this calendar${color_less}"
|
||||||
|
printf '%b' "${color_less}"
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
gc::getIcs() {
|
||||||
|
local arg=
|
||||||
|
local element=
|
||||||
|
local opt=""
|
||||||
|
|
||||||
|
readonly shortMax=80
|
||||||
|
local shortEnd=0
|
||||||
|
|
||||||
|
local color_yellow= ; [ -t 1 ] && color_yellow='\033[1;33m'
|
||||||
|
local color_less= ; [ -t 1 ] && color_less='\033[0m'
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034 # arg not used
|
||||||
|
for arg in "${@}" ; do
|
||||||
|
case "$1" in
|
||||||
|
--help|-h)
|
||||||
|
gc::getIcsUsage
|
||||||
|
return 0 ;;
|
||||||
|
--file|-f)
|
||||||
|
opt="-f"
|
||||||
|
shift ;;
|
||||||
|
--)
|
||||||
|
shift && break ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
local args=("${@}")
|
||||||
|
|
||||||
|
# Use standard input if no files are present
|
||||||
|
[ $# -eq 0 ] && args[0]="-"
|
||||||
|
|
||||||
|
for element in "${args[@]}" ; do
|
||||||
|
if [[ $# -gt 1 ]] ; then
|
||||||
|
printf "%b## CID information from: " "${color_yellow}"
|
||||||
|
# Shorten the URL of PATH if it is greater than $shortMax
|
||||||
|
if [[ ${#element} -gt ${shortMax} ]] ; then
|
||||||
|
shortEnd=$((${#element} - shortMax/2))
|
||||||
|
printf '%s[...]%s' \
|
||||||
|
"${element:0:$((shortMax/2))}" \
|
||||||
|
"${element:${shortEnd}:${#element}}"
|
||||||
|
else
|
||||||
|
printf '%s' "${element}"
|
||||||
|
fi
|
||||||
|
printf '%b\n\n' "${color_less}"
|
||||||
|
fi
|
||||||
|
gc::findcid ${opt} "${element}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
### Check if script is _sourced
|
||||||
|
### https://stackoverflow.com/a/28776166
|
||||||
|
_sourced=0
|
||||||
|
if [ -n "${ZSH_EVAL_CONTEXT:-}" ]; then
|
||||||
|
case ${ZSH_EVAL_CONTEXT:-} in *:file) _sourced=1;; esac
|
||||||
|
elif [ -n "${KSH_VERSION:-}" ]; then
|
||||||
|
[ "$(cd "$(dirname -- "$0")" && pwd -P)/$(basename -- "$0")" \
|
||||||
|
!= "$(cd "$(dirname -- "${.sh.file}")" && pwd -P)/$(basename -- "${.sh.file}")" ] && _sourced=1
|
||||||
|
elif [ -n "${BASH_VERSION:-}" ]; then
|
||||||
|
(return 0 2>/dev/null) && _sourced=1
|
||||||
|
else # All other shells: examine $0 for known shell binary filenames
|
||||||
|
# Detects `sh` and `dash`; add additional shell filenames as needed.
|
||||||
|
case ${0##*/} in sh|dash) _sourced=1;; esac
|
||||||
|
fi
|
||||||
|
###
|
||||||
|
|
||||||
|
if (( ! _sourced )); then
|
||||||
|
gc::getIcs "${@}"
|
||||||
|
fi
|
||||||
|
|
Reference in New Issue
Block a user