status.getText() does not give proper HTML - twitter

I am using java and twitter4j.
Issue : I do not get proper response from status.getText() method, link references comes as text
I have a problem. My method is as follow:
Twitter twitter = null;
String userName = "clientname";
int numberOfTweets = 0;
StringBuilder timeLineText = new StringBuilder();
try {
twitter = new TwitterFactory(new GetAuthenticConfiguration().getConfigObject()).getInstance();
ResponseList<Status> statuses = twitter.getUserTimeline(userName);
timeLineText.append("<li>");
for (Status status : statuses) {
numberOfTweets++;
if (numberOfTweets > 12) {
break;
}
int remainder = numberOfTweets % 3;
if (remainder == 0) {
timeLineText.append("</li><li>");
} else {
StringBuilder tempText = new StringBuilder();
try {
tempText.append("<p>");
tempText.append("<span>");
tempText.append("<img alt=\"" + status.getUser().getScreenName() + "\" src=\"" + status.getUser().getMiniProfileImageURL() + "\" />");
tempText.append("<b>" + status.getUser().getName() + "</b> #" + status.getUser().getScreenName() + " " + new SimpleDateFormat("dd MMM").format(status.getCreatedAt()));
tempText.append("</span>");
tempText.append("<p>" + status.getText() + "</p>");
tempText.append("</p>");
} catch (Exception e) {
System.out.println(e);
}
timeLineText.append(tempText);
}
}
timeLineText.append("</li>");
} catch (Exception te) {
System.out.println(te);
}
The response i get is :
Can you tell us which Rolls-Royce #engine powers this aircraft? #AvGeek http://t.co/t5tNXQuMFB
instead of
Can you tell us which Rolls-Royce <a href="/hashtag/engine?src=hash" data-query-source="hashtag_click" class="twitter-hashtag pretty-link js-nav" dir="ltr" ><s>#</s><b>engine</b></a> powers this aircraft? <a href="/hashtag/AvGeek?src=hash" data-query-source="hashtag_click" class="twitter-hashtag pretty-link js-nav" dir="ltr" ><s>#</s><b>AvGeek</b></a> <a href="http://t.co/t5tNXQuMFB" class="twitter-timeline-link u-isHiddenVisually" data-pre-embedded="true" dir="ltr" >pic.twitter.com/t5tNXQuMFB</a>
The issue is I am not getting the proper html . Can anyone tell me the reason of it please?

After doing lot of R & D, I have found out that Status.getText() method gives only plain text.
We have to manually convert it to links,hashtags and users.
Below is the method I have written to do that.
Just pass your getText() output to this method (tweet).
I hope this will help to many beginners of Twitter4J.
private String linkifyTweet(String tweet) {
Pattern pattern;
Matcher matcher;
String regex_url = "((https?://\\S+)|(www.\\S+))";
String regex_hashtag = "#(\\w+)";
String regex_user = "#(\\w+)";
//regex to apply links to all urls in the tweet
pattern = Pattern.compile(regex_url);
matcher = pattern.matcher(tweet);
if (matcher.find()) {
tweet = tweet.replaceAll(regex_url, "<a target=\"_blank\" href=\"$1\">$1</a>");
}
//regex to apply links to all hashtags in the tweet
pattern = Pattern.compile(regex_hashtag);
matcher = pattern.matcher(tweet);
if (matcher.find()) {
tweet = tweet.replaceAll(regex_hashtag, "<a target=\"_blank\" href=\"https://www.twitter.com/hashtag/$1?src=hash\">#$1</a>");
}
//regex to apply links to all users in the tweet
pattern = Pattern.compile(regex_user);
matcher = pattern.matcher(tweet);
if (matcher.find()) {
tweet = tweet.replaceAll(regex_user, "<a target=\"_blank\" href=\"https://www.twitter.com/$1\">#$1</a>");
}
//System.out.println(tweet);
return tweet;
}

Related

Twitter4j error on processing

