protected override void Ready( ) { ResourceProxy proxy = new ResourceProxy(_resource); proxy.BeginUpdate(); if (!Successfull) { proxy.SetProp(Props.EnclosureDownloadingState, DownloadState.Failed); string lastException = null; if (LastException != null) { lastException = LastException.Message; } proxy.SetProp(Props.EnclosureFailureReason, lastException); proxy.DeleteProp(Props.EnclosureTempFile); ShowDesktopAlert(DownloadState.Failed, "Downloading Failed", _resource.DisplayName, lastException); } else { proxy.SetProp(Props.EnclosureDownloadingState, DownloadState.Completed); ShowDesktopAlert(DownloadState.Completed, "Downloading Completed", _resource.DisplayName, null); } proxy.EndUpdate(); _queued = false; EnclosureDownloadManager.DownloadNextEnclosure(); }
public static void Do(DateTime at, IResource feedItem) { string enclosureUrl = feedItem.GetPropText(Props.EnclosureURL).Trim(); if (enclosureUrl.Length == 0) { return; } IResource feed = feedItem.GetLinkProp(-Props.RSSItem); string directory = FindDownloadDirectory(feedItem, feed); try { Directory.CreateDirectory(directory); string destFullPath = null; FileStream file = null; int startPosition = 0; if (feedItem.GetIntProp(Props.EnclosureDownloadingState) == DownloadState.InProgress) { string enclosureTempFile = feedItem.GetPropText(Props.EnclosureTempFile); if (File.Exists(enclosureTempFile)) { try { file = File.OpenWrite(enclosureTempFile); destFullPath = enclosureTempFile; startPosition = (int)file.Length; file.Seek(startPosition, SeekOrigin.Begin); } catch (Exception exception) { Tracer._TraceException(exception); } } } if (destFullPath == null && file == null) { destFullPath = FindFreeFileName(enclosureUrl, directory, true); file = File.Create(destFullPath); } new ResourceProxy(feedItem).SetProp(Props.EnclosureTempFile, destFullPath); Core.NetworkAP.QueueJobAt(at, new DownloadEnclosure(feedItem, file, directory, startPosition)); _queued = true; } catch (Exception exception) { _queued = false; ResourceProxy proxy = new ResourceProxy(feedItem); proxy.BeginUpdate(); proxy.SetProp(Props.EnclosureDownloadingState, DownloadState.Failed); proxy.SetProp(Props.EnclosureFailureReason, exception.Message); proxy.EndUpdate(); ShowDesktopAlert(DownloadState.Failed, "Downloading Failed", feedItem.DisplayName, exception.Message); EnclosureDownloadManager.DownloadNextEnclosure(); } }
public override void OK() { _chkDownloadPeriod.Checked = _chkDownloadPeriod.Checked && _edtStartDownload.TimeParseable() && _edtFinishDownload.TimeParseable(); Settings.EnclosureDownloadStartHour.Save(_edtStartDownload.Value); Settings.EnclosureDownloadFinishHour.Save(_edtFinishDownload.Value); Settings.EnclosurePath.Save(_browseForFolderControl.SelectedPath); SettingSaver.Save(Controls); Settings.LoadSettings(); Core.ResourceAP.QueueJob(new UpdateDefaultsDelegate(UpdateDefaults), _oldUpdateFrequency, _oldUpdatePeriod); EnclosureDownloadManager.DownloadNextEnclosure(); }
public void Exec(IResource res, IActionParameterStore actionStore) { Guard.NullArgument(res, "res"); Guard.NullArgument(actionStore, "actionStore"); if (res.Type != "RSSItem") { throw new ArgumentException("EnclosureDownloadRuleAction was registered for RSSItem only but there resource with type = '" + res.Type + "'"); } Tracer._Trace("Execute rule: EnclosureDownloadRuleAction"); if (res.HasProp(Props.EnclosureURL)) { EnclosureDownloadManager.PlanToDownload(res); } }
/// <summary> /// Queue for download those enclosures of the feed's unread items which /// are not yet downloaded or queued. /// </summary> /// <param name="feed">A feed resource which items are to be analyzed.</param> private void ScheduleEnclosures(IResource feed) { IResourceList items = feed.GetLinksOfType(Props.RSSItemResource, Props.RSSItem); items = items.Intersect(Core.ResourceStore.FindResourcesWithProp(Props.RSSItemResource, Core.Props.IsUnread), true); items = items.Minus(Core.ResourceStore.FindResourcesWithProp(Props.RSSItemResource, Core.Props.IsDeleted)); IResourceList itemsWithEncls = Core.ResourceStore.FindResources(null, Props.EnclosureDownloadingState, (int)EnclosureDownloadState.NotDownloaded); items = items.Intersect(itemsWithEncls, true); foreach (IResource item in items) { EnclosureDownloadManager.PlanToDownload(item); } }
protected override void Execute() { if (_resource.Id != -1 && _resource.GetIntProp(Props.EnclosureDownloadingState) != DownloadState.NotDownloaded) { // Determine if we want update some of the resource properties (create proxy for that) int nTotalLength = GetLength(); bool bUpdateState = _resource.GetIntProp(Props.EnclosureDownloadingState) != DownloadState.InProgress; bool bUpdateLength = ((nTotalLength > 0) && (nTotalLength != _resource.GetIntProp(Props.EnclosureSize))); if ((bUpdateState) || (bUpdateLength)) { ResourceProxy proxy = new ResourceProxy(_resource); proxy.BeginUpdate(); if (bUpdateState) { proxy.SetProp(Props.EnclosureDownloadingState, DownloadState.InProgress); } if (bUpdateLength) { proxy.SetProp(Props.EnclosureSize, nTotalLength + _startPosition); } proxy.EndUpdateAsync(); } // Check if the downloaded size should be updated // As we take the actual size from the disc file, not from the property, its accuracy is not needed; overwrite the property only if the percent value changes, as it's used only for the percentage display if (nTotalLength > 0) // The total-size info is available (if it's not, we do not have the percentage anyway) { int nSize = GetDownloadedSize(); // Size we've downloaded int nOldSize = _resource.GetIntProp(Props.EnclosureDownloadedSize); // The prev size property value if ((nSize * 100 / nTotalLength) != (nOldSize * 100 / nTotalLength)) // Percentage has changed, should write a new value { Core.UserInterfaceAP.QueueJob("Update Enclosure Downloaded Size", new UpdateDownloadedSizeDelegate(UpdateDownloadedSize), nSize); // Schedulle to the UI AP so that it merges the too-frequent updates for enclosures that download too fast, that reduces flicker } } // Do the download step base.Execute(); } else { InvokeAfterWait(null, null); new ResourceProxy(_resource).SetProp(Props.EnclosureDownloadingState, DownloadState.NotDownloaded); _queued = false; EnclosureDownloadManager.DownloadNextEnclosure(); } }
public void GetItemHtml(IResource item, TextWriter writer) { TextWriterDecor decor = new TextWriterDecor(writer); //////////////////////// // Prepare the strings /* * // Date — date/time of this item * string sDate; * DateTime date = item.GetDateProp( Core.Props.Date ); * if( date.Date == DateTime.Today ) * sDate = "Today " + date.ToShortTimeString(); * else * sDate = date.ToShortDateString() + ' ' + date.ToShortTimeString(); * * // Origin — name of the feed author, etc * string sOrigin = ""; * if( item.HasProp( Core.ContactManager.Props.LinkFrom ) ) * sOrigin = HttpUtility.HtmlEncode( item.GetPropText( Core.ContactManager.Props.LinkFrom ) ); * * ////////// * // Title * writer.WriteLine( "<div class=\"title\">" ); * GenericNewspaperProvider.RenderIcon( item, writer ); // Icon * RssBodyConstructor.AppendLink( item, decor, true ); // Title text & link * writer.WriteLine( "<em class=\"Origin\">{0}{2}{1}</em>", sOrigin, sDate, ((sOrigin.Length > 0) && (sDate.Length > 0) ? " — " : "") ); // Origin (feed name) & Date * writer.WriteLine( "</div>" ); // class=title * * GenericNewspaperProvider.RenderFlag( item, writer ); // Flag (optional) * GenericNewspaperProvider.RenderAnnotation( item, writer ); // Annotation (optional) * * writer.WriteLine( "<br class=\"clear\" />" ); */ // TODO: remove IResource feed = item.GetLinkProp(-Props.RSSItem); GenericNewspaperProvider.RenderCaption(item, writer); ////////////// // Item Body writer.WriteLine("<div>"); if (feed != null && feed.HasProp(Props.URL)) { writer.WriteLine(HtmlTools.FixRelativeLinks(item.GetPropText(Core.Props.LongBody), feed.GetStringProp("URL"))); } else { writer.WriteLine(item.GetPropText(Core.Props.LongBody)); } writer.WriteLine("</div>"); // Enclosure info if (item.HasProp(Props.EnclosureURL)) { writer.Write("<p class=\"Origin\"><span title=\"Enclosure is an attachment to the RSS feed item.\">Enclosure</span>"); // Specify the enclosure size, if available if (item.HasProp(Props.EnclosureSize)) { writer.Write(" ({0})", Utils.SizeToString(item.GetIntProp(Props.EnclosureSize))); } writer.Write(": "); // Add a link to the locally-saved enclosure file string sDownloadComment = null; // Will contain an optional download comment if (item.HasProp(Props.EnclosureDownloadingState)) { // Choose the tooltip text and whether the icon will be clickable, depending on the state string sText = null; bool bLink = false; EnclosureDownloadState nEnclosureDownloadState = (EnclosureDownloadState)item.GetIntProp(Props.EnclosureDownloadingState); switch (nEnclosureDownloadState) { case EnclosureDownloadState.Completed: sText = "The enclosure has been downloaded to your computer.\nClick to open the local file."; bLink = true; break; case EnclosureDownloadState.Failed: sText = "Failed to download the enclosure.\nUse the Web link to download manually."; break; case EnclosureDownloadState.InProgress: sText = "Downloading the enclosure, please wait…\nClick to open the partially-downloaded file."; // Write percentage to the comment if (item.HasProp(Props.EnclosureDownloadedSize)) { if (item.HasProp(Props.EnclosureSize)) // The total size is available, as needed for the percentage { sDownloadComment = String.Format("({0}%)", item.GetIntProp(Props.EnclosureDownloadedSize) * 100 / item.GetIntProp(Props.EnclosureSize)); } else // The total size is not available, percentage not available, show the size downloaded { sDownloadComment = String.Format("({0} downloaded so far)", Utils.SizeToString(item.GetIntProp(Props.EnclosureDownloadedSize))); } } bLink = true; break; case EnclosureDownloadState.NotDownloaded: sText = "The enclosure has not been downloaded.\nUse the Web link to download manually."; break; case EnclosureDownloadState.Planned: sText = "The enclosure has been schedulled for download.\nUse the Web link to download manually."; sDownloadComment = "(0%)"; break; default: throw new Exception("Unexpected enclosure download state."); } // Ensure that there's the path to the local file specified, if we're going to provide a link to it if ((bLink) && (!item.HasProp(Props.EnclosureTempFile))) { Trace.WriteLine("Warning: path to the downloaded or in-progress enclosure is missing, though the downloading state implies on it should be present."); bLink = false; } // Open the link (if available) if (bLink) { writer.Write("<a href=\"{0}\">", "file://" + HttpUtility.HtmlEncode(item.GetStringProp(Props.EnclosureTempFile))); } // Render the icon Icon icon = EnclosureDownloadManager.GetEnclosureStateIcon(nEnclosureDownloadState); writer.Write("<img src=\"{0}\" align=\"top\" width=\"{1}\" height=\"{2}\" alt=\"{3}\" title=\"{3}\" />", FavIconManager.GetIconFile(icon, "EnclosureDownload", null, true), icon.Width, icon.Height, sText, sText); // Close the link if (bLink) { writer.Write("</a>"); } writer.Write(" "); } // Add a link to the Web location of the enclosure writer.Write("<a href=\"{0}\">", HttpUtility.HtmlEncode(item.GetStringProp(Props.EnclosureURL))); if (_iconEnclosureWeb == null) { _iconEnclosureWeb = RSSPlugin.LoadIconFromAssembly("BlogExtensionComposer.Submit.ico"); } writer.Write("<img src=\"{0}\" align=\"top\" width=\"{1}\" height=\"{2}\" alt=\"{3}\" title=\"{3}\" /> ", FavIconManager.GetIconFile(_iconEnclosureWeb, "EnclosureWeb", null, true), _iconEnclosureWeb.Width, _iconEnclosureWeb.Height, "Download enclosure from the Web."); writer.Write("</a>"); // Add the optional download comment if (sDownloadComment != null) { writer.Write(" "); } writer.Write(sDownloadComment); // Close the paragraph writer.WriteLine("</p>"); } // Link to the Source RssBodyConstructor.AppendSourceTag(item, decor); // Link to the comments if (item.HasProp(Props.CommentURL)) { decor.AppendText("<p class=\"Origin\">"); RssBodyConstructor.AppendCommentsTag(item, decor); writer.WriteLine("</p>"); } }