Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

[Script] Lister

1632332238

Edited 1665904009
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
This script was superseded by Campaign Survey .&nbsp; Lister is a scriptlet that looks through your campaign and lists characters, handouts, pages, rollable tables and players. I created it for some administrative accounting reasons, but thought I would share. No guarantees this won't break. :) Syntax: !makelist --[characters,handouts,pages,tables,players,makehandout] You can use multiple arguments, separated by spaces, ex: !makelist --characters handouts In the case of characters , handouts , and tables the list is in the form of links. If you click on a character or handout name, it will open the journal item. If you click on a table, it will roll the table. In the case of players , it will give you a list of players and their playerids, which can be a few steps to find otherwise. If you click on the name, this will take you to the profile page of the player as an external link. This can be useful if you need to send them an out-of-game PM, for instance. If you click on the color box next to the player name, it will issue a reporter macro to give you a list of all characters in the campaign that the player controls. (It does not account for "all players" or multiple controllers. the player must be the first controller listed on the character) makehandout updates a handout called "Lister Report" and sends the output there instead of to chat. If no handout exists by that name it will create one. If you by some bizarre chance have a handout called "Lister Report", this script will overwrite the contents. &nbsp; Handout screenshot: Player screenshot: Clicking on player color (if you have installed Reporter—otherwise nothing will happen) Code: on('chat:message', (msg_orig) =&gt; { &nbsp; &nbsp; let msg = _.clone(msg_orig); &nbsp; &nbsp; if (!/^!makelist/.test(msg.content)) { &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; } &nbsp; &nbsp; function makeButton(name, link) { &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;a style = ' + buttonStyle + ' href="' + link + '"&gt;' + name + '&lt;/a&gt;'; &nbsp; &nbsp; } &nbsp; &nbsp; function reporterMacro(id) { &nbsp; &nbsp; &nbsp; &nbsp; return '&lt;a style = ' + buttonStyle + ' href="' + link + '"&gt;' + name + '&lt;/a&gt;'; &nbsp; &nbsp; } &nbsp; &nbsp; function makeBox(color, id, name) { &nbsp; &nbsp; &nbsp; &nbsp; return `&lt;a href = '!report||+|c|controlledby|${id} -- --- ----compact|true showheader|false showfooter|false title|Characters of ${name}|' style= 'float: left;&nbsp; height: 30px; width: 10px;&nbsp; margin-top: 2px; margin-right: 2px; background-color:${color}; border: 1px solid black; clear: both;'&lt;/a&gt;`; &nbsp; &nbsp; } &nbsp; &nbsp; function makeTableLink(name) { &nbsp; &nbsp; &nbsp; &nbsp; log('name is ' + name); &nbsp; &nbsp; &nbsp; &nbsp; return `&lt;a href = '!&amp;#10;&amp;#47;gmroll 1t[${name}]'&gt;${name}&lt;/a&gt;`; &nbsp; &nbsp; } &nbsp; &nbsp; const closeReport = '&lt;/div&gt;'; &nbsp; &nbsp; const openReport = "&lt;div style='color: #000; border: 1px solid #000; background-color: #fff; box-shadow: 0 0 3px #000; display: block; text-align: left; font-size: 13px; padding: 5px; margin-bottom: 0.25em; font-family: sans-serif; white-space: pre-wrap;'&gt;"; &nbsp; &nbsp; const openHeader = "&lt;div style='font-weight:bold; color:#fff; background-color:#404040; margin-right:3px; padding:3px;'&gt;" &nbsp; &nbsp; const closeHeader = '&lt;/div&gt;'; &nbsp; &nbsp; const buttonStyle = "'background-color: transparent;padding: 0px;color: #ce0f69;display: inline-block;border: none; !important'"; &nbsp; &nbsp; if (!msg.content.includes('--') &amp;&amp; playerIsGM(msg.playerid)) { &nbsp; &nbsp; &nbsp; &nbsp; sendChat('Lister', `${openReport}The !makelist command must be followed by " --" and one or more of the following keywords&lt;br&gt;characters&lt;br&gt;handouts&lt;br&gt;pages&lt;br&gt;tables${closeReport}`, null, { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; noarchive: true &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; } &nbsp; &nbsp; let lines = ''; &nbsp; &nbsp; let sheetURL = '<a href="http://journal.roll20.net/character/" rel="nofollow">http://journal.roll20.net/character/</a>'; &nbsp; &nbsp; let handoutURL = '<a href="http://journal.roll20.net/handout/" rel="nofollow">http://journal.roll20.net/handout/</a>'; &nbsp; &nbsp; let profileURL = '<a href="https://app.roll20.net/users/" rel="nofollow">https://app.roll20.net/users/</a>'; &nbsp; &nbsp; let tableURL = `!&amp;#10;/roll 1t[`; &nbsp; &nbsp; let characters = findObjs({ &nbsp; &nbsp; &nbsp; &nbsp; type: 'character' &nbsp; &nbsp; }); &nbsp; &nbsp; let handouts = findObjs({ &nbsp; &nbsp; &nbsp; &nbsp; type: 'handout' &nbsp; &nbsp; }); &nbsp; &nbsp; let pages = findObjs({ &nbsp; &nbsp; &nbsp; &nbsp; type: 'page' &nbsp; &nbsp; }); &nbsp; &nbsp; let tables = findObjs({ &nbsp; &nbsp; &nbsp; &nbsp; type: 'rollabletable' &nbsp; &nbsp; }); &nbsp; &nbsp; let players = findObjs({ &nbsp; &nbsp; &nbsp; &nbsp; type: 'player' &nbsp; &nbsp; }); &nbsp; &nbsp; let characterList = ''; &nbsp; &nbsp; let handoutList = ''; &nbsp; &nbsp; let pageList = ''; &nbsp; &nbsp; let tableList = ''; &nbsp; &nbsp; let playerList = ''; &nbsp; &nbsp; let args = msg.content.split(/\s--/); &nbsp; &nbsp; let commands = args[1].split(/\s+/); &nbsp; &nbsp; log('commands = ' + commands); &nbsp; &nbsp; commands.forEach(c =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; switch (c) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'characters': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; characterList = (characterList === '') ? `${openHeader}Characters:${closeHeader}${characters.map((obj)=&gt;{return makeButton(obj.get('name'),sheetURL + obj.get('_id'))}).join('&lt;br&gt;')}&lt;br&gt;` : ''; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lines = lines + characterList; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'handouts': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handoutList = (handoutList === '') ? `${openHeader}Handouts:${closeHeader}${handouts.map((obj)=&gt;{return makeButton(obj.get('name'),handoutURL + obj.get('_id'))}).join('&lt;br&gt;')}&lt;br&gt;` : ''; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //handoutList = (handoutList === '') ? `${openHeader}Handouts:${closeHeader}${handouts.map((obj)=&gt;{return '[' + obj.get('name')+']('+handoutURL + obj.get('_id')+')'}).join('&lt;br&gt;')}&lt;br&gt;` : ''; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lines = lines + handoutList; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'pages': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pageList = (pageList === '') ? `${openHeader}Pages:${closeHeader}${pages.map((obj)=&gt;{return obj.get('name')}).join('&lt;br&gt;')}&lt;br&gt;` : ''; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lines = lines + pageList; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'tables': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tableList = (tableList === '') ? `${openHeader}Rollable Tables:${closeHeader}${tables.map((obj)=&gt;{return makeTableLink(obj.get('name'))}).join('&lt;br&gt;')}&lt;br&gt;` : ''; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lines = lines + tableList; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'players': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //playerList = (playerList === '') ? `Players:&lt;br&gt;${players.map((obj)=&gt;{return obj.get('_displayname')+'&lt;BR&gt;id: '+obj.get('_id')}).join('&lt;br&gt;')}&lt;br&gt;` : ''; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; playerList = (playerList === '') ? `${openHeader}Players:${closeHeader}${players.map((obj)=&gt;{return makeBox(obj.get('color'),obj.get('_id'),obj.get('_displayname')) + makeButton(obj.get('_displayname'),profileURL + obj.get('_d20userid'))+'&lt;br&gt;id: '+(obj.get('_id'))}).join('&lt;br&gt;')}&lt;br&gt;` : ''; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lines = lines + playerList; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default: &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }); &nbsp; &nbsp; if (lines) { &nbsp; &nbsp; &nbsp; &nbsp; if (commands.includes('makehandout')) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let reportHandout = findObjs({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type: 'handout', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: 'Lister Report' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reportHandout = reportHandout ? reportHandout[0] : undefined; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!reportHandout) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reportHandout = createObj('handout', { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: 'Lister Report', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; archived: false &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let reportHandoutid = reportHandout.get("_id"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('Lister', '/w gm ' + openReport + `Reporter has created a handout named &lt;b&gt;Lister Report&lt;/b&gt;. &lt;BR&gt;Click &lt;a href="<a href="http://journal.roll20.net/handout/${reportHandoutid}&quot;&gt;here&lt;/a" rel="nofollow">http://journal.roll20.net/handout/${reportHandoutid}"&gt;here&lt;/a</a>&gt; to open.` + closeReport, null, { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; noarchive: true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (reportHandout) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (reportHandout) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reportHandout.get("notes", function(notes) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reportHandout.set("notes", lines) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('Lister', '/w gm ' + openReport + `No handout named Makelist Report was found.` + closeReport, null, { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; noarchive: true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat("Lister", `/w gm ${openReport}${lines}${closeReport}`, null, { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; noarchive: true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; } });
1632429003
Gold
Forum Champion
Not coming to the one-click? You expect me to copy-paste that code block into a New API Script?! Okay. Will do.
1632431000
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
I wasn't sure if it had enough value to warrant one-click. Let me know if you wind up being able to use it for anything.