My Twitter Feed – SAP Webide Plugin
Motivation
As a developer we tend to have many tabs opened in our browser and sometimes it gets irritating. I specifically have this irritating habit of checking my twitter feed frequently. Each time i end up switching tabs etc while working. So this where the motivation to develop a SAP web ide plugin came, so that i can view my recent twitter feed without leaving my current tab and in case anything is interesting then only take some action. So this adventure talks about the quick and dirty solution to resolve my problem.
Where to start of course Hello World Basic Plugin
Of course as the ritual is to start with something like Hello World, so found this great tutorial where you can create a Hello World plugin/feature in like 2 minutes. The real trouble started when i went ahead to adapt it as per my need.
Going beyond Hello World
I created a view folder and created the view and controller for our twitter feed. Next step was to add the list to the view which was also done in no time.
<List noDataText="Drop list items here" id="list2">
<items>
<StandardListItem type="Navigation" title="List Item 1" description="Description text" icon="sap-icon://picture" id="item4"/>
</items>
</List>
Before coding anything for the backend I wanted to check how my view looks like.Although in theory it is quite clear that it has to be done via Services and Plugin.json files but easier said than done. This is where i got stuck but always we have someone to help, so found this great blog series by Wouter Lemaire and was able to quickly resolve all the issue.Must read his blog to understand in detail about the different concepts. So all i need to do was create my service file which will call my view.
define(
["sap/watt/platform/plugin/platform/service/ui/AbstractPart"],
function(AbstractPart) {
"use strict";
return AbstractPart.extend("twitterplugin.service.MyFirstViewService.", {
_oView: null,
getContent: function() {
var me = this;
return AbstractPart.prototype.getContent.apply(this, arguments).then(function() {
me._oView = sap.ui.view({
viewName: "twitterplugin.view.view.twitter",
type: sap.ui.core.mvc.ViewType.XML,
viewData: {
context: me.context
}
});
return me._oView;
});
}
});
});
Next step was to add the service in our plugin.json and bingo we are done we have a simple view with static list as of now. Next step was to fetch the tweets so read on.
{
"name":"twitterplugin",
"description":"twitterplugin",
"i18n":"twitterplugin/i18n/i18n",
"requires":{
"services":[
"usernotification",
"log",
"command",
"commandGroup",
"perspective"
]
},
"provides":{
"services":{
"sample":{
"implements":"twitterplugin.service.Sample",
"module":"twitterplugin/service/Sample"
},
"myfirstviewservice":{
"implements":"sap.watt.common.service.ui.Part",
"module":"twitterplugin/service/MyFirstViewService"
}
},
"interfaces":{
"twitterplugin.service.Sample":"twitterplugin/service/Sample"
}
},
"configures":{
"services":{
"perspective:views":[
{
"id":"myfirstview",
"service":"@myfirstviewservice"
}
],
"perspective:viewToAreaMapping":[
{
"view":"myfirstview",
"perspective":"development",
"area":"right"
}
],
"command:commands":[
{
"id":"myfirstviewcommand",
"label":"Open View",
"icon":"sap-icon://display",
"service":{
"implements":"sap.watt.common.service.ide.AbstractUIPartToggler",
"module":"sap.watt.common.perspective/command/AbstractUIPartToggler",
"configuration":{
"id":"myfirstviewcommand",
"service":"@myfirstviewservice",
"perspective":"development"
}
},
"keyBinding":"mod+shift+8"
},
{
"id":"twitterplugin.helloWorld",
"label":"{i18n>command_helloWorld}",
"service":"twitterplugin/command/HelloWorld"
}
],
"commandGroup:groups":[
{
"id":"tools.sample",
"label":"{i18n>commandgroup_sample}"
},
{
"id":"tools.sample.helloWorld"
}
],
"commandGroup:items":[
{
"parent":"applicationRightSidebar",
"command":"myfirstviewcommand",
"prio":101
},
{
"parent":"tools",
"type":"menu",
"group":"tools.sample",
"prio":100
},
{
"parent":"tools.sample",
"type":"inline",
"group":"tools.sample.helloWorld",
"prio":10
},
{
"parent":"tools.sample.helloWorld",
"type":"action",
"command":"twitterplugin.helloWorld",
"prio":10
}
]
}
},
"subscribes":{
"sample:notificationDisplayed":"sample:onAfterNotificationDisplayed"
}
}
Fetching Tweets via backend
We need an api call in our frontend to fetch all the tweets. Just to keep things simple I created a PHP api to fetch the tweets. The server side is using an open source twitter php library and it was a quite easy to fetch the data.
<?php
require_once('TwitterAPIExchange.php');
/** Set access tokens here - see: https://dev.twitter.com/apps/ **/
$settings = array(
'oauth_access_token' => "<oauth token of your Twitter app>",
'oauth_access_token_secret' => "<oauth secret of your Twitter app>,
'consumer_key' => "< key of your Twitter app>",
'consumer_secret' => "<secret of your Twitter app>”
);
$url = "https://api.twitter.com/1.1/statuses/home_timeline.json";
$requestMethod = "GET";
if (isset($_GET['user'])) {$user = preg_replace("/[^A-Za-z0-9_]/", '', $_GET['user']);} else {$user = "nabheet";}
if (isset($_GET['count']) && is_numeric($_GET['count'])) {$count = $_GET['count'];}
else {
$count = 20;
}
$getfield = "?screen_name=$user&count=$count";
$twitter = new TwitterAPIExchange($settings);
$string = json_decode($twitter->setGetfield($getfield)
->buildOauth($url, $requestMethod)
->performRequest(),$assoc = TRUE);
if(array_key_exists("errors", $string)) {echo "<h3>Sorry, there was a problem.</h3><p>Twitter returned the following error message:</p><p><em>".$string[errors][0]["message"]."</em></p>";exit();}
$count = 0;
$items1 = array();
foreach($string as $items)
{
$items1[$count]['datetime'] = $items['created_at'];
$items1[$count]['user'] = $items['user']['name'];
$items1[$count]['Tweet'] = $items['text'];
$items1[$count]['url'] = $items['user']['profile_image_url'];
$count++;
}
echo json_encode(array("results"=>$items1));
?>
This could have also been done without using the PHP script, check this blog by Meredith Hassett for more details.
Final Output
So now we have backend API also read, all what was needed was to make the call. As my code is hosted on a site which is not HTTPS so calls got blocked but then all i need was simple wrapper as shown below. I could have also used a reverse proxy for the same.
var oModel = new sap.ui.model.json.JSONModel("https://cors-anywhere.herokuapp.com/http://<site>/Twitter/twitter.php",);
this.getView().setModel(oModel);
Finally we have our plugin with tweets ready. It is the quick and dirty solution I came up with to help me with my productivity. The plugin might need finishing touches so please excuse. Feel free to provide your feedback.I think we need a dedicate play store kind of thing where all the plugins can be uploaded and developer can download as per the need. Looking forward to hear back from you.