Last active
November 15, 2020 19:18
-
-
Save schoettl/6b987f587f3c6ba06378fa318b7781ef to your computer and use it in GitHub Desktop.
Script to generate CSV for DHL Online Frankierung CSV-Import
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Script to generate CSV for DHL Online Frankierung CSV-Import. | |
# Dependencies: perl fzf xclip awk iconv | |
printUsage() { | |
cat <<EOF | |
Usage: $PROGNAME [options] | |
Generiert CSV für den CSV-Import bei DHL Online Frankierung: | |
https://www.dhl.de/onlinefrankierung | |
EspoCRM Account URL muss vorher ins Clipboard kopiert werden. | |
Wenn verfügbar wird automatisch ein Coupon Code gewählt | |
(außer wenn -d ist gegeben). | |
Options: | |
-p | |
interactivly select product | |
-c COUPON_CODE | |
coupon code to use | |
-s SENDER | |
sender company prefix (s[xxx] or i[xxx]) | |
default: ixxx | |
-f CSV_FILE | |
append data to given CSV file | |
-r | |
reverse (swap recipient and sender) | |
-h | |
print help message | |
EOF | |
} | |
set -o errexit -o pipefail | |
shopt -s nullglob | |
readonly PROGNAME=${0##*/} | |
readonly COUPON_CODES_DIR=${XDG_DATA_HOME:-~/.local/share/dhl} | |
# ESPOCRM_API_KEY ESPOCRM_API_URL | |
source ~/.parameters-used-in-scripts.sh | |
declare -g SENDER_COMPANY= | |
declare -g SENDER_EMAIL= | |
readonly SENDER_STREET= | |
readonly SENDER_NUMBER= | |
readonly SENDER_ZIP= | |
readonly SENDER_CITY= | |
# $1: error message | |
exitWithError() { | |
declare msg=${1:-} | |
echo "$msg" >&2 | |
exit 1 | |
} | |
# $*: command line arguments = "$@" | |
parseCommandLine() { | |
declare option | |
while getopts 'phs:f:c:r' option; do | |
case $option in | |
h) | |
printUsage | |
exit 0 | |
;; | |
p) declare -gr SELECT_PRODUCT=1 | |
;; | |
r) declare -gr REVERSE=1 | |
;; | |
c) declare -gr COUPON_CODE=$OPTARG | |
;; | |
f) declare -gr CSV_FILE=$OPTARG | |
;; | |
s) | |
case $OPTARG in | |
i*) ;; | |
s*) SENDER_COMPANY= | |
SENDER_EMAIL= | |
;; | |
*) exitWithError "Error: invalid argument for -s option." | |
esac | |
;; | |
*) printUsage >&2 | |
# prints usage after the default error message (invalid option or missing option argument). | |
# default error messages are disabled if the first character of optstring is ":". | |
exit 1 | |
;; | |
esac | |
done | |
shift $((OPTIND-1)) | |
if (( $# != 0 )); then | |
exitWithError "error: no command line arguments allowed." | |
fi | |
return 0 | |
} | |
main() { | |
parseCommandLine "$@" | |
declare url | |
url=$(xclip -o -selection clipboard || true) | |
if [[ $url =~ ^http.*:// ]]; then | |
if ! [[ $url =~ ^http.*://.*/#(Account|Contact)/view/ ]]; then | |
exitWithError "Error: No valid EspoCRM Account URL in clipboard." | |
fi | |
else | |
url= | |
fi | |
declare id=${url##*/} | |
declare jsonFile addressFile | |
jsonFile=$(mktemp) | |
addressFile=$(mktemp) | |
case $url in | |
'') declare tmp | |
tmp=$(mktemp) | |
echo -e "# Name\n# Zusatz (kann weggelassen werden)\n# Straße Hausnummer\n# Ort\n# PLZ\n# Land (oder leere Zeile)" > "$tmp" | |
vim "$tmp" | |
if ! grep -vqE '^#|^ *$' "$tmp"; then | |
exitWithError "Error: Aborting due to empty recepient." | |
fi | |
grep -vE '^#' "$tmp" > "$addressFile" | |
;; | |
*/\#Account/*) | |
entity=Account | |
curl -s -H "X-Api-Key: $ESPOCRM_API_KEY" "$ESPOCRM_API_URL/$entity/$id" > "$jsonFile" | |
printFieldsFromJson name shippingAddressStreet shippingAddressCity shippingAddressPostalCode shippingAddressCountry < "$jsonFile" > "$addressFile" | |
if (( $(grep . "$addressFile" | wc -l) < 4 )); then | |
echo "Warning: No shipping address. Using billing address instead." | |
echo | |
printFieldsFromJson name billingAddressStreet billingAddressCity billingAddressPostalCode billingAddressCountry < "$jsonFile" > "$addressFile" | |
fi | |
;; | |
*/\#Contact/*) | |
entity=Contact | |
curl -s -H "X-Api-Key: $ESPOCRM_API_KEY" "$ESPOCRM_API_URL/$entity/$id" > "$jsonFile" | |
printFieldsFromJson name addressStreet addressCity addressPostalCode addressCountry < "$jsonFile" > "$addressFile" | |
;; | |
esac | |
declare nLines | |
nLines=$(wc -l < "$addressFile") | |
if (( nLines > 6 )); then | |
exitWithError "Error: Too many lines in EspoCRM address fields." | |
fi | |
if (( nLines < 5 )); then | |
exitWithError "Error: Too few lines in EspoCRM address fields." | |
fi | |
#if [[ -n $SHELL ]]; then | |
# vim "$addressFile" | |
# if ! grep . "$addressFile" > /dev/null; then | |
# exitWithError "Empty address file. Canceled." | |
# fi | |
#fi | |
declare name line2 street number zip city streetNumber country | |
#cat "$addressFile" | |
{ | |
read -r name | |
if (( nLines == 6 )); then | |
read -r line2 | |
fi | |
read -r streetNumber | |
read -r city | |
read -r zip | |
read -r country | |
} < "$addressFile" | |
street=${streetNumber% *} | |
number=${streetNumber##* } | |
if [[ -z "$country" ]]; then | |
: | |
elif (( $(printIso3CountryCodes | grep -F --count "$country") == 1 )); then | |
country=$(printIso3CountryCodes | grep -F "$country" | awk '{print $1}') | |
else | |
country=$(printIso3CountryCodes | fzf --delimiter '\t' --query "$country" | awk '{print $1}' || exitWithError "error: no country selected.") | |
fi | |
declare product couponCode | |
if [[ -n $SELECT_PRODUCT ]]; then | |
product=$(printProducts | filterCountry "$country" | fzf --delimiter '\t' | awk '{print $1}') | |
fi | |
if [[ -z $COUPON_CODE && -n $product ]]; then | |
file=$COUPON_CODES_DIR/coupon-codes-$product.txt | |
echo "Trying to lookup coupon code in file:" | |
echo "$file" | |
echo | |
couponCode=$(tryUsingCouponCodeFromList "$file") | |
else | |
couponCode=$COUPON_CODE | |
fi | |
echo "Address:" | |
echo "$name" | |
echo "${line2:-(no second line)}" | |
echo "$street $number" | |
echo "$zip $city" | |
echo "${country:-(default country)}" | |
echo | |
echo "Product: ${product:-(not selected)}" | |
echo "Coupon Code: ${couponCode:-(not selected)}" | |
echo | |
declare targetCsvFile | |
if [[ -z $CSV_FILE ]]; then | |
targetCsvFile=$(mktemp "/tmp/$(date -I)-$(echo "$name" | tr -dc 'a-zA-Z0-9')-XXXXX.csv") | |
printCsvHeader > "$targetCsvFile" | |
else | |
targetCsvFile=$CSV_FILE | |
fi | |
if [[ -z $REVERSE ]]; then | |
linesToCsvLatin1 << TEXT >> "$targetCsvFile" | |
$SENDER_COMPANY | |
$SENDER_STREET | |
$SENDER_NUMBER | |
$SENDER_ZIP | |
$SENDER_CITY | |
$name | |
$line2 | |
$street | |
$number | |
$zip | |
$city | |
$country | |
$product | |
$couponCode | |
$SENDER_EMAIL | |
TEXT | |
else | |
linesToCsvLatin1 << TEXT >> "$targetCsvFile" | |
$name | |
$line2 | |
$street | |
$number | |
$zip | |
$city | |
$country | |
$SENDER_COMPANY | |
$SENDER_STREET | |
$SENDER_NUMBER | |
$SENDER_ZIP | |
$SENDER_CITY | |
$product | |
$couponCode | |
$SENDER_EMAIL | |
TEXT | |
fi | |
echo "Open the DHL page in the browser:" | |
echo "https://www.dhl.de/de/privatkunden/pakete-versenden/online-frankieren.html?type=ShoppingCartImport" | |
echo | |
echo "Copied filename to clipboard:" | |
echo "$targetCsvFile" | |
echo -n "$targetCsvFile" | xclip -i -selection clipboard | |
if (( ${#name} > 50 || ${#line2} > 50 || ${#street} > 50 || ${#city} > 38 )); then | |
echo | |
echo "Warning: Receiver data too long: name (50), name2 (50), street (50), city (38)" | |
echo " Fix this in the output CSV file, before uploading!" | |
fi >&2 | |
} | |
linesToCsvLatin1() { | |
sed -e 's/"/""/g' -e 's/^/"/' -e 's/$/"/' \ | |
| paste -sd';' \ | |
| iconv -futf8 -tlatin1 | |
} | |
printCsvHeader() { | |
cat <<TEXT | |
SEND_NAME1;SEND_NAME2;SEND_STREET;SEND_HOUSENUMBER;SEND_PLZ;SEND_CITY;SEND_COUNTRY;RECV_NAME1;RECV_NAME2;RECV_STREET;RECV_HOUSENUMBER;RECV_PLZ;RECV_CITY;RECV_COUNTRY;PRODUCT;COUPON;SEND_EMAIL | |
TEXT | |
} | |
# https://www.dhl.de/de/privatkunden/pakete-versenden/deutschlandweit-versenden/preise-national.html | |
# https://www.dhl.de/de/privatkunden/pakete-versenden/weltweit-versenden/preise-international.html | |
printProducts() { | |
cat <<TEXT | |
PAECKS.DEU Päckchen S | |
PAECK.DEU Päckchen M | |
PAK02.DEU Paket 2 kg bis 60 x 30 x 15 cm | |
PAK05.DEU Paket 5 kg bis 120 x 60 x 60 cm** | |
PAK10.DEU Paket 10 kg bis 120 x 60 x 60 cm** | |
PAK31.DEU Paket 31,5 kg bis 120 x 60 x 60 cm | |
PAECKXS.EU EU-Päckchen XS EU bis 2 kg | |
PAECK.EU EU-Päckchen | |
PAK02.EU EU-Paket 2 kg bis 60 x 30 x 15 cm | |
PAK05.EU EU-Paket 5 kg bis 120 x 60 x 60 cm | |
PAK10.EU EU-Paket 10 kg bis 120 x 60 x 60 cm | |
PAK20.EU EU-Paket 20 kg bis 120 x 60 x 60 cm | |
PAK315.EU EU-Paket 31,5 kg bis 120 x 60 x 60 | |
TEXT | |
} | |
# from https://unstats.un.org/unsd/tradekb/knowledgebase/country-code | |
# modified with some german country names | |
printIso3CountryCodes() { | |
cat <<TEXT | |
ABW Aruba | |
AFG Afghanistan | |
AGO Angola | |
AIA Anguilla | |
ALA Åland Islands | |
ALB Albania | |
AND Andorra | |
ANT Netherlands Antilles | |
ARE United Arab Emirates | |
ARG Argentina | |
ARM Armenia | |
ASM American Samoa | |
ATA Antarctica | |
ATF French Southern Territories | |
ATG Antigua and Barbuda | |
AUS Australia | |
AUT Austria / Österreich | |
AZE Azerbaijan | |
BDI Burundi | |
BEL Belgium | |
BEN Benin | |
BFA Burkina Faso | |
BGD Bangladesh | |
BGR Bulgaria | |
BHR Bahrain | |
BHS Bahamas | |
BIH Bosnia and Herzegovina | |
BLM Saint Barthélemy | |
BLR Belarus | |
BLZ Belize | |
BMU Bermuda | |
BOL Bolivia, Plurinational State of | |
BRA Brazil | |
BRB Barbados | |
BRN Brunei Darussalam | |
BTN Bhutan | |
BVT Bouvet Island | |
BWA Botswana | |
CAF Central African Republic | |
CAN Canada | |
CCK Cocos (Keeling) Islands | |
CHE Switzerland / Schweiz | |
CHL Chile | |
CHN China | |
CIV Côte d'Ivoire | |
CMR Cameroon | |
COD Congo, the Democratic Republic of the | |
COG Congo | |
COK Cook Islands | |
COL Colombia | |
COM Comoros | |
CPV Cape Verde | |
CRI Costa Rica | |
CUB Cuba | |
CXR Christmas Island | |
CYM Cayman Islands | |
CYP Cyprus | |
CZE Czech Republic | |
DEU Germany / Deutschland | |
DJI Djibouti | |
DMA Dominica | |
DNK Denmark | |
DOM Dominican Republic | |
DZA Algeria | |
ECU Ecuador | |
EGY Egypt | |
ERI Eritrea | |
ESH Western Sahara | |
ESP Spain | |
EST Estonia | |
ETH Ethiopia | |
FIN Finland | |
FJI Fiji | |
FLK Falkland Islands (Malvinas) | |
FRA France | |
FRO Faroe Islands | |
FSM Micronesia, Federated States of | |
GAB Gabon | |
GBR United Kingdom | |
GEO Georgia | |
GGY Guernsey | |
GHA Ghana | |
GIB Gibraltar | |
GIN Guinea | |
GLP Guadeloupe | |
GMB Gambia | |
GNB Guinea-Bissau | |
GNQ Equatorial Guinea | |
GRC Greece | |
GRD Grenada | |
GRL Greenland | |
GTM Guatemala | |
GUF French Guiana | |
GUM Guam | |
GUY Guyana | |
HKG Hong Kong | |
HMD Heard Island and McDonald Islands | |
HND Honduras | |
HRV Croatia | |
HTI Haiti | |
HUN Hungary | |
IDN Indonesia | |
IMN Isle of Man | |
IND India | |
IOT British Indian Ocean Territory | |
IRL Ireland | |
IRN Iran, Islamic Republic of | |
IRQ Iraq | |
ISL Iceland | |
ISR Israel | |
ITA Italy | |
JAM Jamaica | |
JEY Jersey | |
JOR Jordan | |
JPN Japan | |
KAZ Kazakhstan | |
KEN Kenya | |
KGZ Kyrgyzstan | |
KHM Cambodia | |
KIR Kiribati | |
KNA Saint Kitts and Nevis | |
KOR Korea, Republic of | |
KWT Kuwait | |
LAO Lao People's Democratic Republic | |
LBN Lebanon | |
LBR Liberia | |
LBY Libyan Arab Jamahiriya | |
LCA Saint Lucia | |
LIE Liechtenstein | |
LKA Sri Lanka | |
LSO Lesotho | |
LTU Lithuania | |
LUX Luxembourg | |
LVA Latvia | |
MAC Macao | |
MAF Saint Martin (French part) | |
MAR Morocco | |
MCO Monaco | |
MDA Moldova, Republic of | |
MDG Madagascar | |
MDV Maldives | |
MEX Mexico | |
MHL Marshall Islands | |
MKD Macedonia, the former Yugoslav Republic of | |
MLI Mali | |
MLT Malta | |
MMR Myanmar | |
MNE Montenegro | |
MNG Mongolia | |
MNP Northern Mariana Islands | |
MOZ Mozambique | |
MRT Mauritania | |
MSR Montserrat | |
MTQ Martinique | |
MUS Mauritius | |
MWI Malawi | |
MYS Malaysia | |
MYT Mayotte | |
NAM Namibia | |
NCL New Caledonia | |
NER Niger | |
NFK Norfolk Island | |
NGA Nigeria | |
NIC Nicaragua | |
NIU Niue | |
NLD Netherlands | |
NOR Norway | |
NPL Nepal | |
NRU Nauru | |
NZL New Zealand | |
OMN Oman | |
PAK Pakistan | |
PAN Panama | |
PCN Pitcairn | |
PER Peru | |
PHL Philippines | |
PLW Palau | |
PNG Papua New Guinea | |
POL Poland | |
PRI Puerto Rico | |
PRK Korea, Democratic People's Republic of | |
PRT Portugal | |
PRY Paraguay | |
PSE Palestinian Territory, Occupied | |
PYF French Polynesia | |
QAT Qatar | |
REU Réunion | |
ROU Romania | |
RUS Russian Federation | |
RWA Rwanda | |
SAU Saudi Arabia | |
SDN Sudan | |
SEN Senegal | |
SGP Singapore | |
SGS South Georgia and the South Sandwich Islands | |
SHN Saint Helena, Ascension and Tristan da Cunha | |
SJM Svalbard and Jan Mayen | |
SLB Solomon Islands | |
SLE Sierra Leone | |
SLV El Salvador | |
SMR San Marino | |
SOM Somalia | |
SPM Saint Pierre and Miquelon | |
SRB Serbia | |
STP Sao Tome and Principe | |
SUR Suriname | |
SVK Slovakia | |
SVN Slovenia | |
SWE Sweden / Schweden | |
SWZ Swaziland | |
SYC Seychelles | |
SYR Syrian Arab Republic | |
TCA Turks and Caicos Islands | |
TCD Chad | |
TGO Togo | |
THA Thailand | |
TJK Tajikistan | |
TKL Tokelau | |
TKM Turkmenistan | |
TLS Timor-Leste | |
TON Tonga | |
TTO Trinidad and Tobago | |
TUN Tunisia | |
TUR Turkey | |
TUV Tuvalu | |
TWN Taiwan, Province of China | |
TZA Tanzania, United Republic of | |
UGA Uganda | |
UKR Ukraine | |
UMI United States Minor Outlying Islands | |
URY Uruguay | |
USA United States | |
UZB Uzbekistan | |
VAT Holy See (Vatican City State) | |
VCT Saint Vincent and the Grenadines | |
VEN Venezuela, Bolivarian Republic of | |
VGB Virgin Islands, British | |
VIR Virgin Islands, U.S. | |
VNM Viet Nam | |
VUT Vanuatu | |
WLF Wallis and Futuna | |
WSM Samoa | |
YEM Yemen | |
ZAF South Africa | |
ZMB Zambia | |
ZWE Zimbabwe | |
TEXT | |
} | |
tryUsingCouponCodeFromList() { | |
declare file=$1 | |
if [[ -r "$file" ]]; then | |
# Print the first unused coupon code: | |
grep -v '^#' "$file" | head -n1 || true | |
# Now comment the first unused coupon code: | |
sed -i -r '0,/^[^#]/ s/^([^#])/#\1/' "$file" | |
fi | |
} | |
printFieldsFromJson() { | |
perl -MJSON -e '$RS=undef; my $dat=JSON::decode_json(<STDIN>); binmode(STDOUT, ":utf8"); for(@ARGV) {print $dat->{$_} . "\n"}' "$@" | |
} | |
filterCountry() { | |
declare country=$1 | |
if [[ -z $country || $country == DEU ]]; then | |
grep '\.DEU' | |
else | |
cat | |
fi | |
} | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment