123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- #!/bin/bash
- #
- # addnews
- #
- # News addition helper for the Dragora GNU/Linux-Libre website
- # (https://www.dragora.org)
- #
- #
- # Copyright (C) 2021 Michael Siegel
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- #### INCLUDES ####
- . include/constants || exit 1
- . include/subroutines || exit 1
- #### CONSTANTS ####
- #### GLOBAL PARAMETERS ####
- action=add
- date=
- title=
- url=
- #### FUNCTIONS ####
- _days_in_month() {
- local month="$1"
- local year="$2" # Needs to be YYYY.
- local days_in_month=(31 28 31 30 31 30 31 31 30 31 30 31)
- month="${month#0}" # Strip leading zeroes for use in arithmetic expansion
- if [[ "$month" -eq 2 ]]
- then
- # Give February 29 days if $year is a leap year:
- [[ ("$((year % 4))" -eq 0 && "$((year % 100))" -ne 0) || \
- "$((year % 400))" -eq 0 ]] && days_in_month[1]=29
- fi
- printf '%s' "${days_in_month["$((month - 1))"]}"
- }
- _date_valid () {
- local input="$1"
- local day=
- local month=
- local year=
- local days_max=
- local valid=1
- if [[ ! "$input" =~ [0-9]{4}-[0-9]{2}-[0-9]{2} ]]
- then
- valid=0
- else
- year="${input:0:4}"
- month="${input:5:2}"
- day="${input:8:2}"
- if (( 10#"$month" < 1 || 10#"$month" > 12 ))
- then
- _perr "invalid month -- '$month'"
- valid=0
- else
- days_max="$(_days_in_month "$month" "$year")"
- if (( 10#"$day" < 1 || 10#"$day" > 10#"$days_max" ))
- then
- _perr "invalid day of month -- '$day'"
- valid=0
- else
- date_unix_time="$(TZ="$TIMEZONE" \
- date -d "${year#0}-${month#0}-${day#0}" '+%s')"
- if (( 10#"$date_unix_time" < 0 ))
- then
- _perr "date out of range (negative Unix time) -- '$input'"
- valid=0
- fi
- fi
- fi
- fi
- [[ "$valid" -eq 0 ]] && return 1
- return 0
- }
- _prompt_date() {
- local input=
- local date_default; date_default="$(date +%Y-%m-%d)"
- while true
- do
- if [[ -z "$input" ]]
- then
- printf '%s\n' "Please enter the publishing date [$date_default]:"
- printf '%s\n' "$HELP_TIP_INTERACTIVE"
- fi
- read -rp "$PROMPT" input
- if [[ -z "$input" ]]
- then
- date="$date_default"
- break
- elif [[ "$input" = "$HELP_COMMAND" ]]
- then
- _show_help "$FUNCNAME"
- elif ! _date_valid "$input" # _date_valid prints error messages.
- then
- printf '%s\n' "$HELP_TIP_INTERACTIVE"
- else
- date="$input"
- break
- fi
- done
- }
- _prompt_title() {
- local input=
- while true
- do
- if [[ -z "$input" ]]
- then
- printf '%s\n' 'Please enter a title:'
- printf '%s\n' "$HELP_TIP_INTERACTIVE"
- fi
- read -rp "$PROMPT" input
- if [[ -z "$input" ]]
- then
- continue
- elif [[ "$input" = "$HELP_COMMAND" ]]
- then
- _show_help "$FUNCNAME"
- else
- break
- fi
- done
- title="$input"
- }
- _prompt_url() {
- local input=
- local url_pattern='^https://lists\.nongnu\.org/archive/html/dragora-users/[0-9]{4}-[0-9]{2}/msg[0-9]+\.html$'
- # Hard-coded 'https' because plain HTTP access not available.
- # Kept number of digits before '.html' flexible because not sure if it's
- # constant.
- while true
- do
- if [[ -z "$input" ]]
- then
- printf '%s\n' 'Please enter a URL:'
- printf '%s\n' "$HELP_TIP_INTERACTIVE"
- fi
- read -rp "$PROMPT" input
- if [[ -z "$input" ]]
- then
- continue
- elif [[ "$input" = "$HELP_COMMAND" ]]
- then
- _show_help "$FUNCNAME"
- elif [[ ! ("$input" =~ $url_pattern) ]]
- then
- _perr "invalid URL -- '$input'"
- else
- break
- fi
- done
- url="$input"
- }
- _mk_news_item() {
- printf ' <li>%s\\n <a href="%s">%s</a>\\n </li>' "$date" "$url" "$title"
- # Escaping `\n` so the result can be used in sed.
- }
- _add_news() {
- local news_pg=
- local lang=
- for lang in $(_get_lang_dirs)
- do
- news_pg="${PAGES_DIR}/${lang}/$NEWS_PAGE"
- cp -a -- "$news_pg" "$news_pg".old
- sed -i -- "s|<ul>|<ul>\n$(_mk_news_item)|" "$news_pg"
- done
- unset lang
- }
- _revert() {
- local news_pg=
- local lang=
- for lang in $(_get_lang_dirs)
- do
- news_pg="${PAGES_DIR}/${lang}/$NEWS_PAGE"
- if [[ -e "$news_pg".old ]]
- then
- mv -- "$news_pg".old "$news_pg" || return 1
- else
- _perr "cannot find backup file -- ${news_pg}.old"
- fi
- done
- unset lang
- }
- _show_help() {
- case "$1" in
- global)
- cat <<'EOF'
- Add a news item interactively
- Usage:
- addnews [OPTIONS]
- Options:
- -r Revert latest news addition
- --help
- Show this help text and exit
- EOF
- ;;
- *)
- printf '%s\n' "Sorry, no help text available."
- ;;
- esac
- }
- #### MAIN ####
- ## Environment checks
- _env_checks || _abort
- ## Action
- while [[ "$#" -gt 0 ]]
- do
- case "$1" in
- -r)
- shift
- action=revert
- ;;
- --help)
- _show_help global
- exit
- ;;
- --) # End of options
- shift
- break
- ;;
- *)
- _perr "invalid argument -- '$1'"
- exit 1
- ;;
- esac
- done
- if [[ "$action" = revert ]]
- then
- _revert || _abort
- else
- _prompt_date || _abort
- _prompt_title || _abort
- _prompt_url || _abort
- _add_news || _abort
- fi
|