(* ::Package:: *) (* ::Title:: *) (*Twitter*) (* ::Author:: *) (*Rob Raguet-Schofield*) (*packages@ragfield.com*) (* ::Section:: *) (*Initialization*) (* ::Input:: *) (*Needs["WebUtils`"];*) BeginPackage["Twitter`", {"JLink`", "WebUtils`"}]; TwitterSession::usage = "TwitterSession[...] is an object that contains login credentials for a Twitter account."; TwitterSessionScreenName::usage = "TwitterSessionScreenName[session] returns the Twitter account name associated with the given session."; TwitterSessionUser::usage = "TwitterSessionUser[session] returns the TwitterUser object associated with the given session."; TwitterSessionOpen::usage = "TwitterSessionOpen[(\"User\"->\"screen_name\", (\"Password\"->\"password\"))] creates a new TwitterSession with the given account credentials, or (if no credentials are specified) prompts the user for a user name and password."; TwitterSessionClose::usage = "TwitterSessionClose[session] terminates the TwitterSession and releases the resources associated with it."; TwitterSessionAuthorize::usage = "TwitterSessionAuthorize[session] can be used to reauthorize a TwitterSession with new account credentials."; TwitterSessionAuthorizedQ::usage = "TwitterSessionAuthorizedQ[session] returns True if the given TwitterSession is currently authorized, or False if it is not currently authorized."; TwitterUser::usage = "TwitterUser[...] is an object that contains information about a specific Twitter user account."; TwitterUserID::usage = "TwitterUserID[user] returns the unique integer identifier for the given TwitterUser."; TwitterUserName::usage = "TwitterUserName[user] returns the full name of the given TwitterUser (if available)."; TwitterUserScreenName::usage = "TwitterUserScreenName[user] returns the screen name of the given TwitterUser."; TwitterUserLocation::usage = "TwitterUserLocation[user] returns the Twitter profile location of the given TwitterUser (if available)."; TwitterUserHomePage::usage = "TwitterUserHomePage[user] returns the Twitter profile home page URL of the given TwitterUser (if available)."; TwitterUserDescription::usage = "TwitterUserDescription[user] returns the Twitter profile bio information of the given TwitterUser (if available)."; TwitterUserProfilePage::usage = "TwitterUserProfilePage[user] returns the URL of the Twitter web page of the given TwitterUser."; TwitterUserProfileImage::usage = "TwitterProfileImage[user] returns the profile image of the given TwitterUser."; TwitterUserProfileImageURL::usage = "TwitterProfileImageURL[user] returns the profile image URL of the given TwitterUser."; TwitterUserStatusCount::usage = "TwitterUserStatusCount[user] returns the number of status messages posted by the given user."; TwitterUserFriendCount::usage = "TwitterUserFriendCount[user] returns the number of friends the given user has."; TwitterUserFollowerCount::usage = "TwitterUserFollowerCount[user] returns the number of followers the given user has."; TwitterUserFavoriteCount::usage = "TwitterUserFavoriteCount[user] returns the number of favorite status messages the given user has."; TwitterUserProtectedQ::usage = "TwitterUserProtectedQ[user] returns true if the given user has protected their updates, False if they have not."; TwitterUserDate::usage = "TwitterUserDate[user] returns the account creation date of the given user."; TwitterUserInfo::usage = "TwitterUserInfo[user] returns a styled text representation of the name, location, home page, description of the give TwitterUser."; TwitterUserUI::usage = "TwitterUserUI[user] returns a graphical user interface element for the given TwitterUser."; TwitterStatus::usage = "TwitterStatus[...] is an object that contains information about a specific Twitter status message."; TwitterStatusID::usage = "TwitterStatusID[status] returns the unique integer identifier for the given TwitterStatus."; TwitterStatusUser::usage = "TwitterStatusUser[status] returns the TwitterUser who posted the given TwitterStatus."; TwitterStatusText::usage = "TwitterStatusText[status] returns the textual contents of the given TwitterStatus."; TwitterStatusDate::usage = "TwitterStatusDate[status] returns the posted date of the given TwitterStatus."; TwitterStatusDateString::usage = "TwitterStatusDateString[status] returns a string representation of the posted date of the given TwitterStatus."; TwitterStatusPage::usage = "TwitterStatusPage[status] returns the Twitter URL of the given TwitterStatus."; TwitterStatusSource::usage = "TwitterStatusSource[status] returns text or hyperlink representation of the application used to post the given TwitterStatus."; TwitterStatusReplyID::usage = "TwitterStatusReplyID[status] returns the unique integer identifier of the TwitterStatus to which the given TwitterStatus is a reply, or 0 if the given TwitterStatus is not a reply."; TwitterStatusReplyUserID::usage = "TwitterStatusReplyUserID[status] returns the unique integer identifier of the TwitterUser to which the given TwitterStatus replies, or 0 if the given TwitterStatus is not a reply."; TwitterStatusUI::usage = "TwitterStatusUI[status] returns a graphical user interface element for the given TwitterStatus."; TwitterSetStatus::usage = "TwitterSetStatus[session, expr] sets the status of the user associated with session to the string representation of expr."; TwitterReply::usage = "TwitterReply[session, status|id, expr] replies to the given status with the string representation of expr."; TwitterDeleteStatus::usage = "TwitterDeleteStatus[session, status|id] deletes the status specified by the given TwitterStatus or unique integer identifier."; TwitterPublicTimeline::usage = "TwitterPublicTimeline[(\"Page\"->n)] returns the nth page of most recent public Twitter status messages."; TwitterFriendsTimeline::usage = "TwitterFriendsTimeline[session (, \"Page\"->n)] returns the nth page of most recent Twitter status messages of friends of the user associated with session."; TwitterUserTimeline::usage = "TwitterUserTimeline[session|user|id (, \"Page\"->n)] returns the nth page of most recent Twitter status messages of the specified user."; TwitterUserAllTimeline::usage = "TwitterUserAllTimeline[session|user|id] returns all status messages in the timeline of the specified user."; TwitterReplies::usage = "TwitterReplies[session (, \"Page\"->n)] returns the nth page of most recent replies to the user associated with session."; TwitterAllReplies::usage = "TwitterAllReplies[session] returns all status messages which reply to the specified user."; TwitterFriends::usage = "TwitterFriends[session (, user|id (, \"Page\"->n))] returns the nth page of users who are friends of the given user."; TwitterAllFriends::usage = "TwitterAllFriends[session (, user|id)] returns a list of all users who are friends of the given user."; TwitterFollowers::usage = "TwitterFollowers[session (, user|id (, \"Page\"->n))] returns the nth page of users who are followers of the given user."; TwitterAllFollowers::usage = "TwitterAllFollowers[session (, user|id)] returns a list of all users who are followers of the given user."; TwitterSearch::usage = "TwitterSearch[query (, \"Page\"->n, \"Since\"->id)] returns a list of Twitter status messages matching the query term."; Begin["`Private`"]; (* ::Section:: *) (*Implementation*) $TwitterDebug = False; (* ::Subsection:: *) (*Utility Methods*) utcToLocal[{year_, mon_, day_, h_, m_, s_}] := JavaBlock@Module[ {utcZone, localZone, utcCal, localCal, date}, LoadJavaClass["java.util.TimeZone"]; LoadJavaClass["java.util.GregorianCalendar"]; utcZone = TimeZone`getTimeZone["UTC"]; localZone = TimeZone`getDefault[]; utcCal = JavaNew["java.util.GregorianCalendar", utcZone]; localCal = JavaNew["java.util.GregorianCalendar", localZone]; utcCal@set[year, mon - 1, day, h, m, Round[s]]; localCal@setTime[utcCal@getTime[]]; (localCal@get[#]& /@ { Calendar`YEAR, Calendar`MONTH, Calendar`DATE, Calendar`HOURUOFUDAY, Calendar`MINUTE, Calendar`SECOND }) + {0, 1, 0, 0, 0, 0.} (* convert seconds to Real *) ]; xmlElementRules[str_String] := str; xmlElementRules[XMLElement[tag_String, _, {val_String}]] := Rule[tag, val]; xmlElementRules[XMLElement[tag_String, _, {}]] := Rule[tag, ""]; xmlElementRules[XMLElement[tag_String, attrs_List, elems:{___, _XMLElement, ___}]] := Rule[tag, xmlElementRules /@ elems]; (* ::Subsection:: *) (*TwitterSession*) Format[twitter_TwitterSession, StandardForm] := StringForm[ "TwitterSession[<`1`>]", TwitterSessionScreenName[twitter] ]; TwitterSessionHTTPClient[twitter_TwitterSession] := Part[twitter, 1]; TwitterSessionScreenName[twitter_TwitterSession] := Part[twitter, 2]; TwitterSessionUser[twitter_TwitterSession] := Part[twitter, 3]; TwitterSessionOpen[opts___?OptionQ] := Module[ {user, twitter, creds}, user = "User" /. {opts} /. {"User"->""}; twitter = TwitterSession[HTTPOpen[], user]; creds = TwitterSessionAuthorize[twitter]; If[Head[creds] =!= TwitterUser, HTTPClose[TwitterSessionHTTPClient[twitter]]; Return[$Failed] ]; If[StringLength[user] === 0, twitter[[2]] = TwitterUserScreenName[creds]]; AppendTo[twitter, creds] ]; TwitterSessionClose[twitter_TwitterSession] := HTTPClose[TwitterSessionHTTPClient[twitter]]; (* ::Input:: *) (*twitter=TwitterSessionOpen["User"->"ragfield"]*) (* ::Input:: *) (*TwitterSessionClose[twitter]*) TwitterSessionAuthorize[twitter_TwitterSession, opts___?OptionQ] := Module[ {}, If[HTTPAuthorize[TwitterSessionHTTPClient[twitter], "Server"->"twitter.com", "Port"->443, "User"->TwitterSessionScreenName[twitter], opts] =!= True, Return[$Canceled] ]; TwitterSessionCredentials[twitter] ]; (* ::Input:: *) (*TwitterSessionAuthorize[twitter]*) TwitterSessionCredentials[twitter_TwitterSession] := Module[ {res}, res = Quiet[ HTTPGet[TwitterSessionHTTPClient[twitter], "https://twitter.com/account/verify_credentials.xml"], {HTTP::e401} ]; If[res === $Failed, res]; res = Quiet@ImportString[res, "XML"]; If[res === $Failed, res]; TwitterUser[res[[2]]] ]; (* ::Input:: *) (*TwitterSessionCredentials[twitter]*) TwitterSessionAuthorizedQ[twitter_TwitterSession] := Module[ {user = TwitterSessionCredentials[twitter]}, (TwitterSessionScreenName[twitter] == TwitterUserScreenName[user]) ]; (* ::Input:: *) (*TwitterSessionAuthorizedQ[twitter]*) (* ::Input:: *) (*Import["https://twitter.com/account/verify_credentials.xml"]*) (* ::Subsection:: *) (*TwitterUser*) Format[user_TwitterUser, StandardForm] := StringForm[ "TwitterUser[<`1`>]", TwitterUserScreenName[user] ]; TwitterUser[XMLElement["user", _, elems_List]] := Module[ {rules= xmlElementRules /@ elems}, rules = rules /. { Rule[x:("id"|"statuses_count"| "friends_count"|"followers_count"| "favorites_count"), y_] :> Rule[x, ToExpression[y]], Rule[x:"protected", "true"] :> Rule[x, True], Rule[x:"protected", "false"] :> Rule[x, False], Rule["created_at", y_] :> Rule["created_at", utcToLocal[HTTPDateList[y]]] }; TwitterUser@@rules ]; (* ::Input:: *) (*user=TwitterSessionUser[twitter]*) TwitterUser[XMLElement["entry", _, elems_List]] := Module[ {rules = {}, res}, res = Cases[elems, XMLElement["name", _, {s_String}]:>s, \[Infinity]]; If[Length[res] > 0, res = StringCases[First[res], RegularExpression["(.*) \\((.*)\\)"]:>{"$1","$2"}]; If[Length[res] > 0, AppendTo[rules, "screen_name"->res[[1,1]]]; AppendTo[rules, "name"->res[[1,2]]] ]; ]; res = Cases[elems, XMLElement["link", Alternatives[ {___, "href"->s_, ___, "rel"->"image", ___}, {___, "rel"->"image", ___, "href"->s_, ___} ], _] :> s]; If[Length[res] > 0, AppendTo[rules, "profile_image_url"->First[res]]]; (* res = Cases[elems, XMLElement["title", _, {s_String}] :> s]; If[Length[res] > 0, AppendTo[rules, "text"->First[res]]]; res = Cases[elems, XMLElement["published", _, {s_String}] :> s]; If[Length[res] > 0, AppendTo[rules, "date"->utcToLocal[HTTPDateList[First[res]]] ]]; res = Cases[elems, XMLElement[ Alternatives[ "twitter:source", {"http://api.twitter.com/","source"} ], _, {s_String}] :> s]; If[Length[res] > 0, AppendTo[rules, "source"->First[res]]]; *) TwitterUser@@rules ]; TwitterUser[id_Integer] := Module[ {xml}, xml = Import["https://twitter.com/users/show.xml?user_id=" <> ToString[id]]; If[xml === $Failed, Return[$Failed]]; TwitterUser@First@Cases[xml, XMLElement["user", _, _], \[Infinity]] ]; (* ::Input:: *) (*TwitterUser[12920162]*) TwitterUser[screenName_String] := Module[ {xml}, xml = Import["https://twitter.com/users/show.xml?screen_name=" <> screenName, "XML"]; If[xml === $Failed, Return[$Failed]]; TwitterUser@First@Cases[xml, XMLElement["user", _, _], \[Infinity]] ]; (* ::Input:: *) (*TwitterUser["ragfield"]*) TwitterUserUpdate[user_TwitterUser] := Module[ {userid, screen, newuser}, userid = "id" /. List@@user /. {"id"->0}; If[userid =!= 0, newuser = TwitterUser[userid] ,(*else*) screen = "screen_name" /. List@@user /. {"screen_name"->""}; newuser = TwitterUser[screen] ]; TwitterUser@@Join[List@@newuser, List@@user] ] TwitterUserID[user_TwitterUser] := Module[ {id = "id" /. List@@user}, If[Head[id] === String, "id" /. List@@TwitterUserUpdate[user] /. "id"->0, id ] ]; (* ::Input:: *) (*TwitterUserID[user]*) TwitterUserName[user_TwitterUser] := ( "name" /. List@@user /. {"name"->""} ); (* ::Input:: *) (*TwitterUserName[user]//InputForm*) TwitterUserScreenName[user_TwitterUser] := ( "screen_name" /. List@@user /. {"screen_name"->""} ); (* ::Input:: *) (*TwitterUserScreenName[user]*) TwitterUserLocation[user_TwitterUser] := ( "location" /. List@@user /. {"location"->""} ); (* ::Input:: *) (*TwitterUserLocation[user]*) TwitterUserHomePage[user_TwitterUser] := ( "url" /. List@@user /. {"url"->""} ); (* ::Input:: *) (*TwitterUserHomePage[user]*) TwitterUserDescription[user_TwitterUser] := ( "description" /. List@@user /. {"description"->""} ); (* ::Input:: *) (*TwitterUserDescription[user]//InputForm*) TwitterUserProfilePage[user_TwitterUser] := StringJoin[ "http://twitter.com/", TwitterUserScreenName[user] ]; (* ::Input:: *) (*TwitterUserProfilePage[user]*) TwitterUserProfileImage[user_TwitterUser] := Import[TwitterUserProfileImageURL[user]]; TwitterUserProfileImageURL[user_TwitterUser] := ( "profile_image_url" /. List@@user /. { "profile_image_url"->"http://static.twitter.com/images/default_profile_normal.png" } ); (* ::Input:: *) (*TwitterUserProfileImage[user]*) TwitterUserStatusCount[user_TwitterUser] := ( "statuses_count" /. List@@user /. {"statuses_count"->0} ); (* ::Input:: *) (*TwitterUserStatusCount[user]*) TwitterUserFriendCount[user_TwitterUser] := ( "friends_count" /. List@@user /. {"friends_count"->0} ); (* ::Input:: *) (*TwitterUserFriendCount[user]*) TwitterUserFollowerCount[user_TwitterUser] := ( "followers_count" /. List@@user /. {"followers_count"->0} ); (* ::Input:: *) (*TwitterUserFollowerCount[user]*) TwitterUserFavoriteCount[user_TwitterUser] := ( "favorites_count" /. List@@user /. {"favorites_count"->0} ); (* ::Input:: *) (*TwitterUserFavoriteCount[user]*) TwitterUserProtectedQ[user_TwitterUser] := ( "protected" /. List@@user /. {"protected"->False} ); (* ::Input:: *) (*TwitterUserProtectedQ[user]*) TwitterUserDate[user_TwitterUser] := ( "created_at" /. List@@user /. {"created_at":>Date[]} ); (* ::Input:: *) (*TwitterUserDate[user]*) TwitterUserInfo[user_TwitterUser] := Row[{ Style["Name ", Bold], TwitterUserName[user], "\n", Style["Location ", Bold], TwitterUserLocation[user], "\n", Style["Web ", Bold], TwitterUserHomePage[user], "\n", Style["Bio ", Bold], TwitterUserDescription[user] }] (* ::Input:: *) (*TwitterUserInfo[user]*) TwitterUserUI[user_TwitterUser] := Hyperlink[ Column[{ Tooltip[ TwitterUserProfileImage[user], TwitterUserInfo[user] ], TwitterUserScreenName[user] }, Alignment->Center], TwitterUserProfilePage[user] ]; (* ::Input:: *) (*TwitterUserUI[user]*) (* ::Subsection:: *) (*TwitterStatus*) Format[status_TwitterStatus, StandardForm] := StringForm[ "TwitterStatus[<`1`: `2`>]", TwitterUserScreenName@TwitterStatusUser[status], TwitterStatusText[status] ]; (* ::Input:: *) (*status*) TwitterStatus[XMLElement["status", _, elems_List]] := Module[ {rules, users}, rules = Cases[elems, XMLElement[tag_String, _, {str_String}] :> Rule[tag, str]]; users = Cases[elems, XMLElement["user", _, _List]]; rules = rules /. { Rule["id", x_] :> Rule["id", ToExpression[x]], Rule["in_reply_to_status_id", x_] :> Rule["in_reply_to_status_id", ToExpression[x]], Rule["in_reply_to_user_id", x_] :> Rule["in_reply_to_user_id", ToExpression[x]], Rule["created_at", x_] :> Rule["created_at", utcToLocal[HTTPDateList[x]]], Rule["truncated", "true"] :> Rule["truncated", True], Rule["truncated", "false"] :> Rule["truncated", False], Rule["favorited", "true"] :> Rule["favorited", True], Rule["favorited", "false"] :> Rule["favorited", False] }; If[Length[users] =!= 0, rules = Append[rules, Rule["user", TwitterUser[First@users]]] ]; TwitterStatus@@rules ]; TwitterStatus[XMLElement["entry", attrs_, elems_List]] := Module[ {rules = {}, res}, res = Cases[elems, XMLElement["title", _, {s_String}] :> s]; If[Length[res] > 0, AppendTo[rules, "text"->First[res]]]; res = Cases[elems, XMLElement["published", _, {s_String}] :> s]; If[Length[res] > 0, AppendTo[rules, "created_at"->utcToLocal[HTTPDateList[First[res]]] ]]; res = Cases[elems, XMLElement["link", Alternatives[ {___, "href"->s_, ___, "rel"->"alternate", ___}, {___, "rel"->"alternate", ___, "href"->s_, ___} ], _] :> s]; If[Length[res] > 0, AppendTo[rules, "id" -> ToExpression[StringReplace[ First[res], RegularExpression[".*statuses/(.*)"] :> "$1" ]]]; (*AppendTo[rules, "user" -> TwitterUser[StringReplace[ First[res], RegularExpression[".*twitter.com/(.*FIXME)/statuses.*"] :> "$1" ]]];*) ]; res = Cases[elems, XMLElement[ Alternatives[ "twitter:source", {"http://api.twitter.com/","source"} ], _, {s_String}] :> s]; If[Length[res] > 0, AppendTo[rules, "source"->First[res]]]; AppendTo[rules, "user"->TwitterUser[XMLElement["entry", attrs, elems]]]; TwitterStatus@@rules ]; TwitterStatus[id_Integer] := Module[ {xml}, xml = Import["http://twitter.com/statuses/show/" <> ToString[id] <> ".xml"]; If[xml === $Failed, Return[$Failed]]; TwitterStatus@First@Cases[xml, XMLElement["status", _, _], \[Infinity]] ]; (* ::Input:: *) (*TwitterStatus[1533688829]*) TwitterStatusID[status_TwitterStatus] := ( "id" /. List@@status /. {"id"->0} ); (* ::Input:: *) (*TwitterStatusID[status]*) TwitterStatusUser[status_TwitterStatus] := ( "user" /. List@@status /. {"user"->TwitterUser[]} ) (* ::Input:: *) (*TwitterStatusUser[status]*) TwitterStatusText[status_TwitterStatus] := ( "text" /. List@@status /. {"text"->""} ); (* ::Input:: *) (*TwitterStatusText[status]*) TwitterStatusDate[status_TwitterStatus] := ( "created_at" /. List@@status /. {"created_at" :> Date[]} ); TwitterStatusDateString[status_TwitterStatus] := DateString[TwitterStatusDate[status]]; (* ::Input:: *) (*TwitterStatusDate[status]*) TwitterStatusPage[status_TwitterStatus] := TwitterStatusPage[ TwitterUserScreenName[TwitterStatusUser[status]], TwitterStatusID[status] ]; TwitterStatusPage[screenName_String, statusID_Integer] := StringJoin[ "http://twitter.com/", screenName, "/statuses/", ToString[statusID] ]; (* ::Input:: *) (*TwitterStatusPage[status]*) TwitterStatusSource[status_TwitterStatus] := Module[ {source = "source" /. List@@status /. {"source"->"web"}}, First@StringCases[source, { RegularExpression["(.*)"]:>Hyperlink["$2", "$1"], x__ :> x }] ]; (* ::Input:: *) (*TwitterStatusSource[status]*) TwitterStatusReplyID[status_TwitterStatus] := ( "in_reply_to_status_id" /. List@@status /. {"in_reply_to_status_id"->0} ); (* ::Input:: *) (*TwitterStatusReplyID[status]*) TwitterStatusReplyUserID[status_TwitterStatus] := ( "in_reply_to_user_id" /. List@@status /. {"in_reply_to_user_id"->0} ); (* ::Input:: *) (*TwitterStatusReplyUserID[status]*) TwitterStatusUI[status_TwitterStatus] := Module[ {user = TwitterStatusUser[status], replyID, replyUser}, replyID = TwitterStatusReplyID[status]; replyUser = If[replyID =!= 0, TwitterUserScreenName[ TwitterUser[TwitterStatusReplyUserID[status]]], "" ]; Panel@Style[Grid[{{ TwitterUserProfileImage[user], Column[{ Row[{ Hyperlink[ TwitterUserScreenName[user], TwitterUserProfilePage[user] ], ": ", TwitterStatusText[status] }], Row[{ Hyperlink[ TwitterStatusDateString[status], TwitterStatusPage[status] ], " from ", TwitterStatusSource[status], Sequence@@If[replyID === 0, {}, { " in reply to ", Hyperlink[replyUser, TwitterStatusPage[replyUser, replyID]] }] }] }, Dividers->{None, 2->Gray}] }}], "Text"] ]; (* ::Input:: *) (*TwitterStatusUI[status]*) twitterGetXML[url_String, opts___?OptionQ] := Module[ {twitter, client, closeClient = False, query, u, xml}, twitter = "Session" /. {opts}; client = If[Head[twitter] === String, "Client" /. {opts}, TwitterSessionHTTPClient[twitter] ]; If[Head[client] === String, client = HTTPOpen[]; closeClient = True; ]; u = URLQueryString[url, {opts} /. { Rule["Session", _] :> Sequence[], Rule["Page", rhs_] :> Rule["page", rhs], Rule["Since", rhs_] :> Rule["since_id", rhs], Rule["Results", rhs_] :> Rule["rpp", rhs] }]; If[$TwitterDebug, Print["getting XML from ", Hyperlink[u]]]; xml = HTTPGet[client, u]; If[closeClient, HTTPClose[client]]; If[xml === $Failed, Return[$Failed]]; If[$TwitterDebug, Print["importing ", ToString[ByteCount[xml]], " bytes of XML"]]; xml = ImportString[xml, "XML"]; If[xml === $Failed, Return[$Failed]]; xml ]; twitterAll[func_, url_String, opts___?OptionQ] := Module[ {xml, pageResults, allResults = {}, page = 0}, Monitor[ While[True, pageResults = func[ url, "Page"->(++page), opts ]; If[Length[pageResults] === 0, Break[]]; allResults = Join[allResults, pageResults]; ], StringJoin["Importing page ", ToString[page], " (", ToString[Length[allResults]], " results)"] ]; allResults ]; twitterGetStatuses[url_String, opts___?OptionQ] := Module[ {xml = twitterGetXML[url, opts]}, TwitterStatus /@ Cases[xml[[2]], XMLElement["status", _, _], \[Infinity]] ]; twitterAllStatuses[twitter_TwitterSession, url_String, user:(_Integer|_String), opts___?OptionQ] := twitterAll[ twitterGetStatuses, url, "Session"->twitter, If[Head[user]===String, "screen_name", "user_id"]->ToString[user], opts ]; twitterGetUsers[url_String, opts___?OptionQ] := Module[ {xml = twitterGetXML[url, opts]}, TwitterUser /@ Cases[xml[[2]], XMLElement["user", _, _], \[Infinity]] ]; twitterAllUsers[twitter_TwitterSession, url_String, user:(_Integer|_String), opts___?OptionQ] := twitterAll[ twitterGetUsers, url, "Session"->twitter, If[Head[user]===String, "screen_name", "user_id"]->ToString[user], opts ]; (* ::Input:: *) (*users=Twitter`Private`twitterAllUsers[twitter,"https://twitter.com/statuses/friends.xml","WolframResearch"];*) (* ::Input:: *) (*Length[users]*) (* ::Input:: *) (*users=Twitter`Private`twitterAllUsers[twitter,"https://twitter.com/statuses/followers.xml","WolframResearch"];*) (*Length[users]*) (* ::Subsubsection:: *) (*Set/Delete Status*) TwitterSetStatus[twitter_TwitterSession, status_] := Module[ {res, xml}, res = HTTPPost[TwitterSessionHTTPClient[twitter], "https://twitter.com/statuses/update.xml?status=" <> URLEncode[ToString[status]] ]; If[res === $Failed, Return[$Failed]]; xml = ImportString[res, "XML"]; TwitterStatus@First@Cases[xml, XMLElement["status", _, _], \[Infinity]] ]; (* ::Input:: *) (*newstatus=TwitterSetStatus[twitter,"testing... 1..."]*) TwitterReply[twitter_TwitterSession, status_TwitterStatus, reply_] := TwitterReply[twitter, TwitterStatusID[status], reply]; TwitterReply[twitter_TwitterSession, status_Integer, reply_] := Module[ {res}, res = HTTPPost[TwitterSessionHTTPClient[twitter], StringJoin[ "https://twitter.com/statuses/update.xml?", "in_reply_to_status_id=", ToString[status], "&", "status=", URLEncode[ToString[reply]] ]]; If[res === $Failed, Return[$Failed]]; xml = ImportString[res, "XML"]; TwitterStatus@First@Cases[xml, XMLElement["status", _, _], \[Infinity]] ]; TwitterDeleteStatus[twitter_TwitterSession, status_Integer] := Module[ {res, xml}, res = HTTPPost[TwitterSessionHTTPClient[twitter], "https://twitter.com/statuses/destroy/" <> ToString[status] <> ".xml" ]; If[res === $Failed, Return[$Failed]]; xml = ImportString[res, "XML"]; TwitterStatus@First@Cases[xml, XMLElement["status", _, _], \[Infinity]] ]; TwitterDeleteStatus[twitter_TwitterSession, status_TwitterStatus] := TwitterDeleteStatus[twitter, TwitterStatusID[status]]; (* ::Input:: *) (*TwitterDeleteStatus[twitter,newstatus]*) (* ::Subsubsection:: *) (*Public Timeline*) (* ::Text:: *) (*TwitterPublicTimeline[] := Module[*) (* {xml},*) (* xml = Import["http://twitter.com/statuses/public_timeline.xml", "XML"];*) (* If[xml === $Failed, Return[$Failed]];*) (* TwitterStatus /@ Cases[xml[[2]], XMLElement["status", _, _], \[Infinity]]*) (* ];*) TwitterPublicTimeline[opts___?OptionQ] := Module[ {xml}, xml = Import[ URLQueryString[ "https://twitter.com/statuses/public_timeline.xml", {opts}], "XML"]; If[xml === $Failed, Return[$Failed]]; TwitterStatus /@ Cases[xml[[2]], XMLElement["status", _, _], \[Infinity]] ]; (* ::Input:: *) (*statuses=TwitterPublicTimeline["Page"->3]*) (* ::Text:: *) (*TwitterPublicTimeline[sinceID_Integer] := Module[*) (* {xml},*) (* xml = Import[*) (* "http://twitter.com/statuses/public_timeline.xml?since_id=" <>*) (* ToString[sinceID], "XML"];*) (* If[xml === $Failed, Return[$Failed]];*) (* TwitterStatus /@ Cases[xml[[2]], XMLElement["status", _, _], \[Infinity]]*) (* ]; *) (* ::Text:: *) (*TwitterPublicTimeline[status_TwitterStatus] :=*) (* TwitterPublicTimeline[TwitterStatusID[status]];*) (* ::Text:: *) (*First@TwitterPublicTimeline[status] // InputForm*) (* ::Subsubsection:: *) (*Friends Timeline*) TwitterFriendsTimeline[twitter_TwitterSession, opts___?OptionQ] := twitterGetStatuses[ "https://twitter.com/statuses/friends_timeline.xml", "Session"->twitter, opts ]; (* ::Input:: *) (*TwitterFriendsTimeline[twitter,"Page"->2]*) (* ::Subsubsection:: *) (*User Timeline*) TwitterUserTimeline[twitter_TwitterSession, opts___?OptionQ] := twitterGetStatuses[ "https://twitter.com/statuses/user_timeline.xml", "Session"->twitter, opts ]; (* ::Input:: *) (*TwitterUserTimeline[twitter,"Page"->2]*) TwitterUserTimeline[user:(_Integer|_String), opts___?OptionQ] := twitterGetStatuses[ "https://twitter.com/statuses/user_timeline/" <> ToString[user] <> ".xml", opts ]; (* ::Input:: *) (*TwitterUserTimeline["melissa_raguet"]*) (* ::Input:: *) (*TwitterUserID[TwitterUser["melissa_raguet"]]*) (* ::Input:: *) (*TwitterUserTimeline[13140502,"Page"->2]*) TwitterUserTimeline[user_TwitterUser, opts___?OptionQ] := TwitterUserTimeline[TwitterUserID[user], opts]; TwitterUserAllTimeline[twitter_TwitterSession, opts___?OptionQ] := TwitterUserAllTimeline[twitter, TwitterUserID@TwitterSessionUser[twitter], opts]; TwitterUserAllTimeline[twitter_TwitterSession, user:(_Integer|_String), opts___?OptionQ] := twitterAllStatuses[ twitter, "https://twitter.com/statuses/user_timeline.xml", user, "count"->200, opts ]; TwitterUserAllTimeline[twitter_TwitterSession, user_TwitterUser, opts___?OptionQ] := TwitterUserAllTimeline[twitter, TwitterUserID[user], opts]; (* ::Subsubsection:: *) (*Replies*) TwitterReplies[twitter_TwitterSession, opts___?OptionQ] := twitterGetStatuses[ "https://twitter.com/statuses/replies.xml", "Session"->twitter, opts ]; (* ::Input:: *) (*TwitterReplies[twitter]*) (* ::Input:: *) (*TwitterReplies[twitter,"Page"->2]*) (* ::Input:: *) (*TwitterReplies[twitter,"Page"->10]*) TwitterAllReplies[twitter_TwitterSession, opts___?OptionQ] := twitterAllStatuses[ twitter, "https://twitter.com/statuses/replies.xml", TwitterUserID@TwitterSessionUser[twitter], "count"->200, opts ]; (* ::Subsubsection:: *) (*Friends*) TwitterFriends[twitter_TwitterSession, opts___?OptionQ] := twitterGetUsers[ "https://twitter.com/statuses/friends.xml", "Session"->twitter, opts ]; (* ::Input:: *) (*TwitterFriends[twitter]//Length*) TwitterFriends[twitter_TwitterSession, user:(_Integer|_String), opts___?OptionQ] := TwitterFriends[twitter, If[Head[user]===String, "screen_name", "user_id"]->ToString[user], opts ]; (* ::Input:: *) (*TwitterFriends[twitter,"melissa_raguet"]//Length*) (* ::Input:: *) (*TwitterFriends[twitter,12920162]//Length*) TwitterFriends[twitter_TwitterSession, user_TwitterUser, opts___?OptionQ] := TwitterFriends[twitter, TwitterUserID[user], opts]; (* ::Input:: *) (*TwitterFriends[twitter,user]//Length*) TwitterAllFriends[twitter_TwitterSession, opts___?OptionQ] := TwitterAllFriends[twitter, TwitterSessionScreenName[twitter], opts]; TwitterAllFriends[twitter_TwitterSession, user:(_Integer|_String), opts___?OptionQ] := twitterAllUsers[twitter, "https://twitter.com/statuses/friends.xml", user, opts]; TwitterAllFriends[twitter_TwitterSession, user_TwitterUser, opts___?OptionQ] := TwitterAllFriends[twitter, TwitterUserID[user], opts]; (* ::Input:: *) (*TwitterAllFriends[twitter]//Length*) (* ::Input:: *) (*TwitterAllFriends[twitter,"melissa_raguet"]//Length*) (* ::Subsubsection:: *) (*Followers*) TwitterFollowers[twitter_TwitterSession, opts___?OptionQ] := twitterGetUsers[ "https://twitter.com/statuses/followers.xml", "Session"->twitter, opts ]; (* ::Input:: *) (*TwitterFollowers[twitter]//Length*) TwitterFollowers[twitter_TwitterSession, user:(_Integer|_String), opts___?OptionQ] := TwitterFollowers[twitter, If[Head[user]===String, "screen_name", "user_id"]->ToString[user], opts ]; (* ::Input:: *) (*TwitterFollowers[twitter,"melissa_raguet"]//Length*) TwitterFollowers[twitter_TwitterSession, user_TwitterUser, opts___?OptionQ] := TwitterFollowers[twitter, TwitterUserID[user], opts]; (* ::Input:: *) (*TwitterFollowers[twitter,user]//Length*) (* ::Input:: *) (*TwitterFollowers[twitter,12920162]//Length*) TwitterAllFollowers[twitter_TwitterSession, opts___?OptionQ] := TwitterAllFollowers[twitter, TwitterSessionScreenName[twitter], opts]; TwitterAllFollowers[twitter_TwitterSession, user:(_Integer|_String), opts___?OptionQ] := twitterAllUsers[twitter, "https://twitter.com/statuses/followers.xml", user, opts]; TwitterAllFollowers[twitter_TwitterSession, user_TwitterUser, opts___?OptionQ] := TwitterAllFollowers[twitter, TwitterUserID[user], opts]; (* ::Input:: *) (*TwitterAllFollowers[twitter]//Length*) (* ::Input:: *) (*TwitterAllFollowers[twitter,"melissa_raguet"]//Length*) (* ::Subsubsection:: *) (*Search*) TwitterSearch[query_String, opts___?OptionQ] := Module[ {xml}, xml = twitterGetXML[ "http://search.twitter.com/search.atom", "q" -> URLEncode[query], opts ]; TwitterStatus /@ Cases[xml, XMLElement["entry", _, _], \[Infinity]] ]; (* ::Section:: *) (*Finalization*) End[]; (* `Private` *) EndPackage[]; (* Twitter` *)