예제 #1
0
        async Task LoadUserDataAsync(int userId, CancellationTokenSource cts)
        {
            if (_userInfoData.ContainsKey(userId))
            {
                return;
            }

            // 读取数据
            string url         = string.Format("http://www.hi-pda.com/forum/space.php?uid={0}&_={1}", userId, DateTime.Now.Ticks.ToString("x"));
            string htmlContent = await _httpClient.GetAsync(url, cts);

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

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

            // 最先读取提醒数据
            var promptContentNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("promptcontent"));

            PromptService.GetPromptData(promptContentNode);

            var node = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("id", "").Equals("profilecontent"));

            if (node != null)
            {
                string xaml = Html.HtmlToXaml.ConvertUserInfo(node.InnerHtml);
                _userInfoData.Add(userId, xaml);
            }
        }
예제 #2
0
        async Task LoadUserMessageListDataAsync(int pageNo, CancellationTokenSource cts)
        {
            if (pageNo == 1)
            {
                // 如果是新打开,则清空所有短消息列表数据
                _userMessageListData.Clear();
            }

            if (pageNo > _userMessageListMaxPageNo)
            {
                return;
            }

            // 读取数据
            string url     = string.Format("http://www.hi-pda.com/forum/pm.php?filter=privatepm&page={0}&_={1}", pageNo, DateTime.Now.Ticks.ToString("x"));
            string htmlStr = await _httpClient.GetAsync(url, cts);

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

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

            // 最先读取提醒数据
            var promptContentNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("promptcontent"));

            PromptService.GetPromptData(promptContentNode);

            var items = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("ul") && n.GetAttributeValue("class", "").Equals("pm_list"))?.ChildNodes;

            if (items == null)
            {
                return;
            }

            // 读取最大页码
            var pagesNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("pages"));

            _userMessageListMaxPageNo = CommonService.GetMaxPageNo(pagesNode);

            int i = _userMessageListData.Count;

            foreach (var item in items)
            {
                var    isNew           = item.ChildNodes[3].ChildNodes.Count >= 4 && item.ChildNodes[3].ChildNodes[3].Name.Equals("img");
                var    linkNode        = item.ChildNodes[3].ChildNodes[1].ChildNodes[0];
                int    userId          = Convert.ToInt32(linkNode.Attributes[0].Value.Substring("space.php?uid=".Length).Split('&')[0]);
                string username        = linkNode.InnerText.Trim();
                string lastMessageTime = item.ChildNodes[3].ChildNodes[2].InnerText.Trim().Replace(" ", string.Empty);
                string lastMessageText = item.ChildNodes[5].InnerText.Trim();

                var userMessageListItem = new UserMessageListItemModel(i, isNew, pageNo, userId, username, lastMessageTime, lastMessageText);
                _userMessageListData.Add(userMessageListItem);

                i++;
            }
        }
예제 #3
0
        async Task <UserMessageDataModel> LoadUserMessageDataAsync(int userId, int limitCount, CancellationTokenSource cts)
        {
            var listData = new ObservableCollection <UserMessageItemModel>();
            int total    = 0;

            // 读取数据
            string url         = string.Format("http://www.hi-pda.com/forum/pm.php?uid={0}&filter=privatepm&daterange=5&_={1}", userId, DateTime.Now.Ticks.ToString("x"));
            string htmlContent = await _httpClient.GetAsync(url, cts);

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

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

            // 最先读取提醒数据
            var promptContentNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("promptcontent"));

            PromptService.GetPromptData(promptContentNode);

            var messageListNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("pm_list"));

            if (messageListNode != null)
            {
                var nodeList = messageListNode.Descendants().Where(n => n.GetAttributeValue("id", "").StartsWith("pm_"));
                if (nodeList != null)
                {
                    total = nodeList.Count();
                    if (limitCount != -1 && total > limitCount)
                    {
                        nodeList = nodeList.Skip(total - limitCount);
                    }

                    foreach (var item in nodeList)
                    {
                        listData.Add(GetUserMessageItem(item));
                    }
                }
            }

            // 清除此用户的私信标识为“NEW”状态的 toast temp data
            ToastService.ClearPmToastTempData(userId);

            return(new UserMessageDataModel {
                ListData = listData, Total = total
            });
        }
