Skip to content
Sebastien-XL edited this page Apr 16, 2019 · 20 revisions

Hooks & Batches

This pages aims to describe what functionality is available through hooks and the sandboxed javascript API.

Batches

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...

Client side

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.

Server side

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:

  • params contains:
    • user_id: the user involved
    • request: the json given to the CUser.Batch method, such as {"param1" : "xxxxx"}
  • customData contains the result of the previouly called batch (optional)
  • mod contains a reference to system modules which can be used by your code. See below for a reference.
  • this does 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.

Sample batch

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.

Sample batch 2

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

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.

Sandboxed API reference

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

Clone this wiki locally