Removed unused cruft.

Removed unused cruft.

rex = require "rex_pcre"
cli = require "cliargs"
lfs = require "lfs"

import concat, insert from table

contains = (t, item) ->
	return true if item == nil
	for k, v in pairs t
		return true if item == v
	false

file_ext = (str) ->
	return "." .. str\match(".([^%.]+)$")

local dir_list, dir_listing
dir_listing = (path, file) ->
	f = path .. '/' .. file
	attr = lfs.attributes(f).mode
	{file, attr, if attr == 'directory' then dir_list(f)}

dir_list = (path) ->
	[dir_listing(path, file) for file in lfs.dir(path) when not contains({'.', '..'}, file)]

print_listing = (filedata, regex) ->
	for k, {file, mode, data} in pairs filedata
		print file, mode
		print_listing(data, regex) if data

process_files = (filedata, regex, parent) ->
	parent = parent or {'',''}
	for k, {file, mode, data} in pairs filedata
		return if not rex.match(file, regex)
		if mode == 'directory'
			f = rex.match(file, regex)
			f = f\gsub('[^aA-zZ|\\d| ]', '')
			f = f\match("^%s*(.-)%s*$")
			f = target .. '/' .. f
			lfs.mkdir(f)
			parent = {inputdir .. '/' .. file, f}
		else
			ext = file_ext(file)
			newer_f = rex.match(file, regex)
			new_f = rex.match(newer_f, [[(.*)(v\d)]]) or newer_f
			new_f = new_f\gsub('[-,_, ]', '')
			new_f = rex.gsub(new_f, [[(\D*)(\d*)]], [[%1_ep%2]], 1)
			old_f, new_f = parent[1] .. '/' .. file, parent[2] .. '/' .. new_f .. ext
			lfs.link(old_f, new_f)
			print "Link: " .. old_f .. " to: " .. new_f

		process_files(data, regex, parent) if data

cli\set_name("regnamex.lua")
cli\add_argument("DIR", "directory to scan")
cli\add_argument("TARGET", "target directory")
cli\optarg("IGNORED", "ignored files/directories")
cli\add_flag("-t, --type", "action to take: cp, mv, symlink, defaults to symlink", "symlink")
cli\add_flag("-v, --version", "prints the program version")
cli\add_flag("-d, --debug", "script will simulate excution, print actions.")
args = cli\parse_args()
return if not args

ignored_files = switch type(args["IGNORED"])
	when "string"
		{}
	else
		args["IGNORED"]

export inputdir = args["DIR"]
export files = dir_list(args["DIR"])
export target = args["TARGET"]

regex = [==[(?:(?:\[[^\]]*\])|(?:\([^\)]*\)]))?([^\[|\]|\(|\)]*[^\[|\]|\(|\)])?]==]

processed = process_files(files, regex)
print_listing(processed)

-- ([\[]*[^\]]*[\]]*)([^\[|\]|\(|\)]*)([\[]*[^\]]*[\]]*c)
-- (?![^\[|\]*])?([^\[|\]|\(|\)]+\b)(?:[^\[|\]]*)?
-- ([\[][^\]]+[\]])+([^\[|\]|\(|\)]*)?([\[][^\]]+[\]])+
-- ([\[][^\]]*[\]])+([^\[|\]|\(|\)]*)?(([\[][^\]]+[\]])|([\(][^\)]*[\)]))+
-- ((\[[^\]]*\])|(\([^\)]*\)]))+([^\[|\]|\(|\)]*[^\[|\]|\(|\)])?
-- (?:(?:\[[^\]]*\])|(?:\([^\)]*\)]))+([^\[|\]|\(|\)]*[^\[|\]|\(|\)])?

rex = require "rex_pcre"
cli = require "cliargs"
lfs = require "lfs"

import concat, insert from table

contains = (t, item) ->
	return true if item == nil
	for k, v in pairs t
		return true if item == v
	false

file_ext = (str) ->
	return "." .. str\match(".([^%.]+)$")

local dir_list, dir_listing
dir_listing = (path, file) ->
	f = path .. '/' .. file
	attr = lfs.attributes(f).mode
	{file, attr, if attr == 'directory' then dir_list(f)}

dir_list = (path) ->
	[dir_listing(path, file) for file in lfs.dir(path) when not contains({'.', '..'}, file)]

