Good news for Twitter and no so good for developers:
Today(2013-06-11), we(Twitter) are retiring API v1 and fully transitioning to API v1.1.
What does it all mean? This means that all old services are no longer available. Twitter switched to new ones with mandatory OAuth authentication. From now, to work with twitter services we must register new apps and use OAuth.
Also, it means that:
- Script from ““F# Weekly” under the hood” does not work. Twitterizer is a dead project and will not be updated up to Twitter API v1.1.
- Beautiful script from “A Twitter search client in 10 lines of code with F# and the JSON type provider” does not work, because it uses v1 service.
As I know, there are two alternatives available instead of Twitterizer:
- Tweetsharp (TweetSharp is a fast, clean wrapper around the Twitter API.)
- LINQ to Twitter (An open source 3rd party LINQ Provider for the Twitter micro-blogging service.)
I have chosen Tweetsharp because its API similar to Twitterizer. This is a new F# Weekly under the hood script:
#r "Newtonsoft.Json.dll"
#r "Hammock.ClientProfile.dll"
#r "TweetSharp.dll"
open TweetSharp
open System
open System.Net
open System.Text.RegularExpressions
let service = new TwitterService(_consumerKey, _consumerSecret)
service.AuthenticateWith(_accessToken, _accessTokenSecret)
let getTweets query =
let rec collect maxId =
let options = SearchOptions(Q = query, Count =Nullable(100), MaxId = Nullable(maxId),
Resulttype = Nullable(TwitterSearchResultType.Recent))
printfn "Loading %s under id %d" query maxId
let results = service.Search(options).Statuses |> Seq.toList
printfn "\t Loaded %d tweets" results.Length
if (results.Length = 0)
then List.empty
else
let lastTweet = results |> List.rev |> List.head
if (lastTweet.Id < maxId) then results |> List.append (collect (lastTweet.Id))
else results
collect (Int64.MaxValue) |> List.rev
let urlRegexp = Regex("http://([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?", RegexOptions.IgnoreCase);
let filterUniqLinks (tweets: TwitterStatus list) =
let hash = new System.Collections.Generic.HashSet();
tweets |> List.fold
(fun acc t ->
let mathces = urlRegexp.Matches(t.Text)
if (mathces.Count = 0) then acc
else let urls =
[0 .. (mathces.Count-1)]
|> List.map (fun i -> mathces.[i].Value)
|> List.filter (fun url -> not(hash.Contains(url)))
if (List.isEmpty urls) then acc
else urls |> List.iter(fun url -> hash.Add(url) |> ignore)
t :: acc)
[] |> List.rev
let tweets =
["#fsharp";"#fsharpx";"@dsyme";"#websharper";"@c4fsharp"]
|> List.map getTweets
|> List.concat
|> List.sortBy (fun t -> t.CreatedDate)
|> filterUniqLinks
let printTweetsInHtml filename (tweets: TwitterStatus list) =
let formatTweet (text:string) =
let matches = urlRegexp.Matches(text)
seq {0 .. (matches.Count-1)}
|> Seq.fold (
fun (t:string) i ->
let url = matches.[i].Value
t.Replace(url, (sprintf "<a href="\"%s\"" target="\"_blank\"">%s</a>" url url)))
text
let rows =
tweets
|> List.mapi (fun i t ->
let id = (tweets.Length - i)
let text = formatTweet(t.Text)
sprintf "</pre>
<table id="\"%d\"">
<tbody>
<tr>
<td rowspan="\"2\"" width="\"30\"">%d</td>
<td rowspan="\"2\"" width="\"80\""><a href="\"javascript:remove('%d')\"">Remove</a></td>
<td rowspan="\"2\""><a href="\"https://twitter.com/%s\"" target="\"_blank\""><img alt="" src="\"%s\"/" /></a></td>
<td><b>%s</b></td>
</tr>
<tr>
<td>Created : %s</td>
</tr>
</tbody>
</table>
<pre>
"
id id id t.Author.ScreenName t.Author.ProfileImageUrl text (t.CreatedDate.ToString()))
|> List.fold (fun s r -> s+" "+r) ""
let html = sprintf "<script type="text/javascript">// <![CDATA[
function remove(id){return (elem=document.getElementById(id)).parentNode.removeChild(elem);}
// ]]></script>%s" rows
System.IO.File.WriteAllText(filename, html)
printTweetsInHtml "d:\\tweets.html" tweets
Discover more from Sergey Tihon's Blog
Subscribe to get the latest posts sent to your email.
Thanks on your marvelous posting! I definitely enjoyed reading it, you could be a great author.
I will be sure to bookmark your blog and will eventually come back
in the foreseeable future. I want to encourage you to definitely continue
your great job, have a nice morning!