예제 #1
0
        public static string HandleRequest(ServerRequest request)
        {
            if (request.RequestMethod == HttpMethod.Get && !request.IsFaviconRequest && !request.IsDefaultPageRequest)
            {
                Dictionary <string, string> parameters = request.GetParameters();
                if (parameters.ContainsKey("status")) //UpTimeRobot will ping this
                {
                    return("UP");
                }
                else if (parameters.ContainsKey("posthistory"))
                {
                    string query = parameters.ContainsKey("query") ? parameters["query"] : "";
                    int    page  = parameters.ContainsKey("page") ? Convert.ToInt32(parameters["page"]) : 1;
                    return(ShowPostHistory(query, page));
                }
                else if (parameters.ContainsKey("postid") && (parameters.ContainsKey("approve") || parameters.ContainsKey("approveall") || parameters.ContainsKey("approveother")))
                {
                    if (BotFunctions.PostsPendingApproval.ContainsKey(parameters["postid"]))
                    {
                        ApprovalRequest approvalRequest = BotFunctions.PostsPendingApproval[parameters["postid"]];

                        return(GetApproval(parameters, approvalRequest));
                    }
                    else if (parameters.ContainsKey("force"))
                    {
                        //Because the ApprovalRequest & SearchResult have been disposed by now, we need to recreate them. Maybe we can do this in a better way in the future
                        Post         post         = BotFunctions.RedditHelper.GetPost(parameters["postid"]).Result;
                        SearchResult searchResult = MountainProjectDataSearch.ParseRouteFromString(post.Title);
                        return(GetApproval(parameters, new ApprovalRequest {
                            Force = true, RedditPost = post, SearchResult = searchResult
                        }));
                    }
                    else
                    {
                        return(WrapHtml($"<h1>Post '{parameters["postid"]}' expired</h1>" +
                                        $"<br>" +
                                        $"<br>" +
                                        $"<input type=\"button\" onclick=\"force()\" value=\"Force\">" +
                                        $"<script>" +
                                        $"  function force(){{" +
                                        $"    window.location.replace(\"{BotUtilities.ApprovalServerUrl}?{string.Join("&", parameters.Select(p => $"{p.Key}={p.Value}").Concat(new[] { "force" }))}\");" +
                                        $"}}" +
                                        $"</script>"));
                    }
                }
            }

            return(WrapHtml($"<h1>Path '{request.Path}' not understood</h1>"));
        }