print_listing = (filedata, regex) ->
	for k, {file, mode, data} in pairs filedata
		print file, mode
		print_listing(data, regex) if data

process_files = (filedata, regex, parent) ->
	ret = {}
	parent = parent or {'',''}
	for k, {file, mode, data} in pairs filedata
		return if not rex.match(file, regex)
		if mode == 'directory'
			f = rex.match(file, regex)
			f = f\gsub('[^aA-zZ|\\d| ]', '')
			f = f\match("^%s*(.-)%s*$")
			f = target .. '/' .. f
			lfs.mkdir(f)
			parent = {inputdir .. '/' .. file, f}
		else
			ext = file_ext(file)
			newer_f = rex.match(file, regex)
			new_f = rex.match(newer_f, [[(.*)(v\d)]]) or newer_f
			new_f = new_f\gsub('[-,_, ]', '')
			new_f = rex.gsub(new_f, [[(\D*)(\d*)]], [[%1_ep%2]], 1)
			old_f, new_f = parent[1] .. '/' .. file, parent[2] .. '/' .. new_f .. ext
			lfs.link(old_f, new_f)
			print "Link: " .. old_f .. " to: " .. new_f
		item = {rex.match(file, regex), mode, data}
		item[3] = process_files(data, regex, parent) if data
		insert(ret, item)
	ret

cli\set_name("regnamex.lua")
cli\add_argument("DIR", "directory to scan")
cli\add_argument("TARGET", "target directory")
cli\optarg("IGNORED", "ignored files/directories")
cli\add_flag("-t, --type", "action to take: cp, mv, symlink, defaults to symlink", "symlink")
cli\add_flag("-v, --version", "prints the program version")
cli\add_flag("-d, --debug", "script will simulate excution, print actions.")
args = cli\parse_args()
return if not args

ignored_files = switch type(args["IGNORED"])
	when "string"
		{}
	else
		args["IGNORED"]

export inputdir = args["DIR"]
export files = dir_list(args["DIR"])
export target = args["TARGET"]

regex = [==[(?:(?:\[[^\]]*\])|(?:\([^\)]*\)]))?([^\[|\]|\(|\)]*[^\[|\]|\(|\)])?]==]

processed = process_files(files, regex)
print_listing(processed)

-- ([\[]*[^\]]*[\]]*)([^\[|\]|\(|\)]*)([\[]*[^\]]*[\]]*c)
-- (?![^\[|\]*])?([^\[|\]|\(|\)]+\b)(?:[^\[|\]]*)?
-- ([\[][^\]]+[\]])+([^\[|\]|\(|\)]*)?([\[][^\]]+[\]])+
-- ([\[][^\]]*[\]])+([^\[|\]|\(|\)]*)?(([\[][^\]]+[\]])|([\(][^\)]*[\)]))+
-- ((\[[^\]]*\])|(\([^\)]*\)]))+([^\[|\]|\(|\)]*[^\[|\]|\(|\)])?
-- (?:(?:\[[^\]]*\])|(?:\([^\)]*\)]))+([^\[|\]|\(|\)]*[^\[|\]|\(|\)])?


prep-quizs-name: header one more time after data

import Widget from require "lapis.html"

model = require('model')
msk_time = require "msk_time"
all = require('quiz.all')