예제 #4
0
        async Task LoadThreadDataForMyPostsAsync(int pageNo, CancellationTokenSource cts)
        {
            int count = _threadDataForMyPosts.Count(t => t.PageNo == pageNo);

            if (count == _pageSize)
            {
                return;
            }
            else
            {
                _threadDataForMyPosts.RemoveAll(t => t.PageNo == pageNo);
            }

            // 读取数据
            string url         = string.Format("http://www.hi-pda.com/forum/my.php?item=posts&page={0}&_={1}", pageNo, DateTime.Now.Ticks.ToString("x"));
            string htmlContent = await _httpClient.GetAsync(url, cts);

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

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

            // 最先读取提醒数据
            var promptContentNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("promptcontent"));

            PromptService.GetPromptData(promptContentNode);

            // 读取主内容
            var dataTable = doc.DocumentNode.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("datatable"));

            if (dataTable == null)
            {
                return;
            }

            // 读取最大页码
            var pagesNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("pages"));

            _maxPageNo = CommonService.GetMaxPageNo(pagesNode);

            if (pageNo > _maxPageNo)
            {
                return;
            }

            var rows = dataTable.ChildNodes[3].Descendants().Where(n => n.Name.Equals("tr")).ToList();

            if (rows == null)
            {
                return;
            }

            int i = _threadDataForMyPosts.Count;

            for (int j = 0; j < rows.Count - 1; j += 2)
            {
                var tr  = rows[j];
                var tr2 = rows[j + 1];

                var      th         = tr.Descendants().FirstOrDefault(n => n.Name.Equals("th"));
                var      a          = th.Descendants().FirstOrDefault(n => n.Name.Equals("a"));
                string   threadName = a.InnerText.Trim();
                string[] pramaStr   = a.GetAttributeValue("href", "").Substring("redirect.php?goto=findpost&amp;pid=".Length).Replace("&amp;ptid=", ",").Split(',');
                int      threadId   = Convert.ToInt32(pramaStr[1]);
                int      postId     = Convert.ToInt32(pramaStr[0]);

                var    th2             = tr2.Descendants().FirstOrDefault(n => n.Name.Equals("th"));
                string lastPostContent = th2.InnerText.Trim();
                lastPostContent = lastPostContent.Replace("\n", string.Empty);
                lastPostContent = lastPostContent.Replace("\r", string.Empty);

                var    forumNameNode = tr.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("forum"));
                string forumName     = forumNameNode.InnerText.Trim();

                var    lastPostNode = tr.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("lastpost"));
                string lastPostTime = lastPostNode.InnerText.Trim();
                lastPostTime = lastPostTime
                               .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);

                var threadItem = new ThreadItemForMyPostsModel(i, forumName, threadId, postId, pageNo, threadName, lastPostContent, lastPostTime);
                _threadDataForMyPosts.Add(threadItem);

                i++;
            }
        }
