Module:Daily DYK

From Soyjak Wiki, the free ensoyclopedia
Jump to navigationJump to search

Usage

{{#invoke:Daily DYK|main}}

Displays 10 facts.

custom number of facts (x):

{{#invoke:Daily DYK|main|count=x}}

Description

Module:Daily DYK/data

This module selects a set of DYK facts for each UTC calendar date from Module:Daily DYK/data. The selected facts will remain the same all day unless the data pool is edited. Therefore, addition of facts should preferably happen just before the start of the next day.

The UTC date and fact text are hashed together to create a "random" daily order. The module displays the first requested amount of facts from that ordering.

It has a useless, but available, date override. You will not use it.

/data must follow the following formatting: It must be a single line, and begin with an asterisk (*) followed by a space followed by whatever the hell the fact is

example:

* First fact
* Second fact
* Third fact
* Yellow [[Banana]]
* Red Apple
* Red Tasty Strawberry
* Melons

After the first space, there are no formatting rules.

Blank lines and improperly formatted lines are ignored. Duplicate facts are included only once. Do NOT add anything else to /data (header templates, other nonsense)


--[[
Module:Daily DYK
Written by User:Rickert
]]
local p = {}
local dateFormats = {
	daily = 'Y-m-d',
	weekly = 'o-W',
	monthly = 'Y-m',
	yearly = 'Y'
}

function p.main(frame)
	local args = frame.args
	local page = mw.text.trim(args.page or '')
	local count = math.floor(tonumber(args.count) or 10)
	local date = mw.text.trim(args.date or '')
	local period = mw.text.trim(args.period or 'daily')

	if period == '' then
		period = 'daily'
	end

	if page == '' then
		local parent = frame:getParent()
		local parentTitle = parent and parent:getTitle()
		if not parentTitle or parentTitle == '' then
			error('Unable to determine snopes-approved fact page', 0)
		end
		page = parentTitle .. '/data'
	end


	if date == '' then
		local format = dateFormats[mw.ustring.lower(period)] or period
		date = frame:callParserFunction('#time', {format})
	end

	if count < 1 then
		return ''
	end

	local title = mw.title.new(page)
	if not title then
		error('Invalid snopes-approved fact page: ' .. page, 0)
	end
	local text = title:getContent()

	if not text then
		error('Snopes-approved fact page does not exist: ' .. page, 0)
	end

	local entries = {}
	local seen = {}

	for line in mw.text.gsplit(text, '\n', true) do
		local entry = mw.ustring.match(line, '^%s*%*%s+(.+)$')

		if entry then
			entry = mw.text.trim(entry)

			if entry ~= '' and not seen[entry] then
				entries[#entries + 1] = entry
				seen[entry] = true
			end
		end
	end

	if #entries == 0 then
		error('No snopes-approved facts found: ' .. page, 0)
	end

	for i, entry in ipairs(entries) do
		entries[i] = {
			text = entry,
			key = mw.hash.hashValue('md5', date .. '\0' .. entry)
		}
	end

	table.sort(entries, function(a, b)
		if a.key == b.key then
			return a.text < b.text
		end

		return a.key < b.key
	end)

	count = math.min(count, #entries)

	local output = {}

	for i = 1, count do
		output[i] = '* ' .. entries[i].text
	end

	return frame:preprocess(table.concat(output, '\n'))
end

return p