The formatting is a little bit ugly, but here's a script that will let you do that. Just run: !macro-cleanup And hit the ❌ next to a player name to remove all their macros. You can also remove individual macros with the ❌ next to them. code: on('ready',() => {
// ❌
const s = {
button: `font-size: .6em; border: 1px solid #999;background-color: #ccc; border-radius: 1em; padding: .1em .3em;min-width:1.5em;text-align:center;`,
tokenAction: `background: green; font-weight: bold; border: 1px solid #333; color: white;`
};
const playerName = (()=>{
let players = findObjs({type:'player'})
.reduce((m,p)=>({...m, [p.id]: p.get('displayname')}),{});
return (pid) => players[pid] || '[Unknown]';
})();
const f = {
li: (c) => `<li>${c}</li>`,
ul: (c) => `<ul>${c}</ul>`,
ol: (c) => `<ol>${c}</ol>`,
b: (c) => `<b>${c}</b>`,
subhead: (c) => `<h4>${c}</h4>`,
ta: () => `<span style="${s.tokenAction}">TA</span>`,
button: (label,command) => `<a style="${s.button}" href="${command}">${label}</a>`,
mac: (m) => `${f.b(m.get('name'))} ${m.get('istokenaction') ? f.ta() : ''} ${f.button(`❌`,`!macro-cleanup ${m.id}`)}`,
pla: (p,ms) => `${f.subhead(`${playerName(p)} ${f.button(`❌`,`!macro-cleanup ${ms.map(m=>m.id).join(' ')}`)}`)}${f.ul(ms.map(f.mac).map(f.li).join(''))}`,
tree: (tree) => Object.keys(tree).map(pid=>f.pla(pid,tree[pid])).join('')
};
on('chat:message', (msg) => {
if('api' === msg.type && /^!macro-cleanup(\b\s|$)/i.test(msg.content) && playerIsGM(msg.playerid) ){
let who = (getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname');
let args = msg.content.split(/\s+/).slice(1);
if(args.length){
_.chain(args)
.map((id)=>getObj('macro',id))
.reject(_.isUndefined)
.tap((ms)=>sendChat('',`/w "${who}" ${ms.length} removed.`))
.each((m)=>m.remove());
} else {
let macroTree = findObjs({type:'macro'})
.reduce((m,mac)=>({
...m,
[mac.get('playerid')]:[
...(m[mac.get('playerid')]||[]),
mac
]
}),{});
sendChat('',`/w "${who}" ${f.tree(macroTree)}`);
}
}
});
});