예제 #5
0
        async Task LoadThreadDataForMyThreadsAsync(int pageNo, CancellationTokenSource cts)
        {
            int count = _threadDataForMyThreads.Count(t => t.PageNo == pageNo);

            if (count == _pageSize)
            {
                return;
            }
            else
            {
                _threadDataForMyThreads.RemoveAll(t => t.PageNo == pageNo);
            }

            // 读取数据
            string url         = string.Format("http://www.hi-pda.com/forum/my.php?item=threads&page={0}&_={1}", pageNo, DateTime.Now.Ticks.ToString("x"));
            string htmlContent = await _httpClient.GetAsync(url, cts);

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

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

            // 最先读取提醒数据
            var promptContentNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("promptcontent"));

            PromptService.GetPromptData(promptContentNode);

            // 读取主内容
            var dataTable = doc.DocumentNode.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("datatable"));

            if (dataTable == null)
            {
                return;
            }

            // 读取最大页码
            var pagesNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("pages"));

            _threadMaxPageNoForMyThreads = CommonService.GetMaxPageNo(pagesNode);

            if (pageNo > _threadMaxPageNoForMyThreads)
            {
                return;
            }

            var rows = dataTable.ChildNodes[3].Descendants().Where(n => n.Name.Equals("tr"));

            if (rows == null)
            {
                return;
            }

            int i = _threadDataForMyThreads.Count;

            foreach (var item in rows)
            {
                var    th         = item.Descendants().FirstOrDefault(n => n.Name.Equals("th"));
                var    a          = th.Descendants().FirstOrDefault(n => n.Name.Equals("a"));
                string threadName = a.InnerText.Trim();
                int    threadId   = Convert.ToInt32(a.GetAttributeValue("href", "").Substring("viewthread.php?tid=".Length));

                var    forumNameNode = item.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("forum"));
                string forumName     = forumNameNode.InnerText.Trim();

                var      lastPostNode       = item.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("lastpost"));
                string   lastPostAuthorName = "匿名";
                string   lastPostTime       = string.Empty;
                string[] lastPostInfo       = lastPostNode.InnerText.Trim().Replace("\n", "@").Split('@');
                if (lastPostInfo.Length == 2)
                {
                    lastPostAuthorName = lastPostInfo[0].Trim();
                    lastPostTime       = lastPostInfo[1].Trim()
                                         .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);
                }

                var threadItem = new ThreadItemForMyThreadsModel(i, forumName, threadId, pageNo, threadName, lastPostAuthorName, lastPostTime);
                _threadDataForMyThreads.Add(threadItem);

                i++;
            }
        }
예제 #6
0
        async Task LoadThreadDataForSearchFullTextAsync(string searchKeyword, string searchAuthor, int searchTimeSpan, int searchForumSpan, int pageNo, CancellationTokenSource cts)
        {
            int count = _threadDataForSearchFullText.Count(t => t.PageNo == pageNo);

            if (count == _pageSize)
            {
                return;
            }
            else
            {
                _threadDataForSearchFullText.RemoveAll(t => t.PageNo == pageNo);
            }

            // 读取数据
            string searchTimeSpanStr = string.Empty;

            switch (searchTimeSpan)
            {
            case 1:
                searchTimeSpanStr = "604800";     // 一周
                break;

            case 2:
                searchTimeSpanStr = "2592000";     // 一个月
                break;

            case 3:
                searchTimeSpanStr = "7776000";     // 三个月
                break;

            case 4:
                searchTimeSpanStr = "31536000";     // 一年
                break;

            default:
                searchTimeSpanStr = "0";     // 全部时间
                break;
            }

            string searchForumSpanStr = searchForumSpan == -1 ? "all" : searchForumSpan.ToString();

            string url = string.Format("http://www.hi-pda.com/forum/search.php?srchtype={2}&srchtxt={0}&searchsubmit=%CB%D1%CB%F7&st=on&srchuname={1}&srchfilter=all&srchfrom={3}&before=&orderby={5}&ascdesc=desc&srchfid%5B0%5D={4}&page={6}&_={7}",
                                       _httpClient.GetEncoding(searchKeyword), _httpClient.GetEncoding(searchAuthor), "fulltext", searchTimeSpanStr, searchForumSpanStr, "lastpost", pageNo, DateTime.Now.Ticks.ToString("x"));
            string htmlContent = await _httpClient.GetAsync(url, cts);

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

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

            // 最先读取提醒数据
            var promptContentNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("promptcontent"));

            PromptService.GetPromptData(promptContentNode);

            // 读取主内容
            var dataTable = doc.DocumentNode.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("datatable"));

            if (dataTable == null || dataTable.InnerText.Trim().Equals("对不起,没有找到匹配结果。"))
            {
                return;
            }

            // 读取最大页码
            var pagesNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("pages"));

            _threadMaxPageNoForSearchFullText = CommonService.GetMaxPageNo(pagesNode);

            if (pageNo > _threadMaxPageNoForSearchFullText)
            {
                return;
            }

            var rows = dataTable.Descendants().Where(n => n.Name.Equals("tr"));

            if (rows == null)
            {
                return;
            }

            int i = _threadDataForSearchFullText.Count;

            foreach (var r in rows)
            {
                string titleHtml      = string.Empty;
                int    postId         = 0;
                string summaryHtml    = string.Empty;
                string forumName      = string.Empty;
                string replyCount     = string.Empty;
                string viewCount      = string.Empty;
                string authorUsername = string.Empty;
                int    authorUserId   = 0;
                string lastReplyTime  = string.Empty;

                try
                {
                    var div  = r.ChildNodes[0].ChildNodes[0];
                    var div1 = div.ChildNodes[1];
                    var div2 = div.ChildNodes[3];
                    var div3 = div.ChildNodes[5];

                    var    titleNode = div1.ChildNodes[2];
                    string postIdStr = titleNode.Attributes[0].Value.Substring("gotopost.php?pid=".Length).Split('&')[0];
                    if (!string.IsNullOrEmpty(postIdStr))
                    {
                        postId      = Convert.ToInt32(postIdStr);
                        titleHtml   = WebUtility.HtmlDecode(titleNode.InnerHtml);
                        summaryHtml = WebUtility.HtmlDecode(div2.InnerHtml);
                        forumName   = div3.ChildNodes[1].ChildNodes[1].InnerText.Trim();
                        var authorNode = div3.ChildNodes[3];
                        authorUsername = authorNode.InnerText.Replace("作者: ", string.Empty).Trim();
                        authorUserId   = Convert.ToInt32(authorNode.ChildNodes[1].Attributes[0].Value.Substring("space.php?uid=".Length).Split('&')[0]);
                        viewCount      = div3.ChildNodes[5].InnerText.Trim().Replace("查看: ", string.Empty).Trim();
                        replyCount     = div3.ChildNodes[7].InnerText.Trim().Replace("回复: ", string.Empty).Trim();
                        lastReplyTime  = div3.ChildNodes[9].InnerText.Trim().Replace("最后发表: ", string.Empty).Trim();
                    }

                    var threadItem = new ThreadItemForSearchFullTextModel(i, postId, summaryHtml, forumName, pageNo, titleHtml, replyCount, viewCount, authorUsername, authorUserId, lastReplyTime);
                    _threadDataForSearchFullText.Add(threadItem);

                    i++;
                }
                catch (Exception ex)
                {
                    string errorDetails = "k: {0};p: {1};i: {2};t: {3};d: {4}";
                    errorDetails = string.Format(errorDetails, searchKeyword, pageNo, i, titleHtml, ex.Message);
                    CommonService.PostErrorEmailToDeveloper("全文搜索解析出现异常", errorDetails);
                }
            }
        }
