Beispiel #1
0
        /// <summary>
        /// 用于“刷新到尾页”等功能
        /// 直接打开指定主题的最后一页加载数据并返回最后一个回复的Index等数据,以便直接跳到此回复
        /// </summary>
        /// <param name="threadId"></param>
        /// <param name="cts"></param>
        /// <returns></returns>
        public async Task <int[]> LoadReplyDataForRedirectToLastPostAsync(int threadId, CancellationTokenSource cts)
        {
            // 读取数据
            string url     = string.Format("http://www.hi-pda.com/forum/viewthread.php?tid={0}&page=9999999&_={1}", threadId, DateTime.Now.Ticks.ToString("x"));
            string htmlStr = await _httpClient.GetAsync(url, cts);

            // 实例化 HtmlAgilityPack.HtmlDocument 对象
            HtmlDocument doc = new HtmlDocument();

            // 载入HTML
            doc.LoadHtml(htmlStr);

            // 先清空本贴的回复数据,以便重新加载
            _replyData.RemoveAll(r => r.ThreadId == threadId);
            var threadReply = new ReplyPageModel {
                ThreadId = threadId, Replies = new List <ReplyItemModel>()
            };

            _replyData.Add(threadReply);

            // 获取当前页码,及最大页码
            int pageNo           = 1;
            var forumControlNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("forumcontrol s_clear"));
            var pagesNode        = forumControlNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("pages"));

            if (pagesNode != null)
            {
                var nodeList = pagesNode.Descendants().Where(n => n.Name.Equals("a") || n.Name.Equals("strong")).ToList();
                nodeList.RemoveAll(n => n.InnerText.Equals("下一页"));
                string lastPageNodeValue = nodeList.Last().InnerText.Replace("... ", string.Empty);
                _maxPageNo = Convert.ToInt32(lastPageNodeValue);

                var currentPageNode = nodeList.FirstOrDefault(n => n.Name.Equals("strong"));
                if (currentPageNode != null)
                {
                    pageNo = Convert.ToInt32(currentPageNode.InnerText);
                }
            }

            int    threadAuthorUserId   = 0;
            string threadAuthorUsername = string.Empty;
            string threadTitle          = string.Empty;

            #region 如果第一项没有贴子及作者数据,则加载第一页读取贴子标题及作者数据
            if (pageNo > 1)
            {
                var item = threadReply.Replies.FirstOrDefault();
                if (item == null || item.ThreadAuthorUserId == 0 || string.IsNullOrEmpty(item.ThreadTitle))
                {
                    string val = await LoadTopReplyDataAsync(threadId, cts);

                    string[] ary = val.Split(',');
                    threadAuthorUserId   = Convert.ToInt32(ary[0]);
                    threadAuthorUsername = ary[1];
                    threadTitle          = ary[2];
                }
                else
                {
                    threadAuthorUserId   = item.ThreadAuthorUserId;
                    threadAuthorUsername = item.AuthorUsername;
                    threadTitle          = item.ThreadTitle;
                }
            }
            #endregion

            // 读取所属版块之名称及ID
            int    forumId   = 0;
            string forumName = string.Empty;
            var    navNode   = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("id", "").Equals("nav"));
            if (navNode != null)
            {
                var forumLinkNode = navNode.ChildNodes[3];
                forumId   = Convert.ToInt32(forumLinkNode.Attributes[0].Value.Substring("forumdisplay.php?fid=".Length).Split('&')[0]);
                forumName = forumLinkNode.InnerText.Trim();
            }

            var data = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("id", "").Equals("postlist")).ChildNodes;
            int i    = 0;
            int j    = 1;
            foreach (var item in data)
            {
                var mainTable    = item.Descendants().FirstOrDefault(n => n.Name.Equals("table") && n.GetAttributeValue("summary", "").StartsWith("pid"));
                var tableRowNode = mainTable.ChildNodes[1];      // tr

                var postAuthorNode = tableRowNode.ChildNodes[1]; // td.postauthor
                if (string.IsNullOrEmpty(postAuthorNode.InnerText))
                {
                    tableRowNode   = mainTable.ChildNodes[3];    // tr
                    postAuthorNode = tableRowNode.ChildNodes[1]; // td.postauthor
                }

                var postContentNode = tableRowNode.ChildNodes[3]; // td.postcontent

                int    authorUserId   = 0;
                string authorUsername = string.Empty;
                var    authorNode     = postAuthorNode.ChildNodes.FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("postinfo"));
                if (authorNode != null)
                {
                    authorNode = authorNode.ChildNodes[1]; // a
                    string authorUserIdStr = authorNode.Attributes[1].Value.Substring("space.php?uid=".Length);
                    if (authorUserIdStr.Contains("&"))
                    {
                        authorUserId = Convert.ToInt32(authorUserIdStr.Split('&')[0]);
                    }
                    else
                    {
                        authorUserId = Convert.ToInt32(authorUserIdStr);
                    }
                    authorUsername = authorNode.InnerText;
                }

                // 判断当前用户是否已被屏蔽,是则跳过
                if (_myRoamingSettings.BlockUsers.Any(u => u.UserId == authorUserId && u.ForumId == forumId))
                {
                    j++;
                    continue;
                }

                var floorPostInfoNode = postContentNode.ChildNodes.FirstOrDefault(n => n.GetAttributeValue("class", "").StartsWith("postinfo")); // div
                var floorLinkNode     = floorPostInfoNode.ChildNodes[1].ChildNodes[0];                                                           // a
                int postId            = Convert.ToInt32(floorLinkNode.Attributes["id"].Value.Replace("postnum", string.Empty));
                var floorNumNode      = floorLinkNode.ChildNodes[0];                                                                             // em
                int floor             = Convert.ToInt32(floorNumNode.InnerText);
                if (floor == 1)
                {
                    threadAuthorUserId   = authorUserId;
                    threadAuthorUsername = authorUsername;
                    var threadTitleNode = postContentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("id", "").Equals("threadtitle"));
                    if (threadTitleNode != null)
                    {
                        var h1 = threadTitleNode.ChildNodes[1];
                        var a  = h1.Descendants().FirstOrDefault(n => n.Name.Equals("a"));
                        if (a != null)
                        {
                            h1.RemoveChild(a); // 移除版块名称
                        }

                        threadTitle = h1.InnerText.Trim();
                        threadTitle = CommonService.MyHtmlDecodeForLoad(threadTitle);
                    }
                }

                string postTime     = string.Empty;
                var    postTimeNode = postContentNode.Descendants().FirstOrDefault(n => n.Name.Equals("em") && n.GetAttributeValue("id", "").StartsWith("authorposton")); // em
                if (postTimeNode != null)
                {
                    postTime = postTimeNode.InnerText
                               .Replace("发表于 ", string.Empty)
                               .Replace(string.Format("{0}-{1}-{2} ", DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day), string.Empty)
                               .Replace(string.Format("{0}-", DateTime.Now.Year), string.Empty);
                }

                string textContent    = string.Empty;
                string xamlContent    = string.Empty;
                int    imageCount     = 0;
                int    inAppLinkCount = 0;
                var    contentNode    = postContentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("t_msgfontfix"));
                if (contentNode != null)
                {
                    // 用于回复引用
                    textContent = contentNode.InnerText.Trim();
                    textContent = new Regex("\r\n").Replace(textContent, "↵");
                    textContent = new Regex("\r").Replace(textContent, "↵");
                    textContent = new Regex("\n").Replace(textContent, "↵");
                    textContent = new Regex(@"↵{1,}").Replace(textContent, "\r\n");
                    textContent = textContent.Replace("&nbsp;", "  ");

                    // 转换HTML为XAML
                    string htmlContent = contentNode.InnerHtml.Trim();
                    var    ary         = Html.HtmlToXaml.ConvertPost(postId, threadId, forumId, forumName, htmlContent, _floorNoDic, ref InAppLinkUrlDic);
                    xamlContent    = ary[0];
                    inAppLinkCount = Convert.ToInt32(ary[1]);
                }
                else
                {
                    xamlContent = $@"<StackPanel xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""><RichTextBlock><Paragraph>作者被禁止或删除&#160;内容自动屏蔽</Paragraph></RichTextBlock></StackPanel>";
                }

                var reply = new ReplyItemModel(i, j, floor, postId, pageNo, forumId, forumName, threadId, threadTitle, threadAuthorUserId, authorUserId, authorUsername, textContent, xamlContent, postTime, imageCount, false, inAppLinkCount);
                threadReply.Replies.Add(reply);

                if (!_floorNoDic.ContainsKey(postId))
                {
                    _floorNoDic.Add(postId, new string[] { authorUserId.ToString(), floor.ToString() });
                }

                i++;
                j++;
            }

            // 如果本次有加载到数据,则为数据列表的末尾添加一项“载入已完成”的标记项
            // 方便在加载完成时显示“---完---”
            // 注意在下一页开始加载前移除此标记项
            if (i > 0)
            {
                var lastItem = threadReply.Replies.Last();
                var flag     = new ReplyItemModel(lastItem.Index + 1, lastItem.Index2, -1, -1, lastItem.PageNo, -1, string.Empty, lastItem.ThreadId, string.Empty, -1, -1, string.Empty, string.Empty, string.Empty, string.Empty, -1, false, 0);
                flag.IsLast = true;
                threadReply.Replies.Add(flag);
            }

            // 加入历史记录
            ApplicationView.GetForCurrentView().Title = $"{CommonService.ReplaceEmojiLabel(threadTitle)} - {CommonService.ReplaceEmojiLabel(forumName)}";
            _threadHistoryListBoxViewModel.Add(new ThreadItemModelBase {
                ThreadId = threadId, Title = threadTitle, ForumId = forumId, ForumName = forumName, AuthorUserId = threadAuthorUserId, AuthorUsername = threadAuthorUsername
            });

            int index = threadReply.Replies.Last().Index;
            return(new int[] { pageNo, index, threadId });
        }