예제 #2
0
        public void TestPostTitleParse(/*bool outputExtraInfo, bool isGoogleSheetsTest*/)
        {
            bool outputExtraInfo    = false;
            bool isGoogleSheetsTest = false;

            Stopwatch totalStopwatch = Stopwatch.StartNew();

            int           totalPasses                 = 0;
            int           totalFailures               = 0;
            int           yessesWithConfidence1       = 0;
            List <string> failingPostsWithConfidence1 = new List <string>();

            StringWriter writer = new StringWriter();

            Console.SetOut(writer);
            MountainProjectDataSearch.OutputExtraInfo = outputExtraInfo;

            InitMPData();
            string[] testCriteria;
            if (isGoogleSheetsTest)
            {
                string requestUrl = BotUtilities.GetCredentialValue(@"..\..\MountainProjectBot\Credentials.txt", "spreadsheetURL") + "PostHistory";
                testCriteria = Utilities.GetHtml(requestUrl).Split('\n');
            }
            else
            {
                testCriteria = File.ReadAllLines(@"..\PostTitleTest.txt");
            }

            for (int i = 0; i < testCriteria.Length; i++)
            {
                Stopwatch routeStopwatch = Stopwatch.StartNew();

                string[] lineParts = testCriteria[i].Split('\t');

                string inputPostTitle, expectedMPLink, comment;
                if (isGoogleSheetsTest)
                {
                    inputPostTitle = lineParts[2];
                    expectedMPLink = lineParts[9].ToUpper() == "YES" ? Utilities.GetSimpleURL(lineParts[7]) : !string.IsNullOrEmpty(lineParts[10]) ? $"{Utilities.MPROUTEURL}/{lineParts[10]}" : null;
                    comment        = lineParts.Length > 11 && !string.IsNullOrEmpty(lineParts[11]) ? $"//{lineParts[11]}" : null;
                }
                else
                {
                    inputPostTitle = lineParts[0];
                    expectedMPLink = lineParts[1] == "null" ? null : Utilities.GetSimpleURL(lineParts[1]);
                    comment        = lineParts.Length > 2 && !string.IsNullOrEmpty(lineParts[2]) ? $"//{lineParts[2]}" : null;
                }

                //Override input title (uncomment only for debugging)
                //inputPostTitle = "Happy Star Wars Day! Had to practice my mental game for this one: \"Jedi Mind Tricks\" (v4). One of the Best.";

                writer.WriteLine($"POST TITLE: {inputPostTitle}");

                SearchResult result = MountainProjectDataSearch.ParseRouteFromString(WebUtility.HtmlDecode(inputPostTitle));
                Route        route  = result.FilteredResult as Route;

                if (expectedMPLink == null)
                {
                    if (route == null)
                    {
                        writer.WriteLine($"PASS (Correctly guessed no match)");
                        totalPasses++;
                    }
                    else
                    {
                        writer.WriteLine($"FAILED (confidence {result.Confidence}). EXPECTED: , ACTUAL: {route?.URL} {comment}");
                        totalFailures++;

                        if (result.Confidence == 1)
                        {
                            failingPostsWithConfidence1.Add($"{inputPostTitle} {comment}");
                        }
                    }
                }
                else
                {
                    if (route == null || route.URL != expectedMPLink)
                    {
                        writer.WriteLine($"FAILED (confidence {result.Confidence}). EXPECTED: {expectedMPLink} , ACTUAL: {route?.URL} {comment}");
                        totalFailures++;

                        if (result.Confidence == 1)
                        {
                            failingPostsWithConfidence1.Add($"{inputPostTitle} {comment}");
                        }
                    }
                    else
                    {
                        writer.WriteLine($"PASS (confidence: {result.Confidence})");
                        totalPasses++;

                        if (isGoogleSheetsTest && result.Confidence == 1)
                        {
                            yessesWithConfidence1++;
                        }
                    }
                }

                if (outputExtraInfo)
                {
                    writer.WriteLine($"Time taken: {routeStopwatch.Elapsed}");
                }
            }

            if (outputExtraInfo)
            {
                Debug.WriteLine($"Test completed in {totalStopwatch.Elapsed}\n");
            }

            if (!isGoogleSheetsTest)
            {
                Debug.WriteLine($"Passes: {totalPasses}, Failures: {totalFailures}, Pass percentage: {Math.Round((double)totalPasses / (totalPasses + totalFailures) * 100, 2)}%\n");
            }
            else
            {
                Debug.WriteLine($"Yesses that now have confidence 1: {yessesWithConfidence1} (out of {testCriteria.Count(p => p.Split('\t')[9].ToUpper() == "YES")} total yesses)\n");
                Debug.WriteLine($"Passes: {totalPasses}, Failures: {totalFailures}\n");
            }

            if (failingPostsWithConfidence1.Any())
            {
                Debug.WriteLine($"Failing posts with confidence 1 ({failingPostsWithConfidence1.Count()}):\n\n{string.Join("\n", failingPostsWithConfidence1)}\n");
            }

            Debug.WriteLine(writer.ToString());
            writer.Dispose();

            Assert.IsTrue(failingPostsWithConfidence1.Count == 0, "Some failed matches have a confidence of 1");

            if (!isGoogleSheetsTest) //Todo: may want to rework how the spreadsheet is setup so that this line is also relevant for GoogleSheetsTest
            {
                Assert.IsTrue((double)totalPasses / (totalPasses + totalFailures) > 0.95);
            }
        }
