{"id":29543922,"url":"https://github.com/rewindrl/updater","last_synced_at":"2025-07-17T14:09:11.497Z","repository":{"id":65329827,"uuid":"207173525","full_name":"rewindrl/updater","owner":"rewindrl","description":"A simple JavaScript overlay updater that maps Google Sheets values to HTML overlay elements. Originally written for Rewind Gaming, a Rocket League tournament organisation, but open source as of the organisation's closure in late 2019.","archived":false,"fork":false,"pushed_at":"2023-01-18T18:34:47.000Z","size":76,"stargazers_count":14,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-06-13T03:04:27.214Z","etag":null,"topics":["broadcasting","esports","game-streaming","google-sheets","overlay","overlays"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rewindrl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-09-08T21:06:00.000Z","updated_at":"2024-12-15T02:37:56.000Z","dependencies_parsed_at":"2023-02-10T16:45:34.402Z","dependency_job_id":null,"html_url":"https://github.com/rewindrl/updater","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/rewindrl/updater","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rewindrl%2Fupdater","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rewindrl%2Fupdater/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rewindrl%2Fupdater/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rewindrl%2Fupdater/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rewindrl","download_url":"https://codeload.github.com/rewindrl/updater/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rewindrl%2Fupdater/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265614369,"owners_count":23798430,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["broadcasting","esports","game-streaming","google-sheets","overlay","overlays"],"created_at":"2025-07-17T14:09:10.861Z","updated_at":"2025-07-17T14:09:11.486Z","avatar_url":"https://github.com/rewindrl.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Updater.js\nThis repository contains code designed to be used in a broadcast situation, and provides a simple framework to allow a broadcast moderator to control overlays using a Google Sheet. It was created for [Rewind Gaming](https://twitter.com/RewindRL) by [Barnaby 'bucketman' Collins](https://twitter.com/bucketman21). Versions of this program have been used in overlays for several tournaments including:\n\n\u003ctable\u003e\u003ctr\u003e\n    \u003ctd\u003e\u003cimg alt=\"Rewind Gaming: The Colosseum\" src=\"https://liquipedia.net/commons/images/3/3a/Colosseum_Rewind_Gaming.png\" width=\"500\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg alt=\"Rewind Gaming x Psyonix: Neon Dream (EU Renegade Cup)\" src=\"https://liquipedia.net/commons/images/a/a3/Neon_Dream.png\" width=\"500\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg alt=\"Johnnyboi_i: Salt Mine II\" src=\"readme_assets/smii.jpg\" width=\"500\"\u003e\u003c/td\u003e\n\u003c/tr\u003e\u003c/table\u003e\n\nIt is designed to be included inside a set of HTML overlays to be imported into broadcasting software such as OBS, and runs entirely on the client side. An earlier version of this program was used by Rewind Gaming for all of our large events, and it has proven reliable.\n\nWhen using this system, the main latency bottleneck is Google's servers propagating new values to the API. Generally I've found that updates take 2-10 seconds to reach overlays, which is very much satisfactory for most broadcast needs.\n\nNote: for more advanced users, this updater is configurable with your own overlay updating operations. More information on this is available at [Customisation.md](Customisation.md).\n\n## A note on Google API versions\nThis branch now contains the version of Updater.js for Google Sheets API v4. If you are looking for the previous version, which doesn't require an API key but uses a deprecated API version, that can be found on the [`APIv3` branch](https://github.com/rewindrl/updater/tree/APIv3).\n\n## Basic Implementation\nTo use Updater.js, simply import it into an overlay page in a `\u003cscript\u003e` tag and define a new `GraphicsUpdater` object. It doesn't require JQuery so can just be included as a standalone file.\n\nFor example:\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n    \u003c!-- stuff --\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n    \u003cspan id=\"team-name\"\u003e\u003c/span\u003e\n    \u003cimg id=\"team-photo\"\u003e\n\n    \u003c!-- JAVASCRIPT STUFF --\u003e\n    \u003c!-- Import Updater --\u003e\n    \u003cscript src=\"Updater.js\"\u003e\u003c/script\u003e\n    \u003cscript\u003e\n        // Define settings to use\n        const settings = {\n            'string': {\n                'H1': 'team-name'\n            },\n            \"image\": {\n                'H2': 'team-photo'\n            }\n        };\n\n        // Define spreadsheet to use\n        const spreadsheetID = '0B-klwLEjaXWcZHR5SmJJWEwtYnc';\n\n        // Select worksheet\n        const worksheetName = 'Sheet1';\n\n        // Specify the API key to use\n        // (this is just a random string, it won't work okay)\n        const apiKey = \"4fBv9O3L9rR0SeLf6P1l5I679D08s4zP5xX4iZc\";\n\n        // Update the overlay every 3 seconds\n        const updateInterval = 3000;\n\n        // Pass those values into a new GraphicsUpdater object\n        // The code will deal with it from here\n        const u = new GraphicsUpdater(settings, spreadsheetID, worksheetName, apiKey, updateInterval);\n    \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n`Updater.js` and `Updater.min.js` both do exactly the same thing; `Updater.min.js` is just smaller ('minified') and so will take up less disk space and run marginally quicker. I recommend developing with `Updater.js` because it contains [JSDoc](https://jsdoc.app/) comments which should be picked up automatically by most IDEs, and will give you information on things like parameter types. `Updater.min.js` can always be dropped in once development is completed if necessary.\n\n## Class Parameters\nIn this section:\n\n`GraphicsUpdater(`\n\n- [`settings`](#settings)`,`\n- [`spreadsheetID`](###spreadsheetID)`,`\n- [`worksheetName`](###worksheetName)`,`\n- [`apiKey`](###apiKey)`,`\n- [`updateInterval`](###updateInterval-(optional;-default-3000))`,`\n- [`updateNow`](###updatenow-optional-default-true)\n\n`)`\n\n\u0026nbsp;\n\n### `settings`\n`settings` is defined as a JavaScript object. It defines the relationships between the cells in the spreadsheet and the HTML elements in the overlay.\n\n#### Supported element types\nI'm defining an element type here as a type of thing that can be updated in the overlay. For example, a string value, an image or a counter.\n\n##### `\"string\"`\nA string property simply replaces the content of the given HTML ID(s) with the content of the spreadsheet cell. It is useful for text content such as team names, social media tags or the name of your epic mixtape.\n\nA `settings` structure using `\"string\"` might look like:\n```json\n{\n    \"string\": {\n        \"H6\": \"team-name-1\",\n        \"A1\": \"moderator-of-the-month\",\n        \"D7\": [\n            \"buckets-name-big\",\n            \"buckets-name-small\"\n        ]\n    }\n}\n```\nIn this example, `#team-name-1` and `#moderator-of-the-month` would be updated with the values in H6 and A1 respectively, and `#buckets-name-big` and `#buckets-name-small` would both be updated with the value in D7.\n\n\u0026nbsp;\n\n##### `\"image\"`\nAn image element has its `src` attribute set to whatever text content is contained inside the given cell. This URI can point to a file stored locally on the broadcast machine, or an image that's hosted on the web. This can be useful for any dynamic image you'd want to display, from a caster's profile photo to your meme of the day.\n\nA `settings` structure using `\"image\"` might look like:\n```json\n{\n    \"image\": {\n        \"F5\": \"metal-bucket\",\n        \"C4\": [\n            \"anti-bucket-ordnance\",\n            \"bucket-secret-weapon\",\n            \"bucket-assault-squad\"\n        ],\n        \"B2\": \"plastic-bucket\"\n    }\n}\n```\nIn this example, the HTML `img` elements with the IDs `plastic-bucket` and `metal-bucket` would use the image at the URI specified in B2 and F5 respectively, and those with the IDs `anti-bucket-ordnance`, `bucket-secret-weapon` and `bucket-assault-squad` would all use the image at the URI specified in C4.\n\nFun fact: `\"image\"` can also be used to specify sources for other tags that use `src`, such as `iframe`s.\n\n\u0026nbsp;\n\n##### `\"counter\"`\nThe `\"counter\"` element type is a specialised type designed for use with overlays using 'tallies' to display scores. It will reveal or hide elements in a given ID list based on a number given in a single cell in the spreadsheet. For example, for a given score of 2, it will show the first two elements and hide any later elements in the list.\n\nA `settings` structure using `\"counter\"` might look like:\n```json\n{\n    \"counter\": {\n        \"B2\": [\n            \"score-tally-1\",\n            \"score-tally-2\",\n            \"score-tally-3\",\n            \"score-tally-4\"\n        ]\n    }\n}\n```\nIn this example, the updater script would show the first `n` elements in the list and hide the rest, where `n` is the value in B2. Note that you can't update multiple sets of tallies with just one cell (though specifying the same cell twice for two different sets of tallies might work; I haven't tested that though and you do so at your own risk).\n\n\u0026nbsp;\n\n##### `\"switch\"`\nA switch is the last element type, designed to show different elements depending on a cell's value, as well as to allow you to do a lot of other things that aren't natively supported by the updater system. It basically allows you to specify a list of possible values for each spreadsheet cell, with an element ID given for each possible value. The script will show any elements given for the current cell value, and hide the elements affiliated with all other values.\n\nA `settings` structure using `\"switch\"` might look like:\n```json\n{\n    \"switch\": {\n        \"Z14\": {\n            \"bob\": \"bob-overlay\",\n            \"bucket\": \"cartoon-bucket-drawing\",\n            \"doris\": \"doris-esports\",\n            \"linda\": \"linda-overlay\"\n        }\n    }\n}\n```\nIn this example, the value in Z14 would decide which of `#bob-overlay`, `#cartoon-bucket-drawing`, `#doris-esports` and `#linda-overlay` to show. If Z14 contained 'bob', the HTML element with ID `#bob-overlay` would be shown, if it contained 'bucket' it would show `#cartoon-bucket-drawing` and so on. Note that you can't specify multiple tags for a value in a switch statement: if you want to be able to toggle several different things, you could either use containing HTML divs that you pass into the updater instead or, in a similar vein to the counter, specify the same cell multiple times. Again, not strictly supported.\n\n\u0026nbsp;\n\n### `spreadsheetID`\nThis is the [ID of the spreadsheet](https://developers.google.com/sheets/api/guides/concepts#spreadsheet_id), as given in the URL of the Google Sheets page for that spreadsheet. It's usually a long alphanumeric string.\n\nThe system used by this updater can only access public spreadsheets, so make sure that your spreadsheet is set to at least 'Anyone with the link can view'. If it's private, the API will throw an error and your overlay won't be able to update.\n\n\u0026nbsp;\n\n### `worksheetName`\nThis is the name of the worksheet inside the spreadsheet document (ie, corresponding to the tab along the bottom that you'd click to get to that worksheet in the desktop web UI). Here's a picture I found to illustrate:\n\n![Worksheet tabs along the bottom of a Google Sheets document](https://cdn-7dee.kxcdn.com/wp-content/uploads/2019/07/how-add-color-tabs-google-sheets-1.jpg)\n\n\u0026nbsp;\n\n### `apiKey`\nThis is an API key for the script to use when it accesses the Google Sheets API. You need to generate one of these with Google yourself at [this page](https://console.cloud.google.com/apis/credentials). There's more information on that [here](https://cloud.google.com/docs/authentication/api-keys#creating_an_api_key), or a [slightly more in-depth guide](https://developers.google.com/maps/documentation/embed/get-api-key#get-the-api-key) on the Google Maps documentation. You might have to create a new project before you can generate one.\n\nEither way, make sure you've got the Google Sheets API enabled for the project containing your key - you can do it [here](https://console.cloud.google.com/apis/library/sheets.googleapis.com) with your project selected in the top bar.\n\nYou should end up with a long string of letters, numbers and symbols. This should be passed straight into the `GraphicsUpdater` as a string.\n\nBasically, an API key allows an application to do stuff on Google on your behalf. That means it can be abused too, so make sure that you take care to protect it. Treat it like a password. It's a good idea to restrict your key so that it can only be used on Google Sheets - there's a guide for that [here](https://cloud.google.com/docs/authentication/api-keys#api_key_restrictions).\n\n#### Important note:\nGoogle imposes usage limits on API keys: you are allowed a maximum of [100 requests per 100 seconds per user, and 500 requests per 100 seconds per project](https://developers.google.com/sheets/api/limits). As such, if you are planning to use several different overlays in the same broadcast, you may want to generate several API keys and use a different one in each overlay so that you stay well under this limit. You can see statistics on this for your project [here](https://console.cloud.google.com/apis/dashboard).\n\nExceeding this limit won't break the updater, but will negatively impact the latency between a value being updated and that change being represented on the overlay. The best way to check if you are below the limits is probably to open an instance of each of your overlays, and keep an eye on the consoles for each instance. If you start consistently getting errors after a certain amount of time, you are exceeding your usage limits.\n\n\u0026nbsp;\n\n### `updateInterval` (optional; default `3000`)\nThis is simply the interval in milliseconds at which the updater should grab the latest info from the Google Sheet. For example, if `updateInterval` is set to `3000`, the overlay will be updated every 3 seconds (3000 milliseconds).\n\nBear in mind that it may take more than the given time for an inputted value to reach the overlay, given that it has to make the journey from writing client machine to Google Drive servers to API endpoint before it is visible to the script. For example, setting your interval to 1ms would be pointless because it takes much more than 1ms for the value to propagate to the API on Google's servers, by which time the script would have refreshed hundreds of times before getting the update. We've found that timings in the range of 2000-10000 are pretty reasonable values for this (as this is the typical time taken for Google Sheets to propagate).\n\n\u0026nbsp;\n\n### `updateNow` (optional; default `true`)\nThis parameter specifies whether the GraphicsUpdater should start updating straight away after being initialised. It should be set to `false` if you intend to add configuration of your own.\n\nThe updater can be instructed to start updating once configured by calling `GraphicsUpdater.startUpdating()`.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frewindrl%2Fupdater","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frewindrl%2Fupdater","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frewindrl%2Fupdater/lists"}