public void DeUrl_NoneWithBBCode() { string content = "『i』Vote『/i』 for stuff"; string clean = "『i』Vote『/i』 for stuff"; Assert.AreEqual(clean, VoteString.DeUrlContent(content)); }
/// <summary> /// Adds an individual vote. /// </summary> /// <param name="vote">The vote that is being added to.</param> /// <param name="voter">The voter that is supporting the vote.</param> /// <param name="voteType">Type of the vote.</param> /// <exception cref="System.ArgumentNullException">vote and voter must not be null or empty.</exception> private void AddVote(string vote, string voter, VoteType voteType) { if (string.IsNullOrEmpty(vote)) { throw new ArgumentNullException(nameof(vote)); } if (string.IsNullOrEmpty(voter)) { throw new ArgumentNullException(nameof(voter)); } string voteKey = GetVoteKey(vote, voteType); var votes = GetVotesCollection(voteType); // Make sure there's a hashset for the voter list available for the vote key. if (votes.ContainsKey(voteKey) == false) { votes[voteKey] = new HashSet <string>(StringComparer.OrdinalIgnoreCase); OnPropertyChanged("Votes"); } string cleanVoter = VoteString.RemoveBBCode(voter); cleanVoter = VoteString.DeUrlContent(cleanVoter); // Update the supporters list if the voter isn't already in it. if (votes[voteKey].Contains(cleanVoter)) { return; } votes[voteKey].Add(cleanVoter); OnPropertyChanged("Voters"); }
/// <summary> /// Attempt to find any existing vote that matches with the vote we have, /// and can be used as a key in the VotesWithSupporters table. /// </summary> /// <param name="vote">The vote to search for.</param> /// <returns>Returns the string that can be used as a key in the VotesWithSupporters table.</returns> private string GetVoteKey(string vote, VoteType voteType) { // Store a lookup of the cleaned version of the vote so we don't have to repeat the processing. if (!cleanedKeys.TryGetValue(vote, out string cleaned)) { cleaned = VoteString.RemoveBBCode(vote); cleaned = VoteString.DeUrlContent(cleaned); cleanedKeys[vote] = cleaned; } var votes = GetVotesCollection(voteType); // If the vote already matches an existing key, we don't need to search again. if (votes.ContainsKey(vote)) { return(vote); } // Find any vote that matches using an agnostic string comparison, that ignores // case, spacing, and most punctuation. string agVote = votes.Keys.FirstOrDefault(k => Agnostic.StringComparer.Equals(cleaned, cleanedKeys[k])); // If we found a match, return that; otherwise this is a new vote, so return it unchanged. return(agVote ?? vote); }
public void DeUrl_Empty() { string content = ""; string clean = ""; Assert.AreEqual(clean, VoteString.DeUrlContent(content)); }
public void DeUrl_None() { string content = "Vote for stuff"; string clean = "Vote for stuff"; Assert.AreEqual(clean, VoteString.DeUrlContent(content)); }
public void DeUrl_Link() { string content = "Vote for [url=http://google.com/myhome.html]me[/url]!"; string clean = "Vote for me!"; Assert.AreEqual(clean, VoteString.DeUrlContent(content)); }
public void DeUrl_Image() { string content = "[url=http://google.com/image/1.jpg]<Image>[/url]"; string clean = "<Image>"; Assert.AreEqual(clean, VoteString.DeUrlContent(content)); }
public void DeUrl_AtUrl() { string content = "[url=https://forum.questionablequesting.com/members/2392/]@Xryuran[/url]"; string clean = "Xryuran"; Assert.AreEqual(clean, VoteString.DeUrlContent(content)); }
/// <summary> /// Cleans the provided content string of problematic components that would /// make comparing two strings difficult, by removing excess BBCode. /// </summary> /// <param name="content">The content.</param> /// <returns>Returns vote content suitable for comparison.</returns> private string GetComparableContent(string content) { string clean = VoteString.RemoveBBCode(content); clean = VoteString.DeUrlContent(clean); return(clean); }
/// <summary> /// Adds the voter post identifier. /// </summary> /// <param name="voter">The voter.</param> /// <param name="postID">The post identifier.</param> /// <param name="voteType">Type of the vote.</param> /// <exception cref="System.ArgumentNullException">voter and postID may not be null or empty.</exception> private void AddVoterPostID(string voter, string postID, VoteType voteType) { if (string.IsNullOrEmpty(voter)) { throw new ArgumentNullException(nameof(voter)); } if (string.IsNullOrEmpty(postID)) { throw new ArgumentNullException(nameof(postID)); } string cleanVoter = VoteString.RemoveBBCode(voter); cleanVoter = VoteString.DeUrlContent(cleanVoter); // Store/update the post ID of the voter var voters = GetVotersCollection(voteType); voters[cleanVoter] = postID; }
/// <summary> /// Find all votes tied to a given vote line. /// The "plan name" (possibly user name) is checked with the /// standard and alternate extractions (adding a special marker character /// depending on whether the word "plan" is used, and whether it's /// standard or alt) in order to look up votes that said (possible) voter /// supports. /// </summary> /// <param name="voteLine">The vote line to be checked.</param> /// <param name="author">The author of the vote. Prevent circular references.</param> /// <returns>Returns a list of all votes supported by the user or plan /// specified in the vote line, if found. Otherwise returns an /// empty list.</returns> public List <string> GetVotesFromReference(string voteLine, string author) { if (voteLine == null) { throw new ArgumentNullException(nameof(voteLine)); } if (author == null) { throw new ArgumentNullException(nameof(author)); } List <string> results = new List <string>(); var referenceNames = VoteString.GetVoteReferenceNames(voteLine); if (!referenceNames[ReferenceType.Any].Any()) { return(results); } string proxyName = null; if (referenceNames[ReferenceType.Label].Any()) { // If there is a "plan" prefix, then if it's a user reference, // check for a ◈plan before checking for the user's base vote. // If the reference exists as a plan, use it. if (referenceNames[ReferenceType.Plan].Any() && HasPlan(referenceNames[ReferenceType.Plan].First())) { // If this is not a user name, get the plan name as the proxy reference. proxyName = PlanNames.First(p => referenceNames[ReferenceType.Plan] .Contains(VoteString.DeUrlContent(VoteString.RemoveBBCode(p)), Agnostic.StringComparer)); } else if (ReferenceVoters.Contains(referenceNames[ReferenceType.Voter].First(), Agnostic.StringComparer)) { // If it doesn't exist as a plan, then we can check for users. if (!AdvancedOptions.Instance.DisableProxyVotes) { proxyName = ReferenceVoters.First(n => referenceNames[ReferenceType.Voter].Contains(n, Agnostic.StringComparer)); if (proxyName == author) { proxyName = null; } } } } else { // If there is no "plan" prefix, and if the plan name is a user // reference, it may only refer to that user's vote as a whole. // If this matches a user name, get that user name as the proxy reference. if (ReferenceVoters.Contains(referenceNames[ReferenceType.Voter].First(), Agnostic.StringComparer)) { if (!AdvancedOptions.Instance.DisableProxyVotes) { proxyName = ReferenceVoters.First(n => referenceNames[ReferenceType.Voter].Contains(n, Agnostic.StringComparer)); if (proxyName == author) { proxyName = null; } } } else if (referenceNames[ReferenceType.Plan].Any() && HasPlan(referenceNames[ReferenceType.Plan].First())) { // If this is not a user name, get the plan name as the proxy reference. proxyName = PlanNames.First(p => referenceNames[ReferenceType.Plan].Contains(p, Agnostic.StringComparer)); } } if (!string.IsNullOrEmpty(proxyName)) { var planVotes = VotesWithSupporters.Where(v => v.Value.Contains(proxyName)); results.AddRange(planVotes.Select(v => v.Key)); } return(results); }
/// <summary> /// Find all votes tied to a given vote line. /// The "plan name" (possibly user name) is checked with the /// standard and alternate extractions (adding a special marker character /// depending on whether the word "plan" is used, and whether it's /// standard or alt) in order to look up votes that said (possible) voter /// supports. /// </summary> /// <param name="voteLine">The vote line to be checked.</param> /// <param name="author">The author of the vote. Prevent circular references.</param> /// <returns>Returns a list of all votes supported by the user or plan /// specified in the vote line, if found. Otherwise returns an /// empty list.</returns> public List <string> GetVotesFromReference(string voteLine, string author) { if (voteLine == null) { throw new ArgumentNullException(nameof(voteLine)); } if (author == null) { throw new ArgumentNullException(nameof(author)); } List <string> results = new List <string>(); var referenceNames = VoteString.GetVoteReferenceNames(voteLine); if (!referenceNames[ReferenceType.Any].Any()) { return(results); } string proxyName = null; // Label ^ or 'pin' means it must be a user reference. // Label 'plan' means it might be user or plan reference. if (referenceNames[ReferenceType.Label].Contains("plan")) { // If it's labeled as a 'plan', check plans first, then users. // If the reference exists as a plan, use it. if (referenceNames[ReferenceType.Plan].Any() && HasPlan(referenceNames[ReferenceType.Plan].First())) { // Get the plan name from the recorded plan names collection. proxyName = PlanNames.First(p => referenceNames[ReferenceType.Plan] .Contains(VoteString.DeUrlContent(VoteString.RemoveBBCode(p)), Agnostic.StringComparer)); } // If it doesn't exist as a plan, then we can check for users, as long as the quest hasn't disabled proxy votes. else if (!Quest.DisableProxyVotes && ReferenceVoters.Contains(referenceNames[ReferenceType.Voter].First(), Agnostic.InsensitiveComparer)) { proxyName = ReferenceVoters.First(n => referenceNames[ReferenceType.Voter].Contains(n, Agnostic.InsensitiveComparer)); // But don't allow self-references. Some user names conflict with normal vote lines. if (proxyName == author) { proxyName = null; } } } else { // If it's not labeled as a 'plan', then it's either a pin or an unlabeled reference. // Either way, check for users first. // See if any voter names match the line (as long as we're allowing proxy votes). If so, use that. if (!Quest.DisableProxyVotes && ReferenceVoters.Contains(referenceNames[ReferenceType.Voter].First(), Agnostic.InsensitiveComparer)) { proxyName = ReferenceVoters.First(n => referenceNames[ReferenceType.Voter].Contains(n, Agnostic.InsensitiveComparer)); // And make sure it's not the user using their own name. Some user names conflict with normal vote lines. if (proxyName == author) { proxyName = null; } } // If a user isn't found, only check for regular plans if there's not a non-plan label being used, // but not if the quest requires plan vote lines to be labeled. else if (!Quest.ForcePlanReferencesToBeLabeled && !referenceNames[ReferenceType.Label].Any()) { if (referenceNames[ReferenceType.Plan].Any() && HasPlan(referenceNames[ReferenceType.Plan].First())) { // Get the plan name from the recorded plan names collection. proxyName = PlanNames.First(p => referenceNames[ReferenceType.Plan] .Contains(VoteString.DeUrlContent(VoteString.RemoveBBCode(p)), Agnostic.StringComparer)); } } } if (!string.IsNullOrEmpty(proxyName)) { var planVotes = VotesWithSupporters.Where(v => v.Value.Contains(proxyName)); if (planVotes.Count() > 1) { planVotes = VotesWithSupporters.Where(v => v.Value.Contains(proxyName, Agnostic.StringComparer)); } results.AddRange(planVotes.Select(v => v.Key)); } return(results); }