Showing posts with label twitter. Show all posts
Showing posts with label twitter. Show all posts

Monday, July 30, 2018

215 error while requesting Token from Twitter oAuth API

Leave a Comment

I'm trying to Implement Twitter login in my NodeJS app.

As per the documentation from Twitter, I need to pass the below parameters to this url via POST request. URL:

https://api.twitter.com/oauth/request_token

PARAMETERS:

 oauth_nonce=,   oauth_signature=,   oauth_callback="http%3A%2F%2Fmyapp.com%3A3005%2Ftwitter%2Fprocess_callback",   oauth_signature_method="HMAC-SHA1",         oauth_timestamp="currentTimestamp",   oauth_consumer_key=“myKEY”,   oauth_version="1.0" 

I'm passing a random string for oauth_nonce parameter. I'm not clear on how to create a oauth_signature?

I keep getting 215 error whenever I make the POST request beacuse of incorrect oauth_nonce and oauth_signature values I guess.

How do I generate oauth_nonce and oauth_signature values while making the request in NodeJS.

3 Answers

Answers 1

Those parameters need to be passed in your authorization header:

OAuth oauth_nonce="K7ny27JTpKVsTgdyLdDfmQQWVLERj2zAK5BslRsqyw",  oauth_callback="http%3A%2F%2Fmyapp.com%3A3005%2Ftwitter%2Fprocess_callback",  oauth_signature_method="HMAC-SHA1",  oauth_timestamp="1300228849",  oauth_consumer_key="OqEqJeafRSF11jBMStrZz",  oauth_signature="Pc%2BMLdv028fxCErFyi8KXFM%2BddU%3D",  oauth_version="1.0" 

But before that, you need to get a signature, which will then give you all of the parameters above. Check the documentation here.

A recommendation would be to use a 3rd party library like passport, which heavily simplifies this process if needed.

Answers 2

Twitter makes a whole lot of sense if used correctly. I have seen some tutorials that has been quite useful to those around me, that I feel maybe you might want to check Node Authentication: Twitter and Implementing Sign in with Twitter for Node.js

If you're using reactjs, this (npm i react-twitter-auth) might be useful to you too

Answers 3

can't comment, that's why answering here. the docu sais, oauth_nonce:

is a unique token your application should generate for each unique request

it is like the salt of the encryption. you can find oauth_signature under the same link. how to generate it is described here.

Read More

Thursday, April 26, 2018

Styling a Twitter feed - CSS won't target .timeline-Tweet-text

Leave a Comment

I'm bringing a Twitter feed through to my site using the following code which is described on https://publish.twitter.com/

<a class="twitter-timeline" href="https://twitter.com/ACCOUNT-HERE" data-tweet-limit="3">Tweets by</a>  <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script> 

The feed is displayed correctly. However it uses CSS which is provided via Twitter.

When I inspect it using Chrome dev tools I can see the following classes around the Tweets:

<p class="timeline-Tweet-text" lang="en" dir="ltr"> 

So I thought it would be a simple case of targetting this in CSS, e.g.

.timeline-Tweet-text { } 

However, this doesn't apply any styles to the Tweets. Why not?

I have also referred to Twitters guidance on this here https://dev.twitter.com/web/overview/css but that also doesn't work.

The only reason I want to do this is so the font used within the widget matches the font used by the rest of the body text on my website.

3 Answers

Answers 1

Simply adding a style rule to your top-level page won't work, because they are two different and isolated documents as far as the browser is concerned.

However, with the use of kevinburke's Customize Twitter 1.1 project, you should be able to embed CSS into a timeline. It does this by injecting a link to an external CSS file directly into the contents of the document within that frame.

In Kevin's published example, It makes all the text white, which looks a bit broken, but when I took this example and adjusted it to also turn the background red, we can see it's working as intended and you can therefore make any adjustments you like, provided you have a CSS file for it.

Screenshot of twitter feed with red background

Note that this is only possible because Twitter have configured platform.twitter.com so that it can be embedded in frames. For security reasons, many websites will nowadays send a HTTP response header to prevent framing of the content, to avoid people meddling with their contents.

Answers 2

Unfortunately (Unless it has been changed recently) you can't manipulate CSS inside of an iframe

https://jsfiddle.net/tm94g9n4/5/

.timeline-Tweet-text {color: red;}

I added the color red to the text but as you can see when you inspect it doesn't even appear as overwritten. It's not referenced at all.

I think you'll need to look in to custom libraries for this. I can't recommend any as I've not done this before.

https://stackoverflow.com/a/6495816/1379450

Hope it helps

EDIT

It seems it is possible (Duplicate question) How to apply CSS to iframe?

Answers 3

From https://dev.twitter.com/docs/embedded-timelines

Customization Options

Embedded timelines are available in light and dark themes for customization. The light theme is for pages that use a white or light colored background and follows the twitter.com aesthetic, while the dark theme is for pages that use a black or dark color background and looks more like Tweetdeck.

As with your twitter.com profile, you may choose a custom link color for your embedded timelines so that the content matches the links of your website and feels integrated into the color palette of your site.

For sites where the theme and link color do not provide enough customization to make the Tweets feel like they’re a part of the page, we offer a set of additional client side customization features. These settings allow you to control the background color, borders, header, and footer of the timeline, and are detailed in the “Client Side Options” section below

You Can Use CSS * Property for Setting the Fonts for all the Pages...

Example:(this might be useful for you)

#twitterFeed * { font-family: "Lato" !important; } 

Reference Link for Twitter Widget Style :

https://dev.twitter.com/web/overview/css

https://www.solodev.com/blog/web-design/styling-your-websites-twitter-feed.stml

Read More

Thursday, March 22, 2018

Deprecation Errors with Kafka Consumer for twitter streaming

Leave a Comment

I have been working on Kafka twitter streaming feed data.

I am following the sample from below link: http://www.hahaskills.com/tutorials/kafka/Twitter_doc.html

I am able to use Producer code and it is working fine. Able to get twitter feed and send to Kafka Producer.

I am not able to use Consumer code, since it has been throwing as deprecated error for many APIs.

Here is the Consumer code:

import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties;  import kafka.consumer.Consumer; //import kafka.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.ConsumerConfig; import kafka.consumer.ConsumerIterator; //import kafka.consumer.KafkaStream; //import kafka.consumer.KafkaStream; import kafka.javaapi.consumer.ConsumerConnector;   //import org.apache.kafka.clients.producer.KafkaProducer;  public class KafkaConsumer {     private final ConsumerConnector consumer;     private final String topic;      public KafkaConsumer(String zookeeper, String groupId, String topic) {         Properties props = new Properties();         props.put("zookeeper.connect", zookeeper);         props.put("group.id", groupId);         props.put("zookeeper.session.timeout.ms", "500");         props.put("zookeeper.sync.time.ms", "250");         props.put("auto.commit.interval.ms", "1000");          consumer = Consumer.createJavaConsumerConnector(new ConsumerConfig(props));          this.topic = topic;     }      public void testConsumer() {       System.out.println("Test Con called");          Map<String, Integer> topicCount = new HashMap<>();          topicCount.put(topic, 1);          Map<String, List<KafkaStream<byte[], byte[]>>> consumerStreams = consumer.createMessageStreams(topicCount);          List<KafkaStream<byte[], byte[]>> streams = consumerStreams.get(topic);          System.out.println("For");          for (final KafkaStream stream : streams) {              ConsumerIterator<byte[], byte[]> it = stream.iterator();              System.out.println("Size"+it.length());              while (it.hasNext()) {                 System.out.println("Stream");                 System.out.println("Message from Single Topic: " + new String(it.next().message()));             }         }          if (consumer != null) {             consumer.shutdown();         }     }      public static void main(String[] args) {       System.out.println("Started");      String topic="twittertopic";      KafkaConsumer simpleTWConsumer = new KafkaConsumer("localhost:XXXX", "testgroup", topic);      simpleTWConsumer.testConsumer();      System.out.println("End");     }     } 

