Surendra Sharma

Surendra Sharma

Search This Blog

Thursday, September 20, 2018

Control tweets from Sitecore

Manage Twitter Feeds from Sitecore
Manage Twitter Feeds from Sitecore

 
This is a series of 3 articles where I will show how you control Facebook, Twitter and Youtube feeds from Sitecore and display it on your web page.

In my last post, I showed how to manage Facebook feeds using Facebook graph API.

In this post, we will check how to access and control Twitter feeds from Sitecore. 

For this you need Twitter Access tokens, Access Keys, Consumer Key and Consumer secret values 

Create Sitecore template having fields like

Sitecore Twitter Fields
Sitecore Twitter Fields


Code

First we need to create Template mapping class for these Twitter fields as

namespace Sitecore.Feature.Social
{
    using Sitecore.Data;

    public struct Templates
    {
        public struct SocialFeedsManager
        {
            public static ID ID = new ID("{B1959961-A315-468D-8D03-CA50CB790C86}");
            public static ID ContentItemID = new ID("{EC8578D8-4C0F-413E-83F2-C9BA5B249E85}");


            public struct Fields
            {
            
                public static readonly ID TwitterAccessToken = new ID("{68693294-D321-4FCD-8A69-910F27E5B894}");
                public static readonly ID TwitterAccessTokenSecret = new ID("{D2881F03-DCA0-4484-A422-F632813D95D4}");
                public static readonly ID TwitterConsumerKey = new ID("{967E51DE-3155-4D06-9FDE-2E5C1D493C16}");
                public static readonly ID TwitterConsumerSecret = new ID("{0BA077CC-45F6-429F-8B9E-E5A601E411D2}");
                public static readonly ID TwitterPlatformName = new ID("{FD719E96-F7C7-490D-93E4-F48C357E865F}");
                public static readonly ID TwitterMaxFeedsInAll = new ID("{90D7BBA4-F08D-471E-8135-23CF60D21375}");
                public static readonly ID TwitterMaxFeeds = new ID("{CD782AAA-14A3-4B75-BF8D-8D690BF82354}");
                public static readonly ID TwitterIsActive = new ID("{EE7E8B46-62D1-40B8-9591-EF9CB85B0F0B}");
            }
        }


    }
}

Create Model classes to holds values of Sitecore item fields values and JSON data return by Twitter for feeds as

·         ChannelName – Enum for different social channel
·         SocialFeedsManagerModel – Get Sitecore item values for Twitter
·         Tweet and User – Hold Twitter JSON feeds to objects
·         SocialMediaFeed – Class to hold single feed values from JSON data

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Sitecore.Data.Items;
using Sitecore.Foundation.SitecoreExtensions.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using static Sitecore.Feature.Social.Templates;

namespace Sitecore.Feature.Social.Models
{
    public enum ChannelName
    {
        All,
        Facebook,
        Twitter,
        Instagram,
        Youtube
    }

    /// <summary>
    /// Social Feeds Model for getting Sitecore fields data
    /// </summary>
    public class SocialFeedsManagerModel
    {

        //Twitter
        public string TwitterAccessToken { get; set; }
        public string TwitterAccessTokenSecret { get; set; }
        public string TwitterConsumerKey { get; set; }
        public string TwitterConsumerSecret { get; set; }
        public string TwitterPlatformName { get; set; }
        public int TwitterMaxFeedsInAll { get; set; }
        public int TwitterMaxFeeds { get; set; }
        public bool TwitterIsActive { get; set; }

        public SocialFeedsManagerModel() { }

        public void InitializeData(Item dataSourceItem, ChannelName channelName)
        {
            if (channelName == ChannelName.Twitter || channelName == ChannelName.All)
            {
                //Twitter
                this.TwitterIsActive = dataSourceItem.Fields[SocialFeedsManager.Fields.TwitterIsActive].IsChecked();
                if (this.TwitterIsActive)
                {
                    this.TwitterAccessToken = dataSourceItem[SocialFeedsManager.Fields.TwitterAccessToken];
                    this.TwitterAccessTokenSecret = dataSourceItem[SocialFeedsManager.Fields.TwitterAccessTokenSecret];
                    this.TwitterConsumerKey = dataSourceItem[SocialFeedsManager.Fields.TwitterConsumerKey];
                    this.TwitterConsumerSecret = dataSourceItem[SocialFeedsManager.Fields.TwitterConsumerSecret];
                    this.TwitterMaxFeeds = System.Convert.ToInt32(dataSourceItem[SocialFeedsManager.Fields.TwitterMaxFeeds]);
                    this.TwitterMaxFeedsInAll = System.Convert.ToInt32(dataSourceItem[SocialFeedsManager.Fields.TwitterMaxFeedsInAll]);
                    this.TwitterPlatformName = dataSourceItem[SocialFeedsManager.Fields.TwitterPlatformName];
                }
            }

        }
    }

