Module:RestrictedUse

From Bahaiworks

Documentation for this module may be created at Module:RestrictedUse/doc

-- Module:RestrictedUse

local p = {}

function p.main(frame)
    local mw = require('mw')
    local mWikibase = require('mw.wikibase')
    local getArgs = require('Module:Arguments').getArgs
    local args = getArgs(frame)

    local where = args['where']
    local until_year = args['until']

    local text = ""
    local categories = ""

    -- Initialize variables
    local countryLabel = where or "Unknown country"
    local expiryText = "unknown expiry date."

    -- Attempt to fetch missing data from Wikibase
    local entity = mWikibase.getEntityObject()
    if entity then
        -- Get country of origin (P48) if 'where' is not provided
        if not where or where == "" then
            countryLabel = p.getCountryLabel(entity)
        end

        -- Get 'until_year' if it's not provided
        if not until_year or until_year == "" then
            -- Get publication year (P50)
            local publicationYear = p.getPublicationYear(entity)

            -- Get author death year (P17)
            local deathYear = p.getAuthorDeathYear(entity)

            if deathYear then
                -- Calculate expiry date based on country's copyright term
                local expiryYear = p.calculateExpiryYear(countryLabel, deathYear, publicationYear)
                if expiryYear then
                    expiryText = "expires " .. expiryYear .. "."
                    -- Add category if expiry is within the next 5 years
                    local currentYear = tonumber(os.date("%Y"))
                    if expiryYear - currentYear <= 5 then
                        categories = categories .. "\n[[Category:Copyright term expiring soon]]"
                    end
                end
            end
        else
            expiryText = "expires " .. until_year .. "."
            -- Check if expiration is within next 5 years
            local currentYear = tonumber(os.date("%Y"))
            if tonumber(until_year) - currentYear <= 5 then
                categories = categories .. "\n[[Category:Copyright term expiring soon]]"
            end
        end
    end

    -- Build the message
    text = buildMessage(countryLabel, expiryText)

    -- Add category if country is unknown
    if countryLabel == "Unknown country" then
        categories = categories .. "\n[[Category:Works with unknown country in Restricted use template]]"
    end

    -- Add category if expiry date is unknown
    if expiryText == "unknown expiry date." then
        categories = categories .. "\n[[Category:Works with an unknown copyright expiry term]]"
    end

    -- Add [[Category:Restricted works]]
    categories = categories .. "\n[[Category:Restricted works]]"

    return text .. categories
end

function buildMessage(countryLabel, expiryText)
    local text = "'''Access to this work is restricted due to copyright. "

    if countryLabel and countryLabel ~= "" then
        text = text .. countryLabel .. ",&nbsp;"
    else
        text = text .. "Unknown country,&nbsp;"
    end

    if expiryText and expiryText ~= "" then
        text = text .. expiryText .. " '''<br />Use the search function to retrieve results. Direct questions [[Bahaiworks:Contact|here]]."
    else
        text = text .. "unknown expiry date. '''<br />Use the search function to retrieve results. Direct questions [[Bahaiworks:Contact|here]]."
    end

    return text
end

function p.getCountryLabel(entity)
    local mWikibase = require('mw.wikibase')
    local countryClaims = entity.claims and entity.claims['P48']
    if countryClaims then
        for _, claim in pairs(countryClaims) do
            local mainsnak = claim.mainsnak
            if mainsnak and mainsnak.datavalue and mainsnak.datavalue.value['id'] then
                local countryId = mainsnak.datavalue.value['id']
                local countryEntity = mWikibase.getEntity(countryId)
                if countryEntity and countryEntity.labels and countryEntity.labels['en'] then
                    return countryEntity.labels['en'].value
                end
            end
        end
    end
    return "Unknown country"
end

function p.getPublicationYear(entity)
    local publicationClaims = entity.claims and entity.claims['P50']
    if publicationClaims then
        for _, claim in pairs(publicationClaims) do
            local mainsnak = claim.mainsnak
            if mainsnak and mainsnak.datavalue and mainsnak.datavalue.value['time'] then
                local pubDate = mainsnak.datavalue.value['time']
                return tonumber(pubDate:match('^%+?(%d%d%d%d)'))
            end
        end
    end
    return nil
end

