Adding State
Sup provides several ways to store and retrieve state in your patches. This guide covers the different types of state storage and when to use each one.
State Scopes
Sup offers four scopes for storing state:
- Chat Scope - Data tied to a specific chat room
- Message Scope - Data tied to specific messages
- User Scope - Data tied to specific users
- Global Scope - Data shared across all uses of this patch
Chat-Scoped State
Chat-scoped state is shared by all users within a chat. It’s perfect for collaborative features or chat-wide settings.
function main() { // Store chat settings sup.set("gameActive", true); sup.set("currentRound", 1);
// Get chat state const isGameActive = sup.get("gameActive"); const round = sup.get("currentRound");
if (isGameActive) { return `Round ${round} is active!`; }}Common Chat State Uses
// Store chat preferencessup.set("language", "jp");
// Manage game statefunction startGame() { sup.set("gameState", { active: true, players: [], scores: {}, round: 1, });}Message-Scoped State
Message-scoped state lets you store data tied to the message the patch was run in.
function main() { // Store data for current message sup.message.set("yes", 2); sup.message.set("no", 1);
// Get message state const yes = sup.message.get("yes"); const no = sup.message.get("no");}Common Message State Uses
// Track message interactionsfunction onReact(e) { const reactions = sup.message.get("reactions") || []; reactions.push(e.reactionEmoji); sup.message.set("reactions", reactions);}
// Store message metadatafunction markAsAnswered() { sup.message.set("status", { answered: true, answeredBy: sup.user.username, answeredAt: new Date(), });}
// Track thread statefunction updateThread() { sup.message.set("threadInfo", { replyCount: 5, lastReplyAt: new Date(), participants: ["user1", "user2"], });}User-Scoped State
User-scoped state is perfect for storing user preferences, progress, or personal data. It’s accessed through SupUser instances.
function main() { // Store user preference sup.user.set("color", "green");
// Get user preference const color = sup.user.get("color");
// Store user stats sup.user.set("gameScore", 100); sup.user.set("lastPlayed", new Date());}Working with Other Users
You can also access state for other users when you have their SupUser instance:
function onReply(e) { // Get the reply author's data const authorStats = e.reply.author.get("stats");
// Update their interaction count const interactions = e.reply.author.get("interactions") || 0; e.reply.author.set("interactions", interactions + 1);}Global State
Global state is shared across all uses of your patch.
function main() { // Store global data sup.global.set("totalGames", 100); sup.global.set("highScores", [ { name: "player1", score: 1000 }, { name: "player2", score: 950 }, ]);
// Get global data const games = sup.global.get("totalGames"); const scores = sup.global.get("highScores");}Listing Keys
Each scope supports a .keys() method that returns an array of all stored keys:
// List all chat-scoped keysconst chatKeys = sup.keys(); // or sup.chat.keys()
// List all global keysconst globalKeys = sup.global.keys();
// List all user-scoped keysconst userKeys = sup.user.keys();
// List all message-scoped keysconst msgKeys = sup.message.keys();Keys that have been set() during the current patch run are included in the results, even before they are persisted to the database.
Complex Data Structures
All state methods support storing complex data structures:
// Store objectssup.user.set("profile", { preferences: { color: "green", number: 42, }, achievements: ["level1", "level2"],});
// Store arrayssup.set("players", [ { id: "123", name: "Player 1", ready: true }, { id: "456", name: "Player 2", ready: false },]);
// Store datessup.user.set("lastLogin", new Date());
// Store Sup objectssup.set("lastImage", sup.image("example.jpg"));Notes
- State is persistent across patch runs
- State can store any JSON-serializable data
- Choose appropriate scope for your needs
- Initialize state with sensible defaults, and use fallbacks when using the get method