Fetching table details and setting up tabletop...
Fetching table details and setting up tabletop...
Paste the full public edit link of your Google Sheet. We will parse the ID and sheet tab (gid) automatically.
Allows syncing toggles for favorites and play status directly back to the Google Sheet. Without this, these toggles will be disabled in the UI (read-only mode).
If you configured a secret token in your Google Apps Script, enter it here to authorize writes.
// Tabletop Game Organizer Sync Script - Version 1.3.0
var SECURITY_TOKEN = "YOUR_SECRET_TOKEN_HERE"; // Change to a secret password if desired
function doPost(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var data = JSON.parse(e.postData.contents);
console.log("Sync request received for game: '" + data.gameName + "', action: '" + data.action + "', value: " + data.value);
console.log("Token verification: expected: '" + SECURITY_TOKEN + "', received: '" + data.token + "'");
// Security token validation
if (SECURITY_TOKEN && SECURITY_TOKEN !== "YOUR_SECRET_TOKEN_HERE") {
if (data.token !== SECURITY_TOKEN) {
console.log("Verification failed: Tokens do not match.");
return ContentService.createTextOutput(JSON.stringify({
status: "error",
message: "Unauthorized: Invalid Security Token."
})).setMimeType(ContentService.MimeType.JSON);
}
}
var gameName = data.gameName;
var action = data.action; // 'toggleFavorite' or 'togglePlayed'
var value = data.value; // true or false
var rows = sheet.getDataRange().getValues();
var headers = rows[0];
var gameColIndex = headers.indexOf("Game");
var targetColName = action === "toggleFavorite" ? "Favorite" : "Played?";
var targetColIndex = headers.indexOf(targetColName);
if (gameColIndex === -1 || targetColIndex === -1) {
console.log("Error: Required columns not found. Game index: " + gameColIndex + ", Target column '" + targetColName + "' index: " + targetColIndex);
return ContentService.createTextOutput(JSON.stringify({
status: "error",
message: "Required columns 'Game' and '" + targetColName + "' not found."
})).setMimeType(ContentService.MimeType.JSON);
}
// Case-insensitive, whitespace-trimmed comparison to avoid whitespace mismatch issues
var cleanGameName = gameName.toString().trim().toLowerCase();
for (var i = 1; i < rows.length; i++) {
var cellValue = rows[i][gameColIndex].toString().trim().toLowerCase();
if (cellValue === cleanGameName) {
sheet.getRange(i + 1, targetColIndex + 1).setValue(value ? "TRUE" : "FALSE");
console.log("Successfully wrote value " + (value ? "TRUE" : "FALSE") + " to row " + (i + 1) + ", column " + (targetColIndex + 1));
return ContentService.createTextOutput(JSON.stringify({
status: "success",
game: gameName,
column: targetColName,
value: value
})).setMimeType(ContentService.MimeType.JSON);
}
}
console.log("Error: Game name '" + gameName + "' not found in sheet.");
return ContentService.createTextOutput(JSON.stringify({
status: "error",
message: "Game '" + gameName + "' not found in sheet."
})).setMimeType(ContentService.MimeType.JSON);
}
Local Cache Status: No local cache found.
The app caches sheet data locally in your browser for instant startup and offline capability. It refreshes automatically in the background on load.
Based on your filters, we recommend: