<commit_before>package org.talkingpuffin.twitter

import java.net.{URL,URLEncoder}
import scala.xml._

/**
* The TwitterSession object acts as a factory for both authenticated and unauthenticated sessions.
* There are two apply methods.
* <tt><pre>
* val session = TwitterSession()
* </pre></tt>
* will return an UnauthenticatedSession instance, which only supports methods which do not require logon.
* <tt><pre>
* val session = TwitterSession(userid,password)
* </pre></tt>
* will return an AuthenticatedSession.  This extends UnauthenticatedSession, and provides additional
* calls that require authentication
*/
object TwitterSession {
  /**
  * get an AuthenticatedSession instance with the provided user and password
  * Note that this should always succeed.  The userid and password are not (currently) checked
  */
  def apply(user: String, password: String): AuthenticatedSession = {
    new AuthenticatedSession(user,password)
  }

  def apply(user: String, password: String, apiURL: String): AuthenticatedSession = {
    new AuthenticatedSession(user,password,apiURL)
  }
  
  /**
  * get an UnauthenticatedSession instance
  */
  def apply(): UnauthenticatedSession = {
    new UnauthenticatedSession()
  }

  def apply(apiURL: String): UnauthenticatedSession = {
    new UnauthenticatedSession(apiURL)
  }
}

/**
* The base class of both TwitterSession objects
*/
abstract class TwitterSession

/**
* Provides an interface to Twitter for all non-authorized calls.
* This class provides a limited set of functionality, but should be
* safe to use against the 70 calls/hr rate limit.
*
* If you need access to the authenticated calls, see AuthenticatedSession.
*
* This class should be completely thread safe, allowing multiple simultaneous calls to Twitter via this object.
*
* All methods are fairly direct representations of calls specified in the 
* <a href="http://groups.google.com/group/twitter-development-talk/web/api-documentation">Twitter API Doc</a>
*/
class UnauthenticatedSession(apiURL: String) extends TwitterSession{

  def this() = this(API.defaultURL)
  
  def loadAll[T](f:(Int) => List[T]):List[T] = {
    loadAll(1,f,List[T]())
  }

  private def loadAll[T](page: Int, f:(Int) => List[T], listIn: List[T]):List[T] = {
      f(page) match {
          case Nil => listIn
          case l => loadAll(page+1,f,listIn ::: l)
      }
  }
  /** utility class to connect to a URL and fetch XML. */
  val fetcher = new XMLFetcher(null,null)
  
  def getPublicTimeline(): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/public_timeline.xml"),fetcher,TwitterStatus.apply).parseXMLList("status")
  }

  def getPublicTimeline(page: Int): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/public_timeline.xml?page=" + page),fetcher,TwitterStatus.apply).parseXMLList("status")
  }

  def getStatus(id: Long): TwitterStatus = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/show/" + id.toString() + ".xml"),fetcher,TwitterStatus.apply).parseXMLElement()
  }
  
  def getFeatured(): List[TwitterUser] = {
    new Parser[TwitterUser](new URL(apiURL + "/statuses/featured.xml"),fetcher,TwitterUser.apply).parseXMLList("user")
  }

  /**
  * @param id the user id <i>or</i> user name to get favorites for
  */
  def getFavorites(id: String): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/favorites/" + urlEncode(id) + ".xml"),fetcher,TwitterStatus.apply).parseXMLList("status")
  }
  
  /**
  * @param id the user id <i>or</i> user name to get favorites for
  * @param page the results page to fetch.
  */
  def getFavorites(id: String, page: Int): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/favorites/" + urlEncode(id) + ".xml?page=" + page.toString()),fetcher,TwitterStatus.apply).parseXMLList("status")
  }

  /**
  * @param id the user id <i>or</i> user name to get friends for
  */
  def getFriends(id: String): List[TwitterUser] = {
    getFriends(id,TwitterArgs())
  }

  /**
  * @param id the user id <i>or</i> user name to get friends for
  * @param page the results page to fetch.
  */
  def getFriends(id: String, page: Int): List[TwitterUser] = {
    getFriends(id,TwitterArgs().page(page))
  }

  def getFriends(id: String, args: TwitterArgs): List[TwitterUser] = {
    new Parser[TwitterUser](new URL(apiURL + "/statuses/friends/" + urlEncode(id) + ".xml" + args),fetcher,TwitterUser.apply).parseXMLList("user")
  }
  
  protected def urlEncode(value: String) = URLEncoder.encode(value, "UTF-8")
}

