summaryrefslogtreecommitdiffstats
path: root/app/Main.hs
blob: 99daa6e8bf9bbe077db403c7bd169d198bf03099 (plain)
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
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}

module Main where

import Conduit
import Control.Exception
import Data.Maybe
import Data.Text qualified as T
import Data.XML.Types
import Network.HTTP.Conduit
import Text.Atom.Conduit.Parse
import Text.Atom.Conduit.Render
import Text.Atom.Types
import Text.XML.Stream.Parse
import Text.XML.Stream.Render
import Text.XML.Unresolved (elementToEvents)

env_FEED_TITLE :: T.Text
env_FEED_TITLE = "code.nomath.org"

env_FEED_ID :: T.Text
env_FEED_ID = "code.nomath.org"

env_FEED_URLS :: [String]
env_FEED_URLS =
  [ "https://code.nomath.org/anissue/atom",
    "https://code.nomath.org/apaperless/atom",
    "https://code.nomath.org/abuilder/atom",
    "https://code.nomath.org/infra/atom",
    "https://code.nomath.org/json2sql/atom",
    "https://code.nomath.org/nomath-org/atom",
    "https://code.nomath.org/static-nomath-org/atom"
  ]

main :: IO ()
main = do
  manager <- newManager tlsManagerSettings
  runResourceT do
    feeds <- mapM (getFeed manager) env_FEED_URLS
    let feed = merge feeds
    runConduit do
      renderAtomFeed feed
        .| renderBytes def
        .| sinkFile "output.atom"

merge :: [AtomFeed] -> AtomFeed
merge feeds =
  AtomFeed
    { feedAuthors = concatMap (.feedAuthors) feeds,
      feedCategories = concatMap (.feedCategories) feeds,
      feedContributors = concatMap (.feedContributors) feeds,
      feedEntries = concatMap (.feedEntries) feeds,
      feedGenerator = Nothing,
      feedIcon = Nothing,
      feedId = env_FEED_ID,
      feedLinks = concatMap (.feedLinks) feeds,
      feedLogo = Nothing,
      feedRights = Nothing,
      feedSubtitle = Nothing,
      feedTitle = AtomPlainText TypeText env_FEED_TITLE,
      feedUpdated = minimum (map (.feedUpdated) feeds)
    }

data ParserError = ParserError String
  deriving (Show)

instance Exception ParserError

getFeed :: Manager -> String -> ResourceT IO AtomFeed
getFeed manager url = do
  request <- parseRequest url
  response <- http request manager
  fromMaybe (throw (ParserError url))
    <$> runConduit do
      responseBody response
        .| parseBytes def
        .| massage
        .| atomFeed

massage :: ConduitT Event Event (ResourceT IO) ()
massage = do
  await >>= \case
    Nothing -> pure ()
    Just e -> do
      yield e -- BeginDocument
      await >>= \case
        Nothing -> pure ()
        Just e -> do
          yield e -- <feed>
          yieldMany (elementToEvents idE)
          yieldMany (elementToEvents updatedE)
  mapC id
  where
    idE =
      -- TODO(id)
      Element
        "{http://www.w3.org/2005/Atom}id"
        []
        [ NodeContent (ContentText "TODO")
        ]
    updatedE =
      -- TODO(updated)
      Element
        "{http://www.w3.org/2005/Atom}updated"
        []
        [ NodeContent (ContentText "1970-01-01T00:00:00Z")
        ]