1 ' Tween - Client of Twitter
2 ' Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 ' (c) 2008-2011 Moz (@syo68k)
4 ' (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 ' (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 ' (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
9 ' This file is part of Tween.
11 ' This program is free software; you can redistribute it and/or modify it
12 ' under the terms of the GNU General Public License as published by the Free
13 ' Software Foundation; either version 3 of the License, or (at your option)
16 ' This program is distributed in the hope that it will be useful, but
17 ' WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 ' or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 ' You should have received a copy of the GNU General Public License along
22 ' with this program. If not, see <http://www.gnu.org/licenses/>, or write to
23 ' the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
24 ' Boston, MA 02110-1301, USA.
26 Imports System.Text.RegularExpressions
30 Private Shared _ShortUrlService() As String = { _
32 "http://tinyurl.com/", _
34 "http://snipurl.com/", _
35 "http://snurl.com/", _
37 "http://qurlyq.com/", _
38 "http://dwarfurl.com/", _
39 "http://icanhaz.com/", _
41 "http://urlenco.de/", _
43 "http://piurl.com/", _
44 "http://linkbee.com/", _
45 "http://traceurl.com/", _
48 "http://rubyurl.com/", _
49 "http://budurl.com/", _
51 "http://twitthis.com/", _
53 "http://tumblr.com/", _
54 "http://www.qurl.com/", _
60 "http://bctiny.com/", _
64 "http://bkite.com/", _
77 Private Shared _bitlyId As String = ""
78 Private Shared _bitlyKey As String = ""
79 Private Shared _isresolve As Boolean = True
81 Private Shared ReadOnly _lockObj As New Object
83 Public Shared WriteOnly Property BitlyId() As String
84 Set(ByVal value As String)
89 Public Shared WriteOnly Property BitlyKey() As String
90 Set(ByVal value As String)
95 Public Shared Property IsResolve As Boolean
99 Set(ByVal value As Boolean)
104 Public Shared Function Resolve(ByVal orgData As String) As String
106 Static urlCache As New Dictionary(Of String, String)
108 If urlCache.Count > 500 Then
109 urlCache.Clear() '定期的にリセット
113 Dim m As MatchCollection = Regex.Matches(orgData, "<a href=""(?<svc>http://.+?/)(?<path>[^""]+)""", RegexOptions.IgnoreCase)
114 Dim urlList As New List(Of String)
115 For Each orgUrlMatch As Match In m
116 Dim orgUrl As String = orgUrlMatch.Result("${svc}")
117 Dim orgUrlPath As String = orgUrlMatch.Result("${path}")
118 If Array.IndexOf(_ShortUrlService, orgUrl) > -1 AndAlso _
119 Not urlList.Contains(orgUrl + orgUrlPath) Then
121 urlList.Add(orgUrl + orgUrlPath)
125 For Each orgUrl As String In urlList
126 If urlCache.ContainsKey(orgUrl) Then
128 orgData = orgData.Replace("<a href=""" + orgUrl + """", "<a href=""" + urlCache(orgUrl) + """")
129 Catch ex As Exception
134 'urlとして生成できない場合があるらしい
135 'Dim urlstr As String = New Uri(urlEncodeMultibyteChar(orgUrl)).GetLeftPart(UriPartial.Path)
136 Dim retUrlStr As String = ""
137 Dim tmpurlStr As String = New Uri(urlEncodeMultibyteChar(orgUrl)).GetLeftPart(UriPartial.Path)
138 Dim httpVar As New HttpVarious
139 retUrlStr = urlEncodeMultibyteChar(httpVar.GetRedirectTo(tmpurlStr))
140 If retUrlStr.StartsWith("http") Then
141 retUrlStr = retUrlStr.Replace("""", "%22") 'ダブルコーテーションがあるとURL終端と判断されるため、これだけ再エンコード
142 orgData = orgData.Replace("<a href=""" + orgUrl + """", "<a href=""" + retUrlStr + """")
144 urlCache.Add(orgUrl, retUrlStr)
147 Catch ex As Exception
156 Public Shared Function Make(ByVal ConverterType As UrlConverter, ByVal SrcUrl As String) As String
157 Dim src As String = urlEncodeMultibyteChar(SrcUrl)
158 Dim param As New Dictionary(Of String, String)
159 Dim content As String = ""
161 For Each svc As String In _ShortUrlService
162 If SrcUrl.StartsWith(svc) Then
163 Return "Can't convert"
168 If SrcUrl.StartsWith("http://nico.ms/") Then Return "Can't convert"
170 SrcUrl = HttpUtility.UrlEncode(SrcUrl)
172 Select Case ConverterType
173 Case UrlConverter.TinyUrl 'tinyurl
174 If SrcUrl.StartsWith("http") Then
175 If "http://tinyurl.com/xxxxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
176 ' 明らかに長くなると推測できる場合は圧縮しない
180 If Not (New HttpVarious).PostData("http://tinyurl.com/api-create.php?url=" + SrcUrl, Nothing, content) Then
181 Return "Can't convert"
184 If Not content.StartsWith("http://tinyurl.com/") Then
185 Return "Can't convert"
187 Case UrlConverter.Isgd
188 If SrcUrl.StartsWith("http") Then
189 If "http://is.gd/xxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
190 ' 明らかに長くなると推測できる場合は圧縮しない
194 If Not (New HttpVarious).PostData("http://is.gd/api.php?longurl=" + SrcUrl, Nothing, content) Then
195 Return "Can't convert"
198 If Not content.StartsWith("http://is.gd/") Then
199 Return "Can't convert"
201 Case UrlConverter.Twurl
202 If SrcUrl.StartsWith("http") Then
203 If "http://twurl.nl/xxxxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
204 ' 明らかに長くなると推測できる場合は圧縮しない
208 param.Add("link[url]", SrcUrl)
209 If Not (New HttpVarious).PostData("http://tweetburner.com/links", param, content) Then
210 Return "Can't convert"
213 If Not content.StartsWith("http://twurl.nl/") Then
214 Return "Can't convert"
216 Case UrlConverter.Bitly, UrlConverter.Jmp
217 Const BitlyLogin As String = "tweenapi"
218 Const BitlyApiKey As String = "R_c5ee0e30bdfff88723c4457cc331886b"
219 Const BitlyApiVersion As String = "3"
220 If SrcUrl.StartsWith("http") Then
221 If "http://bit.ly/xxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
222 ' 明らかに長くなると推測できる場合は圧縮しない
226 Dim req As String = ""
227 req = "http://api.bitly.com/v" + BitlyApiVersion + "/shorten?"
228 req += "login=" + BitlyLogin + _
229 "&apiKey=" + BitlyApiKey + _
232 If _bitlyId <> "" AndAlso _bitlyKey <> "" Then req += "&x_login=" + _bitlyId + "&x_apiKey=" & _bitlyKey
233 If ConverterType = UrlConverter.Jmp Then req += "&domain=j.mp"
234 If Not (New HttpVarious).GetData(req, Nothing, content) Then
235 Return "Can't convert"
238 Case UrlConverter.Uxnu
239 If SrcUrl.StartsWith("http") Then
240 If "http://ux.nx/xxxxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
241 ' 明らかに長くなると推測できる場合は圧縮しない
245 If Not (New HttpVarious).PostData("http://ux.nu/api/short?url=" + SrcUrl + "&format=plain", Nothing, content) Then
246 Return "Can't convert"
249 If Not content.StartsWith("http://ux.nu/") Then
250 Return "Can't convert"
254 Dim ch As Char() = {ControlChars.Cr, ControlChars.Lf}
255 content = content.TrimEnd(ch)
256 If src.Length < content.Length Then content = src ' 圧縮の結果逆に長くなった場合は圧縮前のURLを返す