It throws error : ConsumerConnector, ConsumerIterator, KafkaStream are deprecated.

ConsumerConfig is not visible.

Is there fixed version of this sample code (Kafka consumer for twitter)?

1 Answers

Answers 1

The tutorial you are following is very old and it's using the old Scala Kafka clients that have been deprecated, see http://kafka.apache.org/documentation/#legacyapis

The classes that have been deprecated are:

  • kafka.consumer.* and kafka.javaapi.consumer instead use the newer Java Consumer under org.apache.kafka.clients.consumer.*

  • kafka.producer.* and kafka.javaapi.producer instead use the newer Java Producer under org.apache.kafka.clients.producer.*

Apart from using deprecated classes, your code was mostly correct, I only had to fix a few imports. See below a fixed version. Using it I was able to consume messages I was producing to a topic called twittertopic.

package example;  import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties;  import kafka.consumer.Consumer; import kafka.consumer.ConsumerConfig; import kafka.consumer.ConsumerIterator; import kafka.consumer.KafkaStream; import kafka.javaapi.consumer.ConsumerConnector;  public class MyConsumer {     private final ConsumerConnector consumer;     private final String topic;      public MyConsumer(String zookeeper, String groupId, String topic) {         Properties props = new Properties();         props.put("zookeeper.connect", zookeeper);         props.put("group.id", groupId);         props.put("zookeeper.session.timeout.ms", "500");         props.put("zookeeper.sync.time.ms", "250");         props.put("auto.commit.interval.ms", "1000");         consumer = Consumer.createJavaConsumerConnector(new ConsumerConfig(props));         this.topic = topic;     }      public void testConsumer() {          Map<String, Integer> topicCount = new HashMap<>();         topicCount.put(topic, 1);          Map<String, List<KafkaStream<byte[], byte[]>>> consumerStreams = consumer.createMessageStreams(topicCount);         List<KafkaStream<byte[], byte[]>> streams = consumerStreams.get(topic);          for (final KafkaStream stream : streams) {             ConsumerIterator<byte[], byte[]> it = stream.iterator();             while (it.hasNext()) {                 System.out.println("Message from Single Topic: " + new String(it.next().message()));             }         }          if (consumer != null) {             consumer.shutdown();         }     }      public static void main(String[] args) {         System.out.println("Started");         String topic = "twittertopic";         MyConsumer simpleTWConsumer = new MyConsumer("localhost:2181", "testgroup", topic);         simpleTWConsumer.testConsumer();         System.out.println("End");     } } 

While the code above can be used, the next major Kafka release is likely to remove classes that are currently deprecated, so you should not write new logic using these.

Instead you should get started with the Java clients, you can use the examples provided on Github: https://github.com/apache/kafka/tree/trunk/examples/src/main/java/kafka/examples

Using the new Java Consumer, your logic would look like:

import java.util.Arrays; import java.util.Properties;  import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; import org.apache.kafka.clients.consumer.KafkaConsumer;  public class MyConsumer {      static final String TOPIC = "twittertopic";     static final String GROUP = "testgroup";      public static void main(String[] args) {         System.out.println("Started");          Properties props = new Properties();         props.put("bootstrap.servers", "localhost:9092");         props.put("group.id", GROUP);         props.put("auto.commit.interval.ms", "1000");         props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");         props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");          try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);) {             consumer.subscribe(Arrays.asList(TOPIC));              for (int i = 0; i < 1000; i++) {                 ConsumerRecords<String, String> records = consumer.poll(1000L);                 System.out.println("Size: " + records.count());                 for (ConsumerRecord<String, String> record : records) {                     System.out.println("Received a message: " + record.key() + " " + record.value());                 }             }         }         System.out.println("End");     }  } 
Read More

Wednesday, March 14, 2018

Deprecation Errors with Kafka Consumer for twitter streaming

Leave a Comment

I have been working on Kafka twitter streaming feed data.

I am following the sample from below link: http://www.hahaskills.com/tutorials/kafka/Twitter_doc.html

I am able to use Producer code and it is working fine. Able to get twitter feed and send to Kafka Producer.

I am not able to use Consumer code, since it has been throwing as deprecated error for many APIs.

Here is the Consumer code:

import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties;  import kafka.consumer.Consumer; //import kafka.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.ConsumerConfig; import kafka.consumer.ConsumerIterator; //import kafka.consumer.KafkaStream; //import kafka.consumer.KafkaStream; import kafka.javaapi.consumer.ConsumerConnector;   //import org.apache.kafka.clients.producer.KafkaProducer;  public class KafkaConsumer {     private final ConsumerConnector consumer;     private final String topic;      public KafkaConsumer(String zookeeper, String groupId, String topic) {         Properties props = new Properties();         props.put("zookeeper.connect", zookeeper);         props.put("group.id", groupId);         props.put("zookeeper.session.timeout.ms", "500");         props.put("zookeeper.sync.time.ms", "250");         props.put("auto.commit.interval.ms", "1000");          consumer = Consumer.createJavaConsumerConnector(new ConsumerConfig(props));          this.topic = topic;     }      public void testConsumer() {       System.out.println("Test Con called");          Map<String, Integer> topicCount = new HashMap<>();          topicCount.put(topic, 1);          Map<String, List<KafkaStream<byte[], byte[]>>> consumerStreams = consumer.createMessageStreams(topicCount);          List<KafkaStream<byte[], byte[]>> streams = consumerStreams.get(topic);          System.out.println("For");          for (final KafkaStream stream : streams) {              ConsumerIterator<byte[], byte[]> it = stream.iterator();              System.out.println("Size"+it.length());              while (it.hasNext()) {                 System.out.println("Stream");                 System.out.println("Message from Single Topic: " + new String(it.next().message()));             }         }          if (consumer != null) {             consumer.shutdown();         }     }      public static void main(String[] args) {       System.out.println("Started");      String topic="twittertopic";      KafkaConsumer simpleTWConsumer = new KafkaConsumer("localhost:XXXX", "testgroup", topic);      simpleTWConsumer.testConsumer();      System.out.println("End");     }     } 

It throws error : ConsumerConnector, ConsumerIterator, KafkaStream are deprecated.

ConsumerConfig is not visible.

Is there fixed version of this sample code (Kafka consumer for twitter)?

0 Answers

Read More

Thursday, March 8, 2018

Kafka Twitter streaming TwitterException error

Leave a Comment

I am trying the sample code on Kafka Twitter streaming from the following tutorial.

https://www.tutorialspoint.com/apache_kafka/apache_kafka_real_time_application.htm

Here is my code:

