diff --git a/container/src/finance/lib/internal/lib_fetch.bash b/container/src/finance/lib/internal/lib_fetch.bash index 9bf840f..4b35275 100644 --- a/container/src/finance/lib/internal/lib_fetch.bash +++ b/container/src/finance/lib/internal/lib_fetch.bash @@ -63,7 +63,7 @@ function lib_fetch::__parse_args() Asset values (see documentation): - price${global_arg_delim_2} + price${global_arg_delim_2} api${global_arg_delim_2} @@ -277,12 +277,15 @@ function lib_fetch::__parse_args() # Arg: api if [ ! -z "$_arg_api" ]; then - if [[ ! "$_arg_api" =~ ^coingecko$|^mobula$ ]]; then - lib_utils::die_usage "$_usage" - fi - declare -gr global_arg_api="$_arg_api" + read -ra _read <<<"$_arg_api" + for _arg in "${_read[@]}"; do + if [[ ! "$_arg" =~ ^coingecko$|^mobula$ ]]; then + lib_utils::die_usage "$_usage" + fi + done + declare -gr global_arg_api=("${_read[@]}") else - declare -gr global_arg_api="mobula" + declare -gr global_arg_api=("coingecko" "mobula") fi # Arg: account @@ -539,88 +542,13 @@ function lib_fetch::__fetch_account() fi } -function lib_fetch::__fetch_price() +function lib_fetch::__parse_price() { - # - # Test configuration for supported members - # + local _master_prices="$1" + lib_utils::print_debug "$_master_prices" - lib_fetch::__parse_yaml "get-value" "price.${global_arg_api}" &>/dev/null \ - || lib_utils::die_fatal "'${global_arg_api}' is unavailable" - - local -r _members=("key" "asset") - for _member in "${_members[@]}"; do - if _value=$(lib_fetch::__parse_yaml "get-value" "price.${global_arg_api}.${_member}"); then - - if [[ "$_member" == "key" ]]; then - local _api_key="$_value" - [ -z "$_api_key" ] \ - && lib_utils::print_warning "${global_arg_api} has empty ${_member}" - fi - - if [[ "$_member" == "asset" ]]; then - [[ $(lib_fetch::__parse_yaml "get-type" "price.${global_arg_api}.${_member}") != "sequence" ]] \ - && lib_utils::die_fatal "Invalid asset sequence!" - fi - else - lib_utils::die_fatal "$_member is unavailable" - fi - done - - # - # Prepare given assets and filesystem layout - # - - # Get assets from configuration - if [ -z "${global_arg_price[*]}" ]; then - # Parse out each asset - while read _line; do - local _assets+=("$_line") - done < <(lib_fetch::__parse_yaml "get-values" "price.${global_arg_api}.asset") - else - # Get assets from CLI - local _assets=("${global_arg_price[*]}") - fi - - # Set base dir for price files (subdirs will be by year) - local -r _prices_dir="${global_child_profile_flow}/prices" - [ ! -d "$_prices_dir" ] && mkdir -p "$_prices_dir" - - # Prices master file - local -r _master_prices="${_prices_dir}/master.prices" - - lib_utils::print_custom "\n" - lib_utils::print_info \ - "Fetching prices in year '${global_arg_year}' for '${global_parent_profile}/${global_child_profile}' ..." - lib_utils::print_custom "\n" - - # - # Execute fetch for master price file creation - # - - declare -x API_FETCH_YEAR="$global_arg_year" - lib_utils::print_debug "$API_FETCH_YEAR" - - declare -x API_PRICES_PATH="$_master_prices" - lib_utils::print_debug "$API_PRICES_PATH" - - declare -x API_PRICES_API="$global_arg_api" - lib_utils::print_debug "$API_PRICES_API" - - declare -x API_PRICES_KEY="$_api_key" - lib_utils::print_debug "$API_PRICES_KEY" - - declare -x API_PRICES_ASSETS="${_assets[*]}" - lib_utils::print_debug "$API_PRICES_ASSETS" - - lib_fetch::__fetch_exec "prices" "crypto" - - if [ $? -eq 0 ]; then - lib_utils::print_custom "\n" - lib_utils::print_info "Fetching prices completed successfully!" - else - return $? - fi + # Parse master file into respective years + [ ! -f "$_master_prices" ] && lib_utils::die_fatal "Master prices not found!" # # Master prices line format: @@ -628,13 +556,11 @@ function lib_fetch::__fetch_price() # P 2023/01/01 USD 1 # - lib_utils::print_normal "\n ─ Parsing master prices file ..." + lib_utils::print_normal "\n ─ Parsing master prices file" # Temporary storage - local -r _tmp_dir="$(mktemp -d -p /tmp docker-finance_XXX)" - - # Parse master file into respective years - [ ! -f "$_master_prices" ] && lib_utils::die_fatal "Master prices not found!" + local _tmp_dir + _tmp_dir="$(mktemp -d -p /tmp docker-finance_XXX)" lib_utils::print_custom " \e[32m│\e[0m\n" echo "$(<$_master_prices)" \ @@ -648,7 +574,8 @@ function lib_fetch::__fetch_price() if [[ "$global_arg_year" == "all" || "$_year" == "$global_arg_year" ]]; then # Prices year location - local _sub_dir="${_prices_dir}/${_year}" + local _sub_dir + _sub_dir="$(dirname $_master_prices)/${_year}" [ ! -d "$_sub_dir" ] && mkdir -p "$_sub_dir" # Prices year journal @@ -676,9 +603,119 @@ function lib_fetch::__fetch_price() lib_utils::print_debug "$_journal" sort -u -o "$_journal" "$_journal" fi - done + local _return=$? + + # Cleanup + [ -d "$_tmp_dir" ] && rm -fr "$_tmp_dir" + + return $? +} + +function lib_fetch::__fetch_price() +{ + # Reconstruct global API arg into only available API(s) + local _arg_api=() + + # + # Test configuration for supported members + # + + for _api in "${global_arg_api[@]}"; do + + if ! lib_fetch::__parse_yaml "get-value" "price.${_api}" &>/dev/null; then + lib_utils::print_warning "'${_api}' price API is not set" + continue + fi + + local _members=("key" "asset") + for _member in "${_members[@]}"; do + if _value=$(lib_fetch::__parse_yaml "get-value" "price.${_api}.${_member}"); then + + if [[ "$_member" == "key" ]]; then + [ -z "$_value" ] \ + && lib_utils::print_warning "${_api} has empty ${_member}" + fi + + if [[ "$_member" == "asset" ]]; then + [[ $(lib_fetch::__parse_yaml "get-type" "price.${_api}.${_member}") != "sequence" ]] \ + && lib_utils::die_fatal "Invalid asset sequence!" + fi + else + lib_utils::die_fatal "'${_member}' is unavailable" + fi + done + + # Available API(s) + _arg_api+=("$_api") + + done + + [ ${#_arg_api[@]} -eq 0 ] && lib_utils::die_fatal "No price API has been set" + + # + # Prepare given assets and filesystem layout + # + + # Prices master file + # NOTE: base dir of all price files (subdirs will be by year) + local _master_prices="${global_child_profile_flow}/prices/master.prices" + + for _api in "${_arg_api[@]}"; do + + # Get API key from configuration + local _key + _key="$(lib_fetch::__parse_yaml "get-value" "price.${_api}.key")" + + # Get assets from configuration + if [ -z "${global_arg_price[*]}" ]; then + # Parse out each asset + while read _line; do + local _assets+=("$_line") + done < <(lib_fetch::__parse_yaml "get-values" "price.${_api}.asset") + else + # Get assets from CLI + local _assets=("${global_arg_price[*]}") + fi + + lib_utils::print_custom "\n" + lib_utils::print_info \ + "Fetching prices from '${_api}' since year '${global_arg_year}' for '${global_parent_profile}/${global_child_profile}' ..." + lib_utils::print_custom "\n" + + # + # Execute fetch for master prices file creation + # + + declare -x API_FETCH_YEAR="$global_arg_year" + lib_utils::print_debug "$API_FETCH_YEAR" + + declare -x API_PRICES_PATH="$_master_prices" + lib_utils::print_debug "$API_PRICES_PATH" + + declare -x API_PRICES_API="$_api" + lib_utils::print_debug "$API_PRICES_API" + unset _api + + declare -x API_PRICES_KEY="$_key" + lib_utils::print_debug "$API_PRICES_KEY" + unset _key + + declare -x API_PRICES_ASSETS="${_assets[*]}" + lib_utils::print_debug "$API_PRICES_ASSETS" + unset _assets + + lib_fetch::__fetch_exec "prices" "crypto" || return $? + + # + # Parse master prices file into final journal + # + + lib_fetch::__parse_price "$API_PRICES_PATH" || return $? + + done + local -r _return=$? if [ $_return -eq 0 ]; then @@ -688,8 +725,7 @@ function lib_fetch::__fetch_price() fi # Cleanup - [ -d "$_tmp_dir" ] && rm -fr "$_tmp_dir" - [ -f "$_master_prices" ] && rm -f "$_master_prices" + [ -f "$API_PRICES_PATH" ] && rm -f "$API_PRICES_PATH" return $_return } @@ -714,12 +750,16 @@ function lib_fetch::__fetch_exec() [ -z "$_subtype" ] && lib_utils::die_fatal local _dir="${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/fetch" + + local _ifs="$IFS" + IFS=' ' + # TODO: remove no-limit after internal fetching writes per-paginated instead of per-fetch local _php=("/usr/bin/php" "-d" "memory_limit=\"-1\"" "-d" "include_path=\"/usr/local/lib:${_dir}\"") + lib_utils::print_debug "${_php[@]}" - IFS=' ' - lib_utils::print_debug "${_php[*]}" "${_php[@]}" "${_dir}/fetch.php" "$_type" "$_subtype" + IFS="$_ifs" } # vim: sw=2 sts=2 si ai et