예제 #3
0
        public static async Task CheckPostsForAutoReply(List <Subreddit> subreddits)
        {
            List <Post> recentPosts = new List <Post>();

            foreach (Subreddit subreddit in subreddits)
            {
                List <Post> subredditPosts = await RedditHelper.GetPosts(subreddit, 10);

                subredditPosts = BotUtilities.RemoveAlreadySeenPosts(subredditPosts);
                subredditPosts = BotUtilities.RemoveBlacklisted(subredditPosts, new[] { BlacklistLevel.NoPostReplies, BlacklistLevel.OnlyKeywordReplies, BlacklistLevel.Total }); //Remove posts from users who don't want the bot to automatically reply to them

                foreach (Post post in subredditPosts.ToList())
                {
                    if (post.IsSelfPost)
                    {
                        subredditPosts.Remove(post);
                        ConsoleHelper.Write($"\tSkipping {post.Id} (self-post)", ConsoleColor.Red);
                        BotUtilities.LogPostBeenSeen(post, "self-post");
                    }

                    double ageInMin = (DateTime.UtcNow - post.CreatedUTC).TotalMinutes;
                    if (ageInMin > 30)
                    {
                        subredditPosts.Remove(post);
                        ConsoleHelper.Write($"\tSkipping {post.Id} (too old: {Math.Round(ageInMin, 2)} min)", ConsoleColor.Red);
                        BotUtilities.LogPostBeenSeen(post, $"too old ({Math.Round(ageInMin, 2)} min)");
                    }
                }

                recentPosts.AddRange(subredditPosts);
            }

            foreach (Post post in recentPosts)
            {
                try
                {
                    string postTitle = WebUtility.HtmlDecode(post.Title);

                    Console.WriteLine($"\tTrying to get an automatic reply for post (/r/{post.SubredditName}): {postTitle}");

                    SearchResult searchResult = MountainProjectDataSearch.ParseRouteFromString(postTitle);
                    if (!searchResult.IsEmpty())
                    {
                        ApprovalRequest approvalRequest = new ApprovalRequest
                        {
                            RedditPost   = post,
                            SearchResult = searchResult
                        };

                        PostsPendingApproval.TryAdd(post.Id, approvalRequest);

                        BotUtilities.LogPostBeenSeen(post, searchResult.Confidence == 1 ? "auto-replying" : "pending approval");

                        if (!DryRun)
                        {
                            if (searchResult.Confidence == 1)
                            {
                                string reply = BotReply.GetFormattedString(searchResult);
                                reply += Markdown.HRule;
                                reply += BotReply.GetBotLinks(post);

                                Comment botReplyComment = await RedditHelper.CommentOnPost(post, reply);

                                monitoredComments.Add(new CommentMonitor()
                                {
                                    Parent = post, BotResponseComment = botReplyComment
                                });
                                ConsoleHelper.Write($"\n\tAuto-replied to post {post.Id}", ConsoleColor.Green);
                            }
                            else
                            {
                                //Until we are more confident with automatic results, we're going to request for approval for confidence values greater than 1 (less than 100%)
                                ConsoleHelper.Write($"\tRequesting approval for post {post.Id}", ConsoleColor.Yellow);
                                BotUtilities.RequestApproval(approvalRequest);
                            }

                            BotUtilities.LogOrUpdateSpreadsheet(approvalRequest);
                        }
                    }
                    else
                    {
                        Console.WriteLine("\tNothing found");
                        BotUtilities.LogPostBeenSeen(post, "nothing found");
                    }
                }
                catch (RateLimitException)
                {
                    Console.WriteLine("\tRate limit hit. Postponing reply until next iteration");
                }
                catch (Exception e)
                {
                    Console.WriteLine($"\tException occurred with post {RedditHelper.GetFullLink(post.Permalink)}");
                    Console.WriteLine($"\t{e.Message}\n{e.StackTrace}");
                }
            }
        }