{"type":"plugin","data":"/// @ 1.1.0\n### {\n  name: \"投稿時刻を表示するプラグイン(aiscript1.1.0以降対応版)\"\n  version: \"3.0.0\"\n  author: \"@souhait@submarin.online (Original: @taiy@submarin.online, 0.12.4Fix: @elysion@submarin.online)\"\n  description: \"ノートメニューに【投稿時刻を表示】を追加します。\"\n  permissions: []\n  config: {\n    format: {\n      type: \"string\"\n      label: \"書式\"\n      description: \"(既定値: YYYY/MM/DD HH:mm:ss.SSS) フォーマットを指定します。Day.jsと同一のトークンが利用できます。(一部非対応)\"\n      default: \"YYYY/MM/DD HH:mm:ss.SSS\"\n    }\n    offset: {\n      type: \"number\"\n      label: \"時差\"\n      description: \"(既定値: 540) 時差を分単位で指定します。日本標準時(JST)は540です。夏時間には非対応です。\"\n      default: 540\n    }\n  }\n}\n\nlet has_format = (Plugin:config.format == \"\") || (Plugin:config.format == null)\nlet c_format = if has_format \"YYYY/MM/DD HH:mm:ss.SSS\" else Plugin:config.format\nlet has_offset = (Plugin:config.offset == \"\") || (Plugin:config.offset == null)\nlet c_offset = if has_offset 540 else Plugin:config.offset\n\nif has_format {\n  Mk:dialog(\"投稿時刻を表示するプラグインより\", `書式の指定がありません。{Str:lf}自動で **YYYY/MM/DD HH:mm:ss.SSS** が適用されます。`, \"warn\")\n}\nif has_offset {\n  Mk:dialog(\"投稿時刻を表示するプラグインより\", `時差の指定がありません。{Str:lf}自動で **540** が適用されます。`, \"warn\")\n}\n\n@format(str, tokens) {\n  @sort(arr, mapfn) {\n    @bubbleSort(arr) {\n      let length = arr.len\n      for let i, length {\n        for let j, (length - i - 1) {\n          if (Obj:get(arr[j], \"index\") > Obj:get(arr[j + 1], \"index\")) {\n            let tmp = arr[j]\n            arr[j] = arr[j + 1]\n            arr[j + 1] = tmp\n          }\n        }\n      }\n      return arr\n    }\n    return bubbleSort(arr.map(mapfn)).map(@(obj) {\n      return Obj:get(obj, \"value\")\n    })\n  }\n  @flat(arr) {\n    @fn_isArr(val) {\n      return (Core:type(val) == \"arr\")\n    }\n    @fn_flat(arr) {\n      arr = arr.reduce(@(prev, val) {\n        if !(fn_isArr(val)) {\n          val = [val]\n        }\n        return prev.concat(val)\n      }, [])\n      if (arr.filter(fn_isArr).len != 0) {\n        arr = fn_flat(arr)\n      }\n      return arr\n    }\n    return fn_flat(arr.copy())\n  }\n  @at(arr, index) {\n    if (index < 0) return null\n    if (arr.len <= index) return null\n    return arr[index]\n  }\n  @startAt(arr) {\n    return at(arr, 0)\n  }\n  @lastAt(arr) {\n    return at(arr, (arr.len-1))\n  }\n\n  @toStr(strArr) {\n    return flat(strArr).map(@(strObj) {\n      return Obj:get(strObj, \"string\")\n    }).join(\"\")\n  }\n\n  tokens = sort(Obj:kvs(tokens), @(arr) {\n    let token = arr[0]\n    let value = arr[1]\n    return {\n      index: token.len\n      value: {\n        token: token\n        value: value\n      }\n    }\n  })\n  tokens.reverse()\n\n  str = str.split(\"\").reduce(@(prev, cur) {\n    if (cur == \"[\") {\n      prev.push({\n        string: \"\"\n        replaced: true\n      })\n    } elif (cur == \"]\") {\n      prev.push({\n        string: \"\"\n        replaced: false\n      })\n    } else {\n      let last = lastAt(prev)\n      let s = Obj:get(last, \"string\")\n      Obj:set(last, \"string\", `{s}{cur}`)\n    }\n    return prev\n  }, [{\n    string: \"\"\n    replaced: false\n  }])\n\n  let result = tokens.reduce(@(strArr, tokenObj) {\n    strArr = flat(strArr)\n    let t = Obj:get(tokenObj, \"token\")\n    let v = Obj:get(tokenObj, \"value\")\n    return strArr.map(@(strObj) {\n      let s = Obj:get(strObj, \"string\")\n      let r = Obj:get(strObj, \"replaced\")\n      if r {\n        return strObj\n      }\n      let a = s.split(t)\n      return a.reduce(@(prev, cur, index) { // index=1~len\n        if (cur != \"\") {\n          prev.push({\n            string: cur\n            replaced: false\n          })\n        }\n        if (a.len != (index + 1)) {\n          prev.push({\n            string: v\n            replaced: true\n          })\n        }\n        return prev\n      }, [])\n    })\n  }, str)\n\n  return toStr(result)\n}\n\n@DateObj(unixtime, minuteOffset) {\n  let YEAR_ONE = 365\n  let YEAR_FOUR = 1461\n  let YEAR_100 = 36524\n  let YEAR_400 = 146097\n  let EPOCH_DAY = 719468\n  let monthday = [0,31,61,92,122,153,184,214,245,275,306,337]\n\n  let result = {\n    unixtime: unixtime\n    minuteOffset: minuteOffset\n  }\n\n  unixtime = (unixtime + (minuteOffset * 60000))\n  var unixday = Math:floor((unixtime / 86400000))\n  var leap = 0\n  var year = 0\n  var month = null\n  var day = null\n  var n = null\n\n  var hour = (Math:floor((unixtime / 3600000)) % 24)\n  var minute = (Math:floor((unixtime / 60000)) % 60)\n  var second = (Math:floor((unixtime / 1000)) % 60)\n  var millisecond = (unixtime % 1000)\n  if (unixtime < 0) {\n    hour = (hour + 24)\n    minute = (minute + 60)\n    second = (second + 60)\n    millisecond = (millisecond + 1000)\n  }\n\n  let weekday = ((Math:floor((unixday + 4)) % 7) + 1)\n  if (weekday < 0) {\n    weekday = (weekday + 7)\n  }\n  unixday = (unixday + EPOCH_DAY)\n\n  year = (year + (400 * Math:floor((unixday / YEAR_400))))\n  unixday = (unixday % YEAR_400)\n  n = Math:floor((unixday / YEAR_100))\n  year = (year + (n * 100))\n  unixday = (unixday % YEAR_100)\n\n  if (n == 4) {\n    leap = 1\n  } else {\n    year = (year + (4 * Math:floor((unixday / YEAR_FOUR))))\n    unixday = (unixday % YEAR_FOUR)\n\n    n = Math:floor((unixday / YEAR_ONE))\n    year = (year + n)\n    unixday = (unixday % YEAR_ONE)\n    if (n == 4) {\n      leap = 1\n    }\n  }\n  if (leap != 0) {\n    month = 2\n    day = 29\n  } else {\n    month = Math:floor((((unixday * 5) + 2) / 153))\n    day = ((unixday - monthday[month]) + 1)\n    month = (month + 3)\n    if (month > 12) {\n      year = (year + 1)\n      month = (month - 12)\n    }\n  }\n\n  result.year = year\n  result.month = month\n  result.day = day\n  result.hour = hour\n  result.minute = minute\n  result.second = second\n  result.millisecond = millisecond\n  result.weekday = weekday\n\n  return result\n}\n@DateTokenObj(unixtime, minuteOffset) {\n  let d = DateObj(unixtime, minuteOffset)\n  let result = {}\n  @zeroPadding(n, length) {\n    let num = n\n    let abs = Math:abs(num)\n    let str = abs.to_str()\n    let sign = if (num < 0) \"-\" else \"\"\n    let len = Math:max(0, (length - str.len))\n    let pstr = if (len == 0) \"\" else Core:range(1, len).map(@(v){\"0\"}).join(\"\")\n    return `{sign}{pstr}{str}`\n  }\n  let z = zeroPadding\n\n  result.YY = z((d.year % 100), 2)\n  result.YYYY = z(d.year, 4)\n  result.M = z(d.month, 1)\n  result.MM = z(d.month, 2)\n  result.D = z(d.day, 1)\n  result.DD = z(d.day, 2)\n\n  result.d = z(d.weekday, 1)\n\n  var hour12 = (d.hour % 12)\n  if (hour12 == 0) {\n    hour12 = 12\n  }\n  result.H = z(d.hour, 1)\n  result.HH = z(d.hour, 2)\n  result.h = z(hour12, 1)\n  result.hh = z(hour12, 2)\n  result.m = z(d.minute, 1)\n  result.mm = z(d.minute, 2)\n  result.s = z(d.second, 1)\n  result.ss = z(d.second, 2)\n  result.SSS = z(d.millisecond, 3)\n\n  let tzoffset = Math:abs(d.minuteOffset)\n  let tzsign = if (d.minuteOffset < 0) \"-\" else \"+\"\n  let tzhour = z((Math:floor((tzoffset / 60)) % 60), 2)\n  let tzminute = z((tzoffset % 60), 2)\n  result.Z = `{tzsign}{tzhour}:{tzminute}`\n  result.ZZ = `{tzsign}{tzhour}{tzminute}`\n\n  result.A = if (d.hour < 12) \"AM\" else \"PM\"\n  result.a = if (d.hour < 12) \"am\" else \"pm\"\n\n  @indicator(n) {\n    let i = Math:abs(n)\n    let cent = (i % 100)\n    if Core:and((10 <= cent), (cent <= 20)) return `{n}th`\n    let dec = (i % 10)\n    match dec {\n      case 1 => return `{n}st`\n      case 2 => return `{n}nd`\n      case 3 => return `{n}rd`\n    }\n    return `{n}th`\n  }\n  result.Do = indicator(d.day)\n\n  var hour24 = (d.hour % 24)\n  if (hour24 == 0) {\n    hour24 = 24\n  }\n  result.k = z(hour24, 1)\n  result.kk = z(hour24, 2)\n  result.X = `{Math:floor((d.unixtime / 1000))}`\n  result.x = `{d.unixtime}`\n\n  return result\n}\n\n@dateformat(fmt, str, offset) {\n  return format(fmt, DateTokenObj(Date:parse(str), offset))\n}\n\nPlugin:register_note_action(\"投稿時刻を表示\", @(note) {\n  let formated = dateformat(c_format, note.createdAt, c_offset)\n  Mk:dialog(\"投稿時刻\", formated, \"info\")\n})\nPlugin:register_user_action(\"作成日時を表示\", @(user) {\n  let formated = dateformat(c_format, user.createdAt, c_offset)\n  Mk:dialog(\"作成日時\", formated, \"info\")\n})"}