Example #1
0
        public static void LogOrUpdateSpreadsheet(ApprovalRequest approvalRequest)
        {
            if (string.IsNullOrEmpty(spreadsheetHistoryURL))
            {
                return;
            }

            string        locationString = Regex.Replace(BotReply.GetLocationString(approvalRequest.SearchResult.FilteredResult, approvalRequest.SearchResult.RelatedLocation), @"\[|\]\(.*?\)", "").Replace("Located in ", "").Replace("\n", "");
            List <string> parameters     = new List <string>
            {
                $"reason={(string.IsNullOrEmpty(approvalRequest.SearchResult.UnconfidentReason) ? "" : Uri.EscapeDataString(approvalRequest.SearchResult.UnconfidentReason))}",
                $"postTitle={Uri.EscapeDataString(WebUtility.HtmlDecode(approvalRequest.RedditPost.Title))}",
                $"postURL={Uri.EscapeDataString(approvalRequest.RedditPost.Shortlink)}",
                $"mpResultTitle={Uri.EscapeDataString(approvalRequest.SearchResult.FilteredResult.Name)}",
                $"mpResultLocation={Uri.EscapeDataString(locationString)}",
                $"mpResultURL={Uri.EscapeDataString(approvalRequest.SearchResult.FilteredResult.URL)}",
                $"mpResultID={Uri.EscapeDataString(approvalRequest.SearchResult.FilteredResult.ID)}",
            };

            if (approvalRequest.SearchResult.FilteredResult is Route route)
            {
                parameters.Add($"mpResultGrade={Uri.EscapeDataString(route.GetRouteGrade(Grade.GradeSystem.YDS).ToString(false))}");
            }

            if (approvalRequest.SearchResult.Confidence == 1 || approvalRequest.IsApproved)
            {
                parameters.Add("alreadyApproved=true");
            }

            DoPOST(spreadsheetHistoryURL, parameters);
        }
Example #2
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>"));
        }
Example #3
0
        private static string GetApproval(Dictionary <string, string> parameters, ApprovalRequest approvalRequest)
        {
            string result = "";

            if (parameters.ContainsKey("approveother"))
            {
                if (parameters.ContainsKey("option"))
                {
                    foreach (string approvedId in parameters["option"].Split(','))
                    {
                        MPObject matchingOption = approvalRequest.SearchResult.AllResults.Find(p => p.ID == approvedId) ?? MountainProjectDataSearch.GetItemWithMatchingID(approvedId);
                        if (matchingOption == null)
                        {
                            result += $"Option '{approvedId}' not found<br>";
                        }
                        else
                        {
                            approvalRequest.ApprovedResults.Add(matchingOption);
                        }
                    }
                }
                else
                {
                    return(ShowApproveOtherPicker(parameters, approvalRequest));
                }
            }
            else if (parameters.ContainsKey("approve"))
            {
                approvalRequest.ApprovedResults = new List <MPObject> {
                    approvalRequest.SearchResult.FilteredResult
                };
                approvalRequest.RelatedLocation = approvalRequest.SearchResult.RelatedLocation;
            }
            else if (parameters.ContainsKey("approveall"))
            {
                approvalRequest.ApprovedResults = approvalRequest.SearchResult.AllResults;
                approvalRequest.RelatedLocation = approvalRequest.SearchResult.RelatedLocation;
            }

            if (approvalRequest.IsApproved)
            {
                BotFunctions.PostsPendingApproval[parameters["postid"]] = approvalRequest;
                result = $"Approved:<br>{string.Join("<br>", approvalRequest.ApprovedResults.Select(r => $"&#8226; {r.Name} ({r.ID})"))}"; //Print out approved results as a bulleted list
            }

            return(WrapHtml($"<h1>{result}</h1>"));
        }
Example #4
0
        public static void RequestApproval(ApprovalRequest approvalRequest)
        {
            if (string.IsNullOrEmpty(requestForApprovalURL) || string.IsNullOrEmpty(WebServerURL))
            {
                return;
            }

            Post         post         = approvalRequest.RedditPost;
            SearchResult searchResult = approvalRequest.SearchResult;

            string messageText = "--------------------------------\n" +
                                 $"**Possible AutoReply found:**\n" +
                                 $"{searchResult.UnconfidentReason}\n\n" +
                                 $"**PostTitle:** {post.Title}\n" +
                                 $"**PostURL:** <{post.Shortlink}>\n\n";

            if (searchResult.AllResults.Count > 1)
            {
                messageText += $"**All results found:**\n";
                foreach (MPObject result in searchResult.AllResults /*Todo: Make sure this is ordered by the likely response*/)
                {
                    messageText += $"\t- [{result.Name} ({(result as Route).GetRouteGrade(Grade.GradeSystem.YDS).ToString(false)})](<{result.URL}>)\n";
                }

                messageText += "\n" +
                               $"**Filtered Result:** [{searchResult.FilteredResult.Name} ({(searchResult.FilteredResult as Route).GetRouteGrade(Grade.GradeSystem.YDS).ToString(false)})](<{searchResult.FilteredResult.URL}>)\n" +
                               $"{Regex.Replace(BotReply.GetLocationString(searchResult.FilteredResult, searchResult.RelatedLocation), @"\[|\]\(.*?\)", "").Replace("Located in ", "").Replace("\n", "")}\n\n" +
                               $"[[APPROVE FILTERED]](<{ApprovalServerUrl}?approve&postid={post.Id}>)  " +
                               $"[[APPROVE ALL]](<{ApprovalServerUrl}?approveall&postid={post.Id}>)  " +
                               $"[[APPROVE OTHER]](<{ApprovalServerUrl}?approveother&postid={post.Id}>)";
            }
            else
            {
                messageText += $"**MPResult:** {searchResult.FilteredResult.Name} ({(searchResult.FilteredResult as Route).GetRouteGrade(Grade.GradeSystem.YDS).ToString(false)})\n" +
                               $"{Regex.Replace(BotReply.GetLocationString(searchResult.FilteredResult, searchResult.RelatedLocation), @"\[|\]\(.*?\)", "").Replace("Located in ", "").Replace("\n", "")}\n" +
                               $"<{searchResult.FilteredResult.URL}>\n\n" +
                               $"[[APPROVE]](<{ApprovalServerUrl}?approve&postid={post.Id}>)  " +
                               $"[[APPROVE OTHER]](<{ApprovalServerUrl}?approveother&postid={post.Id}>)";
            }

            messageText += "\n--------------------------------";

            SendDiscordMessage(messageText);
        }
Example #5
0
        private static string ShowApproveOtherPicker(Dictionary <string, string> parameters, ApprovalRequest approvalRequest)
        {
            string htmlPicker = "<form>";

            foreach (MPObject option in approvalRequest.SearchResult.AllResults)
            {
                htmlPicker += $"<input type=\"radio\" name=\"options\" value=\"{option.ID}\"{(approvalRequest.SearchResult.AllResults.IndexOf(option) == 0 ? " checked=\"true\"" : "")}>" +
                              $"<a href=\"{option.URL}\">{option.Name} ({(option as Route).GetRouteGrade(Grade.GradeSystem.YDS).ToString(false)})</a>" +
                              $" ({Regex.Replace(BotReply.GetLocationString(option, approvalRequest.SearchResult.RelatedLocation), @"\[|\]\(.*?\)", "").Replace("\n", "")})<br>";
            }

            htmlPicker += "<input type=\"radio\" name=\"options\" id=\"other_option\">Other: <input type=\"text\" id=\"other_option_value\" size=\"100\">&nbsp;(separate multiple urls with semicolons)" +
                          "<br><input type=\"button\" onclick=\"choose()\" value=\"Choose\"></form><script>" +
                          "function choose(){" +
                          "  var options = document.forms[0];" +
                          "  for (var i = 0; i < options.length; i++){" +
                          "    if (options[i].checked){" +
                          "      var chosen = options[i].id != \"other_option\" ? options[i].value : document.getElementById(\"other_option_value\").value.match(/(?<=\\/)\\d+(?=\\/)/g);" +
                          $"     window.location.replace(\"{BotUtilities.ApprovalServerUrl}?approveother&postid={parameters["postid"]}{(parameters.ContainsKey("force") ? "&force" : "")}&option=\" + chosen);" +
                          "      break;" +
                          "    }" +
                          "  }" +
                          "}" +
                          "</script>";

            return(WrapHtml(htmlPicker));
        }
Example #6
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}");
                }
            }
        }