Beispiel #2
0
        public static async Task <PostEditDataModel> LoadContentForEditAsync(CancellationTokenSource cts, int postId, int threadId)
        {
            string url         = $"http://www.hi-pda.com/forum/post.php?action=edit&tid={threadId}&pid={postId}&_={DateTime.Now.Ticks.ToString("x")}";
            string htmlContent = await _httpClient.GetAsync(url, cts);

            // 实例化 HtmlAgilityPack.HtmlDocument 对象
            HtmlDocument doc = new HtmlDocument();

            // 载入HTML
            doc.LoadHtml(htmlContent);

            // 标题
            string title        = string.Empty;
            var    subjectInput = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("input") && n.GetAttributeValue("prompt", string.Empty).Equals("post_subject"));

            if (subjectInput != null)
            {
                title = subjectInput.Attributes["value"].Value;
                title = CommonService.MyHtmlDecodeForLoad(title);
            }

            // 内容
            string content         = string.Empty;
            var    contentTextArea = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("textarea") && n.GetAttributeValue("prompt", string.Empty).Equals("post_message"));

            if (contentTextArea != null)
            {
                content = contentTextArea.InnerText.Replace(SendService.MessageTail, string.Empty).TrimEnd();
                content = CommonService.MyHtmlDecodeForLoad(content);
            }

            // 读取图片附件
            var attachFileList      = new ObservableCollection <AttachFileItemModel>();
            var uploadFileListNodes = doc.DocumentNode.Descendants().Where(n => n.Name.Equals("div") && n.GetAttributeValue("class", string.Empty).Equals("upfilelist"));
            var imgList             = uploadFileListNodes.First()?.ChildNodes.FirstOrDefault(n => n.Name.Equals("table") && n.GetAttributeValue("class", string.Empty).Equals("imglist"));

            if (imgList != null)
            {
                var images = imgList.Descendants().Where(n => n.Name.Equals("img") && n.GetAttributeValue("src", string.Empty).StartsWith("attachments/day_") && n.GetAttributeValue("id", string.Empty).StartsWith("image_"));
                if (images != null)
                {
                    foreach (var img in images)
                    {
                        string id  = img.GetAttributeValue("id", string.Empty).Replace("image_", string.Empty);
                        string src = img.GetAttributeValue("src", string.Empty);
                        //src = $"http://www.hi-pda.com/forum/{src}";
                        attachFileList.Add(new AttachFileItemModel(0, id, src, true));
                    }
                }
            }

            // 读取文件附件
            var fileList = uploadFileListNodes.Last()?.ChildNodes.FirstOrDefault(n => n.Name.Equals("table") && n.GetAttributeValue("summary", string.Empty).Equals("post_attachbody"));

            if (fileList != null)
            {
                var fileLinks = fileList.Descendants().Where(n => n.Name.Equals("a") && (n.GetAttributeValue("onclick", string.Empty).StartsWith("insertAttachTag(") || n.GetAttributeValue("onclick", string.Empty).StartsWith("insertAttachimgTag(")));
                if (fileLinks != null)
                {
                    foreach (var link in fileLinks)
                    {
                        string attr = link.GetAttributeValue("onclick", string.Empty);
                        if (attr.StartsWith("insertAttachTag("))
                        {
                            string id       = attr.Replace("insertAttachTag('", string.Empty).Replace("')", string.Empty);
                            string fileName = link.InnerText.Trim();
                            attachFileList.Add(new AttachFileItemModel(1, id, fileName, true));
                        }
                        else if (attr.StartsWith("insertAttachimgTag("))
                        {
                            string id      = attr.Replace("insertAttachimgTag('", string.Empty).Replace("')", string.Empty);
                            var    imgNode = fileList.Descendants().FirstOrDefault(f => f.Name.Equals("img") && f.GetAttributeValue("id", string.Empty).StartsWith($"image_{id}"));
                            string src     = imgNode.Attributes[0].Value;
                            //src = $"http://www.hi-pda.com/forum/{src}";
                            attachFileList.Add(new AttachFileItemModel(0, id, src, true));
                        }
                    }
                }
            }

            return(new PostEditDataModel(postId, threadId, title, content, attachFileList));
        }
