From 7f93410bba2882797dc5d9ff7d0b52338c951f27 Mon Sep 17 00:00:00 2001 From: Felix Lohmeier Date: Fri, 25 Mar 2022 11:16:02 +0100 Subject: [PATCH] first draft --- orcli | 467 ++++++++++++++++++++++++++++++++++++++++++++ src/bashly.yml | 35 ++++ src/info_command.sh | 5 + src/initialize.sh | 6 + src/lib/error.sh | 4 + src/lib/get_csrf.sh | 12 ++ src/lib/get_id.sh | 21 ++ src/list_command.sh | 7 + 8 files changed, 557 insertions(+) create mode 100755 orcli create mode 100644 src/bashly.yml create mode 100644 src/info_command.sh create mode 100644 src/initialize.sh create mode 100644 src/lib/error.sh create mode 100644 src/lib/get_csrf.sh create mode 100644 src/lib/get_id.sh create mode 100644 src/list_command.sh diff --git a/orcli b/orcli new file mode 100755 index 0000000..24015ff --- /dev/null +++ b/orcli @@ -0,0 +1,467 @@ +#!/usr/bin/env bash +# This script was generated by bashly 0.7.8 (https://bashly.dannyb.co) +# Modifying it manually is not recommended + +# :script.bash3_bouncer +if [[ "${BASH_VERSINFO:-0}" -lt 4 ]]; then + printf "bash version 4 or higher is required\n" + exit 1 +fi + +# :command.version_command +version_command() { + echo "$version" +} + +# :command.usage +orcli_usage() { + if [[ -n $long_usage ]]; then + printf "orcli - OpenRefine command-line interface written in Bash\n" + echo + + else + printf "orcli - OpenRefine command-line interface written in Bash\n" + echo + + fi + + printf "Usage:\n" + printf " orcli [command]\n" + printf " orcli [command] --help | -h\n" + printf " orcli --version | -v\n" + echo + # :command.usage_commands + printf "Commands:\n" + echo " info show project metadata" + echo " list list projects on OpenRefine server" + echo + + if [[ -n $long_usage ]]; then + printf "Options:\n" + # :command.usage_fixed_flags + echo " --help, -h" + printf " Show this help\n" + echo + echo " --version, -v" + printf " Show version number\n" + echo + + # :command.usage_environment_variables + printf "Environment Variables:\n" + + # :environment_variable.usage + echo " OPENREFINE_URL" + printf " URL to OpenRefine server\n" + printf " Default: http://localhost:3333\n" + echo + + # :environment_variable.usage + echo " OPENREFINE_CSRF" + printf " set to false for OpenRefine < 3.3\n" + printf " Default: true\n" + echo + # :command.usage_examples + printf "Examples:\n" + + printf " orcli list\n" + printf " orcli info clipboard\n" + printf " orcli info 1234567890123\n" + echo + + fi +} + +# :command.usage +orcli_info_usage() { + if [[ -n $long_usage ]]; then + printf "orcli info - show project metadata\n" + echo + + else + printf "orcli info - show project metadata\n" + echo + + fi + + printf "Usage:\n" + printf " orcli info PROJECT\n" + printf " orcli info --help | -h\n" + echo + + if [[ -n $long_usage ]]; then + printf "Options:\n" + # :command.usage_fixed_flags + echo " --help, -h" + printf " Show this help\n" + echo + + # :command.usage_args + printf "Arguments:\n" + + # :argument.usage + echo " PROJECT" + printf " project name or id\n" + echo + + # :command.usage_examples + printf "Examples:\n" + + printf " info clipboard\n" + printf " info 1234567890123\n" + echo + + fi +} + +# :command.usage +orcli_list_usage() { + if [[ -n $long_usage ]]; then + printf "orcli list - list projects on OpenRefine server\n" + echo + + else + printf "orcli list - list projects on OpenRefine server\n" + echo + + fi + + printf "Usage:\n" + printf " orcli list\n" + printf " orcli list --help | -h\n" + echo + + if [[ -n $long_usage ]]; then + printf "Options:\n" + # :command.usage_fixed_flags + echo " --help, -h" + printf " Show this help\n" + echo + + fi +} + +# :command.normalize_input +normalize_input() { + local arg flags + + while [[ $# -gt 0 ]]; do + arg="$1" + if [[ $arg =~ ^(--[a-zA-Z0-9_\-]+)=(.+)$ ]]; then + input+=("${BASH_REMATCH[1]}") + input+=("${BASH_REMATCH[2]}") + elif [[ $arg =~ ^(-[a-zA-Z0-9])=(.+)$ ]]; then + input+=("${BASH_REMATCH[1]}") + input+=("${BASH_REMATCH[2]}") + elif [[ $arg =~ ^-([a-zA-Z0-9][a-zA-Z0-9]+)$ ]]; then + flags="${BASH_REMATCH[1]}" + for (( i=0 ; i < ${#flags} ; i++ )); do + input+=("-${flags:i:1}") + done + else + input+=("$arg") + fi + + shift + done +} +# :command.inspect_args +inspect_args() { + readarray -t sorted_keys < <(printf '%s\n' "${!args[@]}" | sort) + if (( ${#args[@]} )); then + echo args: + for k in "${sorted_keys[@]}"; do echo "- \${args[$k]} = ${args[$k]}"; done + else + echo args: none + fi + + if (( ${#other_args[@]} )); then + echo + echo other_args: + echo "- \${other_args[*]} = ${other_args[*]}" + for i in "${!other_args[@]}"; do + echo "- \${other_args[$i]} = ${other_args[$i]}" + done + fi +} + +# :command.user_lib +# :src/lib/error.sh +# log error message to STDERR +function error { + echo >&2 "[$(date +'%Y-%m-%dT%H:%M:%S')]: ERROR $*" +} + +# :src/lib/get_csrf.sh +# get CSRF token (introduced in OpenRefine 3.3) +function get_csrf { +if [[ "${OPENREFINE_CSRF}" == true ]]; then + local response + response=$(curl -fs "${OPENREFINE_URL}/command/core/get-csrf-token") + if ! [[ "${response}" == '{"token":"'* ]]; then + error "getting CSRF token failed!" + exit 1 + fi + echo "?csrf_token=$(echo "$response" | cut -d \" -f 4)" +fi +} + +# :src/lib/get_id.sh +# get project id (derived from project name if needed) +function get_id { +local response +local projects +local ids +if ! response="$(curl -fs --get "${OPENREFINE_URL}/command/core/get-all-project-metadata")"; then + error "no OpenRefine reachable/running at ${OPENREFINE_URL}" + exit 1 +fi +if ! projects="$(echo "$response" | jq -r '.projects | keys[] as $k | "\($k):\(.[$k] | .name)"' | grep "${args[project]}")"; then + error "project ${args[project]} not found" + exit 1 +fi +ids=$(echo "$projects" | cut -d : -f 1) +if ! [[ "${#ids}" == 13 ]]; then + error "multiple projects found" + echo >&2 "$projects" + exit 1 +fi +echo "$ids" +} + +# :command.command_functions +# :command.function +orcli_info_command() { + # :src/info_command.sh + echo "# this file is located in 'src/info_command.sh'" + echo "# code for 'openrefine-cli.sh info' goes here" + echo "# you can edit it freely and regenerate (it will not be overwritten)" + inspect_args + get_id +} + +# :command.function +orcli_list_command() { + # :src/list_command.sh + # get all project metadata and reshape json to print a list + if ! response="$(curl -fs --get "${OPENREFINE_URL}/command/core/get-all-project-metadata")" + then + error "no OpenRefine reachable/running at ${OPENREFINE_URL}" + else + echo "$response" | jq -r '.projects | keys[] as $k | "\($k):\(.[$k] | .name)"' + fi +} + +# :command.parse_requirements +parse_requirements() { + # :command.fixed_flag_filter + case "${1:-}" in + --version | -v ) + version_command + exit + ;; + + --help | -h ) + long_usage=yes + orcli_usage + exit + ;; + + esac + # :command.environment_variables_filter + export OPENREFINE_URL="${OPENREFINE_URL:-http://localhost:3333}" + export OPENREFINE_CSRF="${OPENREFINE_CSRF:-true}" + # :command.dependencies_filter + if ! [[ -x "$(command -v curl)" ]]; then + printf "missing dependency: curl\n" + exit 1 + fi + if ! [[ -x "$(command -v jq)" ]]; then + printf "missing dependency: jq\n" + exit 1 + fi + # :command.command_filter + action=${1:-} + + case $action in + -* ) + ;; + + info ) + action="info" + shift + orcli_info_parse_requirements "$@" + shift $# + ;; + + list ) + action="list" + shift + orcli_list_parse_requirements "$@" + shift $# + ;; + + # :command.command_fallback + * ) + orcli_usage + exit 1 + ;; + + esac + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?* ) + printf "invalid option: %s\n" "$key" + exit 1 + ;; + + * ) + # :command.parse_requirements_case + printf "invalid argument: %s\n" "$key" + exit 1 + ;; + + esac + done + # :command.required_args_filter + # :command.required_flags_filter + # :command.catch_all_filter + # :command.default_assignments + # :command.whitelist_filter + # :command.user_filter +} + +# :command.parse_requirements +orcli_info_parse_requirements() { + # :command.fixed_flag_filter + case "${1:-}" in + --help | -h ) + long_usage=yes + orcli_info_usage + exit + ;; + + esac + # :command.environment_variables_filter + # :command.dependencies_filter + # :command.command_filter + action="info" + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?* ) + printf "invalid option: %s\n" "$key" + exit 1 + ;; + + * ) + # :command.parse_requirements_case + if [[ -z ${args[project]+x} ]]; then + # :argument.validations + args[project]=$1 + shift + else + printf "invalid argument: %s\n" "$key" + exit 1 + fi + ;; + + esac + done + # :command.required_args_filter + if [[ -z ${args[project]+x} ]]; then + printf "missing required argument: PROJECT\nusage: orcli info PROJECT\n" + exit 1 + fi + # :command.required_flags_filter + # :command.catch_all_filter + # :command.default_assignments + # :command.whitelist_filter + # :command.user_filter +} + +# :command.parse_requirements +orcli_list_parse_requirements() { + # :command.fixed_flag_filter + case "${1:-}" in + --help | -h ) + long_usage=yes + orcli_list_usage + exit + ;; + + esac + # :command.environment_variables_filter + # :command.dependencies_filter + # :command.command_filter + action="list" + # :command.parse_requirements_while + while [[ $# -gt 0 ]]; do + key="$1" + case "$key" in + + -?* ) + printf "invalid option: %s\n" "$key" + exit 1 + ;; + + * ) + # :command.parse_requirements_case + printf "invalid argument: %s\n" "$key" + exit 1 + ;; + + esac + done + # :command.required_args_filter + # :command.required_flags_filter + # :command.catch_all_filter + # :command.default_assignments + # :command.whitelist_filter + # :command.user_filter +} + +# :command.initialize +initialize() { + version="0.1.0" + long_usage='' + set -e + + # :src/initialize.sh +} + +# :command.run +run() { + declare -A args=() + declare -a other_args=() + declare -a input=() + normalize_input "$@" + parse_requirements "${input[@]}" + + if [[ $action == "info" ]]; then + if [[ ${args[--help]:-} ]]; then + long_usage=yes + orcli_info_usage + else + orcli_info_command + fi + + elif [[ $action == "list" ]]; then + if [[ ${args[--help]:-} ]]; then + long_usage=yes + orcli_list_usage + else + orcli_list_command + fi + + elif [[ $action == "root" ]]; then + root_command + fi +} + +initialize +run "$@" diff --git a/src/bashly.yml b/src/bashly.yml new file mode 100644 index 0000000..a3d0a0b --- /dev/null +++ b/src/bashly.yml @@ -0,0 +1,35 @@ +name: orcli +help: OpenRefine command-line interface written in Bash +version: 0.1.0 + +dependencies: +- curl +- jq + +environment_variables: +- name: OPENREFINE_URL + help: URL to OpenRefine server + default: "http://localhost:3333" +- name: OPENREFINE_CSRF + default: "true" + help: set to false for OpenRefine < 3.3 + +examples: +- orcli list +- orcli info clipboard +- orcli info 1234567890123 + +commands: + +- name: info + help: show project metadata + args: + - name: project + help: project name or id + required: true + examples: + - info clipboard + - info 1234567890123 + +- name: list + help: list projects on OpenRefine server diff --git a/src/info_command.sh b/src/info_command.sh new file mode 100644 index 0000000..2efddfb --- /dev/null +++ b/src/info_command.sh @@ -0,0 +1,5 @@ +echo "# this file is located in 'src/info_command.sh'" +echo "# code for 'openrefine-cli.sh info' goes here" +echo "# you can edit it freely and regenerate (it will not be overwritten)" +inspect_args +get_id diff --git a/src/initialize.sh b/src/initialize.sh new file mode 100644 index 0000000..3cfee95 --- /dev/null +++ b/src/initialize.sh @@ -0,0 +1,6 @@ +## Code here runs inside the initialize() function +## Use it for anything that you need to run before any other function, like +## setting environment vairables: +## CONFIG_FILE=settings.ini +## +## Feel free to empty (but not delete) this file. diff --git a/src/lib/error.sh b/src/lib/error.sh new file mode 100644 index 0000000..41774da --- /dev/null +++ b/src/lib/error.sh @@ -0,0 +1,4 @@ +# log error message to STDERR +function error { + echo >&2 "[$(date +'%Y-%m-%dT%H:%M:%S')]: ERROR $*" +} diff --git a/src/lib/get_csrf.sh b/src/lib/get_csrf.sh new file mode 100644 index 0000000..e10ae5a --- /dev/null +++ b/src/lib/get_csrf.sh @@ -0,0 +1,12 @@ +# get CSRF token (introduced in OpenRefine 3.3) +function get_csrf { +if [[ "${OPENREFINE_CSRF}" == true ]]; then + local response + response=$(curl -fs "${OPENREFINE_URL}/command/core/get-csrf-token") + if ! [[ "${response}" == '{"token":"'* ]]; then + error "getting CSRF token failed!" + exit 1 + fi + echo "?csrf_token=$(echo "$response" | cut -d \" -f 4)" +fi +} diff --git a/src/lib/get_id.sh b/src/lib/get_id.sh new file mode 100644 index 0000000..3a0150a --- /dev/null +++ b/src/lib/get_id.sh @@ -0,0 +1,21 @@ +# get project id (derived from project name if needed) +function get_id { +local response +local projects +local ids +if ! response="$(curl -fs --get "${OPENREFINE_URL}/command/core/get-all-project-metadata")"; then + error "no OpenRefine reachable/running at ${OPENREFINE_URL}" + exit 1 +fi +if ! projects="$(echo "$response" | jq -r '.projects | keys[] as $k | "\($k):\(.[$k] | .name)"' | grep "${args[project]}")"; then + error "project ${args[project]} not found" + exit 1 +fi +ids=$(echo "$projects" | cut -d : -f 1) +if ! [[ "${#ids}" == 13 ]]; then + error "multiple projects found" + echo >&2 "$projects" + exit 1 +fi +echo "$ids" +} diff --git a/src/list_command.sh b/src/list_command.sh new file mode 100644 index 0000000..93cad38 --- /dev/null +++ b/src/list_command.sh @@ -0,0 +1,7 @@ +# get all project metadata and reshape json to print a list +if ! response="$(curl -fs --get "${OPENREFINE_URL}/command/core/get-all-project-metadata")" +then + error "no OpenRefine reachable/running at ${OPENREFINE_URL}" +else + echo "$response" | jq -r '.projects | keys[] as $k | "\($k):\(.[$k] | .name)"' +fi