public async Task <List <RevisionAction <JiraAttachment> > > DownloadAttachments(JiraRevision rev)
        {
            var attChanges = rev.AttachmentActions;

            if (attChanges != null && attChanges.Any(a => a.ChangeType == RevisionChangeType.Added))
            {
                var downloadedAtts = new List <JiraAttachment>();
                using (var web = new WebClientWrapper(this))
                {
                    foreach (var remoteAtt in attChanges)
                    {
                        var jiraAtt = await DownloadAttachmentAsync(remoteAtt.Value, web);

                        if (jiraAtt != null && !string.IsNullOrWhiteSpace(jiraAtt.LocalPath))
                        {
                            downloadedAtts.Add(jiraAtt);
                        }
                    }
                }

                // of added attachments, leave only attachments that have been successfully downloaded
                attChanges.RemoveAll(ac => ac.ChangeType == RevisionChangeType.Added);
                attChanges.AddRange(downloadedAtts.Select(da => new RevisionAction <JiraAttachment>()
                {
                    ChangeType = RevisionChangeType.Added, Value = da
                }));
            }

            return(attChanges);
        }
        private async Task <JiraAttachment> DownloadAttachmentAsync(JiraAttachment att, WebClientWrapper web)
        {
            if (att != null)
            {
                if (string.IsNullOrWhiteSpace(att.Url))
                {
                    att = await GetAttachmentInfo(att.Id);
                }

                if (att != null)
                {
                    if (!string.IsNullOrWhiteSpace(att.Url))
                    {
                        try
                        {
                            string path = Path.Combine(Settings.AttachmentsDir, att.Id, att.Filename);
                            EnsurePath(path);
                            await web.DownloadWithAuthenticationAsync(att.Url, path);

                            att.LocalPath = path;
                            Logger.Log(LogLevel.Debug, $"Downloaded attachment '{att.ToString()}'");
                        }
                        catch (Exception)
                        {
                            Logger.Log(LogLevel.Warning, $"Attachment download failed for '{att.Id}'. ");
                        }
                    }

                    if (!string.IsNullOrWhiteSpace(att.ThumbUrl))
                    {
                        try
                        {
                            string thumbname = Path.GetFileNameWithoutExtension(att.Filename) + ".thumb" + Path.GetExtension(att.Filename);
                            var    thumbPath = Path.Combine(Settings.AttachmentsDir, att.Id, thumbname);
                            EnsurePath(thumbPath);
                            await web.DownloadWithAuthenticationAsync(att.ThumbUrl, Path.Combine(Settings.AttachmentsDir, att.Id, thumbname));

                            att.LocalThumbPath = thumbPath;
                            Logger.Log(LogLevel.Debug, $"Downloaded attachment thumbnail '{att.ToString()}'.");
                        }
                        catch (Exception)
                        {
                            Logger.Log(LogLevel.Warning, $"Attachment thumbnail '{att.ToString()}' download failed.");
                        }
                    }
                }
            }

            return(att);
        }