Pull request 1789: AG-20200-translation-script-fix-upload

Merge in DNS/adguard-home from AG-20200-translation-script-fix-upload to master

Squashed commit of the following:

commit 4d898926828dc438c29b0ae7cbad70d8dea0b8de
Merge: 41ad204b 487675b9
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Mar 28 13:30:36 2023 +0300

    Merge branch 'master' into AG-20200-translation-script-fix-upload

commit 41ad204bc3ce52ecc61e95261b9519cfc0af9abe
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Mar 28 13:29:26 2023 +0300

    scripts: imp more

commit 5ea4821ee49638ad9011809faba0316a753a078b
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Mar 28 12:38:22 2023 +0300

    scripts: imp code

commit 253a72fd0e195c7603883322885b7206ed434918
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Mar 28 12:04:16 2023 +0300

    scripts: add docs

commit bfd70e338c78fd5b0292480d7f54f396593e98ca
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Mar 28 10:56:05 2023 +0300

    scripts: imp more

commit 547b82785f210cc137903cb5b7e2ee41b2a20e59
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Mar 28 10:08:16 2023 +0300

    scripts: imp code

commit a788e5ef8a3aa2633cc9fb64c83534f1d4080ef7
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Mar 27 20:14:55 2023 +0300

    scripts: add multipart

commit 39d352edf85288a51931dea5b758bc74dd08e19d
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Mar 27 18:35:08 2023 +0300

    scripts: fix more

commit bcbf155135c53789cc5c6c2c7c8b57dd471e4ea2
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Mar 27 17:47:40 2023 +0300

    scripts: fix upload
This commit is contained in:
Stanislav Chzhen 2023-03-28 18:02:32 +03:00
parent 487675b9ad
commit c576d5059e

View File

@ -8,7 +8,9 @@ import (
"flag" "flag"
"fmt" "fmt"
"io" "io"
"mime/multipart"
"net/http" "net/http"
"net/textproto"
"net/url" "net/url"
"os" "os"
"path/filepath" "path/filepath"
@ -426,6 +428,8 @@ func printUnused(loc locales) {
// upload base translation. uri is the base URL. projectID is the name of the // upload base translation. uri is the base URL. projectID is the name of the
// project. baseLang is the base language code. // project. baseLang is the base language code.
func upload(uri *url.URL, projectID string, baseLang langCode) (err error) { func upload(uri *url.URL, projectID string, baseLang langCode) (err error) {
defer func() { err = errors.Annotate(err, "upload: %w") }()
uploadURI := uri.JoinPath("upload") uploadURI := uri.JoinPath("upload")
lang := baseLang lang := baseLang
@ -436,20 +440,90 @@ func upload(uri *url.URL, projectID string, baseLang langCode) (err error) {
} }
basePath := filepath.Join(localesDir, defaultBaseFile) basePath := filepath.Join(localesDir, defaultBaseFile)
b, err := os.ReadFile(basePath)
if err != nil { formData := map[string]string{
return fmt.Errorf("upload: %w", err) "format": "json",
"language": string(lang),
"filename": defaultBaseFile,
"project": projectID,
} }
var buf bytes.Buffer buf, cType, err := prepareMultipartMsg(formData, basePath)
buf.Write(b)
uri = translationURL(uploadURI, defaultBaseFile, projectID, lang)
var client http.Client
resp, err := client.Post(uri.String(), "application/json", &buf)
if err != nil { if err != nil {
return fmt.Errorf("upload: client post: %w", err) return fmt.Errorf("preparing multipart msg: %w", err)
}
err = send(uploadURI.String(), cType, buf)
if err != nil {
return fmt.Errorf("sending multipart msg: %w", err)
}
return nil
}
// prepareMultipartMsg prepares translation data for upload.
func prepareMultipartMsg(
formData map[string]string,
basePath string,
) (buf *bytes.Buffer, cType string, err error) {
buf = &bytes.Buffer{}
w := multipart.NewWriter(buf)
var fw io.Writer
for k, v := range formData {
err = w.WriteField(k, v)
if err != nil {
return nil, "", fmt.Errorf("writing field: %w", err)
}
}
file, err := os.Open(basePath)
if err != nil {
return nil, "", fmt.Errorf("opening file: %w", err)
}
defer func() {
err = errors.WithDeferred(err, file.Close())
}()
h := make(textproto.MIMEHeader)
h.Set("Content-Type", "application/json")
d := fmt.Sprintf("form-data; name=%q; filename=%q", "file", defaultBaseFile)
h.Set("Content-Disposition", d)
fw, err = w.CreatePart(h)
if err != nil {
return nil, "", fmt.Errorf("creating part: %w", err)
}
_, err = io.Copy(fw, file)
if err != nil {
return nil, "", fmt.Errorf("copying: %w", err)
}
err = w.Close()
if err != nil {
return nil, "", fmt.Errorf("closing writer: %w", err)
}
return buf, w.FormDataContentType(), nil
}
// send POST request to uriStr.
func send(uriStr, cType string, buf *bytes.Buffer) (err error) {
var client http.Client
req, err := http.NewRequest(http.MethodPost, uriStr, buf)
if err != nil {
return fmt.Errorf("bad request: %w", err)
}
req.Header.Set("Content-Type", cType)
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("client post form: %w", err)
} }
defer func() { defer func() {