/**
* Provides access to Twitter API methods that require authentication.
* Like UnauthenticatedSession, this class is thread safe, and more or less directly mirrors the
* <a href="http://groups.google.com/group/twitter-development-talk/web/api-documentation">Twitter API Doc</a>
*/
class AuthenticatedSession(val user: String, val password: String, val apiURL: String) extends UnauthenticatedSession(apiURL){

  val authFetcher = new XMLFetcher(user,password)

  def this(user: String,password: String) = this(user,password,API.defaultURL)
  /**
  * @param id the user id <i>or</i> user name of the desired friends timeline
  */
  def getFriendsTimeline(id: String): List[TwitterStatus] = {
    getFriendsTimeline(id,TwitterArgs())
  }

  def getFriendsTimeline(id: String,page: Int): List[TwitterStatus] = {
    getFriendsTimeline(id,TwitterArgs.page(page))
  }

  def getFriendsTimeline(id: String, args:TwitterArgs): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/friends_timeline/" + urlEncode(id) + 
        ".xml" + args),authFetcher,TwitterStatus.apply).parseXMLList("status")
  }

  def getFriendsTimeline(): List[TwitterStatus] = {
    getFriendsTimeline(user,TwitterArgs())
  }

  def getFriendsTimeline(page: Int): List[TwitterStatus] = {
    getFriendsTimeline(user,TwitterArgs.page(page))
  }

  def getFriendsTimeline(args:TwitterArgs): List[TwitterStatus] = {
    getFriendsTimeline(user,args)
  }

  /**
  * @param id the user id <i>or</i> user name of the desired user's timeline
  */
  def getUserTimeline(id: String): List[TwitterStatus] = {
    getUserTimeline(id,TwitterArgs())
  }
  def getUserTimeline(id: String, page: Int): List[TwitterStatus] = {
    getUserTimeline(id,TwitterArgs.page(page))
  }

  def getUserTimeline(id: String, args: TwitterArgs): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/user_timeline/" + urlEncode(id) + ".xml" + args),authFetcher,TwitterStatus.apply).parseXMLList("status")
  }

  /**
  * @param id the user id <i>or</i> user name of the desired user's timeline with retweets
  */
  def getHomeTimeline(id: String): List[TwitterStatus] = {
    getHomeTimeline(id,TwitterArgs())
  }
  def getHomeTimeline(id: String, page: Int): List[TwitterStatus] = {
    getHomeTimeline(id,TwitterArgs.page(page))
  }

  def getHomeTimeline(id: String, args: TwitterArgs): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/home_timeline/" + URLEncoder.encode(id) + ".xml" + args),authFetcher,TwitterStatus.apply).parseXMLList("status")
  }
  /**
  * @param id the user id <i>or</i> user name who was mentioned
  */
  def getMentions(id: String): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/mentions/" + urlEncode(id) + ".xml"),authFetcher,TwitterStatus.apply).parseXMLList("status")
  }
  def getMentions(id: String, page: Int): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/mentions/" + urlEncode(id) + ".xml?page=" + page),authFetcher,TwitterStatus.apply).parseXMLList("status")
  }

  def getRetweetedByMe(): List[TwitterStatus] = {
    getRetweetedByMe(TwitterArgs())
  }
  def getRetweetedByMe(page: Int): List[TwitterStatus] = {
    getRetweetedByMe(TwitterArgs.page(page))
  }

  def getRetweetedByMe(args: TwitterArgs): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/retweeted_by_me.xml" + args),authFetcher,TwitterStatus.apply).parseXMLList("status")
  }

  def getRetweetedToMe(): List[TwitterStatus] = {
    getRetweetedToMe(TwitterArgs())
  }<commit_msg>Fix getHomeTimeline to urlencode with UTF-8, like the others<commit_after>package org.talkingpuffin.twitter

import java.net.{URL,URLEncoder}
import scala.xml._

