socialnetworknews

This will basicly get a paper.li OpenSource clone at some point - DEPRECATED NOT USED ANYMORE
git clone git://archive.git.mtrnord.blog/SocialNetworkNews/socialnetworknews.git
Log | Files | Refs | README | LICENSE

StreamingApi.scala (5161B)


      1 package twitterCrawler
      2 
      3 import java.io.File
      4 import java.text.SimpleDateFormat
      5 import java.util.Date
      6 
      7 import com.danielasfregola.twitter4s.entities.streaming.common.{DisconnectMessage, LimitNotice, WarningMessage}
      8 import com.danielasfregola.twitter4s.entities.{Tweet, User}
      9 import com.danielasfregola.twitter4s.http.clients.streaming.TwitterStream
     10 import com.danielasfregola.twitter4s.{TwitterRestClient, TwitterStreamingClient}
     11 import com.github.tototoshi.csv.CSVWriter
     12 import com.typesafe.config.{Config, ConfigFactory}
     13 import com.typesafe.scalalogging.StrictLogging
     14 import org.joda.time.{DateTime, DateTimeZone}
     15 
     16 import scala.collection.JavaConverters._
     17 import scala.concurrent.ExecutionContext.Implicits.global
     18 import scala.concurrent.{Await, Future}
     19 
     20 
     21 object RestAPISingleton {
     22   private var restAPI: TwitterRestClient = _
     23   def getRestAPI: TwitterRestClient = {
     24     this.restAPI
     25   }
     26 
     27   def setRestAPI(restAPI: TwitterRestClient): Unit = {
     28     this.restAPI = restAPI
     29   }
     30 
     31 }
     32 
     33 /**
     34   *
     35   * StreamingAPI class is the connector for the Twitter Streaming Api
     36   *
     37   * It mainly has the purpose to get Tweets of the users from the Lists and Hashtags defined inside the Config
     38   *
     39   * @param streamingClient holds the current Client for the Twitter Streaming API
     40   */
     41 class StreamingApi(val streamingClient: TwitterStreamingClient) extends StrictLogging {
     42   val conf: Config = ConfigFactory.load()
     43   val restClient: TwitterRestClient = RestAPISingleton.getRestAPI
     44 
     45   /**
     46     * fetchTweets is a async function, that listens on Twitter's Streaming API for the defined Lists and Hastags
     47     *
     48     * @return
     49     */
     50   def fetchTweets: Future[TwitterStream] = {
     51     val trackedWordsConf =
     52       conf.getStringList("twitter.trackedWords")
     53     var trackedWords: Seq[String] = Seq()
     54     val trackedLists: List[String] =
     55       conf.getStringList("twitter.lists").asScala.toList
     56     val trackedUsers: Seq[Long] = Await.result(
     57       this.getListUsers(trackedLists),
     58       scala.concurrent.duration.Duration.Inf
     59     )
     60 
     61     trackedWordsConf.forEach((s: String) =>{
     62       trackedWords = trackedWords :+ s
     63     })
     64 
     65     logger.info(
     66       s"Launching streaming session with tracked keywords: $trackedWords\r\n" +
     67         s"And with tracked Users: $trackedUsers"
     68     )
     69 
     70     streamingClient.filterStatuses(tracks = trackedWords, follow = trackedUsers) {
     71       case tweet: Tweet =>
     72         println("=============")
     73         logger.info("Found a new Tweet... Saving...")
     74         logger.debug(tweet.text)
     75         this.saveIDforLater(tweet)
     76         logger.debug("Done Saving")
     77         println("=============")
     78       case disconnect: DisconnectMessage =>
     79         logger.warn("Disconnect: ", disconnect.disconnect)
     80       case limit: LimitNotice =>
     81         logger.warn("Limit: ", limit)
     82       case warning: WarningMessage =>
     83         logger.warn("Warning: ", warning.warning)
     84       case default =>
     85         logger.debug(default.toString)
     86     }
     87   }
     88 
     89   /**
     90     * saveIDforLater saves the tweetID and indexing Date to a csv as soon as the Tweet gets published
     91     *
     92     * @todo implement
     93     * @param tweet holds the currently processed Tweet
     94     */
     95   private def saveIDforLater(tweet: Tweet): Unit = {
     96     val currentDate =
     97       new Date(DateTime.now(DateTimeZone.UTC).getMillis)
     98     val today = new SimpleDateFormat("dd_MM_yyyy").format(currentDate)
     99     val dir = new File("data/")
    100     if (!dir.exists()) {
    101       dir.mkdir()
    102     }
    103     val todaysTweets = new File(s"data/tweets.$today")
    104     if (!todaysTweets.exists()) {
    105       todaysTweets.createNewFile()
    106     }
    107     val writer = CSVWriter.open(todaysTweets, append = true)
    108     writer.writeRow(List(tweet.id_str, currentDate.toString))
    109 
    110     writer.close()
    111   }
    112 
    113   /**
    114     * getListUsers is used to ask the Twitter API about what users are in a List
    115     *
    116     * Uses the Twitter Rest API
    117     *
    118     * @param trackedLists holds the list slugs and corresponding Users for all tracked lists
    119     * @return
    120     */
    121   private def getListUsers(trackedLists: List[String]): Future[Seq[Long]] = {
    122     Future {
    123       var trackedUsers: Seq[Long] = Seq()
    124       trackedLists.foreach((v: String) => {
    125         val splitted = v.split("/")
    126         val username = splitted(0)
    127         val slug = splitted(1)
    128 
    129         var listUsers = Await.result(
    130           restClient.listMembersBySlugAndOwnerName(
    131             slug = slug,
    132             owner_screen_name = username,
    133             include_entities = false
    134           ),
    135           scala.concurrent.duration.Duration.Inf
    136         )
    137         listUsers.data.users.foreach((user: User) => {
    138           trackedUsers = trackedUsers :+ user.id
    139         })
    140         while (listUsers.data.next_cursor != listUsers.data.previous_cursor) {
    141           listUsers = Await.result(
    142             restClient.listMembersBySlugAndOwnerName(
    143               slug = slug,
    144               owner_screen_name = username,
    145               include_entities = false,
    146               cursor = listUsers.data.next_cursor
    147             ),
    148             scala.concurrent.duration.Duration.Inf
    149           )
    150           listUsers.data.users.foreach((user: User) => {
    151             trackedUsers = trackedUsers :+ user.id
    152           })
    153         }
    154 
    155       })
    156       trackedUsers
    157     }
    158   }
    159 }