class PrepQuizsName extends Widget
  content: =>
    q = all[@quiz_name]
    if not q
      error(@_("No such quiz found"))
    quizs = model.quizs_of_name(@quiz_name, model.FINISHED)
    h1 @_[[All quizes]] .. ' ' .. @quiz_name
    print_header = ->
      element 'tr', ->
        element 'td' -- id
        element 'td', -> text @_("user")
        element 'td', -> text @_("right answers")
        element 'td', -> text @_("tasks")
        for task_name, func in pairs(q) do
          element 'td', -> text task_name
    element 'table', border: 1, ->
      print_header!
      name2score = {}
      for quiz in *quizs
        color = 'red'
        if quiz.right_answers == quiz.tasks
          color = 'green'
        element 'tr', ->
          element 'td', ->
            a href: @url_for("prep-quiz", {id: quiz.id}), ->
              text '#'
          element 'td', ->
            url = @url_for("prep-quizs-of", {user: quiz.user})
            a href: url, ->
              text quiz.user
          element 'td', bgcolor: color, ->
            text quiz.right_answers
          element 'td', bgcolor: color, ->
            text quiz.tasks
          tasks = quiz\all_tasks!
          name2task = {}
          for task in *tasks
            name2task[task.name] = task
          for task_name, func in pairs(q) do
            task = name2task[task_name]
            color = 'white'
            t = ''
            if task and task.selected == 1
              color = 'green'
              t = '1'
              if not name2score[task_name]
                name2score[task_name] = 0
              name2score[task_name] = name2score[task_name] + 1
            if task and task.selected > 1
              color = 'red'
              t = '0'
            element 'td', bgcolor: color, ->
              text t
      element 'tr', ->
        element 'td' -- id
        element 'td' --, -> text @_("user")
        element 'td' --, -> text @_("right answers")
        element 'td' --, -> text @_("tasks")
        for task_name, func in pairs(q) do
          element 'td', ->
            if name2score[task_name]
              text name2score[task_name]
            else
              text 0
      print_header!

import Widget from require "lapis.html"

model = require('model')
msk_time = require "msk_time"
all = require('quiz.all')

class PrepQuizsName extends Widget
  content: =>
    q = all[@quiz_name]
    if not q
      error(@_("No such quiz found"))
    quizs = model.quizs_of_name(@quiz_name, model.FINISHED)
    h1 @_[[All quizes]] .. ' ' .. @quiz_name
    element 'table', border: 1, ->
      element 'tr', ->
        element 'td' -- id
        element 'td', -> text @_("user")
        element 'td', -> text @_("right answers")
        element 'td', -> text @_("tasks")
        for task_name, func in pairs(q) do
          element 'td', -> text task_name
      name2score = {}
      for quiz in *quizs
        color = 'red'
        if quiz.right_answers == quiz.tasks
          color = 'green'
        element 'tr', ->
          element 'td', ->
            a href: @url_for("prep-quiz", {id: quiz.id}), ->
              text '#'
          element 'td', ->
            url = @url_for("prep-quizs-of", {user: quiz.user})
            a href: url, ->
              text quiz.user
          element 'td', bgcolor: color, ->
            text quiz.right_answers
          element 'td', bgcolor: color, ->
            text quiz.tasks
          tasks = quiz\all_tasks!
          name2task = {}
          for task in *tasks
            name2task[task.name] = task
          for task_name, func in pairs(q) do
            task = name2task[task_name]
            color = 'white'
            t = ''
            if task and task.selected == 1
              color = 'green'
              t = '1'
              if not name2score[task_name]
                name2score[task_name] = 0
              name2score[task_name] = name2score[task_name] + 1
            if task and task.selected > 1
              color = 'red'
              t = '0'
            element 'td', bgcolor: color, ->
              text t
      element 'tr', ->
        element 'td' -- id
        element 'td' --, -> text @_("user")
        element 'td' --, -> text @_("right answers")
        element 'td' --, -> text @_("tasks")
        for task_name, func in pairs(q) do
          element 'td', ->
            if name2score[task_name]
              text name2score[task_name]
            else
              text 0


added all key data

added all key data


Stopped overwriting the global `debug` function.

inspect = require('vendor/inspect/inspect')

