private bool ToggleBookmark(ThreadMetadata thread, BookmarkAction action, int timeout = CoreConstants.DEFAULT_TIMEOUT_IN_MILLISECONDS) { //Logger.AddEntry(string.Format("ToggleBookmarkAsync - ThreadID: {0}, Action: {1}", thread.ID, action)); string url = String.Format("{0}/{1}", CoreConstants.BASE_URL, CoreConstants.BOOKMARK_THREAD_URI); //Logger.AddEntry(string.Format("ToggleBookmarkAsync - Bookmark url: {0}", url)); // create request and request data var request = InitializePostRequest(url); var signal = new AutoResetEvent(false); var result = request.BeginGetRequestStream(callback => ProcessToggleBookmarkAsyncGetRequest(callback, signal, action, thread), request); // wait for processing signal.WaitOne(); // begin the response process request = result.AsyncState as HttpWebRequest; result = request.BeginGetResponse(callback => { signal.Set(); }, request); signal.WaitOne(timeout); // process response and return success status bool success = ProcessToggleBookmarkAsyncGetResponse(result); return(success); }
private Uri ReplyToThread(ThreadMetadata thread, string text) { var threadID = thread.ThreadID; ThreadReplyData?data = GetReplyData(threadID, text); if (data.HasValue) { AwfulDebugger.AddLog(this, AwfulDebugger.Level.Debug, "ThreadReplyService"); AwfulDebugger.AddLog(this, AwfulDebugger.Level.Debug, "Begin Reply data..."); AwfulDebugger.AddLog(this, AwfulDebugger.Level.Debug, "ThreadID: " + data.Value.THREADID); AwfulDebugger.AddLog(this, AwfulDebugger.Level.Debug, "Begin Text..."); AwfulDebugger.AddLog(this, AwfulDebugger.Level.Debug, data.Value.TEXT); AwfulDebugger.AddLog(this, AwfulDebugger.Level.Debug, "...End Text."); AwfulDebugger.AddLog(this, AwfulDebugger.Level.Debug, "Form key: " + data.Value.FORMKEY); AwfulDebugger.AddLog(this, AwfulDebugger.Level.Debug, "Form cookie: " + data.Value.FORMCOOKIE); AwfulDebugger.AddLog(this, AwfulDebugger.Level.Debug, "...End reply data."); return(InitiateReply(data.Value)); } else { AwfulDebugger.AddLog(this, AwfulDebugger.Level.Critical, "ThreadReplyService - ReplyAsync failed on null ThreadReplyData."); return(null); } }
private static ThreadMetadata ParseReplies(this ThreadMetadata thread, HtmlNode node) { var threadRepliesNode = node.Descendants("td") .Where(value => value.GetAttributeValue("class", "").Equals("replies")) .FirstOrDefault(); try { string repliesValue = threadRepliesNode.InnerText.Sanitize(); int replies = 0; if (Int32.TryParse(repliesValue, out replies)) { thread.ReplyCount = replies; //Logger.AddEntry(string.Format("AwfulThread - # of replies: {0}", replies)); } int postsPerPage = CoreConstants.POSTS_PER_THREAD_PAGE; thread.PageCount = (replies / postsPerPage) + (replies % postsPerPage > 0 ? 1 : 0); //Logger.AddEntry(string.Format("AwfulThread - Max Pages: {0}", thread.TotalPages)); } catch (Exception ex) { //Logger.AddEntry(string.Format("AwfulThread - Exception thrown while parsing replies: {0}", // ex.Message)); } return(thread); }
public static bool Rate(ThreadMetadata data, int rating) { var url = string.Format("http://forums.somethingawful.com/threadrate.php?vote={0}&threadid={1}", rating, data.ThreadID); return(RunURLTask(url)); }
private static ThreadMetadata ParseThreadSeen(this ThreadMetadata thread, HtmlNode node) { // if the node is null, then we haven't seen this thread, otherwise it's been visited var threadSeenNode = node.DescendantsAndSelf() .Where(value => value.GetAttributeValue("class", "").Contains("thread seen")) .FirstOrDefault(); bool seen = threadSeenNode == null ? false : true; thread.IsNew = !seen; // if thread is new, all posts are new, so don't show post count if (thread.IsNew) { thread.NewPostCount = -1; thread.ShowPostCount = false; //Logger.AddEntry("AwfulThread - This thread is brand new! Hide the post count."); } // else parse thread count else { thread = ParseThreadCount(thread, node); } return(thread); }
public static bool ClearMarkedPosts(ThreadMetadata thread, int timeout = CoreConstants.DEFAULT_TIMEOUT_IN_MILLISECONDS) { // create request HttpWebRequest request = AwfulWebRequest.CreateFormDataPostRequest( "http://forums.somethingawful.com/showthread.php", "application/x-www-form-urlencoded"); // begin request stream creation and wait... var signal = new AutoResetEvent(false); var result = request.BeginGetRequestStream(callback => SendClearMarkedPostRequest(callback, signal, thread), request); signal.WaitOne(); // begin response stream and wait... request = result.AsyncState as HttpWebRequest; result = request.BeginGetResponse(callback => { signal.Set(); }, request); signal.WaitOne(timeout); if (!result.IsCompleted) { throw new TimeoutException(); } // process the response and return status bool success = ProcessClearMarkedPostResponse(result); return(success); }
private static ThreadMetadata ParseSticky(this ThreadMetadata thread, HtmlNode node) { var stickyNode = node.Descendants("td").Where(aNode => aNode.GetAttributeValue("class", "") .Contains("sticky")).FirstOrDefault(); thread.IsSticky = stickyNode != null; return(thread); }
public static ThreadMetadata FromPageMetadata(ThreadPageMetadata page) { var data = new ThreadMetadata(); data.ThreadID = page.ThreadID; data.Title = page.ThreadTitle; data.PageCount = page.LastPage; return(data); }
public static ThreadPageMetadata FirstUnreadPost(this ThreadMetadata thread) { // adding some special logic here. // if the thread is new, then using 'goto=newpost' actually loads the last page. // in this case, users typically want the first unread post, // and for new threads, that would be the first page. return(thread.IsNew ? AwfulContentRequest.Threads.LoadThreadPage(thread.ThreadID, 1) : AwfulContentRequest.Threads.LoadThreadUnreadPostPage(thread.ThreadID)); }
private static ThreadMetadata ParseThreadAuthor(this ThreadMetadata thread, HtmlNode node) { var threadAuthorParentNode = node.Descendants("td") .Where(value => value.GetAttributeValue("class", "").Equals("author")) .FirstOrDefault(); thread.Author = threadAuthorParentNode.FirstChild.InnerText; //Logger.AddEntry(string.Format("AwfulThread - Author Name: {0}", thread.Author)); return(thread); }
private static ThreadMetadata ParseThreadID(this ThreadMetadata thread, HtmlNode node) { string id = node.GetAttributeValue(THREAD_ID_ATTRIBUTE, "").Trim(); id = id.Replace("thread", ""); thread.ThreadID = id; //Logger.AddEntry(string.Format("AwfulThread - ThreadID: {0}", id)); return(thread); }
public static ThreadMetadata AsSample(this ThreadMetadata data) { data.ThreadID = "1"; data.Title = "Sample Thread Title"; data.IsNew = true; data.IsSticky = true; data.Rating = 5; data.LastUpdated = DateTime.Now; data.ColorCategory = BookmarkColorCategory.Category0; data.Author = "Sample Thread Author"; data.PageCount = 10; return(data); }
private static ThreadMetadata ParseThreadCount(this ThreadMetadata thread, HtmlNode node) { // locate the thread count var threadCountNode = node.Descendants("a") .Where(value => value.GetAttributeValue("class", "").Equals("count")) .FirstOrDefault(); // if we found the new post count, get and set the value if (threadCountNode != null) { #region if we found the thread count... int count = -1; if (Int32.TryParse(threadCountNode.InnerText.Sanitize(), out count)) { thread.NewPostCount = count; thread.ShowPostCount = true; //Logger.AddEntry(string.Format("AwfulThread - Thread has new unread posts: {0}", count)); } else { // no new posts, set to maximum int value for low score sorting thread.NewPostCount = 0; thread.ShowPostCount = true; //Logger.AddEntry("AwfulThread - Thread has no new posts."); } if (count > 0) { int readPostCount = thread.ReplyCount - count; int postsPerPage = CoreConstants.POSTS_PER_THREAD_PAGE; int readPage = (readPostCount / postsPerPage) + (readPostCount % postsPerPage > 0 ? 1 : 0); //Logger.AddEntry(string.Format("AwfulThread - posts read: {0}, last page: {1}", readPostCount, thread.TotalPages)); } #endregion } else { // must be a brand new thread so don't show post count. // Logger.AddEntry("AwfulThread - Couldn't find the threadCountNode. no new posts."); thread.NewPostCount = -1; } return(thread); }
public static ThreadMetadata ParseThread(HtmlNode node) { ThreadMetadata thread = new ThreadMetadata() .ParseThreadID(node) .ParseThreadSeen(node) .ParseThreadTitleAndUrl(node) .ParseThreadAuthor(node) .ParseReplies(node) .ParseRating(node) .ParseSticky(node) .ParseColorCategory(node) .ParseIconUri(node); thread.LastUpdated = DateTime.Now; return(thread); }
private static ThreadMetadata ParseRating(this ThreadMetadata thread, HtmlNode node) { var ratingNode = node.Descendants("td") .Where(parent => parent.GetAttributeValue("class", "").Contains("rating")) .FirstOrDefault(); if (ratingNode != null) { ratingNode = ratingNode.Element("img"); } if (ratingNode == null) { thread.Rating = 0; } else { string src = ratingNode.GetAttributeValue("src", ""); var tokens = src.Split('/'); var ratingToken = tokens[tokens.Length - 1]; switch (ratingToken) { case CoreConstants.THREAD_RATING_5: thread.Rating = 5; break; case CoreConstants.THREAD_RATING_4: thread.Rating = 4; break; case CoreConstants.THREAD_RATING_3: thread.Rating = 3; break; case CoreConstants.THREAD_RATING_2: thread.Rating = 2; break; case CoreConstants.THREAD_RATING_1: thread.Rating = 1; break; } } return(thread); }
private static ThreadMetadata ParseIconUri(this ThreadMetadata thread, HtmlNode node) { var iconNode = node.Descendants("td") .Where(n => n.GetAttributeValue("class", "") .Contains("icon")).FirstOrDefault(); if (iconNode != null) { var imageNode = iconNode.Descendants("img").FirstOrDefault(); if (imageNode != null) { thread.IconUri = imageNode.Attributes["src"].Value; } } return(thread); }
private void LoadFromQuery() { var query = NavigationContext.QueryString; if (query.ContainsKey("link")) { string value = query["link"]; try { this.threadSlideView.ControlViewModel.LoadPageFromUri(new Uri(value)); } catch (Exception ex) { AwfulDebugger.AddLog(this, AwfulDebugger.Level.Critical, ex); NavigationService.GoBack(); } } else if (query.ContainsKey("id") && query.ContainsKey("nav")) { string ThreadID = query["id"]; ThreadMetadata thread = new ThreadMetadata() { ThreadID = ThreadID }; switch (query["nav"]) { case "unread": this.threadSlideView.ControlViewModel.LoadFirstUnreadPost(thread); break; case "last": this.threadSlideView.ControlViewModel.LoadLastPost(thread); break; case "page": int pageNumber = -1; int.TryParse(query["pagenumber"], out pageNumber); this.threadSlideView.ControlViewModel.LoadPageNumber(thread, pageNumber); break; } } }
private void ProcessToggleBookmarkAsyncGetRequest(IAsyncResult asyncResult, AutoResetEvent signal, BookmarkAction action, ThreadMetadata data) { //Logger.AddEntry("ToggleBookmarkAsync - Initializingweb request..."); HttpWebRequest request = asyncResult.AsyncState as HttpWebRequest; StreamWriter writer = new StreamWriter(request.EndGetRequestStream(asyncResult)); var postData = String.Format("{0}&{1}={2}", action == BookmarkAction.Add ? CoreConstants.BOOKMARK_ADD : CoreConstants.BOOKMARK_REMOVE, CoreConstants.THREAD_ID, data.ThreadID); //Logger.AddEntry(string.Format("ToggleBookmarkAsync - PostData: {0}", postData)); writer.Write(postData); writer.Close(); signal.Set(); }
private static ThreadMetadata ParseThreadTitleAndUrl(this ThreadMetadata thread, HtmlNode node) { // check if thread is basic thread var threadTitleNode = node.Descendants("a") .Where(value => value.GetAttributeValue("class", "").Equals("thread_title")) .FirstOrDefault(); if (threadTitleNode != null) { var title = threadTitleNode.InnerText.Sanitize(); thread.Title = HttpUtility.HtmlDecode(title); } else { // check if thread is an announcement thread threadTitleNode = node.Descendants("td") .Where(value => value.GetAttributeValue("class", "").Equals("title")) .FirstOrDefault(); if (threadTitleNode != null) { var titleTextNode = threadTitleNode.Descendants("a").First(); var title = titleTextNode.InnerText.Sanitize(); thread.Title = HttpUtility.HtmlDecode(title); } else { throw new Exception("Could not parse thread title!"); } } //Logger.AddEntry(string.Format("AwfulThread - Thread Title: {0}", thread.Title)); //thread.PageUri = Constants.BASE_URL + "/" + threadTitleNode.GetAttributeValue("href", ""); //Logger.AddEntry(string.Format("AwfulThread - Thread Url: '{0}'", thread.Url)); return(thread); }
private static ThreadMetadata ParseColorCategory(this ThreadMetadata thread, HtmlNode node) { // code block example: <td class="star bm0"> var colorNode = node.Descendants("td").Where(aNode => aNode.GetAttributeValue("class", "") .Contains("star")).FirstOrDefault(); if (colorNode != null) { try { string colorValue = colorNode.GetAttributeValue("class", ""); string categoryToken = colorValue.Split(new char[] { ' ' })[1]; thread.ColorCategory = ConvertColorValueToBookmarkCategory(categoryToken); } catch (Exception ex) { AwfulDebugger.AddLog(thread, AwfulDebugger.Level.Info, ex); thread.ColorCategory = BookmarkColorCategory.Unknown; } } return(thread); }
public static Uri Reply(ThreadMetadata data, string message) { return(ThreadReplyTask.Reply(data, message)); }
public static Uri Reply(ThreadMetadata thread, string text) { return(instance.ReplyToThread(thread, text)); }
public static int Rate(this ThreadMetadata thread, int rating) { bool success = ThreadTasks.Rate(thread, rating); return(success ? rating : -1); }
public static ThreadPageMetadata Page(this ThreadMetadata thread, int pageNumber) { return(AwfulContentRequest.Threads.LoadThreadPage(thread.ThreadID, pageNumber)); }
public static ThreadPageMetadata LastPage(this ThreadMetadata thread) { return(AwfulContentRequest.Threads.LoadThreadLastPostPage(thread.ThreadID)); }
public static IThreadPostRequest CreateReplyRequest(this ThreadMetadata thread) { return(AwfulContentRequest.Threads.BeginReplyToThread(thread.ThreadID)); }
public static bool AddToUserBookmarks(this UserMetadata user, ThreadMetadata thread) { return(ThreadTasks.AddBookmark(thread)); }
public static bool RemoveFromUserBookmarks(this UserMetadata user, ThreadMetadata thread) { return(ThreadTasks.RemoveBookmark(thread)); }
public static bool Bookmark(ThreadMetadata thread, BookmarkAction action) { return(instance.ToggleBookmark(thread, action)); }
public static bool RemoveBookmark(ThreadMetadata data) { return(ThreadBookmarkTask.Bookmark(data, BookmarkAction.Remove)); }