/// <summary> /// Parse the results of the Bing search /// </summary> /// <param name="reader">The xml reader containing the search results</param> public Collection<Article> ParseItems(XmlReader reader, Feed ownerFeed) { Collection<Article> results = new Collection<Article>(); reader.ReadToFollowing("item"); do { if (reader.ReadToFollowing("title")) { string name = reader.ReadElementContentAsString(); if (reader.ReadToFollowing("link")) { string uri = reader.ReadElementContentAsString(); // Assign feed information to Article object. Article newResult = new Article { ArticleTitle = name, ArticleBaseURI = uri }; // Safely add the search result to the collection. lock (_lockObject) { results.Add(newResult); } } } } while (reader.ReadToFollowing("item")); return results; }
/// <summary> /// Create a secondary tile linking to an existing feed. /// </summary> /// <param name="feed">The feed to be linked to on the tile</param> public static void AddLiveTile(Feed feed) { // Look to see whether the Tile already exists; if so, don't try to create it again. ShellTile tileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("/Feed/" + feed.FeedID.ToString())); // Create the Tile if we didn't find that it already exists. if (tileToFind == null) { // Create the Tile object and set some initial properties for the Tile. StandardTileData newTileData = new StandardTileData { BackgroundImage = new Uri(feed.ImageURL, UriKind.RelativeOrAbsolute), Title = feed.FeedTitle, Count = 0, BackTitle = feed.FeedTitle, BackContent = "Read the latest in " + feed.FeedTitle + "!", }; // Create the Tile and pin it to Start. This will cause a navigation to Start and a deactivation of our application. ShellTile.Create(new Uri("/Feed/" + feed.FeedID, UriKind.Relative), newTileData); // note: Tile URI could also have listed the full path to the feed page. For example --> /Views/FeedPage.xaml?id= feed.IsPinned = true; App.DataBaseUtility.SaveChangesToDB(); } }
//Add an article to the article table! public void AddArticles(ICollection<Article> newArticles, Feed feed) { dbMutex.WaitOne(); int downloadedArticleCount = newArticles.Count; int numOfNew = 0; // Query local database for existing articles. for (int i = 0; i < downloadedArticleCount; i++) { Article newArticle = newArticles.ElementAt(i); var d = from q in db.Article where q.ArticleBaseURI == newArticle.ArticleBaseURI select q; List<Article> a = d.ToList(); //Determine if any articles are already in the database bool alreadyInDB = (d.ToList().Count == 0); if (alreadyInDB) { newArticle.Read = false; newArticle.Favorite = false; numOfNew++; } else { //If so, remove them from the list newArticles.Remove(newArticle); downloadedArticleCount--; i--; } } //Try to submit and update counts. try { db.Article.InsertAllOnSubmit(newArticles); Deployment.Current.Dispatcher.BeginInvoke(() => { feed.UnreadCount += numOfNew; SaveChangesToDB(); }); SaveChangesToDB(); } //TODO handle errors. catch { } finally { dbMutex.ReleaseMutex(); } }
/// <summary> /// Gets the image url for a feed. If there is no usable one, then use a default image. /// </summary> /// <param name="feed">The feed to get the image for</param> /// <param name="synFeed">The SyndicationFeed to obtain data from</param> /// <returns>Whether or not the feed had an obtainable image</returns> public static bool GetImage(Feed feed, SyndicationFeed synFeed) { bool imageIsOkay = false; if (IfImageExists(synFeed)) { string url = synFeed.ImageUrl.ToString(); // Make sure that an image exists in the right filetype. if (url.EndsWith("png") || url.EndsWith("jpg") || url.EndsWith("jpeg")) { feed.ImageURL = url; imageIsOkay = true; } } // If there's no image, set it to a default one. if (!imageIsOkay) { feed.ImageURL = GetDefaultImage(); } return imageIsOkay; }
/// <summary> /// Function to parse the item of a feed and obtain useful data. /// </summary> /// <param name="feed">The Feed the article being parsed belongs to.</param> /// <param name="synFeed">Syndication Feed to be parsed</param> /// <param name="item">SyndicationItem that will be added to the database</param> public Collection<Article> ParseItems(XmlReader reader, Feed parentFeed) { // Collection to store all parsed articles Collection<Article> parsedArticles = new Collection<Article>(); SyndicationFeed synFeed; // Create a syndicationFeed from the provided reader try { synFeed = SyndicationFeed.Load(reader); } catch { return null; } if (null != synFeed) { // First, obtain an image for the feed if it does not have one. if (!ImageGrabber.IfImageExists(parentFeed)) { ImageGrabber.GetImage(parentFeed, synFeed); latestDate = new DateTime(); } // Parse the xml file, getting each article. foreach (SyndicationItem item in synFeed.Items) { // Get the necessary details from the SyndicationItem. string title = (item.Title != null) ? item.Title.Text : String.Empty; title = HTMLParser(title); // parse the title for html leftovers string itemURI = (item.Links[0].Uri.ToString() != null) ? item.Links[0].Uri.ToString() : String.Empty; DateTimeOffset date = item.PublishDate; // Special case for the text/preview of article. StringBuilder text = new StringBuilder(); if (item.Summary != null) { text.Append(item.Summary.Text); } // If the article instead writes to the content:encoded portion of the xml. else { foreach (SyndicationElementExtension extension in item.ElementExtensions) { XElement ele = extension.GetObject<XElement>(); if (ele.Name.LocalName == "encoded" && ele.Name.Namespace.ToString().Contains("content")) { text.Append(ele.Value + "<br/>"); } } } string parsedText = HTMLParser(text.ToString()); if (parsedText.Length >= 3500) { parsedText = parsedText.Substring(0, 2499); } if (null == latestDate) { lock (_lockObject) { latestDate = new DateTime(); } } bool val; lock (_lockObject) { val = latestDate.CompareTo(date.DateTime) < 0; } if (val) { // Initialize new article, then add it to the database. Article newArticle = new Article { ArticleTitle = title, Authors = parentFeed.FeedTitle, PublishDate = date.DateTime.ToLocalTime(), Summary = parsedText, LastUpdatedTime = DateTime.Now, ArticleBaseURI = itemURI, FeedID = parentFeed.FeedID, ImageURL = parentFeed.ImageURL }; parsedArticles.Add(newArticle); } } } return parsedArticles; }
/// <summary> /// Display the previous feed. /// </summary> private void OnPreviousClick(object sender, EventArgs e) { if (null != _allFeeds && _allFeeds.Count > 0) { int prevFeedIndex = _allFeeds.IndexOf(SelectedFeed) - 1; if (prevFeedIndex >= 0) { Feed previousFeed = _allFeeds[prevFeedIndex]; List<Article> feedArticles = App.DataBaseUtility.GetFeedArticles(previousFeed.FeedID); if (null != feedArticles) { this.SelectedFeed = previousFeed; this.DataContext = feedArticles; _nextButton.IsEnabled = true; _previousButton.IsEnabled = (prevFeedIndex > 0); } } } }
/// <summary> /// Retrieve the feed selected by the user and all it's corresponding articles. /// </summary> protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); string idStr; if (NavigationContext.QueryString.TryGetValue("id", out idStr)) { SelectedFeed = App.DataBaseUtility.QueryFeed(Convert.ToInt32(idStr)); _allFeedsArticles = App.DataBaseUtility.GetFeedArticles(Convert.ToInt32(idStr)); List<Article> firstSetOfArticles = new List<Article>(_allFeedsArticles); if (firstSetOfArticles.Count > 10) { firstSetOfArticles.RemoveRange(10, firstSetOfArticles.Count - 10); } FeedArticles = new ObservableCollection<Article>(firstSetOfArticles); DataContext = FeedArticles; } _allFeeds = App.DataBaseUtility.GetAllFeeds(); _allFeeds.Sort(); ApplicationBar appBar = new ApplicationBar { IsMenuEnabled = false }; int index = _allFeeds.IndexOf(SelectedFeed); _previousButton = new ApplicationBarIconButton { IconUri = new Uri("/Icons/appbar.back.rest.png", UriKind.Relative), Text = AppResources.AppBarButtonPreviousText, IsEnabled = (index > 0) }; _previousButton.Click += OnPreviousClick; _nextButton = new ApplicationBarIconButton { IconUri = new Uri("/Icons/appbar.next.rest.png", UriKind.Relative), Text = AppResources.AppBarButtonNextText, IsEnabled = (index < _allFeeds.Count - 1) }; _nextButton.Click += OnNextClick; appBar.Buttons.Add(_previousButton); appBar.Buttons.Add(_nextButton); this.ApplicationBar = appBar; }
/// <summary> /// Creates a new instance of SingleDownloadFinishedEventArgs which /// provides arguments relevant to the download performed. /// </summary> /// <param name="downloadedFeeds">The feed whose articles were downloaded.</param> /// <param name="downloadedArticles">Articles corresponding to ParentFeed that were downloaded.</param> public SingleDownloadFinishedEventArgs(Feed parentFeed, IList <Article> downloadedArticles) { this.ParentFeed = parentFeed; this.DownloadedArticles = downloadedArticles; }
/// <summary> /// Callback method called when the "Download" method returns from an HTTPWebRequest. /// </summary> /// <param name="result">The result of the asynchronous operation.</param> private void ResponseCallback(IAsyncResult result) { RequestState state = result.AsyncState as RequestState; Feed parentFeed = state.Argument as Feed; if (null != parentFeed) { HttpWebRequest request = state.Request as HttpWebRequest; // Progress only if this download has not been timed out. if (null != request) { // Retrieve response. try { using (HttpWebResponse response = request.EndGetResponse(result) as HttpWebResponse) { if (null != response && response.StatusCode == HttpStatusCode.OK) { using (XmlReader reader = XmlReader.Create(response.GetResponseStream())) { // Collection to store all articles Collection <Article> parsedArticles = _parser.ParseItems(reader, parentFeed); // Raise event for a single feed downloaded. if (null != SingleDownloadFinished) { SingleDownloadFinished(this, new SingleDownloadFinishedEventArgs(parentFeed, parsedArticles)); } // Add to all downloads dictionary and raise AllDownloadsFinished if all async requests have finished. Downloads.Add(parentFeed, parsedArticles); CheckIfDone(); } } } } catch (WebException we) { if (we.Status == WebExceptionStatus.RequestCanceled) { // The web request was timed out. Let debug know it failed. System.Diagnostics.Debug.WriteLine("ERROR: Feed \"" + parentFeed.FeedTitle + "\" was timed out."); CheckIfDone(); return; } else if (we.Message == "The remote server returned an error: NotFound.") { // The web site did not respond. This means one of two things: Either the web site is bad, or you have no internet. // If error code NotFound is received, then there is no connection. Throw the exception. if ((we.Response as HttpWebResponse).StatusCode == HttpStatusCode.NotFound) { // WebTools throws an exception if without connection. Warn the user. CheckIfDone(); if (!IsDownloading) { Deployment.Current.Dispatcher.BeginInvoke(() => { MessageBox.Show("FeedCast is unable to reach a connection. Please check your network connectivity."); }); } } // If error code InternalServerError is received, then it is a faulty site. else { System.Diagnostics.Debug.WriteLine("ERROR: Feed \"" + parentFeed.FeedTitle + "\" is faulty."); CheckIfDone(); return; } } else { // Unexpected web exception. throw we; } } } } }
partial void InsertFeed(Feed instance);
partial void DeleteFeed(Feed instance);
partial void UpdateFeed(Feed instance);
/// <summary> /// Determines whether or not the imageURL field of a Feed is empty or not. /// </summary> /// <param name="feed">The feed to be looked at</param> /// <returns>Whether or not the imageURL is empty or not</returns> public static bool IfImageExists(Feed feed) { return (feed.ImageURL != null); }
//Add a feed to the feed table, and a corresponding entry in Category_Feed Table public bool AddFeed(Feed newFeed, Category cat) { dbMutex.WaitOne(); bool checkfeed = checkFeed(newFeed.FeedBaseURI, cat.CategoryID); bool feedexists = checkIfFeedExists(newFeed.FeedBaseURI); //Checks if the feed is in the database if (feedexists) { newFeed.SharedCount = 0; newFeed.UnreadCount = 0; newFeed.ViewCount = 0; newFeed.FavoritedCount = 0; newFeed.IsPinned = false; db.Feed.InsertOnSubmit(newFeed); SaveChangesToDB(); Category_Feed newCat_Feed = new Category_Feed { CategoryID = cat.CategoryID, FeedID = newFeed.FeedID }; db.Category_Feed.InsertOnSubmit(newCat_Feed); SaveChangesToDB(); } //If it does, but not to the category, add it to the category else if (checkfeed) { Category_Feed newCat_Feed = new Category_Feed { CategoryID = cat.CategoryID, FeedID = newFeed.FeedID }; db.Category_Feed.InsertOnSubmit(newCat_Feed); SaveChangesToDB(); } //Else do nothing. dbMutex.ReleaseMutex(); return (feedexists); }
//Delete a feed. public void DeleteFeed(Feed deleteFeed) { var q = from o in db.Category_Feed where o.FeedID == deleteFeed.FeedID select o; //Delete all the cat_feed pairings db.Category_Feed.DeleteAllOnSubmit(q.ToList()); var a = from o in db.Article where o.FeedID == deleteFeed.FeedID select o; //Delete all the articles in that feed DeleteArticles(a.ToList()); db.Feed.DeleteOnSubmit(deleteFeed); SaveChangesToDB(); }
/// <summary> /// Determines whether or not the imageURL field of a Feed is empty or not. /// </summary> /// <param name="feed">The feed to be looked at</param> /// <returns>Whether or not the imageURL is empty or not</returns> public static bool IfImageExists(Feed feed) { return(feed.ImageURL != null); }