15 Commits

9 changed files with 97 additions and 41 deletions

View File

@@ -2,12 +2,16 @@
## Overview
This FoundryVTT module allows players to suggest titles for the session, similar to how podcast titles are suggested. In my own sessions, I record every session's audio and make it into a podcast. Many of my favorite podcasts use a random, funny, out-of-context quote from the episode for the title. Inspired by this, I created this module so players can suggest titles and the GM can list them all and choose the best one. Players can use the `/title` or `/t` command to suggest a title. A GM or trusted player can use the `/titles` or `/ts` command to get a list of all the suggestions for the most recent day's session.
This FoundryVTT module allows players to suggest titles for the session, similar to how podcast titles are suggested. In my own sessions, I record every session's audio and make it into a podcast. Many of my favorite podcasts use a random, funny, out-of-context quote from the episode for the title. Inspired by this, I created this module so players can suggest titles and the GM can list them all and choose the best one. Players can use the `/title` or `/t` command to suggest a title. The GM (or other configurable role) can use the `/titles` or `/ts` command to get a list of all the suggestions for the most recent day's session.
## Example
![](screenshot.png)
## Features
- Players can suggest session titles using the `/title`, `/t`, or `t/` command.
- GMs or trusted players can view all suggested titles for the most recent session using the `/titles` or `/ts` command.
- GMs or trusted players can view all suggested titles for the most recent session using the `/titles` or `/ts` command. (Role is configurable in settings)
- Copy the titles using the clipboard icon button next to each suggestion in the list.
## Requirements
@@ -15,11 +19,9 @@ This module requires the Chat Commander module to be installed and enabled. You
## Installation
1. Open FoundryVTT and go to the "Add-on Modules" tab in the "Configuration and Setup" menu.
2. Click on "Install Module".
3. In the "Manifest URL" field, paste the following URL: `[your-module-manifest-url]`.
4. Click "Install" and wait for the installation to complete.
5. Enable the module in your game settings.
1. In the "Manifest URL" field, paste the following URL: `https://github.com/anthonyscorrea/asc-session-title-suggestions/releases/latest/download/module.json`.
2. Click "Install" and wait for the installation to complete.
3. Enable the module in your game settings.
## Usage

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

4
scripts/zip-for-release.sh Executable file
View File

@@ -0,0 +1,4 @@
echo "version:"$(cat src/module.json|jq .version)
echo "download:"$(cat src/module.json|jq .download)
git archive --format zip --output dist/module.zip master:src
cp src/module.json dist/

10
src/lang/en.json Normal file
View File

@@ -0,0 +1,10 @@
{
"SESSION_TITLE_SUGGESTIONS.SETTING_ROLE_HINT": "Select the minimum role required to use the /titles command.",
"SESSION_TITLE_SUGGESTIONS.SETTING_ROLE_NAME": "List Titles Command Required Role",
"SESSION_TITLE_SUGGESTIONS.INVALID_DATE": "Invalid date provided.",
"SESSION_TITLE_SUGGESTIONS.SUGGESTION_AUTOCOMPLETE_MESSAGE": "Enter your session title suggestion.",
"SESSION_TITLE_SUGGESTIONS.SUGGESTION_LIST_COMMAND_DESCRIPTION": "List all title suggestions for the provided date",
"SESSION_TITLE_SUGGESTIONS.SUGGESTION_COMMAND_DESCRIPTION": "Suggest a title for this session",
"SESSION_TITLE_SUGGESTIONS.SUGGESTION_FLAVOR": "suggesting a session title",
"SESSION_TITLE_SUGGESTIONS.SUGGESTION_LIST_FLAVOR": "session title suggestions"
}

View File

@@ -4,16 +4,25 @@
"description": "A simple module that keeps track of session title suggestions",
"authors": [
{
"name": "lmxsdl"
"name": "anthonyscorrea",
"url": "https://github.com/anthonyscorrea"
}
],
"version": "0.1.2",
"url": "https://github.com/anthonyscorrea/asc-session-title-suggestions",
"compatibility": {
"minimum": "10",
"verified": "11"
"minimum": "11",
"verified": "12"
},
"download": "https://gitea.ascorrea.com/asc/asc-session-title-suggestions/releases/download/0.1.2/asc-session-title-suggestions-0.1.2.zip",
"manifest":"https://gitea.ascorrea.com/asc/asc-session-title-suggestions/raw/branch/master/src/module.json",
"languages": [
{
"lang": "en",
"name": "English",
"path": "lang/en.json"
}
],
"download": "https://github.com/anthonyscorrea/asc-session-title-suggestions/releases/download/0.5.1/module.zip",
"manifest": "https://github.com/anthonyscorrea/asc-session-title-suggestions/releases/latest/download/module.json",
"version": "0.5.1",
"scripts": [
"scripts/main.js"
],

View File

