public void postAction(string actionId, IDictionary actionProperties, string objectId,
                           IDictionary objectProperties, string objectInstanceId = null,
                           CarrotRequestResponse callback = null)
    {
        if(string.IsNullOrEmpty(objectId))
        {
            throw new ArgumentNullException("objectId must not be null or empty string.", "objectId");
        }

        if(string.IsNullOrEmpty(actionId))
        {
            throw new ArgumentNullException("actionId must not be null or empty string.", "actionId");
        }

        if(objectProperties == null)
        {
            throw new ArgumentNullException("objectProperties must not be null.", "objectProperties");
        }
        else if(!objectProperties.Contains("title") ||
                !objectProperties.Contains("description") ||
                !objectProperties.Contains("image"))
        {
            throw new ArgumentException("objectProperties must contain keys for 'title', 'description', and 'image'.", "objectProperties");
        }

        objectProperties["object_type"] = objectId;
        if(!string.IsNullOrEmpty(objectInstanceId)) objectProperties["object_instance_id"] = objectInstanceId;
        Dictionary<string, object> parameters = new Dictionary<string, object>() {
            {"action_id", actionId},
            {"action_properties", actionProperties == null ? new Dictionary<string, object>() : actionProperties},
            {"object_properties", objectProperties}
        };
        StartCoroutine(cachedRequestCoroutine(ServiceType.Post, "/me/actions.json", parameters, callback));
    }
示例#2
0
    private IEnumerator signedRequestCoroutine(Request carrotRequest,
                                               CarrotRequestResponse callback = null)
    {
        Response ret = Response.UnknownError;
        string errorText = null;
        string hostname = hostForServiceType(carrotRequest.ServiceType);

        if(string.IsNullOrEmpty(hostname))
        {
            if(callback != null) callback(Response.OK, "", null);
            return false;
        }

        if(string.IsNullOrEmpty(mUserId))
        {
            throw new NullReferenceException("UserId is empty. Assign a UserId before using Carrot.");
        }

        ServicePointManager.ServerCertificateValidationCallback = CarrotCertValidator;

        Dictionary<string, object> urlParams = new Dictionary<string, object> {
            {"api_key", mUserId},
            {"game_id", mFacebookAppId},
            {"request_date", carrotRequest.RequestDate},
            {"request_id", carrotRequest.RequestId}
        };
        Dictionary<string, object> parameters = carrotRequest.Parameters;

        // If this has an attached image, bytes will be placed here.
        byte[] imageBytes = null;

        if(parameters != null)
        {
            // Check for image on dynamic objects
            if(parameters.ContainsKey("object_properties"))
            {
                IDictionary objectProperties = parameters["object_properties"] as IDictionary;
                object image = objectProperties["image"];
                Texture2D imageTex2D;
                if((imageTex2D = image as Texture2D) != null)
                {
                    imageBytes = imageTex2D.EncodeToPNG();
                    using(SHA256 sha256 = SHA256Managed.Create())
                    {
                        objectProperties["image_sha"] = System.Text.Encoding.UTF8.GetString(sha256.ComputeHash(imageBytes));
                    }
                }
                else if(image is string)
                {
                    objectProperties["image_url"] = image;
                }
                objectProperties.Remove("image");
            }

            // Merge params
            foreach(KeyValuePair<string, object> entry in parameters)
            {
                urlParams[entry.Key] = entry.Value;
            }
        }

        UnityEngine.WWWForm formPayload = new UnityEngine.WWWForm();
        addCommonPayloadFields(formPayload, urlParams);

        string[] keys = new string[urlParams.Keys.Count];
        urlParams.Keys.CopyTo(keys, 0);
        foreach(string key in keys)
        {
            string asStr;
            if((asStr = urlParams[key] as string) != null)
            {
                formPayload.AddField(key, asStr);
            }
            else
            {
                formPayload.AddField(key,
                    Json.Serialize(urlParams[key]));
            }
        }

        string sig = signParams(hostname, carrotRequest.Endpoint, mCarrotAppSecret, urlParams);
        formPayload.AddField("sig", sig);

        // Attach image
        if(imageBytes != null)
        {
            formPayload.AddBinaryData("image_bytes", imageBytes);
        }

        UnityEngine.WWW request = new UnityEngine.WWW(String.Format("https://{0}{1}", hostname, carrotRequest.Endpoint), formPayload);
        yield return request;

        Dictionary<string, object> reply = null;
        int statusCode = 0;
        if(request.error != null)
        {
            Match match = Regex.Match(request.error, "^([0-9]+)");
            if(match.Success)
            {
                statusCode = int.Parse(match.Value);
            }
            else
            {
                errorText = request.error;
                Debug.Log(request.error);
            }
        }
        else
        {
            if(!string.IsNullOrEmpty(request.text))
            {
                reply = Json.Deserialize(request.text) as Dictionary<string, object>;
                statusCode = (int)((long)reply["code"]);
            }
        }

        switch(statusCode)
        {
            case 201:
            case 200: // Successful
                ret = Response.OK;
                if(carrotRequest.ServiceType != ServiceType.Metrics) this.Status = AuthStatus.Ready;
                break;

            case 401: // User has not authorized 'publish_actions', read only
                ret = Response.ReadOnly;
                if(carrotRequest.ServiceType != ServiceType.Metrics) this.Status = AuthStatus.ReadOnly;
                break;

            case 402: // Service tier exceeded, not posted
                ret = Response.UserLimitHit;
                if(carrotRequest.ServiceType != ServiceType.Metrics) this.Status = AuthStatus.Ready;
                break;

            case 403: // Authentication error, app secret incorrect
                ret = Response.BadAppSecret;
                if(carrotRequest.ServiceType != ServiceType.Metrics) this.Status = AuthStatus.Ready;
                break;

            case 404: // Resource not found
                ret = Response.NotFound;
                if(carrotRequest.ServiceType != ServiceType.Metrics) this.Status = AuthStatus.Ready;
                break;

            case 405: // User is not authorized for Facebook App
                ret = Response.NotAuthorized;
                if(carrotRequest.ServiceType != ServiceType.Metrics) this.Status = AuthStatus.NotAuthorized;
                break;

            case 424: // Dynamic OG object not created due to parameter error
                ret = Response.ParameterError;
                if(carrotRequest.ServiceType != ServiceType.Metrics) this.Status = AuthStatus.Ready;
                break;
        }
        if(callback != null) callback(ret, errorText, reply);
    }
示例#3
0
    private CarrotRequestResponse cachedRequestHandler(CarrotCache.CachedRequest cachedRequest,
                                                       CarrotRequestResponse callback)
    {
        return (Response ret, string errorText, Dictionary<string, object> reply) => {
                switch(ret)
                {
                    case Response.OK:
                    case Response.NotFound:
                    case Response.ParameterError:
                        cachedRequest.RemoveFromCache();
                        break;

                    default:
                        cachedRequest.AddRetryInCache();
                        break;
                }
                if(callback != null) callback(ret, errorText, reply);
        };
    }
示例#4
0
 private IEnumerator cachedRequestCoroutine(ServiceType serviceType,
                                            string endpoint,
                                            Dictionary<string, object> parameters,
                                            CarrotRequestResponse callback = null)
 {
     CarrotCache.CachedRequest cachedRequest = mCarrotCache.CacheRequest(serviceType, endpoint, parameters);
     if((int)serviceType <= (int)mAuthStatus)
     {
         yield return StartCoroutine(signedRequestCoroutine(cachedRequest, cachedRequestHandler(cachedRequest, callback)));
     }
     else
     {
         if(callback != null) callback(Response.OK, authStatusString(mAuthStatus), null);
         yield return null;
     }
 }
示例#5
0
 /// <summary>
 /// Inform Carrot about a purchase of premium currency for metrics tracking.
 /// </summary>
 /// <param name="amount">The amount of real money spent.</param>
 /// <param name="currency">The type of real money spent (eg. USD).</param>
 /// <param name="callback">Optional <see cref="CarrotRequestResponse"/> which will be used to deliver the reply.</param>
 public void postPremiumCurrencyPurchase(float amount, string currency, CarrotRequestResponse callback = null)
 {
     StartCoroutine(cachedRequestCoroutine(ServiceType.Metrics, "/purchase.json", new Dictionary<string, object>() {
         {"amount", amount},
         {"currency", currency}
     }, callback));
 }
示例#6
0
 /// <summary>
 /// Post a high score to Carrot.
 /// </summary>
 /// <param name="score">Score.</param>
 /// <param name="callback">Optional <see cref="CarrotRequestResponse"/> which will be used to deliver the reply.</param>
 public void postHighScore(uint score, CarrotRequestResponse callback = null)
 {
     StartCoroutine(cachedRequestCoroutine(ServiceType.Post, "/me/scores.json", new Dictionary<string, object>() {
             {"value", score}
     }, callback));
 }
示例#7
0
    /// <summary>
    /// Sends an Open Graph action which will create a new object.
    /// </summary>
    /// <param name="actionId">Carrot action id.</param>
    /// <param name="actionProperties">Parameters to be submitted with the action.</param>
    /// <param name="viralObject">A <see cref="ViralObject"/> describing the object to be created.</param>
    /// <param name="callback">Optional <see cref="CarrotRequestResponse"/> which will be used to deliver the reply.</param>
    public void postAction(string actionId, IDictionary actionProperties,
                           ViralObject viralObject,
                           CarrotRequestResponse callback = null)
    {
        if(string.IsNullOrEmpty(actionId))
        {
            throw new ArgumentNullException("actionId must not be null or empty string.", "actionId");
        }

        if(viralObject == null)
        {
            throw new ArgumentNullException("viralObject must not be null.", "viralObject");
        }

        Dictionary<string, object> parameters = new Dictionary<string, object>() {
            {"action_id", actionId},
            {"action_properties", actionProperties == null ? new Dictionary<string, object>() : actionProperties},
            {"object_properties", viralObject.toDictionary()}
        };
        StartCoroutine(cachedRequestCoroutine(ServiceType.Post, "/me/actions.json", parameters, callback));
    }
示例#8
0
 /// <summary>
 /// Sends an Open Graph action which will create a new object.
 /// </summary>
 /// <param name="actionId">Carrot action id.</param>
 /// <param name="viralObject">A <see cref="ViralObject"/> describing the object to be created.</param>
 /// <param name="callback">Optional <see cref="CarrotRequestResponse"/> which will be used to deliver the reply.</param>
 public void postAction(string actionId, ViralObject viralObject,
                        CarrotRequestResponse callback = null)
 {
     postAction(actionId, null, viralObject, callback);
 }
示例#9
0
    /// <summary>
    /// Sends an Open Graph action which will use an existing object.
    /// </summary>
    /// <param name="actionId">Carrot action id.</param>
    /// <param name="actionProperties">Parameters to be submitted with the action.</param>
    /// <param name="objectInstanceId">Carrot object instance id.</param>
    /// <param name="callback">Optional <see cref="CarrotRequestResponse"/> which will be used to deliver the reply.</param>
    public void postAction(string actionId, IDictionary actionProperties, string objectInstanceId,
                           CarrotRequestResponse callback = null)
    {
        if(string.IsNullOrEmpty(objectInstanceId))
        {
            throw new ArgumentNullException("objectInstanceId must not be null or empty string.", "objectInstanceId");
        }

        if(string.IsNullOrEmpty(actionId))
        {
            throw new ArgumentNullException("actionId must not be null or empty string.", "actionId");
        }

        Dictionary<string, object> parameters = new Dictionary<string, object>() {
            {"action_id", actionId},
            {"action_properties", actionProperties == null ? new Dictionary<string, object>() : actionProperties},
            {"object_properties", new Dictionary<string, object>()}
        };
        if(objectInstanceId != null) parameters["object_instance_id"] = objectInstanceId;

        StartCoroutine(cachedRequestCoroutine(ServiceType.Post, "/me/actions.json", parameters, callback));
    }
示例#10
0
 /// <summary>
 /// Sends an Open Graph action which will use an existing object.
 /// </summary>
 /// <param name="actionId">Carrot action id.</param>
 /// <param name="objectInstanceId">Carrot object instance id.</param>
 /// <param name="callback">Optional <see cref="CarrotRequestResponse"/> which will be used to deliver the reply.</param>
 public void postAction(string actionId, string objectInstanceId, CarrotRequestResponse callback = null)
 {
     postAction(actionId, null, objectInstanceId, callback);
 }