import java.util.Arrays; import java.util.Properties; import java.util.concurrent.LinkedBlockingQueue;  import twitter4j.*; import twitter4j.conf.*; import twitter4j.StatusListener;  import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.KafkaProducer; import org.apache.kafka.clients.producer.ProducerRecord;  public class KafkaTwitterProducer {    public static void main(String[] args) throws Exception {       LinkedBlockingQueue<Status> queue = new LinkedBlockingQueue<Status>(1000);         String consumerKey = “XXXXXXXXXXXXXXXXX”; //args[0].toString();       String consumerSecret = "XXXXXXXXXXXXXXXXX"; //args[1].toString();       String accessToken = "XXXXXXXXXXXXXXXXX" ; //args[2].toString();       String accessTokenSecret = "XXXXXXXXXXXXXXXXX" ; //args[3].toString();       String topicName = "twittertest" ; //args[4].toString();       //String[] arguments = args.clone();       String[] keyWords = {“Hello”,”Hi”,”Welcome”}; //Arrays.copyOfRange(arguments, 5, arguments.length);        ConfigurationBuilder cb = new ConfigurationBuilder();       cb.setDebugEnabled(true)          .setOAuthConsumerKey(consumerKey)          .setOAuthConsumerSecret(consumerSecret)          .setOAuthAccessToken(accessToken)          .setOAuthAccessTokenSecret(accessTokenSecret);        TwitterStream twitterStream = new TwitterStreamFactory(cb.build()).getInstance();        StatusListener listener = new StatusListener() {           @Override          public void onStatus(Status status) {                   queue.offer(status);               System.out.println("@" + status.getUser().getScreenName()                       + " - " + status.getText());             // System.out.println("@" + status.getUser().getScreen-Name());              /*for(URLEntity urle : status.getURLEntities()) {                System.out.println(urle.getDisplayURL());             }*/              /*for(HashtagEntity hashtage : status.getHashtagEntities()) {                System.out.println(hashtage.getText());             }*/          }           @Override          public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {             System.out.println("Got a status deletion notice id:"                 + statusDeletionNotice.getStatusId());          }           @Override          public void onTrackLimitationNotice(int numberOfLimitedStatuses) {              System.out.println("Got track limitation notice:" +                       numberOfLimitedStatuses);          }           @Override          public void onScrubGeo(long userId, long upToStatusId) {              System.out.println("Got scrub_geo event userId:" + userId +                       "upToStatusId:" + upToStatusId);          }                 @Override          public void onStallWarning(StallWarning warning) {             // System.out.println("Got stall warning:" + warning);          }           @Override          public void onException(Exception ex) {             ex.printStackTrace();          }       };       twitterStream.addListener(listener);        FilterQuery query = new FilterQuery().track(keyWords);       twitterStream.filter(query);        Thread.sleep(5000);        //Add Kafka producer config settings       Properties props = new Properties();       props.put("bootstrap.servers", "localhost:9092");        props.put("client.id", "SampleProducer");       props.put("auto.commit.interval.ms", "1000");       props.put("session.timeout.ms", "30000");            props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");       props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");        //props.put("key.serializer",          // "org.apache.kafka.common.serialization.StringSerializer");       //props.put("value.serializer",          // "org.apache.kafka.common.serialization.StringSerializer");        Producer<String, String> producer = new KafkaProducer<String, String>(props);       int i = 0;       int j = 0;        while(i < 10) {          Status ret = queue.poll();           if (ret == null) {             Thread.sleep(100);             i++;          }else {             for(HashtagEntity hashtage : ret.getHashtagEntities()) {                System.out.println("Hashtag: " + hashtage.getText());                producer.send(new ProducerRecord<String, String>(                   topicName, Integer.toString(j++), hashtage.getText()));             }          }       }       producer.close();       Thread.sleep(5000);       twitterStream.shutdown();    } } 

When I run this as Java application, I am getting the following error: (this is not compile/build error)

Read timed out Relevant discussions can be found on the Internet at:     http://www.google.co.jp/search?q=1169356e or     http://www.google.co.jp/search?q=c04b39f0 TwitterException{exceptionCode=[1169356e-c04b39f0 c2863472-491bffd7], statusCode=-1, message=null, code=-1, retryAfter=-1, rateLimitStatus=null, version=4.0.4}     at twitter4j.HttpClientImpl.handleRequest(HttpClientImpl.java:179)     at twitter4j.HttpClientBase.request(HttpClientBase.java:57)     at twitter4j.HttpClientBase.post(HttpClientBase.java:86)     at twitter4j.TwitterStreamImpl.getFilterStream(TwitterStreamImpl.java:346)     at twitter4j.TwitterStreamImpl$8.getStream(TwitterStreamImpl.java:322)     at twitter4j.TwitterStreamImpl$TwitterStreamConsumer.run(TwitterStreamImpl.java:552) Caused by: java.net.SocketTimeoutException: Read timed out     at java.net.SocketInputStream.socketRead0(Native Method)     at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)     at java.net.SocketInputStream.read(SocketInputStream.java:170)     at java.net.SocketInputStream.read(SocketInputStream.java:141)     at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)     at sun.security.ssl.InputRecord.read(InputRecord.java:503)     at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)     at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:930)     at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)     at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)     at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)     at java.io.BufferedInputStream.read(BufferedInputStream.java:345)     at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:704)     at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:647)     at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1536)     at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)     at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)     at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)     at twitter4j.HttpResponseImpl.<init>(HttpResponseImpl.java:35)     at twitter4j.HttpClientImpl.handleRequest(HttpClientImpl.java:143)     ... 5 more 

I am not sure what is the problem here. Could someone suggest me the solution or fix please?

Ok Update here: It is working now if key words are generic like String[] keyWords = {"USA","Basketball","Sports};

If I change this to my requirement with specific keywords like my company name, product name etc., for ex: String[] keyWords = {"XXX","YYY","ZZZ"}; then the java application is getting terminated. What could be the reason? How to fix it in this code? Please advise?

1 Answers

Answers 1

The Twitter4J source code shows that this exception is thrown because of Http connection time out.

I get similar exception by setting a low value for connection timeout.

ConfigurationBuilder cb = new ConfigurationBuilder(); cb.setDebugEnabled(true)  .setOAuthConsumerKey(consumerKey)  .setOAuthConsumerSecret(consumerSecret)  .setOAuthAccessToken(accessToken)  .setOAuthAccessTokenSecret(accessTokenSecret)  .setHttpStreamingReadTimeout(10); 

This is the stack trace I get.

TwitterException{exceptionCode=[1169356e-c3c3770e 1169356e-c3c376e4], statusCode=-1, message=null, code=-1, retryAfter=-1, rateLimitStatus=null, version=4.0.6} at twitter4j.HttpClientImpl.handleRequest(HttpClientImpl.java:179) at twitter4j.HttpClientBase.request(HttpClientBase.java:57) at twitter4j.HttpClientBase.post(HttpClientBase.java:86) at twitter4j.TwitterStreamImpl.getFilterStream(TwitterStreamImpl.java:347) at twitter4j.TwitterStreamImpl$8.getStream(TwitterStreamImpl.java:323) at twitter4j.TwitterStreamImpl$TwitterStreamConsumer.run(TwitterStreamImpl.java:554)                                                                            Caused by: java.net.SocketTimeoutException: Read timed out     at java.net.SocketInputStream.socketRead0(Native Method)     at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)     at java.net.SocketInputStream.read(SocketInputStream.java:171)     at java.net.SocketInputStream.read(SocketInputStream.java:141)     at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)     at sun.security.ssl.InputRecord.read(InputRecord.java:503)     at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983)     at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)     at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)     at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)     at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)     at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)     at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1316)     at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1291)     at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)     at twitter4j.HttpClientImpl.handleRequest(HttpClientImpl.java:137)     ... 5 more 

For your example, please try setting a higher value for HttpStreamingReadTimeout. The default value in the code is 40 seconds. Try setting it to 120,000 (milliseconds) or higher. That should work.

Read More

Wednesday, March 7, 2018

Twitter Video Embed auto play

Leave a Comment

I have looked through certain resources on the stack over flows but some doesn't have answer nor they are inactive.

I will want to autoplay a twitter video when some arrives on my website.

Currently It looks like this: enter image description here

I was able to do Youtube, so believe this should be possible also?

1 Answers

Answers 1

The solution is a bit hacky, but here it is.

The twitter widget script seems to inject the player after clicking the image into an iframe, but the link to click is... embedded in an iframe. So when you see on your screen the "player" to click, it is in fact not the player but just a link to activate the injection of the player.

