Bước tới nội dung

Mô đun:Citron/Spam

Bách khoa toàn thư mở Wikipedia
local p = {}local lang = mw.language.getContentLanguage()-- Initializelocal title = mw.title.new('MediaWiki:BlockedExternalDomains.json')local content = title:getContent()local data = mw.text.jsonDecode(content)local domains = {}local domainLookup = {}for _, entry in ipairs(data) do    table.insert(domains, entry.domain)endfor _, domain in ipairs(domains) do	domainLookup[domain] = trueend-- Mainlocal function isAdded(hostname)	return domainLookup[hostname] == trueendlocal function statsText(hostnames, feedbacks)	local stats = { good = 0, bad = 0, added = 0 }		for _, hostname in ipairs(hostnames) do		for _, feedback in ipairs(feedbacks) do			if feedback.hostname == hostname.hostname then				if feedback.status == 0 then					stats.good = stats.good + 1				else					stats.bad = stats.bad + 1				end			end		end		if isAdded(hostname.hostname) then			stats.added = stats.added + 1		end	end		local texts = {}		for key, value in pairs(stats) do		if value ~= 0 then			table.insert(texts, tostring(				mw.html.create("span")					:addClass("citron-spam-" .. key .. "-count")					:wikitext(value)				))		end	end		return table.concat(texts, " · ")endlocal function createHostnameListNode(title, node, hostnames, revisions, reportDate, id, feedbacks)	if #hostnames == 0 then		return nil	end		node		:node(			mw.html.create("div")				:addClass("citron-spam-content-title-placeholder mw-collapsible"					.. (id:find("uncertain") and " mw-collapsed" or ""))				:css("position", "absolute")				:attr("id", "mw-customcollapsible-" .. id)		)		:node(			mw.html.create("div")				:addClass("citron-spam-content-title-wrapper mw-customtoggle-" .. id)				:node(					mw.html.create("div")						:addClass("citron-spam-content-title")						:wikitext(title .. " (" .. #hostnames .. ")")				)				:node(					mw.html.create("div")						:addClass("citron-spam-content-feedback-stats")						:wikitext(statsText(hostnames, feedbacks))				)		)	for _, hostname in ipairs(hostnames) do		-- .citron-spam-hostname-inner-bottom		local hostnameInnerBottomNode = mw.html.create("div")			:addClass("citron-spam-hostname-inner-bottom mw-collapsible mw-collapsed")			:attr("id", "mw-customcollapsible-citron-" .. reportDate)		for _, revisionId in ipairs(hostname.revisionIds) do			local revision = revisions[revisionId]		    hostnameInnerBottomNode		    	:node(		    		mw.html.create("div")		    			:addClass("citron-spam-revision")		    			:wikitext(		    				"[[Special:Contributions/"			    				.. revision.user			    				.. "|"			    				.. revision.user			    				.. "]] ([[Special:Diff/"			    				.. revisionId			    				.. "|"			    				.. revision.page			    				.. "]])"		    			)		    	)		end				-- .citron-spam-feedbacks		local feedbacksNode = mw.html.create("div")			:addClass("citron-spam-feedbacks")		local feedbacksCount = 0		for _, feedback in ipairs(feedbacks) do			if feedback.hostname == hostname.hostname then				feedbacksCount = feedbacksCount + 1				feedbacksNode:node(					mw.html.create("div")						:addClass("citron-spam-feedback "							.. (feedback.status == 0								and "citron-spam-feedback-good" 								or "citron-spam-feedback-bad"))						:attr("title", feedback.createdAt)						:node(mw.html.create("span")							:addClass("citron-spam-feedback-icon"))						:node(mw.html.create("span")							:addClass("citron-spam-feedback-user")							:wikitext(feedback.user))				)			end		end		local statusClass, bgHostnameInnerTopLeftStart, bgHostnameInnerTopLeftEnd		if hostname.score >= 0.8 then		    statusClass = "citron-spam-very-bad"		    bgHostnameInnerTopLeftStart = "var(--background-color-destructive-subtle--hover, #ffdad3)"		    bgHostnameInnerTopLeftEnd = "var(--background-color-destructive-subtle, #ffe9e5)"		elseif hostname.score >= 0.5 then		    statusClass = "citron-spam-bad"		    bgHostnameInnerTopLeftStart = "light-dark(#ffdcb8, #572c19)"		    bgHostnameInnerTopLeftEnd = "light-dark(#ffead4, #361d13)"		else		    statusClass = "citron-spam-uncertain"		    bgHostnameInnerTopLeftStart = "var(--background-color-progressive-subtle--hover, #dce3f9)"		    bgHostnameInnerTopLeftEnd = "var(--background-color-progressive-subtle, #f1f4fd)"		end		local added = isAdded(hostname.hostname)		local addedClass = added and "citron-spam-added" or "citron-spam-not-added"		local addedText = added and "Đã thêm" or "Chưa thêm"		local score = string.format("%.0f%%", hostname.score * 100)    	node    		:node(    			mw.html.create("div")    				:addClass("citron-spam-hostname mw-collapsible"    					.. (id:find("uncertain") and " mw-collapsed" or ""))    				:attr("id", "mw-customcollapsible-" .. id)    				:node(    					mw.html.create("div")    						:addClass("citron-spam-hostname-time")    						:wikitext(hostname.time)    				)    				:node(    					mw.html.create("div")    						:addClass("citron-spam-hostname-inner")    						:attr("data-added", tostring(added))    						:node(    							mw.html.create("div")    								:addClass("citron-spam-hostname-inner-top")									:css("--percentage", score)									:css("--background-hostname-inner-top-left-start", bgHostnameInnerTopLeftStart)									:css("--background-hostname-inner-top-left-end", bgHostnameInnerTopLeftEnd)									:css("--background-hostname-inner-top-left",										"linear-gradient(to right, var(--background-hostname-inner-top-left-start) var(--percentage), var(--background-hostname-inner-top-left-end) var(--percentage))")    								:node(    									mw.html.create("div")    										:addClass("citron-spam-hostname-inner-top-left "    											.. statusClass)    										:node(    											mw.html.create("div")    												:addClass("citron-spam-hostname-hostname")    												:wikitext(hostname.hostname)    										)    										:node(    											mw.html.create("div")    												:addClass("citron-spam-hostname-score")		    										:wikitext(score)    										)    								)    								:node(    									mw.html.create("div")    										:addClass("citron-spam-hostname-inner-top-right")    										:node(feedbacksCount ~= 0     											and feedbacksNode    											or nil)    										:node(    											mw.html.create("div")    												:addClass("citron-spam-hostname-status "    													.. addedClass)		    										:wikitext(addedText)    										)    								)    						)    						:node(hostnameInnerBottomNode)    				)    		)	end		return nodeendlocal function createReport(date)	local today = os.date("%Y-%m-%d") == date;    local title = mw.title.new("Project:Citron/Spam/" .. date .. ".json")    local content = title:getContent()    local wrapperNode = mw.html.create("div")        :addClass("citron-spam-wrapper")        :node(        	mw.html.create("div")        		:addClass("citron-spam-header")        		:node(        			mw.html.create("div")        				:addClass("citron-spam-title")        				:wikitext("[[Project:Citron/Spam|Citron · Spam]]")        		)        		:node(					mw.html.create("div")						:addClass("citron-spam-actions")						:node(							mw.html.create("span")								:addClass("mw-customtoggle-citron-" .. date)								:wikitext("Xem phiên bản")						)						:node(							today							and mw.html.create("span")									:addClass("citron-spam-support")									:attr("data-date", date)									:wikitext("Hỗ trợ đánh giá")							or nil						)						:node(		        			mw.html.create("span")		        				:addClass("citron-spam-date")		        				:wikitext(		        					"[[Project:Citron/Spam/"			        					.. date			        					.. ".json|"			        					.. date			        					.. "]]"		        				)		        		)				)        )    if content == nil then    	wrapperNode:node(    		mw.html.create("div")    			:addClass("citron-spam-empty")    			:wikitext("Không có báo cáo tại thời điểm được cung cấp")    	)		return tostring(wrapperNode)    end    local data = mw.text.jsonDecode(content)    local very_bad_hostnames = {}	local bad_hostnames = {}	local uncertain_hostnames = {}	for _, hostname in ipairs(data.hostnames) do	    if hostname.score >= 0.8 then	        table.insert(very_bad_hostnames, hostname)	    elseif hostname.score >= 0.5 then	        table.insert(bad_hostnames, hostname)	    else	        table.insert(uncertain_hostnames, hostname)	    end	end	local contentVeryBadNode = createHostnameListNode(		"Có khả năng rất cao là xấu",		mw.html.create("div"):addClass("citron-spam-content"),		very_bad_hostnames,		data.revisions,		date,		"citron-" .. date .. "-very-bad",		data.feedbacks	)	local contentBadNode = createHostnameListNode(		"Có khả năng cao là xấu",		mw.html.create("div"):addClass("citron-spam-content"),		bad_hostnames,		data.revisions,		date,		"citron-" .. date .. "-bad",		data.feedbacks	)	local contentUncertainNode = createHostnameListNode(		"Chưa chắc chắn",		mw.html.create("div"):addClass("citron-spam-content"),		uncertain_hostnames,		data.revisions,		date,		"citron-" .. date .. "-uncertain",		data.feedbacks	)	if #data.hostnames > 0 then		wrapperNode:node(contentVeryBadNode)		wrapperNode:node(contentBadNode)		wrapperNode:node(contentUncertainNode)	else    	wrapperNode:node(    		mw.html.create("div")    			:addClass("citron-spam-empty")    			:wikitext("Chưa có dữ liệu")    	)	end	wrapperNode		:node(			mw.html.create("div")				:addClass("citron-spam-footer")				:node(					mw.html.create("div")						:addClass("citron-spam-last-update")						:wikitext(							"Cập nhật lúc "							.. lang:formatDate("H:i, j F, Y", data.updatedAt)							.. " (UTC). Truy cập [[Special:BlockedExternalDomains|Tên miền bị chặn]]. "							.. tostring(								mw.html.create("span")									:addClass("citron-spam-info")									:wikitext("[[:vi:User:Plantaest/Citron|ⓘ]]")							)						)				)				:node(					mw.html.create("div")						:addClass("citron-spam-status")						:attr("data-today", tostring(today))						:wikitext(today and "Đang cập nhật" or "Kết thúc cập nhật")				)		)    return tostring(wrapperNode)endlocal function createTemplatestylesNode()    return mw.getCurrentFrame():extensionTag{		name = "templatestyles", args = { src = "Module:Citron/Spam/styles.css" }	}endfunction p.report(frame)    local date = frame.args["date"]    return createTemplatestylesNode() .. createReport(date)endfunction p.main(frame)	local dates = {}	local reports = {}	for i = 0, 6 do		table.insert(			dates,			lang:formatDate("Y-m-d", "-" .. i .. " days")		)	end		for _, date in ipairs(dates) do		table.insert(reports, createReport(date))	end	return createTemplatestylesNode() .. table.concat(reports, "\n")endreturn p