function p.getAuthorDeathYear(entity)
    local mWikibase = require('mw.wikibase')
    local authorProperties = {'P10', 'P43'}
    for _, prop in ipairs(authorProperties) do
        local authorClaims = entity.claims and entity.claims[prop]
        if authorClaims then
            for _, claim in pairs(authorClaims) do
                local mainsnak = claim.mainsnak
                if mainsnak and mainsnak.datavalue and mainsnak.datavalue.value['id'] then
                    local authorId = mainsnak.datavalue.value['id']
                    local authorEntity = mWikibase.getEntity(authorId)
                    local deathClaims = authorEntity and authorEntity.claims and authorEntity.claims['P17']
                    if deathClaims then
                        for _, deathClaim in pairs(deathClaims) do
                            local deathSnak = deathClaim.mainsnak
                            if deathSnak and deathSnak.datavalue and deathSnak.datavalue.value['time'] then
                                local deathDate = deathSnak.datavalue.value['time']
                                return tonumber(deathDate:match('^%+?(%d%d%d%d)'))
                            end
                        end
                    end
                end
            end
            -- If death year is found, no need to check other properties
            break
        end
    end
    return nil
end

function p.calculateExpiryYear(countryLabel, deathYear, publicationYear)
    local currentYear = tonumber(os.date("%Y"))

    if not deathYear then
        return nil
    end

    if countryLabel == 'Australia' then
        -- Changed to life+70 in 2005, not retroactive
        if deathYear >= 1955 then
            return deathYear + 70
        else
            return deathYear + 50
        end

    elseif countryLabel == 'Bangladesh' then
        -- Followed British colonial law, then life + 50 under 1962 law; stable since
        return deathYear + 50

    elseif countryLabel == 'Belgium' then
        -- Currently life+70
        return deathYear + 70

    elseif countryLabel == 'Canada' then
        -- Changed from life+50 to life+70 in 2022, but not retroactive
        if deathYear >= 1972 then
            return deathYear + 70
        else
            return deathYear + 50
        end

    elseif countryLabel == 'Switzerland' then
        -- Changed from life+50 to life+70 in 1993
        if deathYear >= 1943 then
            return deathYear + 70
        else
            return deathYear + 50
        end

    elseif countryLabel == 'Spain' then
        -- Life+80 for authors who died before 1987, life+70 after
        if deathYear < 1987 then
            return deathYear + 80
        else
            return deathYear + 70
        end

    elseif countryLabel == 'Ireland' then
        -- Changed from life+50 to life+70 in 1995 (EU harmonization)
        if deathYear >= 1945 then
            return deathYear + 70
        else
            return deathYear + 50
        end

    elseif countryLabel == 'India' then
        -- Originally life+50 (1957), changed to life+60 in 1992
        if deathYear >= 1932 then
            return deathYear + 60
        else
            return deathYear + 50
        end

    elseif countryLabel == 'Israel' then
        -- Changed from life+50 to life+70 in 2007 (not retroactive)
        if deathYear >= 1957 then
            return deathYear + 70
        else
            return deathYear + 50
        end

    elseif countryLabel == 'United Kingdom' then
        -- Varied over time; life+70 since 1995 (EU harmonization)
        if deathYear >= 1945 then
            return deathYear + 70
        else
            return deathYear + 50
        end

    elseif countryLabel == 'United States' then
        return p.calculateUSExpiryYear(publicationYear, deathYear)

    elseif countryLabel == 'Malaysia' then
        -- Changed from life+50 to life+70 in 2012 (not retroactive)
        if deathYear >= 1962 then
            return deathYear + 70
        else
            return deathYear + 50
        end

    elseif countryLabel == 'South Africa' then
        -- Life+50, stable for decades
        return deathYear + 50

    elseif countryLabel == 'Trinidad and Tobago' then
        -- Currently life+70; aligned with UK/EU standards post-independence
        return deathYear + 70

    elseif countryLabel == 'Taiwan' then
        -- Changed from life+50 to life+70 in 2003
        if deathYear >= 1933 then
            return deathYear + 70
        else
            return deathYear + 50
        end

    else
        -- Default term
        return deathYear + 70
    end
end

function p.calculateUSExpiryYear(publicationYear, deathYear)
    if not publicationYear then
        -- If publication year is unknown, default to life + 70
        if deathYear then
            return deathYear + 70
        else
            return nil
        end
    end

    if publicationYear < 1928 then
        -- Works published before 1928 are in the public domain
        return publicationYear
    elseif publicationYear >= 1928 and publicationYear <= 1963 then
        -- 28 years + 28-year renewal = 56 years
        return publicationYear + 56
    elseif publicationYear >= 1964 and publicationYear <= 1977 then
        -- Automatic 95 years
        return publicationYear + 95
    elseif publicationYear >= 1978 then
        -- Life of author + 70 years, or 95 years from publication if anonymous or work made for hire
        if deathYear then
            return deathYear + 70
        else
            return publicationYear + 95  -- Assume 95 years if death year is unknown
        end
    else
        -- Fallback to deathYear + 70
        if deathYear then
            return deathYear + 70
        else
            return nil
        end
    end
end

return p