/// <summary> /// Assemble a tooltip string using the marker text as input. /// </summary> /// <param name="markerText">input marker</param> /// <returns>the tooltip</returns> public string GetTooltip(string markerText) { if (!_api.IsConfigured) { return(FormatText("<Bold>Plugin not configured!</Bold>")); } // Get the entry info String text = String.Empty; try { int entryNumber = Int32.Parse(markerText); SourceForgeEntry entry = _api.GetEntry(entryNumber); // Check that we get a proper entry if (entry == null) { return(FormatText("<Bold>Error retrieving entry!</Bold>")); } text = entry.GetTooltip(); if (!String.IsNullOrEmpty(text)) { return(FormatText(text)); } } catch (ArgumentNullException) { return(FormatText("<Bold>Error: Not a valid entry number!</Bold>")); } catch (Exception e) { return(FormatText(String.Format("<Bold>Internal error: {0}</Bold>", e.Message))); } return(text); }
/// <summary> /// Get information on an entry /// </summary> /// <param name="entryNumber">the entry number</param> /// <returns>a SourceForgeEntry containing the information</returns> public SourceForgeEntry GetEntry(int entryNumber) { SourceForgeEntry entry = new SourceForgeEntry(); try { // Search for this entry String page = String.Empty; using (var client = new WebClient()) { page = client.DownloadString(String.Format("http://sourceforge.net/search/index.php?group_id={0}&type_of_search=artifact&q=&artifact_id={1}", _groupId, entryNumber)); page = TrimPage(page); if (String.IsNullOrEmpty(page)) { return(null); } // Try getting the entry data string regPattern = "<td class=\"p5\"> (?<priority>[^<]*) </td> <td> (?<id>[^<]*) </td> <td> <a href=\"/tracker/\\?group_id=(?:[0-9]*)&atid=(?<trackerId>[^\"]*)\">(?<tracker>[^<]*)</a> </td> <td class=\"summary\"> <a href=\"(?<url>[^\"]*)\">(?<title>[^<]*)</a> </td> <td> <a (?:[^>]*)>(?<assignee>[^<]*)</a>(?:<a[^>]*><img[^>]*></a>)* </td> <td> <a (?:[^>]*)>(?<submitter>[^<]*)</a> </td> <td> (?<status>[^<]*) </td> <td> (?<opened>[^<]*) </td>"; Regex reg = new Regex(regPattern, RegexOptions.Singleline); if (reg.IsMatch(page)) { Match m = reg.Match(page); GroupCollection collection = m.Groups; entry.priority = collection["priority"].Value; entry.tracker = collection["tracker"].Value; entry.title = collection["title"].Value; entry.assignee = collection["assignee"].Value; entry.submitter = collection["submitter"].Value; entry.status = collection["status"].Value; entry.opened = collection["opened"].Value; // Save the tracker id for later _lastTrackerId = collection["trackerId"].Value; // We need to open the bug page and get the details and last comment if necessary if (!String.IsNullOrEmpty(collection["url"].Value) && (ShowDetails || ShowLastComment || ShowSummary)) { page = client.DownloadString(String.Format("http://sourceforge.net{0}", collection["url"].Value)); page = TrimPage(page); if (String.IsNullOrEmpty(page)) { return(entry); } if (ShowDetails || ShowSummary) { string detailsPattern = "<label>Details:</label> <p><!-- google_ad_section_start -->(?<details>.*)<!-- google_ad_section_end --></p> <hr noshade=\"noshade\" class=\"divider\" /> <div class=\"yui-u first\"> <label>Submitted:</label> <p>(?<submitter>[^(]*)(?:.*)<label>Resolution:</label> <p>(?<resolution>[^<]*)</p> </div> <div class=\"yui-u\"> <label>Assigned:</label> <p>(?<assignee>[^<]*)</p> <label>Category:</label> <p><!-- google_ad_section_start -->(?<category>[^<]*)<!-- google_ad_section_end --></p> <label>Group:</label> <p>(?<group>[^<]*)</p>"; Regex regDetails = new Regex(detailsPattern, RegexOptions.Singleline); if (regDetails.IsMatch(page)) { Match mDetails = regDetails.Match(page); GroupCollection details = mDetails.Groups; if (ShowSummary) { entry.summary = CleanupBRs(details["details"].Value); } if (ShowDetails) { entry.submitterName = details["submitter"].Value; entry.resolution = details["resolution"].Value; entry.assigneeName = details["assignee"].Value; entry.category = details["category"].Value; entry.group = details["group"].Value; } } } // Last comment if (ShowLastComment) { string lastCommentPattern = "<input type=\"hidden\" name=\"artifact_comment(?:.*?)<div class=\"yui-u\"(?:[^>]*)> <p><!-- google_ad_section_start -->(?<comment>[^!]*)<br /> <br /> <br /> <!-- google_ad_section_end --></p>"; Regex regComment = new Regex(lastCommentPattern, RegexOptions.Singleline); if (regComment.IsMatch(page)) { MatchCollection mComments = regComment.Matches(page); GroupCollection comments = mComments[0].Groups; entry.commentCount = mComments.Count; entry.lastComment = CleanupBRs(comments["comment"].Value); } } } } } } catch (Exception) { // Return whatever we were able to parse return(entry); } return(entry); }