-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.fs
More file actions
111 lines (89 loc) · 3.54 KB
/
Program.fs
File metadata and controls
111 lines (89 loc) · 3.54 KB
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
module Agg
open DotNetEnv
open System
open System.IO
open System.Xml.Linq
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Hosting
open Microsoft.AspNetCore.Http
open Microsoft.Extensions.FileProviders
open Microsoft.Extensions.Hosting
Env.Load() |> ignore
type RssItemGenerator = unit -> Async<string option>
let rssItemGenerators: RssItemGenerator[] = [|
MostRecentCommit.getMostRecentPushEventAsRssString
MostRecentMovieRating.getMostRecentMovieRatingAsRssString
MostRecentMovieRating.getMostRecentEpisodeRatingAsRssString
MostRecentPhoto.getMostRecentFlickrPhotoAsRssString
|]
let generateRssFeed (items: string list) =
let channel =
XElement(XName.Get("channel"),
XElement(XName.Get("title"), "Joe's digital journal"),
XElement(XName.Get("description"), "A curated stream of my discoveries, thoughts, and activities"),
XElement(XName.Get("lastBuildDate"), DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc))
)
items
|> List.filter (fun item -> not (String.IsNullOrWhiteSpace(item)))
|> List.iter (fun item ->
let itemElement = XElement.Parse(item)
channel.Add(itemElement))
let rss =
XElement(XName.Get("rss"),
XAttribute(XName.Get("version"), "2.0"),
channel
)
let declaration = XDeclaration("1.0", "utf-8", "yes")
let doc = XDocument(rss)
doc.Declaration <- declaration
// Add XML stylesheet processing instruction for browser syntax highlighting
let styleSheet = XProcessingInstruction("xml-stylesheet", "type=\"text/xml\"")
doc.AddFirst(styleSheet)
doc
let generateRssToWwwroot () =
async {
printfn "Generating RSS feed..."
let! results =
rssItemGenerators
|> Array.map (fun generator -> generator())
|> Async.Sequential
let validItems =
results
|> Array.choose id
|> Array.toList
printfn $"Generated %d{validItems.Length} RSS items"
let rssFeed = generateRssFeed validItems
Directory.CreateDirectory("wwwroot") |> ignore
let filePath = Path.Combine("wwwroot", "journal.xml")
rssFeed.Save(filePath)
printfn $"RSS feed saved to: %s{filePath}"
}
let mutable timer: System.Threading.Timer option = None
let startScheduler () =
timer <- Some(new System.Threading.Timer(
(fun _ -> generateRssToWwwroot() |> Async.RunSynchronously),
null,
TimeSpan.Zero,
TimeSpan.FromHours(12.0)))
[<EntryPoint>]
let main argv =
let builder = WebApplication.CreateBuilder()
builder.WebHost.UseUrls("http://0.0.0.0:5001") |> ignore
let app = builder.Build()
app.MapGet("/", fun (context: Microsoft.AspNetCore.Http.HttpContext) ->
let filePath = Path.Combine("wwwroot", "journal.xml")
if File.Exists(filePath) then
context.Response.ContentType <- "application/xml; charset=utf-8"
context.Response.SendFileAsync(filePath)
else
context.Response.StatusCode <- 404
System.Threading.Tasks.Task.CompletedTask
) |> ignore
app.MapGet("/health", fun (context: Microsoft.AspNetCore.Http.HttpContext) ->
context.Response.StatusCode <- 200
context.Response.WriteAsync("OK")
) |> ignore
app.UseStaticFiles(StaticFileOptions(FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot")))) |> ignore
startScheduler()
app.Run()
0