示例#11
0
    /// <summary>
    /// Post an achievement to Carrot.
    /// </summary>
    /// <param name="achievementId">Carrot achievement id.</param>
    /// <param name="callback">Optional <see cref="CarrotRequestResponse"/> which will be used to deliver the reply.</param>
    public void postAchievement(string achievementId, CarrotRequestResponse callback = null)
    {
        if(string.IsNullOrEmpty(achievementId))
        {
            throw new ArgumentNullException("achievementId must not be null or empty string.", "achievementId");
        }

        StartCoroutine(cachedRequestCoroutine(ServiceType.Post, "/me/achievements.json", new Dictionary<string, object>() {
                {"achievement_id", achievementId}
        }, callback));
    }
示例#12
0
    /// 
    public void popupFeedPost(string objectInstanceId, Dictionary<string, object> objectProperties = null,
                              CarrotRequestResponse callback = null)
    {
        if(string.IsNullOrEmpty(objectInstanceId))
        {
            throw new ArgumentNullException("objectInstanceId must not be null or empty string.", "objectInstanceId");
        }

        Dictionary<string, object> parameters = new Dictionary<string, object>() {
            {"object_instance_id", objectInstanceId},
            {"object_properties", objectProperties == null ? new Dictionary<string, object>() : objectProperties}
        };

        Request request = new Request(ServiceType.Post, "/me/feed_post.json", parameters);
        StartCoroutine(signedRequestCoroutine(request, (Response response, string errorText, Dictionary<string, object> reply) => {
            if(response == Response.OK)
            {
                Dictionary<string, object> fb_data = reply["fb_data"] as Dictionary<string, object>;

                if(fb_data["method"] as string == "feed")
                {
                    if(mFacebookSDKType == FacebookSDKType.OfficialUnitySDK)
                    {
                        string actionName = "";
                        string actionLink = "";
                        if(fb_data.ContainsKey("actions"))
                        {
                            object[] actions = fb_data["actions"] as object[];
                            if(actions != null && actions.Length > 0)
                            {
                                // Will only ever have 1 element
                                Dictionary<string, object> action = actions[0] as Dictionary<string, object>;
                                actionName = action["name"] as string;
                                actionLink = action["link"] as string;
                            }
                        }

                        MethodInfo mi1 = typeof(Carrot).GetMethod("unitySDKFeedPostCallback", BindingFlags.NonPublic | BindingFlags.Instance);
                        object fbDelegate = Delegate.CreateDelegate(mFacebookDelegateType, this, mi1);
                        mOfficialFBSDKFeedMethod.Invoke(null, new object[] {
                            "", // FBID of timeline this should be posted to (default: current)
                            fb_data["link"] as string,
                            "", // Name of the link (default: App Name)
                            fb_data["caption"] as string,
                            fb_data["description"] as string,
                            fb_data["picture"] as string,
                            "", // URL of audio/video content
                            actionName, // Action name
                            actionLink, // Action link
                            fb_data["ref"] as string,
                            new Dictionary<string, string[]>{},
                            fbDelegate
                        });
                    }
                    else if(mFacebookSDKType == FacebookSDKType.JavaScriptSDK)
                    {
                        Application.ExternalEval("FB.ui(" + Json.Serialize(fb_data) + ", function(response) {" +
                                                 "    if(response == null || response == undefined) { response = {canceled: true}; }" +
                                                 "    " + mUnityObject2Instance + ".getUnity().SendMessage('CarrotGameObject', 'javascriptSDKFeedPostCallback', JSON.stringify(response));" +
                                                 "});"
                        );
                    }
                }
            }
            else
            {
                // Something-something danger zone
            }
        }));
    }
 public void postAction(string actionId, string objectId, IDictionary objectProperties,
                        string objectInstanceId = null, CarrotRequestResponse callback = null)
 {
     postAction(actionId, null, objectId, objectProperties, objectInstanceId, callback);
 }