Repository navigation
Batches
This pages aims to describe what functionality is available through hooks and the sandboxed javascript API.
Batches represent user-defined operations executed on the server that can be triggered from the client SDK via an API call. In other words, a batch is a snippet of javascript code that runs in a sandboxed environment and has access to most of the CotC operations which could be triggered by API calls via the supplied API. In this chapter, you will learn the the basics of batches and hooks, and find an API reference.
Just like any Javascript, Batches are asynchronous. They make heavy use of promises, which are a prerequisite. The exact promise library we're using is Bluebird. It is strongly recommended to read the Quick Start Guide...
Batches are run from the client SDK by invoking the method CUserManager.Batch(callback, config, params).
-
config: contains the keys "name" and "domain" which identify the batch to be called
-
params: the user data to be passed to the batch
config = { "name" : "test", "domain" : "private" }; params = { "param1" : "xxxxx" };
The callback receives the data returned by the batch.
In the Backoffice, make sure to create the batch in the appropriate game/domain space, then click on New hook button. A stub like this will be created:
function __test(params, customData, mod) {
"use strict;"
// don't edit above this line // must be on line 3
return "done!";
}
Note: batch names have to be prefixed by two underscores, as opposed to hooks which use predefined names. These underscores will be added automatically to the name entered when creating a batch in the editor.
The return value can be either a Javascript value, or a Bluebird Promise. In both cases, the client will receive this value in its success callback.
If an exception is thrown, it will be wrapped into a HookError and returned to the client.
Here is a description of the parameters of the function:
-
paramscontains:-
user_id: the user involved -
request: the json given to theCUser.Batchmethod, such as{"param1" : "xxxxx"}
-
-
customDatacontains the result of the previouly called batch (optional) -
modcontains a reference to system modules which can be used by your code. See below for a reference. -
thisdoes reference the sandboxed API
mod gives you access to the following:
| Module | Comment |
|---|---|
| Q | Promise module, implemeted by bluebird. |
| _ | Underscore module. |
| ObjectID | Usage: ObjectID(string); converts a string to an ID in the database. |
| ObjectIDs | Usage: ObjectIDs(array); converts an array of ID in the database. |
isSafe |
isSafe() returns true if the current hook/batch is called by another hook/bach, but false if called by a client. |
| common | common allows you to factor out common functions and objects in the common hook. |
| debug | debug() lets you log to the batch console. This log is found below the Backoffice batch editor. |
This chapter demonstrates how to create a sample batch that returns the name of an user. You will pass the user ID and its profile is read and returned to the caller. In this case, a Promise is returned. This promise will resolve to the profile.displayName value.
function __getprofile(params, customData, mod) {
"use strict;"
// don't edit above this line // must be on line 3
return this.user.profile.read(params.user_id, ["profile.displayName"]);
}
By invoking the batch with the following JSON as configuration:
{
config: {
"name": "getprofile",
"domain": "private"
},
params: {
user_id: "123456789012345678901234"
}
}
Here is an example of what could be returned.
{
"profile": {
"displayName": "Guest"
},
"_error": 0,
"_httpcode": 200
}
The {profile: {displayName: "Guest"}} is actually what is returned by the call to this.user.profile.read, so it appears as is in the response.
In the following example, we are going to customize the response given when querying the user profile.
function __testprofile(params, customData, mod) {
"use strict;"
// don't edit above this line // must be on line 3
return this.user.profile.read(params.user_id, ["profile"]).then(function (values) {
var clean = {};
clean.displayName = values.profile.displayName;
clean.name = values.profile.lastName;
return clean;
});
}
By calling it the same was as before, you should obtain something like that:
{
"displayName": "Guest",
"name": "John",
"_error": 0,
"_httpcode": 200
}
Note that in this case, we still return a Promise, which is actually a chain of promises. A first promise will resolve to the data we want
which is .then'ed with another promise, which will modify the return value.
Hooks are very similar to the batches. They are intended to execute actions on the server when certain events happen, so they take a name matching the event instead of a custom-defined batch to be called. From the backoffice, you can select one of the predefined hook names and provide your own code.
While hooks have the same signature as batches, the passed parameters depend on the hook itself. The table below gives a reference of all the hook methods.
| Hook name | Content of params
|
Description |
|---|---|---|
| before-transaction | domain, user_id, transaction, description, balanceBefore | Raised before a transaction is executed. The transaction may be interrupted by throwing an exception. |
| after-transaction | domain, user_id, transaction, description, adjustedBalance, triggeredAchievements | Raised after a transaction has been be executed. The user balance is adjusted. |
| before-gamervfs-write | user_id, key, value | Raised before writing a value for a key in the user VFS. |
| after-gamervfs-write | user_id, key, value | Raised after writing a value for a key in the user VFS. |
| before-gamervfs-delete | user_id, key | Raised before deletion of a key from an user VFS. |
| after-gamervfs-delete | user_id, key | Raised after deletion of a key from an user VFS. |
| before-properties-write | domain, user_id, key, value | Raised before writing to a property of an user. |
| after-properties-write | domain, user_id, key, value | Raised after writing to a property of an user. |
| before-properties-delete | domain, user_id, key | Raised before deletion of a user property will be executed. |
| after-properties-delete | domain, user_id, key | Raised after the deletion of a user property. |
| social-addprofile | domain, users, userids | Raised when a description of an user is needed (friends, godchildren, highscores, …). |
| after-achievement-triggered | domain, user_id, triggeredAchivements, runTransactions | Raised after an achievement has been triggered (i.e. the balance has been adjusted and triggered an achievement as a result). |
| after-achievement-userdata-modified | domain, user_id, achievement, gamerData | Triggered after the user data of an achievement has been modified (API such as POST /v1/gamer/achievements/…/…/gamerdata). |
| before-match-create | domain, user_id: creator, match: as inserted in the DB | Triggered before the creation of a match. Like in most 'before' hooks, the creation of the match may be interrupted by throwing an exception. |
| after-match-create | domain, user_id, match | Triggered after the creation of a match. The match parameter has additional information in it, as returned to the client. |
| before-match-delete | user_id, match | Raised before deleting a match. |
| after-match-delete | user_id, match: cached; not valid anymore | Raised after a match has been deleted. |
| after-match-dismissinvitation | user_id, match | Raised when an user has dismissed an invitation sent by another player. |
| before-match-drawfromshoe | user_id, match, drawnItems | Raised whenever items are about to be drawn from the shoe of a match. |
| after-match-drawfromshoe | user_id, match: as updated, drawnItems | Raised after items have been drawn from the shoe. The match has already been modified to reflect the drawn items. |
| before-match-finish | user_id, match | Raised when a player is trying to finish a match. |
| after-match-finish | user_id, match: as updated | Raised after a match has been marked as terminated. Nothing much can be done with the match from there. |
| before-match-invite | user_id, match, invitee_id | Raised when a player tries to invite another player to the match. |
| after-match-invite | user_id, match, invitee_id | Raised after an invitation has been sent to the other player. |
| before-match-join | user_id, match | Raised when a player joins a match. |
| after-match-join | user_id, match: as updated | Raised when a match has been joined by a player. |
| after-match-leave | user_id, match: as updated | Raised after a player has left a match. |
| before-match-postmove | user_id, match | Raised before a move has been posted to the match. |
| after-match-postmove | user_id, match: as updated | Raised after a move has been posted to the match. |
In the following, any variable name suffixed by _id must be passed as a Database ID. See ObjectID in the above documentation.
| Namespace | Method | Comment |
|---|---|---|
| virtualfs | read(domain, user_id, key) | Reads a key in the VFS of the user. |
| virtualfs | write(domain, user_id, key, value) | Writes a value to the VFS of the user. |
| virtualfs | delete(domain, user_id, key) | Deletes a key in the VFS of the user. |
| virtualfs | readmulti(domain, ids, keys, fields) | Returns an array of data according to the IDs passed. ids is an array of user_id, keys is an array of key name, fields is an array containing either relations or leaderboards. |
| user.profile | read(user_id, fields) | Reads global user information. fields controls which fields are included. It is an array which can contain the following values: profile, games, links, registerBy or registerTime. |
| user.profile | write(user_id, fields) | Writes global user profile information. The given fields are updated, the omitted ones are left untouched. The acceptable fields are: avatar, email, displayName, firstName, lastName, lang, addr1, addr2, and addr3. For example: fields = {displayName: "newDisplayName", "lang": "en"}
|
| user.account | convert(user_id, network, token) | Convert an anonymous account to a facebook or googleplus account when possible. |
| user.properties | read(domain, user_id, key) | Reads user related property named key. |
| user.properties | write(domain, user_id, key, value) | Writes user related property named key. |
| user.properties | delete(domain, user_id, key) | Deletes user related property named key. |
| user.relations | friends(domain, user_id) | Returns the friends in the specified domain. |
| user.relations | setFriendStatus(domain, user_id, friend_id, status, osn) | Sets the status between two gamers as friends (status == "add") or blacklisted (status == "blacklist"), or forget any status (status == "forget") in the specified domain. |
| tx | balance(domain, user_id) | Returns the user balance (values as affected by transactions). |
| tx | transaction(domain, user_id, transaction, description) | Runs a transaction for the user. Returns an array with two values: the adjusted balance and the list of achievements triggered. Note that as with most API calls, this is a promise, so you should do something like this.tx.transaction(...).spread(function(adjustedBalance, triggeredAchievements) { ... });
|
| gamevfs | read(domain, key) | Reads game related key. |
| gamevfs | write(domain, key, value) | Writes game related key. |
| gamevfs | incr(domain, key) | Atomic incrementation (+1) on key. |
| game | runBatch(domain, name, params) | Runs the batch by name and domain. |
| game | runBatchWithLock(domain, name, params, resource) | Runs the batch by name and domain, acquire a lock on resource(string) first. |
| game | runDelayedBatch(domain, name, params, delay) | Runs the batch later. The delay is in seconds. |
| game | getPrivateDomain() | Returns the name of the private domain. It is a safe choice by default, and can be passed to most functions requiring a domain unless you need a domain. |
| game | sendEvent(domain, user_id, message) | .Send message to user on domain (user_id can be an array of user_ids) |
| game | sendVolatileEvent(domain, user_id, message) | .Send volatile message (no guarantees) to user on domain (user_id can be an array of user_ids) |
| leaderboard | score(domain, user_id, board, order, value, info, force) | Post a new score for a user. |
| leaderboard | bestscores(domain, user_id) | Get the best scores of a user for every leaderboard. |
| leaderboard | usersscores(domain, board, users_ids) | Get the scores of a list of user ids. |
| leaderboard | highscore(domain, user_id, board, count) | Get the hishscore of a board. returns count results (max 100). If user_id is null returns bests scores, if not, returns scores centered on user_id
|
| index | index(domain, indexName, objectId, properties, payload) | Index a new document. |
| index | search(domain, indexName, q, sort=[], from=0, max=10) | Search documents by query string. |
| index | query(domain, indexName, query, from=0, max=10) | Search documents by full-body query. |
| index | delete(domain, indexName, objectId) | Remove a document from the index. |
| timer | add(domain, user_id, timerObject={expirySeconds, timerId, description, customData}, batchToRun) | Add a timer that will tun batchToRun in expirySeconds. batchToRun will be called with params={domain, user_id, timerId, now, expiredAt, description, customData}. |
| timer | delete(domain, user_id, timerId) | Delete a timer. |
| timer | retime(domain, user_id, timerId, expirySeconds) | Change the expiry of a timer to expirySeconds since addition. |
| timer | get(domain, user_id) | Get all timers for a user. |
| kv | create(domain, user_id, key, value, acl={}) | Create a new key |
| kv | get(domain, user_id, key) | Gets a key. |
| kv | set(domain, user_id, key, value, udate=null) | Set the value of a key. |
| kv | changeACL(domain, user_id, key, acl) | Change the ACL of a key. |
| kv | updateObject(domain, user_id, key, value, udate=null) | Update the object inside a key. |
| kv | del(domain, user_id, key) | Delete a key. |
| match | createMatch(domain, user_id, description, maxPlayers, customProperties, globalState, shoe) | Create a match |
| match | deleteMatch(match_id, creator_gamer_id) | Delete a match |
| match | dismissInvitation(match_id, gamer_id) | Dismiss an invitation |
| match | drawFromShoe(match_id, gamer_id, eventOsn, lastEventId, count) | Draw an object from the shoe |
| match | getMatch(match_id) | Get a match |
| match | finishMatch(match_id, caller_gamer_id, eventOsn, lastEventId) | Finish a match |
| match | inviteToMatch(match_id, caller_gamer_id, invitee_id) | Invite a player to a match |
| match | joinMatch(match_id, gamer_id, eventOsn) | Join a user to a match |
| match | leaveMatch(match_id, gamer_id, eventOsn) | Leave a match |
| match | postMove(match_id, gamer_id, moveData, lastEventId, eventOsn) | Send a move to the match |