{"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: [\"write:notes\", \"write:drive\", \"read:drive\"]\n  config: {\n    visibility: {\n      type: \"string\"\n      label: \"公開範囲\"\n      description: \"(既定値: auto) 以下から、投稿するノートの公開範囲を指定します。 auto public home followers\"\n      default: \"auto\"\n    }\n    localOnly: {\n      type: \"boolean\"\n      label: \"常にローカルでパクる\"\n      description: \"(既定値: 無効) 公開範囲が【auto】の場合、この指定は無視され、元のノートに追従します。\"\n      default: false\n    }\n    channel: {\n      type: \"boolean\"\n      label: \"元のチャンネルでパクる\"\n      description: \"(既定値: 有効) 公開範囲が【auto】の場合、この指定は無視され、元のノートに追従します。\"\n      default: true\n    }\n    reply: {\n      type: \"boolean\"\n      label: \"返信元でパクる\"\n      description: \"(既定値: 有効)\"\n      default: true\n    }\n    renote: {\n      type: \"boolean\"\n      label: \"引用もパクる\"\n      description: \"(既定値: 有効)\"\n      default: true\n    }\n    poll: {\n      type: \"boolean\"\n      label: \"投票もパクる\"\n      description: \"(既定値: 有効)\"\n      default: true\n    }\n    files: {\n      type: \"boolean\"\n      label: \"添付ファイルもパクる\"\n      description: \"(既定値: 有効) ドライブに保存・添付するため、時間を要することがあります。\"\n      default: true\n    }\n  }\n}\n\nlet c = {}\nc.visibility = Plugin:config.visibility\nif !([\"auto\", \"public\", \"home\", \"followers\"].incl(c.visibility)) {\n  c.visibility = \"auto\"\n  Mk:dialog(\"パクるプラグイン\", `公開範囲の指定に誤りがあります。{Str:lf}自動で **{c.visibility}** が適用されます。`, \"warning\")\n}\nc.localOnly = Plugin:config.localOnly\nc.channel = Plugin:config.channel\nc.reply = Plugin:config.reply\nc.renote = Plugin:config.renote\nc.poll = Plugin:config.poll\nc.files = Plugin:config.files\nc.auto = (c.visibility == \"auto\")\n\n@upload(files, callback) {\n  @at(arr, index) {\n    if (index < 0) return null\n    if (arr.len <= index) return null\n    return arr[index]\n  }\n  @lastAt(arr) {\n    return at(arr, (arr.len-1))\n  }\n  @fn_upload(file) {\n    let uuid = Util:uuid()\n    let uploadObj = {\n      url: file.url\n      force: true\n      isSensitive: file.isSensitive\n      comment: uuid\n    }\n    if (file.marker != null) {\n      uploadObj.marker = file.marker\n    }\n    Mk:api(\"drive/files/upload-from-url\", uploadObj)\n\n    return {\n      uuid: uuid\n      comment: file.comment\n    }\n  }\n\n  let latest = lastAt(Mk:api(\"drive/stream\", {limit: 1}))\n  var latestId = if (latest != null) Obj:get(latest, \"id\") else null\n  let arr = files.map(@(file){ fn_upload(file) })\n  let complete = Core:range(1, arr.len).map(@(v){ null })\n  let streamObj = {limit: arr.len}\n  if (latestId != null) {\n    streamObj.sinceId = latestId\n  }\n\n  let stop = Async:interval(2000, @() {\n    let result = Mk:api(\"drive/stream\", streamObj)\n    if (result != null) {\n      each let file, result {\n        var id = file.id\n        arr.map(@(obj, index) {\n          if (file.comment == obj.uuid) {\n            var file_ex = Mk:api(\"drive/files/update\", {\n              fileId: file.id\n              comment: obj.comment\n            })\n            complete[index] = file_ex\n            id = file_ex.id\n          }\n        })\n        latestId = id\n      }\n    }\n    if !(complete.incl(null)) {\n      stop()\n      callback(complete)\n    }\n  }, true)\n  return null\n}\n\n@parse(note, callback) {\n  @toBool(value) {\n    match value {\n      case true => return true\n      case false => return false\n      case \"\" => return false\n      case null => return false\n      case 0 => return false\n    }\n    return true\n  }\n  @or(arr) {\n    var bool = false\n    arr.find(@(v) {\n      return if toBool(v) {\n        bool = true\n        true\n      } else false\n    })\n    return bool\n  }\n  @and(arr) {\n    var bool = true\n    arr.find(@(v) {\n      return if toBool(v) false else {\n        bool = false\n        true\n      }\n    })\n    return bool\n  }\n\n  let obj = {\n    text: note.text\n    cw: note.cw\n  }\n  if c.auto {\n    obj.visibility = note.visibility\n    if (note.localOnly != null) {\n      obj.localOnly = note.localOnly\n    }\n    if (note.channelId != null) {\n      obj.channelId = note.channelId\n    }\n  } else {\n    obj.visibility = c.visibility\n    obj.localOnly = c.localOnly\n    if and([c.channel, note.channelId]) {\n      obj.channelId = note.channelId\n    }\n  }\n\n  if and([c.reply, note.replyId]) {\n    obj.replyId = note.replyId\n  }\n  if and([c.renote, note.renoteId]) {\n    obj.renoteId = note.renoteId\n  }\n  if and([c.poll, note.poll]) {\n    let poll = {\n      choices: note.poll.choices.map(@(choice) {\n        return if (Core:type(choice) == \"obj\") Obj:get(choice, \"text\") else choice\n      })\n    }\n    if (note.poll.multiple != null) {\n      poll.multiple = note.poll.multiple\n    }\n    if (note.poll.expiresAt != null) {\n      let diff = (Date:parse(note.poll.expiresAt) - Date:parse(note.createdAt))\n      poll.expiredAfter = diff\n    }\n    obj.poll = poll\n  }\n  if and([c.files, note.files.len]) {\n    upload(note.files, @(files) {\n      obj.fileIds = files.map(@(file) { file.id })\n      callback(obj)\n    })\n  } else {\n    callback(obj)\n  }\n  return null\n}\n\nPlugin:register_note_action(\"パクる\", @(note) {\n  parse(note, @(parsed) {\n    Mk:api(\"notes/create\", parsed)\n  })\n})"}