So your goal is to activate this injection by the following steps:

  1. set up a target listener for the widget factory

  2. get the widget element, once it's added to the DOM (but after it has been altered by the widget factory)

  3. get it's iframe document's link that triggers the embedding of the player

Set up Twitter for websites

Prepare your page according to the following documentation:

<div id="videoTarget"></div>  <!--<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>--> <script>     window.twttr = (function(d, s, id) {         var js, fjs = d.getElementsByTagName(s)[0],             t = window.twttr || {};         if (d.getElementById(id)) return t;         js = d.createElement(s);         js.id = id;         js.src = "https://platform.twitter.com/widgets.js";         fjs.parentNode.insertBefore(js, fjs);          t._e = [];         t.ready = function(f) {             t._e.push(f);         };          return t;     }(document, "script", "twitter-wjs"));  </script> 

Our factory target will be the videoTarget. This is the place, where the iframe with the video injection link will be placed.

Create the embed link

First wait for the twttr to be ready. Read more in this in the scripting events.

Then use the factory function to create your video.

Once it's loaded, you can use jQuery to find the iframe content's link, that triggers the injection.

Code:

window.twttr.ready(function(_twttr) {     _twttr.widgets.createVideo(             '560070183650213889',             $('#videoTarget').get(0), {                 lang: "en",             }         )         .then(function(el) {             const dataId = $(el).attr('data-tweet-id');             const doc = $('iframe').get(0).contentWindow.document;             const link = $(doc).find("a[href*=" + dataId + "]")[0];             link.click();         }); }); 

Working solution: https://jsfiddle.net/5qmh1Lpn/121/

Summary

Twitters video embed lacks of proper ways to do autoplay. However, it is IMHO an antifeature and it should be the user's decision, wether to play a video or not.

The solution is only a hack and may not work on all browsers in all situations.

Please create a fork, if you want to extend the fiddle to your needs.

Edit: Just for your interest, I found a hidden link with cookie consent in this code, which basically breaks down to "if you click this you agree to our policies" which is very strange, since nobody can't see this message as it's hidden.

Thanks to:

https://stackoverflow.com/a/2893315/3098783

https://stackoverflow.com/a/303961/3098783

Read More

Thursday, March 1, 2018

Get twitter and google plus share count or any alternate

Leave a Comment

Hi I have tried below code for twitter.

var tw_share_count = 0; TWUrl = "https://cdn.api.twitter.com/1/urls/count.json?url=" + url + '&callback=?' $.ajax({     type: 'GET',     url: TWUrl,     success: function (data) {         tw_share_count = data.count.toString();         alert(tw_share_count);     },     async: false }); 

And below code for google share count

var gl_shares_count = 0;

