using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text; using System.Text.RegularExpressions; using System.Globalization; using System.Reflection; namespace bdf { public class MegaT { // SIP Extractions section // A class to hold the extracted data for a single row of SIP INSIS data public class SIPData { public string Item { get; set; } public string Code { get; set; } public string Description { get; set; } public string Period { get; set; } public string UnitPrice { get; set; } public string Quantity { get; set; } public string Amount { get; set; } public string BillingType { get; set; } public string Currency { get; set; } public string StartDate { get; set; } public string EndDate { get; set; } public override string ToString() { return $"Code: {Code}, Description: {Description}, Unit Price: {UnitPrice}, Qty: {Quantity}, Amount: {Amount}, Start Date: {StartDate}"; } } public static List GetSIPDetails_bySCHED(string sched, ref CookieContainer cookies) { bool success = false; byte[] webResp = null; List sip_rvnu = new List { }; success = Web.MakeRequest( "GET", "http://megatool.rogers.com/megatool/megatool/INSIS/insisMainwindow.asp?serv_id=" + sched, false, "", ref webResp, ref cookies); if (!success) { Logger.Log(5, "Get SIP INSIS TopLevel Details FAIL {0}", sched); } string html = Encoding.ASCII.GetString(webResp); if (html.Length > 5000) // valid SCHED, seek RVNU items for SIP data { try { Dictionary rvnu = SIP_RVNU_items(html); foreach (var kvp in rvnu) { success = false; webResp = null; success = Web.MakeRequest( "GET", "http://megatool.rogers.com/megatool/megatool/INSIS/" + kvp.Value.ToString(), false, "", ref webResp, ref cookies); if (!success) { Logger.Log(5, "Get INSIS RVNU Details FAIL {0}-{1} {2}", sched, kvp.Key, webResp); } string html2 = Encoding.ASCII.GetString(webResp); SIPData x = ExtractSIPData(html2); sip_rvnu.Add(x); Logger.Log(6, "Desc: {0} sip_rnvu size {1}", x.Description, sip_rvnu.Count); } } catch (Exception e) { Logger.Log(0, "Error SCHED {0} - SIP HTML={0}", sched, e.Message); } } return sip_rvnu; } public static Dictionary SIP_RVNU_items(string html) { Dictionary result = new System.Collections.Generic.Dictionary( System.StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(html)) return result; string trPattern = @"]*id\s*=\s*['""]R\d+['""][^>]*>(.*?)"; System.Text.RegularExpressions.MatchCollection trMatches = System.Text.RegularExpressions.Regex.Matches( html, trPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline ); foreach (System.Text.RegularExpressions.Match trMatch in trMatches) { string trContent = trMatch.Groups[1].Value; System.Text.RegularExpressions.MatchCollection tdMatches = System.Text.RegularExpressions.Regex.Matches( trContent, @"]*>(.*?)", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline ); if (tdMatches.Count < 5) continue; // ----- Extract Service Code (5th ) ----- string serviceCode = System.Text.RegularExpressions.Regex.Replace( tdMatches[4].Groups[1].Value, "<[^>]+>", string.Empty ).Trim(); if (serviceCode.Length == 0) continue; // Skip "Install" rows if (serviceCode.IndexOf("Install", System.StringComparison.OrdinalIgnoreCase) >= 0) { //Console.WriteLine("skipping [{0}]", serviceCode); continue; } // ----- Extract openIt('...') from 4th ----- string fourthTd = tdMatches[3].Groups[1].Value; //Console.WriteLine("4th [{0}]", fourthTd); string openItValue = ""; if (fourthTd.IndexOf("RVNU", System.StringComparison.OrdinalIgnoreCase) >= 0) { System.Text.RegularExpressions.Match onclickMatch = System.Text.RegularExpressions.Regex.Match( fourthTd, @"openIt\('(?[^']+)'\)", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline ); if (!onclickMatch.Success) { //Console.WriteLine("no match"); continue; } openItValue = onclickMatch.Groups["openit"].Value.Trim(); } else // Skip non-RVNU rows { //Console.WriteLine("non-revenue [{0}]", fourthTd); continue; } // Avoid duplicate keys if (!result.ContainsKey(serviceCode)) { result.Add(serviceCode, openItValue); } } return result; } public static SIPData ExtractSIPData(string html) { var extractedData = new SIPData(); // Regex to find table rows () within a specific table structure (adjust if needed, e.g., using a table ID) // The pattern uses capturing groups for each content // It assumes tags might have extra spaces or attributes, but the content inside is the target. Dictionary result = new Dictionary(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(html)) return null; string pattern = @"]*class\s*=\s*""heading""[^>]*>\s*(?[^<]+)\s*[\s\S]*?" + @"value\s*=\s*""(?[^""]*)"""; System.Text.RegularExpressions.MatchCollection matches = System.Text.RegularExpressions.Regex.Matches( html, pattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase); foreach (System.Text.RegularExpressions.Match match in matches) { string heading = match.Groups["heading"].Value.Trim(); string value = match.Groups["value"].Value.Trim().Replace("$","").Replace("/", "-"); // FIXME convert to SSC style date if (!result.ContainsKey(heading)) { result.Add(heading.Replace(" ", ""), value); //Remove field label spaces to make them valid dictionary entries Logger.Log(3, "Found: {0}={1}", heading, value); } } System.Type type = typeof(SIPData); foreach (System.Reflection.PropertyInfo prop in type.GetProperties( System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)) { //Console.WriteLine("a4n {0} : {1}", prop.PropertyType.Name, prop.Name); if (prop.PropertyType != typeof(string)) continue; if (!prop.CanWrite) continue; if (result.TryGetValue(prop.Name, out string value)) { //Console.WriteLine("a5 {0}", value); try { prop.SetValue( extractedData, (string)value); } catch (Exception e) { Logger.Log(0, "Error prop.SetValue {0}:{1}\n{2}", prop.Name, value, e.Message); } } } return extractedData; } public static string ConvertDate(string input) { System.DateTime date = System.DateTime.ParseExact( input, "M-d-yyyy", System.Globalization.CultureInfo.InvariantCulture ); return date.ToString("yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture); } //------------------------------------ /* public static Dictionary ExtractServiceCodesFromTable(string html) { Dictionary result = new Dictionary(); if (string.IsNullOrWhiteSpace(html)) return result; // Match each with id="R", including multi-line content string trPattern = @"]*id\s*=\s*['""]R\d+['""][^>]*>(.*?)"; var trMatches = Regex.Matches( html, trPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline // Singleline allows . to match newlines ); foreach (Match trMatch in trMatches) { string trContent = trMatch.Groups[1].Value; // Match all elements inside the var tdMatches = Regex.Matches( trContent, @"]*>(.*?)", RegexOptions.IgnoreCase | RegexOptions.Singleline ); if (tdMatches.Count >= 4) { string fourthTd = tdMatches[3].Groups[1].Value; // Extract openIt('...') string inside the tag string onclickPattern = @"openIt\('(?[^']+)'\)"; var onclickMatch = Regex.Match(fourthTd, onclickPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline); if (onclickMatch.Success) { string openItValue = onclickMatch.Groups["openit"].Value.Trim(); //result.Add(openItValue); Console.WriteLine("Found {0}", openItValue); } } } return result; } /* // Match each row string rowPattern = @"]*id\s*=\s*['""]R\d+['""][^>]*>(.*?)"; MatchCollection rowMatches = Regex.Matches(html, rowPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline); foreach (Match rowMatch in rowMatches) { string rowContent = rowMatch.Groups[1].Value; Console.WriteLine(" {0}", rowContent); foreach (Match trMatch in rowContent) { string trContent = trMatch.Groups[1].Value; Console.WriteLine(" {0}", trContent); // Match all elements inside the var tdMatches = Regex.Matches( trContent, @"]*>(.*?)", RegexOptions.IgnoreCase | RegexOptions.Singleline ); if (tdMatches.Count >= 4) { string fourthTd = tdMatches[3].Groups[1].Value; // Extract openIt('...') string inside the tag string onclickPattern = @"openIt\('(?[^']+)'\)"; var onclickMatch = Regex.Match(fourthTd, onclickPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline); if (onclickMatch.Success) { string openItValue = onclickMatch.Groups["openit"].Value.Trim(); result.Add(openItValue); } } } // Match followed by with service code string cellPattern = @"]*onclick\s*=\s*['""][^'""]*'(?[^']+)'[^'""]*['""][^>]*>.*?.*?" + @"]*>\s*(?[^<\s][^<]*)\s*"; Match cellMatch = Regex.Match(rowContent, cellPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline); if (cellMatch.Success) { string onclick = cellMatch.Groups["onclick"].Value.Trim(); string code = cellMatch.Groups["code"].Value.Trim(); if (!string.IsNullOrEmpty(code) && !string.IsNullOrEmpty(onclick)) { // Avoid duplicate keys if (!result.ContainsKey(code)) result[code] = onclick; Console.WriteLine("Found {0} : {1}", code, onclick); } } } return result; */ // from Megatool RVNU sub-page, return extracted SIPData item // old public static List ExtractSIPData_RevScreen(string htmlContent) { var extractedData = new List(); // Regex to find table rows () within a specific table structure (adjust if needed, e.g., using a table ID) // The pattern uses capturing groups for each content // It assumes tags might have extra spaces or attributes, but the content inside is the target. string rowPattern = @"]*?\bid=[^>]*?>(.*?)"; //@"]*>(.*?)"; string cellPattern = @"]*>[$]*(.*?)"; // Find all rows in the HTML MatchCollection rows = Regex.Matches(htmlContent, rowPattern, RegexOptions.Singleline | RegexOptions.IgnoreCase); foreach (Match rowMatch in rows) { string rowHtml = rowMatch.Groups[1].Value; // Find all cells in the current row MatchCollection cells = Regex.Matches(rowHtml, cellPattern, RegexOptions.Singleline | RegexOptions.IgnoreCase); // Check if the row has exactly 9 columns of data (Item, Description, Unit Price, Qty, Amount) if (cells.Count >= 9) { // Extract the inner text and clean up whitespace string item = cells[0].Groups[1].Value.Replace(" ", " ").Trim(); string code = cells[1].Groups[1].Value.Replace(" ", " ").Trim(); string description = cells[2].Groups[1].Value.Replace(" ", " ").Trim(); string period = cells[3].Groups[1].Value.Replace(" ", " ").Trim(); string unitPrice = cells[4].Groups[1].Value.Replace(" ", " ").Trim(); string qty = cells[5].Groups[1].Value.Replace(" ", " ").Trim(); string amount = cells[6].Groups[1].Value.Replace(" ", " ").Trim(); string billingType = cells[7].Groups[1].Value.Replace(" ", " ").Trim(); string currency = cells[8].Groups[1].Value.Replace(" ", " ").Trim(); // Add to the list extractedData.Add(new SIPData { Item = item, Code = code, Description = description, Period = period, UnitPrice = unitPrice, Quantity = qty, Amount = amount, BillingType = billingType, Currency = currency }); } } return extractedData; } //old version public static double getSIP_RVNU(string sched, ref CookieContainer cookies) { bool success = false; double mrr = 0; byte[] webResp = null; success = Web.MakeRequest( "GET", "http://megatool.rogers.com/megatool/megatool/INSIS/insisMainwindow.asp?serv_id=" + sched, false, "", ref webResp, ref cookies); if (!success) { Logger.Log(5, "MRR FAIL {0}", sched); } string html = Encoding.ASCII.GetString(webResp); if (html.Length > 5000) { try { Regex word = new Regex(@"]*>[\s\S]*?Total\s+MRR[\s\S]*?\$\s*([0-9]{1,3}(?:,[0-9]{3})*(?:\.[0-9]{2})?)[\s\S]*?<\/tr>"); // find MRR dollar value Match m = word.Match(html); // if (m.Success) { Group g = m.Groups[1]; //Capture c = g.Captures[0]; Logger.Log(6, "Regex Match {0} / Group Count {1} / Captures Count {2} / result={3}", m.Success, m.Groups.Count, m.Captures.Count, g.Value); mrr = Convert.ToDouble(g.Value); if ((mrr >= 0) && (mrr <= 999999)) Logger.Log(5, "MRR found successfully {0}", mrr); } else { Logger.Log(1, "No MRR found."); } } catch (Exception e) { Logger.Log(0, "Error parsing MRR {0}", e.Message); } } return mrr; } // _RevScreen public static List GetSIPDetails(string sched, ref CookieContainer cookies) { string token = ""; bool success = false; byte[] webResp = null; string html = ""; // http://megatool.rogers.com/megatool/megatool/INSIS/revenue.asp?logo=N&serv_id== if (sched != "dummy") { success = Web.MakeRequest( "GET", "http://megatool.rogers.com/megatool/megatool/INSIS/revenue.asp?logo=N&serv_id=" + sched, false, "", ref webResp, ref cookies); if (!success) { Logger.Log(0, "Get SIP details fail{0}", token); } //Console.WriteLine(Encoding.ASCII.GetString(webResp)); html = Encoding.ASCII.GetString(webResp); } else { success = true; html = ""; } List data = new List { }; // SIP details extraction try { // data = ExtractSIPData(html); SIPData junk = ExtractSIPData(html); /* foreach (var row in data) { //Console.WriteLine(row.ToString()); if ( row.Description.Contains("Access") ) Logger.Log(1,"Found Access: {0} x {1}", row.UnitPrice, row.Qty); if ( row.Description.Contains("Session") ) Logger.Log(1, "Found Sessions: {0} x {1}", row.UnitPrice, row.Qty); } */ } catch (Exception e) { Logger.Log(0, "Exception: SIP Details {0}:{1}", e.Message, e.InnerException.Message); } return data; // no match found } //------------------------------------ // SCHED-A Info Extraction public static Dictionary GetParms(string sched, ref CookieContainer cookies) { string token = ""; bool success = false; byte[] webResp = null; string html = ""; Dictionary parms = new Dictionary { }; if (sched != "dummy") { success = Web.MakeRequest( "GET", "http://megatool.rogers.com/megatool/megatool/INSIS/schedule.asp?logo=N&serv_id=" + sched, false, "", ref webResp, ref cookies); if (!success) { Logger.Log(0, "GetParms fail{0}", token); } //Console.WriteLine(Encoding.ASCII.GetString(webResp)); html = Encoding.ASCII.GetString(webResp); } else { success = true; html = ""; } try { // SO + up to 5 non-digits + six digits var regex = new Regex(@"SO(?:\D{0,5})(\d{6})", RegexOptions.IgnoreCase); Match m = regex.Match(html); if (m.Success) { // m.Value = the entire match parms.Add("SO", m.Groups[1].ToString()); // = the 6-digit number } else { parms.Add("SO", "XXX"); } // TA + up to 5 non-digits + R + nine digits regex = new Regex(@"TA(?:\D{0,5})(\d{9})", RegexOptions.IgnoreCase); m = regex.Match(html); if (m.Success) { // m.Value = the entire match parms.Add("TA", "R"+m.Groups[1].ToString()); // = the 6-digit number } else { parms.Add("TA", "XXX"); } // COP + up to 5 non-digits + six digits regex = new Regex(@"COP(?:\D{0,5})(\d{6})", RegexOptions.IgnoreCase); m = regex.Match(html); if (m.Success) { // m.Value = the entire match parms.Add("COP", m.Groups[1].ToString()); // = the 6-digit number } else { parms.Add("COP", "XXX"); } // PRID + up to 5 non-digits + four digits //regex = new Regex(@"PR.*ID(?:\D{0,5})(\d{4})", RegexOptions.IgnoreCase); regex = new Regex(@"PR(?:\s?ID)?(?:\D{0,5})(\d{4})", RegexOptions.IgnoreCase); m = regex.Match(html); if (m.Success) { // m.Value = the entire match parms.Add("PRID", m.Groups[1].ToString()); // = the 6-digit number } else { parms.Add("PRID", "XXX"); } // Contract + up to 5 non-digits + letter + 9 digits regex = new Regex(@"CONTRACT(?:\D{0,5})([a-zA-Z]\d{9})", RegexOptions.IgnoreCase); m = regex.Match(html); if (m.Success) { // m.Value = the entire match parms.Add("CONTRACT", m.Groups[1].ToString()); // = the alpha+9-digit number } else { parms.Add("CONTRACT", "XXX"); } // parms.Add("SCHED", sched); // needed to build that datatable correctly in MAIN // // Billing Start Date; seems to come in Mon D, YYYY format, need to convert to YYYYMMDD //regex = new Regex(@"
Bill Start Date:\s+([a-zA-Z0-9,\s]+[0-9]{4})[.]?\s*
", RegexOptions.IgnoreCase); // Bill(?:ing|in)?\sStart(?: Date)?:\s regex = new Regex(@"
Bill(?:ing|in)?\sStart(?: Date)?:\s+([a-zA-Z0-9,\s]+[0-9]{4})[.]?\s*
", RegexOptions.IgnoreCase); m = regex.Match(html); if (m.Success) { Logger.Log(5, "raw BSD = |{0}|", m.Groups[1].ToString()); try { // m.Value = the entire match string input = m.Groups[1].ToString(); string iformat = "MMM d, yyyy"; string oformat = "yyyyMMdd"; DateTime fdate = DateTime.ParseExact(input, iformat, CultureInfo.InvariantCulture); parms.Add("BSD", fdate.ToString(oformat)); // = the alpha+9-digit number Logger.Log(4, "BSD = >{0}<", fdate.ToString(oformat)); } catch (Exception e) { Logger.Log(0, "Error converting date from SchedA->Schedule details {0}", e.Message); } } else { parms.Add("BSD", "XXX"); } // MRR+ up to 5 non-digits + $XXX.XX //regex = new Regex(@"(?]*>[\s\S]*?MRR[\s\S]*?\$\s*(\d{1,3}(?:,\d{3})*(?:\.\d{2})?)[\s\S]*? public static double getMRR(string sched, ref CookieContainer cookies) { bool success = false; double mrr = 0; byte[] webResp = null; success = Web.MakeRequest( "GET", "http://megatool.rogers.com/megatool/megatool/INSIS/insisMainwindow.asp?serv_id=" + sched, false, "", ref webResp, ref cookies); if (!success) { Logger.Log(5, "MRR FAIL {0}", sched); } string html = Encoding.ASCII.GetString(webResp); if (html.Length > 5000) { try { Regex word = new Regex(@"]*>[\s\S]*?Total\s+MRR[\s\S]*?\$\s*([0-9]{1,3}(?:,[0-9]{3})*(?:\.[0-9]{2})?)[\s\S]*?<\/tr>"); // find MRR dollar value Match m = word.Match(html); // if (m.Success) { Group g = m.Groups[1]; //Capture c = g.Captures[0]; Logger.Log(6, "Regex Match {0} / Group Count {1} / Captures Count {2} / result={3}", m.Success, m.Groups.Count, m.Captures.Count, g.Value); mrr = Convert.ToDouble(g.Value); if ((mrr >= 0) && (mrr <= 999999)) Logger.Log(5, " {1} MRR found successfully {0}", mrr, sched); } else { Logger.Log(1, "No MRR found."); } } catch (Exception e) { Logger.Log(0, "Error parsing MRR {0}", e.Message); } } return mrr; } public static bool SchedXL(string sched, ref CookieContainer cookies) { string token = ""; bool success = false; byte[] webResp = null; success = Web.MakeRequest( "GET", "http://megatool.rogers.com/megatool/megatool/INSIS/insisMainwindow.asp?serv_id=" + sched, false, "", ref webResp, ref cookies); if (!success) { Logger.Log(5, "Check Inactive SchedA's fail. {0}", token); } //Console.WriteLine(Encoding.ASCII.GetString(webResp)); else { string html = Encoding.ASCII.GetString(webResp); if (html.Length < 5000) return true; // bit of a h*ck for when NSIS says 'no records' const string startKey = ">Order Type ("; const string endKey = ")(); int index = 0; while (true) { // Find "serv_id=" int start = html.IndexOf(startKey, index, StringComparison.OrdinalIgnoreCase); if (start == -1) break; // no more matches start += startKey.Length; // Find "')" int end = html.IndexOf(endKey, start, StringComparison.Ordinal); if (end == -1) break; string value = html.Substring(start, end - start); if ((value == "XL") || (value == "XP") || (value == "NX")) return true; index = end + endKey.Length; } } return false; } public static bool GetSchedAs(string serv_id, ref List scheds, ref CookieContainer cookies) { bool success = false; string token = ""; byte[] webResp = null; success = Web.MakeRequest( "POST", "http://megatool.rogers.com/megatool/megatool/INSIS/SearchSites.asp?query=Y&exportFlag=N", "service_id="+serv_id, false, "", ref webResp, ref cookies); if (!success) { Logger.Log(0, "Get SchedA's Fail {0}", token); } //Console.WriteLine(Encoding.ASCII.GetString(webResp)); else { string html = Encoding.ASCII.GetString(webResp); const string startKey = "serv_id="; const string endKey = "')"; //var results = new List(); int index = 0; while (true) { // Find "serv_id=" int start = html.IndexOf(startKey, index, StringComparison.OrdinalIgnoreCase); if (start == -1) break; // no more matches start += startKey.Length; // Find "')" int end = html.IndexOf(endKey, start, StringComparison.Ordinal); if (end == -1) break; string value = html.Substring(start, end - start); scheds.Add(value); index = end + endKey.Length; } } return success; } //perform NTLM authentication for MegaTool with users LAN ID public static bool Auth(string user, string pass, ref CookieContainer cookies) { string url = "http://megatool.rogers.com/megatool/megatool/"; bool success = false; // Explicit credentials (domain\user) var creds = new NetworkCredential(user, pass, "RCI"); // A cookie container is REQUIRED to capture session cookies // var cookies = new CookieContainer(); var request = (HttpWebRequest)WebRequest.Create(url); request.Method = "GET"; request.AllowAutoRedirect = false; // Required for NTLM handshake request.PreAuthenticate = false; // NTLM cannot pre-authenticate request.UseDefaultCredentials = false; request.Credentials = creds; // Enables SSPI NTLM handshake request.CookieContainer = cookies; // Store session cookies request.KeepAlive = true; // NTLM requires same connection request.UserAgent = "NTLMClient/.NET4.8"; Logger.Log(1, "Megatool NTLM authentication for ({0})...", user); HttpWebResponse response; try { response = (HttpWebResponse)request.GetResponse(); } catch (WebException wex) when (wex.Response is HttpWebResponse) { response = (HttpWebResponse)wex.Response; } // If server demands NTLM, the framework automatically: // • sends Type1 // • receives Type2 // • sends Type3 // • then returns the real authenticated page response Logger.Log(5, "HTTP Status: " + (int)response.StatusCode + " " + response.StatusCode); // Read response body string body; using (var reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { body = reader.ReadToEnd(); } /* Console.WriteLine("\n--- Page Content ---\n"); Console.WriteLine(body); Console.WriteLine("\n--- Cookies Received ---"); */ foreach (Cookie ck in cookies.GetCookies(request.RequestUri)) { Logger.Log(5, $"{ck.Name} = {ck.Value}; Domain={ck.Domain}; Path={ck.Path}"); success = true; } response.Close(); return success; } } }