Beispiel #3
0
        async Task <string> LoadTopReplyDataAsync(int threadId, CancellationTokenSource cts)
        {
            string threadTitle          = string.Empty;
            int    threadAuthorUserId   = 0;
            string threadAuthorUsername = string.Empty;

            // 读取数据
            string url     = string.Format("http://www.hi-pda.com/forum/viewthread.php?tid={0}&page=1", threadId);
            string htmlStr = await _httpClient.GetAsync(url, cts);

            // 实例化 HtmlAgilityPack.HtmlDocument 对象
            HtmlDocument doc = new HtmlDocument();

            // 载入HTML
            doc.LoadHtml(htmlStr);

            var data = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("id", "").Equals("postlist"))?.ChildNodes;

            if (data == null)
            {
                return(null);
            }

            var item           = data[0];
            var mainTable      = item.Descendants().FirstOrDefault(n => n.Name.Equals("table") && n.GetAttributeValue("summary", "").StartsWith("pid") && n.GetAttributeValue("id", "").Equals(n.GetAttributeValue("summary", "")));
            var postAuthorNode = mainTable        // table
                                 .ChildNodes[1]   // tr
                                 .ChildNodes[1];  // td.postauthor

            var postContentNode = mainTable       // table
                                  .ChildNodes[1]  // tr
                                  .ChildNodes[3]; // td.postcontent

            int authorUserId = 0;
            var authorNode   = postAuthorNode.ChildNodes.FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("postinfo"));

            if (authorNode != null)
            {
                authorNode = authorNode.ChildNodes[1]; // a
                string authorUserIdStr = authorNode.Attributes[1].Value.Substring("space.php?uid=".Length);
                if (authorUserIdStr.Contains("&"))
                {
                    authorUserId = Convert.ToInt32(authorUserIdStr.Split('&')[0]);
                }
                else
                {
                    authorUserId = Convert.ToInt32(authorUserIdStr);
                }
                threadAuthorUserId   = authorUserId;
                threadAuthorUsername = authorNode.InnerText.Trim();
            }

            var threadTitleNode = postContentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("id", "").Equals("threadtitle"));

            if (threadTitleNode != null)
            {
                var h1 = threadTitleNode.ChildNodes[1];
                var a  = h1.Descendants().FirstOrDefault(n => n.Name.Equals("a"));
                if (a != null)
                {
                    h1.RemoveChild(a); // 移除版块名称
                }

                threadTitle = h1.InnerText.Trim();
                threadTitle = CommonService.MyHtmlDecodeForLoad(threadTitle);
            }

            return($"{threadAuthorUserId},{threadAuthorUsername},{threadTitle}");
        }