Module:Sandbox/Aidan9382/DiscussionOverview explained

--[=[ A module designed to provide an overall summary and some statistics on a discussion board Inspired by, and partially borrowed from, [[Module:Sandbox/Smalljim/DiscussionIndexTest]]--]=]local Transcluder = require("Module:Transcluder")local p =

table.find = function(t,o) --Used to luau, so assumed this existed. Heres a quick version for a,b in next,t do if b

o then return true end end return falseend

local lang = mw.getContentLanguagelocal function getTime(timestamp) return tonumber(lang:formatDate("U",timestamp))end

local function concatUsers(users) local final = "" for _,user in next,users do if string.match(user,"^%d+%.%d+%.%d+%.%d+$") or string.match(user,"^%x+:[%x:]+$") or string.match(user, "^~%d%d%d%d%-%d%d%d%d%d%-%d%d%d$") then --Lazy but mostly working basic IPv6 regex final = final .. ""..user..", " else final = final .. ""..user..", " end end return string.sub(final,1,-3)end

--Specialised version of Sandbox/Smalljim/ParsePageTest.formatDateDiff that just does hours (better for sorting cause im not learning wikitables)local function formatDateDiff(date_diff) return tonumber(math.floor(date_diff/(6*60))/10) .. ' hours';end

--Specialised version of Transcluder.getSections, using a similar designlocal function getSectionData(text) local sections = text = "\n"..text.."\n

" while true do local section,content = string.match(text,"\n

%s*([^=]-)%s*

\n(.-)\n

[^=]") if not section then break end text = string.sub(text,string.find(text,content,1,true)+#content,-1) sections[#sections+1] = end return sectionsend

--This is a bloody mess of a mix of ideas, but it mostly works, so good enoughlocal function getUserMentions(text) --Returns a list of users, and if they were considered a "participant" or someone who was just mentioned local mentions = text = mw.text.decode(text,true) --Timestamp is %d%d:%d%d, %d%d? %w+ %d%d%d%d %(UTC%)) but we allow some (minor) leniancy for those who just slightly edit their dates (why?) so that it still picks up local timestampRegex = "((%d%d:%d%d, %d%d? %w+,? %d%d%d%d) %(UTC%))" local userRegex = "(%[%[:?[Uu]ser:([^#|%]]+))" local userTalkRegex = "(%[%[:?[Uu]ser[_][Tt]alk:([^#|%]]+))" local userContribRegex = "(%[%[:?[Ss]pecial:[Cc]ontributions/([^#|%]]+))" for line in string.gmatch(text,"[^\n]+") do --Split by line and check all content on said line. This assumes all signatures never use newlines, which they should not be doing anyways. --Bar of entry for being labelled a "participant" is a valid timestamp along with their user/usertalk/contribs --Users can be noted as being both a participant and a mention during the data, so be smart in using this data local usersOnThisLine = for _,reg in next, do local index = 1 while true do local targetText = string.sub(line,index,-1) local wholeText,identifier = string.match(targetText,reg) if not wholeText then break end identifier = string.gsub(identifier,"_"," ") if not string.find(identifier,"/") then --Avoid subpage nonsense usersOnThisLine[string.find(targetText,reg)] = identifier end index = index + string.find(targetText,reg) + #wholeText end end --Start associating timestamps with users local index = 1 local pindex = --Lazy coding local participants = while true do local targetText = string.sub(line,index,-1) local wholeText,identifier = string.match(targetText,timestampRegex) if not wholeText then break end --Backtrack through the text for a mention local timestampLocation = string.find(targetText,identifier) local user,where for i = timestampLocation,1,-1 do user,where = usersOnThisLine[i],i if user then break end end if user then participants[#participants+1] = pindex[user] = true else --else: be confused as hell mw.log("Timestamp had no associated users on its line (TS "..wholeText..")") end index = index + timestampLocation + #wholeText end local pings = for _,user in next,usersOnThisLine do if not pings[user] and not pindex[user] then --If they participated on a line, just ignore all pings pings[user] = true end end --Integrate the new data for user,_ in next,pings do mentions[#mentions+1] = end for _,userData in next,participants do mentions[#mentions+1] = userData end end return mentionsend

function p.main(frame) local page = frame.args[1] or frame.args.page assert(type(page)

"string","Invalid or no page provided") local _, text = xpcall(function return Transcluder.get(page) end, function(err) error(debug.traceback) end) local sections = getSectionData(text) local tableContent = '

Conversation summary for ' .. page .. '' .. 'v' .. '\n-\n! Section Initiator Last Comment Size Participants Mentions' for _,section in next,sections do local sanitisedName = string.gsub(string.gsub(mw.uri.anchorEncode(frame:preprocess(section.name)),"%[%[:?[^|]-|([^%]]-)]]","%1"),"%[%[:?([^%]]-)]]","%1") local displayName = string.gsub(string.gsub(frame:preprocess(section.name),"%[%[:?[^|]-|([^%]]-)]]","%1"),"%[%[:?([^%]]-)]]","%1") local wikilinkAnchor = ""..displayName.."" local membersInText = getUserMentions(section.content) local uniqueParticipants = for _,userData in next,membersInText do if userData.participated and not table.find(uniqueParticipants,userData.user) then uniqueParticipants[#uniqueParticipants+1] = userData.user end end local mentionedUsers = for _,userData in next,membersInText do if not userData.participated and not table.find(uniqueParticipants,userData.user) and not table.find(mentionedUsers,userData.user) then mentionedUsers[#mentionedUsers+1] = userData.user end end local now = getTime local orderedComments = for _,userData in next,membersInText do if userData.participated then local when = getTime(userData.when) if now > when then --Ensure comment is from the past if #orderedComments

0 then orderedComments[#orderedComments+1] = else for i = 1,#orderedComments do local comment = orderedComments[i] if when < comment.when then for i2 = #orderedComments+1,i,-1 do orderedComments[i2] = orderedComments[i2-1] end orderedComments[i] = break end if i

#orderedComments then orderedComments[#orderedComments+1] = --Reached the end, latest comment break end end end end end end local firstComment,lastComment if #orderedComments

0 then firstComment = "N/A" lastComment = "N/A" elseif #orderedComments

1 then firstComment = formatDateDiff(now-orderedComments[1].when) .. " ago" .. "
" .. concatUsers lastComment = "N/A" else firstComment = formatDateDiff(now-orderedComments[1].when) .. " ago" .. "
" .. concatUsers lastComment = formatDateDiff(now-orderedComments[#orderedComments].when) .. " ago" .. "
" .. concatUsers end local participants = #uniqueParticipants .. ": " .. concatUsers(uniqueParticipants) local mentions = #mentionedUsers .. ": " .. concatUsers(mentionedUsers) local sectionContent = "\n

-\n"..wikilinkAnchor.." "..firstComment.." "..lastComment.." "..#section.content.." "..participants.." "..mentions tableContent = tableContent .. sectionContent end return tableContent .. "\n
"end

function p.maindev(frame) local content = p.main(frame) return content .. "\n\n" .. frame:extensionTag("syntaxhighlight",content,)end

p.getSectionData = getSectionDatap.getUserMentions = getUserMentions

return p