traverse = (value, depth, hideMeta = false) ->
	output = ''
	if _.isTable(value) and value.__class then output ..= "#{value.__class.__name}:"

	options = { :depth }
	if hideMeta then options.process = (item, path) -> if path[#path] != inspect.METATABLE then return item

	output ..= inspect(value, options)
	return output

export log = (...) ->
	args = { ... }
	depth = if #args == 1 then 2 else 1
	output = ''
	for value in *args
		if #output > 0 then output ..= '\t'
		output ..= traverse(value, depth, true)
	print output

export dump = (value, depth = 2) ->
	print traverse(value, depth)

inspect = require('vendor/inspect/inspect')

dump = (value, depth, hideMeta = false) ->
	output = ''
	if _.isTable(value) and value.__class then output ..= "#{value.__class.__name}:"

	options = { :depth }
	if hideMeta then options.process = (item, path) -> if path[#path] != inspect.METATABLE then return item

	output ..= inspect(value, options)
	return output

export log = (...) ->
	args = { ... }
	depth = if #args == 1 then 2 else 1
	output = ''
	for value in *args
		if #output > 0 then output ..= '\t'
		output ..= dump(value, depth, true)
	print output

export debug = (value, depth = 2) ->
	print dump(value, depth)


utf8: add another silly mapping

utf8: add another silly mapping

Former-commit-id: 5284c340fcfbb311bcaaae011db249b3933cec80 [formerly 89b0c753df7213124d26cc6181ea601cecce6823]
Former-commit-id: 747a38b56b58a3c97d28b6d5b955d199ef229c79

util = require'util'
html2unicode = require'html'

an = [[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789,.?!"'`()[]{}<>&_]]
charmaps = {
ci: 'ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⓪①②③④⑤⑥⑦⑧⑨'
bl: '𝔄𝔅ℭ𝔇𝔈𝔉𝔊ℌℑ𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔ℜ𝔖𝔗𝔘𝔙𝔚𝔛𝔜ℨ𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷'
ud: [[∀BƆDƎℲפHIſK˥WNOԀQRS┴∩ΛMX⅄Zɐqɔpǝɟƃɥᴉɾʞlɯuodbɹsʇnʌʍxʎz0ƖᄅƐㄣϛ9ㄥ86'˙¿¡,,,)(][}{><⅋‾]]
nc: [[🅐🅑🅒🅓🅔🅕🅖🅗🅘🅙🅚🅛🅜🅝🅞🅟🅠🅡🅢🅣🅤🅥🅦🅧🅨🅩🅐🅑🅒🅓🅔🅕🅖🅗🅘🅙🅚🅛🅜🅝🅞🅟🅠🅡🅢🅣🅤🅥🅦🅧🅨🅩⓿]]
sq: [[🄰🄱🄲🄳🄴🄵🄶🄷🄸🄹🄺🄻🄼🄽🄾🄿🅀🅁🅂🅃🅄🅅🅆🅇🅈🅉🄰🄱🄲🄳🄴🄵🄶🄷🄸🄹🄺🄻🄼🄽🄾🄿🅀🅁🅂🅃🅄🅅🅆🅇🅈🅉0123456789,⊡]]
ns: [[🅰🅱🅲🅳🅴🅵🅶🅷🅸🅹🅺🅻🅼🅽🅾🅿🆀🆁🆂🆃🆄🆅🆆🆇🆈🆉🅰🅱🅲🅳🅴🅵🅶🅷🅸🅹🅺🅻🅼🅽🅾🅿🆀🆁🆂🆃🆄🆅🆆🆇🆈🆉]]
ds: [[𝔸𝔹ℂ𝔻𝔼𝔽𝔾ℍ𝕀𝕁𝕂𝕃𝕄ℕ𝕆ℙℚℝ𝕊𝕋𝕌𝕍𝕎𝕏𝕐ℤ𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫𝟘𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡]]
bo: [[𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳𝟎𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗]]
bi: [[𝑨𝑩𝑪𝑫𝑬𝑭𝑮𝑯𝑰𝑱𝑲𝑳𝑴𝑵𝑶𝑷𝑸𝑹𝑺𝑻𝑼𝑽𝑾𝑿𝒀𝒁𝒂𝒃𝒄𝒅𝒆𝒇𝒈𝒉𝒊𝒋𝒌𝒍𝒎𝒏𝒐𝒑𝒒𝒓𝒔𝒕𝒖𝒗𝒘𝒙𝒚𝒛0123456789]]
bs: [[𝓐𝓑𝓒𝓓𝓔𝓕𝓖𝓗𝓘𝓙𝓚𝓛𝓜𝓝𝓞𝓟𝓠𝓡𝓢𝓣𝓤𝓥𝓦𝓧𝓨𝓩𝓪𝓫𝓬𝓭𝓮𝓯𝓰𝓱𝓲𝓳𝓴𝓵𝓶𝓷𝓸𝓹𝓺𝓻𝓼𝓽𝓾𝓿𝔀𝔁𝔂𝔃]]
pt: [[⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵0⑴⑵⑶⑷⑸⑹⑺⑻⑼]]
tl: [[ค๒ς๔єŦﻮђเןкl๓ภ๏קợгรtยשฬץאzค๒ς๔єŦﻮђเןкl๓ภ๏קợгรtยשฬץאz0123456789,.؟!"'`()[]{}«»&_]]
}
codepoints = (str) ->
  str\gmatch("[%z\1-\127\194-\244][\128-\191]*")

-- Construct a table which can be used for lookup replacement later
-- Iterate over normal ascii and find counterparts in the weirdo strings as substrings
maps = {}
for charmap, chars in pairs charmaps
  i = 1
  maps[charmap] = {}
  for uchar in util.utf8.chars(chars)
    maps[charmap][an\sub(i,i)] = uchar
    i = i +1

unichr = (n) ->
  html2unicode('&#x%x;'\format(n))

wireplace = (offset, arg) ->
    s = arg or ''
    t = {}
    for i = 1, #s
      bc = string.byte(s, i, i)
      -- Replace space width ideographic space for fullwidth offset
      if bc == 32 and offset == 0xFEE0
        t[#t + 1] = '\227\128\128'
      elseif bc == 32
        t[#t + 1] = ' '
      elseif bc < 0x80 then
        t[#t + 1] = html2unicode("&#" .. (offset + bc) .. ";")
      else
        t[#t + 1] = s\sub(i, i)

    table.concat(t, "")

remap = (map, s) ->
  table.concat [map[s\sub(i,i)] or s\sub(i,i) for i=1, #s], ''

zalgo = (text, intensity=50) ->
  zalgo_chars = {}
  for i=0x0300, 0x036f
    zalgo_chars[i-0x2ff] = unichr(i)

  zalgo_chars[#zalgo_chars + 1] = unichr(0x0488)
  zalgo_chars[#zalgo_chars + 0] = unichr(0x0489)

  zalgoized = {}
  for letter in codepoints(text)
    zalgoized[#zalgoized + 1] = letter
    zalgo_num = math.random(1, intensity)
    for i=1, zalgo_num
      zalgoized[#zalgoized + 1] = zalgo_chars[math.random(1, #zalgo_chars)]
  table.concat(zalgoized)

PRIVMSG:
  '^%pwide (.+)$': (source, destination, arg) =>
    say wireplace(0xFEE0, arg)
  '^%pblackletter (.+)$': (source, destination, arg) =>
    say remap(maps.bl, arg)
  '^%pcircled (.+)$': (source, destination, arg) =>
    say remap(maps.ci, arg)
  '^%pzalgo (.+)$': (source, destination, arg) =>
    say zalgo(arg, 7)
  '^%pupsidedown (.+)$': (source, destination, arg) =>
    say remap(maps.ud, util.utf8.reverse(arg))
  '^%pflip (.+)$': (source, destination, arg) =>
    say remap(maps.ud, arg)
  '^%pthrow (.+)$': (source, destination, arg) =>
    say "（╯°□°）╯︵ #{remap maps.ud, util.utf8.reverse(arg)}"
  '^%pparanthesized (.+)$': (source, destination, arg) =>
    say remap(maps.pt, arg)
  '^%pnegcircle (.+)$': (source, destination, arg) =>
    say remap(maps['nc'], arg)
  '^%psquare (.+)$': (source, destination, arg) =>
    say remap(maps.sq, arg)
  '^%pnegsquare (.+)$': (source, destination, arg) =>
    say remap(maps.ns, arg)
  '^%pdoublestruck (.+)$': (source, destination, arg) =>
    say remap(maps.ds, arg)
  '^%pubold (.+)$': (source, destination, arg) =>
    say remap(maps.bo, arg)
  '^%pbolditalic (.+)$': (source, destination, arg) =>
    say remap(maps.bi, arg)
  '^%pboldscript (.+)$': (source, destination, arg) =>
    say remap(maps.bs, arg)
  '^%pthai (.+)$': (source, destination, arg) =>
    say remap(maps.tl, arg)
  '^%putfuk (.+)$': (source, destination, arg) =>
    keys = [x for x,_ in pairs(maps)]
    say table.concat([remap(maps[keys[math.random(#keys)]], letter) for letter in codepoints(arg)])

util = require'util'
html2unicode = require'html'

an = [[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789,.?!"'`()[]{}<>&_]]
charmaps = {
ci: 'ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⓪①②③④⑤⑥⑦⑧⑨'
bl: '𝔄𝔅ℭ𝔇𝔈𝔉𝔊ℌℑ𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔ℜ𝔖𝔗𝔘𝔙𝔚𝔛𝔜ℨ𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷'
ud: [[∀BƆDƎℲפHIſK˥WNOԀQRS┴∩ΛMX⅄Zɐqɔpǝɟƃɥᴉɾʞlɯuodbɹsʇnʌʍxʎz0ƖᄅƐㄣϛ9ㄥ86'˙¿¡,,,)(][}{><⅋‾]]
nc: [[🅐🅑🅒🅓🅔🅕🅖🅗🅘🅙🅚🅛🅜🅝🅞🅟🅠🅡🅢🅣🅤🅥🅦🅧🅨🅩🅐🅑🅒🅓🅔🅕🅖🅗🅘🅙🅚🅛🅜🅝🅞🅟🅠🅡🅢🅣🅤🅥🅦🅧🅨🅩⓿]]
sq: [[🄰🄱🄲🄳🄴🄵🄶🄷🄸🄹🄺🄻🄼🄽🄾🄿🅀🅁🅂🅃🅄🅅🅆🅇🅈🅉🄰🄱🄲🄳🄴🄵🄶🄷🄸🄹🄺🄻🄼🄽🄾🄿🅀🅁🅂🅃🅄🅅🅆🅇🅈🅉0123456789,⊡]]
ns: [[🅰🅱🅲🅳🅴🅵🅶🅷🅸🅹🅺🅻🅼🅽🅾🅿🆀🆁🆂🆃🆄🆅🆆🆇🆈🆉🅰🅱🅲🅳🅴🅵🅶🅷🅸🅹🅺🅻🅼🅽🅾🅿🆀🆁🆂🆃🆄🆅🆆🆇🆈🆉]]
ds: [[𝔸𝔹ℂ𝔻𝔼𝔽𝔾ℍ𝕀𝕁𝕂𝕃𝕄ℕ𝕆ℙℚℝ𝕊𝕋𝕌𝕍𝕎𝕏𝕐ℤ𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫𝟘𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡]]
bo: [[𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳𝟎𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗]]
bi: [[𝑨𝑩𝑪𝑫𝑬𝑭𝑮𝑯𝑰𝑱𝑲𝑳𝑴𝑵𝑶𝑷𝑸𝑹𝑺𝑻𝑼𝑽𝑾𝑿𝒀𝒁𝒂𝒃𝒄𝒅𝒆𝒇𝒈𝒉𝒊𝒋𝒌𝒍𝒎𝒏𝒐𝒑𝒒𝒓𝒔𝒕𝒖𝒗𝒘𝒙𝒚𝒛0123456789]]
bs: [[𝓐𝓑𝓒𝓓𝓔𝓕𝓖𝓗𝓘𝓙𝓚𝓛𝓜𝓝𝓞𝓟𝓠𝓡𝓢𝓣𝓤𝓥𝓦𝓧𝓨𝓩𝓪𝓫𝓬𝓭𝓮𝓯𝓰𝓱𝓲𝓳𝓴𝓵𝓶𝓷𝓸𝓹𝓺𝓻𝓼𝓽𝓾𝓿𝔀𝔁𝔂𝔃]]
pt: [[⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵0⑴⑵⑶⑷⑸⑹⑺⑻⑼]]
}
codepoints = (str) ->
  str\gmatch("[%z\1-\127\194-\244][\128-\191]*")

-- Construct a table which can be used for lookup replacement later
-- Iterate over normal ascii and find counterparts in the weirdo strings as substrings
maps = {}
for charmap, chars in pairs charmaps
  i = 1
  maps[charmap] = {}
  for uchar in util.utf8.chars(chars)
    maps[charmap][an\sub(i,i)] = uchar
    i = i +1

unichr = (n) ->
  html2unicode('&#x%x;'\format(n))

wireplace = (offset, arg) ->
    s = arg or ''
    t = {}
    for i = 1, #s
      bc = string.byte(s, i, i)
      -- Replace space width ideographic space for fullwidth offset
      if bc == 32 and offset == 0xFEE0
        t[#t + 1] = '\227\128\128'
      elseif bc == 32
        t[#t + 1] = ' '
      elseif bc < 0x80 then
        t[#t + 1] = html2unicode("&#" .. (offset + bc) .. ";")
      else
        t[#t + 1] = s\sub(i, i)

    table.concat(t, "")

remap = (map, s) ->
  table.concat [map[s\sub(i,i)] or s\sub(i,i) for i=1, #s], ''

zalgo = (text, intensity=50) ->
  zalgo_chars = {}
  for i=0x0300, 0x036f
    zalgo_chars[i-0x2ff] = unichr(i)

  zalgo_chars[#zalgo_chars + 1] = unichr(0x0488)
  zalgo_chars[#zalgo_chars + 0] = unichr(0x0489)

  zalgoized = {}
  for letter in codepoints(text)
    zalgoized[#zalgoized + 1] = letter
    zalgo_num = math.random(1, intensity)
    for i=1, zalgo_num
      zalgoized[#zalgoized + 1] = zalgo_chars[math.random(1, #zalgo_chars)]
  table.concat(zalgoized)

PRIVMSG:
  '^%pwide (.+)$': (source, destination, arg) =>
    say wireplace(0xFEE0, arg)
  '^%pblackletter (.+)$': (source, destination, arg) =>
    say remap(maps.bl, arg)
  '^%pcircled (.+)$': (source, destination, arg) =>
    say remap(maps.ci, arg)
  '^%pzalgo (.+)$': (source, destination, arg) =>
    say zalgo(arg, 7)
  '^%pupsidedown (.+)$': (source, destination, arg) =>
    say remap(maps.ud, util.utf8.reverse(arg))
  '^%pflip (.+)$': (source, destination, arg) =>
    say remap(maps.ud, arg)
  '^%pthrow (.+)$': (source, destination, arg) =>
    say "（╯°□°）╯︵ #{remap maps.ud, util.utf8.reverse(arg)}"
  '^%pparanthesized (.+)$': (source, destination, arg) =>
    say remap(maps.pt, arg)
  '^%pnegcircle (.+)$': (source, destination, arg) =>
    say remap(maps['nc'], arg)
  '^%psquare (.+)$': (source, destination, arg) =>
    say remap(maps.sq, arg)
  '^%pnegsquare (.+)$': (source, destination, arg) =>
    say remap(maps.ns, arg)
  '^%pdoublestruck (.+)$': (source, destination, arg) =>
    say remap(maps.ds, arg)
  '^%pubold (.+)$': (source, destination, arg) =>
    say remap(maps.bo, arg)
  '^%pbolditalic (.+)$': (source, destination, arg) =>
    say remap(maps.bi, arg)
  '^%pboldscript (.+)$': (source, destination, arg) =>
    say remap(maps.bs, arg)
  '^%putfuk (.+)$': (source, destination, arg) =>
    keys = [x for x,_ in pairs(maps)]
    say table.concat([remap(maps[keys[math.random(#keys)]], letter) for letter in codepoints(arg)])


Added LocalPonyData()

Added LocalPonyData()

--
-- Copyright (C) 2017-2019 DBot

-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-- of the Software, and to permit persons to whom the Software is furnished to do so,
-- subject to the following conditions:

-- The above copyright notice and this permission notice shall be included in all copies
-- or substantial portions of the Software.

-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-- PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-- FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-- OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-- DEALINGS IN THE SOFTWARE.

PARSE_VECTOR = (str = '1.0 1.0 1.0', X = 1, Y = 1, Z = 1) ->
	return Vector(X, Y, Z) if str == ''
	x, y, z = str\match('([0-9.]+) ([0-9.]+) ([0-9.]+)')
	return Vector(tonumber(x) or X, tonumber(y) or Y, tonumber(z) or Z)

PARSE_COLOR = (str = '1.0 1.0 1.0', r = 255, g = 255, b = 255) ->
	return Color(r, g, b) if str == ''
	{x, y, z} = PARSE_VECTOR(str, r / 255, g / 255, b / 255)
	return Color(x * 255, y * 255, z * 255)

IMPORT_TABLE = {
	'gender': {
		name: 'Gender'
		func: (arg = 0) ->
			num = tonumber(arg)
			return num == 0 and 'MALE' or 'FEMALE'
	}

	'coatcolor': {
		name: 'BodyColor'
		func: (arg = '1.0 1.0 1.0') -> PARSE_COLOR(arg)
	}

	'eyecolor_bg': {
		name: 'EyeBackground'
		func: (arg = '1.0 1.0 1.0') -> PARSE_COLOR(arg)
	}

	'eyecolor_grad': {
		name: 'EyeIrisBottom'
		func: (arg = '1.0 1.0 1.0') -> PARSE_COLOR(arg)
	}

	'eyecolor_iris': {
		name: 'EyeIrisTop'
		func: (arg = '1.0 1.0 1.0') -> PARSE_COLOR(arg)
	}

	'eyecolor_line1': {
		name: 'EyeIrisLine1'
		func: (arg = '1.0 1.0 1.0') -> PARSE_COLOR(arg)
	}

	'eyecolor_line2': {
		name: 'EyeIrisLine2'
		func: (arg = '1.0 1.0 1.0') -> PARSE_COLOR(arg)
	}

	'haircolor1': {
		name: {'ManeColor1', 'TailColor1', 'ManeColor2', 'TailColor2'}
		func: (arg = '1.0 1.0 1.0') -> PARSE_COLOR(arg)
	}

	'eyejholerssize': {
		name: 'HoleWidth'
		func: (arg = '1') -> tonumber(arg) or 1
	}

	'eyeirissize': {
		name: 'IrisSize'
		func: (arg = '1') -> (tonumber(arg) or 1) * 1.2
	}

	'eyeholesize': {
		name: 'HoleSize'
		func: (arg = '0.8') -> tonumber(arg) or 0.8
	}

	'bodyweight': {
		name: 'Weight'
		func: (arg = 1) -> tonumber(arg) or 1
	}

	'mane': {
		name: {'ManeType', 'ManeTypeNew'}
		func: (arg = 0) -> (tonumber(arg) or 0) - 1
	}

	'manel': {
		name: {'ManeTypeLower', 'ManeTypeLowerNew'}
		func: (arg = 0) -> (tonumber(arg) or 0) - 1
	}

	'tail': {
		name: {'TailType', 'TailTypeNew'}
		func: (arg = 0) -> (tonumber(arg) or 0) - 1
	}

	'tailsize': {
		name: 'TailSize'
		func: (arg = 1) -> tonumber(arg) or 1
	}

	'cmark': {
		name: 'CMarkType'
		func: (arg = 1) -> (tonumber(arg) or 1) - 1
	}

	'cmark_enabled': {
		name: 'CMark'
		func: (arg = '1') -> arg == '1' or arg == '2'
	}
}

for i = 1, 8
	IMPORT_TABLE["bodydetail#{i}"] = {
		name: "BodyDetail#{i}"
		func: (arg = 1) -> (tonumber(arg) or 1) - 1
	}

	IMPORT_TABLE["bodydetail#{i}_c"] = {
		name: "BodyDetailColor#{i}"
		func: (arg = '1.0 1.0 1.0') -> PARSE_COLOR(arg)
	}

for i = 2, 6
	IMPORT_TABLE["haircolor#{i}"] = {
		name: {"ManeDetailColor#{i - 1}", "TailDetailColor#{i - 1}"}
		func: (arg = '1.0 1.0 1.0') -> PARSE_COLOR(arg)
	}

PPM2.ReadFromOldData = (filename = '_current') ->
	read = file.Read("ppm/#{filename}.txt", 'DATA')
	return false if read == ''
	split = [str\Trim() for _, str in ipairs string.Explode('\n', read\Replace('\r', ''))]
	outputData = {}

	for _, line in ipairs split
		varID = line\match('([a-zA-Z0-9_]+)')
		continue if not varID or varID == ''
		continue if not IMPORT_TABLE[varID]
		dt = IMPORT_TABLE[varID]
		value = line\sub(#varID + 2)
		if type(dt.name) ~= 'table'
			outputData[dt.name] = dt.func(value)
		else
			get = dt.func(value)
			outputData[name] = get for _, name in ipairs dt.name

	data = PPM2.PonyDataInstance("#{filename}_imported", nil, false)
	for key, value in pairs outputData
		data["Set#{key}"](data, value, false)
	return data, outputData

_G.LocalPonyData = ->
	ply = LocalPlayer()
	return false if not ply
	return ply\GetPonyData() or false