Skip to content

Commit

Permalink
Implement Slack posting
Browse files Browse the repository at this point in the history
  • Loading branch information
rgwood committed Nov 29, 2021
1 parent 22a4805 commit 6de0235
Showing 1 changed file with 48 additions and 5 deletions.
53 changes: 48 additions & 5 deletions RezoningScraper/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.CommandLine.Invocation;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using System.Text.Json;
using static Spectre.Console.AnsiConsole;

namespace RezoningScraper;
Expand All @@ -15,17 +17,18 @@ static async Task<int> Main(string[] args)
var rootCommand = new RootCommand("A tool to detect new+modified postings on Vancouver's shapeyourcity.ca website. Data is stored in a local SQLite database next to the executable.")
{
new Option<string?>("--slack-webhook-url",
getDefaultValue: () => "",
description: "A Slack Incoming Webhook URL. If specified, RezoningScraper will post info about new+modified rezonings to this address."),
};

rootCommand.Handler = CommandHandler.Create<string?>(RunScraper);
rootCommand.Handler = CommandHandler.Create<string>(RunScraper);
return await rootCommand.InvokeAsync(args);
}

static async Task RunScraper(string? slackWebhookUri)
static async Task RunScraper(string slackWebhookUrl)
{
MarkupLine($"[green]Welcome to RezoningScraper v{Assembly.GetExecutingAssembly().GetName().Version}[/]");
if(string.IsNullOrEmpty(slackWebhookUri)) { WriteLine($"Slack URI not specified; will not publish updates to Slack."); }
if(string.IsNullOrWhiteSpace(slackWebhookUrl)) { WriteLine($"Slack URI not specified; will not publish updates to Slack."); }
WriteLine();

// Use Spectre.Console's Status UI https://spectreconsole.net/live/status
Expand Down Expand Up @@ -74,9 +77,9 @@ await AnsiConsole.Status().StartAsync("Opening DB...", async ctx =>
MarkupLine($"Upserted {latestProjects.Count} projects to the DB in [yellow]{stopwatch.ElapsedMilliseconds}ms[/]");
MarkupLine($"Found [green]{newProjects.Count}[/] new projects and [green]{changedProjects.Count}[/] modified projects.");

if (!string.IsNullOrEmpty(slackWebhookUri))
if (!string.IsNullOrEmpty(slackWebhookUrl) && (newProjects.Any() || changedProjects.Any()))
{
// TODO: post changes to Slack
await PostToSlack(slackWebhookUrl, newProjects, changedProjects);
}

PrintNewProjects(newProjects);
Expand All @@ -90,6 +93,46 @@ await AnsiConsole.Status().StartAsync("Opening DB...", async ctx =>
});
}

private static async Task PostToSlack(string slackWebhookUri, List<Project> newProjects, List<ChangedProject> changedProjects)
{
WriteLine($"Posting to Slack...");

var message = new StringBuilder();

foreach (var proj in newProjects)
{
message.AppendLine($"New: *<{proj.links!.self!}|{proj.attributes!.name!}>*\n");
}

foreach (var changedProject in changedProjects)
{
message.AppendLine($"Changed: *<{changedProject.LatestVersion.links!.self!}|{changedProject.LatestVersion.attributes!.name!}>*\n");

foreach (var change in changedProject.Changes)
{
const int MaxLength = 100; // arbitrary; we just need some way to avoid huuuuuuuge descriptions that look bad in Slack
if (change.Value.OldValue?.Length > MaxLength || change.Value.NewValue?.Length > MaxLength)
{
message.AppendLine($" {Capitalize(change.Key)} changed, too big to show");
}
else
{
message.AppendLine($" {Capitalize(change.Key)}: {change.Value.OldValue} ➡️ {change.Value.NewValue}");
}

string Capitalize(string str) => str.Substring(0, 1).ToUpper() + str.Substring(1);

}
}

var json = JsonSerializer.Serialize(new { text = message.ToString() });
var client = new HttpClient();
var content = new StringContent(json, Encoding.UTF8, "application/json");

await client.PostAsync(slackWebhookUri, content);
WriteLine("Posted new+changed projects to Slack");
}

static void PrintNewProjects(List<Project> newProjects)
{
if (newProjects.Count == 0) return;
Expand Down

0 comments on commit 6de0235

Please sign in to comment.