$.ajax({     type: 'POST',     url: 'https://apis.google.com/js/platform.js',     processData: true,     contentType: 'application/json',     data: JSON.stringify({         'method': 'pos.plusones.get',         'id': url,         'params': {         'nolog': true,         'id': url,         'source': 'widget',         'userId': '@viewer',         'groupId': '@self'     },     'jsonrpc': '2.0',     'key': 'p',     'apiVersion': 'v1'     }),     success: function (response) {           alert(response.result.metadata.globalCounts.count);         //  $('a.googleplus .counter').text(response.result.metadata.globalCounts.count);     } }); 

In had checked in some of the sight and they are saying that both twitter and google + has stopped sharing count. I dont know how much it is true.

I am able to share the link but not able to have count. My Facebook and Pinterest count is coming very well but twitter and google plus count is not coming

Please get me rid of this issue or give me the alternate for this that is easy and free to implement.

For test I am using some random site to get the exact data for twitter/ google+ count like https://draxe.com/emotions-lower-inflammation/

1 Answers

Answers 1

take a look at this, i got a third party js to get social count. May be this will help you

<!doctype html>  <html lang="ja">  <head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">    <meta http-equiv="X-UA-Compatible" content="ie=edge">    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">    <script src="https://webcyou.github.io/social-share-count-js/js/social-share-count.js"></script>    <title>Share Count</title>    <style>  .fa {    padding: 20px;    font-size: 30px;    width: 50px;    text-align: center;    text-decoration: none;    margin: 5px 2px;  }    .fa:hover {      opacity: 0.7;  }    .fa-facebook {    background: #3B5998;    color: white;  }    .fa-twitter {    background: #55ACEE;    color: white;  }    .fa-google {    background: #dd4b39;    color: white;  }    .fa-linkedin {    background: #007bb5;    color: white;  }      .fa-pinterest {    background: #cb2027;    color: white;  }    .fa-yahoo {    background: #430297;    color: white;  }  p{  	font-size:14px;  }  </style>  </head>  <body>  <a href="#" class="fa fa-facebook">  	<p data-sc-fb="http://www.eventbee.com"></p>  </a>    <a href="#" class="fa fa-twitter">  	<p data-sc-tw="https://stackoverflow.com"></p>  </a>    <a href="#" class="fa fa-google">  	<p data-sc-gp="http://www.webcyou.com"></p>  </a>    <a href="#" class="fa fa-pinterest">  	<p data-sc-pr="https://www.google.com/"></p>  </a>    <a href="#" class="fa fa-linkedin">  	<p data-sc-ln="https://www.yahoo.com/"></p>  </a>    </body>  </html>

Read More

Wednesday, January 10, 2018

How can I get a bigger Twitter Video size from the API?

Leave a Comment

When doing a search via the Twitter API, I get URLs to only small videos, for example:

u'video_info': {u'aspect_ratio': [1, 1],                 u'duration_millis': 98615,                 u'variants': [{u'bitrate': 320000,                 u'content_type': u'video/mp4', u'url': u'https://video.twimg.com/ext_tw_video/944064088308510720/pu/vid/240x240/Dbol1j YzSdt5A9Pi.mp4'},                {u'content_type': u'application/x-mpegURL', u'url': u'https://video.twimg.com/ext_tw_video/944064088308510720/pu/pl/6iSBw8vIHgtISD_ 1.m3u8'}]}}]} 

The video is only 240x240

How can I get a bigger version for resizing?

2 Answers

Answers 1

I think you're looking for the Media Size Objects

All Tweets with native media (photos, video, and GIFs) will include a set of ‘thumb’, ‘small’, ‘medium’, and ‘large’ sizes with height and width pixel sizes.

Also look at the overall Media Objects:

The entities section will contain a media array containing a single media object if any media object has been ‘attached’ to the Tweet. If no native media has been attached, there will be no media array in the entities. The has:media Operator will match if this array is populated.

Ideally your code should check which media sizes exist and use whichever suits your site the best, since you can't rely on all of the sizes being there all the time.

Answers 2

Are you able to provide any more information about the specific Tweet ID you're trying to retrieve? maybe it does not have any larger video size available?

Read More

Saturday, October 7, 2017

How to detect pages when a user browses inside twitter in app?

Leave a Comment

I want to be able to detect user when the user browses a web page inside twitter app. By detecting, I want to just add a body class that I will use to change the way the page looks for users inside twitter app. However, all my tries so far failed.

I can detect webview inside Facebook app using the following code

var ua = navigator.userAgent; if ((ua.indexOf("FBAN") > -1) || (ua.indexOf("FBAV") > -1)) {   return 'facebook'; } 

I have looked around/ googled around/ checked other StackOverflow solutions. However, I could not find a solution where I can detect twitter in-app. That is, I want to detect when a user browses a page inside twitter app.

The things I have tried and failed are below

   if (/Twitter for/i.test(nua) === true) {       return 'twitter';    } 

or

if (/\/\/t.co\//i.test(document.referrer) === true && /Safari\//.test(nua) === false) {   return 'twitter'; } 

or checking for the browser, device, vendor, model, device type, engine, os, os version (why was I checking this?!?). I checked using Modernizr; however, no difference was found between as standalone Safari and in-app Twitter. Also, checked using Detect if user is using webview for android/iOS or a regular browser

Also tried the following with failure

   var userAgent = window.navigator.userAgent.toLowerCase(),       safari = /safari/.test( userAgent ),       ios = /iphone|ipod|ipad/.test( userAgent );  var standalone = window.navigator.standalone,   userAgent = window.navigator.userAgent.toLowerCase(),   safari = /safari/.test( userAgent ),   ios = /iphone|ipod|ipad/.test( userAgent );  if( ios ) {   if ( safari ) {     $('.debug').prepend('Yeah I am a browser in ios');   } else if ( !safari ) {     $('.debug').prepend('Yeah I am a webview in ios');   } } else {   $('.debug').prepend('Yeah I am NOT a ios'); }  if( ios ) {   if ( !standalone && safari ) {     $('.debug').prepend('Yeah I am a browser in ios');   } else if ( standalone && !safari ) {     $('.debug').prepend('Yeah I am a standaline in ios');   } else if ( !standalone && !safari ) {     $('.debug').prepend('Yeah I am WEBVIEW');   } } else {   $('.debug').prepend('Yeah I am NOT IOS'); }  var isWebView = !/safari/.test( window.navigator.userAgent.toLowerCase()) || navigator.platform === 'iOS' || navigator.platform === 'iPhone' $('.debug').prepend('<br>isWebView? : ' + isWebView + "<br>"); $('.debug').prepend('<br>AM I WEBVIEW?: ' + /AppName\/[0-9\.]+$/.test(navigator.userAgent));  var is_uiwebview = /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent); var is_safari_or_uiwebview = /(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent); $('.debug').prepend('<br> is_uiwebview :' + is_uiwebview); $('.debug').prepend('<br> is_safari_or_uiwebview :' + is_safari_or_uiwebview);   var uaSafari = navigator.userAgent.match(/Safari/i) var uaSafariInput = navigator.userAgent.match(/Safari/i).input var uaSafariIndex  = navigator.userAgent.match(/Safari/i).index $('.debug').prepend('<br> ' + uaSafari + '<br>' + uaSafariInput + '<br>' + uaSafariIndex + '<br>' + navigator.vendor + '<br>' + navigator.product + '<br>' + navigator.productSub + '<br>' + navigator.languages.length + '<br>' + navigator.doNotTrack + '<br>' + navigator.maxTouchPoints + navigator.maxTouchPoints);  //Check headers and see if any difference there var req = new XMLHttpRequest(); req.open('GET', document.location, false); req.send(null); var headers = req.getAllResponseHeaders().toLowerCase(); $('.debug').prepend('<br> headers \t ' + headers);   if (/Twitter for/i.test(navigator.userAgent) === true) {   $('.debug').prepend('<br> Test1 '); }  $('.debug').prepend('<br> Document referrer is : '+ document.referrer + " <br> ");  if (/\/\/t.co\//i.test(document.referrer) === true && /Safari\//.test(navigator.userAgent) === false) {   $('.debug').prepend('<br> Test2 '); }   } 

1 Answers

Answers 1

I don't believe it's possible to detect the Twitter in-app browser in JavaScript, because it uses a generic Web View with no identifiable properties.

Most of your examples rely on searching the user agent string for specific keywords. Here's a comparison of user agent strings between the relevant browsers in iOS 11 for iPad based on a test I just conducted:

Safari

Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5372a Safari/604.1

Facebook (in-app)

Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Mobile/15A5372a [FBAN/FBIOS;FBAV/140.0.0.63.89;FBBV/70896504;FBDV/iPad4,2;FBMD/iPad;FBSN/iOS;FBSV/11.0;FBSS/2;FBCR/AT&T;FBID/tablet;FBLC/en_US;FBOP/5;FBRV/0]

Twitter (in-app)

Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5372a Safari/604.1

You can see that Twitter's browser user agent is identical to Safari.

Obviously this is not a solution to your problem, but more of an explanation why you haven't found an actual answer.

Read More

Friday, June 2, 2017

Twitter REST API: Bad Authentication data

Leave a Comment

I'm trying to post a tweet but for any reason it doesn't work as expected.

I suspect that the issue could be related to the signature string, but following what twitter says according to signing requests looks ok.

Here is my code:

function postTweet(user_id, AccessToken, AccessTokenSecret) {   var base_url = 'https://api.twitter.com/1.1/statuses/update.json',     oauth_nonce = randomString(),     oauth_signature,     oauth_timestamp = Math.floor(new Date().getTime() / 1000),     reqArray,     req,     signature_base_string,     signing_key;    reqArray = [     "include_entities=true",     'oauth_consumer_key="' + CONFIG.TWITTER_CONSUMER_KEY + '"',     'oauth_nonce="' + oauth_nonce + '"',     'oauth_signature_method="HMAC-SHA1"',     'oauth_timestamp="' + oauth_timestamp + '"',     'oauth_token="' + AccessToken + '"',     'oauth_version="1.0"',     'status=' + encodeURIComponent("hello world")   ];    req = reqArray.sort().join('&');    signature_base_string = "POST&" + encodeURIComponent(base_url) + "&" + encodeURIComponent(req);    signing_key = CONFIG.TWITTER_CONSUMER_KEY_SECRET + '&' + AccessTokenSecret;    oauth_signature = encodeURIComponent(CryptoJS.HmacSHA1(signature_base_string, signing_key).toString(CryptoJS.enc.Base64));    return $http.post('https://api.twitter.com/1.1/statuses/update.json', {     status: 'hello world'   }).then(function (response) {     return response;   }).catch(function (error) {     console.log(error);   }); } 

enter image description here

As a response, I get that:

enter image description here

UPDATE

considering that in my project I already have $cordovaOauthUtility I started using it this way:

function postTweet(accessToken, accessTokenSecret) {   var params, signature;    params = {     include_entities: true,     oauth_consumer_key: CONFIG.TWITTER_CONSUMER_KEY,     oauth_nonce: $cordovaOauthUtility.createNonce(10),     oauth_signature_method: "HMAC-SHA1",     oauth_token: accessToken,     oauth_timestamp: Math.round((new Date()).getTime() / 1000.0),     oauth_version: "1.0"   };    signature = $cordovaOauthUtility.createSignature('POST', 'https://api.twitter.com/1.1/statuses/update.json', params, { status: "hello" }, CONFIG.TWITTER_CONSUMER_KEY_SECRET, accessTokenSecret);    return $http.post('https://api.twitter.com/1.1/statuses/update.json', {     status: "hello"   }, {     headers: {       Authorization: signature.authorization_header     }   })     .then(function (response) {       return response;     }).catch(function (error) {       console.log(error);     }); } 

enter image description here

UPDATE 2

After trying all the posibilities, the problem persist. Here I paste a plnkr where I have my code.

3 Answers

Answers 1

You are using crypto's HmacSHA256 but sending HMAC-SHA1 as the oauth_signature_method parameter which is the twitter one.

You should probably change your code to

oauth_signature = CryptoJS.HmacSHA1(signature_base_string, signing_key).toString(CryptoJS.enc.Base64); 

If you look at your authorization header, you can also notice that something is wrong with it. Indeed, you can see that the oauth_nonce and the oauth_version are prefixed by a & sign, which shouldn't be the case and most likely mean to the api you are not specifying them. It probably comes from the fact you are using the same reqArray to construct both the signature and the header, or your code is not updated.

You also probably don't want to change the global headers sent from your app, in case another request is sent to another api at the same time. Rather, you should send this authorization header only for this specific xhr.

return $http.post('https://api.twitter.com/1.1/statuses/update.json', {   status: 'hello world', }, {   headers: {     Authorization: auth,   }, }) 

Answers 2

Well, you're clearly adding oauth_token in your request array but it didn't show up in the screenshot? Is the AccessToken in the params undefined?

EDIT

According to the documentation, we must append double quotes to the headers. Try this?

reqArray = [     "include_entities=true",     'oauth_consumer_key="'+CONFIG.TWITTER_CONSUMER_KEY+'"',     'oauth_nonce="'+oauth_nonce+'"',     'oauth_signature_method="HMAC-SHA1"',     'oauth_timestamp="'+oauth_timestamp+'"',     'oauth_token="'+AccessToken+'"',     'oauth_version="1.0"',     'status='+encodeURIComponent("hello world")   ]; 

Answers 3

Yikes.

I've downloaded your plnkr bundle and added a read only application key set. I only had to set up and make one change to get a {"request":"\/1.1\/statuses\/update.json","error":"Read-only application cannot POST."} response. Initially I was receiving {"errors":[{"code":32,"message":"Could not authenticate you."}]}.

Remove status: "hello" from between the curly brackets { } where you create your signature.

signature = $cordovaOauthUtility.createSignature('POST', 'https://api.twitter.com/1.1/statuses/update.json', params, { }, twitter.consumer_secret, twitter.access_token_secret); 

My request headers become the following:

:authority:api.twitter.com :method:POST :path:/1.1/statuses/update.json :scheme:https accept:application/json, text/plain, */* accept-encoding:gzip, deflate, br accept-language:en-US,en;q=0.8 authorization:OAuth     oauth_consumer_key="x",oauth_nonce="QFMmqiasFs",oauth_signature_method="HMAC-SHA1",oauth_token="y",oauth_timestamp="1496340853",oauth_version="1.0",oauth_signature="7Ts91LKcP%2FrYsLcF5WtryCvZQFU%3D" content-length:18 content-type:application/json;charset=UTF-8 origin:http://localhost referer:http://localhost/twits/ user-agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36 

Googling eventually led me to a tutorial: Displaying the Twitter Feed within Your Ionic App. I noted his general createTwitterSignature function does not take parameters and tweaked your code similarly.

function createTwitterSignature(method, url) {     var token = angular.fromJson(getStoredToken());     var oauthObject = {         oauth_consumer_key: clientId,         oauth_nonce: $cordovaOauthUtility.createNonce(10),         oauth_signature_method: "HMAC-SHA1",         oauth_token: token.oauth_token,         oauth_timestamp: Math.round((new Date()).getTime() / 1000.0),         oauth_version: "1.0"     };     var signatureObj = $cordovaOauthUtility.createSignature(method, url, oauthObject, {}, clientSecret, token.oauth_token_secret);     $http.defaults.headers.common.Authorization = signatureObj.authorization_header; } 

I've read conflicting things about why there should/shouldn't be other parameters there, but I believe the signature is just supposed to be the basis of access and doesn't hash in every operation you want to perform - see Understanding Request Signing For Oauth 1.0a Providers.

Read More

Saturday, February 25, 2017

Using twitter API get error sometimes

Leave a Comment

I use the following code which works sometimes but its unstable , when I run the program sometimes I got error 420 with json parse error which doesnt give you lot of hints how to solve it. any idea what am I doing wrong ?

The error is :

Error getting tweets: Error: Status Code: 420 Error getting tweets: SyntaxError: Unexpected token E in JSON at position 0

var Twitter=require('twitter'); var lclconf = require('../config.json');   var client=new Twitter({   consumer_key: lclconf.twitter.consumer_key,   consumer_secret: lclconf.twitter.consumer_secret,   access_token_key: lclconf.twitter.access_token_key,   access_token_secret: lclconf.twitter.access_token_secret }); stream.on("data", function(data){   console.log(data.id_str);   var tweet_id="https://api.twitter.com/1.1/statuses/oembed.json?id="+data.id_str;   request.get(tweet_id)   .end(function(err,res){       if(err){         console.log("Error from Twitter API: " + err);       }else{         //console.log(res.body);         io.emit('tweet',res.body);       }   }); }); stream.on('error', function(err){   console.log("Error getting tweets: "+err); }); io.on('connection', function(client){   client.on("join", function(data){     console.log(data);   });   client.emit("join",{"message":"running"}); }); 

Maybe if there is a way that when the error is occurred ignore it and proceed since now the process is stopped.

Update:

In twitter docs there is info about HTTP 420 but not sure how to fix it ...

2 Answers

Answers 1

HTTP 420 is returned when you are being rate limited.

There is a https://publish.twitter.com/oembed resource URL, that is neither rate limited nor requires authentication. I think it returns the same things that your program expects. You can use that if you pass a query parameter url having the link to tweet. Try making the link like:

"https://publish.twitter.com/oembed?url=https://twitter.com/"+data.user.screen_name+"/statuses/"+data.id_str 

For sample data returned by Twitter click here

Answers 2

As per pii_ke's response you should simply modify tweet_id as follows:

var tweet_id = "https://publish.twitter.com/oembed?url=https://twitter.com/" + data.user.screen_name + "/statuses/" + data.id_str; 

Full modified code you can copy paste:

var Twitter=require('twitter'); var lclconf = require('../config.json');   var client=new Twitter({   consumer_key: lclconf.twitter.consumer_key,   consumer_secret: lclconf.twitter.consumer_secret,   access_token_key: lclconf.twitter.access_token_key,   access_token_secret: lclconf.twitter.access_token_secret }); stream.on("data", function(data){   console.log(data.id_str);   var tweet_id = "https://publish.twitter.com/oembed?url=https://twitter.com/" + data.user.screen_name + "/statuses/" + data.id_str;   request.get(tweet_id)   .end(function(err,res){       if(err){         console.log("Error from Twitter API: " + err);       }else{         //console.log(res.body);         io.emit('tweet',res.body);       }   }); }); stream.on('error', function(err){   console.log("Error getting tweets: "+err); }); io.on('connection', function(client){   client.on("join", function(data){     console.log(data);   });   client.emit("join",{"message":"running"}); }); 
Read More

Friday, January 20, 2017

Javascript array is not accessible as an array

Leave a Comment

I'm working with the twitter API and I'm hitting a really confusing issue.

I have the following script:

const Twitter = require('twitter-api-stream') const twitterCredentials = require('./credentials').twitter  const twitterApi = new Twitter(twitterCredentials.consumerKey, twitterCredentials.consumerSecret, function(){     console.log(arguments) })  twitterApi.getUsersTweets('everycolorbot', 1, twitterCredentials.accessToken, twitterCredentials.accessTokenSecret, (error, result) => {     if (error) {         console.error(error)     }     if (result) {         console.log(result) // outputs an array of json objects         console.log(result.length) //outputs 3506 for some reason (it's only an array of 1)         console.log(result[0]) // outputs a opening bracket ('[')         console.log(result[0].text) // outputs undefined     } }) 

Which is calling the following function to interact with twitter:

TwitterApi.prototype.getUsersTweets = function (screenName, statusCount, userAccessToken, userRefreshToken,cb ) {     var count = statusCount || 10;     var screenName = screenName || "";      _oauth.get(         "https://api.twitter.com/1.1/statuses/user_timeline.json?count=" + count + "&screen_name=" + screenName         , userAccessToken         , userRefreshToken         , cb     ); }; 

It seems like I'm getting the result I want. When I log the result itself I get the following output:

[   {     "created_at": "Thu Sep 01 13:31:23 +0000 2016",     "id": 771339671632838656,     "id_str": "771339671632838656",     "text": "0xe07732",     "truncated": false,     ...   } ] 

Which is great, an array of the tweets limited to 1 tweet.

The problem I'm running into is when I try to access this array.

console.log(result.length) //outputs 3506 for some reason (it's only an array of 1) console.log(result[0]) // outputs a opening bracket ('[') console.log(result[0].text) // outputs undefined 

I read back through the api docs for the user_timeline but unless I'm completely missing it I'm not seeing any mention of special output.

Any ideas?

Update

Thanks @nicematt for pointing out that answer.

Just to elaborate on the solution, I updated my code to this and now I'm getting the result I want:

if (result) {     let tweet = JSON.parse(result)[0] // parses the json and returns the first index     console.log(tweet.text) // outputs '0xe07732' } 

Thanks for the help!

1 Answers

Answers 1

Result is a String and you're indexing it (result[0] (whereas 0 is converted to a string), is almost identical to result.charAt(0) though), this is why result[0] is equal to "["–because it's the first character specified in. You forgot to parse the result as JSON data.

JSON.parse(result).length // probably 1 

And result.text is undefined since result (a string) is like an Object (but isn't instanceof) and allow lookups and getters to happen in itself.

I'd show the difference between str[0] and str.charAt(0), too:

str[0] // same as str['0'], but a getter. 0 converts to        // string (because every key of an object        // is string in ECMAScript)  str.charAt(0) // get/lookup String#charAt, call it               // without new `this` context and with arguments list: 0 
Read More

Saturday, August 20, 2016

how to create user interactive tweet or Facebook post with UIActivityViewController

Leave a Comment

I am trying to figure out how to create a user interactive post or tweet kind of like SoundCloud's here below:

(Shared directly from Sound Cloud)

The portion highlighted in yellow is the part that interests me because as far as I can tell when it comes to UIActivityViewController (which is what Sound Cloud uses for this) the only objects that work for sharing are images and strings.

Further more, if you were to tap the portion highlighted in yellow this screen would pop up on twitter:

enter image description here

HOW DO THEY DO THAT!? THEY HAVE A PAUSE BUTTON AND EVERYTHING!

This is my attempt to do that...

func displayShareSheet(shareContent:String) {          let someView:CustomView = CustomView() // CustomView is a subclass of UIView          let activityViewController = UIActivityViewController(activityItems: [someView], applicationActivities: nil)         presentViewController(activityViewController, animated: true, completion: {})     } 

...which doesn't work. The UIActivityViewController sheet pops up with no share options indicated.

I understand that some may consider this a broad question but if you could at least point me in the right direction I would be very grateful. Thank You.

2 Answers

Answers 1

This works. For the full list of sharing destinations run it on your device and not the simulator. The simulator gives you a smaller list.

func createActivityController() -> UIActivityViewController {     let someText:String = textView.text      let google = NSURL(string:"http://google.com/")!      // let's add a String and an NSURL     var activityViewController = UIActivityViewController(         activityItems: [someText, google],         applicationActivities: nil)      activityViewController.completionHandler = {(activityType, completed:Bool) in         if !completed {             print("cancelled")             return         }          if activityType == UIActivityTypePostToTwitter {             print("twitter")         }          if activityType == UIActivityTypeMail {             print("mail")         }     }      // you can specify these if you'd like.     //        activityViewController.excludedActivityTypes =  [     //            UIActivityTypePostToTwitter,     //            UIActivityTypePostToFacebook,     //            UIActivityTypePostToWeibo,     //            UIActivityTypeMessage,     //            UIActivityTypeMail,     //            UIActivityTypePrint,     //            UIActivityTypeCopyToPasteboard,     //            UIActivityTypeAssignToContact,     //            UIActivityTypeSaveToCameraRoll,     //            UIActivityTypeAddToReadingList,     //            UIActivityTypePostToFlickr,     //            UIActivityTypePostToVimeo,     //            UIActivityTypePostToTencentWeibo     //        ]      return activityViewController } 

Answers 2

For the first part it's only play button that clicks you to popup the player view.

Second: You can do this by just popping a new viewController, use any popup pod: CWPOP as ex. Or whatever suits you or as Twitter here i'm not sure but probably they're doing their own, and you just build a normal view which has the play and everything.

They used do it better before and let you play the music during going through tweets, that was way better to me at least.

Read More

Sunday, May 1, 2016

Twitter OAuth Rest Api Status Parameter '@' symbol

Leave a Comment

I am using twitter rest api which is (https://api.twitter.com/1.1/).

First of all I used signpost library to generate oauth_signature. it is working well.

Upload Status endpoint (https://api.twitter.com/1.1/statuses/upload.json) is working well, but if status parameter contains '@' symbol, that is not working. So here is my code

TwitterStatusesService.java

import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.POST; import retrofit2.http.Path; import retrofit2.http.Query;  public interface TwitterStatusesService {     @POST("/1.1/statuses/update.json")     Call<ResponseBody> update(@Query("status") String status, @Query("in_reply_to_status_id") String inReplyToStatusId, @Query("lat") Double lat, @Query("long") Double lon, @Query("media_ids") String mediaIds); } 

TwitterStatusesAPIClient.java

import android.util.Log;  import com.twitter.sdk.android.core.TwitterAuthToken; import com.twitter.sdk.android.core.TwitterCore; import com.twitter.sdk.android.core.TwitterSession;  import okhttp3.OkHttpClient; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Retrofit; import se.akerfeldt.okhttp.signpost.OkHttpOAuthConsumer; import se.akerfeldt.okhttp.signpost.SigningInterceptor;  public class TwitterStatusesClient {      private final String TAG = getClass().getSimpleName();      private static final String BASE_URL = "https://api.twitter.com/";      private final TwitterStatusesService apiService;      private static TwitterStatusesClient webServiceClient;      public static TwitterStatusesClient getInstance() {         if (webServiceClient == null)             webServiceClient = new TwitterStatusesClient();         return webServiceClient;     }      private TwitterStatusesClient() {         private TwitterStatusesClient() {         OkHttpOAuthConsumer consumer = new OkHttpOAuthConsumer(TWITTER_KEY, TWITTER_SECRET);          TwitterSession activeSession = TwitterCore.getInstance().getSessionManager().getActiveSession();         if (activeSession != null) {             TwitterAuthToken authToken = activeSession.getAuthToken();             String token = authToken.token;             String secret = authToken.secret;             consumer.setTokenWithSecret(token, secret);         }          OkHttpClient client = new OkHttpClient.Builder()                 .addInterceptor(new SigningInterceptor(consumer))                 .build();          Retrofit retrofit = new Retrofit.Builder()                 .baseUrl(BASE_URL)                 .client(client)                 .build();          apiService = retrofit.create(TwitterStatusesService.class);     }      public Call<ResponseBody> update(String status, String statusId, Double lat, Double lon, String mediaIds) {         return apiService.update(status, statusId, lat, lon, mediaIds);     } } 

calling api client

String status = "@example"; TwitterStatusesClient.getInstance().update(status, null, null, null, null).enqueue(new Callback<ResponseBody>() {         @Override         public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {             Log.v(TAG, "onResponse");             progressDialog.dismiss();             try {                 if (response.errorBody() != null) {                     String error = response.errorBody().string();                     Log.e(TAG, "Error : " + error);                     ToastUtils.showErrorMessage(getContext(), "Error : " + error);                     return;                 }                  String body = response.body().string();                 Log.v(TAG, "body : " + body);             } catch (Exception e) {                 e.printStackTrace();             }         }          @Override         public void onFailure(Call<ResponseBody> call, Throwable t) {             Log.v(TAG, "onFailure");             t.printStackTrace();         }     }); 

giving error :

{"errors":[{"code":32,"message":"Could not authenticate you."}]} 

but, if I will use status variable "just example" instead of "@example" ( specific point is removing @ character ) that is working. only '@' symbol is not working.

EDIT

This is my manually creating OAuth v1.0a signature signing code via retrofit interceptor :

OkHttpClient client = new OkHttpClient.Builder()             .addInterceptor(new Interceptor() {                 @Override                 public Response intercept(Interceptor.Chain chain) throws IOException {                     Request request = chain.request();                      String method = request.method();                     String baseUrl = "https://api.twitter.com" + request.url().url().getPath();                      String oauthToken = "";                     String oauthTokenSecret = "";                      TwitterSession activeSession = TwitterCore.getInstance().getSessionManager().getActiveSession();                     if (activeSession != null) {                         TwitterAuthToken authToken = activeSession.getAuthToken();                         oauthToken = authToken.token;                         oauthTokenSecret = authToken.secret;                     }                      String oauthNonce = "TXZScw4M8TG";                     String oauthSignatureMethod = "HMAC-SHA1";                     String oauthTimestamp = String.valueOf(System.currentTimeMillis() / 1000);                     String oauthVersion = "1.0";                      String parameterString = "";                      parameterString = OAuthParams.addParam(request, parameterString, "count");                     parameterString = OAuthParams.addParam(request, parameterString, "id");                     parameterString = OAuthParams.addParam(request, parameterString, "in_reply_to_status_id");                      // if any parameter added to parameterString, append '&' character.                     if (parameterString.length() > 0) {                         parameterString += "&";                     }                      parameterString += "oauth_consumer_key=" + TWITTER_KEY + "&"                             + "oauth_nonce=" + oauthNonce + "&"                             + "oauth_signature_method=" + oauthSignatureMethod + "&"                             + "oauth_timestamp=" + oauthTimestamp + "&"                             + "oauth_token=" + oauthToken + "&"                             + "oauth_version=" + oauthVersion;                      // add status parameter to parameterString.                     parameterString = OAuthParams.addParam(request, parameterString, "status");                      Log.d(TAG, "normalizedParameters : " + parameterString);                     Log.d(TAG, "parameterStringPercent : " + OAuth.percentEncode(parameterString));                      String signatureBaseString = "";                     signatureBaseString += OAuth.percentEncode(method) + "&";                     signatureBaseString += OAuth.percentEncode(baseUrl) + "&";                     signatureBaseString += OAuth.percentEncode(parameterString);                      String oauthSignature = OauthSignature.generateSignature(signatureBaseString, TWITTER_SECRET,                             oauthTokenSecret);                      String authorization = "OAuth oauth_consumer_key=\"" + TWITTER_KEY + "\", " +                             "oauth_signature_method=\"HMAC-SHA1\", " +                             "oauth_timestamp=\"" + oauthTimestamp + "\", " +                             "oauth_nonce=\"" + oauthNonce + "\", " +                             "oauth_version=\"1.0\", " +                             "oauth_token=\"" + oauthToken + "\", " +                             "oauth_signature=\"" + OAuth.percentEncode(oauthSignature) + "\"";                      Log.w(TAG, "Authorization : " + authorization);                      request = request.newBuilder()                             .addHeader("Authorization", authorization)                             .build();                     return chain.proceed(request);                 }             }).addInterceptor(interceptor).build(); 

OAuth.java

public static String percentEncode(String s) {     if (s == null) {         return "";     }     try {         return URLEncoder.encode(s, ENCODING)                 // OAuth encodes some characters differently:                 .replace("+", "%20").replace("*", "%2A")                 .replace("%7E", "~");         // This could be done faster with more hand-crafted code.     } catch (UnsupportedEncodingException wow) {         throw new RuntimeException(wow.getMessage(), wow);     } } 

OAuthSignature.java

import android.util.Base64; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec;  public class OauthSignature {  public static String generateSignature(String signatueBaseStr, String oAuthConsumerSecret, String oAuthTokenSecret) {     byte[] byteHMAC = null;     try {         Mac mac = Mac.getInstance("HmacSHA1");         SecretKeySpec spec;         if (null == oAuthTokenSecret) {             String signingKey = OAuth.percentEncode(oAuthConsumerSecret) + '&';             spec = new SecretKeySpec(signingKey.getBytes(), "HmacSHA1");         } else {             String signingKey = OAuth.percentEncode(oAuthConsumerSecret) + '&' + OAuth.percentEncode(oAuthTokenSecret);             spec = new SecretKeySpec(signingKey.getBytes(), "HmacSHA1");         }         mac.init(spec);         byteHMAC = mac.doFinal(signatueBaseStr.getBytes());     } catch (Exception e) {         e.printStackTrace();     }     return new String(Base64.encode(byteHMAC, Base64.DEFAULT)); } } 

1 Answers

Answers 1

I suggest go with fabric - https://fabric.io which has twitters various libs like twitter login, crashlytics and alss you need to setup fabric plugin with android studio. Post that you will be able to post/retrieve you tweets irrespective what you want to post.

For your question - check that '@' is special symbol where by retrofit is causing a problem. These kind of issues come up with retrofit which I have faced in different scenarios.

Try using Fabric for Twitter Login/oAuth

Read More

Monday, March 7, 2016

What is the best way to handle connection to many Twitter accounts?

Leave a Comment

My application need a twitter account to create an account and authentify. Then, the user can link any other Twitter accounts as he like. So, a user has ONE main twitter account which allow him to connect to my app, then, he can browser all the accounts he has previously linked in the app. My question is about the login process on Twitter side.

First, I've thinked about setting force_login only when linking new account. This way, the user does not have to reconnect on Twitter each time he want to connect to my app. And, when he want to link another account, force_login force him to chose the right account. The problem is that Twitter stay connected to the last authentified account. So, if the user logout from my app just after linking another account, then login with twitter, he login with the second account, and create a new user on my app. Exemple:

User has two twitter accounts : @a and @b. He's authentified to Twitter with @a. He signup to my app, Twitter shows him the permissions asked by my app, user accept, he's redirected to my app, a new User which can auth with @a is created. Then, he link @b account. Thanks to force_login, Twitter asks him for credentials. User login to @b, Twitter asks permissions, then, the account is linked to the user on my app. We now have a user who can auth with @a and who is linked to @b. Then, session on my app is over, user needs to reconnect. Because there is no force_login, Twitter sees he's already connected with an account which authtorised my app, so connection is accepted without any action from the user. But, what nobody sees is that user was connected with the last account : @b. So, I get a signin action with @b, which means to a new user creation. I now have two users : User1 which can auth with @a and is linked to @b, and User2 which can auth with @b. And my user doesn't understand where is its @a account.

So my question is : do I have to set force_login anywhere ? Or is there another way to tell Twitter to not authentify when linking an account?

1 Answers

Answers 1

For me it looks like your problem is not related to twitter at all. You just need to handle the login / sign up process properly in your application.

Here is what happens, according to your description:

  • User signs up with @a account
  • Internally you create the user profile in your database (I assume that you have the database, doesn't really matter what kind of database), like this:
    • User A
    • id = 1 (your internal id)
    • name = UserA
    • accounts (related table)
      • twitter @a
  • User adds one more (@b) account
  • You update the user profile like this:
    • User A
    • id = 1
    • name = UserA
    • accounts
      • twitter @a
      • twitter @b
  • The user signs out
  • The user logs in back with @b account
  • Twitter approves it and redirects back to your app

Now you say "So, I get a signin action with @b, which means to a new user creation.". Why so? Twitter knows nothing about your application, but you do know it.

What you want to do here is just search through your database, find that you already have the "twitter @b" account and it is linked to "UserA". Then you just login the "UserA" into your application instead of creating the new user (you anyway don't want to have different users with the same twitter account, so twitter account id should be unique in your database).

Read More