Add: plugin system[WIP]
This commit is contained in:
parent
8873af4597
commit
7169f1147b
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -25,3 +25,4 @@ app/git
|
|||
*.code-workspace
|
||||
releasenote.md
|
||||
app/yarn-error.log
|
||||
app/js/platform/aiscript.js
|
||||
|
|
10
app/aiscript.js
Normal file
10
app/aiscript.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
const { AiScript, parse, values, utils } = require('@syuilo/aiscript')
|
||||
global.asValue = values
|
||||
global.AiScript = AiScript
|
||||
global.asParse = parse
|
||||
global.asCommon = {
|
||||
'TheDesk:console': values.FN_NATIVE((z) => {
|
||||
console.log(z[0].value)
|
||||
})
|
||||
}
|
||||
global.asUtil = utils
|
|
@ -1,3 +1,9 @@
|
|||
window.onload = function () {
|
||||
console.log('loaded')
|
||||
initPostbox()
|
||||
connection()
|
||||
initPlugin(plugins)
|
||||
}
|
||||
$.strip_tags = function (str, allowed) {
|
||||
if (!str) {
|
||||
return ''
|
||||
|
|
152
app/js/platform/plugin.js
Normal file
152
app/js/platform/plugin.js
Normal file
|
@ -0,0 +1,152 @@
|
|||
|
||||
var plugins = getPlugin()
|
||||
function getPlugin() {
|
||||
const json = localStorage.getItem('plugins')
|
||||
let ret = {
|
||||
buttonOnPostbox: [],
|
||||
buttonOnToot: []
|
||||
}
|
||||
//if(!json) return ret
|
||||
//const plugins = JSON.parse(json)
|
||||
const plugins = [
|
||||
{
|
||||
id: randomStr(20),
|
||||
content: `### {
|
||||
name: "マイ・ファースト・プラグイン"
|
||||
version: 1
|
||||
event: "buttonOnPostbox"
|
||||
author: "Cutls P"
|
||||
}
|
||||
`
|
||||
}
|
||||
]
|
||||
for (let plugin of plugins) {
|
||||
const meta = getMeta(plugin.content)
|
||||
if (!meta) continue
|
||||
const type = meta.event
|
||||
ret[type] ? ret[type].push(plugin) : ret[type] = [plugin]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
function initPlugin() {
|
||||
asCommon['TheDesk:dialog'] = asValue.FN_NATIVE((z) => {
|
||||
Swal.fire({
|
||||
title: z[0].value,
|
||||
icon: z[2] ? z[2].value : 'info',
|
||||
text: z[1] ? z[1].value : ''
|
||||
})
|
||||
})
|
||||
asCommon['TheDesk:confirm'] = asValue.FN_NATIVE(async (z) => {
|
||||
const alert = await Swal.fire({
|
||||
title: z[0].value,
|
||||
text: z[1].value,
|
||||
icon: z[2] ? z[2].value : 'info',
|
||||
showCancelButton: true
|
||||
})
|
||||
return asUtil.jsToVal(!!(alert.value && alert.value === true))
|
||||
})
|
||||
asCommon['TheDesk:css'] = asValue.FN_NATIVE((z) => {
|
||||
$(escapeHTML(z[0].value)).css(escapeHTML(z[1].value), escapeHTML(z[2].value))
|
||||
})
|
||||
asCommon['TheDesk:api'] = asValue.FN_NATIVE(async (z) => {
|
||||
try {
|
||||
if (!getMeta(exe).apiGet && z[0].value == "GET") return asUtil.jsToVal(false)
|
||||
if (!getMeta(exe).apiPost && (z[0].value == "POST" || z[0].value == "DELETE" || z[0].value == "PUT")) return asUtil.jsToVal(false)
|
||||
const domain = localStorage.getItem(`domain_${z[3].value}`)
|
||||
const at = localStorage.getItem(`acct_${z[3].value}_at`)
|
||||
const start = `https://${domain}/api/${z[1].value}`
|
||||
const q = {
|
||||
method: z[0].value,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
Authorization:
|
||||
`Bearer ${at}`
|
||||
}
|
||||
}
|
||||
if (z[2]) q.body = z[2].value
|
||||
const promise = await fetch(start, q)
|
||||
const json = await promise.json()
|
||||
return asUtil.jsToVal(json)
|
||||
} catch (e) {
|
||||
return asUtil.jsToVal(e)
|
||||
}
|
||||
|
||||
})
|
||||
const { buttonOnPostbox, init } = plugins
|
||||
for (let target of buttonOnPostbox) {
|
||||
const meta = getMeta(target.content)
|
||||
$('#dropdown2').append(`<li><a onclick="execPlugin('${target.id}','buttonOnPostbox', null);">${escapeHTML(meta.name)}</a></li>`)
|
||||
}
|
||||
for (let target of init) {
|
||||
const as = new AiScript(asCommon)
|
||||
const meta = getMeta(target.content)
|
||||
M.toast({ html: `${escapeHTML(meta.name)}を実行しました`, displayLength: 1000 })
|
||||
if (target) as.exec(asParse(target.content))
|
||||
}
|
||||
}
|
||||
function getMeta(plugin) {
|
||||
try {
|
||||
return AiScript.collectMetadata(asParse(plugin)).get(null)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
async function execPlugin(id, source, args) {
|
||||
const coh = plugins[source]
|
||||
let exe = null
|
||||
for (let plugin of coh) {
|
||||
if (plugin.id == id) {
|
||||
exe = plugin.content
|
||||
break
|
||||
}
|
||||
}
|
||||
const common = _.cloneDeep(asCommon)
|
||||
if (source == 'buttonOnToot') {
|
||||
common.DATA = args
|
||||
const domain = localStorage.getItem(`domain_${args.acct_id}`)
|
||||
const at = localStorage.getItem(`acct_${args.acct_id}_at`)
|
||||
const start = `https://${domain}/api/v1/statuses/${args.id}`
|
||||
const promise = await fetch(start, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
Authorization:
|
||||
`Bearer ${at}`
|
||||
}
|
||||
})
|
||||
const json = await promise.json()
|
||||
common.TOOT = asUtil.jsToVal(json)
|
||||
common['TheDesk:changeText'] = asValue.FN_NATIVE((z) => {
|
||||
if (getMeta(exe).dangerHtml) $(`[unique-id=${args.id}] .cvo`).html(z[0].value)
|
||||
})
|
||||
} else if (source == 'buttonOnPostbox') {
|
||||
const postDt = post(null, false, true)
|
||||
common.POST = asUtil.jsToVal(postDt)
|
||||
common.ACCT_ID = asUtil.jsToVal(postDt.TheDeskAcctId)
|
||||
common['TheDesk:postText'] = asValue.FN_NATIVE((z) => {
|
||||
$('#textarea').val(z[0].value)
|
||||
})
|
||||
common['TheDesk:postCW'] = asValue.FN_NATIVE((z) => {
|
||||
if (z[1]) $('#cw-text').val(z[1].value)
|
||||
cw(z[0] ? z[0].value : false)
|
||||
})
|
||||
common['TheDesk:postNSFW'] = asValue.FN_NATIVE((z) => {
|
||||
nsfw(z[0] ? z[0].value : false)
|
||||
})
|
||||
common['TheDesk:postVis'] = asValue.FN_NATIVE((z) => {
|
||||
vis(z[0].value)
|
||||
})
|
||||
common['TheDesk:postClearbox'] = asValue.FN_NATIVE(() => {
|
||||
clear()
|
||||
})
|
||||
common['TheDesk:postExec'] = asValue.FN_NATIVE(() => {
|
||||
if (getMeta(exe).apiPost) post()
|
||||
})
|
||||
}
|
||||
common['TheDesk:console'] = asValue.FN_NATIVE((z) => {
|
||||
console.log(z[0].value)
|
||||
})
|
||||
const as = new AiScript(common)
|
||||
if (exe) as.exec(asParse(exe))
|
||||
}
|
|
@ -1,14 +1,14 @@
|
|||
/*保護系*/
|
||||
//画像保護
|
||||
function nsfw() {
|
||||
if ($('#nsfw').hasClass('nsfw-avail')) {
|
||||
$('#nsfw').removeClass('yellow-text')
|
||||
$('#nsfw').html('visibility_off')
|
||||
$('#nsfw').removeClass('nsfw-avail')
|
||||
} else {
|
||||
function nsfw(force) {
|
||||
if (force || !$('#nsfw').hasClass('nsfw-avail')) {
|
||||
$('#nsfw').addClass('yellow-text')
|
||||
$('#nsfw').html('visibility')
|
||||
$('#nsfw').addClass('nsfw-avail')
|
||||
} else {
|
||||
$('#nsfw').removeClass('yellow-text')
|
||||
$('#nsfw').html('visibility_off')
|
||||
$('#nsfw').removeClass('nsfw-avail')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,12 +80,7 @@ loadVis()
|
|||
|
||||
//コンテントワーニング
|
||||
function cw(force) {
|
||||
if ($('#cw').hasClass('cw-avail') || !force) {
|
||||
$('#cw-text').val()
|
||||
$('#cw-text').hide()
|
||||
$('#cw').removeClass('yellow-text')
|
||||
$('#cw').removeClass('cw-avail')
|
||||
} else {
|
||||
if (force || !$('#cw').hasClass('cw-avail')) {
|
||||
$('#cw-text').show()
|
||||
$('#cw').addClass('yellow-text')
|
||||
$('#cw').addClass('cw-avail')
|
||||
|
@ -93,6 +88,11 @@ function cw(force) {
|
|||
if (cwt) {
|
||||
$('#cw-text').val(cwt)
|
||||
}
|
||||
} else {
|
||||
$('#cw-text').val()
|
||||
$('#cw-text').hide()
|
||||
$('#cw').removeClass('yellow-text')
|
||||
$('#cw').removeClass('cw-avail')
|
||||
}
|
||||
}
|
||||
//TLでコンテントワーニングを表示トグル
|
||||
|
|
|
@ -437,7 +437,6 @@ function draftToPost(json, acct_id, id) {
|
|||
$('#post-acct-sel').val(acct_id)
|
||||
$('select').formSelect()
|
||||
mdCheck()
|
||||
var medias = $('[toot-id=' + id + ']').attr('data-medias')
|
||||
mediack = null
|
||||
if(json.media_attachments) mediack = json.media_attachments[0]
|
||||
//メディアがあれば
|
||||
|
@ -684,9 +683,9 @@ function staEx(mode) {
|
|||
})
|
||||
return
|
||||
}
|
||||
function toggleAction(id) {
|
||||
const elm = document.getElementById(id)
|
||||
const instance = M.Dropdown.init(elm);
|
||||
function toggleAction(elm) {
|
||||
console.log(elm)
|
||||
const instance = M.Dropdown.init(elm)
|
||||
console.log(instance.isOpen)
|
||||
instance.open()
|
||||
}
|
||||
|
|
|
@ -334,9 +334,14 @@ function cardCheck(tlid) {
|
|||
}
|
||||
}
|
||||
|
||||
function mov(id, tlid, type) {
|
||||
const dropdownTrigger = `dropdown_${tlid}_${id}`
|
||||
const elm = document.getElementById(dropdownTrigger)
|
||||
function mov(id, tlid, type, rand, target) {
|
||||
const dropdownTrigger = `dropdown_${rand}`
|
||||
let elm = document.querySelector(`#timeline_${tlid} #${dropdownTrigger}`)
|
||||
if(tlid == 'notf') {
|
||||
const timeline = $(target).parents('.notf-indv-box').attr('id')
|
||||
elm = document.querySelector(`#${timeline} #${dropdownTrigger}`)
|
||||
console.log(`#${timeline} #${dropdownTrigger}`)
|
||||
}
|
||||
const instance = M.Dropdown.getInstance(elm)
|
||||
if(instance) {
|
||||
if(instance.isOpen) return false
|
||||
|
|
|
@ -765,9 +765,10 @@ function misskeyParse(obj, mix, acct_id, tlid, popup, mutefilter) {
|
|||
} else {
|
||||
var actemojick = false
|
||||
}
|
||||
var rand = randomStr(8)
|
||||
templete = templete + '<div id="pub_' + toot.id + '" class="cvo ' +
|
||||
boostback + ' ' + fav_app + ' ' + rt_app + ' ' + hasmedia + '" toot-id="' + id + '" unique-id="' + uniqueid + '" data-medias="' + media_ids + ' " unixtime="' + date(obj[
|
||||
key].created_at, 'unix') + '" ' + if_notf + ' onmouseover="mov(\'' + toot.id + '\',\'' + tlid + '\',\'mv\')" onclick="mov(\'' + toot.id + '\',\'' + tlid + '\',\'cl\')" onmouseout="resetmv(\'mv\')" reacted="' + reacted + '">' +
|
||||
key].created_at, 'unix') + '" ' + if_notf + ' onmouseover="mov(\'' + toot.id + '\',\'' + tlid + '\',\'mv\', \''+rand+'\')" onclick="mov(\'' + toot.id + '\',\'' + tlid + '\',\'cl\', \''+rand+'\')" onmouseout="resetmv(\'mv\')" reacted="' + reacted + '">' +
|
||||
'<div class="area-notice"><span class="gray sharesta">' + notice + home +
|
||||
'</span></div>' +
|
||||
'<div class="area-icon"><a onclick="udg(\'' + toot.user.id +
|
||||
|
|
|
@ -271,8 +271,7 @@ function parse(obj, mix, acct_id, tlid, popup, mutefilter, type) {
|
|||
var noticetext = `<span onclick="notfFilter('${toot.account.id}','${tlid}');" class=" pointer big-text ${notfFilHide}"><i class="fas fa-filter"
|
||||
title="${lang.lang_parse_notffilter}">
|
||||
</i><span class="voice">${lang.lang_parse_notffilter}</span></span>
|
||||
<span class="cbadge cbadge-hover" title="${date(toot.created_at, 'absolute')}(${
|
||||
lang.lang_parse_notftime
|
||||
<span class="cbadge cbadge-hover" title="${date(toot.created_at, 'absolute')}(${lang.lang_parse_notftime
|
||||
})" aria-hidden="true"><i class="far fa-clock"></i>
|
||||
${date(toot.created_at, datetype)}
|
||||
</span>
|
||||
|
@ -709,8 +708,7 @@ function parse(obj, mix, acct_id, tlid, popup, mutefilter, type) {
|
|||
var featured = ` <a onclick="tagFeature('${tag.name}','${acct_id}')" class="pointer" title="add it to Featured tags">Feature</a> `
|
||||
tags =
|
||||
tags +
|
||||
`<span class="hide" data-tag="${tag.name}" data-regTag="${tag.name.toLowerCase()}">#${
|
||||
tag.name
|
||||
`<span class="hide" data-tag="${tag.name}" data-regTag="${tag.name.toLowerCase()}">#${tag.name
|
||||
}:
|
||||
<a onclick="tl('tag','${tag.name}','${acct_id}','add')" class="pointer"
|
||||
title="${lang.lang_parse_tagTL.replace(
|
||||
|
@ -957,11 +955,9 @@ function parse(obj, mix, acct_id, tlid, popup, mutefilter, type) {
|
|||
bgColorCSS = bgColorCSS + bg + ','
|
||||
}
|
||||
bgColorCSS = `linear-gradient(90deg, ${bgColorCSS} transparent)`
|
||||
var tickerdom = `<div aria-hidden="true" style="user-select:none;cursor:default;background:${bgColorCSS} !important; color:${
|
||||
fontColor
|
||||
var tickerdom = `<div aria-hidden="true" style="user-select:none;cursor:default;background:${bgColorCSS} !important; color:${fontColor
|
||||
};width:100%; height:0.9rem; font-size:0.8rem;" class="tickers">
|
||||
<img draggable="false" src="${
|
||||
value.favicon
|
||||
<img draggable="false" src="${value.favicon
|
||||
}" style="height:100%;" onerror="this.src=\'../../img/loading.svg\'" loading="lazy">
|
||||
<span style="position:relative; top:-0.2rem;">${escapeHTML(value.name)}</span>
|
||||
</div>`
|
||||
|
@ -981,8 +977,7 @@ function parse(obj, mix, acct_id, tlid, popup, mutefilter, type) {
|
|||
poll +
|
||||
`<div class="quote-renote">
|
||||
<div class="renote-icon">
|
||||
<a onclick="udg('${toot.quote.account.id}','${acct_id}');" user="${
|
||||
toot.quote.account.acct
|
||||
<a onclick="udg('${toot.quote.account.id}','${acct_id}');" user="${toot.quote.account.acct
|
||||
}" class="udg">
|
||||
<img draggable="false" src="${toot.quote.account.avatar}" loading="lazy">
|
||||
</a>
|
||||
|
@ -994,8 +989,7 @@ function parse(obj, mix, acct_id, tlid, popup, mutefilter, type) {
|
|||
${toot.quote.content}
|
||||
</div>
|
||||
<div class="renote-details">
|
||||
<a onclick="details('${
|
||||
toot.quote.id
|
||||
<a onclick="details('${toot.quote.id
|
||||
}','${acct_id}','${tlid}','normal')" class="waves-effect waves-dark btn-flat details" style="padding:0">
|
||||
<i class="text-darken-3 material-icons">more_vert</i>
|
||||
</a>
|
||||
|
@ -1022,6 +1016,15 @@ function parse(obj, mix, acct_id, tlid, popup, mutefilter, type) {
|
|||
if (trans != '') {
|
||||
menuct++
|
||||
}
|
||||
//このトゥート内のアクションを完了させるために、適当にIDを振る
|
||||
var rand = randomStr(8)
|
||||
//プラグイン機構
|
||||
var plugin = plugins.buttonOnToot
|
||||
var pluginHtml = ''
|
||||
for (let target of plugin) {
|
||||
const meta = getMeta(target.content)
|
||||
pluginHtml = pluginHtml + `<li><a onclick="execPlugin('${target.id}','buttonOnToot',{id: '${uniqueid}', acct_id: '${acct_id}'});">${escapeHTML(meta.name)}</a></li>`
|
||||
}
|
||||
templete =
|
||||
templete +
|
||||
`<div
|
||||
|
@ -1032,8 +1035,8 @@ function parse(obj, mix, acct_id, tlid, popup, mutefilter, type) {
|
|||
'unix'
|
||||
)}"
|
||||
${if_notf}
|
||||
onmouseover="mov('${uniqueid}','${tlid}','mv')"
|
||||
onclick="mov('${uniqueid}','${tlid}','cl')"
|
||||
onmouseover="mov('${uniqueid}','${tlid}','mv', '${rand}', this)"
|
||||
onclick="mov('${uniqueid}','${tlid}','cl', '${rand}', this)"
|
||||
onmouseout="resetmv('mv')"
|
||||
>
|
||||
<div class="area-notice grid"><span class="gray sharesta">${notice}${home}</span></div>
|
||||
|
@ -1094,8 +1097,7 @@ function parse(obj, mix, acct_id, tlid, popup, mutefilter, type) {
|
|||
</a>
|
||||
</div>
|
||||
<div class="action ${can_rt} ${disp['rt']} ${noauth}">
|
||||
<a onclick="rt('${
|
||||
toot.id
|
||||
<a onclick="rt('${toot.id
|
||||
}','${acct_id}','${tlid}')" class="waves-effect waves-dark btn-flat actct bt-btn"
|
||||
style="padding:0" title="${lang.lang_parse_bt}">
|
||||
<i class="fas fa-retweet ${if_rt} rt_${toot.id}"></i>
|
||||
|
@ -1130,8 +1132,8 @@ function parse(obj, mix, acct_id, tlid, popup, mutefilter, type) {
|
|||
</div>
|
||||
<div class="area-side">
|
||||
<div class="action ${noauth}">
|
||||
<a onclick="toggleAction('trigger_${tlid}_${uniqueid}')" data-target="dropdown_${tlid}_${uniqueid}"
|
||||
class="ctxMenu waves-effect waves-dark btn-flat" style="padding:0" id="trigger_${tlid}_${uniqueid}">
|
||||
<a onclick="toggleAction(this)" data-target="dropdown_${rand}"
|
||||
class="ctxMenu waves-effect waves-dark btn-flat" style="padding:0" id="trigger_${rand}">
|
||||
<i class="text-darken-3 material-icons act-icon" aria-hidden="true">expand_more</i>
|
||||
<span class="voice">Other actions</span>
|
||||
</a>
|
||||
|
@ -1144,7 +1146,7 @@ function parse(obj, mix, acct_id, tlid, popup, mutefilter, type) {
|
|||
<span class="voice">${lang.lang_parse_detail}</span>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="dropdown-content contextMenu" id="dropdown_${tlid}_${uniqueid}">
|
||||
<ul class="dropdown-content contextMenu" id="dropdown_${rand}">
|
||||
<li class="${viashow} via-dropdown" onclick="client('${$.strip_tags(via)}')" title="${lang.lang_parse_clientop}">
|
||||
via ${escapeHTML(via)}</a>
|
||||
</li>
|
||||
|
@ -1169,6 +1171,7 @@ function parse(obj, mix, acct_id, tlid, popup, mutefilter, type) {
|
|||
style="padding:0">
|
||||
<i class="fas text-darken-3 fa-globe"></i>${lang.lang_parse_link}
|
||||
</li>
|
||||
${pluginHtml}
|
||||
</ul>
|
||||
</div>
|
||||
`
|
||||
|
|
|
@ -101,7 +101,6 @@ if (location.search) {
|
|||
$('.mini-btn').text('expand_less')
|
||||
}
|
||||
}
|
||||
window.onload = function () { initPostbox(); connection() }
|
||||
function initPostbox() {
|
||||
$('#posttgl').click(function (e) {
|
||||
if (!$('#post-box').hasClass('appear')) {
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
"main": "main.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"construct": "cd view/make && node make --automatic && cd ../../",
|
||||
"construct:store": "cd view/make && node make --automatic --store && cd ../../",
|
||||
"construct": "cd view/make && node make --automatic && cd ../../ && browserify aiscript.js -o js/platform/aiscript.js",
|
||||
"construct:store": "cd view/make && node make --automatic --store && cd ../../ && browserify aiscript.js -o js/platform/aiscript.js",
|
||||
"dev": "npx electron ./ --dev",
|
||||
"dist": "build --linux snap",
|
||||
"watchview": "node view/make/make.js --automatic --watch",
|
||||
|
@ -60,6 +60,7 @@
|
|||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.15.1",
|
||||
"@syuilo/aiscript": "^0.11.1",
|
||||
"electron-dl": "^3.0.2",
|
||||
"jimp": "^0.16.1",
|
||||
"jquery": "^3.5.1",
|
||||
|
@ -76,6 +77,7 @@
|
|||
"itunes-nowplaying-mac": "0.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^17.0.0",
|
||||
"chokidar": "^3.4.3",
|
||||
"electron": "^10.1.5",
|
||||
"electron-builder": "^22.9.1",
|
||||
|
|
|
@ -1221,8 +1221,10 @@
|
|||
<!--JS-->
|
||||
<script type="text/javascript" src="../../@@node_base@@/jquery/dist/jquery.js"></script>
|
||||
<script type="text/javascript" src="../../js/platform/first.js"></script>
|
||||
<script type="text/javascript" src="../../@@node_base@@/grapheme-splitter/index.js"></script>
|
||||
<script type="text/javascript" src="../../js/platform/aiscript.js"></script>
|
||||
<script type="text/javascript" src="../../js/platform/plugin.js"></script>
|
||||
<script type="text/javascript" src="../../@@node_base@@/materialize-css/dist/js/materialize.js"></script>
|
||||
<script type="text/javascript" src="../../@@node_base@@/grapheme-splitter/index.js"></script>
|
||||
<script type="text/javascript" src="../../@@node_base@@/lodash/lodash.min.js"></script>
|
||||
<script type="text/javascript" src="main.js"></script>
|
||||
<script type="text/javascript" src="../../js/common/time.js"></script>
|
||||
|
|
|
@ -385,13 +385,6 @@
|
|||
</template><br>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="collapsible-header">
|
||||
<i class="material-icons">keyboard</i>@@keysc@@
|
||||
</div>
|
||||
<div class="collapsible-body">
|
||||
<h5>@@iks@@</h5>
|
||||
@@okswarn@@<br>
|
||||
Ctrl+Shift+1:<input type="text" style="width:11.5rem" id="oks-1">
|
||||
|
@ -400,6 +393,15 @@
|
|||
<button onclick="oks(2)" class="btn waves-effect" style="width:7.7rem;">@@set@@</button><br><br>
|
||||
Ctrl+Shift+3:<input type="text" style="width:11.5rem" id="oks-3">
|
||||
<button onclick="oks(3)" class="btn waves-effect" style="width:7.7rem;">@@set@@</button><br><br>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="collapsible-header">
|
||||
<i class="material-icons">power</i>@@plugin@@
|
||||
</div>
|
||||
<div class="collapsible-body">
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
|
|
1054
app/yarn.lock
1054
app/yarn.lock
File diff suppressed because it is too large
Load Diff
117
plugin.md
Normal file
117
plugin.md
Normal file
|
@ -0,0 +1,117 @@
|
|||
# TheDesk Plugin
|
||||
|
||||
[AiScript](https://github.com/syuilo/aiscript)で書きます。
|
||||
|
||||
[AiScriptの書き方](https://github.com/syuilo/aiscript/blob/master/docs/get-started.md)
|
||||
|
||||
## メタデータ
|
||||
```
|
||||
### {
|
||||
name: "マイ・ファースト・プラグイン"
|
||||
version: 1
|
||||
event: "buttonOnPostbox"
|
||||
author: "Cutls P"
|
||||
}
|
||||
```
|
||||
これを冒頭に入れます。
|
||||
|
||||
* dangerHtml: true|false
|
||||
`TheDesk:changeText`にアクセスするために必要です。
|
||||
* apiGetl: true|false
|
||||
`TheDesk:api`にGETメソッドでアクセスするときに必要です。
|
||||
* apiPost: true|false
|
||||
`TheDesk:api`にPOST/PUT/DELETEメソッドでアクセスするときや、`postExec`を実行するときに必要です。
|
||||
|
||||
### event
|
||||
|
||||
eventに設定できるもの
|
||||
|
||||
* `buttonOnPostbox`
|
||||
投稿フォームの…(90°回転)で出てくるメニュー内に表示されます
|
||||
* `buttonOnToot`
|
||||
トゥートの詳細メニューに表示されます
|
||||
* `init`
|
||||
起動時(なるべく早い段階で)
|
||||
|
||||
追加予定…
|
||||
|
||||
## 変数
|
||||
|
||||
### buttonOnTootのとき
|
||||
|
||||
* DATA
|
||||
```
|
||||
{
|
||||
id: "トゥートのID文字列",
|
||||
acct_id: "アカウントのTheDesk内部ID"
|
||||
}
|
||||
```
|
||||
* TOOT
|
||||
|
||||
トゥートのAPIを叩いた時と同じオブジェクトが返ります。なお、プラグインが実行されてから取得します。
|
||||
プラグインの実行ボタン押下から実行までの時間差はこれによるものです。
|
||||
|
||||
### buttonOnPostboxのとき
|
||||
|
||||
* POST
|
||||
投稿するときのオブジェクトがそのまま入りますが、`TheDeskAcctId`というTheDeskが内部で扱うアカウントのID(string)が入ったプロパティが追加されます。
|
||||
* ACCT_ID
|
||||
TheDeskが内部で扱うアカウントのID(string)
|
||||
|
||||
|
||||
## 関数
|
||||
|
||||
### TheDesk:dialog(title: string, text: string, type?: string)
|
||||
typeのデフォルトは'info'で、他に'error','question','success'などがある
|
||||
|
||||
### TheDesk:confirm(title: string, text: string, type?: string)
|
||||
typeのデフォルトは'info'で、他に'error','question','success'などがある
|
||||
返り値はboolean(true|false)
|
||||
|
||||
### TheDesk:css(query: string, attr: string, val: string)
|
||||
jQueryの`$(query).css(attr, val)`に相当
|
||||
|
||||
### TheDesk:api(method: 'GET'|'POST'|'PUT'|'DELETE', endpoint: string, body: string, acct_id: string)
|
||||
bodyにもstringを投げてください。
|
||||
endpointは`v1`から書いてください。(`v1/accounts...`)
|
||||
|
||||
返り値はjsonのオブジェクト。
|
||||
|
||||
### TheDesk:changeText(body: string)
|
||||
`buttonOnToot`で使用可能
|
||||
|
||||
該当トゥート(や他タイムラインの同一トゥート)のテキストを書き換えます。
|
||||
`dangerHtml`をtrueにしてください。
|
||||
HTMLを引数にすることに留意してください。
|
||||
|
||||
### TheDesk:postText(text: string)
|
||||
`buttonOnPostbox`で使用可能
|
||||
|
||||
トゥートボックスの中身を書き換えます。
|
||||
|
||||
### TheDesk:postCW(force: boolean, text: string)
|
||||
`buttonOnPostbox`で使用可能
|
||||
|
||||
CWを切り替えます。forceはデフォルトでfalseで、trueにするとオンに、falseにするとトグルになります。
|
||||
textには警告文を入れます。
|
||||
|
||||
### TheDesk:postNSFW(force: boolean)
|
||||
`buttonOnPostbox`で使用可能
|
||||
|
||||
NSFWを切り替えます。forceはデフォルトでfalseで、trueにするとオンに、falseにするとトグルになります。
|
||||
|
||||
### TheDesk:postVis(vis: 'public'|'unlisted'|'private'|'direct')
|
||||
`buttonOnPostbox`で使用可能
|
||||
|
||||
公開範囲を変更します。
|
||||
|
||||
### TheDesk:postNSFW(force: postClearbox)
|
||||
`buttonOnPostbox`で使用可能
|
||||
|
||||
投稿ボックスをクリアします。
|
||||
|
||||
### TheDesk:postExec()
|
||||
`buttonOnPostbox`で使用可能
|
||||
|
||||
`apiPost`をtrueにしてください。
|
||||
トゥートボタンを押したのと同じ挙動をします。
|
Loading…
Reference in New Issue
Block a user