    /// <summary>
    /// Model for Social Media Feeds returning as JSON
    /// </summary>
    public class SocialMediaFeed
    {
        public string FeedID { get; set; }
        public string PlatformName { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public string ImageURL { get; set; }
        public string FeedURL { get; set; }
        public DateTime Timestamp { get; set; }
        public string From { get; set; }
    }
    /// <summary>
    /// Twitter Tweet Model
    /// </summary>
    public class Tweet
    {
        public string created_at;
        public string favorite_count;
        public string id;
        public string id_str;
        public string lang;
        public string name;
        public string retweet_count;
        public string text;
        public user user;

        public Tweet() { }
    }

    /// <summary>
    /// Twitter user details model
    /// </summary>
    public class user
    {
        public string id;
        public string id_str;
        public string name;
        public string screen_name;

        public user() { }
    }
}

Below is Controller code for fetching feeds from Twitter and then as per settings in Sitecore item, return JSONResult of Twitter Feeds which finally received by AJAX request to show it on page.

namespace Sitecore.Feature.Social.Controllers
{
    using Newtonsoft.Json;
    using Sitecore.Data.Items;
    using Sitecore.Feature.Social.Models;
    using Sitecore.Foundation.SitecoreExtensions.Extensions;
    using Sitecore.Mvc.Presentation;
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Security.Cryptography;
    using System.Text;
    using System.Web.Mvc;
    using System.Web.Script.Serialization;
    using static Sitecore.Feature.Social.Templates;

    public class SocialController : Controller
    {
        private List<SocialMediaFeed> lstSocialFeeds = null;

        public ActionResult GetSocialFeeds(string channelName, string token)
        {
            string result = "Error - ";

            if (string.IsNullOrEmpty(channelName) || string.IsNullOrEmpty(token) || !token.Equals("accesstoken"))
            {
                result += "Unauthorized request!!!";
            }


            channelName = channelName ?? "all";
            result = CollectSocialFeeds(channelName, result);

            if (lstSocialFeeds != null && lstSocialFeeds.Count > 0)
            {
                return Json(new { success = true, responseResult = lstSocialFeeds }, JsonRequestBehavior.AllowGet);
            }
            else
            {
                return Json(new { success = false, responseResult = result }, JsonRequestBehavior.AllowGet);
            }

        }
        /// <summary>
        /// Collect all feeds in list
        /// </summary>
        /// <param name="channelName"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        private string CollectSocialFeeds(string channelName, string result)
        {
            try
            {
                SocialFeedsManagerModel _SocialFeedsManagerModel = new SocialFeedsManagerModel();

                Item dataSourceItem = null;

                if (RenderingContext.CurrentOrNull != null)
                {
                    var dataSourceId = RenderingContext.CurrentOrNull.Rendering.DataSource;
                    dataSourceItem = Sitecore.Context.Database.GetItem(dataSourceId);
                }

                if (!dataSourceItem?.IsDerived(Templates.SocialFeedsManager.ID) ?? true)
                {
                    dataSourceItem = Context.Database.GetItem(SocialFeedsManager.ContentItemID);
                }

                lstSocialFeeds = new List<SocialMediaFeed>();

                switch (channelName.ToLower())
                {                    
                    case "twitter":
                        {
                            _SocialFeedsManagerModel.InitializeData(dataSourceItem, ChannelName.Twitter);

                            if (_SocialFeedsManagerModel.TwitterIsActive)
                            {
                                lstSocialFeeds = GetTwitterFeeds(_SocialFeedsManagerModel.TwitterAccessToken, _SocialFeedsManagerModel.TwitterAccessTokenSecret,
                                _SocialFeedsManagerModel.TwitterConsumerKey, _SocialFeedsManagerModel.TwitterConsumerSecret,
                                _SocialFeedsManagerModel.TwitterPlatformName, _SocialFeedsManagerModel.TwitterMaxFeeds);
                            }
                            else
                            {
                                result += " Twitter feeds are disabled.";
                            }
                            break;
                        }                   
                    default:
                        {
                            result += " Invalid Social Media.";
                            lstSocialFeeds = null;
                            break;
                        }
                }
            }
            catch (Exception ex)
            {
                result += " Occurred." + ex.Message;
                lstSocialFeeds = null;
                string str = ex.Message;
            }

            return result;
        }

