Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using Newtonsoft.Json;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Net.Mail;
- using System.Security.Cryptography;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace BlackBeltWatcher
- {
- /// <summary>
- /// this is a super stripped down object that represents a discord message
- /// that is used with the webhook API
- /// </summary>
- class WebHookMessage
- {
- public string username { get; set; }
- public string content { get; set; }
- }
- class Program
- {
- /// <summary>
- /// used for calculating the hash of the website to monitor....
- /// </summary>
- static SHA256 shaHash;
- /// <summary>
- /// static counter to track how many updates are detected
- /// </summary>
- static int changesDetected = 0;
- /// <summary>
- /// the Discord webhook url to send message notifications to
- /// </summary>
- static string webHook = null;
- /// <summary>
- /// Generate the message to post into my private discord channel using the Site Update Bot user...
- /// </summary>
- /// <param name="content"></param>
- /// <returns></returns>
- static byte[] GenerateDiscordMessage(string content)
- {
- WebHookMessage msg = new WebHookMessage
- {
- username = "Site Update Bot",
- content = content
- };
- string body = JsonConvert.SerializeObject(msg);
- byte[] data = Encoding.ASCII.GetBytes(body);
- return data;
- }
- /// <summary>
- /// wrapper function for the message to use when this detects a page update
- /// </summary>
- /// <param name="url"></param>
- /// <param name="changeCount"></param>
- /// <returns></returns>
- static byte[] GenerateDiscordMessage(string url, int changeCount)
- {
- return GenerateDiscordMessage(string.Format("Page Update [changes:{0}]: {1}", changeCount, url));
- }
- /// <summary>
- /// thank god for the webhooks API...there is a different API
- /// for discord that I
- /// </summary>
- /// <param name="data"></param>
- /// <returns></returns>
- static HttpStatusCode SendDiscordMessage(byte[] data)
- {
- WebRequest request = WebRequest.Create(webHook);
- request.Method = "POST";
- request.ContentType = "application/json";
- request.ContentLength = data.Length;
- Stream stream = request.GetRequestStream();
- stream.Write(data, 0, data.Length);
- stream.Close();
- HttpWebResponse response = request.GetResponse() as HttpWebResponse;
- stream = response.GetResponseStream();
- StreamReader sr = new StreamReader(stream);
- string result = sr.ReadToEnd();
- Console.WriteLine(result);
- sr.Close();
- stream.Close();
- return response.StatusCode;
- }
- static void GeneralDiscordAlert(string msg)
- {
- byte[] data = GenerateDiscordMessage(msg);
- SendDiscordMessage(data);
- }
- static void DiscordAlert(string url, int changeCount)
- {
- byte[] data = GenerateDiscordMessage(url,changeCount);
- SendDiscordMessage(data);
- }
- static string ComputeHash(byte[] body)
- {
- byte[] hash = shaHash.ComputeHash(body);
- return BitConverter.ToString(hash).Replace("-", "");
- }
- /// <summary>
- /// Look for any of the strings in the blacklist entries
- /// if they are not found, we know the page has been updated...
- /// </summary>
- /// <param name="rawBody"></param>
- /// <param name="blacklistEntries"></param>
- /// <returns></returns>
- static bool HasUpdatedBlackListCheck(byte[] rawBody, List<string> blacklistEntries)
- {
- string body = Encoding.ASCII.GetString(rawBody);
- foreach(string entry in blacklistEntries)
- {
- if (!body.Contains(entry))
- {
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// Simple webrequest wrapper that makes a GET request to the endPoint returns
- /// the server response, and outputs the body of the response back as as a byte array....
- /// </summary>
- /// <param name="endPoint"></param>
- /// <param name="responseBody"></param>
- /// <returns></returns>
- static HttpStatusCode FetchSite(string endPoint, out byte[] responseBody)
- {
- WebRequest r = WebRequest.Create(endPoint);
- HttpWebResponse response = r.GetResponse() as HttpWebResponse;
- MemoryStream ms = new MemoryStream();
- Stream s = response.GetResponseStream();
- s.CopyTo(ms);
- responseBody = ms.ToArray();
- s.Close();
- response.Close();
- return response.StatusCode;
- }
- /// <summary>
- /// Here is where the magic happens for monitoring the page
- /// </summary>
- /// <param name="endPoint">the endpoint to monitor</param>
- /// <param name="blEntries">entries that should not appear on the updated webpage </param>
- /// <param name="intervalSec">how often to check the website for updated</param>
- static void WatchEndPoint(string endPoint,List<string> blEntries,int intervalSec)
- {
- string currentHash = string.Empty;
- bool firstCheck = true;
- byte[] rawBody = null;
- while (true) {
- HttpStatusCode responseCode = FetchSite(endPoint, out rawBody);
- // checking the http response because I <did> get some 500 error codes here
- if (responseCode == HttpStatusCode.OK)
- {
- string hash = ComputeHash(rawBody);
- // if this is the first time checking the site
- // use this to preload the hash
- if (firstCheck)
- {
- Console.WriteLine("First Check");
- GeneralDiscordAlert("Starting Check");
- firstCheck = false;
- currentHash = hash;
- continue;
- }
- // Not sure why I was getting false positives with the hash check
- // earlier....the black list check should help mitigate this for now
- // as well as the response check
- //
- if (!currentHash.Equals(hash) && HasUpdatedBlackListCheck(rawBody, blEntries))
- {
- // ok so the hash of the site content is different && we have some missing names
- //
- ++changesDetected;
- DiscordAlert(endPoint, changesDetected);
- Console.WriteLine("Changes:{0} (Check The Site)", changesDetected);
- //update the original
- currentHash = hash;
- }
- else
- {
- Console.WriteLine("Changes:{0} Not Yet...", changesDetected);
- }
- }
- else
- {
- Console.Error.WriteLine("Status Back: {0}", responseCode);
- }
- // goto sleep until we do a new check
- Thread.Sleep(intervalSec * 1000);
- }
- }
- /// <summary>
- /// TODO: endpoint, make the data values used here config/args driven....
- /// </summary>
- /// <param name="args"></param>
- static void Main(string[] args)
- {
- shaHash = SHA256.Create();
- webHook="https://discordapp.com/api/webhooks/<redacted>/<redacted";
- string endPoint = "http://www.<redacted>.com/page/black-belt-exam";
- // Names of folks I know have not tested...but are showing on the current page
- //
- // This specific check <will> fail once the page itself gets cleared....
- // (and YES this check will fail once the page itself gets cleared)....
- List<string> blEntries = new List<string>();
- blEntries.Add("<redacted>");
- blEntries.Add("<redacted>");
- WatchEndPoint(endPoint, blEntries, 30);
- }
- }
- }
Add Comment
Please, Sign In to add comment