Module:Biobox: Difference between revisions
Jump to navigation
Jump to search
Content deleted Content added
PeaceDeadC (talk | contribs) No edit summary |
PeaceDeadC (talk | contribs) No edit summary |
||
| Line 399: | Line 399: | ||
local personalSection, rowIndex |
local personalSection, rowIndex |
||
local success, |
local success, result1, result2 = pcall(function() |
||
return BioboxPersonal.formatPersonalSection(state, args, title) |
return BioboxPersonal.formatPersonalSection(state, args, title) |
||
end) |
end) |
||
if success then |
if success then |
||
personalSection, rowIndex = |
personalSection, rowIndex = result1, result2 |
||
else |
else |
||
personalSection |
personalSection = string.format('{| %s\n|-\n! colspan="2" %s | \'\'\'%s\'\'\'', |
||
STYLES.INFOBOX, |
|||
STYLES.HEADER, |
|||
title) |
|||
rowIndex = 1 |
|||
end |
end |
||
local bodySection = "" |
local bodySection = "" |
||
success, |
success, result1 = pcall(function() |
||
return BioboxBody.formatBodySection(state, args, rowIndex) |
return BioboxBody.formatBodySection(state, args, rowIndex) |
||
end) |
end) |
||
if success then |
if success then |
||
bodySection = |
bodySection = result1 |
||
end |
end |
||
local personalPagesSection, ppRowIndex = {}, rowIndex |
local personalPagesSection, ppRowIndex = {}, rowIndex |
||
success, |
success, result1, result2 = pcall(function() |
||
return BioboxPersonalPages.formatPersonalPagesSection(state, args, rowIndex) |
return BioboxPersonalPages.formatPersonalPagesSection(state, args, rowIndex) |
||
end) |
end) |
||
if success then |
if success then |
||
personalPagesSection, ppRowIndex = |
personalPagesSection, ppRowIndex = result1, result2 |
||
end |
end |
||
local databasesSection, dbRowIndex = {}, ppRowIndex |
local databasesSection, dbRowIndex = {}, ppRowIndex |
||
success, |
success, result1, result2 = pcall(function() |
||
return BioboxDatabases.formatDatabasesSection(state, args, ppRowIndex) |
return BioboxDatabases.formatDatabasesSection(state, args, ppRowIndex) |
||
end) |
end) |
||
if success then |
if success then |
||
databasesSection, dbRowIndex = |
databasesSection, dbRowIndex = result1, result2 |
||
end |
end |
||
if isEmpty(personalSection) then |
if isEmpty(personalSection) or not string.find(personalSection, '{|%s+class="infoboxnew"') then |
||
personalSection = string.format('{| %s\n|-\n! colspan="2" %s | \'\'\'%s\'\'\'', |
personalSection = string.format('{| %s\n|-\n! colspan="2" %s | \'\'\'%s\'\'\'', |
||
STYLES.INFOBOX, |
STYLES.INFOBOX, |
||
Latest revision as of 00:22, 19 March 2025
Documentation for this module may be created at Module:Biobox/doc
local p = {}
local PBDIB = require('Module:PornBaseDataIB')
local CategoryMapping = require('Module:BioboxCategoryMapping')
local BioboxPersonal = require('Module:BioboxPersonal')
local BioboxBody = require('Module:BioboxBody')
local BioboxPersonalPages = require('Module:BioboxPersonalPages')
local BioboxDatabases = require('Module:BioboxDatabases')
local ALIAS_TO_PRIMARY = {}
do
for primary, aliases in pairs(CategoryMapping.PARAM_ALIASES) do
for _, alias in ipairs(aliases) do
ALIAS_TO_PRIMARY[alias] = primary
end
ALIAS_TO_PRIMARY[primary] = primary
end
end
local STYLES = {
INFOBOX = 'class="infoboxnew" align="left" cellspacing="1" cellpadding="1" style="text-align:center; font-size:88%; line-height:1.5em; white-space:normal;"',
HEADER = 'style="color:white; text-align:center; border: 1px solid white; background:#657D91; font-size:112%;"',
LABEL = 'width:40%; padding-left:0.1em; overflow-wrap: break-word; font-weight:normal; text-align:left;',
SECTION_HEADER = 'style="color:white; text-align:center; border: 1px solid white; background:#657D91; font-size:100%;"',
ODD_ROW = 'background-color:#F7F7F7;',
EVEN_ROW = 'background-color:white;'
}
local function isEmpty(value)
return value == nil or value == ''
end
local function isPositive(value)
if isEmpty(value) then return false end
value = tostring(value):lower()
local positiveValues = {
['yes'] = true,
['y'] = true,
['ya'] = true,
['yep'] = true,
['true'] = true,
['1'] = true
}
return positiveValues[value] or false
end
local POSITIVE_ONLY_FIELDS = {
['tattoo'] = true
}
local function normalizeKeys(args)
local normalized = {}
local seenParams = {}
local processedAliases = {}
local firstOccurrence = {}
for key, value in pairs(args) do
local normalizedKey = tostring(key):gsub(" ", "_"):lower()
local primaryKey = ALIAS_TO_PRIMARY[normalizedKey] or normalizedKey
if not firstOccurrence[primaryKey] then
firstOccurrence[primaryKey] = #seenParams + 1
end
table.insert(seenParams, {
key = key,
value = value,
normalizedKey = normalizedKey,
primaryKey = primaryKey,
position = firstOccurrence[primaryKey]
})
end
table.sort(seenParams, function(a, b)
return a.position < b.position
end)
for _, param in ipairs(seenParams) do
local primaryKey = param.primaryKey
if not processedAliases[primaryKey] then
if not isEmpty(param.value) then
normalized[primaryKey] = param.value
processedAliases[primaryKey] = true
elseif not normalized[primaryKey] then
normalized[primaryKey] = param.value
end
end
end
return normalized
end
local function isNumeric(value)
if type(value) == "number" then return true end
if type(value) ~= "string" then return false end
return tonumber(value) ~= nil
end
local function shouldDisplayField(fieldName, value)
if not isEmpty(value) then
if POSITIVE_ONLY_FIELDS[fieldName] then
return isPositive(value)
end
return true
end
return false
end
local function getPBDIBValue(propertyId, args, options)
if not args.qid or args.qid == "" then
return nil
end
local success, result = pcall(function()
return PBDIB._getValue({
[1] = propertyId,
qid = args.qid,
format = options and options.format,
fpbd = "ALL"
})
end)
if success then
return result
else
return nil
end
end
local function extractNumber(str)
if type(str) == 'number' then
return str
end
if type(str) ~= 'string' or str == '' then
return nil
end
local num = tonumber(str)
if num then return num end
num = str:match("^%s*(%d+%.?%d*)[%s%a]*$")
if num then return tonumber(num) end
num = str:match("^%s*(%d+%.?%d*)%a*$")
if num then return tonumber(num) end
num = str:match("^%s*(%d+,%d+)%s*$")
if num then return tonumber(num:gsub(",", ".")) end
return nil
end
local State = {}
function State:new()
local state = {}
setmetatable(state, self)
self.__index = self
state.STYLES = STYLES
return state
end
function State:getRowStyle(index)
return index % 2 == 1 and STYLES.ODD_ROW or STYLES.EVEN_ROW
end
function State:splitByComma(str)
if not str then return {} end
local result = {}
for value in str:gmatch("[^,]+") do
table.insert(result, mw.text.trim(value))
end
return result
end
function State:formatCategoryLink(value, prefix, displayText)
if isEmpty(value) then return nil end
local normalized = mw.text.trim(value):gsub("^%l", string.upper)
displayText = displayText or normalized
local result = string.format("[[:Category:%s%s|%s]]",
prefix,
normalized,
displayText
)
if mw.title.getCurrentTitle().namespace == 0 then
result = result .. string.format("[[Category:%s%s]]",
prefix,
normalized
)
end
return result
end
function State:collectNumberedParams(args, baseParam)
local values = {}
local numbered = {}
if not isEmpty(args[baseParam]) then
table.insert(values, {index = 0, value = args[baseParam]})
end
for param, value in pairs(args) do
local index = param:match("^" .. baseParam .. "(%d+)$")
if index and not isEmpty(value) then
index = tonumber(index)
if index and index > 0 and index < 100 then
table.insert(values, {index = index, value = value})
end
end
end
table.sort(values, function(a, b) return a.index < b.index end)
local result = {}
for _, item in ipairs(values) do
table.insert(result, item.value)
end
return result
end
function State:formatField(label, value, fieldName, index)
if isEmpty(value) then
return ''
end
if POSITIVE_ONLY_FIELDS[fieldName] and not isPositive(value) then
return ''
end
local rowStyle = self:getRowStyle(index)
return string.format('|-\n! style="%s %s" | \'\'\'%s\'\'\'\n| style="%s text-align:left;" | %s',
rowStyle,
STYLES.LABEL,
label,
rowStyle,
value)
end
function State:formatFeatureList(values, featureType)
if not values or #values == 0 then return nil end
local displayValues = {}
local addedCategories = {}
local isMainNamespace = mw.title.getCurrentTitle().namespace == 0
if featureType == 'foreskin' then
for _, value in ipairs(values) do
if value then
local feature = mw.text.trim(value):lower()
local mapping = CategoryMapping.MAPPINGS[featureType][feature]
if mapping then
local result = string.format("[[:Category:%s|%s]]",
mapping.category,
mapping.display
)
if isMainNamespace then
result = result .. string.format("[[Category:%s]]",
mapping.category
)
end
return result
end
end
end
return nil
end
if featureType == 'ass_type' then
local foundMappings = {}
local hasMainType = false
for _, value in ipairs(values) do
if value then
local features = self:splitByComma(value)
for _, feature in ipairs(features) do
feature = mw.text.trim(feature):lower()
for _, mapping in ipairs(CategoryMapping.MAPPINGS[featureType]) do
for _, alias in ipairs(mapping.aliases) do
if feature == alias:lower() then
local isMainSize = mapping.priority >= 1 and mapping.priority <= 3
if (not isMainSize or not hasMainType) and not addedCategories[mapping.category] then
table.insert(foundMappings, mapping)
addedCategories[mapping.category] = true
if isMainSize then
hasMainType = true
end
end
end
end
end
end
end
end
table.sort(foundMappings, function(a, b)
return a.priority < b.priority
end)
for i, mapping in ipairs(foundMappings) do
if i > 1 then
table.insert(displayValues, ", ")
end
local result = string.format("[[:Category:%s|%s]]",
mapping.category,
mapping.display
)
if isMainNamespace then
result = result .. string.format("[[Category:%s]]",
mapping.category
)
end
table.insert(displayValues, result)
end
else
for _, value in ipairs(values) do
if value then
local features = self:splitByComma(value)
for _, feature in ipairs(features) do
feature = mw.text.trim(feature):lower()
for _, mapping in ipairs(CategoryMapping.MAPPINGS[featureType]) do
local found = false
for _, alias in ipairs(mapping.aliases) do
if feature == alias:lower() then
found = true
if not addedCategories[mapping.category] then
if #displayValues > 0 then
table.insert(displayValues, ", ")
end
local result = string.format("[[:Category:%s|%s]]",
mapping.category,
mapping.display
)
if isMainNamespace then
result = result .. string.format("[[Category:%s]]",
mapping.category
)
end
table.insert(displayValues, result)
addedCategories[mapping.category] = true
end
break
end
end
if found then break end
end
end
end
end
end
if #displayValues > 0 then
return table.concat(displayValues)
end
return nil
end
function p.main(frame)
local args = frame.args
if not next(args) then
args = frame:getParent().args
end
args = normalizeKeys(args)
if isEmpty(args.qid) then
local success, entityId = pcall(mw.wikibase.getEntityIdForCurrentPage)
if success and entityId then
args.qid = entityId
else
args.qid = nil
end
end
local title = mw.title.getCurrentTitle().text
local state = State:new()
local personalSection, rowIndex
local success, result1, result2 = pcall(function()
return BioboxPersonal.formatPersonalSection(state, args, title)
end)
if success then
personalSection, rowIndex = result1, result2
else
personalSection = string.format('{| %s\n|-\n! colspan="2" %s | \'\'\'%s\'\'\'',
STYLES.INFOBOX,
STYLES.HEADER,
title)
rowIndex = 1
end
local bodySection = ""
success, result1 = pcall(function()
return BioboxBody.formatBodySection(state, args, rowIndex)
end)
if success then
bodySection = result1
end
local personalPagesSection, ppRowIndex = {}, rowIndex
success, result1, result2 = pcall(function()
return BioboxPersonalPages.formatPersonalPagesSection(state, args, rowIndex)
end)
if success then
personalPagesSection, ppRowIndex = result1, result2
end
local databasesSection, dbRowIndex = {}, ppRowIndex
success, result1, result2 = pcall(function()
return BioboxDatabases.formatDatabasesSection(state, args, ppRowIndex)
end)
if success then
databasesSection, dbRowIndex = result1, result2
end
if isEmpty(personalSection) or not string.find(personalSection, '{|%s+class="infoboxnew"') then
personalSection = string.format('{| %s\n|-\n! colspan="2" %s | \'\'\'%s\'\'\'',
STYLES.INFOBOX,
STYLES.HEADER,
title)
end
local result = personalSection .. '\n' .. bodySection
if #personalPagesSection > 0 then
result = result .. '\n' .. table.concat(personalPagesSection, '\n')
end
if #databasesSection > 0 then
result = result .. '\n' .. table.concat(databasesSection, '\n')
end
if not isEmpty(args.qid) then
local success, pbcLink = pcall(mw.wikibase.getSitelink, args.qid)
if success and pbcLink then
result = result .. '\n|-class="stop-section-collapse"\n! colspan="2" style="background:#F0E68C;text-align:center;" | [[File:Pbd.svg | 45px | alt=' .. args.qid .. ' | link=pbd:' .. args.qid .. ']] [[:pbd:' .. args.qid .. '|' .. pbcLink .. ']] ([[:pbd:' .. args.qid .. '|' .. args.qid .. ']])'
end
local newFrame = {
args = {
qid = args.qid,
wiki = "pbcimagerepo"
}
}
local imageRepoLink
success, imageRepoLink = pcall(function()
return PBDIB.getSiteLink(newFrame)
end)
if success and imageRepoLink and imageRepoLink ~= '' then
result = result .. '\n|-class="stop-section-collapse"\n! colspan="2" style="background:#F0E68C;text-align:center;" | [[File:Image-icon.svg | 18px | link=:' .. imageRepoLink .. ']] [[:' .. imageRepoLink .. '| PBC Image Repository]]'
end
newFrame.args.wiki = "pbcvideorepo"
local videoRepoLink
success, videoRepoLink = pcall(function()
return PBDIB.getSiteLink(newFrame)
end)
if success and videoRepoLink and videoRepoLink ~= '' then
result = result .. '\n|-class="stop-section-collapse"\n! colspan="2" style="background:#F0E68C;text-align:center;" | [[File:Video-icon.svg | 18px | link=:' .. videoRepoLink .. ']] [[:' .. videoRepoLink .. '| PBC Video Repository]]'
end
end
result = result .. '\n|}'
local categories = {}
if not isEmpty(args.qid) then
success, categories = pcall(function()
return BioboxPersonal.getPBDCategories(args)
end)
if not success then
categories = {}
end
end
if #categories > 0 then
local categoryStrings = {}
for _, category in ipairs(categories) do
table.insert(categoryStrings, '[[Category:' .. category .. ']]')
end
result = result .. '\n' .. table.concat(categoryStrings, '\n')
end
return result
end
return p