/**
* The TwitterSession object acts as a factory for both authenticated and unauthenticated sessions.
* There are two apply methods.
* <tt><pre>
* val session = TwitterSession()
* </pre></tt>
* will return an UnauthenticatedSession instance, which only supports methods which do not require logon.
* <tt><pre>
* val session = TwitterSession(userid,password)
* </pre></tt>
* will return an AuthenticatedSession.  This extends UnauthenticatedSession, and provides additional
* calls that require authentication
*/
object TwitterSession {
  /**
  * get an AuthenticatedSession instance with the provided user and password
  * Note that this should always succeed.  The userid and password are not (currently) checked
  */
  def apply(user: String, password: String): AuthenticatedSession = {
    new AuthenticatedSession(user,password)
  }

  def apply(user: String, password: String, apiURL: String): AuthenticatedSession = {
    new AuthenticatedSession(user,password,apiURL)
  }
  
  /**
  * get an UnauthenticatedSession instance
  */
  def apply(): UnauthenticatedSession = {
    new UnauthenticatedSession()
  }

  def apply(apiURL: String): UnauthenticatedSession = {
    new UnauthenticatedSession(apiURL)
  }
}

/**
* The base class of both TwitterSession objects
*/
abstract class TwitterSession

/**
* Provides an interface to Twitter for all non-authorized calls.
* This class provides a limited set of functionality, but should be
* safe to use against the 70 calls/hr rate limit.
*
* If you need access to the authenticated calls, see AuthenticatedSession.
*
* This class should be completely thread safe, allowing multiple simultaneous calls to Twitter via this object.
*
* All methods are fairly direct representations of calls specified in the 
* <a href="http://groups.google.com/group/twitter-development-talk/web/api-documentation">Twitter API Doc</a>
*/
class UnauthenticatedSession(apiURL: String) extends TwitterSession{

  def this() = this(API.defaultURL)
  
  def loadAll[T](f:(Int) => List[T]):List[T] = {
    loadAll(1,f,List[T]())
  }

  private def loadAll[T](page: Int, f:(Int) => List[T], listIn: List[T]):List[T] = {
      f(page) match {
          case Nil => listIn
          case l => loadAll(page+1,f,listIn ::: l)
      }
  }
  /** utility class to connect to a URL and fetch XML. */
  val fetcher = new XMLFetcher(null,null)
  
  def getPublicTimeline(): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/public_timeline.xml"),fetcher,TwitterStatus.apply).parseXMLList("status")
  }

  def getPublicTimeline(page: Int): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/public_timeline.xml?page=" + page),fetcher,TwitterStatus.apply).parseXMLList("status")
  }

  def getStatus(id: Long): TwitterStatus = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/show/" + id.toString() + ".xml"),fetcher,TwitterStatus.apply).parseXMLElement()
  }
  
  def getFeatured(): List[TwitterUser] = {
    new Parser[TwitterUser](new URL(apiURL + "/statuses/featured.xml"),fetcher,TwitterUser.apply).parseXMLList("user")
  }

  /**
  * @param id the user id <i>or</i> user name to get favorites for
  */
  def getFavorites(id: String): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/favorites/" + urlEncode(id) + ".xml"),fetcher,TwitterStatus.apply).parseXMLList("status")
  }
  
  /**
  * @param id the user id <i>or</i> user name to get favorites for
  * @param page the results page to fetch.
  */
  def getFavorites(id: String, page: Int): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/favorites/" + urlEncode(id) + ".xml?page=" + page.toString()),fetcher,TwitterStatus.apply).parseXMLList("status")
  }

  /**
  * @param id the user id <i>or</i> user name to get friends for
  */
  def getFriends(id: String): List[TwitterUser] = {
    getFriends(id,TwitterArgs())
  }

  /**
  * @param id the user id <i>or</i> user name to get friends for
  * @param page the results page to fetch.
  */
  def getFriends(id: String, page: Int): List[TwitterUser] = {
    getFriends(id,TwitterArgs().page(page))
  }

  def getFriends(id: String, args: TwitterArgs): List[TwitterUser] = {
    new Parser[TwitterUser](new URL(apiURL + "/statuses/friends/" + urlEncode(id) + ".xml" + args),fetcher,TwitterUser.apply).parseXMLList("user")
  }
  
  protected def urlEncode(value: String) = URLEncoder.encode(value, "UTF-8")
}

