-
Notifications
You must be signed in to change notification settings - Fork 0
/
DurableDilbertPoster.cs
137 lines (112 loc) · 5.16 KB
/
DurableDilbertPoster.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using HtmlAgilityPack;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.Logging;
using System;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.InputFiles;
namespace DilbertPoster
{
public static class DurableDilbertPoster
{
private const bool runOnStartup = false;
[FunctionName(nameof(DilbertPoster_Timer))]
public static async Task DilbertPoster_Timer(
[TimerTrigger("0 0 9 * * *", RunOnStartup = runOnStartup)] TimerInfo dilbertTimer,
[DurableClient] IDurableOrchestrationClient starter,
ILogger log)
{
string currentDate = DateTime.Now.ToString("yyyy-MM-dd");
string instanceId = await starter.StartNewAsync(nameof(DilbertPoster_Orchestrator), null, currentDate);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
}
[FunctionName(nameof(DilbertPoster_Orchestrator))]
public static async Task DilbertPoster_Orchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context,
ILogger log)
{
string currentDate = context.GetInput<string>();
if (!context.IsReplaying)
log.LogInformation($"Starting strip search for {currentDate}...");
int pollingInterval = 5 * 60; //5 minutes
DateTime expiryTime = context.CurrentUtcDateTime.AddHours(1);
while (context.CurrentUtcDateTime < expiryTime)
{
var data = await context.CallActivityAsync<StripData>(nameof(ReadPageContent), currentDate);
if (!data.IsError)
{
log.LogInformation("Strip found!");
await context.CallActivityAsync(nameof(SendToTelegram), data);
log.LogInformation("Sent!");
return;
}
log.LogInformation("Still waiting...");
var nextCheck = context.CurrentUtcDateTime.AddSeconds(pollingInterval);
await context.CreateTimer(nextCheck, CancellationToken.None);
}
log.LogError($"Timeout waiting for the strip {currentDate} to be released");
}
[FunctionName(nameof(ReadPageContent))]
public static async Task<StripData> ReadPageContent([ActivityTrigger] string currentDate, ILogger log)
{
string url = "https://dilbert.com";
var client = new HttpClient();
var tResp = client.GetAsync(url);
var tTimeout = Task.Delay(30 * 1000);
if (await Task.WhenAny(tResp, tTimeout) == tTimeout)
{
var ex = new TimeoutException($"Timeout while getting html from {url}");
return new StripData("Err", ex.ToString(), true);
}
else
{
var response = await tResp;
var stream = await response.Content.ReadAsStreamAsync();
string html = "";
using (StreamReader sr = new(stream))
{
html = await sr.ReadToEndAsync();
}
//find today's div
//<div class="comic-item-container js-comic js-comic-container-{yyyy-MM-dd}"
var doc = new HtmlDocument();
doc.LoadHtml(html);
string xpathNode = $@"//div[@class='comic-item-container js-comic js-comic-container-{currentDate}'][1]";
var div = doc.DocumentNode.SelectSingleNode(xpathNode);
if (div is null)
return new StripData(null, null, true);
string title = div.Attributes["data-title"].Value;
string address = div.Attributes["data-image"].Value;
title = title.Trim();
if (title.Length > 0)
title += " - ";
title += "Dilbert by Scott Adams";
if (!address.StartsWith("https:"))
address = "https:" + address;
return new StripData(title, address, false);
}
}
[FunctionName(nameof(SendToTelegram))]
public static async Task SendToTelegram([ActivityTrigger] StripData strip, ILogger log)
{
TelegramBotClient HorseBot = new(Environment.GetEnvironmentVariable("HorseBotKey"));
string channel = Environment.GetEnvironmentVariable("Channel");
string jackChat = Environment.GetEnvironmentVariable("JackChat");
#if DEBUG
channel = jackChat;
#endif
Message message = await HorseBot.SendPhotoAsync(channel,
// trick the Telegram API into thinking it's a gif
photo: new InputOnlineFile(strip.Address + ".gif"),
caption: strip.Title,
parseMode: ParseMode.Html);
}
public record StripData(string Title, string Address, bool IsError);
}
}