@@ -24,12 +24,11 @@ function registerClipboardCopyButton() {
function registerCustomChatCommands() {
game.chatCommands.unregister(NAME)
game.chatCommands.register({
name: NAME,
module: "_chatcommands",
aliases: ["/t", "t/"],
description: "Suggest a title for this episode",
description: game.i18n.localize("SESSION_TITLE_SUGGESTIONS.SUGGESTION_COMMAND_DESCRIPTION"),
icon: '<i class="fa-solid fa-podcast"></i>',
requiredRole: "NONE",
callback: async (chat, parameters, messageData) => {
@@ -40,55 +39,87 @@ function registerCustomChatCommands() {
newMessageData.flags = {session_title_suggestion: titleSuggestion}
return newMessageData;
},
autocompleteCallback: (menu, alias, parameters) => [game.chatCommands.createInfoElement("Enter a message.")],
autocompleteCallback: (menu, alias, parameters) => [
game.chatCommands.createInfoElement(game.i18n.localize("SESSION_TITLE_SUGGESTIONS.SUGGESTION_AUTOCOMPLETE_MESSAGE"))
],
closeOnComplete: true
});
}, true);
game.chatCommands.unregister(NAME+"s")
game.chatCommands.register({
name: NAME+"s",
module: "_chatcommands",
aliases: ["/ts"],
description: "List all titles for the most recent episode",
description: game.i18n.localize("SESSION_TITLE_SUGGESTIONS.SUGGESTION_LIST_COMMAND_DESCRIPTION"),
icon: '<i class="fa-solid fa-podcast"></i>',
requiredRole: "TRUSTED",
requiredRole: game.settings.get("asc-session-title-suggestions", "titleListCommandRole"),
callback: async (chat, parameters, messageData) => {
const newMessageData = {}
const suggestions = game.messages.filter(m => {
return m.flags.session_title_suggestion
})
const last_message_date = new Date(suggestions[suggestions.length-1].timestamp)
let selected_message_date
if (!parameters) {
selected_message_date = new Date(suggestions[suggestions.length-1].timestamp)
} else {
const epoch_date = Date.parse(parameters)
if (Number.isNaN(epoch_date)){
ui.notifications.error(`${game.i18n.localize("SESSION_TITLE_SUGGESTIONS.INVALID_DATE")} (${parameter})`);
return;
}
selected_message_date = new Date(epoch_date)
}
const filtered_suggestions = suggestions.filter(m=>{
const message_date = new Date(m.timestamp)
return message_date.toDateString() == last_message_date.toDateString()
return message_date.toDateString() == selected_message_date.toDateString()
})
newMessageData.content = await renderTemplate(TEMPLATES.suggestionList.content, {messages:filtered_suggestions })
newMessageData.flavor = await renderTemplate(TEMPLATES.suggestionList.flavor, {date:last_message_date.toDateString()})
newMessageData.flavor = await renderTemplate(TEMPLATES.suggestionList.flavor, {date:selected_message_date.toDateString()})
return newMessageData;
},
autocompleteCallback: (menu, alias, parameters) => [game.chatCommands.createInfoElement("Enter a message.")],
autocompleteCallback: (menu, alias, parameters) => {
const suggestions = game.messages.filter(m => {
return m.flags.session_title_suggestion
})
const dates = new Set(
suggestions.map(s=>new Date(s.timestamp).toDateString())
)
const entries = [...dates].map(date=>{
return game.chatCommands.createCommandElement(`${alias} ${date}`, date)
})
entries.length = Math.min(entries.length, menu.maxEntries);
return entries;
},
closeOnComplete: true
});
}, true);
}
console.log("Hello World! This code runs immediately when the file is loaded.");
Hooks.on("init", function() {
//This code runs once the Foundry VTT software begins its initialization workflow
registerCustomChatCommands();
registerClipboardCopyButton();
loadTemplates(flavor_template_path)
Object.values(TEMPLATES.suggestion).forEach((template_path)=>{
loadTemplates(template_path)
}
)
Object.values(TEMPLATES.suggestionList).forEach((template_path)=>{
loadTemplates(template_path)
}
)
Object.values(TEMPLATES.suggestion).forEach((template_path)=>loadTemplates(template_path))
Object.values(TEMPLATES.suggestionList).forEach((template_path)=>loadTemplates(template_path))
game.settings.register("asc-session-title-suggestions", "titleListCommandRole", {
name: game.i18n.localize("SESSION_TITLE_SUGGESTIONS.SETTING_ROLE_NAME"),
scope: "world",
config: true,
type: String,
default: "TRUSTED",
requiresReload: true,
choices: {
"PLAYER": game.i18n.localize("USER.RolePlayer"),
"TRUSTED": game.i18n.localize("USER.RoleTrusted"),
"ASSISTANT": game.i18n.localize("USER.RoleAssistant"),
"GAMEMASTER": game.i18n.localize("USER.RoleGamemaster")
},
hint: game.i18n.localize("SESSION_TITLE_SUGGESTIONS.SETTING_ROLE_HINT")
});
import ('https://cdn.jsdelivr.net/npm/title-case@4.3.1/dist/index.min.js')
.then((module)=>{console.log('asc','loading...');Handlebars.registerHelper("titlecase", module.titleCase)})
});
Hooks.on("ready", function() {
//This code runs once core initialization is ready and game data is available.
registerCustomChatCommands();
});

View File

@@ -1 +1 @@
<i class="fa-solid fa-podcast"></i> suggesting an session title...
<i class="fa-solid fa-podcast"></i> {{localize 'SESSION_TITLE_SUGGESTIONS.SUGGESTION_FLAVOR'}}...

View File

@@ -1,3 +1,3 @@
<ul>{{~#each messages ~}}
<li><a class="fa-regular fa-clipboard clipboard" style="padding-left:.5em;padding-right:.5em;" data-clipboard-text="{{this.flags.session_title_suggestion}}"></a><i>"{{this.flags.session_title_suggestion}}"</i> - {{this.user.name}}</li>
<li><a class="fa-regular fa-clipboard clipboard" style="padding-left:.5em;padding-right:.5em;" data-clipboard-text="{{titlecase this.flags.session_title_suggestion}}"></a><i>"{{titlecase this.flags.session_title_suggestion}}"</i> - {{this.user.name}}</li>
{{~/each~}}</ul>

View File

@@ -1 +1 @@
<i class="fa-solid fa-podcast"></i> title suggestions ({{date}}):
<i class="fa-solid fa-podcast"></i> {{localize "SESSION_TITLE_SUGGESTIONS.SUGGESTION_LIST_FLAVOR"}} ({{date}}):