/**
* Provides access to Twitter API methods that require authentication.
* Like UnauthenticatedSession, this class is thread safe, and more or less directly mirrors the
* <a href="http://groups.google.com/group/twitter-development-talk/web/api-documentation">Twitter API Doc</a>
*/
class AuthenticatedSession(val user: String, val password: String, val apiURL: String) extends UnauthenticatedSession(apiURL){

  val authFetcher = new XMLFetcher(user,password)

  def this(user: String,password: String) = this(user,password,API.defaultURL)
  /**
  * @param id the user id <i>or</i> user name of the desired friends timeline
  */
  def getFriendsTimeline(id: String): List[TwitterStatus] = {
    getFriendsTimeline(id,TwitterArgs())
  }

  def getFriendsTimeline(id: String,page: Int): List[TwitterStatus] = {
    getFriendsTimeline(id,TwitterArgs.page(page))
  }

  def getFriendsTimeline(id: String, args:TwitterArgs): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/friends_timeline/" + urlEncode(id) + 
        ".xml" + args),authFetcher,TwitterStatus.apply).parseXMLList("status")
  }

  def getFriendsTimeline(): List[TwitterStatus] = {
    getFriendsTimeline(user,TwitterArgs())
  }

  def getFriendsTimeline(page: Int): List[TwitterStatus] = {
    getFriendsTimeline(user,TwitterArgs.page(page))
  }

  def getFriendsTimeline(args:TwitterArgs): List[TwitterStatus] = {
    getFriendsTimeline(user,args)
  }

  /**
  * @param id the user id <i>or</i> user name of the desired user's timeline
  */
  def getUserTimeline(id: String): List[TwitterStatus] = {
    getUserTimeline(id,TwitterArgs())
  }
  def getUserTimeline(id: String, page: Int): List[TwitterStatus] = {
    getUserTimeline(id,TwitterArgs.page(page))
  }

  def getUserTimeline(id: String, args: TwitterArgs): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/user_timeline/" + urlEncode(id) + ".xml" + args),authFetcher,TwitterStatus.apply).parseXMLList("status")
  }

  /**
  * @param id the user id <i>or</i> user name of the desired user's timeline with retweets
  */
  def getHomeTimeline(id: String): List[TwitterStatus] = {
    getHomeTimeline(id,TwitterArgs())
  }
  def getHomeTimeline(id: String, page: Int): List[TwitterStatus] = {
    getHomeTimeline(id,TwitterArgs.page(page))
  }

  def getHomeTimeline(id: String, args: TwitterArgs): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/home_timeline/" + urlEncode(id) + ".xml" + args),authFetcher,TwitterStatus.apply).parseXMLList("status")
  }
  /**
  * @param id the user id <i>or</i> user name who was mentioned
  */
  def getMentions(id: String): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/mentions/" + urlEncode(id) + ".xml"),authFetcher,TwitterStatus.apply).parseXMLList("status")
  }
  def getMentions(id: String, page: Int): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/mentions/" + urlEncode(id) + ".xml?page=" + page),authFetcher,TwitterStatus.apply).parseXMLList("status")
  }

  def getRetweetedByMe(): List[TwitterStatus] = {
    getRetweetedByMe(TwitterArgs())
  }
  def getRetweetedByMe(page: Int): List[TwitterStatus] = {
    getRetweetedByMe(TwitterArgs.page(page))
  }

  def getRetweetedByMe(args: TwitterArgs): List[TwitterStatus] = {
    new Parser[TwitterStatus](new URL(apiURL + "/statuses/retweeted_by_me.xml" + args),authFetcher,TwitterStatus.apply).parseXMLList("status")
  }

  def getRetweetedToMe(): List[TwitterStatus] = {
    getRetweetedToMe(TwitterArgs())
  }
{'fraction_non_alphanumeric': 0.13371135906347173, 'fraction_numerical': 0.0006706908115358819, 'mean_word_length': 4.650017223561832, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 28}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7250064', 'n_tokens_mistral': 5430, 'n_tokens_neox': 5210, 'n_words': 1256}