UploadAndAttach uploads assets in order and stops at the first failure. It points existing references at the URLs of successful uploads and appends only successful uploads the markdown did not reference. Assets after a failure are not attempted. The returned count reports how many assets reached th
(ctx context.Context, md string, assets []UserAsset)
| 21 | // The markdown is returned unchanged when it could not be rewritten, so a |
| 22 | // caller that assigns the result in place never destroys what it was given. |
| 23 | func (u *Uploader) UploadAndAttach(ctx context.Context, md string, assets []UserAsset) (string, int, error) { |
| 24 | args := make([]attachmentArg, len(assets)) |
| 25 | for i, a := range assets { |
| 26 | f := a.getAsset() |
| 27 | args[i] = attachmentArg{Path: f.path, Alt: f.alt, RendersAsPlayer: a.rendersAsPlayer()} |
| 28 | } |
| 29 | |
| 30 | attachableMD, err := newAttachableMarkdown(md, args) |
| 31 | if err != nil { |
| 32 | return md, 0, err |
| 33 | } |
| 34 | |
| 35 | var failures []error |
| 36 | uploaded := 0 |
| 37 | for i, a := range assets { |
| 38 | assetURL, err := u.upload(ctx, a) |
| 39 | if err != nil { |
| 40 | // Stopping at the first failure. It makes recovery much simpler. |
| 41 | failures = append(failures, err) |
| 42 | break |
| 43 | } |
| 44 | args[i].URL = assetURL |
| 45 | uploaded++ |
| 46 | } |
| 47 | |
| 48 | attachedMD, err := attachAssetsToMarkdown(attachableMD) |
| 49 | if err != nil { |
| 50 | failures = append(failures, err) |
| 51 | return md, uploaded, errors.Join(failures...) |
| 52 | } |
| 53 | |
| 54 | return appendUnreferenced(attachedMD, assets), uploaded, errors.Join(failures...) |
| 55 | } |
| 56 | |
| 57 | // appendUnreferenced adds a paragraph for every attachment the author never |
| 58 | // referenced, in the order they were attached. Each one renders itself, since |