예제 #7
0
        async Task LoadReplyDataAsync(int threadId, int pageNo, CancellationTokenSource cts)
        {
            if (pageNo > 1 && pageNo > _maxPageNo)
            {
                return;
            }

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

            // 如果页面已存在,则不重新从网站拉取数据,以便节省流量,
            var threadReply = _replyData.FirstOrDefault(r => r.ThreadId == threadId);

            if (threadReply != null && threadReply.Replies.Count > 0)
            {
                #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

                var pageData = threadReply.Replies.Where(r => r.PageNo == pageNo);
                if (pageData != null && pageData.Count() > 0)
                {
                    var lastItem = pageData.Last();
                    if (lastItem != null)
                    {
                        if (lastItem.Index2 == _pageSize) // 当前页已加载满
                        {
                            return;
                        }
                        else
                        {
                            threadReply.Replies.RemoveAll(r => r.PageNo == pageNo);
                        }
                    }
                }
                else
                {
                    if (pageNo == 1 && threadReply.Replies.Count > 0)
                    {
                        threadReply.Replies.Clear();
                    }
                }
            }
            else
            {
                threadReply = new ReplyPageModel {
                    ThreadId = threadId, Replies = new List <ReplyItemModel>()
                };
                _replyData.Add(threadReply);
            }

            // 先移除 IsLast 为 True 的标记项,确保此标记项永远只出现在最后面
            threadReply.Replies.RemoveAll(r => r.IsLast);

            // 读取数据
            string url     = string.Format("http://www.hi-pda.com/forum/viewthread.php?tid={0}&page={1}&ordertype={2}&_={3}", threadId, pageNo, string.Empty, DateTime.Now.Ticks.ToString("x"));
            string htmlStr = await _httpClient.GetAsync(url, cts);

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

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

            // 最先读取提醒数据
            var promptContentNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("promptcontent"));
            PromptService.GetPromptData(promptContentNode);

            // 读取最大页码
            var pagesNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("pages"));
            _maxPageNo = CommonService.GetMaxPageNo(pagesNode);

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

            // 读取所属版块之名称及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();
            }

            int i = threadReply.Replies.Count();
            int j = 1;
            foreach (var item in data)
            {
                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;
                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") || n.GetAttributeValue("class", "").Equals("specialmsg")));
                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 (j > 1)
            {
                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
            });
        }