Im trying to follow this tutorial:
//Build an ArrayList to hold all of the words that we get from the
imported tweets
ArrayList<String> words = new ArrayList();
void setup() { //Set the size of the stage, and the background to black.
size(550,550);
background(0);
smooth();
//Credentials ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setOAuthConsumerKey("lPFSpjBppo5u4KI5xEXaQ");
cb.setOAuthConsumerSecret("SYt3e4xxSHUL1gPfM9bxQIq6Jf34Hln9T1q9KGCPs");
cb.setOAuthAccessToken("17049577-Yyo3AEVsqZZopPTr055TFdySop228pKKAZGbJDtnV");
cb.setOAuthAccessTokenSecret("6ZjJBebElMBiOOeyVeh8GFLsROtXXtKktXALxAT0I");
//Make the twitter object and prepare the query
Twitter twitter = new
TwitterFactory(cb.build()).getInstance();
Query query = new Query("#OWS");
query.setRpp(100);
//Try making the query request. try {
QueryResult result = twitter.search(query);
ArrayList tweets = (ArrayList) result.getTweets();
for (int i = 0; i < tweets.size(); i++) {
Tweet t = (Tweet) tweets.get(i);
String user = t.getFromUser();
String msg = t.getText();
Date d = t.getCreatedAt();
println("Tweet by " + user + " at " + d + ": " + msg);
//Break the tweet into words
String[] input = msg.split(" ");
for (int j = 0; j < input.length; j++) {
//Put each word into the words ArrayList
words.add(input[j]);
}
}; } catch (TwitterException te) {
println("Couldn't connect: " + te); }; } void draw() { //Draw a faint black rectangle over what is currently on the stage so
it fades over time. fill(0,1); rect(0,0,width,height);
//Draw a word from the list of words that we've built int i = (frameCount % words.size()); String word = words.get(i);
//Put it somewhere random on the stage, with a random size and colour fill(255,random(50,150)); textSize(random(10,30));
text(word, random(width), random(height)); }
But i get the following error when i run the code in processing. cannot find class or type named tweet
Ive added the twitter4j libraries by dragging and dropping to the processing IDE.
Im using processing 2.1 and twitter4j3.05
Any suggestions?
This is a basic example using twitter4j 3.0.5.
import java.util.*;
List<Status>statuses = null;
TwitterFactory twitterFactory;
Twitter twitter;
void setup() {
size(100, 100);
background(0);
connectTwitter();
getTimeline();
getSearchTweets();
}
void draw() {
background(0);
}
// Initial connection
void connectTwitter() {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setOAuthConsumerKey("xxx");
cb.setOAuthConsumerSecret("xxx");
cb.setOAuthAccessToken("xxx");
cb.setOAuthAccessTokenSecret("xxx");
twitterFactory = new TwitterFactory(cb.build());
twitter = twitterFactory.getInstance();
println("connected");
}
// Get your tweets
void getTimeline() {
try {
statuses = twitter.getHomeTimeline();
}
catch(TwitterException e) {
println("Get timeline: " + e + " Status code: " + e.getStatusCode());
}
for (Status status:statuses) {
println(status.getUser().getName() + ": " + status.getText());
}
}
// Search for tweets
void getSearchTweets() {
try {
Query query = new Query("love");
QueryResult result = twitter.search(query);
for (Status status : result.getTweets()) {
println("#" + status.getUser().getScreenName() + ":" + status.getText());
}
}
catch (TwitterException e) {
println("Search tweets: " + e);
}
}

"Authorization is required to perform that action" in Google Scripts with no way to give authorization