        /// <summary>
        /// Get Twitter Feeds
        /// </summary>
        /// <param name="oauthToken"></param>
        /// <param name="oauthTokenSecret"></param>
        /// <param name="oauthConsumerKey"></param>
        /// <param name="oauthConsumerSecret"></param>
        /// <param name="PlatformName"></param>
        /// <param name="MaxResult"></param>
        /// <returns></returns>
        private List<SocialMediaFeed> GetTwitterFeeds(string oauthToken, string oauthTokenSecret, string oauthConsumerKey, string oauthConsumerSecret,
            string PlatformName = "Twitter", int MaxResult = 2)
        {
            string tempTwitterResponse = GetLatestTweetsFromUserTimeline(oauthToken, oauthTokenSecret, oauthConsumerKey, oauthConsumerSecret, MaxResult);

            JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
            List<Tweet> tweetList = jsonSerializer.Deserialize<List<Tweet>>(tempTwitterResponse);
            tempTwitterResponse = string.Empty;

            List<SocialMediaFeed> lstTwitterFeeds = null;

            if (tweetList != null && tweetList.Count > 0)
            {
                lstTwitterFeeds = tweetList.Select(x => new SocialMediaFeed
                {
                    FeedID = x.id,
                    PlatformName = PlatformName,
                    Title = x.name,
                    Description = Server.HtmlEncode(x.text),
                    ImageURL = "",
                    FeedURL = "https://twitter.com/" + x.user.screen_name + "/status/" + x.id_str,
                    From = x.user.name,
                    Timestamp = DateTime.ParseExact(x.created_at, "ddd MMM dd HH:mm:ss zzz yyyy", CultureInfo.InvariantCulture)
                }).ToList();
            }

            return lstTwitterFeeds;
        }

        /// <summary>
        /// Get Twitter feeds from User Timeline
        /// </summary>
        /// <param name="oauthToken"></param>
        /// <param name="oauthTokenSecret"></param>
        /// <param name="oauthConsumerKey"></param>
        /// <param name="oauthConsumerSecret"></param>
        /// <param name="MaxResult"></param>
        /// <returns></returns>
        private string GetLatestTweetsFromUserTimeline(string oauthToken, string oauthTokenSecret, string oauthConsumerKey, string oauthConsumerSecret, int MaxResult = 2)//Item twitterCalloutItem)
        {
            string tempTwitterResponse = string.Empty;
            try
            {
                string resourceUrl = "https://api.twitter.com/1.1/statuses/user_timeline.json";

                string oauthVersion = "1.0";
                string oauthSignatureMethod = "HMAC-SHA1";
                string oauthSignature = string.Empty;
                var compositeKey = string.Concat(Uri.EscapeDataString(oauthConsumerSecret), "&", Uri.EscapeDataString(oauthTokenSecret));
                string oauthNonce = System.Convert.ToBase64String(new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()));
                var timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
                string oauthTimestamp = System.Convert.ToInt64(timeSpan.TotalSeconds).ToString();

                string baseFormat = "count=" + MaxResult.ToString() + "&oauth_consumer_key={0}&oauth_nonce={1}&oauth_signature_method={2}" +
                                "&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}";

                string baseString = string.Format(baseFormat, oauthConsumerKey, oauthNonce, oauthSignatureMethod, oauthTimestamp,
                                            oauthToken, oauthVersion);

                string headerFormat = "OAuth oauth_nonce=\"{0}\", oauth_signature_method=\"{1}\", " +
                                 "oauth_timestamp=\"{2}\", oauth_consumer_key=\"{3}\", " +
                                 "oauth_token=\"{4}\", oauth_signature=\"{5}\", " +
                                 "oauth_version=\"{6}\"";

                baseString = string.Concat("GET&", Uri.EscapeDataString(resourceUrl), "&", Uri.EscapeDataString(baseString));

                using (HMACSHA1 hasher = new HMACSHA1(ASCIIEncoding.ASCII.GetBytes(compositeKey)))
                {
                    oauthSignature = System.Convert.ToBase64String(hasher.ComputeHash(ASCIIEncoding.ASCII.GetBytes(baseString)));
                }

                string authHeader = string.Format(headerFormat,
                                        Uri.EscapeDataString(oauthNonce),
                                        Uri.EscapeDataString(oauthSignatureMethod),
                                        Uri.EscapeDataString(oauthTimestamp),
                                        Uri.EscapeDataString(oauthConsumerKey),
                                        Uri.EscapeDataString(oauthToken),
                                        Uri.EscapeDataString(oauthSignature),
                                        Uri.EscapeDataString(oauthVersion)
                                );
                ServicePointManager.Expect100Continue = false;
                var postBody = "count=" + MaxResult.ToString();
                resourceUrl += "?" + postBody;
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(resourceUrl);
                request.Headers.Add("Authorization", authHeader);
                request.Method = "GET";
                request.ContentType = "application/x-www-form-urlencoded";
                var response = (HttpWebResponse)request.GetResponse();
                var reader = new StreamReader(response.GetResponseStream());
                tempTwitterResponse = reader.ReadToEnd();
            }
            catch (Exception ex)
            {
                string str = ex.Message;
            }
            return tempTwitterResponse;
        }

Write AJAX script and view in HTML to load the feeds
@model Sitecore.Feature.Social.Models.JSONOutput

<div id="SocialFeedsDiv">


    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    <script>