예제 #8
0
        async Task LoadThreadDataAsync(int typeId, int forumId, int pageNo, CancellationTokenSource cts)
        {
            var d = _threadData.Where(t => t.ForumId == forumId && t.PageNo == pageNo);

            if (d != null && d.Count() > 0)
            {
                int indexInPage = d.Last().Index2;
                if (indexInPage == _pageSize)
                {
                    return;
                }
                else
                {
                    _threadData.RemoveAll(t => t.ForumId == forumId && t.PageNo == pageNo);
                }
            }

            if (pageNo == 1)
            {
                // 第一次打开或刷新时,先请求一下,看看是否有新私信
                // 这是论坛的一种机制,否则APP过了一段时间之后不能从HTML中解析私人消息的数量
                await _httpClient.GetAsync(string.Format("http://www.hi-pda.com/forum/pm.php?checknewpm={0}&inajax=1&ajaxtarget=myprompt_check", DateTime.Now.Ticks.ToString("x")), cts);
            }

            // 读取数据
            string _orderBy = RoamingSettingsService.GetOrderByDateline(forumId) == true ? "dateline" : string.Empty;
            string url      = string.Format("http://www.hi-pda.com/forum/forumdisplay.php?fid={0}&orderby={1}&page={2}&_={3}", forumId, _orderBy, pageNo, DateTime.Now.Ticks.ToString("x"));

            if (typeId > 0)
            {
                url += $"&filter=type&typeid={typeId}";
            }
            string htmlContent = await _httpClient.GetAsync(url, cts);

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

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

            // 最先读取提醒数据
            var promptContentNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("promptcontent"));

            PromptService.GetPromptData(promptContentNode);

            // 读取主内容
            var dataTable = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("table") && n.GetAttributeValue("class", "").Equals("datatable"));

            if (dataTable == null)
            {
                _maxPageNo = -1; // 找不到目标数据,一般为得到的是提示登录的页面的HTML,故在此将最大页标记为-1,以便增量加载不再继续
                return;
            }

            // 读取所属版块之名称
            string forumName = string.Empty;
            var    titleNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("title"));

            if (titleNode != null)
            {
                string[] tary = titleNode.InnerText.Trim().Split('-');
                forumName = tary[0].Trim();
            }

            // 读取最大页码
            var pagesNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("pages"));

            _maxPageNo = CommonService.GetMaxPageNo(pagesNode);

            if (pageNo > _maxPageNo)
            {
                return;
            }

            // 如果置顶贴数过多,只取非置顶贴的话,第一页数据项过少,会导致不会自动触发加载下一页数据
            var tbodies = dataTable.ChildNodes.Where(n => n.GetAttributeValue("id", "").Contains("stickthread_") || n.GetAttributeValue("id", "").Contains("normalthread_"));

            if (tbodies == null)
            {
                return;
            }

            int i = _threadData.Count(t => t.ForumId == forumId);
            int j = 1;

            foreach (var item in tbodies)
            {
                var tr         = item.ChildNodes[1];
                var th         = tr.ChildNodes[5];
                var span       = th.ChildNodes.FirstOrDefault(n => n.Name.Equals("span") && n.GetAttributeValue("id", "").StartsWith("thread_"));
                var a          = span.ChildNodes[0];
                var tdAuthor   = tr.ChildNodes[7];
                var tdNums     = tr.ChildNodes[9];
                var tdLastPost = tr.ChildNodes[11];

                int    threadId = Convert.ToInt32(span.Attributes[0].Value.Substring("thread_".Length));
                string title    = a.InnerText.Trim();
                title = WebUtility.HtmlDecode(title);

                // 判断当前主题是否已被屏蔽,是则跳过
                if (_myRoamingSettings.BlockThreads.Any(t => t.ThreadId == threadId))
                {
                    j++;
                    continue;
                }

                var authorName     = string.Empty;
                int authorUserId   = 0;
                var authorNameNode = tdAuthor.ChildNodes[1]; // cite 此节点有出“匿名”的可能
                var authorNameLink = authorNameNode.ChildNodes.FirstOrDefault(n => n.Name.Equals("a"));
                if (authorNameLink == null)
                {
                    authorName = authorNameNode.InnerText.Trim();
                }
                else
                {
                    authorName = authorNameLink.InnerText;
                    string authorUserIdStr = authorNameLink.Attributes[0].Value.Substring("space.php?uid=".Length);
                    if (authorUserIdStr.Contains("&"))
                    {
                        authorUserId = Convert.ToInt32(authorUserIdStr.Split('&')[0]);
                    }
                    else
                    {
                        authorUserId = Convert.ToInt32(authorUserIdStr);
                    }
                }

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

                bool isTop = item.GetAttributeValue("id", "").StartsWith("stickthread_");

                // 根据“是否显示置顶贴”的设置值来决定是否跳过当前主题
                if (!_myRoamingSettings.CanShowTopThread && isTop)
                {
                    j++;
                    continue;
                }

                int attachType     = -1;
                var attachIconNode = th.ChildNodes.FirstOrDefault(n => n.Name.Equals("img") && n.GetAttributeValue("class", "").Equals("attach"));
                if (attachIconNode != null)
                {
                    string attachString = attachIconNode.Attributes[1].Value;
                    if (attachString.Equals("图片附件"))
                    {
                        attachType = 1;
                    }

                    if (attachString.Equals("附件"))
                    {
                        attachType = 2;
                    }
                }

                var authorCreateTime = tdAuthor.ChildNodes[3].InnerText;

                string[] nums     = tdNums.InnerText.Split('/');
                var      replyNum = nums[0].Trim();
                var      viewNum  = nums[1].Trim();

                string   lastPostAuthorName = "匿名";
                string   lastPostTime       = string.Empty;
                string[] lastPostInfo       = tdLastPost.InnerText.Trim().Replace("\n", "@").Split('@');
                if (lastPostInfo.Length == 2)
                {
                    lastPostAuthorName = lastPostInfo[0].Trim();
                    lastPostTime       = lastPostInfo[1].Trim()
                                         .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);
                }

                var threadItem = new ThreadItemModel(i, j, forumId, forumName, threadId, pageNo, title, attachType, replyNum, viewNum, isTop, authorName, authorUserId, authorCreateTime, lastPostAuthorName, lastPostTime, AccountService.UserId == authorUserId);
                _threadData.Add(threadItem);

                i++;
                j++;
            }
        }
