Monday, January 31, 2011

Setting Privacy options in Status Update via Facebook toolkit



Recently I was working over the status updates via facebook toolkit http://facebooktoolkit.codeplex.com/,  which works like a charm no doubt about that.
But one of the requirements I had this time, was to allow the facebook application to set the status updates, but with a privacy level of SELF.
I have read the Facebook publish stream API in detail, and I was quite sure that there must be an option there in the facebook toolkit, to use the privacy levels as specified in facebook documentation here http://developers.facebook.com/docs/reference/rest/stream.publish/

Apparently I couldn’t find any option with the Facebook toolkit to use the privacy options.
How hard could it to be extend the toolkit to start doing the privacy thing?
Answer – not at all.
The facebook Rest based api expect the applications to send the privacy levels as a json encoded object – as per documentation ---
privacy
object
A JSON-encoded object that defines the privacy setting for a post, video, or album. It contains the following fields.
·         value (string): The privacy value for the object, specify one of EVERYONE, CUSTOM, ALL_FRIENDS, NETWORKS_FRIENDS, FRIENDS_OF_FRIENDS, SELF.
·         friends (string): For CUSTOM settings, this indicates which users can see the object. Can be one of EVERYONE, NETWORKS_FRIENDS (when the object can be seen by networks and friends), FRIENDS_OF_FRIENDS, ALL_FRIENDS, SOME_FRIENDS, SELF, or NO_FRIENDS (when the object can be seen by a network only).
·         networks (string): For CUSTOM settings, specify a comma-separated list of network IDs that can see the object, or 1 for all of a user's networks.
·         allow (string): When friends is set to SOME_FRIENDS, specify a comma-separated list of user IDs and friend list IDs that ''can'' see the post.
·         deny (string): When friends is set to SOME_FRIENDS, specify a comma-separated list of user IDs and friend list IDs that ''cannot'' see the post.
Only the user can specify the privacy settings for the post. You can create an interface that lets the user specify the privacy setting. For CUSTOM settings, use friends.getand friends.getLists to get the user's friends and friend lists to populate the interface, then pass along the selections to the privacy object.
Note: This privacy setting only applies to posts to the current or specified user's own Wall; Facebook ignores this setting for targeted Wall posts (when the user is writing on the Wall of a friend, Page, event, group connected to the user). Consistent with behavior on Facebook, all targeted posts are viewable by anyone who can see the target's Wall.
Privacy Policy: Any non-default privacy setting must be intentionally chosen by the user. You may not set a custom privacy setting unless the user has proactively specified that they want this non-default setting.


I created an overloaded function of public string Publish(string message,string privacy) in Stream.cs of C# project of facebook toolkit’s Facebook base project.
Here’s how it looks

STREAM.cs
public string Publish(string message,string privacy)
        {
            return Publish(message, null, null, null, 0, false, null, null,privacy);           
        }

Then I wrote an overload of the private publish function in the same class stream.cs, again with the privacy string in it, here’s how that function looks
Look for the additional parameter – colored as YELLOW in the below function.

STREAM.cs

/// <summary>
        /// For the Privacy based publishing
        /// like  "{\"value\":\"SELF\"}"
        /// </summary>
        /// <param name="message"></param>
        /// <param name="attachment"></param>
        /// <param name="action_links"></param>
        /// <param name="target_id"></param>
        /// <param name="uid"></param>
        /// <param name="isAsync"></param>
        /// <param name="callback"></param>
        /// <param name="state"></param>
        /// <param name="privacy">Privacy like "{\"value\":\"SELF\"}"</param>
        /// <returns></returns>
        private string Publish(string message, attachment attachment, IList<action_link> action_links, string target_id, long uid, bool isAsync, PublishCallback callback, Object state,string privacy)
        {
            var parameterList = new Dictionary<string, string> { { "method", "facebook.stream.publish" } };
            Utilities.AddOptionalParameter(parameterList, "message", message);
            if (attachment != null)
            {
                var mediaList = new List<string>();
                var prop = new Dictionary<string, string>();
                if (attachment.properties != null)
                {
                    foreach (var item in attachment.properties)
                    {
                        prop.Add(item.name, item.value.ToString());
                    }
                }

                if (attachment.media != null)
                {
                    foreach (var item in attachment.media)
                    {
                        var media = new Dictionary<string, string>{
                               {"type", item.type.ToString()}
                                };
                        if (item.type == attachment_media_type.image)
                        {
                            var image = item as attachment_media_image;
                            media.Add("src", image.src);
                            media.Add("href", image.href);
                        }
                        else if (item.type == attachment_media_type.flash)
                        {
                            var flash = item as attachment_media_flash;
                            media.Add("swfsrc", flash.swfsrc);
                            media.Add("imgsrc", flash.imgsrc);
                            media.Add("width", flash.width.ToString());
                            media.Add("height", flash.height.ToString());
                            media.Add("expanded_width", flash.expanded_width.ToString());
                            media.Add("expanded_height", flash.expanded_height.ToString());
                        }
                        else if (item.type == attachment_media_type.mp3)
                        {
                            var mp3 = item as attachment_media_mp3;
                            media.Add("src", mp3.src);
                            media.Add("title", mp3.title);
                            media.Add("artist", mp3.artist);
                            media.Add("album", mp3.album);
                        }
                        else
                        {
                            var video = item as attachment_media_video;
                            media.Add("video_src", video.video_src);
                            media.Add("preview_img", video.preview_img);
                            media.Add("video_link", video.video_link);
                            media.Add("video_title", video.video_title);
                        }
                        mediaList.Add(JSONHelper.ConvertToJSONAssociativeArray(media));
                    }

                }
                var dict = new Dictionary<string, string>{
                    {"name", attachment.name},
                    {"href", attachment.href},
                    {"caption", attachment.caption},
                    {"description", attachment.description},
                    {"properties", JSONHelper.ConvertToJSONAssociativeArray(prop)},
                    {"media", JSONHelper.ConvertToJSONArray(mediaList)},
                    {"latitude", attachment.latitude},
                    {"longitude", attachment.longitude}
                };
                Utilities.AddOptionalParameter(parameterList, "attachment", JSONHelper.ConvertToJSONAssociativeArray(dict));
            }
            if (action_links != null)
            {
                var list = new List<string>();
                foreach (var item in action_links)
                {
                    var dict = new Dictionary<string, string>{
                    {"text", item.text},
                    {"href", item.href}
                };
                    list.Add(JSONHelper.ConvertToJSONAssociativeArray(dict));
                }
                Utilities.AddJSONArray(parameterList, "action_links", list);

            }
            Utilities.AddOptionalParameter(parameterList, "target_id", target_id);
            Utilities.AddOptionalParameter(parameterList, "uid", uid);
            Utilities.AddOptionalParameter(parameterList, "privacy",privacy);
            if (isAsync)
            {
                SendRequestAsync<stream_publish_response, string>(parameterList, uid <= 0, new FacebookCallCompleted<string>(callback), state);
                return null;
            }

            var response = SendRequest<stream_publish_response>(parameterList, uid <= 0);
            return response == null ? null : response.TypedValue;
        }
         



It’s that simple, at the upper level, I asked my clients to send me the privacy as an object, and I convert it into an encoded json string, this is something that I can’t share due to copyright issues.


There was an error in this gadget