        $(document).ready(function () {
            var b = null;
            $("#all").click(function () {
                loadfeeds("All")
            });

            $("#Facebook").click(function () {
                loadfeeds("Facebook")
            });

            $("#Twitter").click(function () {
                loadfeeds("Twitter")
            });

            $("#Youtube").click(function () {
                loadfeeds("Youtube")
            });

            $("#Instagram").click(function () {
                loadfeeds("Instagram")
            });


            function loadfeeds(channelName) {
                $.get("/api/sitecore/social/GetSocialFeeds?channelName=" + channelName + "&token=accesstoken", function (data, status) {
                    var index = 1;
                    $("#feedlist").html("");
                    $.each(data.responseResult, function (i, field) {
                        var imageurl = "";
                        if (field.ImageURL !="" || field.ImageURL != null) {
                            imageurl = "ImageURL : <a href='" + field.FeedURL + "' ><img src='" + field.ImageURL + "' alt='" + field.Title + "' /> </a> <br>";
                        }
                        $("#feedlist").append(
                            "<li>Sr No :" + index + "<br>" +
                            "FeedID :" + field.FeedID + "<br>" +
                            "PlatformName :" + field.PlatformName + "<br>" +
                            "Title :" + field.Title + "<br>" +
                            "Description :" + field.Description + "<br>" + imageurl
                            +
                            "FeedURL :" + field.FeedURL + "<br>" +
                            "Timestamp :" + field.Timestamp + "<br>" +
                            "From :" + field.From + "<br><br><br>" + "</li>"
                        );
                        index++;
                    });
                });
            }
        });

    </script>

     <br />
    <a href="javascript:void(0)" id="all">All</a><br />
    <a href="javascript:void(0)" id="Facebook">Facebook</a><br />
    <a href="javascript:void(0)" id="Twitter">Twitter</a><br />
    <a href="javascript:void(0)" id="Youtube">Youtube</a><br />
    <a href="javascript:void(0)" id="Instagram">Instagram</a><br />

    <div id="feed">

    </div>

    <br />
    <br />

    <div id="HTMLfeed">
        <ul id="feedlist"></ul>


    </div>

</div>

We can access this action method from URL AJAX as

This will return JSON result which include individual feeds
{
    "success": true,
    "responseResult": [
        {
            "FeedID": "111111111_2222222",
            "PlatformName": "Twitter",
            "Title": null,
            "Description": " We all love free things. If you apply same concept on study, its great for professional life as well as for future",
            "ImageURL": "",
            "FeedURL": " https://twitter.com/billgates/status/929590756544123456",
            "Timestamp": "/Date(1530689661000)/",
            "From": " Bill Gates"
        }
    ]
}

Once we have JSON, we can show it in page in any desired HTML format.
That’s it.

I hope you enjoy this Sitecore article. Stay tuned for more Sitecore related articles.

Till that happy Sitecoring :)

Please leave your comments or share this article if it’s useful for you.

No comments:

Post a Comment