diff options
author | sanine <sanine.not@pm.me> | 2022-01-04 22:28:43 -0600 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2022-01-04 22:28:43 -0600 |
commit | 72e13dff9ff4fde91b84054167da91a5d27cb952 (patch) | |
tree | fca4ac07fe5b8e03ab6352fb999be1459f115db4 /src/lua-script/script.lua | |
parent | 43347c36ec9b1f5e988cf6c89edd4d901061a303 (diff) |
add working rss:
Diffstat (limited to 'src/lua-script/script.lua')
-rw-r--r-- | src/lua-script/script.lua | 204 |
1 files changed, 196 insertions, 8 deletions
diff --git a/src/lua-script/script.lua b/src/lua-script/script.lua index e44ece5..65bf0cf 100644 --- a/src/lua-script/script.lua +++ b/src/lua-script/script.lua @@ -1,3 +1,133 @@ +local RssChannel = {} +RssChannel.new = function(title, link, description, settings) + local settings = settings or {} + + local channel = { + title=title, + link=link, + description=description, + } + + channel.language = settings.language + channel.copyright = settings.copyright + channel.managingEditor = settings.managingEditor + channel.webMaster = settings.webMaster + channel.lastBuildDate = settings.lastBuildDate + channel.category = settings.category + channel.generator = 'argent v0.1.0' + channel.docs = 'https://www.rssboard.org/rss-specification' + + channel.items = {} + + setmetatable( + channel, + { + __index=RssChannel, + __tostring=RssChannel.tostring, + } + ) + return channel +end + + +RssChannel.addItem = function(self, tbl) + local to_rfc822 = function(datestring, zone) + if not string.match(datestring, '^%d%d%d%d%-%d%d%-%d%d$') then + error(string.format('%q is not a valid date string', datestring)) + end + + local year = string.match(datestring, '^%d%d%d%d') + local month = string.match(datestring, '-(%d%d)-') + local day = string.match(datestring, '%d%d$') + + local month_names = {'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'} + month = month_names[tonumber(month)] + + return string.format('%s %s %s 00:00:00 %s', day, month, year, zone) + end + + if not (tbl.title or tbl.description) then + error('items must specify either a title or description!') + end + + if not tbl.pubDate then + error('items must specify a pubDate!') + else + tbl.pubDate = to_rfc822(tbl.pubDate, 'Z') + print(tbl.pubDate) + end + + table.insert(self.items, tbl) +end + + +local tag_builder = function(source_table, indent_level) + local str = '' + local indent = string.rep(' ', indent_level) + local add_tag = function(tag) + if source_table[tag] then + str = str .. + string.format('%s<%s>%s</%s>\n', + indent, tag, source_table[tag], tag) + end + end + local content = function() + return str + end + return add_tag, content +end + +local render_item = function(item_tbl) + local add_tag, content = tag_builder(item_tbl, 2) + add_tag('title') + add_tag('link') + add_tag('description') + add_tag('author') + add_tag('category') + add_tag('comments') + add_tag('guid') + add_tag('pubDate') + + local indent = string.rep(' ', 1) + return string.format('%s<item>\n%s%s</item>', + indent, content(), indent) +end + +RssChannel.tostring = function(self) + local add_tag, content = tag_builder(self, 1) + add_tag('title') + add_tag('link') + add_tag('description') + + add_tag('language') + add_tag('copyright') + add_tag('managingEditor') + add_tag('webMaster') + add_tag('pubDate') + add_tag('lastBuildDate') + add_tag('category') + add_tag('generator') + add_tag('docs') + + items_str = '' + + for _, item in ipairs(self.items) do + items_str = items_str .. render_item(item) .. '\n' + end + + return string.format( + '<rss version="2.0">\n<channel>\n%s\n%s</channel>\n</rss>', + content(), items_str) +end + + +RssChannel.save = function(self, filename) + file = io.open(filename, 'w') + file:write(self:tostring()) + file:close() +end + + return function(config) local fmt = string.format @@ -21,6 +151,7 @@ return function(config) function set_tostring(set) local str = '[empty]' + if not set then return str end for element in pairs(set) do if str == '[empty]' then str = tostring(element) @@ -82,17 +213,30 @@ return function(config) function setup(config) argent.log('debug', 'begin setup') - + + if not config.site_name then + error('site_name MUST be set!') + end + argent.config = { + site_name = config.site_name, + site_address = add_end_slash(config.site_address) or nil, + site_description = config.site_description or '', + site_language = config.site_language, + site_copyright = config.site_copyright, + site_directory = add_end_slash(config.site_directory) or 'site/', output_directory = add_end_slash(config.output_directory) or 'public/', layout_directory = add_end_slash(config.layout_directory) or nil, plugin_directory = add_end_slash(config.plugin_directory) or nil, + exclude = Set(config.exclude, strip_end_slash) or {}, include = Set(config.include, strip_end_slash) or {}, keep = Set(config.keep, strip_end_slash) or {}, noprocess = Set(config.noprocess, strip_end_slash) or {}, - rss_include = Set(config.rss_include, strip_end_slash) or {}, + + rss_include = Set(config.rss_include, strip_end_slash) or nil, + webmaster_email = config.webmaster_email, } argent.log('info', fmt('site directory: %s', argent.config.site_directory)) @@ -118,6 +262,22 @@ return function(config) add_end_slash(argent.currentWorkingDirectory()) ..argent.config.plugin_directory..'?.lua;'..package.path end + + if argent.config.rss_include then + if not argent.config.site_address then + error('rss_include is set, but site_address is not!') + end + argent.rss_channel = RssChannel.new( + argent.config.site_name, + argent.config.site_address, + argent.config.site_description, + { language = argent.config.site_language, + copyright = argent.config.site_copyright, + webMaster = argent.config.webmaster_email, + } + ) + end + argent.log('debug', 'end setup') end @@ -175,11 +335,11 @@ return function(config) end argent.log('debug', fmt('obliterating files in %q', parent..dir)) - return obliterate_directory(dir, parent) + return obliterate(dir, parent) end - function obliterate_directory(dirname, parent) + function obliterate(dirname, parent) local dirname = add_end_slash(dirname) or '' local parent = parent or '' @@ -324,6 +484,30 @@ return function(config) local output_file = io.open(argent.config.output_directory..parent..output_name, 'w') output_file:write(output_data) output_file:close() + + for pattern in pairs(argent.config.rss_include) do + if string.match(filename, pattern) + or string.match(parent..filename, pattern) + then -- add to the RSS feed! + if not result.date then + argent.log( + 'warn', + fmt( + '%q did not specify a date; it will not be included in rss.xml!', + parent..filename + ) + ) + return + end + + argent.rss_channel:addItem{ + title=result.title, + link=argent.config.site_address..parent..output_name, + description = result.description, + pubDate = result.date, + } + end + end end @@ -336,11 +520,11 @@ return function(config) if not directory_exists(directory, parent) then argent.createDirectory(argent.config.output_directory..parent..directory) end - process_directory(directory, parent) + process(directory, parent) end - function process_directory(directory, parent) + function process(directory, parent) local directory = add_end_slash(directory) or '' local parent = add_end_slash(parent) or '' local dirs, files = argent.scanDirectory(argent.config.site_directory..parent..directory) @@ -366,7 +550,11 @@ return function(config) if not output_directory_exists() then argent.createDirectory(argent.config.output_directory) else - obliterate_directory() + obliterate() + end + process() + + if argent.rss_channel then + argent.rss_channel:save(argent.config.output_directory..'rss.xml') end - process_directory() end |