I am trying to create a sort of middleware so some legacy software I am working on can consume Twitter feeds.
Since Twitter has made API 1.0 obsolete and 1.1 requires OAuth and because for this project I only have client-side scripting available to me, I opted to use a Google script to perform the OAuth negotiation:
Source: http://www.labnol.org/internet/twitter-rss-feeds/27931/
function start() {
// Get your Twitter keys from dev.twitter.com
var CONSUMER_KEY = "-----";
var CONSUMER_SECRET = "----";
// Ignore everything after this line
initialize(CONSUMER_KEY, CONSUMER_SECRET);
}
function initialize(key, secret) {
ScriptProperties.setProperty("TWITTER_CONSUMER_KEY", key);
ScriptProperties.setProperty("TWITTER_CONSUMER_SECRET", secret);
var url = ScriptApp.getService().getUrl();
if (url) {
connectTwitter();
var msg = "";
msg += "Sample RSS Feeds for Twitter\n";
msg += "============================";
msg += "\n\nTwitter Timeline of user #labnol";
msg += "\n" + url + "?action=timeline&q=labnol";
msg += "\n\nTwitter Favorites of user #labnol";
msg += "\n" + url + "?action=favorites&q=labnol";
msg += "\n\nTwitter List labnol/friends-in-india";
msg += "\n" + url + "?action=list&q=labnol/friends-in-india";
msg += "\n\nTwitter Search for New York";
msg += "\n" + url + "?action=search&q=new+york";
msg += "\n\nYou should replace the value of 'q' parameter in the URLs as per requirement.";
msg += "\n\nFor help, please refer to http://www.labnol.org/?p=27931";
MailApp.sendEmail(Session.getActiveUser().getEmail(), "Twitter RSS Feeds", msg);
}
}
function doGet(e) {
var a = e.parameter.action;
var q = e.parameter.q;
var feed;
switch (a) {
case "timeline":
feed = "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=" + q;
break;
case "search":
feed = "https://api.twitter.com/1.1/search/tweets.json?q=" + encodeString(q);
break;
case "favorites":
feed = "https://api.twitter.com/1.1/favorites/list.json?screen_name=" + q;
break;
case "list":
var i = q.split("/");
feed = "https://api.twitter.com/1.1/lists/statuses.json?slug=" + i[1] + "&owner_screen_name=" + i[0];
break;
default:
feed = "https://api.twitter.com/1.1/statuses/user_timeline.json";
break;
}
var id = Utilities.base64Encode(feed);
var cache = CacheService.getPublicCache();
var rss = cache.get(id);
if ((!rss) || (rss == "undefined")) {
rss = JSONtoRSS(feed, a, q);
cache.put(id, rss, 3600);
}
return ContentService.createTextOutput(rss)
.setMimeType(ContentService.MimeType.RSS);
}
function JSONtoRSS(json, type, key) {
oAuth();
var options = {
"method": "get",
"oAuthServiceName": "twitter",
"oAuthUseToken": "always"
};
try {
var result = UrlFetchApp.fetch(json, options);
if (result.getResponseCode() === 200) {
var tweets = Utilities.jsonParse(result.getContentText());
if (type == "search")
tweets = tweets.statuses;
if (tweets) {
var len = tweets.length;
var rss = "";
if (len) {
rss = '<?xml version="1.0"?><rss version="2.0">';
rss += ' <channel><title>Twitter ' + type + ': ' + key + '</title>';
rss += ' <link>' + htmlentities(json) + '</link>';
rss += ' <pubDate>' + new Date() + '</pubDate>';
for (var i = 0; i < len; i++) {
var sender = tweets[i].user.screen_name;
var tweet = htmlentities(tweets[i].text);
rss += "<item><title>" + sender + ": " + tweet + "</title>";
rss += " <author>" + tweets[i].user.name + " (#" + sender + ")</author>";
rss += " <pubDate>" + tweets[i].created_at + "</pubDate>";
rss += " <guid isPermaLink='false'>" + tweets[i].id_str + "</guid>";
rss += " <link>https://twitter.com/" + sender + "/statuses/" + tweets[i].id_str + "</link>";
rss += " <description>" + tweet + "</description>";
rss += "</item>";
}
rss += "</channel></rss>";
return rss;
}
}
}
} catch (e) {
Logger.log(e.toString());
}
}
function connectTwitter() {
oAuth();
var search = "https://api.twitter.com/1.1/application/rate_limit_status.json";
var options = {
"method": "get",
"oAuthServiceName": "twitter",
"oAuthUseToken": "always"
};
try {
var result = UrlFetchApp.fetch(search, options);
} catch (e) {
Logger.log(e.toString());
}
}
function encodeString(q) {
var str = encodeURIComponent(q);
str = str.replace(/!/g, '%21');
str = str.replace(/\*/g, '%2A');
str = str.replace(/\(/g, '%28');
str = str.replace(/\)/g, '%29');
str = str.replace(/'/g, '%27');
return str;
}
function htmlentities(str) {
str = str.replace(/&/g, "&");
str = str.replace(/>/g, ">");
str = str.replace(/</g, "<");
str = str.replace(/"/g, """);
str = str.replace(/'/g, "'");
return str;
}
function oAuth() {
var oauthConfig = UrlFetchApp.addOAuthService("twitter");
oauthConfig.setAccessTokenUrl("https://api.twitter.com/oauth/access_token");
oauthConfig.setRequestTokenUrl("https://api.twitter.com/oauth/request_token");
oauthConfig.setAuthorizationUrl("https://api.twitter.com/oauth/authorize");
oauthConfig.setConsumerKey(ScriptProperties.getProperty("TWITTER_CONSUMER_KEY"));
oauthConfig.setConsumerSecret(ScriptProperties.getProperty("TWITTER_CONSUMER_SECRET"));
}
I have followed all of the instructions prescribed in the guide including running 'start' twice... and all that does is send my email account an email with the various URLs. When I try to access the URLs provided in the email (and the plan is to drop that URL into our legacy javascript that currently points to the Twitter 1.0 API), i get the error "Authorization is required to perform that action"
I have confirmed countless times that it is set up to "Execute the app as [me]" and "Anyone, even anonymous can access app"
I am not sure what I am missing or what got screwed up.
Turns out, I forgot to set up the callback URL within the Twitter app setup as specified in the source instructions. Oops!
This would explain why it wasn't working even though everything on the Google side was correct.

MissingMethodException on domain class save in Grails 1.3.7

I'm having a problem calling the save method on a domain object. The error is:
groovy.lang.MissingMethodException: No signature of method: static my.awesome.Class.FeedHit.save() is applicable for argument types: () values: []
Possible solutions: save(), save(java.lang.Boolean), save(java.util.Map), wait(), any(), wait(long)
I'm going through an array of FeedHits, updating a flag, and then calling the save method:
void updateFeedHits(Set<FeedHit> list, FeedHitStatus status) {
for (FeedHit feedHit: list) {
feedHit.status = status
try {
feedHit.save()
} catch (Exception ex) {
log.info("unknown exception during update FeedHit", ex)
}
}
}
I've seen other StackOVerflow users have the same problem, but only during tests. This code is in normal release code.
Any help would be appreciated.
EDIT:
Here is the FeedHit object, slightly edited.
class FeedHit {
Feed feed
String title
String body
String url
FeedHitStatus status
String sourceId
String hash
Date publishedDate
Date dateCreated = new Date()
Integer pos = -1
static constraints = {
alert(nullable: true)
title(nullable: true)
body(nullable: true)
url(nullable: true)
status(nullable: true)
sourceId(nullable: true)
hash(nullable: true)
pos(nullable: true)
publishedDate(nullable: true)
dateCreated(nullable: true)
}
static mapping = {
table('alert_hit')
autoTimestamp false
version(false)
alert(column: 'alert_id')
body(sqlType: 'text')
url(sqlType: 'text')
sourceId(column: 'sourceId')
publishedDate(column: 'publishedDate')
dateCreated(column: 'dateCreated')
}
/**
* Generates a hash from title, body and url.
*/
public AlertHit generateHash() {
StringBuffer sb = new StringBuffer();
if (this.title != null) {
sb.append(this.title);
}
if (this.body != null) {
sb.append(this.body);
}
if (this.url != null) {
sb.append(this.url);
}
if (this.publishedDate != null) {
sb.append(this.publishedDate.getTime());
}
if (sb.length() > 0) {
hash = Md5Hash.hash(sb.toString());
}
this
}
#Override
public String toString() {
return "AlertHit{" +
"id=" + id +
", alert=" + alert +
", title='" + title + '\'' +
", body='" + body + '\'' +
", url='" + url + '\'' +
", status=" + status +
", sourceId='" + sourceId + '\'' +
", hash='" + hash + '\'' +
", publishedDate=" + publishedDate +
", dateCreated=" + dateCreated +
", pos=" + pos +
", version=" + version +
'}';
}
}
You need to annotate GORM functions, if you want to use domain class outside grails. See http://www.rimerosolutions.com/using-gorm-standalone-outside-grails/
I would recommend you to use another way than native threads. Try: Quartz-Plugin

Parse IMAP message and extract header information

I am trying to extract header and body information from email, the following code retrieves the header and body in their raw form. I have an email object that contains the fields from, subject, date, and body. I would like to extract these values from the email and assign them to the email object. How do I get around it? I have tried several ways like getting the header info and using a streamReader.ReadLine() to get a line but I got illegal path exceptions. I know I can use a library but I need to achieve it this way.
What I mean is this, IMAP command returns header information. And I want to extract subject value, date value, sender e-amil, etc. and assign them to my email objects corresponding values like
emailObject.subject = "subjectValue"
public class Imap
{
static void Main(string[] args)
{
try
{
path = Environment.CurrentDirectory + "\\emailresponse.txt";
if (System.IO.File.Exists(path))
System.IO.File.Delete(path);
sw = new System.IO.StreamWriter(System.IO.File.Create(path));
tcpc = new System.Net.Sockets.TcpClient("imap.gmail.com", 993);
ssl = new System.Net.Security.SslStream(tcpc.GetStream());
ssl.AuthenticateAsClient("imap.gmail.com");
receiveResponse("");
Console.WriteLine("username : ");
username = Console.ReadLine();
Console.WriteLine("password : ");
password = Console.ReadLine();
receiveResponse("$ LOGIN " + username + " " + password + " \r\n");
Console.Clear();
receiveResponse("$ LIST " + "\"\"" + " \"*\"" + "\r\n");
receiveResponse("$ SELECT INBOX\r\n");
receiveResponse("$ STATUS INBOX (MESSAGES)\r\n");
Console.WriteLine("enter the email number to fetch :");
int number = int.Parse(Console.ReadLine());
Console.WriteLine("*************Header************");
Console.WriteLine("");
// receiveResponse("$ FETCH " + number + " body[header]\r\n");
// BODY.PEEK[HEADER.FIELDS (SUBJECT)]
// StringBuilder sb = receiveResponse("$ FETCH " + number + " BODY.PEEK[HEADER.FIELDS (From Subject Date)]\r\n");
StringBuilder sb= receiveResponse("$ FETCH " + number + " body.peek[header]\r\n");
Console.WriteLine(sb);
Console.WriteLine("");
Console.WriteLine("Body");
sb = new StringBuilder();
sb=receiveResponse("$ FETCH " + number + " body[text]\r\n");
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
byte[] serverbuff = new Byte[1024];
int count = 0;
string retval = enc.GetString(serverbuff, 0, count);
Console.WriteLine(sb.ToString());
receiveResponse("$ LOGOUT\r\n");
}
catch (Exception ex)
{
Console.WriteLine("error: " + ex.Message);
}
finally
{
if (sw != null)
{
sw.Close();
sw.Dispose();
}
if (ssl != null)
{
ssl.Close();
ssl.Dispose();
}
if (tcpc != null)
{
tcpc.Close();
}
}
Console.ReadKey();
}
static StringBuilder receiveResponse(string command)
{
sb = new StringBuilder();
try
{
if (command != "")
{
if (tcpc.Connected)
{
dummy = Encoding.ASCII.GetBytes(command);
ssl.Write(dummy, 0, dummy.Length);
}
else
{
throw new ApplicationException("TCP CONNECTION DISCONNECTED");
}
}
ssl.Flush();
buffer = new byte[2048];
bytes = ssl.Read(buffer, 0, 2048);
sb.Append(Encoding.ASCII.GetString(buffer));
// Console.WriteLine(sb.ToString());
sw.WriteLine(sb.ToString());
// sb = new StringBuilder();
return sb;
}
catch (Exception ex)
{
throw new ApplicationException(ex.Message);
}
}
You said you do not want to use an IMAP library. This means that you will have to implement your own. You should start by reading RFC 3501 because there is no chance you could get the protocol right without reading the docs carefuly. In particular, you're issuing a STATUS command on the currently selected mailbox, which is explicitly forbidden by the protocol specification. The rest of the code supports the assumption that you have not read the RFC yet.

Issues with Crypto.generateMac() in SalesForce APEX

We need to make a few callouts to a service that is using OAuth 1.0 and requires each request to be signed with HMAC-SHA1.
The service doesn't have any APEX client API. Thus, we have to do it manually.
Unfortunately,
EncodingUtil.base64Encode(Crypto.generateMac('hmacSHA1', Blob.valueOf(data), Blob.valueOf(key)));
returns a different string from what we expect. We have compared the output for the same input with libraries for other languages. And the output was different.
I have no problems calling out to OAuth 1.0. Here's some sample Apex for signing your request:
EDIT: Added additional code
private Map<String,String> getUrlParams(String value)
{
Map<String,String> res = new Map<String,String>();
if(value==null || value=='')
{
return res;
}
for(String s : value.split('&'))
{
List<String> kv = s.split('=');
if(kv.size()>1)
{
res.put(kv[0],kv[1]);
}
}
return res;
}
private String createBaseString(Map<String,String> oauthParams, HttpRequest req)
{
Map<String,String> p = oauthParams.clone();
if(req.getMethod().equalsIgnoreCase('post') && req.getBody()!=null && req.getHeader('Content-Type')=='application/x-www-form-urlencoded')
p.putAll(getUrlParams(req.getBody()));
String host = req.getEndpoint();
Integer n = host.indexOf('?');
if(n > -1)
{
p.putAll(getUrlParams(host.substring(n+1)));
host = host.substring(0,n);
}
List<String> keys = new List<String>();
keys.addAll(p.keySet());
keys.sort();
String s = keys.get(0)+'='+p.get(keys.get(0));
for(Integer i=1; i<keys.size(); i++)
s = s + '&' + keys.get(i) + '=' + p.get(keys.get(i));
return req.getMethod().toUpperCase() + '&' + EncodingUtil.urlEncode(host, 'UTF-8') + '&' + EncodingUtil.urlEncode(s, 'UTF-8');
}
public void sign(HttpRequest req)
{
nonce = String.valueOf(Crypto.getRandomLong());
timestamp = String.valueOf(DateTime.now().getTime() / 1000);
refreshParameters();
String s = createBaseString(parameters, req);
Blob sig = Crypto.generateMac('HmacSHA1', Blob.valueOf(s),
Blob.valueOf(consumerSecret+'&'+ (tokenSecret!=null ? tokenSecret : '')));
signature = EncodingUtil.urlEncode(EncodingUtil.base64encode(sig), 'UTF-8');
String header = 'OAuth ';
for (String key : parameters.keySet())
{
header = header + key + '="'+parameters.get(key)+'", ';
}
header = header + 'oauth_signature="'+signature+'"';
req.setHeader('Authorization',header);
}
This might be reaching, but could there be a case-sensitivity issue? Notice I'm calling 'HmacSHA1' not 'hmacSHA1'

Resources