예제 #9
0
        async Task LoadThreadDataForSearchTitleAsync(string searchKeyword, string searchAuthor, int searchTimeSpan, int searchForumSpan, int pageNo, CancellationTokenSource cts)
        {
            int count = _threadDataForSearchTitle.Count(t => t.PageNo == pageNo);

            if (count == _pageSize)
            {
                return;
            }
            else
            {
                _threadDataForSearchTitle.RemoveAll(t => t.PageNo == pageNo);
            }

            // 读取数据
            string searchTimeSpanStr = string.Empty;

            switch (searchTimeSpan)
            {
            case 1:
                searchTimeSpanStr = "604800";     // 一周
                break;

            case 2:
                searchTimeSpanStr = "2592000";     // 一个月
                break;

            case 3:
                searchTimeSpanStr = "7776000";     // 三个月
                break;

            case 4:
                searchTimeSpanStr = "31536000";     // 一年
                break;

            default:
                searchTimeSpanStr = "0";     // 全部时间
                break;
            }

            string searchForumSpanStr = searchForumSpan == -1 ? "all" : searchForumSpan.ToString();

            string url = string.Format("http://www.hi-pda.com/forum/search.php?srchtype={2}&srchtxt={0}&searchsubmit=%CB%D1%CB%F7&st=on&srchuname={1}&srchfilter=all&srchfrom={3}&before=&orderby={5}&ascdesc=desc&srchfid%5B0%5D={4}&page={6}&_={7}",
                                       _httpClient.GetEncoding(searchKeyword), _httpClient.GetEncoding(searchAuthor), "title", searchTimeSpanStr, searchForumSpanStr, "lastpost", pageNo, DateTime.Now.Ticks.ToString("x"));
            string htmlContent = await _httpClient.GetAsync(url, cts);

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

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

            // 最先读取提醒数据
            var promptContentNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.Name.Equals("div") && n.GetAttributeValue("class", "").Equals("promptcontent"));

            PromptService.GetPromptData(promptContentNode);

            // 读取主内容
            var dataTable = doc.DocumentNode.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("datatable"));

            if (dataTable == null || dataTable.ChildNodes[2].InnerText.Trim().Equals("对不起,没有找到匹配结果。"))
            {
                return;
            }

            // 读取最大页码
            var pagesNode = doc.DocumentNode.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("pages"));

            _threadMaxPageNoForSearchTitle = CommonService.GetMaxPageNo(pagesNode);

            if (pageNo > _threadMaxPageNoForSearchTitle)
            {
                return;
            }

            var tbodies = dataTable.Descendants().Where(n => n.Name.Equals("tbody"));

            if (tbodies == null)
            {
                return;
            }

            int i = _threadDataForSearchTitle.Count;

            foreach (var item in tbodies)
            {
                var tr         = item.ChildNodes[1];
                var th         = tr.ChildNodes[5];
                var a          = th.ChildNodes[3];
                var tdAuthor   = tr.ChildNodes[9];
                var tdNums     = tr.ChildNodes[11];
                var tdLastPost = tr.ChildNodes[13];

                int    threadId    = 0;
                string threadIdStr = a.Attributes[0].Value.Substring("viewthread.php?tid=".Length);
                threadIdStr = threadIdStr.Split('&')[0];
                int.TryParse(threadIdStr, out threadId);

                string title = a.InnerHtml;

                int attachType     = -1;
                var attachIconNode = th.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("attach"));
                if (attachIconNode != null)
                {
                    string attachString = attachIconNode.Attributes[1].Value;
                    if (attachString.Equals("图片附件"))
                    {
                        attachType = 1;
                    }

                    if (attachString.Equals("附件"))
                    {
                        attachType = 2;
                    }
                }

                var    forumNameNode = item.Descendants().FirstOrDefault(n => n.GetAttributeValue("class", "").Equals("forum"));
                string forumName     = forumNameNode.InnerText.Trim();

                var authorUsername = string.Empty;
                int authorUserId   = 0;
                var authorNameNode = tdAuthor.ChildNodes[1]; // cite 此节点有出“匿名”的可能
                var authorNameLink = authorNameNode.Descendants().FirstOrDefault(n => n.Name.Equals("a"));
                if (authorNameLink == null)
                {
                    authorUsername = authorNameNode.InnerText.Trim();
                }
                else
                {
                    authorUsername = authorNameLink.InnerText;
                    string authorUserIdStr = authorNameLink.Attributes[0].Value.Substring("space.php?uid=".Length);
                    authorUserIdStr = authorUserIdStr.Split('&')[0];
                    authorUserId    = Convert.ToInt32(authorUserIdStr);
                }

                var authorCreateTime = tdAuthor.ChildNodes[3].InnerText;

                string[] nums       = tdNums.InnerText.Split('/');
                var      replyCount = nums[0].Trim();
                var      viewCount  = nums[1].Trim();

                string   lastReplyUsername = "******";
                string   lastReplyTime     = string.Empty;
                string[] lastPostInfo      = tdLastPost.InnerText.Trim().Replace("\n", "@").Split('@');
                if (lastPostInfo.Length == 2)
                {
                    lastReplyUsername = lastPostInfo[0];
                    lastReplyTime     = lastPostInfo[1]
                                        .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);
                }

                var threadItem = new ThreadItemForSearchTitleModel(i, searchKeyword, forumName, threadId, pageNo, title, attachType, replyCount, viewCount, authorUsername, authorUserId, authorCreateTime, lastReplyUsername, lastReplyTime);
                _threadDataForSearchTitle.Add(threadItem);

                i++;
            }
        }