local module = {} local getArgs = require('Module:Arguments').getArgs local getCode = require('Module:GetPageCode') local wrappers = { 'Template:大召唤术', 'Template:大召唤术/群组' } -- 可匹配多个正则。 mw.ustring.gsub_m = function(s, patterns, repl, n) local length = mw.ustring.len(s) local init = 1 local v1, v2 local i = 0 local ss = {} while (n == nil or i < n) and init < length do v1, v2 = length + 1, length local p = nil for _, pattern in ipairs(patterns) do local v3, v4 = mw.ustring.find(s, pattern, init, false) if v3 ~= nil and (v3 < v1 or (v3 == v1 and v4 <= v2)) then v1, v2 = v3, v4 -- 更新匹配范围。 p = pattern -- 更新使用的正则。 end end if p ~= nil then table.insert(ss, mw.ustring.sub(s, init, v1 - 1)) local new_s = mw.ustring.gsub(mw.ustring.sub(s, v1, v2), p, repl, 1) -- 调用原生替换函数。 table.insert(ss, new_s) else break end init = v2 + 1 i = i + 1 end table.insert(ss, mw.ustring.sub(s, init)) return table.concat(ss) end -- 一个值是否在表里。 table.has = function(table, value) for _, item in ipairs(table) do if value == item then return true end end end function module._main(args, frame) local users = nil local users_show = {} local group = args['group'] or args['群组'] or args['群組'] or '' local filter = args['filter'] or args['筛选'] or args['篩選'] or '' local offset = tonumber(args['offset']) or 0 local page = mw.title.new(group) or mw.title.new('Module:UserGroup') -- 过滤掉含有不能使用字符的标题。 if page.exists then if page.contentModel == "Scribunto" then -- 页面存在且页面内容模型为Lua源码,尝试获取枚举接口。 local success = nil success, users = pcall(function(p, f) local _mod = require(tostring(p)) if type(_mod.enumerate) == 'function' then -- 接口正确。 local _list = _mod.enumerate(f) if type(_list) == 'table' then -- 接口返回值正确。 return _list end end return nil -- 接口错误,或接口返回值错误。 end, page, filter) if not success then users = nil end -- 通过接口获取返回值过程中发生错误而失败。 end page = tostring(page) else page = tostring(mw.title.makeTitle('Template', tostring(page))) -- 页面不存在默认添加Template名字空间。 end if users == nil then -- 若已通过接口获取过Module页面提供的用户列表,则不对其代码进行识别。 users = {} local code = getCode(page) -- 构造正则列表。 local templates = { 'User', 'Supu', 'Supuc' } local patterns = { '%[%[%s*[Uu][Ss][Ee][Rr]%s*:([^|%]/\\]+)%]%]', -- 匹配[[User:XXX]]。 '%[%[%s*[Uu][Ss][Ee][Rr]%s*:([^|%]/\\]+)|.-%]%]', -- 匹配[[User:XXX|YYYY]]。 } for _, template in ipairs(templates) do -- 将模板名中首位西文字母替换为正则表达式“[【大写】【小写】]”。 template = mw.ustring.gsub(template, '^%a', function(letter) return '[' .. mw.ustring.upper(letter) .. mw.ustring.lower(letter) .. ']' end) table.insert(patterns, '{{%s*' .. template .. '%s*|([^|}/\\]+)}}') -- 匹配{{【模板名】:XXX}}模板。 table.insert(patterns, '{{%s*' .. template .. '%s*|([^|}/\\]+)|.-}}') -- 匹配{{【模板名】:XXX|YYYY}}模板。 end for _, alias in ipairs(mw.site.namespaces['User'].aliases) do -- 将别名中所有西文字母替换为正则表达式“[【大写】【小写】]”。 alias = mw.ustring.gsub(alias, '%a', function(letter) return '[' .. mw.ustring.upper(letter) .. mw.ustring.lower(letter) .. ']' end) table.insert(patterns, '%[%[%s*' .. alias .. '%s*:([^|%]/\\]+)%]%]') -- 匹配[[【User名字空间的别名】:XXX]]。 table.insert(patterns, '%[%[%s*' .. alias .. '%s*:([^|%]/\\]+)|.-%]%]') -- 匹配[[【User名字空间的别名】:XXX|YYYY]]。 end mw.ustring.gsub_m(code, patterns, function(name) name = tostring(mw.title.new(name) or name) -- 标准化。 if users[name] == nil then users[name] = true -- 标志已存在这个用户名。 users[#users + 1] = name end end) end local except = args[1] or args['except'] or args['除去'] or '' for name in mw.text.gsplit(except, ',') do name = tostring(mw.title.new(name) or name) -- 标准化。 users[name] = false -- 标志除去这个用户名。 end for i = #users, 1, -1 do if users[users[i]] == false then table.remove(users, i) end end -- 由于表中无用的标志会被expandTemplate识别为调用参数,因此需要清除,保留键为正整数的键值对。 for k, _ in pairs(users) do if type(k) ~= "number" then users[k] = nil end end -- 分页召唤群组成员 local msg ="" if offset ~= 0 then if (offset-1)*50 >= #users then msg = '<span style="color:red;font-weight:bold;">offset过大,无可召唤用户!</span>' elseif offset*50 <= #users then for i=(offset-1)*50+1,offset*50,1 do table.insert(users_show, users[i]) end msg = string.format("(%d~%d)", (offset-1)*50+1, offset*50) else for i=(offset-1)*50+1,#users,1 do table.insert(users_show, users[i]) end msg = string.format("(%d~%d)", (offset-1)*50+1, #users) end else if #users>50 then for i=1,50,1 do table.insert(users_show, users[i]) msg = "(1~50)" end else for i=1,#users,1 do table.insert(users_show, users[i]) end end end return msg .. frame:expandTemplate{ title = 'Reply to', args = users_show } end function module.main(frame) local args = getArgs(frame, { trim = true, removeBlanks = false, valueFunc = function(key, value) if value == '' then return nil else return value end end, wrappers = wrappers }) if not mw.isSubsting() and (os.time() >= os.time({ year = 2020, month = 7, day = 22, hour = 16, minute = 0, second = 0 })) then local title = frame:getTitle() local caller = '调用模块[['..title..'|'..mw.title.new(title).text..']]' local parent = frame:getParent() if parent then title = parent:getTitle() if table.has(wrappers, title) then caller = '使用'..frame:expandTemplate{ title = 'Tl', args = { mw.title.new(title).text } } end end local time = frame:callParserFunction{ name = '#time', args = { 'Y年n月j日(D)H:i:s', '2020-7-23' } } return require('Module:Error').error({ '自'..time..'(CST)起,'..caller..'时必须被[[Help:替换引用|替换引用]]。[[Category:有脚本错误的页面]]' }) else return module._main(args, frame) end end return module