https://en.wikipedia.org/w/index.php?action=history&feed=atom&title=Module%3AIPblock%2Fsandbox Module:IPblock/sandbox - Revision history 2025-05-26T04:49:05Z Revision history for this page on the wiki MediaWiki 1.45.0-wmf.2 https://en.wikipedia.org/w/index.php?title=Module:IPblock/sandbox&diff=810439138&oldid=prev Johnuniq: announce new release 2017-11-15T07:01:56Z <p>announce new release</p> <table style="background-color: #fff; color: #202122;" data-mw="interface"> <col class="diff-marker" /> <col class="diff-content" /> <col class="diff-marker" /> <col class="diff-content" /> <tr class="diff-title" lang="en"> <td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">← Previous revision</td> <td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">Revision as of 07:01, 15 November 2017</td> </tr><tr> <td colspan="2" class="diff-lineno">Line 978:</td> <td colspan="2" class="diff-lineno">Line 978:</td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local lines = Collection.new()</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local lines = Collection.new()</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if not options.noannounce then</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if not options.noannounce then</div></td> </tr> <tr> <td class="diff-marker" data-marker="−"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> -- Commented out April 2016 as expired.</div></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> --<ins style="font-weight: bold; text-decoration: none;"> 1:</ins> Commented out April 2016 as expired.</div></td> </tr> <tr> <td class="diff-marker" data-marker="−"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> -- lines:add("'''Please see [[Template talk:Blockcalc#Version February 2016|this announcement]].'''")</div></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> --<ins style="font-weight: bold; text-decoration: none;"> 1:</ins> lines:add("'''Please see [[Template talk:Blockcalc#Version February 2016|this announcement]].'''")</div></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> lines:add("'''By default, links now use [[Special:Contributions]] per [[Template talk:IP range calculator#Version November 2017|this announcement]].'''")</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> process_ips(lines, v4list, v4omitted)</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> process_ips(lines, v4list, v4omitted)</div></td> </tr> </table> Johnuniq https://en.wikipedia.org/w/index.php?title=Module:IPblock/sandbox&diff=810284000&oldid=prev Johnuniq: first draft to use Special:Contributions 2017-11-14T09:48:05Z <p>first draft to use Special:Contributions</p> <table style="background-color: #fff; color: #202122;" data-mw="interface"> <col class="diff-marker" /> <col class="diff-content" /> <col class="diff-marker" /> <col class="diff-content" /> <tr class="diff-title" lang="en"> <td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">← Previous revision</td> <td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">Revision as of 09:48, 14 November 2017</td> </tr><tr> <td colspan="2" class="diff-lineno">Line 44:</td> <td colspan="2" class="diff-lineno">Line 44:</td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local key = code .. months</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local key = code .. months</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if not timestamps[key] then</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if not timestamps[key] then</div></td> </tr> <tr> <td class="diff-marker" data-marker="−"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> -- A local test can set the global variable to produce fixed results.</div></td> <td colspan="2" class="diff-empty diff-side-added"></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local date = os.date('!*t') -- today's UTC date</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local date = os.date('!*t') -- today's UTC date</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local y, m, d = date.year, date.month, date.day -- full year, month (1-12), day (1-31)</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local y, m, d = date.year, date.month, date.day -- full year, month (1-12), day (1-31)</div></td> </tr> <tr> <td colspan="2" class="diff-lineno">Line 616:</td> <td colspan="2" class="diff-lineno">Line 615:</td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- or return an empty string if cannot do anything useful.</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- or return an empty string if cannot do anything useful.</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- The given address is a string of either a single IP or a CIDR range.</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- The given address is a string of either a single IP or a CIDR range.</div></td> </tr> <tr> <td class="diff-marker" data-marker="−"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> -- For IPv6 CIDR, return a Special:Contributions link using an asterisk</div></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> --<ins style="font-weight: bold; text-decoration: none;"> If using old system:</ins></div></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> -- </ins> For IPv6 CIDR, return a Special:Contributions link using an asterisk</div></td> </tr> <tr> <td class="diff-marker" data-marker="−"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> -- wildcard which should work if the user has enabled the gadget</div></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> --<ins style="font-weight: bold; text-decoration: none;"> </ins> wildcard which should work if the user has enabled the gadget</div></td> </tr> <tr> <td class="diff-marker" data-marker="−"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> -- "Allow /16, /24 and /27 – /32 CIDR ranges on Special:Contributions".</div></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> --<ins style="font-weight: bold; text-decoration: none;"> </ins> "Allow /16, /24 and /27 – /32 CIDR ranges on Special:Contributions".</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local encoded, count = address:gsub('/', '%%2F')</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local encoded, count = address:gsub('/', '%%2F')</div></td> </tr> <tr> <td class="diff-marker" data-marker="−"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> if count &gt; 0 then</div></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> if<ins style="font-weight: bold; text-decoration: none;"> strings.want_old and</ins> count &gt; 0 then</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> make_note(strings, 'range')</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> make_note(strings, 'range')</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if address:find(':', 1, true) then</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if address:find(':', 1, true) then</div></td> </tr> <tr> <td colspan="2" class="diff-lineno">Line 843:</td> <td colspan="2" class="diff-lineno">Line 843:</td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local strings = iplist.want_plain and plaintext or wikitable</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local strings = iplist.want_plain and plaintext or wikitable</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> strings.notes = nil -- needed when module is kept loaded for multiple tests</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> strings.notes = nil -- needed when module is kept loaded for multiple tests</div></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> strings.want_old = iplist.want_old</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> strings.nonote = iplist.nonote</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> strings.nonote = iplist.nonote</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> strings.months = iplist.months</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> strings.months = iplist.months</div></td> </tr> <tr> <td colspan="2" class="diff-lineno">Line 873:</td> <td colspan="2" class="diff-lineno">Line 874:</td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> options.comment = args.comment</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> options.comment = args.comment</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> -- Parameter 'months' is only used if 'old' is also used.</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local months = math.floor(tonumber(args.months) or tonumber(args.month) or 1)</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local months = math.floor(tonumber(args.months) or tonumber(args.month) or 1)</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if months &lt; 1 then</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if months &lt; 1 then</div></td> </tr> <tr> <td colspan="2" class="diff-lineno">Line 906:</td> <td colspan="2" class="diff-lineno">Line 908:</td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- If an argument matches k, an option named v is set to true.</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- If an argument matches k, an option named v is set to true.</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> ok = 'noannounce',</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> ok = 'noannounce',</div></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> old = 'want_old',</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> nolist = 'nolist',</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> nolist = 'nolist',</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> nonote = 'nonote',</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> nonote = 'nonote',</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> text = 'text',</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> text = 'text',</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> }</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> }</div></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> local want_old</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> for i, arg in ipairs(args) do</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> for i, arg in ipairs(args) do</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local flag = keywords[arg:match('^%s*(%w+)%s*$')]</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local flag = keywords[arg:match('^%s*(%w+)%s*$')]</div></td> </tr> <tr> <td colspan="2" class="diff-lineno">Line 915:</td> <td colspan="2" class="diff-lineno">Line 919:</td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> options[i] = 'skip'</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> options[i] = 'skip'</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> options[flag] = true</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> options[flag] = true</div></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> if flag == 'want_old' then</div></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> want_old = true</div></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> if not want_old then</div></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> options.nonote = true</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> return options</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> return options</div></td> </tr> <tr> <td colspan="2" class="diff-lineno">Line 939:</td> <td colspan="2" class="diff-lineno">Line 949:</td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> v6list.minsize = 19 -- or /19 for IPv6 ($wgBlockCIDRLimit)</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> v6list.minsize = 19 -- or /19 for IPv6 ($wgBlockCIDRLimit)</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> </tr> <tr> <td class="diff-marker" data-marker="−"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> for _, k in ipairs({'maxresults', 'months', 'nolist', 'nonote'}) do</div></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> for _, k in ipairs({'maxresults', 'months<ins style="font-weight: bold; text-decoration: none;">', 'want_old</ins>', 'nolist', 'nonote'}) do</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> v4list[k] = options[k]</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> v4list[k] = options[k]</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> v6list[k] = options[k]</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> v6list[k] = options[k]</div></td> </tr> </table> Johnuniq https://en.wikipedia.org/w/index.php?title=Module:IPblock/sandbox&diff=809919418&oldid=prev Johnuniq: clean-up prior to fixing to use new ranges ability of Special:Contributions 2017-11-12T09:28:28Z <p>clean-up prior to fixing to use new ranges ability of <a href="/wiki/Special:Contributions" title="Special:Contributions">Special:Contributions</a></p> <a href="//en.wikipedia.org/w/index.php?title=Module:IPblock/sandbox&amp;diff=809919418&amp;oldid=717169640">Show changes</a> Johnuniq https://en.wikipedia.org/w/index.php?title=Module:IPblock/sandbox&diff=717169640&oldid=prev Johnuniq: show contribs link for IPv6 ranges (user must enable gadget); show notes for contribs links including age of contribs; can set age with months=N; disable "ok" for now as not needed 2016-04-26T04:06:25Z <p>show contribs link for IPv6 ranges (user must enable gadget); show notes for contribs links including age of contribs; can set age with months=N; disable &quot;ok&quot; for now as not needed</p> <a href="//en.wikipedia.org/w/index.php?title=Module:IPblock/sandbox&amp;diff=717169640&amp;oldid=702381574">Show changes</a> Johnuniq https://en.wikipedia.org/w/index.php?title=Module:IPblock/sandbox&diff=702381574&oldid=prev Johnuniq: fix pre tags for plain text 2016-01-30T06:08:38Z <p>fix pre tags for plain text</p> <table style="background-color: #fff; color: #202122;" data-mw="interface"> <col class="diff-marker" /> <col class="diff-content" /> <col class="diff-marker" /> <col class="diff-content" /> <tr class="diff-title" lang="en"> <td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">← Previous revision</td> <td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">Revision as of 06:08, 30 January 2016</td> </tr><tr> <td colspan="2" class="diff-lineno">Line 675:</td> <td colspan="2" class="diff-lineno">Line 675:</td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> )</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> )</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> -- Pre tags returned by a module are html tags, not like wikitext &lt;pre&gt;...&lt;/pre&gt;.</div></td> </tr> <tr> <td class="diff-marker" data-marker="−"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> lines:add(s)</div></td> <td colspan="2" class="diff-empty diff-side-added"></td> </tr> <tr> <td colspan="2" class="diff-empty diff-side-deleted"></td> <td class="diff-marker" data-marker="+"></td> <td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div> lines:add(want_plain and mw.text.nowiki(s) or s)</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td> </tr> <tr> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>end</div></td> <td class="diff-marker"></td> <td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>end</div></td> </tr> </table> Johnuniq https://en.wikipedia.org/w/index.php?title=Module:IPblock/sandbox&diff=702332102&oldid=prev Johnuniq: major upgrade: IPv4 and IPv6; look for best summary; results in a table 2016-01-29T22:52:19Z <p>major upgrade: IPv4 and IPv6; look for best summary; results in a table</p> <p><b>New page</b></p><div>-- Calculate the minimum-sized blocks of IP addresses that covers each<br /> -- IPv4 or IPv6 address entered in the arguments.<br /> <br /> local bit32 = require(&#039;bit32&#039;)<br /> <br /> local function collection()<br /> -- Return a table to hold items.<br /> return {<br /> n = 0,<br /> add = function (self, item)<br /> self.n = self.n + 1<br /> self[self.n] = item<br /> end,<br /> join = function (self, sep)<br /> return table.concat(self, sep)<br /> end,<br /> remove = function (self, pos)<br /> if self.n &gt; 0 and (pos == nil or (0 &lt; pos and pos &lt;= self.n)) then<br /> self.n = self.n - 1<br /> return table.remove(self, pos)<br /> end<br /> end,<br /> sort = function (self, comp)<br /> table.sort(self, comp)<br /> end,<br /> }<br /> end<br /> <br /> local function empty(text)<br /> -- Return true if text is nil or empty (assuming a string).<br /> return text == nil or text == &#039;&#039;<br /> end<br /> <br /> local function describe_total(total, isalloc)<br /> -- Return text describing given number of addresses or /64 allocations.<br /> if total &lt;= 9999 then<br /> -- Can have fractions if total is the number of /64 allocations.<br /> if total &lt; 9 then<br /> return (string.format(&#039;%.1f&#039;, total):gsub(&#039;%.0$&#039;, &#039;&#039;))<br /> end<br /> return string.format(&#039;%.0f&#039;, total)<br /> end<br /> if not isalloc then<br /> local alloc = 2^64<br /> if total &gt;= alloc then<br /> return describe_total(total / alloc, true) .. &#039; /64&#039;<br /> end<br /> end<br /> total = total/1024<br /> local suffix = &#039;K&#039;<br /> if total &gt;= 1024 then<br /> total = total/1024<br /> suffix = &#039;M&#039;<br /> if total &gt;= 1024 then<br /> total = total/1024<br /> suffix = &#039;G&#039;<br /> if total &gt; 64 then<br /> return &#039;&gt;64G&#039;<br /> end<br /> end<br /> end<br /> return string.format(&#039;%.0f&#039;, total) .. suffix<br /> end<br /> <br /> local function describe_size(ipsize, size)<br /> -- Return text describing how many IPs are in a range with size = prefix length.<br /> local function numtext(n)<br /> if n &lt;= 16 then<br /> return tostring(2^n)<br /> end<br /> if n &lt;= 19 then<br /> return tostring(2^(n - 10)) .. &#039;K&#039;<br /> end<br /> if n &lt;= 29 then<br /> return tostring(2^(n - 20)) .. &#039;M&#039;<br /> end<br /> if n &lt;= 36 then<br /> return tostring(2^(n - 30)) .. &#039;G&#039;<br /> end<br /> return &#039;&gt;64G&#039;<br /> end<br /> local host = ipsize - size<br /> if host &lt;= 32 then<br /> -- IPv4 or IPv6.<br /> return numtext(host)<br /> end<br /> -- Must be IPv6.<br /> if host &lt;= 64 then<br /> local s = ({<br /> [64] = &#039;1&#039;, [63] = &#039;50%&#039;, [62] = &#039;25%&#039;, [61] = &#039;12%&#039;,<br /> [60] = &#039;6%&#039;, [59] = &#039;3%&#039;, [58] = &#039;2%&#039;<br /> })[host] or &#039;&lt;1%&#039;<br /> return s .. &#039; /64&#039;<br /> end<br /> -- IPv6 with size &lt; 64.<br /> return numtext(host - 64) .. &#039; /64&#039;<br /> end<br /> <br /> local function ipv6_string(ip)<br /> -- Return a string equivalent to given IPv6 address.<br /> local z1, z2 -- indices of run of zeros to be displayed as &quot;::&quot;<br /> local zstart, zcount<br /> for i = 1, 9 do<br /> -- Find left-most occurrence of longest run of two or more zeros.<br /> if i &lt; 9 and ip[i] == 0 then<br /> if zstart then<br /> zcount = zcount + 1<br /> else<br /> zstart = i<br /> zcount = 1<br /> end<br /> else<br /> if zcount and zcount &gt; 1 then<br /> if not z1 or zcount &gt; z2 - z1 + 1 then<br /> z1 = zstart<br /> z2 = zstart + zcount - 1<br /> end<br /> end<br /> zstart = nil<br /> zcount = nil<br /> end<br /> end<br /> local parts = collection()<br /> for i = 1, 8 do<br /> if z1 and z1 &lt;= i and i &lt;= z2 then<br /> if i == z1 then<br /> if z1 == 1 or z2 == 8 then<br /> if z1 == 1 and z2 == 8 then<br /> return &#039;::&#039;<br /> end<br /> parts:add(&#039;:&#039;)<br /> else<br /> parts:add(&#039;&#039;)<br /> end<br /> end<br /> else<br /> parts:add(string.format(&#039;%x&#039;, ip[i]))<br /> end<br /> end<br /> return table.concat(parts, &#039;:&#039;)<br /> end<br /> <br /> local function ip_string(ip)<br /> -- Return a string equivalent to given IP address (IPv4 or IPv6).<br /> local floor = math.floor<br /> local parts = {}<br /> if ip.n == 2 then<br /> -- IPv4.<br /> for i = 1, 2 do<br /> local w = ip[i]<br /> local q = i == 1 and 1 or 3<br /> parts[q] = floor(w / 256)<br /> parts[q+1] = w % 256<br /> end<br /> return table.concat(parts, &#039;.&#039;)<br /> end<br /> return ipv6_string(ip)<br /> end<br /> <br /> -- Metatable for some operations on IP addresses.<br /> local ipmt = {<br /> __eq = function (lhs, rhs)<br /> -- Return true if values in numbered tables match.<br /> if lhs.n == rhs.n then<br /> for i = 1, lhs.n do<br /> if lhs[i] ~= rhs[i] then<br /> return false<br /> end<br /> end<br /> return true<br /> end<br /> return false<br /> end,<br /> __lt = function (lhs, rhs)<br /> -- Return true if lhs &lt; rhs; for sort.<br /> if lhs.n == rhs.n then<br /> for i = 1, lhs.n do<br /> if lhs[i] ~= rhs[i] then<br /> return lhs[i] &lt; rhs[i]<br /> end<br /> end<br /> return false<br /> end<br /> return lhs.n &lt; rhs.n -- sort IPv4 before IPv6, although not needed<br /> end,<br /> }<br /> <br /> local function ipv4_address(ip_str)<br /> -- Return a collection of two 16-bit words (numbers) equivalent<br /> -- to the IPv4 address given as a quad-dotted string, or<br /> -- return nil if invalid.<br /> -- This representation is for compatibility with IPv6 addresses.<br /> local parts = collection()<br /> local s = ip_str:match(&#039;^%s*(.-)%s*$&#039;) .. &#039;.&#039;<br /> for item in s:gmatch(&#039;(.-)%.&#039;) do<br /> parts:add(item)<br /> end<br /> if parts.n == 4 then<br /> for i, s in ipairs(parts) do<br /> if s:match(&#039;^%d+$&#039;) then<br /> local num = tonumber(s)<br /> if 0 &lt;= num and num &lt;= 255 then<br /> if num &gt; 0 and s:match(&#039;^0&#039;) then<br /> -- A redundant leading zero is an error because it is for an IP in octal.<br /> return nil<br /> end<br /> parts[i] = num<br /> else<br /> return nil<br /> end<br /> else<br /> return nil<br /> end<br /> end<br /> local result = collection()<br /> for i = 1, 3, 2 do<br /> result:add(parts[i] * 256 + parts[i+1])<br /> end<br /> return setmetatable(result, ipmt)<br /> end<br /> return nil<br /> end<br /> <br /> local function ipv6_address(ip_str)<br /> -- Return a collection of eight 16-bit words (numbers) equivalent<br /> -- to the IPv6 address given as a colon-delimited string, or<br /> -- return nil if invalid.<br /> local _, n = ip_str:gsub(&#039;:&#039;, &#039;:&#039;)<br /> if n &lt; 7 then<br /> ip_str, n = ip_str:gsub(&#039;::&#039;, string.rep(&#039;:&#039;, 9 - n))<br /> end<br /> local parts = collection()<br /> for item in (ip_str .. &#039;:&#039;):gmatch(&#039;(.-):&#039;) do<br /> parts:add(item)<br /> end<br /> if parts.n == 8 then<br /> for i, s in ipairs(parts) do<br /> if s == &#039;&#039; then<br /> parts[i] = 0<br /> else<br /> local num = tonumber(&#039;0x&#039; .. s)<br /> if num and 0 &lt;= num and num &lt;= 65535 then<br /> parts[i] = num<br /> else<br /> return nil<br /> end<br /> end<br /> end<br /> return setmetatable(parts, ipmt)<br /> end<br /> return nil<br /> end<br /> <br /> local function common_length(num1, num2, nr_bits)<br /> -- Return number of prefix bits that two integers have in common.<br /> -- Number of bits in each number is nr_bits = 16, 8, 4, 2 or 1.<br /> if nr_bits &lt;= 1 then<br /> return num1 == num2 and 1 or 0<br /> end<br /> local half = nr_bits / 2<br /> local splitter = 2^half<br /> local upper1, lower1 = math.modf(num1 / splitter)<br /> local upper2, lower2 = math.modf(num2 / splitter)<br /> if upper1 == upper2 then<br /> lower1 = math.floor(lower1 * splitter + 0.5)<br /> lower2 = math.floor(lower2 * splitter + 0.5)<br /> return half + common_length(lower1, lower2, half)<br /> end<br /> return common_length(upper1, upper2, half)<br /> end<br /> <br /> local function common_prefix_length(ip1, ip2)<br /> -- Return number of prefix bits that two IPs have in common.<br /> -- Caller ensures that both IPs are IPv4 or both are IPv6.<br /> local size = 0<br /> for i = 1, ip1.n do<br /> local w1, w2 = ip1[i], ip2[i]<br /> if w1 == w2 then<br /> size = size + 16<br /> else<br /> return size + common_length(w1, w2, 16)<br /> end<br /> end<br /> return size<br /> end<br /> <br /> local function ip_prefix(ip, length)<br /> -- Return a copy of ip masked to contain only the prefix of given length.<br /> local result = { n = ip.n }<br /> for i = 1, ip.n do<br /> if length &gt; 0 then<br /> if length &gt;= 16 then<br /> result[i] = ip[i]<br /> length = length - 16<br /> else<br /> result[i] = bit32.band(ip[i], bit32.arshift(0xffff8000, length - 1))<br /> length = 0<br /> end<br /> else<br /> result[i] = 0<br /> end<br /> end<br /> return setmetatable(result, ipmt)<br /> end<br /> <br /> local function ip_incremented(ip)<br /> -- Return a new IP equal to ip + 1.<br /> -- Will wraparound (255.255.255.255 + 1 = 0.0.0.0)!<br /> local result = { n = ip.n }<br /> local carry = 1<br /> for i = ip.n, 1, -1 do<br /> local sum = ip[i] + carry<br /> if sum &gt;= 0x10000 then<br /> carry = 1<br /> sum = sum - 0x10000<br /> else<br /> carry = 0<br /> end<br /> result[i] = sum<br /> end<br /> return setmetatable(result, ipmt)<br /> end<br /> <br /> local function is_next_ip(ip1, ip2)<br /> -- Return true if ip2 is the next IP after ip1 (ip2 == ip1 + 1).<br /> -- IPs are sorted and unique so ip1 &lt; ip2 and can ignore wrapping to zero.<br /> -- This is lower overhead than making a new incremented IP then comparing.<br /> if ip1 and ip2 then<br /> local carry = 1<br /> for i = ip1.n, 1, -1 do<br /> local sum = ip1[i] + carry<br /> if sum &gt;= 0x10000 then<br /> carry = 1<br /> sum = sum - 0x10000<br /> else<br /> carry = 0<br /> end<br /> if sum ~= ip2[i] then<br /> return false<br /> end<br /> end<br /> return true<br /> end<br /> end<br /> <br /> -- Each IP in a range except for the last IP has a &#039;common&#039; field which is<br /> -- a number specifying how many bits are common between the prefixes of this<br /> -- IP and the next IP (0 if this IP starts with 0 and the next starts with 1).<br /> -- Each non-empty range has exactly one &quot;minimum common&quot;, that is, its value<br /> -- of common is smaller than all others. That there is only one minimum common<br /> -- follows from the fact that the IPs are unique and sorted.<br /> local function make_range(iplist, ifirst, ilast)<br /> -- Return a table for the range of IPs from iplist[ifirst] to iplist[ilast] inclusive.<br /> local imin, vmin, done<br /> if ifirst &lt; ilast then<br /> for i = ifirst, ilast - 1 do<br /> -- Find the (unique) minimum of common lengths.<br /> local common = iplist[i].common<br /> if vmin then<br /> if vmin &gt; common then<br /> vmin = common<br /> imin = i<br /> end<br /> else<br /> vmin = common<br /> imin = i<br /> end<br /> end<br /> else<br /> vmin = iplist.ipsize<br /> imin = ifirst<br /> done = true<br /> end<br /> if vmin &gt; iplist.allocation then<br /> -- For IPv6, the default allocation is /64 and there is no point having<br /> -- more precise ranges as they add unnecessary complexity.<br /> -- However, using results=all sets allocation = 128 so vmin is not changed.<br /> vmin = iplist.allocation<br /> end<br /> return {<br /> ifirst = ifirst, -- index of first IP<br /> ilast = ilast, -- index of last IP<br /> imin = imin, -- index of IP with minimum common<br /> size = vmin, -- number of common bits in prefix (the minimum)<br /> prefix = ip_prefix(iplist[imin], vmin), -- IP table of the base IP<br /> done = done, -- true if know that this range cannot be improved<br /> }<br /> end<br /> <br /> local function split_range(iplist, range, depth)<br /> -- Return a table of two or more ranges that more precisely target<br /> -- the IPs in range, or return nothing if unable to improve range.<br /> depth = depth and depth + 1 or 0<br /> if depth &lt;= 20 and -- 20 examines 1M contiguous addresses down to individual IPs<br /> not range.done and<br /> range.size &lt; iplist.allocation and<br /> range.ifirst &lt; range.ilast then<br /> local imin = range.imin<br /> assert(imin and range.ifirst &lt;= imin and imin &lt; range.ilast)<br /> local r1 = make_range(iplist, range.ifirst, range.imin)<br /> local r2 = make_range(iplist, range.imin + 1, range.ilast)<br /> local pointless = range.size + 1<br /> if r1.size &gt; pointless or r2.size &gt; pointless then<br /> return { r1, r2 }<br /> end<br /> local result = collection()<br /> local function store_split(range)<br /> local split = split_range(iplist, range, depth)<br /> if split then<br /> for _, r in ipairs(split) do<br /> result:add(r)<br /> end<br /> return true<br /> else<br /> result:add(range)<br /> end<br /> end<br /> local improved1 = store_split(r1)<br /> local improved2 = store_split(r2)<br /> if improved1 or improved2 then<br /> return result<br /> end<br /> end<br /> range.done = true<br /> end<br /> <br /> local function better_summary(iplist, summary)<br /> -- Return a better summary that more precisely targets the specified IPs,<br /> -- or return nil if unable to improve the summary.<br /> local better = collection()<br /> local improved<br /> for _, range in ipairs(summary) do<br /> local split = split_range(iplist, range)<br /> if split then<br /> improved = true<br /> for _, r in ipairs(split) do<br /> better:add(r)<br /> end<br /> else<br /> better:add(range)<br /> end<br /> end<br /> return improved and better<br /> end<br /> <br /> local function make_summaries(iplist)<br /> -- Return a collection where each item is a summary.<br /> -- A summary is a table of one or more ranges.<br /> -- A summary covers all the given IPs and probably more.<br /> -- A range is a table representing a CIDR block such as 1.2.248.0/21.<br /> -- The first summary found is a single range; each subsequent summary<br /> -- (if any) uses more ranges to better target the given IPs.<br /> -- The result omits any summary with a range size that is too small (too many IPs).<br /> local function good_size(summary)<br /> for _, range in ipairs(summary) do<br /> if range.size &lt; iplist.minsize then<br /> return false<br /> end<br /> end<br /> return true<br /> end<br /> local summaries = collection()<br /> if iplist.n &gt; 0 then<br /> for i = 1, iplist.n - 1 do<br /> -- Set length of prefixes common between each pair of IPs.<br /> iplist[i].common = common_prefix_length(iplist[i], iplist[i+1])<br /> end<br /> local summary = { make_range(iplist, 1, iplist.n) }<br /> while summary and summaries.n &lt; iplist.maxresults do<br /> if good_size(summary) then<br /> summaries:add(summary)<br /> end<br /> summary = better_summary(iplist, summary)<br /> end<br /> end<br /> return summaries<br /> end<br /> <br /> local function extract_ipv4(result, omitted, line)<br /> -- Extract any IPv4 addresses from given line or throw error.<br /> -- Accept CIDR /n to specify a range (only accept 16 to 32).<br /> -- Addresses must be delimited with whitespace to reduce false positives.<br /> local function store(hit)<br /> local n = 32<br /> local lhs, rhs = hit:match(&#039;^(.-)/(%d+)$&#039;)<br /> if lhs then<br /> hit = lhs<br /> n = tonumber(rhs)<br /> if not (n and 16 &lt;= n and n &lt;= 32) then<br /> error(&#039;CIDR /n only accepts n = 16 to 32, invalid: &#039; .. lhs .. &#039;/&#039; .. rhs, 0)<br /> end<br /> end<br /> local ip = ipv4_address(hit)<br /> if ip then<br /> if n == 32 then<br /> result:add(ip)<br /> else<br /> if ip ~= ip_prefix(ip, n) then<br /> error(&#039;Invalid base address (host bits should be zero): &#039; .. hit, 0)<br /> end<br /> for _ = 1, 2^(32 - n) do<br /> result:add(ip)<br /> ip = ip_incremented(ip)<br /> end<br /> end<br /> else<br /> omitted:add(hit)<br /> end<br /> end<br /> line = line:gsub(&#039;:&#039;, &#039; &#039;) -- so wikitext indents or other colons don&#039;t obscure an IVp4 address<br /> for hit in line:gmatch(&#039;%S+&#039;) do<br /> if hit:match(&#039;^%d+%.%d+[%.%d/]+$&#039;) then<br /> local _, n = hit:gsub(&#039;%.&#039;, &#039;.&#039;)<br /> if n &gt;= 3 then<br /> store(hit)<br /> end<br /> end<br /> end<br /> end<br /> <br /> local function extract_ipv6(result, omitted, line)<br /> -- Extract any IPv6 addresses from given line or throw error.<br /> -- Addresses must be delimited with whitespace to reduce false positives.<br /> -- Want to accept all valid IPv6 despite the fact that contributors will<br /> -- not have an address starting with &#039;:&#039;.<br /> -- Also want to be able to parse arbitrary wikitext which might use colons<br /> -- for indenting. To achieve that, if an address at the start of a line<br /> -- is valid, use it; otherwise strip any leading colons and try again.<br /> for pos, hit in line:gmatch(&#039;()(%S+)&#039;) do<br /> local ipstr, length = hit:match(&#039;^([:%x]+)(/?%d*)$&#039;)<br /> if ipstr then<br /> local _, n = ipstr:gsub(&#039;:&#039;, &#039;:&#039;)<br /> if n &gt;= 2 then<br /> local ip = ipv6_address(ipstr)<br /> if not ip and pos == 1 then<br /> ipstr, n = ipstr:gsub(&#039;^:+&#039;, &#039;&#039;)<br /> if n &gt; 0 then<br /> ip = ipv6_address(ipstr)<br /> end<br /> end<br /> if ip then<br /> if length and #length &gt; 0 then<br /> error(&#039;CIDR /n not accepted for IPv6: &#039; .. hit, 0)<br /> end<br /> result:add(ip)<br /> else<br /> omitted:add(hit)<br /> end<br /> end<br /> end<br /> end<br /> end<br /> <br /> local function contribs(address)<br /> -- Return a URL or wikilink to list the contributions for an IP or IP range,<br /> -- or return an empty string if cannot do anything useful (IPv6 CIDR).<br /> -- The given address is a string of either a single IP or a CIDR range.<br /> local encoded, count = address:gsub(&#039;/&#039;, &#039;%%2F&#039;)<br /> if count &gt; 0 then<br /> if address:find(&#039;:&#039;, 1, true) then<br /> return &#039;&#039; -- no contributions link is available for a CIDR IPv6 range<br /> end<br /> local url = &#039;[https://tools.wmflabs.org/xtools/rangecontribs/?project=en.wikipedia.org&amp;namespace=all&amp;limit=50&amp;text=%s&amp;begin=%s c]&#039;<br /> -- %s = IPv4 CIDR range with &#039;/&#039; changed to &#039;%2F&#039;<br /> -- %s = Start date formatted &#039;yyyy-mm-dd&#039; (am using today&#039;s date less one month)<br /> local date = os.date(&#039;!*t&#039;) -- table with today&#039;s UTC date<br /> local y, m, d = date.year, date.month, date.day -- full year, month (1-12), day (1-31)<br /> if m &gt; 1 then<br /> m = m - 1<br /> else<br /> m = 12<br /> y = y - 1<br /> end<br /> return string.format(url,<br /> encoded,<br /> string.format(&#039;%d-%02d-%02d&#039;, y, m, d)<br /> )<br /> end<br /> return &#039;[[Special:Contributions/&#039; .. address .. &#039;|c]]&#039;<br /> end<br /> <br /> -- Strings for results using plain text.<br /> -- The pre tags used are html which do not provide &quot;nowiki&quot;,<br /> -- but that is not required by the text used.<br /> local plaintext = {<br /> <br /> header = [=[<br /> &lt;pre&gt;<br /> Total Affected Given Range]=],<br /> <br /> footer = &#039;&lt;/pre&gt;&#039;,<br /> <br /> sumfirst = [=[<br /> ----------------------------------------------------------<br /> %s%-12s %-12s %-11d %s%s]=],<br /> -- %s = empty string (dummy for compatibility)<br /> -- %s = total affected<br /> -- %s = affected<br /> -- %d = given (number of addresses given in input covered by this range)<br /> -- %s = IP address range<br /> -- %s = empty string<br /> <br /> sumnext = [=[<br /> %-12s %-11d %s%s]=],<br /> -- %s = affected<br /> -- %d = given<br /> -- %s = IP address range<br /> -- %s = empty string<br /> <br /> }<br /> <br /> -- Strings for results using a table in wikitext.<br /> local wikitable = {<br /> <br /> header = [=[<br /> {| class=&quot;wikitable&quot;<br /> ! Total&lt;br /&gt;affected !! Affected&lt;br /&gt;addresses !! Given&lt;br /&gt;addresses !! Range !! Contribs]=],<br /> <br /> footer = &#039;|}&#039;,<br /> <br /> sumfirst = [=[<br /> |- style=&quot;background: darkgray; height: 6px;&quot;<br /> |colspan=&quot;5&quot; |<br /> |- style=&quot;vertical-align: top;&quot;<br /> |rowspan=&quot;%s&quot; |%s ||%s ||%d ||%s ||%s]=],<br /> -- %s = string of number of ranges in summary (number of rows)<br /> -- %s = total affected<br /> -- %s = affected<br /> -- %d = given<br /> -- %s = IP address range<br /> -- %s = contributions link<br /> <br /> sumnext = [=[<br /> |-<br /> |%s ||%d ||%s ||%s]=],<br /> -- %s = affected<br /> -- %d = given<br /> -- %s = IP address range<br /> -- %s = contributions link<br /> <br /> }<br /> <br /> local function show_summary(lines, iplist, summary)<br /> -- Show the summary by adding table wikitext or plain text to lines.<br /> local want_plain = iplist.want_plain<br /> local total = 0<br /> for _, range in ipairs(summary) do<br /> -- A number is a double which easily handles 2^128 = 3.4e38.<br /> total = total + 2^(iplist.ipsize - range.size)<br /> end<br /> local str = want_plain and plaintext or wikitable<br /> for i, range in ipairs(summary) do<br /> local prefix = ip_string(range.prefix)<br /> local size = range.size<br /> local affected = describe_size(iplist.ipsize, size)<br /> local given = range.ilast - range.ifirst + 1<br /> local address<br /> if size == iplist.ipsize then<br /> address = prefix<br /> else<br /> address = prefix .. &#039;/&#039; .. size<br /> end<br /> local s<br /> if i == 1 then<br /> s = string.format(str.sumfirst,<br /> want_plain and &#039;&#039; or tostring(#summary),<br /> describe_total(total),<br /> affected, given, address,<br /> want_plain and &#039;&#039; or contribs(address)<br /> )<br /> else<br /> s = string.format(str.sumnext,<br /> affected, given, address,<br /> want_plain and &#039;&#039; or contribs(address)<br /> )<br /> end<br /> lines:add(s)<br /> end<br /> end<br /> <br /> local function process_ips(lines, iplist, omitted)<br /> -- Process a list of IP addresses, adding text of results to lines.<br /> -- The list should contain either all IPv4 addresses, or all IPv6 (not a mixture).<br /> local seq1, seq2, seqmany<br /> local function show_sequence()<br /> if seq1 and seq2 then<br /> local text = ip_string(seq1)<br /> if seqmany then<br /> seqmany = false<br /> text = text .. &#039; – &#039; .. ip_string(seq2)<br /> end<br /> seq1 = nil<br /> seq2 = nil<br /> local markup = text:sub(1, 1) == &#039;:&#039; and &#039;:&lt;nowiki/&gt;&#039; or &#039;:&#039;<br /> lines:add(markup .. text)<br /> end<br /> end<br /> local function show_ip(ip)<br /> -- Show IP or record it to be included in a &quot;from to&quot; sequence of IPs.<br /> if is_next_ip(seq2, ip) then<br /> seq2 = ip<br /> seqmany = true<br /> else<br /> show_sequence()<br /> seq1 = ip<br /> seq2 = ip<br /> seqmany = false<br /> end<br /> end<br /> if iplist.n &lt; 1 then<br /> return<br /> end<br /> if lines.n &gt; 0 then<br /> lines:add(&#039;&#039;)<br /> end<br /> if omitted.n &gt; 0 then<br /> lines:add(&#039;Warning, omitted as invalid: &#039; .. omitted:join(&#039; &#039;))<br /> lines:add(&#039;&#039;)<br /> end<br /> lines:add(&#039;&#039;) -- this blank line is replaced with a heading<br /> local heading_line = lines.n<br /> local duplicates = collection()<br /> local previous<br /> iplist:sort()<br /> -- Check for duplicates which can interfere with method to get ranges.<br /> for i, ip in ipairs(iplist) do<br /> if previous == ip then<br /> duplicates:add(i) -- index to omit duplicate later<br /> elseif not iplist.nolist then<br /> show_ip(ip)<br /> end<br /> previous = ip<br /> end<br /> show_sequence()<br /> local duplicate_text = &#039;&#039;<br /> if duplicates.n &gt; 0 then<br /> duplicate_text = &#039; (after omitting some duplicates)&#039;<br /> for i = duplicates.n, 1, -1 do<br /> iplist:remove(duplicates[i])<br /> end<br /> end<br /> local heading_text = string.format(&#039;Sorted %d %s address%s&#039;,<br /> iplist.n,<br /> iplist.ipname,<br /> iplist.n == 1 and &#039;&#039; or &#039;es&#039;<br /> )<br /> lines[heading_line] = heading_text .. duplicate_text .. &#039;:&#039;<br /> local str = iplist.want_plain and plaintext or wikitable<br /> lines:add(str.header)<br /> local upto = lines.n<br /> for _, summary in ipairs(make_summaries(iplist)) do<br /> show_summary(lines, iplist, summary)<br /> end<br /> lines:add(str.footer)<br /> if upto + 1 == lines.n then<br /> -- Show message in the very unlikely event that no results are found.<br /> lines:add(&#039;----&#039;)<br /> lines:add(&#039;No suitable ranges found; use &lt;code&gt;|results=all&lt;/code&gt; to see all ranges.&#039;)<br /> end<br /> end<br /> <br /> local function make_options(args)<br /> -- Return table of options from validated args or throw error.<br /> local options = {}<br /> if not empty(args.comment) then<br /> options.comment = args.comment<br /> end<br /> local allocation<br /> if not empty(args.allocation) then<br /> allocation = tonumber(args.allocation)<br /> if not (allocation and 48 &lt;= allocation and allocation &lt;= 128) then<br /> error(&#039;Invalid allocation &quot;&#039; .. args.allocation .. &#039;&quot; (should be 48 to 128; default is 64)&#039;, 0)<br /> end<br /> end<br /> local maxresults<br /> if not empty(args.results) then<br /> if args.results == &#039;all&#039; then<br /> options.all = true<br /> allocation = allocation or 128<br /> maxresults = 1000<br /> else<br /> maxresults = tonumber(args.results)<br /> if not (maxresults and 1 &lt;= maxresults and maxresults &lt;= 100) then<br /> error(&#039;Invalid results &quot;&#039; .. args.results .. &#039;&quot; (should be 1 to 100)&#039;, 0)<br /> end<br /> end<br /> end<br /> options.allocation = allocation or 64<br /> options.maxresults = maxresults or 10<br /> local keywords = {<br /> -- Table of k, v strings.<br /> -- If an argument matches k, an option named v is set to true.<br /> ok = &#039;noannounce&#039;,<br /> nolist = &#039;nolist&#039;,<br /> text = &#039;text&#039;,<br /> }<br /> for i, arg in ipairs(args) do<br /> local flag = keywords[arg:match(&#039;^%s*(%w+)%s*$&#039;)]<br /> if flag then<br /> options[i] = &#039;skip&#039;<br /> options[flag] = true<br /> end<br /> end<br /> return options<br /> end<br /> <br /> local function _IPblock(args)<br /> -- Process given args; can be called from another module.<br /> -- Throw an error if need to report a problem.<br /> local options = make_options(args)<br /> local v4list, v4omitted = collection(), collection()<br /> local v6list, v6omitted = collection(), collection()<br /> v4list.ipsize = 32<br /> v4list.ipname = &#039;IPv4&#039;<br /> v6list.ipsize = 128<br /> v6list.ipname = &#039;IPv6&#039;<br /> v4list.allocation = 32<br /> v6list.allocation = options.allocation<br /> if options.all then<br /> v4list.minsize = 0<br /> v6list.minsize = 0<br /> else<br /> v4list.minsize = 16 -- cannot block more IPs than /16 for IPv4<br /> v6list.minsize = 19 -- or /19 for IPv6 ($wgBlockCIDRLimit)<br /> end<br /> v4list.maxresults = options.maxresults<br /> v6list.maxresults = options.maxresults<br /> v4list.nolist = options.nolist<br /> v6list.nolist = options.nolist<br /> if options.text then<br /> v4list.want_plain = true<br /> v6list.want_plain = true<br /> end<br /> for i, arg in ipairs(args) do<br /> if options[i] ~= &#039;skip&#039; then<br /> for line in string.gmatch(arg .. &#039;\n&#039;, &#039;[\t ]*(.-)[\t\r ]*\n&#039;) do<br /> -- Skip line if is empty or a comment.<br /> if line ~= &#039;&#039; then<br /> local comment = options.comment<br /> if not (comment and line:sub(1, #comment) == comment) then<br /> -- Replace accepted delimiters with a space.<br /> line = line:gsub(&#039;[!&quot;#&amp;\&#039;()+,%-;&lt;=&gt;?[%]_{|}]&#039;, &#039; &#039;)<br /> extract_ipv4(v4list, v4omitted, line)<br /> extract_ipv6(v6list, v6omitted, line)<br /> end<br /> end<br /> end<br /> end<br /> end<br /> if v4list.n &lt; 1 and v6list.n &lt; 1 then<br /> error(&#039;No valid IPv4 or IPv6 address in arguments&#039;, 0)<br /> end<br /> local lines = collection()<br /> if not options.noannounce then<br /> lines:add(&quot;&#039;&#039;&#039;Please see [[Template talk:Blockcalc#Version February 2016|this announcement]].&#039;&#039;&#039;&quot;)<br /> end<br /> process_ips(lines, v4list, v4omitted)<br /> process_ips(lines, v6list, v6omitted)<br /> return lines:join(&#039;\n&#039;)<br /> end<br /> <br /> local function IPblock(frame)<br /> -- Return wikitext to display the smallest IPv4 or IPv6 CIDR range that<br /> -- covers each address given in the arguments, or return error text.<br /> -- An IP starting with &#039;#&#039; is ignored (commented out).<br /> -- Input can have any mixture of IPs; IPv4 and IPv6 are processed separately.<br /> local ok, msg = pcall(_IPblock, frame:getParent().args)<br /> if ok then<br /> return msg<br /> end<br /> return &#039;&lt;strong class=&quot;error&quot;&gt;Error: &#039; .. msg .. &#039;&lt;/strong&gt;&#039;<br /> end<br /> <br /> return { IPblock = IPblock, _IPblock = _IPblock }</div> Johnuniq