From ec8626317cee2f7afaa142f5b1647ee23a1a023b Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Thu, 26 Dec 2024 14:39:05 +0300 Subject: [PATCH] Code refactoring --- app/app.go | 96 +++++++++++++++------------- common/atlassian-cloud-backuper.spec | 7 +- go.mod | 22 +++---- go.sum | 64 +++++++++---------- 4 files changed, 101 insertions(+), 88 deletions(-) diff --git a/app/app.go b/app/app.go index 1f96b37..677d798 100644 --- a/app/app.go +++ b/app/app.go @@ -42,7 +42,7 @@ import ( // Basic utility info const ( APP = "Atlassian Cloud Backuper" - VER = "0.2.0" + VER = "0.2.1" DESC = "Tool for backuping Atlassian cloud services (Jira and Confluence)" ) @@ -300,7 +300,7 @@ func loadConfig() error { // validateConfig validates configuration file values func validateConfig() error { - validators := []*knf.Validator{ + validators := knf.Validators{ {ACCESS_ACCOUNT, knfv.Set, nil}, {ACCESS_EMAIL, knfv.Set, nil}, {ACCESS_API_KEY, knfv.Set, nil}, @@ -308,58 +308,62 @@ func validateConfig() error { {STORAGE_TYPE, knfv.SetToAnyIgnoreCase, []string{ STORAGE_FS, STORAGE_SFTP, STORAGE_S3, }}, + {TEMP_DIR, knff.Perms, "DWX"}, {LOG_FORMAT, knfv.SetToAnyIgnoreCase, []string{ "", "text", "json", }}, - {LOG_LEVEL, knfv.SetToAnyIgnoreCase, []string{ - "", "debug", "info", "warn", "error", "crit", - }}, - {TEMP_DIR, knff.Perms, "DWX"}, + {LOG_LEVEL, knfv.SetToAnyIgnoreCase, log.LogLevels}, } - switch strings.ToLower(knfu.GetS(STORAGE_TYPE)) { - case STORAGE_FS: - validators = append(validators, - &knf.Validator{STORAGE_FS_PATH, knff.Perms, "DRW"}, - ) + validators = validators.AddIf( + knfu.GetS(STORAGE_TYPE) == STORAGE_FS, + knf.Validators{ + {STORAGE_FS_PATH, knff.Perms, "DRW"}, + }, + ) - case STORAGE_SFTP: - validators = append(validators, - &knf.Validator{STORAGE_SFTP_HOST, knfv.Set, nil}, - &knf.Validator{STORAGE_SFTP_USER, knfv.Set, nil}, - &knf.Validator{STORAGE_SFTP_KEY, knfv.Set, nil}, - &knf.Validator{STORAGE_SFTP_PATH, knfv.Set, nil}, - ) + validators = validators.AddIf( + knfu.GetS(STORAGE_TYPE) == STORAGE_SFTP, + knf.Validators{ + {STORAGE_SFTP_HOST, knfv.Set, nil}, + {STORAGE_SFTP_USER, knfv.Set, nil}, + {STORAGE_SFTP_KEY, knfv.Set, nil}, + {STORAGE_SFTP_PATH, knfv.Set, nil}, + }, + ) - case STORAGE_S3: - validators = append(validators, - &knf.Validator{STORAGE_S3_HOST, knfv.Set, nil}, - &knf.Validator{STORAGE_S3_ACCESS_KEY, knfv.Set, nil}, - &knf.Validator{STORAGE_S3_SECRET_KEY, knfv.Set, nil}, - &knf.Validator{STORAGE_S3_BUCKET, knfv.Set, nil}, - &knf.Validator{STORAGE_S3_PART_SIZE, knfv.Greater, 5}, - &knf.Validator{STORAGE_S3_PART_SIZE, knfv.Less, 5_000}, - ) - } + validators = validators.AddIf( + knfu.GetS(STORAGE_TYPE) == STORAGE_S3, + knf.Validators{ + {STORAGE_S3_HOST, knfv.Set, nil}, + {STORAGE_S3_ACCESS_KEY, knfv.Set, nil}, + {STORAGE_S3_SECRET_KEY, knfv.Set, nil}, + {STORAGE_S3_BUCKET, knfv.Set, nil}, + {STORAGE_S3_PART_SIZE, knfv.Greater, 5}, + {STORAGE_S3_PART_SIZE, knfv.Less, 5_000}, + }, + ) - if options.GetB(OPT_SERVER) { - validators = append(validators, - &knf.Validator{SERVER_IP, knfn.IP, nil}, - &knf.Validator{SERVER_PORT, knfn.Port, nil}, - ) - } + validators = validators.AddIf( + options.GetB(OPT_SERVER), + knf.Validators{ + {SERVER_IP, knfn.IP, nil}, + {SERVER_PORT, knfn.Port, nil}, + }, + ) - if knfu.GetS(STORAGE_ENCRYPTION_KEY) != "" { - validators = append(validators, - &knf.Validator{STORAGE_ENCRYPTION_KEY, knfv.LenGreater, 16}, - &knf.Validator{STORAGE_ENCRYPTION_KEY, knfv.LenLess, 96}, - ) - } + validators = validators.AddIf( + knfu.GetS(STORAGE_ENCRYPTION_KEY) != "", + knf.Validators{ + {STORAGE_ENCRYPTION_KEY, knfv.LenGreater, 16}, + {STORAGE_ENCRYPTION_KEY, knfv.LenLess, 96}, + }, + ) errs := knfu.Validate(validators) - if len(errs) > 0 { - return errs[0] + if !errs.IsEmpty() { + return errs.First() } return nil @@ -403,9 +407,13 @@ func setupLogger() error { func setupTemp() error { var err error - temp, err = tmp.NewTemp(knfu.GetS(TEMP_DIR, "/tmp")) + temp, err = tmp.NewTemp(knfu.GetS(TEMP_DIR, "/var/tmp")) - return err + if err != nil { + return fmt.Errorf("Can't setup temporary data directory: %w", err) + } + + return nil } // setupReq configures HTTP request engine diff --git a/common/atlassian-cloud-backuper.spec b/common/atlassian-cloud-backuper.spec index 3fdf0ef..2f7c72a 100644 --- a/common/atlassian-cloud-backuper.spec +++ b/common/atlassian-cloud-backuper.spec @@ -10,7 +10,7 @@ Summary: Tool for backuping Atlassian cloud services Name: atlassian-cloud-backuper -Version: 0.2.0 +Version: 0.2.1 Release: 0%{?dist} Group: Applications/System License: Apache License, Version 2.0 @@ -113,6 +113,11 @@ rm -rf %{buildroot} ################################################################################ %changelog +* Thu Dec 26 2024 Anton Novojilov - 0.2.1-0 +- Fixed bug with timers installation +- Dependencies update +- Code refactoring + * Thu Sep 05 2024 Anton Novojilov - 0.2.0-0 - Added option (-F/--force) and query param (force) to force backup creation - Added multipart uploading to S3 storage diff --git a/go.mod b/go.mod index 6231ac6..310bae1 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,11 @@ module github.com/essentialkaos/atlassian-cloud-backuper go 1.22.8 require ( - github.com/aws/aws-sdk-go-v2 v1.32.6 - github.com/aws/aws-sdk-go-v2/credentials v1.17.47 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.43 - github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0 - github.com/essentialkaos/ek/v13 v13.15.1 + github.com/aws/aws-sdk-go-v2 v1.32.7 + github.com/aws/aws-sdk-go-v2/credentials v1.17.48 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.44 + github.com/aws/aws-sdk-go-v2/service/s3 v1.71.1 + github.com/essentialkaos/ek/v13 v13.15.3 github.com/essentialkaos/katana v0.4.1 github.com/pkg/sftp v1.13.7 golang.org/x/crypto v0.31.0 @@ -15,13 +15,13 @@ require ( require ( github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.26 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.6 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.7 // indirect github.com/aws/smithy-go v1.22.1 // indirect github.com/essentialkaos/depsy v1.3.1 // indirect github.com/essentialkaos/sio v1.1.0 // indirect diff --git a/go.sum b/go.sum index 934a203..aa76f42 100644 --- a/go.sum +++ b/go.sum @@ -1,39 +1,39 @@ -github.com/aws/aws-sdk-go-v2 v1.32.6 h1:7BokKRgRPuGmKkFMhEg/jSul+tB9VvXhcViILtfG8b4= -github.com/aws/aws-sdk-go-v2 v1.32.6/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= +github.com/aws/aws-sdk-go-v2 v1.32.7 h1:ky5o35oENWi0JYWUZkB7WYvVPP+bcRF5/Iq7JWSb5Rw= +github.com/aws/aws-sdk-go-v2 v1.32.7/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7/go.mod h1:QraP0UcVlQJsmHfioCrveWOC1nbiWUl3ej08h4mXWoc= -github.com/aws/aws-sdk-go-v2/config v1.28.6 h1:D89IKtGrs/I3QXOLNTH93NJYtDhm8SYa9Q5CsPShmyo= -github.com/aws/aws-sdk-go-v2/config v1.28.6/go.mod h1:GDzxJ5wyyFSCoLkS+UhGB0dArhb9mI+Co4dHtoTxbko= -github.com/aws/aws-sdk-go-v2/credentials v1.17.47 h1:48bA+3/fCdi2yAwVt+3COvmatZ6jUDNkDTIsqDiMUdw= -github.com/aws/aws-sdk-go-v2/credentials v1.17.47/go.mod h1:+KdckOejLW3Ks3b0E3b5rHsr2f9yuORBum0WPnE5o5w= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 h1:AmoU1pziydclFT/xRV+xXE/Vb8fttJCLRPv8oAkprc0= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21/go.mod h1:AjUdLYe4Tgs6kpH4Bv7uMZo7pottoyHMn4eTcIcneaY= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.43 h1:iLdpkYZ4cXIQMO7ud+cqMWR1xK5ESbt1rvN77tRi1BY= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.43/go.mod h1:OgbsKPAswXDd5kxnR4vZov69p3oYjbvUyIRBAAV0y9o= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 h1:s/fF4+yDQDoElYhfIVvSNyeCydfbuTKzhxSXDXCPasU= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25/go.mod h1:IgPfDv5jqFIzQSNbUEMoitNooSMXjRSDkhXv8jiROvU= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 h1:ZntTCl5EsYnhN/IygQEUugpdwbhdkom9uHcbCftiGgA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25/go.mod h1:DBdPrgeocww+CSl1C8cEV8PN1mHMBhuCDLpXezyvWkE= +github.com/aws/aws-sdk-go-v2/config v1.28.7 h1:GduUnoTXlhkgnxTD93g1nv4tVPILbdNQOzav+Wpg7AE= +github.com/aws/aws-sdk-go-v2/config v1.28.7/go.mod h1:vZGX6GVkIE8uECSUHB6MWAUsd4ZcG2Yq/dMa4refR3M= +github.com/aws/aws-sdk-go-v2/credentials v1.17.48 h1:IYdLD1qTJ0zanRavulofmqut4afs45mOWEI+MzZtTfQ= +github.com/aws/aws-sdk-go-v2/credentials v1.17.48/go.mod h1:tOscxHN3CGmuX9idQ3+qbkzrjVIx32lqDSU1/0d/qXs= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22 h1:kqOrpojG71DxJm/KDPO+Z/y1phm1JlC8/iT+5XRmAn8= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22/go.mod h1:NtSFajXVVL8TA2QNngagVZmUtXciyrHOt7xgz4faS/M= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.44 h1:2zxMLXLedpB4K1ilbJFxtMKsVKaexOqDttOhc0QGm3Q= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.44/go.mod h1:VuLHdqwjSvgftNC7yqPWyGVhEwPmJpeRi07gOgOfHF8= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26 h1:I/5wmGMffY4happ8NOCuIUEWGUvvFp5NSeQcXl9RHcI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26/go.mod h1:FR8f4turZtNy6baO0KJ5FJUmXH/cSkI9fOngs0yl6mA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26 h1:zXFLuEuMMUOvEARXFUVJdfqZ4bvvSgdGRq/ATcrQxzM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26/go.mod h1:3o2Wpy0bogG1kyOPrgkXA8pgIfEEv0+m19O9D5+W8y8= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.25 h1:r67ps7oHCYnflpgDy2LZU0MAQtQbYIOqNNnqGO6xQkE= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.25/go.mod h1:GrGY+Q4fIokYLtjCVB/aFfCVL6hhGUFl8inD18fDalE= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.26 h1:GeNJsIFHB+WW5ap2Tec4K6dzcVTsRbsT1Lra46Hv9ME= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.26/go.mod h1:zfgMpwHDXX2WGoG84xG2H+ZlPTkJUU4YUvx2svLQYWo= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.6 h1:HCpPsWqmYQieU7SS6E9HXfdAMSud0pteVXieJmcpIRI= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.6/go.mod h1:ngUiVRCco++u+soRRVBIvBZxSMMvOVMXA4PJ36JLfSw= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 h1:50+XsN70RS7dwJ2CkVNXzj7U2L1HKP8nqTd3XWEXBN4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6/go.mod h1:WqgLmwY7so32kG01zD8CPTJWVWM+TzJoOVHwTg4aPug= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.6 h1:BbGDtTi0T1DYlmjBiCr/le3wzhA37O8QTC5/Ab8+EXk= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.6/go.mod h1:hLMJt7Q8ePgViKupeymbqI0la+t9/iYFBjxQCFwuAwI= -github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0 h1:nyuzXooUNJexRT0Oy0UQY6AhOzxPxhtt4DcBIHyCnmw= -github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0/go.mod h1:sT/iQz8JK3u/5gZkT+Hmr7GzVZehUMkRZpOaAwYXeGY= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 h1:rLnYAfXQ3YAccocshIH5mzNNwZBkBo+bP6EhIxak6Hw= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.7/go.mod h1:ZHtuQJ6t9A/+YDuxOLnbryAmITtr8UysSny3qcyvJTc= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6 h1:JnhTZR3PiYDNKlXy50/pNeix9aGMo6lLpXwJ1mw8MD4= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6/go.mod h1:URronUEGfXZN1VpdktPSD1EkAL9mfrV+2F4sjH38qOY= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.2 h1:s4074ZO1Hk8qv65GqNXqDjmkf4HSQqJukaLuuW0TpDA= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.2/go.mod h1:mVggCnIWoM09jP71Wh+ea7+5gAp53q+49wDFs1SW5z8= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.7 h1:tB4tNw83KcajNAzaIMhkhVI2Nt8fAZd5A5ro113FEMY= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.7/go.mod h1:lvpyBGkZ3tZ9iSsUIcC2EWp+0ywa7aK3BLT+FwZi+mQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.7 h1:8eUsivBQzZHqe/3FE+cqwfH+0p5Jo8PFM/QYQSmeZ+M= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.7/go.mod h1:kLPQvGUmxn/fqiCrDeohwG33bq2pQpGeY62yRO6Nrh0= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.7 h1:Hi0KGbrnr57bEHWM0bJ1QcBzxLrL/k2DHvGYhb8+W1w= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.7/go.mod h1:wKNgWgExdjjrm4qvfbTorkvocEstaoDl4WCvGfeCy9c= +github.com/aws/aws-sdk-go-v2/service/s3 v1.71.1 h1:aOVVZJgWbaH+EJYPvEgkNhCEbXXvH7+oML36oaPK3zE= +github.com/aws/aws-sdk-go-v2/service/s3 v1.71.1/go.mod h1:r+xl5yzMk9083rMR+sJ5TYj9Tihvf/l1oxzZXDgGj2Q= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.8 h1:CvuUmnXI7ebaUAhbJcDy9YQx8wHR69eZ9I7q5hszt/g= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.8/go.mod h1:XDeGv1opzwm8ubxddF0cgqkZWsyOtw4lr6dxwmb6YQg= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.7 h1:F2rBfNAL5UyswqoeWv9zs74N/NanhK16ydHW1pahX6E= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.7/go.mod h1:JfyQ0g2JG8+Krq0EuZNnRwX0mU0HrwY/tG6JNfcqh4k= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.3 h1:Xgv/hyNgvLda/M9l9qxXc4UFSgppnRczLxlMs5Ae/QY= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.3/go.mod h1:5Gn+d+VaaRgsjewpMvGazt0WfcFO+Md4wLOuBfGR9Bc= github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -43,8 +43,8 @@ github.com/essentialkaos/check v1.4.1 h1:SuxXzrbokPGTPWxGRnzy0hXvtb44mtVrdNxgPa1 github.com/essentialkaos/check v1.4.1/go.mod h1:xQOYwFvnxfVZyt5Qvjoa1SxcRqu5VyP77pgALr3iu+M= github.com/essentialkaos/depsy v1.3.1 h1:00k9QcMsdPM4IzDaEFHsTHBD/zoM0oxtB5+dMUwbQa8= github.com/essentialkaos/depsy v1.3.1/go.mod h1:B5+7Jhv2a2RacOAxIKU2OeJp9QfZjwIpEEPI5X7auWM= -github.com/essentialkaos/ek/v13 v13.15.1 h1:11m8g8SaW2B7N6y9q3c/5p9qMi7ElwXUD8HxKc2fE+Q= -github.com/essentialkaos/ek/v13 v13.15.1/go.mod h1:FnKbXv0qaoT7Ocqg0oAhlkgQZKVQFAP32wKEmrf7xNw= +github.com/essentialkaos/ek/v13 v13.15.3 h1:lDJ0qMs6wQRXWFuFRKnPvNX1SxvW2AowKgz6pRoMhAs= +github.com/essentialkaos/ek/v13 v13.15.3/go.mod h1:ez9V1qvfXvjI6gqT24fZfkdVefHzYi6bm/c2NrD7B3s= github.com/essentialkaos/katana v0.4.1 h1:+yLk5ngPOu5SKQ7LdUQ7Bip0vD9BLU4/CzmL589wD38= github.com/essentialkaos/katana v0.4.1/go.mod h1:r2/CwIhVo9T8bhJd9eQlEqfZNAJJ0191s6h6LTdw2QM= github.com/essentialkaos/sio v1.1.0 h1:XPyScH8G08NIC94373ZHs+afPjZT5OKxQCuudbdFaIc=