1 ' Tween - Client of Twitter
2 ' Copyright (c) 2007-2010 kiri_feather (@kiri_feather) <kiri_feather@gmail.com>
3 ' (c) 2008-2010 Moz (@syo68k) <http://iddy.jp/profile/moz/>
4 ' (c) 2008-2010 takeshik (@takeshik) <http://www.takeshik.org/>
7 ' This file is part of Tween.
9 ' This program is free software; you can redistribute it and/or modify it
10 ' under the terms of the GNU General Public License as published by the Free
11 ' Software Foundation; either version 3 of the License, or (at your option)
14 ' This program is distributed in the hope that it will be useful, but
15 ' WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 ' or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 ' You should have received a copy of the GNU General Public License along
20 ' with this program. If not, see <http://www.gnu.org/licenses/>, or write to
21 ' the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
22 ' Boston, MA 02110-1301, USA.
27 Imports System.Threading
29 Imports System.Text.RegularExpressions
30 Imports System.Globalization
31 Imports System.Diagnostics
35 Delegate Sub GetIconImageDelegate(ByVal post As PostClass)
36 'Delegate Function GetTimelineDelegate(ByVal page As Integer, _
37 ' ByVal read As Boolean, _
38 ' ByRef endPage As Integer, _
39 ' ByVal gType As WORKERTYPE, _
40 ' ByRef getDM As Boolean) As String
41 'Delegate Function GetDirectMessageDelegate(ByVal page As Integer, _
42 ' ByVal read As Boolean, _
43 ' ByVal endPage As Integer, _
44 ' ByVal gType As WORKERTYPE) As String
45 Private ReadOnly LockObj As New Object
46 'Private GetTmSemaphore As New Threading.Semaphore(8, 8)
48 'Private follower As New List(Of String)
49 Private followerId As New List(Of Long)
50 'Private tmpFollower As New List(Of String)
52 Private _followersCount As Integer = 0
53 Private _friendsCount As Integer = 0
54 Private _statusesCount As Integer = 0
55 Private _location As String = ""
56 Private _bio As String = ""
57 'Private _useSsl As Boolean = True
58 Private _protocol As String = "https://"
59 Private _bitlyId As String = ""
60 Private _bitlyKey As String = ""
63 Private _uid As String
64 'Private _pwd As String
65 'Private _proxyType As ProxyType
66 'Private _proxyAddress As String
67 'Private _proxyPort As Integer
68 'Private _proxyUser As String
69 'Private _proxyPassword As String
71 'Private _nextThreshold As Integer
72 'Private _nextPages As Integer
74 Private _iconSz As Integer
75 Private _getIcon As Boolean
76 Private _lIcon As ImageList
77 Private _dIcon As Dictionary(Of String, Image)
79 Private _tinyUrlResolve As Boolean
80 Private _restrictFavCheck As Boolean
81 'Private _useAPI As Boolean
83 Private _hubServer As String
84 'Private _defaultTimeOut As Integer ' MySocketクラスへ渡すタイムアウト待ち時間(秒単位 ミリ秒への換算はMySocketクラス側で行う)
85 Private _countApi As Integer
86 Private _countApiReply As Integer
87 'Private _usePostMethod As Boolean
88 'Private _ApiMethod As MySocket.REQ_TYPE
89 Private _readOwnPost As Boolean
90 Private _hashList As New List(Of String)
93 'Private _authKey As String 'StatusUpdate、発言削除で使用
94 'Private _authKeyDM As String 'DM送信、DM削除で使用
95 Private _infoTwitter As String = ""
96 'Private _dmCount As Integer
97 'Private _getDm As Boolean
98 Private _remainCountApi As Integer = -1
100 Private _ShortUrlService() As String = { _
101 "http://tinyurl.com/", _
103 "http://snipurl.com/", _
104 "http://snurl.com/", _
106 "http://qurlyq.com/", _
107 "http://dwarfurl.com/", _
108 "http://icanhaz.com/", _
110 "http://urlenco.de/", _
112 "http://piurl.com/", _
113 "http://linkbee.com/", _
114 "http://traceurl.com/", _
115 "http://twurl.nl/", _
117 "http://rubyurl.com/", _
118 "http://budurl.com/", _
120 "http://twitthis.com/", _
122 "http://tumblr.com/", _
123 "http://www.qurl.com/", _
124 "http://digg.com/", _
126 "http://ustre.am/", _
128 "http://airme.us/", _
129 "http://qurl.com/", _
130 "http://bctiny.com/", _
134 "http://bkite.com/" _
137 Private Const _apiHost As String = "api."
138 Private Const _baseUrlStr As String = "twitter.com"
139 'Private Const _loginPath As String = "/sessions"
140 'Private Const _homePath As String = "/home"
141 'Private Const _replyPath As String = "/replies"
142 'Private Const _DMPathRcv As String = "/inbox"
143 'Private Const _DMPathSnt As String = "/sent"
144 Private Const _DMDestroyPath As String = "/1/direct_messages/destroy/"
145 Private Const _StDestroyPath As String = "/1/statuses/destroy/"
146 Private Const _postRetweetPath As String = "/1/statuses/retweet/"
147 Private Const _uidHeader As String = "session[username_or_email]="
148 Private Const _pwdHeader As String = "session[password]="
149 Private Const _pageQry As String = "?page="
150 Private Const _cursorQry As String = "?cursor="
151 Private Const _statusHeader As String = "status="
152 Private Const _statusUpdatePathAPI As String = "/1/statuses/update.xml"
153 'Private Const _linkToOld As String = "class=""section_links"" rel=""prev"""
154 Private Const _postFavAddPath As String = "/1/favorites/create/"
155 Private Const _postFavRemovePath As String = "/1/favorites/destroy/"
156 'Private Const _authKeyHeader As String = "authenticity_token="
157 'Private Const _parseLink1 As String = "<a href="""
158 'Private Const _parseLink2 As String = """>"
159 'Private Const _parseLink3 As String = "</a>"
160 Private Const _GetFollowers As String = "/1/statuses/followers.xml"
161 Private Const _ShowStatus As String = "/1/statuses/show/"
162 Private Const _rateLimitStatus As String = "/1/account/rate_limit_status.xml"
163 Private Const FOLLOWER_PATH As String = "/1/followers/ids.xml"
164 Private Const RECEIVE_PATH As String = "/1/direct_messages.xml"
165 Private Const SENT_PATH As String = "/1/direct_messages/sent.xml"
166 Private Const COUNT_QUERY As String = "count="
167 Private Const FAV_PATH As String = "/1/favorites.xml"
168 Private Const PATH_FRIENDSHIP As String = "/1/friendships/show.xml?source_screen_name="
169 Private Const QUERY_TARGET As String = "&target_screen_name="
170 Private Const FRIEND_PATH As String = "/1/statuses/home_timeline.xml"
171 Private Const REPLY_PATH As String = "/1/statuses/mentions.xml"
172 Private Const PATH_FOLLOW As String = "/1/friendships/create.xml?screen_name="
173 Private Const PATH_REMOVE As String = "/1/friendships/destroy.xml?screen_name="
178 '''OAuthのアクセストークン取得先URI
180 Private Const AccessTokenUrl As String = "http://twitter.com/oauth/access_token"
183 '''OAuthのリクエストトークン取得先URI
185 Private Const RequestTokenUrl As String = "http://twitter.com/oauth/request_token"
188 '''OAuthのユーザー認証用ページURI
191 '''クエリ「oauth_token=リクエストトークン」を付加して、このURIをブラウザで開く。ユーザーが承認操作を行うとPINコードが表示される。
193 Private Const AuthorizeUrl As String = "http://twitter.com/oauth/authorize"
196 'Private Const wedataUrl As String = "http://wedata.net/databases/Tween/items.json"
198 Private op As New Outputz
199 'max_idで古い発言を取得するために保持(lists分は個別タブで管理)
200 Private minHomeTimeline As Long = Long.MaxValue
201 Private minMentions As Long = Long.MaxValue
202 Private minDirectmessage As Long = Long.MaxValue
203 Private minDirectmessageSent As Long = Long.MaxValue
204 Private minFavorites As Long = Long.MaxValue
206 Private twCon As New HttpTwitter
208 Public Function Authenticate(ByVal username As String, ByVal password As String) As Boolean
209 Dim rslt As Boolean = twCon.AuthUserAndPass(username, password)
211 _uid = twCon.AuthenticatedUsername.ToLower
216 Public Sub ClearAuthInfo()
217 twCon.ClearAuthInfo()
220 Public Sub Initialize(ByVal token As String, ByVal tokenSecret As String, ByVal username As String)
222 twCon.Initialize(token, tokenSecret, username)
223 _uid = username.ToLower
226 Public Sub Initialize(ByVal username As String, ByVal password As String)
228 twCon.Initialize(username, password)
229 _uid = username.ToLower
232 'Private Function SignIn() As String
233 ' If _endingFlag Then Return ""
236 ' Dim account As String = ""
237 ' Static skipCount As Integer = 0
240 ' If _signed Then Return ""
241 ' If Twitter.AccountState <> ACCOUNT_STATE.Valid AndAlso skipCount < 10 Then
243 ' Return "SignIn -> Check Username/Password in setting."
250 ' MySocket.ResetCookie()
252 ' Dim resStatus As String = ""
253 ' Dim resMsg As String = ""
255 ' '設定によらずログイン処理はhttps固定
256 ' resMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + "/login", resStatus, MySocket.REQ_TYPE.ReqGET), String)
257 ' If resMsg.Length = 0 Then
258 ' 'Twitter.AccountState = ACCOUNT_STATE.Invalid
259 ' Return "SignIn -> " + resStatus
261 ' Dim authToken As String = ""
262 ' Dim rg As New Regex("authenticity_token"" type=""hidden"" value=""(?<auth>[a-z0-9]+)""")
263 ' Dim m As Match = rg.Match(resMsg)
265 ' authToken = m.Result("${auth}")
267 ' Return "SignIn -> Can't get token."
270 ' account = _authKeyHeader + authToken + "&" + _uidHeader + _uid + "&" + _pwdHeader + HttpUtility.UrlEncode(_pwd) + "&" + "remember_me=1"
273 ' resMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _loginPath, resStatus, MySocket.REQ_TYPE.ReqPOST, account), String)
274 ' If resStatus.StartsWith("OK") Then
275 ' 'OK (username/passwordが合致しない)
276 ' Dim msg As String = resStatus
277 ' If resMsg.Contains("Wrong Username/Email and password combination.") Then
278 ' msg = "Wrong Username or password."
280 ' '未知の応答(May be required Chapta)
281 ' msg = "Wrong Username or password. Try from web."
283 ' Twitter.AccountState = ACCOUNT_STATE.Invalid
284 ' Return "SignIn Failed -> " + msg
285 ' ElseIf resMsg.Contains("https://twitter.com/account/locked") Then '302 FOUND
286 ' Dim msg As String = "You account is Locked Out."
287 ' Twitter.AccountState = ACCOUNT_STATE.Invalid
288 ' Return "SignIn Failed -> " + msg
289 ' ElseIf resMsg.Contains("https://twitter.com:443/") Then '302 FOUND
291 ' ElseIf resMsg.Contains("https://twitter.com/") OrElse _
292 ' resMsg.Contains("http://twitter.com/") Then '302 FOUND
294 ' ElseIf resStatus.StartsWith("Err:") Then
296 ' Return "SignIn Failed"
298 ' '応答がOK でありサインインできていない場合の未知の応答
299 ' 'TraceOut(True, "SignIn Failed." + vbCrLf + "resStatus:" + resStatus + vbCrLf + "resMsg:" + vbCrLf + resMsg)
300 ' Twitter.AccountState = ACCOUNT_STATE.Invalid
301 ' Return "SignIn Failed -> " + "Unknown problems."
303 ' Twitter.AccountState = ACCOUNT_STATE.Valid
309 'Public Function GetTimeline(ByVal page As Integer, _
310 ' ByVal read As Boolean, _
311 ' ByRef endPage As Integer, _
312 ' ByVal gType As WORKERTYPE, _
313 ' ByRef getDM As Boolean) As String
315 ' If endPage = 0 Then
317 ' Dim epage As Integer = page
318 ' GetTmSemaphore.WaitOne()
319 ' Dim trslt As String = ""
320 ' trslt = GetTimelineThread(page, read, epage, gType, getDM)
321 ' If trslt.Length > 0 Then Return trslt
323 ' If epage < page OrElse gType = WORKERTYPE.Reply Then Return ""
326 ' '起動時モード or 通常モードの読み込み継続 -> 複数ページ同時取得
327 ' Dim num As Integer = endPage - page
328 ' Dim ar(num) As IAsyncResult
329 ' Dim dlgt(num) As GetTimelineDelegate
331 ' For idx As Integer = 0 To num
332 ' dlgt(idx) = New GetTimelineDelegate(AddressOf GetTimelineThread)
333 ' GetTmSemaphore.WaitOne()
334 ' ar(idx) = dlgt(idx).BeginInvoke(page + idx, read, endPage + idx, gType, getDM, Nothing, Nothing)
336 ' Dim rslt As String = ""
337 ' For idx As Integer = 0 To num
338 ' Dim epage As Integer = 0
339 ' Dim dm As Boolean = False
340 ' Dim trslt As String = ""
342 ' trslt = dlgt(idx).EndInvoke(epage, dm, ar(idx))
343 ' Catch ex As Exception
344 ' '最後までendinvoke回す(ゾンビ化回避)
345 ' ex.Data("IsTerminatePermission") = False
347 ' rslt = "GetTimelineErr"
349 ' If trslt.Length > 0 AndAlso rslt.Length = 0 Then rslt = trslt
350 ' If dm Then getDM = True
355 ' Private Function GetTimelineThread(ByVal page As Integer, _
356 ' ByVal read As Boolean, _
357 ' ByRef endPage As Integer, _
358 ' ByVal gType As WORKERTYPE, _
359 ' ByRef getDM As Boolean) As String
361 ' If _endingFlag Then Return ""
363 ' Dim retMsg As String = ""
364 ' Dim resStatus As String = ""
366 ' Static redirectToTimeline As String = ""
367 ' Static redirectToReply As String = ""
369 ' If _signed = False Then
371 ' If retMsg.Length > 0 Then
376 ' If _endingFlag Then Return ""
379 ' Dim pageQuery As String
384 ' pageQuery = _pageQry + page.ToString
387 ' If gType = WORKERTYPE.Timeline Then
388 ' retMsg = DirectCast(CreateSocket.GetWebResponse(_protocol + _hubServer + _homePath + pageQuery, resStatus, MySocket.REQ_TYPE.ReqGetApp), String)
390 ' retMsg = DirectCast(CreateSocket.GetWebResponse(_protocol + _hubServer + _replyPath + pageQuery, resStatus, MySocket.REQ_TYPE.ReqGetApp), String)
393 ' If retMsg.Length = 0 Then
398 ' ' tr 要素の class 属性を消去
399 ' retMsg = Regex.Replace(retMsg, "(?<tagStart><li)(?<cls>\s+class=""[^""]+""\s+)", "${tagStart} ")
402 ' ' Dim idx As Integer = retMsg.IndexOf(_removeClass, StringComparison.Ordinal)
403 ' ' If idx = -1 Then Exit Do
404 ' ' Dim idx2 As Integer = retMsg.IndexOf("""", idx + _removeClass.Length, StringComparison.Ordinal) - idx + 1 - 3
405 ' ' If idx2 > 0 Then retMsg = retMsg.Remove(idx + 3, idx2)
406 ' ' Catch ex As Exception
408 ' ' TraceOut("TM-Remove: " + retMsg)
409 ' ' Return "GetTimeline -> Err: Can't parse data."
413 ' If _endingFlag Then Return ""
416 ' Dim strSepTmp As String
417 ' If gType = WORKERTYPE.Timeline Then
418 ' strSepTmp = _splitPostRecent
420 ' strSepTmp = _splitPost
423 ' Dim pos1 As Integer
424 ' Dim pos2 As Integer
426 ' pos1 = retMsg.IndexOf(strSepTmp, StringComparison.Ordinal)
430 ' Return "GetTimeline -> Err: tweets count is 0."
433 ' Dim strSep() As String = {strSepTmp}
434 ' Dim posts() As String = retMsg.Split(strSep, StringSplitOptions.RemoveEmptyEntries)
435 ' Dim intCnt As Integer = 0
436 ' Dim listCnt As Integer = 0
438 ' listCnt = TabInformations.GetInstance.ItemCount
440 ' Dim dlgt(20) As GetIconImageDelegate
441 ' Dim ar(20) As IAsyncResult
442 ' Dim arIdx As Integer = -1
446 ' For Each strPost As String In posts
450 ' If page = 1 And gType = WORKERTYPE.Timeline Then
452 ' 'pos1 = strPost.IndexOf(_getSiv, 0)
454 ' ' pos2 = strPost.IndexOf(_getSivTo, pos1 + _getSiv.Length)
455 ' ' If pos2 > -1 Then
456 ' ' _authSiv = strPost.Substring(pos1 + _getSiv.Length, pos2 - pos1 - _getSiv.Length)
460 ' ' Return "GetTimeline -> Err: Can't get Siv."
465 ' ' Return "GetTimeline -> Err: Can't get Siv."
469 ' If GetAuthKey(retMsg) < 0 Then
471 ' Return "GetTimeline -> Err: Can't get auth token."
475 ' pos1 = retMsg.IndexOf(_getInfoTwitter, StringComparison.Ordinal)
477 ' pos2 = retMsg.IndexOf(_getInfoTwitterTo, pos1, StringComparison.Ordinal)
479 ' _infoTwitter = retMsg.Substring(pos1 + _getInfoTwitter.Length, pos2 - pos1 - _getInfoTwitter.Length)
489 ' Dim post As New PostClass
491 ' pos1 = strPost.IndexOf("</ol>")
493 ' strPost = strPost.Substring(0, pos1)
499 ' pos2 = strPost.IndexOf(_statusIdTo, 0, StringComparison.Ordinal)
500 ' post.Id = Long.Parse(HttpUtility.HtmlDecode(strPost.Substring(0, pos2)))
501 ' Catch ex As Exception
503 ' TraceOut("TM-ID:" + strPost)
504 ' Return "GetTimeline -> Err: Can't get ID."
508 ' pos1 = strPost.IndexOf(_parseName, pos2, StringComparison.Ordinal)
509 ' pos2 = strPost.IndexOf(_parseNameTo, pos1, StringComparison.Ordinal)
510 ' post.Name = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseName.Length, pos2 - pos1 - _parseName.Length))
511 ' Catch ex As Exception
513 ' TraceOut("TM-Name:" + strPost)
514 ' Return "GetTimeline -> Err: Can't get Name."
518 ' If strPost.IndexOf("twitter.com/images/heart.png", pos2, StringComparison.Ordinal) > -1 Then
519 ' post.Nickname = post.Name
522 ' pos1 = strPost.IndexOf(_parseNick, pos2, StringComparison.Ordinal)
523 ' pos2 = strPost.IndexOf(_parseNickTo, pos1 + _parseNick.Length, StringComparison.Ordinal)
524 ' post.Nickname = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseNick.Length, pos2 - pos1 - _parseNick.Length))
525 ' Catch ex As Exception
527 ' TraceOut("TM-Nick:" + strPost)
528 ' Return "GetTimeline -> Err: Can't get Nick."
534 ' If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
537 ' Dim orgData As String = ""
539 ' If strPost.IndexOf("<form action=""/status/update"" id=""heartForm", 0, StringComparison.Ordinal) > -1 Then
541 ' pos1 = strPost.IndexOf("<strong>", 0, StringComparison.Ordinal)
542 ' pos2 = strPost.IndexOf("</strong>", pos1, StringComparison.Ordinal)
543 ' orgData = strPost.Substring(pos1 + 8, pos2 - pos1 - 8)
544 ' Catch ex As Exception
546 ' TraceOut("TM-VBody:" + strPost)
547 ' Return "GetTimeline -> Err: Can't get Valentine body."
554 ' pos1 = strPost.IndexOf(_parseImg, pos2, StringComparison.Ordinal)
555 ' pos2 = strPost.IndexOf(_parseImgTo, pos1 + _parseImg.Length, StringComparison.Ordinal)
556 ' post.ImageUrl = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseImg.Length, pos2 - pos1 - _parseImg.Length))
557 ' Catch ex As Exception
559 ' TraceOut("TM-Img:" + strPost)
560 ' Return "GetTimeline -> Err: Can't get ImagePath."
564 ' If strPost.IndexOf(_isProtect, pos2, StringComparison.Ordinal) > -1 Then
565 ' post.IsProtect = True
569 ' If strPost.IndexOf("class=""big-retweet-icon""") > -1 Then
570 ' rg = New Regex("class=""shared-content"".+<a href=""/(?<name>[a-zA-Z0-9_]+)""")
571 ' m = rg.Match(strPost)
573 ' post.RetweetedBy = m.Result("${name}")
575 ' post.RetweetedBy = ""
577 ' rg = New Regex("&in_reply_to_status_id=(?<id>[0-9]+)&in_reply_to=")
578 ' m = rg.Match(strPost)
580 ' post.RetweetedId = Long.Parse(m.Result("${id}"))
582 ' post.RetweetedId = 0
587 ' pos1 = strPost.IndexOf(_parseMsg1, pos2, StringComparison.Ordinal)
591 ' If strPost.IndexOf("<div id=""doyouheart", pos2, StringComparison.Ordinal) > -1 Then
593 ' orgData += " <3 you! Do you <3 "
594 ' pos1 = strPost.IndexOf("<a href", pos2, StringComparison.Ordinal)
595 ' pos2 = strPost.IndexOf("?", pos1, StringComparison.Ordinal)
596 ' orgData += strPost.Substring(pos1, pos2 - pos1 + 1)
598 ' pos1 = strPost.IndexOf(_parseProtectMsg1, pos2, StringComparison.Ordinal)
601 ' orgData += " <3 's "
602 ' pos1 = strPost.IndexOf("<a href", pos2, StringComparison.Ordinal)
604 ' pos2 = strPost.IndexOf("!", pos1, StringComparison.Ordinal)
605 ' orgData += strPost.Substring(pos1, pos2 - pos1 + 1)
609 ' pos2 = strPost.IndexOf(_parseProtectMsg2, pos1, StringComparison.Ordinal)
610 ' orgData = strPost.Substring(pos1 + _parseProtectMsg1.Length, pos2 - pos1 - _parseProtectMsg1.Length).Trim()
613 ' Catch ex As Exception
615 ' TraceOut("TM-VBody2:" + strPost)
616 ' Return "GetTimeline -> Err: Can't get Valentine body2."
621 ' pos2 = strPost.IndexOf(_parseMsg2, pos1, StringComparison.Ordinal)
622 ' orgData = strPost.Substring(pos1 + _parseMsg1.Length, pos2 - pos1 - _parseMsg1.Length).Trim()
623 ' Catch ex As Exception
625 ' TraceOut("TM-Body:" + strPost)
626 ' Return "GetTimeline -> Err: Can't get body."
630 ' ' orgData = Regex.Replace(orgData, "<a href=""https://twitter\.com/" + post.Name + "/status/[0-9]+"">\.\.\.</a>$", "")
633 ' orgData = orgData.Replace("<3", "♡")
637 ' orgData = PreProcessUrl(orgData)
639 ' '短縮URL解決処理(orgData書き換え)
640 ' orgData = ShortUrlResolve(orgData)
643 ' post.OriginalData = AdjustHtml(orgData)
645 ' '単純テキストの取り出し(リンクタグ除去)
647 ' post.Data = GetPlainText(orgData)
648 ' Catch ex As Exception
650 ' TraceOut("TM-Link:" + strPost)
651 ' Return "GetTimeline -> Err: Can't parse links."
655 ' Dim ImgTag As New Regex("<img src=.*?/>", RegexOptions.IgnoreCase)
656 ' If ImgTag.IsMatch(post.Data) Then post.Data = ImgTag.Replace(post.Data, "<img>")
661 ' pos1 = strPost.IndexOf(_parseDate, pos2, StringComparison.Ordinal)
663 ' pos2 = strPost.IndexOf(_parseDateTo, pos1 + _parseDate.Length, StringComparison.Ordinal)
664 ' post.PDate = DateTime.ParseExact(strPost.Substring(pos1 + _parseDate.Length, pos2 - pos1 - _parseDate.Length), "ddd MMM dd HH':'mm':'ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, Globalization.DateTimeStyles.None)
668 ' Catch ex As Exception
670 ' TraceOut("TM-Date:" + strPost)
671 ' Return "GetTimeline -> Err: Can't get date."
674 ' '取得できなくなったため暫定対応(2/26)
680 ' 'ToDo: _parseSourceFromを正規表現へ。wedataからの取得へ変更(次版より)
681 ' rg = New Regex("<span>.+>(?<name>.+)</a>.*</span>")
682 ' m = rg.Match(strPost)
684 ' post.Source = m.Result("${name}")
686 ' post.Source = "Web"
689 ' ' pos1 = strPost.IndexOf(_parseSourceFrom, pos2, StringComparison.Ordinal)
690 ' ' If pos1 = -1 Then pos1 = strPost.IndexOf(_parseSourceFrom2, pos2, StringComparison.Ordinal)
691 ' ' If pos1 > -1 Then
692 ' ' pos1 = strPost.IndexOf(_parseSource2, pos1 + 19, StringComparison.Ordinal)
693 ' ' pos2 = strPost.IndexOf(_parseSourceTo, pos1 + 2, StringComparison.Ordinal)
694 ' ' post.Source = HttpUtility.HtmlDecode(strPost.Substring(pos1 + 2, pos2 - pos1 - 2))
696 ' ' post.Source = "Web"
698 ' 'Catch ex As Exception
700 ' ' TraceOut("TM-Src:" + strPost)
701 ' ' Return "GetTimeline -> Err: Can't get src."
704 ' 'Get Reply(in_reply_to_user/id)
705 ' 'ToDo: _isReplyEngを正規表現へ。wedataからの取得へ変更(次版より)
706 ' rg = New Regex("<a href=""https?:\/\/twitter\.com\/(?<name>[a-zA-Z0-9_]+)\/status\/(?<id>[0-9]+)"">(in reply to )*\k<name>")
707 ' m = rg.Match(strPost)
709 ' post.InReplyToUser = m.Result("${name}")
710 ' post.InReplyToId = Long.Parse(m.Result("${id}"))
711 ' post.IsReply = post.InReplyToUser.Equals(_uid, StringComparison.OrdinalIgnoreCase)
715 ' rg = New Regex("@<a [^>]*href=""\/(?<1>[a-zA-Z0-9_]+)[^a-zA-Z0-9_]")
716 ' m = rg.Match(orgData)
718 ' post.ReplyToList.Add(m.Groups(1).Value.ToLower())
721 ' If Not post.IsReply Then post.IsReply = post.ReplyToList.Contains(_uid)
723 ' If gType = WORKERTYPE.Reply Then post.IsReply = True
726 ' If strPost.IndexOf("class=""fav-action fav""") > -1 Then
731 ' 'pos1 = strPost.IndexOf(_parseStar, pos2, StringComparison.Ordinal)
734 ' ' pos2 = strPost.IndexOf(_parseStarTo, pos1 + _parseStar.Length, StringComparison.Ordinal)
735 ' ' If strPost.Substring(pos1 + _parseStar.Length, pos2 - pos1 - _parseStar.Length) = _parseStarEmpty Then
736 ' ' post.IsFav = False
738 ' ' post.IsFav = True
740 ' ' Catch ex As Exception
742 ' ' TraceOut("TM-Fav:" + strPost)
743 ' ' Return "GetTimeline -> Err: Can't get fav status."
746 ' ' post.IsFav = False
749 ' If _endingFlag Then Return ""
751 ' post.IsMe = post.Name.Equals(_uid, StringComparison.OrdinalIgnoreCase)
753 ' If follower.Count > 1 Then
754 ' post.IsOwl = Not follower.Contains(post.Name.ToLower())
760 ' If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
763 ' dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
764 ' ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
769 ' If intCnt = posts.Length AndAlso gType = WORKERTYPE.Timeline AndAlso page = 1 Then
770 ' pos1 = strPost.IndexOf(_parseDMcountFrom, pos2, StringComparison.Ordinal)
773 ' pos2 = strPost.IndexOf(_parseDMcountTo, pos1 + _parseDMcountFrom.Length, StringComparison.Ordinal)
774 ' Dim dmCnt As Integer = Integer.Parse(strPost.Substring(pos1 + _parseDMcountFrom.Length, pos2 - pos1 - _parseDMcountFrom.Length))
775 ' If dmCnt > _dmCount Then
779 ' Catch ex As Exception
780 ' Return "GetTimeline -> Err: Can't get DM count."
787 ' For i As Integer = 0 To arIdx
789 ' dlgt(i).EndInvoke(ar(i))
790 ' Catch ex As Exception
791 ' '最後までendinvoke回す(ゾンビ化回避)
792 ' ex.Data("IsTerminatePermission") = False
798 ' If page = 1 AndAlso (TabInformations.GetInstance.ItemCount - listCnt) >= _nextThreshold Then
799 ' '新着が閾値の件数以上なら、次のページも念のため読み込み
800 ' endPage = _nextPages + 1
806 ' GetTmSemaphore.Release()
810 ' Public Function GetDirectMessage(ByVal page As Integer, _
811 ' ByVal read As Boolean, _
812 ' ByVal endPage As Integer, _
813 ' ByVal gType As WORKERTYPE) As String
815 ' If endPage = 0 Then
820 ' Dim num As Integer = endPage - page
821 ' Dim ar(num) As IAsyncResult
822 ' Dim dlgt(num) As GetDirectMessageDelegate
824 ' For idx As Integer = 0 To num
825 ' gType = WORKERTYPE.DirectMessegeRcv
826 ' dlgt(idx) = New GetDirectMessageDelegate(AddressOf GetDirectMessageThread)
827 ' GetTmSemaphore.WaitOne()
828 ' ar(idx) = dlgt(idx).BeginInvoke(page + idx, read, endPage + idx, gType, Nothing, Nothing)
830 ' Dim rslt As String = ""
831 ' For idx As Integer = 0 To num
832 ' Dim trslt As String = ""
834 ' trslt = dlgt(idx).EndInvoke(ar(idx))
835 ' Catch ex As Exception
836 ' '最後までendinvoke回す(ゾンビ化回避)
837 ' ex.Data("IsTerminatePermission") = False
839 ' rslt = "GetDirectMessageErr"
841 ' If trslt.Length > 0 AndAlso rslt.Length = 0 Then rslt = trslt
843 ' For idx As Integer = 0 To num
844 ' gType = WORKERTYPE.DirectMessegeSnt
845 ' dlgt(idx) = New GetDirectMessageDelegate(AddressOf GetDirectMessageThread)
846 ' GetTmSemaphore.WaitOne()
847 ' ar(idx) = dlgt(idx).BeginInvoke(page + idx, read, endPage + idx, gType, Nothing, Nothing)
849 ' For idx As Integer = 0 To num
850 ' Dim trslt As String = ""
852 ' trslt = dlgt(idx).EndInvoke(ar(idx))
853 ' Catch ex As Exception
854 ' '最後までendinvoke回す(ゾンビ化回避)
855 ' ex.Data("IsTerminatePermission") = False
857 ' rslt = "GetDirectMessageErr"
859 ' If trslt.Length > 0 AndAlso rslt.Length = 0 Then rslt = trslt
864 ' Private Function GetDirectMessageThread(ByVal page As Integer, _
865 ' ByVal read As Boolean, _
866 ' ByVal endPage As Integer, _
867 ' ByVal gType As WORKERTYPE) As String
869 ' If _endingFlag Then Return ""
871 ' Dim retMsg As String = ""
872 ' Dim resStatus As String = ""
874 ' Static redirectToDmRcv As String = ""
875 ' Static redirectToDmSnd As String = ""
879 ' If _signed = False Then
881 ' If retMsg.Length > 0 Then
886 ' If _endingFlag Then Return ""
889 ' Dim pageQuery As String = _pageQry + page.ToString
890 ' If gType = WORKERTYPE.DirectMessegeRcv Then
891 ' retMsg = DirectCast(CreateSocket.GetWebResponse(_protocol + _hubServer + _DMPathRcv + pageQuery, resStatus, MySocket.REQ_TYPE.ReqGetApp), String)
893 ' retMsg = DirectCast(CreateSocket.GetWebResponse(_protocol + _hubServer + _DMPathSnt + pageQuery, resStatus, MySocket.REQ_TYPE.ReqGetApp), String)
896 ' If retMsg.Length = 0 Then
901 ' ' tr 要素の class 属性を消去
902 ' retMsg = Regex.Replace(retMsg, "(?<tagStart><li)(?<cls>\s+class=""[^""]+""\s+)", "${tagStart} ")
905 ' ' Dim idx As Integer = retMsg.IndexOf(_removeClass, StringComparison.Ordinal)
906 ' ' If idx = -1 Then Exit Do
907 ' ' Dim idx2 As Integer = retMsg.IndexOf("""", idx + _removeClass.Length, StringComparison.Ordinal) - idx + 1 - 3
908 ' ' If idx2 > 0 Then retMsg = retMsg.Remove(idx + 3, idx2)
909 ' ' Catch ex As Exception
911 ' ' TraceOut("DM-Remove: " + retMsg)
912 ' ' Return "GetDm -> Err: Can't parse data."
916 ' If _endingFlag Then Return ""
919 ' 'If GetAuthKeyDM(retMsg) < 0 Then
921 ' ' Return "GetDirectMessage -> Err: Busy(1)"
924 ' Dim pos1 As Integer
925 ' Dim pos2 As Integer
928 ' pos1 = retMsg.IndexOf(_splitDM, StringComparison.Ordinal)
930 ' '0件(メッセージなし。エラーの場合もありうるが判別できないので正常として戻す)
934 ' Dim strSep() As String = {_splitDM}
935 ' Dim posts() As String = retMsg.Split(strSep, StringSplitOptions.RemoveEmptyEntries)
936 ' Dim intCnt As Integer = 0 'カウンタ
937 ' 'Dim listCnt As Integer = 0
939 ' ' listCnt = TabInformations.GetInstance.ItemCount
941 ' Dim dlgt(20) As GetIconImageDelegate
942 ' Dim ar(20) As IAsyncResult
943 ' Dim arIdx As Integer = -1
945 ' For Each strPost As String In posts
948 ' If intCnt > 1 Then '1件目はヘッダなので無視
949 ' 'Dim lItem As New MyListItem
950 ' Dim post As New PostClass()
952 ' pos1 = strPost.IndexOf("</ol>")
954 ' strPost = strPost.Substring(0, pos1)
960 ' pos2 = strPost.IndexOf("""", 0, StringComparison.Ordinal)
961 ' post.Id = Long.Parse(HttpUtility.HtmlDecode(strPost.Substring(0, pos2)))
962 ' Catch ex As Exception
964 ' TraceOut("DM-ID:" + strPost)
965 ' Return "GetDirectMessage -> Err: Can't get ID"
970 ' pos1 = strPost.IndexOf(_parseName, pos2, StringComparison.Ordinal)
971 ' pos2 = strPost.IndexOf(_parseNameTo, pos1, StringComparison.Ordinal)
972 ' post.Name = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseName.Length, pos2 - pos1 - _parseName.Length))
973 ' Catch ex As Exception
975 ' TraceOut("DM-Name:" + strPost)
976 ' Return "GetDirectMessage -> Err: Can't get Name"
981 ' pos1 = strPost.IndexOf(_parseNick, pos2, StringComparison.Ordinal)
982 ' pos2 = strPost.IndexOf(_parseNickTo, pos1 + _parseNick.Length, StringComparison.Ordinal)
983 ' post.Nickname = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseNick.Length, pos2 - pos1 - _parseNick.Length))
984 ' Catch ex As Exception
986 ' TraceOut("DM-Nick:" + strPost)
987 ' Return "GetDirectMessage -> Err: Can't get Nick."
991 ' If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
996 ' pos1 = strPost.IndexOf(_parseImg, pos2, StringComparison.Ordinal)
997 ' pos2 = strPost.IndexOf(_parseImgTo, pos1 + _parseImg.Length, StringComparison.Ordinal)
998 ' post.ImageUrl = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseImg.Length, pos2 - pos1 - _parseImg.Length))
999 ' Catch ex As Exception
1001 ' TraceOut("DM-Img:" + strPost)
1002 ' Return "GetDirectMessage -> Err: Can't get ImagePath"
1007 ' pos1 = strPost.IndexOf(_isProtect, pos2, StringComparison.Ordinal)
1008 ' If pos1 > -1 Then post.IsProtect = True
1009 ' Catch ex As Exception
1011 ' TraceOut("DM-Protect:" + strPost)
1012 ' Return "GetDirectMessage -> Err: Can't get Protect"
1015 ' Dim orgData As String = ""
1019 ' pos1 = strPost.IndexOf(_parseDM1, pos2, StringComparison.Ordinal)
1021 ' pos2 = strPost.IndexOf(_parseDM2, pos1, StringComparison.Ordinal)
1022 ' orgData = strPost.Substring(pos1 + _parseDM1.Length, pos2 - pos1 - _parseDM1.Length).Trim()
1024 ' pos1 = strPost.IndexOf(_parseDM11, pos2, StringComparison.Ordinal)
1025 ' pos2 = strPost.IndexOf(_parseDM2, pos1, StringComparison.Ordinal)
1026 ' orgData = strPost.Substring(pos1 + _parseDM11.Length, pos2 - pos1 - _parseDM11.Length).Trim()
1028 ' 'orgData = Regex.Replace(orgData, "<a href=""https://twitter\.com/" + post.Name + "/status/[0-9]+"">\.\.\.</a>$", "")
1029 ' orgData = orgData.Replace("<3", "♡")
1030 ' Catch ex As Exception
1032 ' TraceOut("DM-Body:" + strPost)
1033 ' Return "GetDirectMessage -> Err: Can't get body"
1036 ' 'URL前処理(IDNデコードなど)
1037 ' orgData = PreProcessUrl(orgData)
1039 ' '短縮URL解決処理(orgData書き換え)
1040 ' orgData = ShortUrlResolve(orgData)
1043 ' post.OriginalData = AdjustHtml(orgData)
1045 ' '単純テキストの取り出し(リンクタグ除去)
1047 ' post.Data = GetPlainText(orgData)
1048 ' Catch ex As Exception
1050 ' TraceOut("DM-Link:" + strPost)
1051 ' Return "GetDirectMessage -> Err: Can't parse links"
1057 ' pos1 = strPost.IndexOf(_parseDate, pos2, StringComparison.Ordinal)
1059 ' pos2 = strPost.IndexOf(_parseDateTo, pos1 + _parseDate.Length, StringComparison.Ordinal)
1060 ' post.PDate = DateTime.ParseExact(strPost.Substring(pos1 + _parseDate.Length, pos2 - pos1 - _parseDate.Length), "ddd MMM dd HH':'mm':'ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, Globalization.DateTimeStyles.None)
1062 ' post.PDate = Now()
1064 ' Catch ex As Exception
1066 ' TraceOut("DM-Date:" + strPost)
1067 ' Return "GetDirectMessage -> Err: Can't get date."
1070 ' '取得できなくなったため暫定対応(2/26)
1071 ' post.PDate = Now()
1075 ' 'pos1 = strPost.IndexOf(_parseStar, pos2)
1076 ' 'pos2 = strPost.IndexOf("""", pos1 + _parseStar.Length)
1077 ' 'If strPost.Substring(pos1 + _parseStar.Length, pos2 - pos1 - _parseStar.Length) = "empty" Then
1078 ' ' lItem.Fav = False
1080 ' ' lItem.Fav = True
1082 ' post.IsFav = False
1085 ' If _endingFlag Then Return ""
1088 ' If gType = WORKERTYPE.DirectMessegeRcv Then
1089 ' post.IsOwl = False
1094 ' post.IsRead = read
1099 ' dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
1100 ' ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
1104 ' For i As Integer = 0 To arIdx
1106 ' dlgt(i).EndInvoke(ar(i))
1107 ' Catch ex As Exception
1108 ' ex.Data("IsTerminatePermission") = False
1116 ' GetTmSemaphore.Release()
1120 ' Public Function GetFavorites(ByVal page As Integer, _
1121 ' ByVal read As Boolean, _
1122 ' ByRef endPage As Integer, _
1123 ' ByVal gType As WORKERTYPE, _
1124 ' ByRef getDM As Boolean) As String
1126 ' GetTmSemaphore.WaitOne()
1128 ' If _endingFlag Then Return ""
1130 ' Dim retMsg As String = ""
1131 ' Dim resStatus As String = ""
1133 ' Static redirectToFav As String = ""
1134 ' Const FAV_PATH As String = "/favorites"
1136 ' If _signed = False Then
1138 ' If retMsg.Length > 0 Then
1143 ' If _endingFlag Then Return ""
1146 ' Dim pageQuery As String
1151 ' pageQuery = _pageQry + page.ToString
1154 ' retMsg = DirectCast(CreateSocket.GetWebResponse(_protocol + _hubServer + FAV_PATH + pageQuery, resStatus, MySocket.REQ_TYPE.ReqGetApp), String)
1156 ' If retMsg.Length = 0 Then
1161 ' ' tr 要素の class 属性を消去
1162 ' retMsg = Regex.Replace(retMsg, "(?<tagStart><li)(?<cls>\s+class=""[^""]+""\s+)", "${tagStart} ")
1165 ' ' Dim idx As Integer = retMsg.IndexOf(_removeClass, StringComparison.Ordinal)
1166 ' ' If idx = -1 Then Exit Do
1167 ' ' Dim idx2 As Integer = retMsg.IndexOf("""", idx + _removeClass.Length, StringComparison.Ordinal) - idx + 1 - 3
1168 ' ' If idx2 > 0 Then retMsg = retMsg.Remove(idx + 3, idx2)
1169 ' ' Catch ex As Exception
1171 ' ' TraceOut("GetFav-Remove: " + retMsg)
1172 ' ' Return "GetFav -> Err: Can't parse data."
1176 ' If _endingFlag Then Return ""
1179 ' Dim strSepTmp As String
1180 ' strSepTmp = _splitPostRecent
1182 ' Dim pos1 As Integer
1183 ' Dim pos2 As Integer
1185 ' pos1 = retMsg.IndexOf(strSepTmp, StringComparison.Ordinal)
1189 ' Return "GetTimeline -> Err: tweets count is 0."
1192 ' Dim strSep() As String = {strSepTmp}
1193 ' Dim posts() As String = retMsg.Split(strSep, StringSplitOptions.RemoveEmptyEntries)
1194 ' Dim intCnt As Integer = 0
1195 ' 'Dim listCnt As Integer = 0
1197 ' ' listCnt = TabInformations.GetInstance.ItemCount
1199 ' Dim dlgt(20) As GetIconImageDelegate
1200 ' Dim ar(20) As IAsyncResult
1201 ' Dim arIdx As Integer = -1
1205 ' For Each strPost As String In posts
1208 ' If intCnt = 1 Then
1212 ' Dim post As New PostClass
1214 ' pos1 = strPost.IndexOf("</ol>")
1216 ' strPost = strPost.Substring(0, pos1)
1222 ' pos2 = strPost.IndexOf(_statusIdTo, 0, StringComparison.Ordinal)
1223 ' post.Id = Long.Parse(HttpUtility.HtmlDecode(strPost.Substring(0, pos2)))
1224 ' Catch ex As Exception
1226 ' TraceOut("TM-ID:" + strPost)
1227 ' Return "GetTimeline -> Err: Can't get ID."
1231 ' pos1 = strPost.IndexOf(_parseName, pos2, StringComparison.Ordinal)
1232 ' pos2 = strPost.IndexOf(_parseNameTo, pos1, StringComparison.Ordinal)
1233 ' post.Name = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseName.Length, pos2 - pos1 - _parseName.Length))
1234 ' Catch ex As Exception
1236 ' TraceOut("TM-Name:" + strPost)
1237 ' Return "GetTimeline -> Err: Can't get Name."
1241 ' If strPost.IndexOf("twitter.com/images/heart.png", pos2, StringComparison.Ordinal) > -1 Then
1242 ' post.Nickname = post.Name
1245 ' pos1 = strPost.IndexOf(_parseNick, pos2, StringComparison.Ordinal)
1246 ' pos2 = strPost.IndexOf(_parseNickTo, pos1 + _parseNick.Length, StringComparison.Ordinal)
1247 ' post.Nickname = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseNick.Length, pos2 - pos1 - _parseNick.Length))
1248 ' Catch ex As Exception
1250 ' TraceOut("TM-Nick:" + strPost)
1251 ' Return "GetTimeline -> Err: Can't get Nick."
1257 ' ' If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
1260 ' Dim orgData As String = ""
1262 ' If strPost.IndexOf("<form action=""/status/update"" id=""heartForm", 0, StringComparison.Ordinal) > -1 Then
1264 ' pos1 = strPost.IndexOf("<strong>", 0, StringComparison.Ordinal)
1265 ' pos2 = strPost.IndexOf("</strong>", pos1, StringComparison.Ordinal)
1266 ' orgData = strPost.Substring(pos1 + 8, pos2 - pos1 - 8)
1267 ' Catch ex As Exception
1269 ' TraceOut("TM-VBody:" + strPost)
1270 ' Return "GetTimeline -> Err: Can't get Valentine body."
1277 ' pos1 = strPost.IndexOf(_parseImg, pos2, StringComparison.Ordinal)
1278 ' pos2 = strPost.IndexOf(_parseImgTo, pos1 + _parseImg.Length, StringComparison.Ordinal)
1279 ' post.ImageUrl = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseImg.Length, pos2 - pos1 - _parseImg.Length))
1280 ' Catch ex As Exception
1282 ' TraceOut("TM-Img:" + strPost)
1283 ' Return "GetTimeline -> Err: Can't get ImagePath."
1287 ' If strPost.IndexOf(_isProtect, pos2, StringComparison.Ordinal) > -1 Then
1288 ' post.IsProtect = True
1292 ' If strPost.IndexOf("class=""big-retweet-icon""") > -1 Then
1293 ' rg = New Regex("class=""shared-content"".+<a href=""/(?<name>[a-zA-Z0-9_]+)""")
1294 ' m = rg.Match(strPost)
1296 ' post.RetweetedBy = m.Result("${name}")
1298 ' post.RetweetedBy = ""
1300 ' rg = New Regex("&in_reply_to_status_id=(?<id>[0-9]+)&in_reply_to=")
1301 ' m = rg.Match(strPost)
1303 ' post.RetweetedId = Long.Parse(m.Result("${id}"))
1305 ' post.RetweetedId = 0
1310 ' pos1 = strPost.IndexOf(_parseMsg1, pos2, StringComparison.Ordinal)
1314 ' If strPost.IndexOf("<div id=""doyouheart", pos2, StringComparison.Ordinal) > -1 Then
1316 ' orgData += " <3 you! Do you <3 "
1317 ' pos1 = strPost.IndexOf("<a href", pos2, StringComparison.Ordinal)
1318 ' pos2 = strPost.IndexOf("?", pos1, StringComparison.Ordinal)
1319 ' orgData += strPost.Substring(pos1, pos2 - pos1 + 1)
1321 ' pos1 = strPost.IndexOf(_parseProtectMsg1, pos2, StringComparison.Ordinal)
1324 ' orgData += " <3 's "
1325 ' pos1 = strPost.IndexOf("<a href", pos2, StringComparison.Ordinal)
1327 ' pos2 = strPost.IndexOf("!", pos1, StringComparison.Ordinal)
1328 ' orgData += strPost.Substring(pos1, pos2 - pos1 + 1)
1332 ' pos2 = strPost.IndexOf(_parseProtectMsg2, pos1, StringComparison.Ordinal)
1333 ' orgData = strPost.Substring(pos1 + _parseProtectMsg1.Length, pos2 - pos1 - _parseProtectMsg1.Length).Trim()
1336 ' Catch ex As Exception
1338 ' TraceOut("TM-VBody2:" + strPost)
1339 ' Return "GetTimeline -> Err: Can't get Valentine body2."
1344 ' pos2 = strPost.IndexOf(_parseMsg2, pos1, StringComparison.Ordinal)
1345 ' orgData = strPost.Substring(pos1 + _parseMsg1.Length, pos2 - pos1 - _parseMsg1.Length).Trim()
1346 ' Catch ex As Exception
1348 ' TraceOut("TM-Body:" + strPost)
1349 ' Return "GetTimeline -> Err: Can't get body."
1353 ' ' orgData = Regex.Replace(orgData, "<a href=""https://twitter\.com/" + post.Name + "/status/[0-9]+"">\.\.\.</a>$", "")
1356 ' orgData = orgData.Replace("<3", "♡")
1359 ' 'URL前処理(IDNデコードなど)
1360 ' orgData = PreProcessUrl(orgData)
1362 ' '短縮URL解決処理(orgData書き換え)
1363 ' orgData = ShortUrlResolve(orgData)
1366 ' post.OriginalData = AdjustHtml(orgData)
1368 ' '単純テキストの取り出し(リンクタグ除去)
1370 ' post.Data = GetPlainText(orgData)
1371 ' Catch ex As Exception
1373 ' TraceOut("TM-Link:" + strPost)
1374 ' Return "GetTimeline -> Err: Can't parse links."
1377 ' ' Imageタグ除去(ハロウィン)
1378 ' Dim ImgTag As New Regex("<img src=.*?/>", RegexOptions.IgnoreCase)
1379 ' If ImgTag.IsMatch(post.Data) Then post.Data = ImgTag.Replace(post.Data, "<img>")
1384 ' pos1 = strPost.IndexOf(_parseDate, pos2, StringComparison.Ordinal)
1386 ' pos2 = strPost.IndexOf(_parseDateTo, pos1 + _parseDate.Length, StringComparison.Ordinal)
1387 ' post.PDate = DateTime.ParseExact(strPost.Substring(pos1 + _parseDate.Length, pos2 - pos1 - _parseDate.Length), "ddd MMM dd HH':'mm':'ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, Globalization.DateTimeStyles.None)
1389 ' post.PDate = Now()
1391 ' Catch ex As Exception
1393 ' TraceOut("TM-Date:" + strPost)
1394 ' Return "GetTimeline -> Err: Can't get date."
1397 ' '取得できなくなったため暫定対応(2/26)
1398 ' post.PDate = Now()
1403 ' 'ToDo: _parseSourceFromを正規表現へ。wedataからの取得へ変更(次版より)
1404 ' rg = New Regex("<span>.+>(?<name>.+)</a>.*</span>")
1405 ' m = rg.Match(strPost)
1407 ' post.Source = m.Result("${name}")
1409 ' post.Source = "Web"
1412 ' ' pos1 = strPost.IndexOf(_parseSourceFrom, pos2, StringComparison.Ordinal)
1413 ' ' If pos1 = -1 Then pos1 = strPost.IndexOf(_parseSourceFrom2, pos2, StringComparison.Ordinal)
1414 ' ' If pos1 > -1 Then
1415 ' ' pos1 = strPost.IndexOf(_parseSource2, pos1 + 19, StringComparison.Ordinal)
1416 ' ' pos2 = strPost.IndexOf(_parseSourceTo, pos1 + 2, StringComparison.Ordinal)
1417 ' ' post.Source = HttpUtility.HtmlDecode(strPost.Substring(pos1 + 2, pos2 - pos1 - 2))
1419 ' ' post.Source = "Web"
1421 ' 'Catch ex As Exception
1423 ' ' TraceOut("TM-Src:" + strPost)
1424 ' ' Return "GetTimeline -> Err: Can't get src."
1427 ' 'Get Reply(in_reply_to_user/id)
1428 ' 'ToDo: _isReplyEngを正規表現へ。wedataからの取得へ変更(次版より)
1429 ' rg = New Regex("<a href=""https?:\/\/twitter\.com\/(?<name>[a-zA-Z0-9_]+)\/status\/(?<id>[0-9]+)"">(in reply to )*\k<name>")
1430 ' m = rg.Match(strPost)
1432 ' post.InReplyToUser = m.Result("${name}")
1433 ' post.InReplyToId = Long.Parse(m.Result("${id}"))
1434 ' post.IsReply = post.InReplyToUser.Equals(_uid, StringComparison.OrdinalIgnoreCase)
1438 ' rg = New Regex("@<a [^>]*href=""\/(?<1>[a-zA-Z0-9_]+)[^a-zA-Z0-9_]")
1439 ' m = rg.Match(orgData)
1441 ' post.ReplyToList.Add(m.Groups(1).Value.ToLower())
1444 ' If Not post.IsReply Then post.IsReply = post.ReplyToList.Contains(_uid)
1449 ' If _endingFlag Then Return ""
1451 ' post.IsMe = post.Name.Equals(_uid, StringComparison.OrdinalIgnoreCase)
1453 ' If follower.Count > 1 Then
1454 ' post.IsOwl = Not follower.Contains(post.Name.ToLower())
1456 ' post.IsOwl = False
1459 ' post.IsRead = read
1462 ' dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
1463 ' ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
1469 ' For i As Integer = 0 To arIdx
1471 ' dlgt(i).EndInvoke(ar(i))
1472 ' Catch ex As Exception
1473 ' '最後までendinvoke回す(ゾンビ化回避)
1474 ' ex.Data("IsTerminatePermission") = False
1481 ' GetTmSemaphore.Release()
1485 Private Function PreProcessUrl(ByVal orgData As String) As String
1486 Dim posl1 As Integer
1487 Dim posl2 As Integer = 0
1488 Dim IDNConveter As IdnMapping = New IdnMapping()
1489 Dim href As String = "<a href="""
1492 If orgData.IndexOf(href, posl2, StringComparison.Ordinal) > -1 Then
1493 Dim urlStr As String = ""
1495 posl1 = orgData.IndexOf(href, posl2, StringComparison.Ordinal)
1496 posl1 += href.Length
1497 posl2 = orgData.IndexOf("""", posl1, StringComparison.Ordinal)
1498 urlStr = orgData.Substring(posl1, posl2 - posl1)
1500 If Not urlStr.StartsWith("http://") AndAlso Not urlStr.StartsWith("https://") AndAlso Not urlStr.StartsWith("ftp://") Then
1504 Dim replacedUrl As String = IDNDecode(urlStr)
1505 If replacedUrl Is Nothing Then Continue Do
1506 If replacedUrl = urlStr Then Continue Do
1508 orgData = orgData.Replace("<a href=""" + urlStr, "<a href=""" + replacedUrl)
1517 ' Private Function doShortUrlResolve(ByRef orgData As String) As Boolean
1518 ' Dim replaced As Boolean = False
1519 ' For Each _svc As String In _ShortUrlService
1520 ' Dim svc As String = _svc
1521 ' Dim posl1 As Integer
1522 ' Dim posl2 As Integer = 0
1525 ' If orgData.IndexOf("<a href=""" + svc, posl2, StringComparison.Ordinal) > -1 Then
1526 ' Dim urlStr As String = ""
1528 ' posl1 = orgData.IndexOf("<a href=""" + svc, posl2, StringComparison.Ordinal)
1529 ' posl1 = orgData.IndexOf(svc, posl1, StringComparison.Ordinal)
1530 ' posl2 = orgData.IndexOf("""", posl1, StringComparison.Ordinal)
1531 ' urlStr = New Uri(urlEncodeMultibyteChar(orgData.Substring(posl1, posl2 - posl1))).GetLeftPart(UriPartial.Path)
1532 ' Dim Response As String = ""
1533 ' Dim retUrlStr As String = ""
1534 ' Dim tmpurlStr As String = urlStr
1535 ' Dim SchemeAndDomain As Regex = New Regex("http://.+?/+?")
1536 ' Dim tmpSchemeAndDomain As String = ""
1537 ' For i As Integer = 0 To 4 'とりあえず5回試す
1538 ' retUrlStr = urlEncodeMultibyteChar(DirectCast(CreateSocket.GetWebResponse(tmpurlStr, Response, MySocket.REQ_TYPE.ReqGETForwardTo), String))
1539 ' If retUrlStr.Length > 0 Then
1540 ' ' 転送先URLが返された (まだ転送されるかもしれないので返値を引数にしてもう一度)
1541 ' ' 取得試行回数オーバーの場合は取得結果を転送先とする
1542 ' Dim scd As Match = SchemeAndDomain.Match(retUrlStr)
1543 ' If scd.Success AndAlso scd.Value <> svc Then
1546 ' tmpurlStr = retUrlStr
1550 ' If tmpurlStr <> urlStr Then
1551 ' '少なくとも一度以上転送されている (前回の結果を転送先とする)
1552 ' retUrlStr = tmpurlStr
1560 ' If retUrlStr.Length > 0 Then
1561 ' If Not retUrlStr.StartsWith("http") Then
1562 ' If retUrlStr.StartsWith("/") Then
1563 ' retUrlStr = urlEncodeMultibyteChar(svc + retUrlStr.Substring(1))
1564 ' ElseIf retUrlStr.StartsWith("data:") Then
1567 ' retUrlStr = urlEncodeMultibyteChar(retUrlStr.Insert(0, svc))
1570 ' retUrlStr = urlEncodeMultibyteChar(retUrlStr)
1572 ' orgData = orgData.Replace("<a href=""" + urlStr, "<a href=""" + retUrlStr)
1573 ' posl2 = 0 '置換した場合は頭から再探索(複数同時置換での例外対応)
1576 ' Catch ex As Exception
1578 ' 'Return "GetTimeline -> Err: Can't get tinyurl."
1589 ' Private Sub doShortUrlResolve(ByRef orgData As String)
1590 ' 'Dim replaced As Boolean = False
1591 ' 'Dim svc As String
1592 ' 'Dim posl1 As Integer
1593 ' 'Dim posl2 As Integer = 0
1594 ' Static urlCache As New Specialized.StringDictionary()
1595 ' If urlCache.Count > 500 Then urlCache.Clear() '定期的にリセット
1597 ' Dim rx As New Regex("<a href=""(?<svc>http://.+?/)(?<path>[^""]+)""", RegexOptions.IgnoreCase)
1598 ' Dim m As MatchCollection = rx.Matches(orgData)
1599 ' Dim urlList As New List(Of String)
1600 ' For Each orgUrlMatch As Match In m
1601 ' Dim orgUrl As String = orgUrlMatch.Result("${svc}")
1602 ' Dim orgUrlPath As String = orgUrlMatch.Result("${path}")
1603 ' If Array.IndexOf(_ShortUrlService, orgUrl) > -1 AndAlso _
1604 ' Not urlList.Contains(orgUrl + orgUrlPath) Then
1605 ' urlList.Add(orgUrl + orgUrlPath)
1608 ' For Each orgUrl As String In urlList
1609 ' If urlCache.ContainsKey(orgUrl) Then
1611 ' orgData = orgData.Replace("<a href=""" + orgUrl + """", "<a href=""" + urlCache(orgUrl) + """")
1612 ' Catch ex As Exception
1617 ' 'urlとして生成できない場合があるらしい
1618 ' 'Dim urlstr As String = New Uri(urlEncodeMultibyteChar(orgUrl)).GetLeftPart(UriPartial.Path)
1619 ' Dim retUrlStr As String = ""
1620 ' Dim tmpurlStr As String = New Uri(urlEncodeMultibyteChar(orgUrl)).GetLeftPart(UriPartial.Path)
1621 ' Dim httpVar As New HttpVarious
1622 ' retUrlStr = urlEncodeMultibyteChar(httpVar.GetRedirectTo(tmpurlStr))
1623 ' If retUrlStr.StartsWith("http") Then
1624 ' retUrlStr = retUrlStr.Replace("""", "%22") 'ダブルコーテーションがあるとURL終端と判断されるため、これだけ再エンコード
1625 ' orgData = orgData.Replace("<a href=""" + orgUrl + """", "<a href=""" + retUrlStr + """")
1626 ' urlCache.Add(orgUrl, retUrlStr)
1628 ' Catch ex As Exception
1634 ' 'For Each ma As Match In m
1635 ' ' svc = ma.Result("${svc}")
1636 ' ' posl1 = ma.Index
1637 ' ' If orgData.IndexOf("<a href=""" + svc, posl2, StringComparison.Ordinal) > -1 Then
1638 ' ' Dim urlStr As String = ""
1640 ' ' posl1 = orgData.IndexOf("<a href=""" + svc, posl2, StringComparison.Ordinal)
1641 ' ' posl1 = orgData.IndexOf(svc, posl1, StringComparison.Ordinal)
1642 ' ' posl2 = orgData.IndexOf("""", posl1, StringComparison.Ordinal)
1643 ' ' urlStr = New Uri(urlEncodeMultibyteChar(orgData.Substring(posl1, posl2 - posl1))).GetLeftPart(UriPartial.Path)
1644 ' ' Dim Response As String = ""
1645 ' ' Dim retUrlStr As String = ""
1646 ' ' Dim tmpurlStr As String = urlStr
1647 ' ' Dim SchemeAndDomain As Regex = New Regex("http://.+?/+?")
1648 ' ' Dim tmpSchemeAndDomain As String = ""
1649 ' ' For i As Integer = 0 To 4 'とりあえず5回試す
1650 ' ' retUrlStr = urlEncodeMultibyteChar(DirectCast(CreateSocket.GetWebResponse(tmpurlStr, Response, MySocket.REQ_TYPE.ReqGETForwardTo, timeOut:=2000), String))
1651 ' ' If retUrlStr.Length > 0 Then
1652 ' ' ' 転送先URLが返された (まだ転送されるかもしれないので返値を引数にしてもう一度)
1653 ' ' ' 取得試行回数オーバーの場合は取得結果を転送先とする
1654 ' ' Dim scd As Match = SchemeAndDomain.Match(retUrlStr)
1655 ' ' If scd.Success AndAlso scd.Value <> svc Then
1656 ' ' svc = scd.Value()
1658 ' ' tmpurlStr = retUrlStr
1661 ' ' ' 転送先URLが返されなかった
1662 ' ' If tmpurlStr <> urlStr Then
1663 ' ' '少なくとも一度以上転送されている (前回の結果を転送先とする)
1664 ' ' retUrlStr = tmpurlStr
1672 ' ' If retUrlStr.Length > 0 Then
1673 ' ' If Not retUrlStr.StartsWith("http") Then
1674 ' ' If retUrlStr.StartsWith("/") Then
1675 ' ' retUrlStr = urlEncodeMultibyteChar(svc + retUrlStr.Substring(1))
1676 ' ' ElseIf retUrlStr.StartsWith("data:") Then
1679 ' ' retUrlStr = urlEncodeMultibyteChar(retUrlStr.Insert(0, svc))
1682 ' ' retUrlStr = urlEncodeMultibyteChar(retUrlStr)
1684 ' ' orgData = orgData.Replace("<a href=""" + urlStr, "<a href=""" + retUrlStr)
1685 ' ' posl2 = 0 '置換した場合は頭から再探索(複数同時置換での例外対応)
1688 ' ' Catch ex As Exception
1689 ' ' '_signed = False
1690 ' ' 'Return "GetTimeline -> Err: Can't get tinyurl."
1700 Private Function ShortUrlResolve(ByVal orgData As String) As String
1701 If _tinyUrlResolve Then
1702 Static urlCache As New Specialized.StringDictionary()
1703 If urlCache.Count > 500 Then urlCache.Clear() '定期的にリセット
1705 Dim rx As New Regex("<a href=""(?<svc>http://.+?/)(?<path>[^""]+)""", RegexOptions.IgnoreCase)
1706 Dim m As MatchCollection = rx.Matches(orgData)
1707 Dim urlList As New List(Of String)
1708 For Each orgUrlMatch As Match In m
1709 Dim orgUrl As String = orgUrlMatch.Result("${svc}")
1710 Dim orgUrlPath As String = orgUrlMatch.Result("${path}")
1711 If Array.IndexOf(_ShortUrlService, orgUrl) > -1 AndAlso _
1712 Not urlList.Contains(orgUrl + orgUrlPath) Then
1713 urlList.Add(orgUrl + orgUrlPath)
1716 For Each orgUrl As String In urlList
1717 If urlCache.ContainsKey(orgUrl) Then
1719 orgData = orgData.Replace("<a href=""" + orgUrl + """", "<a href=""" + urlCache(orgUrl) + """")
1720 Catch ex As Exception
1725 'urlとして生成できない場合があるらしい
1726 'Dim urlstr As String = New Uri(urlEncodeMultibyteChar(orgUrl)).GetLeftPart(UriPartial.Path)
1727 Dim retUrlStr As String = ""
1728 Dim tmpurlStr As String = New Uri(urlEncodeMultibyteChar(orgUrl)).GetLeftPart(UriPartial.Path)
1729 Dim httpVar As New HttpVarious
1730 retUrlStr = urlEncodeMultibyteChar(httpVar.GetRedirectTo(tmpurlStr))
1731 If retUrlStr.StartsWith("http") Then
1732 retUrlStr = retUrlStr.Replace("""", "%22") 'ダブルコーテーションがあるとURL終端と判断されるため、これだけ再エンコード
1733 orgData = orgData.Replace("<a href=""" + orgUrl + """", "<a href=""" + retUrlStr + """")
1734 urlCache.Add(orgUrl, retUrlStr)
1736 Catch ex As Exception
1745 Private Function GetPlainText(ByVal orgData As String) As String
1746 Return HttpUtility.HtmlDecode(Regex.Replace(orgData, "(?<tagStart><a [^>]+>)(?<text>[^<]+)(?<tagEnd></a>)", "${text}"))
1748 ''単純テキストの取り出し(リンクタグ除去)
1749 'If orgData.IndexOf(_parseLink1, StringComparison.Ordinal) = -1 Then
1750 ' retStr = HttpUtility.HtmlDecode(orgData)
1752 ' Dim posl1 As Integer
1753 ' Dim posl2 As Integer
1754 ' Dim posl3 As Integer = 0
1760 ' posl1 = orgData.IndexOf(_parseLink1, posl3, StringComparison.Ordinal)
1761 ' If posl1 = -1 Then Exit Do
1763 ' If (posl3 + _parseLink3.Length <> posl1) Or posl3 = 0 Then
1764 ' If posl3 <> 0 Then
1765 ' retStr += HttpUtility.HtmlDecode(orgData.Substring(posl3 + _parseLink3.Length, posl1 - posl3 - _parseLink3.Length))
1767 ' retStr += HttpUtility.HtmlDecode(orgData.Substring(0, posl1))
1770 ' posl2 = orgData.IndexOf(_parseLink2, posl1, StringComparison.Ordinal)
1771 ' posl3 = orgData.IndexOf(_parseLink3, posl2, StringComparison.Ordinal)
1772 ' retStr += HttpUtility.HtmlDecode(orgData.Substring(posl2 + _parseLink2.Length, posl3 - posl2 - _parseLink2.Length))
1774 ' retStr += HttpUtility.HtmlDecode(orgData.Substring(posl3 + _parseLink3.Length))
1780 ' htmlの簡易サニタイズ(詳細表示に不要なタグの除去)
1782 Private Function SanitizeHtml(ByVal orgdata As String) As String
1783 Dim retdata As String = orgdata
1785 ' <script ~ </script>
1786 Dim rx As Regex = New Regex( _
1787 "<(script|object|applet|image|frameset|fieldset|legend|style).*" & _
1788 "</(script|object|applet|image|frameset|fieldset|legend|style)>", RegexOptions.IgnoreCase)
1789 retdata = rx.Replace(retdata, "")
1792 rx = New Regex("<(frame|link|iframe|img)>", RegexOptions.IgnoreCase)
1793 retdata = rx.Replace(retdata, "")
1798 Private Function AdjustHtml(ByVal orgData As String) As String
1799 Dim retStr As String = orgData
1800 Dim hash As New Regex("<a [^>]+>[#|#](?<1>[a-zA-Z0-9_]+)</a>")
1801 Dim m As Match = hash.Match(retStr)
1804 _hashList.Add("#" + m.Groups(1).Value)
1808 retStr = Regex.Replace(retStr, "<a [^>]*href=""/", "<a href=""" + _protocol + "twitter.com/")
1809 retStr = retStr.Replace("<a href=", "<a target=""_self"" href=")
1810 retStr = retStr.Replace(vbLf, "<br>")
1812 '半角スペースを置換(Thanks @anis774)
1813 Dim ret As Boolean = False
1815 ret = EscapeSpace(retStr)
1817 'Dim isTag As Boolean = False
1818 'For i As Integer = 0 To retStr.Length - 1
1819 ' If retStr(i) = "<"c Then
1822 ' If retStr(i) = ">"c Then
1826 ' If (Not isTag) AndAlso (retStr(i) = " "c) Then
1827 ' retStr = retStr.Remove(i, 1)
1828 ' retStr = retStr.Insert(i, " ")
1832 Return SanitizeHtml(retStr)
1835 Private Function EscapeSpace(ByRef html As String) As Boolean
1836 '半角スペースを置換(Thanks @anis774)
1837 Dim isTag As Boolean = False
1838 For i As Integer = 0 To html.Length - 1
1839 If html(i) = "<"c Then
1842 If html(i) = ">"c Then
1846 If (Not isTag) AndAlso (html(i) = " "c) Then
1847 html = html.Remove(i, 1)
1848 html = html.Insert(i, " ")
1855 Private Sub GetIconImage(ByVal post As PostClass)
1860 If Not _getIcon Then
1861 post.ImageIndex = -1
1862 TabInformations.GetInstance.AddPost(post)
1867 post.ImageIndex = _lIcon.Images.IndexOfKey(post.ImageUrl)
1870 If post.ImageIndex > -1 Then
1871 TabInformations.GetInstance.AddPost(post)
1875 Dim httpVar As New HttpVarious
1876 img = httpVar.GetImage(post.ImageUrl)
1877 If img Is Nothing Then
1878 post.ImageIndex = -1
1879 TabInformations.GetInstance.AddPost(post)
1883 If _endingFlag Then Exit Sub
1885 bmp2 = New Bitmap(_iconSz, _iconSz)
1886 Using g As Graphics = Graphics.FromImage(bmp2)
1887 g.InterpolationMode = Drawing2D.InterpolationMode.High
1888 g.DrawImage(img, 0, 0, _iconSz, _iconSz)
1893 post.ImageIndex = _lIcon.Images.IndexOfKey(post.ImageUrl)
1894 If post.ImageIndex = -1 Then
1896 Dim fd As New System.Drawing.Imaging.FrameDimension(img.FrameDimensionsList(0))
1897 Dim fd_count As Integer = img.GetFrameCount(fd)
1898 If fd_count > 1 Then
1900 img.SelectActiveFrame(fd, 1)
1901 _dIcon.Add(post.ImageUrl, img) '詳細表示用ディクショナリに追加
1902 Catch ex As Exception
1903 Dim bmp As New Bitmap(img)
1904 _dIcon.Add(post.ImageUrl, bmp) '詳細表示用ディクショナリに追加
1908 _dIcon.Add(post.ImageUrl, img) '詳細表示用ディクショナリに追加
1910 _lIcon.Images.Add(post.ImageUrl, bmp2)
1911 post.ImageIndex = _lIcon.Images.IndexOfKey(post.ImageUrl)
1912 Catch ex As InvalidOperationException
1913 'タイミングにより追加できない場合がある?(キー重複ではない)
1914 post.ImageIndex = -1
1918 TabInformations.GetInstance.AddPost(post)
1919 Catch ex As ArgumentException
1928 'Private Function GetAuthKey(ByVal resMsg As String) As Integer
1929 ' Dim pos1 As Integer
1930 ' Dim pos2 As Integer
1932 ' pos1 = resMsg.IndexOf(_getAuthKey, StringComparison.Ordinal)
1937 ' pos2 = resMsg.IndexOf(_getAuthKeyTo, pos1 + _getAuthKey.Length, StringComparison.Ordinal)
1939 ' _authKey = resMsg.Substring(pos1 + _getAuthKey.Length, pos2 - pos1 - _getAuthKey.Length)
1947 'Private Function GetAuthKeyDM(ByVal resMsg As String) As Integer
1948 ' Dim pos1 As Integer
1949 ' Dim pos2 As Integer
1951 ' pos1 = resMsg.IndexOf(_getAuthKey, StringComparison.Ordinal)
1956 ' pos2 = resMsg.IndexOf("""", pos1 + _getAuthKey.Length, StringComparison.Ordinal)
1957 ' _authKeyDM = resMsg.Substring(pos1 + _getAuthKey.Length, pos2 - pos1 - _getAuthKey.Length)
1962 Private Structure PostInfo
1963 Public CreatedAt As String
1965 Public Text As String
1966 Public UserId As String
1967 Public Sub New(ByVal Created As String, ByVal IdStr As String, ByVal txt As String, ByVal uid As String)
1973 Public Shadows Function Equals(ByVal dst As PostInfo) As Boolean
1974 If Me.CreatedAt = dst.CreatedAt AndAlso Me.Id = dst.Id AndAlso Me.Text = dst.Text AndAlso Me.UserId = dst.UserId Then
1982 Private Function IsPostRestricted(ByRef resMsg As String) As Boolean
1983 Static _prev As New PostInfo("", "", "", "")
1984 Dim _current As New PostInfo("", "", "", "")
1987 Dim xd As XmlDocument = New XmlDocument()
1990 _current.CreatedAt = xd.SelectSingleNode("/status/created_at/text()").Value
1991 _current.Id = xd.SelectSingleNode("/status/id/text()").Value
1992 _current.Text = xd.SelectSingleNode("/status/text/text()").Value
1993 _current.UserId = xd.SelectSingleNode("/status/user/id/text()").Value
1995 If _current.Equals(_prev) Then
1998 _prev.CreatedAt = _current.CreatedAt
1999 _prev.Id = _current.Id
2000 _prev.Text = _current.Text
2001 _prev.UserId = _current.UserId
2002 Catch ex As XmlException
2009 Public Function PostStatus(ByVal postStr As String, ByVal reply_to As Long) As String
2011 If _endingFlag Then Return ""
2013 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2015 postStr = postStr.Trim()
2017 Dim res As HttpStatusCode
2018 Dim content As String = ""
2020 res = twCon.UpdateStatus(postStr, reply_to, content)
2021 Catch ex As Exception
2022 Return "Err:" + ex.Message
2026 Case HttpStatusCode.OK
2027 Dim xd As XmlDocument = New XmlDocument()
2030 Dim xNode As XmlNode = Nothing
2031 xNode = xd.SelectSingleNode("/status/user/followers_count/text()")
2032 If xNode IsNot Nothing Then _followersCount = Integer.Parse(xNode.Value)
2033 xNode = xd.SelectSingleNode("/status/user/friends_count/text()")
2034 If xNode IsNot Nothing Then _friendsCount = Integer.Parse(xNode.Value)
2035 xNode = xd.SelectSingleNode("/status/user/statuses_count/text()")
2036 If xNode IsNot Nothing Then _statusesCount = Integer.Parse(xNode.Value)
2037 xNode = xd.SelectSingleNode("/status/user/location/text()")
2038 If xNode IsNot Nothing Then _location = xNode.Value
2039 xNode = xd.SelectSingleNode("/status/user/description/text()")
2040 If xNode IsNot Nothing Then _bio = xNode.Value
2041 Catch ex As Exception
2045 If Not postStr.StartsWith("D ", StringComparison.OrdinalIgnoreCase) AndAlso _
2046 Not postStr.StartsWith("DM ", StringComparison.OrdinalIgnoreCase) AndAlso _
2047 IsPostRestricted(content) Then
2048 Return "OK:Delaying?"
2050 If op.Post(postStr.Length) Then
2053 Return "Outputz:Failed"
2055 Case HttpStatusCode.Forbidden
2056 Return "Err:Update Limits?"
2057 Case HttpStatusCode.Unauthorized
2058 Twitter.AccountState = ACCOUNT_STATE.Invalid
2059 Return "Check your Username/Password."
2061 Return "Err:" + res.ToString
2065 Public Function RemoveStatus(ByVal id As Long) As String
2066 If _endingFlag Then Return ""
2068 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2070 Dim res As HttpStatusCode
2073 res = twCon.DestroyStatus(id)
2074 Catch ex As Exception
2075 Return "Err:" + ex.Message
2079 Case HttpStatusCode.OK
2081 Case HttpStatusCode.Unauthorized
2082 Twitter.AccountState = ACCOUNT_STATE.Invalid
2083 Return "Check your Username/Password."
2084 Case HttpStatusCode.NotFound
2087 Return "Err:" + res.ToString
2092 Public Function PostRetweet(ByVal id As Long, ByVal read As Boolean) As String
2093 If _endingFlag Then Return ""
2094 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2097 Dim target As Long = id
2098 If TabInformations.GetInstance.Item(id).RetweetedId > 0 Then
2099 target = TabInformations.GetInstance.Item(id).RetweetedId '再RTの場合は元発言をRT
2102 Dim res As HttpStatusCode
2103 Dim content As String = ""
2105 res = twCon.RetweetStatus(target, content)
2106 Catch ex As Exception
2107 Return "Err:" + ex.Message
2111 Case HttpStatusCode.Unauthorized
2112 Twitter.AccountState = ACCOUNT_STATE.Invalid
2113 Return "Check your Username/Password."
2114 Case Is <> HttpStatusCode.OK
2115 Return "Err:" + res.ToString()
2118 Dim dlgt As GetIconImageDelegate 'countQueryに合わせる
2119 Dim ar As IAsyncResult 'countQueryに合わせる
2120 Dim xdoc As New XmlDocument
2122 xdoc.LoadXml(content)
2123 Catch ex As Exception
2125 'MessageBox.Show("不正なXMLです。(TL-LoadXml)")
2126 Return "Invalid XML!"
2130 Dim xentryNode As XmlNode = xdoc.DocumentElement.SelectSingleNode("/status")
2131 If xentryNode Is Nothing Then Return "Invalid XML!"
2132 Dim xentry As XmlElement = CType(xentryNode, XmlElement)
2133 Dim post As New PostClass
2135 post.Id = Long.Parse(xentry.Item("id").InnerText)
2138 If TabInformations.GetInstance.ContainsKey(post.Id) Then Return ""
2141 Dim xRnode As XmlNode = xentry.SelectSingleNode("./retweeted_status")
2142 If xRnode Is Nothing Then Return "Invalid XML!"
2144 Dim xRentry As XmlElement = CType(xRnode, XmlElement)
2145 post.PDate = DateTime.ParseExact(xRentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
2147 post.RetweetedId = Long.Parse(xRentry.Item("id").InnerText)
2149 post.Data = xRentry.Item("text").InnerText
2150 'Source取得(htmlの場合は、中身を取り出し)
2151 post.Source = xRentry.Item("source").InnerText
2153 Long.TryParse(xRentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
2154 post.InReplyToUser = xRentry.Item("in_reply_to_screen_name").InnerText
2155 post.IsFav = TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.RetweetedId)
2158 Dim xRUentry As XmlElement = CType(xRentry.SelectSingleNode("./user"), XmlElement)
2159 post.Uid = Long.Parse(xRUentry.Item("id").InnerText)
2160 post.Name = xRUentry.Item("screen_name").InnerText
2161 post.Nickname = xRUentry.Item("name").InnerText
2162 post.ImageUrl = xRUentry.Item("profile_image_url").InnerText
2163 post.IsProtect = Boolean.Parse(xRUentry.Item("protected").InnerText)
2164 'post.IsMe = post.Name.ToLower.Equals(_uid)
2168 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
2169 post.RetweetedBy = xUentry.Item("screen_name").InnerText
2172 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
2173 post.Data = HttpUtility.HtmlDecode(post.Data)
2174 post.Data = post.Data.Replace("<3", "♡")
2176 If post.Source.StartsWith("<") Then
2177 Dim rgS As New Regex(">(?<source>.+)<")
2178 Dim mS As Match = rgS.Match(post.Source)
2180 post.Source = mS.Result("${source}")
2185 post.IsReply = post.ReplyToList.Contains(_uid)
2190 If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.Uid)
2192 If post.IsMe AndAlso _readOwnPost Then post.IsRead = True
2195 Catch ex As Exception
2197 'MessageBox.Show("不正なXMLです。(TL-Parse)")
2198 Return "Invalid XML!"
2201 '非同期アイコン取得&StatusDictionaryに追加
2202 dlgt = New GetIconImageDelegate(AddressOf GetIconImage)
2203 ar = dlgt.BeginInvoke(post, Nothing, Nothing)
2208 Catch ex As Exception
2209 '最後までendinvoke回す(ゾンビ化回避)
2210 ex.Data("IsTerminatePermission") = False
2217 Public Function RemoveDirectMessage(ByVal id As Long) As String
2218 If _endingFlag Then Return ""
2220 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2222 Dim res As HttpStatusCode
2225 res = twCon.DestroyDirectMessage(id)
2226 Catch ex As Exception
2227 Return "Err:" + ex.Message
2231 Case HttpStatusCode.OK
2233 Case HttpStatusCode.Unauthorized
2234 Twitter.AccountState = ACCOUNT_STATE.Invalid
2235 Return "Check your Username/Password."
2236 Case HttpStatusCode.NotFound
2239 Return "Err:" + res.ToString
2243 Public Function PostFollowCommand(ByVal screenName As String) As String
2245 If _endingFlag Then Return ""
2247 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2249 Dim res As HttpStatusCode
2252 res = twCon.CreateFriendships(screenName)
2253 Catch ex As Exception
2254 Return "Err:" + ex.Message
2258 Case HttpStatusCode.OK
2260 Case HttpStatusCode.Unauthorized
2261 Twitter.AccountState = ACCOUNT_STATE.Invalid
2262 Return "Check your Username/Password."
2263 Case HttpStatusCode.Forbidden
2264 Return "Err:Update Limits?"
2266 Return "Err:" + res.ToString
2270 Public Function PostRemoveCommand(ByVal screenName As String) As String
2272 If _endingFlag Then Return ""
2274 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2276 Dim res As HttpStatusCode
2279 res = twCon.DestroyFriendships(screenName)
2280 Catch ex As Exception
2281 Return "Err:" + ex.Message
2285 Case HttpStatusCode.OK
2287 Case HttpStatusCode.Unauthorized
2288 Twitter.AccountState = ACCOUNT_STATE.Invalid
2289 Return "Check your Username/Password."
2291 Return "Err:" + res.ToString
2295 Public Function GetFriendshipInfo(ByVal screenName As String, ByRef isFollowing As Boolean, ByRef isFollowed As Boolean) As String
2297 If _endingFlag Then Return ""
2299 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2301 Dim res As HttpStatusCode
2302 Dim content As String = ""
2304 res = twCon.ShowFriendships(_uid, screenName, content)
2305 Catch ex As Exception
2306 Return "Err:" + ex.Message
2310 Case HttpStatusCode.OK
2311 Dim xdoc As New XmlDocument
2312 Dim result As String = ""
2314 xdoc.LoadXml(content)
2315 isFollowing = Boolean.Parse(xdoc.SelectSingleNode("/relationship/source/following").InnerText)
2316 isFollowed = Boolean.Parse(xdoc.SelectSingleNode("/relationship/source/followed_by").InnerText)
2317 Catch ex As Exception
2318 result = "Err:Invalid XML."
2321 Case HttpStatusCode.BadRequest
2322 Return "Err:API Limits?"
2323 Case HttpStatusCode.Unauthorized
2324 Twitter.AccountState = ACCOUNT_STATE.Invalid
2325 Return "Check your Username/Password."
2327 Return "Err:" + res.ToString
2331 Public Function PostFavAdd(ByVal id As Long) As String
2332 If _endingFlag Then Return ""
2334 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2336 Dim res As HttpStatusCode
2339 res = twCon.CreateFavorites(id)
2340 Catch ex As Exception
2341 Return "Err:" + ex.Message
2345 Case HttpStatusCode.OK
2346 If Not _restrictFavCheck Then Return ""
2347 Case HttpStatusCode.Unauthorized
2348 Twitter.AccountState = ACCOUNT_STATE.Invalid
2349 Return "Check your Username/Password."
2350 Case HttpStatusCode.Forbidden
2351 Return "Err:Update Limits?"
2353 Return "Err:" + res.ToString
2356 'http://twitter.com/statuses/show/id.xml APIを発行して本文を取得
2358 Dim content As String = ""
2360 res = twCon.ShowStatuses(id, content)
2361 Catch ex As Exception
2362 Return "Err:" + ex.Message
2366 Case HttpStatusCode.OK
2368 Using rd As Xml.XmlTextReader = New Xml.XmlTextReader(New System.IO.StringReader(content))
2370 While rd.EOF = False
2371 If rd.IsStartElement("favorited") Then
2372 If rd.ReadElementContentAsBoolean() = True Then
2373 Return "" '正常にふぁぼれている
2375 Return "NG(Restricted?)" '正常応答なのにふぁぼれてないので制限っぽい
2382 Return "Err:Invalid XML!"
2384 Catch ex As XmlException
2387 Case HttpStatusCode.Unauthorized
2388 Twitter.AccountState = ACCOUNT_STATE.Invalid
2389 Return "Check your Username/Password."
2390 Case HttpStatusCode.BadRequest
2391 Return "Err:API Limits?"
2393 Return "Err:" + res.ToString
2398 Public Function PostFavRemove(ByVal id As Long) As String
2399 If _endingFlag Then Return ""
2401 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2403 Dim res As HttpStatusCode
2406 res = twCon.DestroyFavorites(id)
2407 Catch ex As Exception
2408 Return "Err:" + ex.Message
2412 Case HttpStatusCode.OK
2414 Case HttpStatusCode.Unauthorized
2415 Twitter.AccountState = ACCOUNT_STATE.Invalid
2416 Return "Check your Username/Password."
2417 Case HttpStatusCode.Forbidden
2418 Return "Err:Update Limits?"
2420 Return "Err:" + res.ToString
2424 '#Region "follower取得"
2425 ' 'Delegate Function GetFollowersDelegate(ByVal Query As Integer) As String
2426 ' 'Private semaphore As Threading.Semaphore = Nothing
2427 ' 'Private threadNum As Integer = 0
2428 ' Private _threadErr As Boolean = False
2430 ' Private Function GetFollowersMethod() As String
2431 ' Dim resStatus As String = ""
2432 ' Dim resMsg As String = ""
2433 ' Dim lineCount As Integer = 0
2434 ' Dim page As Long = -1
2437 ' If _endingFlag Then Exit Do
2438 ' resMsg = DirectCast(CreateSocket.GetWebResponse(_protocol + _apiHost + _hubServer + _GetFollowers + _cursorQry + page.ToString, resStatus, MySocket.REQ_TYPE.ReqGetAPI), String)
2439 ' If resStatus.StartsWith("OK") = False Then
2440 ' Debug.WriteLine(page.ToString)
2445 ' Using rd As Xml.XmlTextReader = New Xml.XmlTextReader(New System.IO.StringReader(resMsg))
2448 ' While rd.EOF = False
2449 ' If rd.IsStartElement("screen_name") Then
2450 ' Dim tmp As String = rd.ReadElementString("screen_name").ToLower()
2452 ' If Not tmpFollower.Contains(tmp) Then
2453 ' tmpFollower.Add(tmp)
2457 ' ElseIf rd.IsStartElement("next_cursor") Then
2458 ' page = Long.Parse(rd.ReadElementString("next_cursor"))
2459 ' If page = 0 Then Exit Do
2466 ' Catch ex As Exception
2468 ' TraceOut("NG(XmlException)")
2469 ' Return "NG(XmlException)"
2471 ' Loop While lineCount > 0
2476 'Private Sub GetFollowersCallback(ByVal ar As IAsyncResult)
2477 ' Dim dlgt As GetFollowersDelegate = DirectCast(ar.AsyncState, GetFollowersDelegate)
2480 ' Dim ret As String = dlgt.EndInvoke(ar)
2481 ' If Not ret.Equals("") AndAlso Not _threadErr Then
2485 ' Catch ex As Exception
2487 ' ex.Data("IsTerminatePermission") = False
2490 ' GetTmSemaphore.Release() ' セマフォから出る
2491 ' Interlocked.Decrement(threadNum) ' スレッド数カウンタを-1
2496 '' キャッシュの検証と読み込み -1を渡した場合は読み込みのみ行う(APIエラーでFollowersCountが取得できなかったとき)
2497 'Private Function ValidateCache() As Integer
2501 ' Dim setting As SettingFollower = SettingFollower.Load()
2502 ' follower = setting.Follower
2503 ' If follower.Count = 0 OrElse Not follower(0).Equals(_uid.ToLower()) Then
2504 ' ' 別IDの場合はキャッシュ破棄して読み直し
2507 ' Catch ex As XmlException
2510 ' Catch ex As InvalidOperationException
2515 ' 'If _FollowersCount = -1 Then Return tmpFollower.Count
2516 ' Return follower.Count
2518 ' 'If (_FollowersCount + 1) = tmpFollower.Count Then
2519 ' ' '変動がないので読み込みの必要なし
2521 ' 'ElseIf (_FollowersCount + 1) < tmpFollower.Count Then
2522 ' ' '減っている場合はどこが抜けているのかわからないので全部破棄して読み直し
2523 ' ' tmpFollower.Clear()
2524 ' ' tmpFollower.Add(_uid.ToLower())
2525 ' ' Return _FollowersCount
2530 ' 'Return _FollowersCount - tmpFollower.Count
2534 'Private Sub UpdateCache()
2535 ' Dim setting As New SettingFollower(follower)
2539 ' Public Function GetFollowers(ByVal CacheInvalidate As Boolean) As String
2541 ' Dim sw As New System.Diagnostics.Stopwatch
2545 ' If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2547 ' 'Dim resStatus As String = ""
2548 ' 'Dim resMsg As String = ""
2549 ' 'Dim i As Integer = 0
2550 ' 'Dim DelegateInstance As GetFollowersDelegate = New GetFollowersDelegate(AddressOf GetFollowersMethod)
2551 ' 'Dim threadMax As Integer = 4 ' 最大スレッド数
2552 ' 'Dim followersCount As Integer = 0
2554 ' 'Interlocked.Exchange(threadNum, 0) ' スレッド数カウンタ初期化
2555 ' _threadErr = False
2557 ' tmpFollower.Clear()
2558 ' 'follower.Add(_uid.ToLower())
2559 ' tmpFollower.Add(_uid.ToLower())
2561 ' 'resMsg = DirectCast(CreateSocket.GetWebResponse("https://twitter.com/users/show/" + _uid + ".xml", resStatus, MySocket.REQ_TYPE.ReqGetAPI), String)
2562 ' 'If resMsg = "" Then
2563 ' ' If resStatus.StartsWith("Err: BadRequest") Then
2564 ' ' Return "Maybe, the requests reached API limit."
2565 ' ' ElseIf resStatus.StartsWith("Err: Unauthorized") Then
2566 ' ' Twitter.AccountState = ACCOUNT_STATE.Invalid
2567 ' ' Return "Check your Username/Password."
2569 ' ' Return resStatus
2573 ' 'Dim xd As XmlDocument = New XmlDocument()
2575 ' ' xd.LoadXml(resMsg)
2576 ' ' followersCount = Integer.Parse(xd.SelectSingleNode("/user/followers_count/text()").Value)
2577 ' 'Catch ex As Exception
2578 ' ' 'If CacheInvalidate OrElse ValidateCache(-1) < 0 Then
2579 ' ' If ValidateCache(-1) < 0 Then
2580 ' ' ' FollowersカウントがAPIで取得できず、なおかつキャッシュから読めなかった
2581 ' ' SyncLock LockObj
2582 ' ' follower.Clear()
2583 ' ' follower.Add(_uid.ToLower())
2585 ' ' Return "Can't get followers_count and invalid cache."
2587 ' ' 'キャッシュを読み出せたのでキャッシュを使う
2588 ' ' SyncLock LockObj
2589 ' ' follower = tmpFollower
2595 ' 'Dim tmp As Integer
2597 ' ''If CacheInvalidate Then
2598 ' 'tmp = followersCount
2600 ' ''tmp = ValidateCache(followersCount)
2605 ' ' i = (tmp + 100) \ 100 ' Followersカウント取得しページ単位に切り上げる。1ページ余分に読む
2607 ' ' ' ' キャッシュの件数に変化がなかった
2610 ' ' ' Console.WriteLine(sw.ElapsedMilliseconds)
2612 ' ' ' SyncLock LockObj
2613 ' ' ' follower = tmpFollower
2616 ' ' Return "" 'ユーザー情報のフォロワー数が0
2620 ' ''semaphore = New System.Threading.Semaphore(threadMax, threadMax) 'スレッド最大数
2622 ' 'For cnt As Integer = 0 To i
2623 ' ' If _endingFlag Then Exit For
2624 ' ' 'semaphore.WaitOne() 'セマフォ取得 threadMax以上ならここでブロックされる
2625 ' ' GetTmSemaphore.WaitOne()
2626 ' ' 'Interlocked.Increment(threadNum) 'スレッド数カウンタを+1
2627 ' ' 'DelegateInstance.BeginInvoke(cnt + 1, New System.AsyncCallback(AddressOf GetFollowersCallback), DelegateInstance)
2628 ' ' Dim ret As String = GetFollowersMethod(cnt + 1)
2629 ' ' 'Interlocked.Decrement(threadNum) 'スレッド数カウンタを-1
2630 ' ' GetTmSemaphore.Release()
2631 ' ' If _threadErr Then Exit For
2634 ' '''全てのスレッドの終了を待つ(スレッド数カウンタが0になるまで待機)
2636 ' '' Thread.Sleep(50)
2637 ' ''Loop Until Interlocked.Add(threadNum, 0) = 0
2639 ' ''semaphore.Close()
2641 ' Dim ret As String = GetFollowersMethod()
2642 ' If _endingFlag Then Return ""
2644 ' If _threadErr Then
2645 ' If ValidateCache() > 0 Then
2647 ' For Each name As String In tmpFollower
2648 ' If Not follower.Contains(name) Then follower.Add(name)
2651 ' If Not _endingFlag AndAlso follower.Count > 1 Then UpdateCache()
2652 ' ret = "Can't get followers. Use cache."
2654 ' ' エラーが発生しているならFollowersリストクリア
2657 ' follower.Add(_uid.ToLower())
2659 ' ret = "Can't get followers."
2663 ' follower = tmpFollower
2668 ' If Not _endingFlag AndAlso follower.Count > 1 Then UpdateCache()
2672 ' 'Console.WriteLine(sw.ElapsedMilliseconds)
2675 ' TabInformations.GetInstance.RefreshOwl(follower)
2681 'Public Sub RefreshOwl()
2682 ' TabInformations.GetInstance.RefreshOwl(follower)
2685 'Public Sub RefreshOwlApi()
2686 ' TabInformations.GetInstance.RefreshOwl(followerId)
2689 Public ReadOnly Property Username() As String
2691 Return twCon.AuthenticatedUsername
2695 Public ReadOnly Property Password() As String
2697 Return twCon.Password
2701 Private Shared _accountState As ACCOUNT_STATE = ACCOUNT_STATE.Valid
2702 Public Shared Property AccountState() As ACCOUNT_STATE
2704 Return _accountState
2706 Set(ByVal value As ACCOUNT_STATE)
2707 _accountState = value
2711 'Public Property NextThreshold() As Integer
2713 ' Return _nextThreshold
2715 ' Set(ByVal value As Integer)
2716 ' _nextThreshold = value
2720 'Public Property NextPages() As Integer
2724 ' Set(ByVal value As Integer)
2725 ' _nextPages = value
2729 Public ReadOnly Property InfoTwitter() As String
2735 'Public Property UseAPI() As Boolean
2739 ' Set(ByVal value As Boolean)
2744 ' Public Sub GetWedata()
2745 ' Dim resStatus As String = ""
2746 ' Dim resMsg As String = ""
2748 ' resMsg = DirectCast(CreateSocket.GetWebResponse(wedataUrl, resStatus, timeOut:=10 * 1000), String) 'タイムアウト時間を10秒に設定
2749 ' If resMsg.Length = 0 Then Exit Sub
2751 ' Dim rs As New System.IO.StringReader(resMsg)
2753 ' Dim mode As Integer = 0 '0:search name 1:search data 2:read data
2754 ' Dim name As String = ""
2758 ' While rs.Peek() > -1
2763 ' If ln.StartsWith(" ""name"": ") Then
2764 ' name = ln.Substring(13, ln.Length - 2 - 13)
2768 ' If ln = " ""data"": {" Then
2772 ' If ln = " }," Then
2775 ' If ln.EndsWith(",") Then ln = ln.Substring(0, ln.Length - 1)
2777 ' Case "SplitPostReply"
2778 ' If ln.StartsWith(" ""tagfrom"": """) Then
2779 ' _splitPost = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2781 ' Case "SplitPostRecent"
2782 ' If ln.StartsWith(" ""tagfrom"": """) Then
2783 ' _splitPostRecent = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2786 ' If ln.StartsWith(" ""tagto"": """) Then
2787 ' _statusIdTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2790 ' If ln.StartsWith(" ""tagfrom"": """) Then
2791 ' _isProtect = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2794 ' If ln.StartsWith(" ""tagfrom"": """) Then
2795 ' _isReplyEng = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2797 ' If ln.StartsWith(" ""tagfrom2"": """) Then
2798 ' _isReplyJpn = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
2800 ' If ln.StartsWith(" ""tagto"": """) Then
2801 ' _isReplyTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2804 ' ' If ln.StartsWith(" ""tagfrom"": """) Then
2805 ' ' _parseStar = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2807 ' ' If ln.StartsWith(" ""tagfrom2"": """) Then
2808 ' ' _parseStarEmpty = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
2810 ' ' If ln.StartsWith(" ""tagto"": """) Then
2811 ' ' _parseStarTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2814 ' If ln.StartsWith(" ""tagfrom"": """) Then
2815 ' _followerList = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2817 ' If ln.StartsWith(" ""tagfrom2"": """) Then
2818 ' _followerMbr1 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
2820 ' If ln.StartsWith(" ""tagfrom3"": """) Then
2821 ' _followerMbr2 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
2823 ' If ln.StartsWith(" ""tagto"": """) Then
2824 ' _followerMbr3 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2827 ' If ln.StartsWith(" ""tagfrom"": """) Then
2828 ' _splitDM = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2831 ' If ln.StartsWith(" ""tagfrom"": """) Then
2832 ' _parseDM1 = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2834 ' If ln.StartsWith(" ""tagfrom2"": """) Then
2835 ' _parseDM11 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
2837 ' If ln.StartsWith(" ""tagto"": """) Then
2838 ' _parseDM2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2841 ' If ln.StartsWith(" ""tagfrom"": """) Then
2842 ' _parseDate = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2844 ' If ln.StartsWith(" ""tagto"": """) Then
2845 ' _parseDateTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2848 ' If ln.StartsWith(" ""tagfrom"": """) Then
2849 ' _parseMsg1 = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2851 ' If ln.StartsWith(" ""tagto"": """) Then
2852 ' _parseMsg2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2854 ' Case "GetImagePath"
2855 ' If ln.StartsWith(" ""tagfrom"": """) Then
2856 ' _parseImg = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2858 ' If ln.StartsWith(" ""tagto"": """) Then
2859 ' _parseImgTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2862 ' If ln.StartsWith(" ""tagfrom"": """) Then
2863 ' _parseNick = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2865 ' If ln.StartsWith(" ""tagto"": """) Then
2866 ' _parseNickTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2869 ' If ln.StartsWith(" ""tagfrom"": """) Then
2870 ' _parseName = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2872 ' If ln.StartsWith(" ""tagto"": """) Then
2873 ' _parseNameTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2876 ' ' If ln.StartsWith(" ""tagfrom"": """) Then
2877 ' ' _getSiv = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2879 ' ' If ln.StartsWith(" ""tagto"": """) Then
2880 ' ' _getSivTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2883 ' If ln.StartsWith(" ""tagfrom"": """) Then
2884 ' _getAuthKey = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2886 ' If ln.StartsWith(" ""tagto"": """) Then
2887 ' _getAuthKeyTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2889 ' Case "InfoTwitter"
2890 ' If ln.StartsWith(" ""tagfrom"": """) Then
2891 ' _getInfoTwitter = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2893 ' If ln.StartsWith(" ""tagto"": """) Then
2894 ' _getInfoTwitterTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2896 ' Case "GetProtectMsg"
2897 ' If ln.StartsWith(" ""tagfrom"": """) Then
2898 ' _parseProtectMsg1 = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2900 ' If ln.StartsWith(" ""tagto"": """) Then
2901 ' _parseProtectMsg2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2904 ' If ln.StartsWith(" ""tagfrom"": """) Then
2905 ' _parseDMcountFrom = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2907 ' If ln.StartsWith(" ""tagto"": """) Then
2908 ' _parseDMcountTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2911 ' If ln.StartsWith(" ""tagfrom"": """) Then
2912 ' _parseSourceFrom = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2914 ' If ln.StartsWith(" ""tagfrom2"": """) Then
2915 ' _parseSource2 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
2917 ' If ln.StartsWith(" ""tagto"": """) Then
2918 ' _parseSource2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2920 ' Case "RemoveClass"
2921 ' If ln.StartsWith(" ""tagfrom"": """) Then
2922 ' _removeClass = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2932 ' GenerateAnalyzeKey()
2936 Public WriteOnly Property GetIcon() As Boolean
2937 Set(ByVal value As Boolean)
2942 Public WriteOnly Property TinyUrlResolve() As Boolean
2943 Set(ByVal value As Boolean)
2944 _tinyUrlResolve = value
2948 'Public WriteOnly Property SelectedProxyType() As ProxyType
2949 ' Set(ByVal value As ProxyType)
2950 ' _proxyType = value
2954 'Public WriteOnly Property ProxyAddress() As String
2955 ' Set(ByVal value As String)
2956 ' _proxyAddress = value
2960 'Public WriteOnly Property ProxyPort() As Integer
2961 ' Set(ByVal value As Integer)
2962 ' _proxyPort = value
2966 'Public WriteOnly Property ProxyUser() As String
2967 ' Set(ByVal value As String)
2968 ' _proxyUser = value
2972 'Public WriteOnly Property ProxyPassword() As String
2973 ' Set(ByVal value As String)
2974 ' _proxyPassword = value
2978 Public WriteOnly Property RestrictFavCheck() As Boolean
2979 Set(ByVal value As Boolean)
2980 _restrictFavCheck = value
2984 Public WriteOnly Property IconSize() As Integer
2985 Set(ByVal value As Integer)
2990 Public Function MakeShortUrl(ByVal ConverterType As UrlConverter, ByVal SrcUrl As String) As String
2991 Dim src As String = urlEncodeMultibyteChar(SrcUrl)
2992 Dim param As New Dictionary(Of String, String)
2993 Dim content As String = ""
2995 For Each svc As String In _ShortUrlService
2996 If SrcUrl.StartsWith(svc) Then
2997 Return "Can't convert"
3002 If SrcUrl.StartsWith("http://nico.ms/") Then Return "Can't convert"
3004 SrcUrl = HttpUtility.UrlEncode(SrcUrl)
3006 Select Case ConverterType
3007 Case UrlConverter.TinyUrl 'tinyurl
3008 If SrcUrl.StartsWith("http") Then
3009 If "http://tinyurl.com/xxxxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
3010 ' 明らかに長くなると推測できる場合は圧縮しない
3014 If Not (New HttpVarious).PostData("http://tinyurl.com/api-create.php?url=" + SrcUrl, Nothing, content) Then
3015 Return "Can't convert"
3018 If Not content.StartsWith("http://tinyurl.com/") Then
3019 Return "Can't convert"
3021 Case UrlConverter.Isgd
3022 If SrcUrl.StartsWith("http") Then
3023 If "http://is.gd/xxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
3024 ' 明らかに長くなると推測できる場合は圧縮しない
3028 If Not (New HttpVarious).PostData("http://is.gd/api.php?longurl=" + SrcUrl, Nothing, content) Then
3029 Return "Can't convert"
3032 If Not content.StartsWith("http://is.gd/") Then
3033 Return "Can't convert"
3035 Case UrlConverter.Twurl
3036 If SrcUrl.StartsWith("http") Then
3037 If "http://twurl.nl/xxxxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
3038 ' 明らかに長くなると推測できる場合は圧縮しない
3042 param.Add("link[url]", SrcUrl)
3043 If Not (New HttpVarious).PostData("http://tweetburner.com/links", param, content) Then
3044 Return "Can't convert"
3047 If Not content.StartsWith("http://twurl.nl/") Then
3048 Return "Can't convert"
3050 Case UrlConverter.Unu
3051 If SrcUrl.StartsWith("http") Then
3052 If "http://u.nu/xxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
3053 ' 明らかに長くなると推測できる場合は圧縮しない
3057 If Not (New HttpVarious).PostData("http://u.nu/unu-api-simple?url=" + SrcUrl, Nothing, content) Then
3058 Return "Can't convert"
3061 If Not content.StartsWith("http://u.nu") Then
3062 Return "Can't convert"
3064 Case UrlConverter.Bitly, UrlConverter.Jmp
3065 Dim BitlyLogin As String = "tweenapi"
3066 Dim BitlyApiKey As String = "R_c5ee0e30bdfff88723c4457cc331886b"
3067 If _bitlyId <> "" Then
3068 BitlyLogin = _bitlyId
3069 BitlyApiKey = _bitlyKey
3071 Const BitlyApiVersion As String = "2.0.1"
3072 If SrcUrl.StartsWith("http") Then
3073 If "http://bit.ly/xxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
3074 ' 明らかに長くなると推測できる場合は圧縮しない
3078 Dim req As String = ""
3079 If ConverterType = UrlConverter.Bitly Then
3080 req = "http://api.bit.ly/shorten?version="
3082 req = "http://api.j.mp/shorten?version="
3084 req += BitlyApiVersion + _
3085 "&login=" + BitlyLogin + _
3086 "&apiKey=" + BitlyApiKey + _
3087 "&longUrl=" + SrcUrl
3088 If BitlyLogin <> "tweenapi" Then req += "&history=1"
3089 If Not (New HttpVarious).PostData(req, Nothing, content) Then
3090 Return "Can't convert"
3092 Dim rx As Regex = New Regex("""shortUrl"": ""(?<ShortUrl>.*?)""")
3093 If rx.Match(content).Success Then
3094 content = rx.Match(content).Groups("ShortUrl").Value
3098 If Not content.StartsWith("http://bit.ly") AndAlso Not content.StartsWith("http://j.mp") Then
3099 Return "Can't convert"
3103 Dim ch As Char() = {ControlChars.Cr, ControlChars.Lf}
3104 content = content.TrimEnd(ch)
3105 If src.Length < content.Length Then content = src ' 圧縮の結果逆に長くなった場合は圧縮前のURLを返す
3109 'Public Function MakeShortNicoms(ByVal SrcUrl As String) As String
3110 ' Dim content As String = ""
3112 ' If Not (New HttpVarious).GetData("http://nico.ms/q/" + SrcUrl, Nothing, content) Then
3113 ' Return "Can't convert"
3116 ' If content.StartsWith("http") Then
3119 ' Return "Can't convert"
3125 Public Function GetVersionInfo() As String
3126 Dim content As String = ""
3127 If Not (New HttpVarious).GetData("http://tween.sourceforge.jp/version2.txt?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), Nothing, content) Then
3128 Throw New Exception("GetVersionInfo Failed")
3133 Public Function GetTweenBinary(ByVal strVer As String) As String
3135 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/Tween" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
3136 Path.Combine(Application.StartupPath(), "TweenNew.exe")) Then
3137 Return "Err:Download failed"
3139 If Directory.Exists(Path.Combine(Application.StartupPath(), "en")) = False Then
3140 Directory.CreateDirectory(Path.Combine(Application.StartupPath(), "en"))
3142 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenRes" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
3143 Path.Combine(Application.StartupPath(), "en\Tween.resourcesNew.dll")) Then
3144 Return "Err:Download failed"
3146 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenUp.gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
3147 Path.Combine(Application.StartupPath(), "TweenUp.exe")) Then
3148 Return "Err:Download failed"
3150 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenDll" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
3151 Path.Combine(Application.StartupPath(), "TweenNew.XmlSerializers.dll")) Then
3152 Return "Err:Download failed"
3155 Catch ex As Exception
3156 Return "Err:Download failed"
3161 Public WriteOnly Property ListIcon() As ImageList
3162 Set(ByVal value As ImageList)
3167 Public WriteOnly Property DetailIcon() As Dictionary(Of String, Image)
3168 Set(ByVal value As Dictionary(Of String, Image))
3173 'Public Property DefaultTimeOut() As Integer
3175 ' Return _defaultTimeOut
3177 ' Set(ByVal value As Integer)
3178 ' _defaultTimeOut = value
3182 Public WriteOnly Property CountApi() As Integer
3184 Set(ByVal value As Integer)
3189 Public WriteOnly Property CountApiReply() As Integer
3191 Set(ByVal value As Integer)
3192 _countApiReply = value
3196 ' Public WriteOnly Property UsePostMethod() As Boolean
3197 ' Set(ByVal value As Boolean)
3198 ' _usePostMethod = False
3200 ' 'POSTメソッドが弾かれるためGETに固定(2009/4/9)
3202 ' _ApiMethod = MySocket.REQ_TYPE.ReqPOSTAPI
3204 ' _ApiMethod = MySocket.REQ_TYPE.ReqGetAPI
3207 ' _ApiMethod = MySocket.REQ_TYPE.ReqGetAPI
3212 Public Property ReadOwnPost() As Boolean
3216 Set(ByVal value As Boolean)
3217 _readOwnPost = value
3221 Public ReadOnly Property FollowersCount() As Integer
3223 Return _followersCount
3227 Public ReadOnly Property FriendsCount() As Integer
3229 Return _friendsCount
3233 Public ReadOnly Property StatusesCount() As Integer
3235 Return _statusesCount
3239 Public ReadOnly Property Location() As String
3245 Public ReadOnly Property Bio() As String
3251 Public WriteOnly Property UseSsl() As Boolean
3252 Set(ByVal value As Boolean)
3253 HttpTwitter.UseSsl = value
3255 _protocol = "https://"
3257 _protocol = "http://"
3262 Public WriteOnly Property BitlyId() As String
3263 Set(ByVal value As String)
3268 Public WriteOnly Property BitlyKey() As String
3269 Set(ByVal value As String)
3274 Public Function GetTimelineApi(ByVal read As Boolean, _
3275 ByVal gType As WORKERTYPE, _
3276 ByVal more As Boolean) As String
3278 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
3280 If _endingFlag Then Return ""
3282 Dim countQuery As Integer
3283 Dim res As HttpStatusCode
3284 Dim content As String = ""
3286 If gType = WORKERTYPE.Timeline Then
3288 res = twCon.HomeTimeline(_countApi, minHomeTimeline, 0, content)
3290 res = twCon.HomeTimeline(_countApi, 0, 0, content)
3292 countQuery = _countApi
3295 res = twCon.Mentions(_countApiReply, minMentions, 0, content)
3297 res = twCon.Mentions(_countApiReply, 0, 0, content)
3299 countQuery = _countApiReply
3301 Catch ex As Exception
3302 Return "Err:" + ex.Message
3305 Case HttpStatusCode.OK
3306 Case HttpStatusCode.Unauthorized
3307 Twitter.AccountState = ACCOUNT_STATE.Invalid
3308 Return "Check your Username/Password."
3309 Case HttpStatusCode.BadRequest
3310 Return "Err:API Limits?"
3312 Return "Err:" + res.ToString()
3315 Dim arIdx As Integer = -1
3316 Dim dlgt(countQuery) As GetIconImageDelegate 'countQueryに合わせる
3317 Dim ar(countQuery) As IAsyncResult 'countQueryに合わせる
3318 Dim xdoc As New XmlDocument
3320 xdoc.LoadXml(content)
3321 Catch ex As Exception
3323 'MessageBox.Show("不正なXMLです。(TL-LoadXml)")
3324 Return "Invalid XML!"
3327 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("./status")
3328 Dim xentry As XmlElement = CType(xentryNode, XmlElement)
3329 Dim post As New PostClass
3331 post.Id = Long.Parse(xentry.Item("id").InnerText)
3332 If gType = WORKERTYPE.Timeline Then
3333 If minHomeTimeline > post.Id Then minHomeTimeline = post.Id
3335 If minMentions > post.Id Then minMentions = post.Id
3339 If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
3342 Dim xRnode As XmlNode = xentry.SelectSingleNode("./retweeted_status")
3343 If xRnode IsNot Nothing Then
3344 Dim xRentry As XmlElement = CType(xRnode, XmlElement)
3345 post.PDate = DateTime.ParseExact(xRentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
3347 post.RetweetedId = Long.Parse(xRentry.Item("id").InnerText)
3349 post.Data = xRentry.Item("text").InnerText
3350 'Source取得(htmlの場合は、中身を取り出し)
3351 post.Source = xRentry.Item("source").InnerText
3353 Long.TryParse(xRentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
3354 post.InReplyToUser = xRentry.Item("in_reply_to_screen_name").InnerText
3355 'post.IsFav = TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.RetweetedId)
3356 post.IsFav = Boolean.Parse(xentry.Item("favorited").InnerText)
3359 Dim xRUentry As XmlElement = CType(xRentry.SelectSingleNode("./user"), XmlElement)
3360 post.Uid = Long.Parse(xRUentry.Item("id").InnerText)
3361 post.Name = xRUentry.Item("screen_name").InnerText
3362 post.Nickname = xRUentry.Item("name").InnerText
3363 post.ImageUrl = xRUentry.Item("profile_image_url").InnerText
3364 post.IsProtect = Boolean.Parse(xRUentry.Item("protected").InnerText)
3365 post.IsMe = post.Name.ToLower.Equals(_uid)
3368 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
3369 post.RetweetedBy = xUentry.Item("screen_name").InnerText
3371 post.PDate = DateTime.ParseExact(xentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
3373 post.Data = xentry.Item("text").InnerText
3374 'Source取得(htmlの場合は、中身を取り出し)
3375 post.Source = xentry.Item("source").InnerText
3376 Long.TryParse(xentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
3377 post.InReplyToUser = xentry.Item("in_reply_to_screen_name").InnerText
3378 'in_reply_to_user_idを使うか?
3379 post.IsFav = Boolean.Parse(xentry.Item("favorited").InnerText)
3382 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
3383 post.Uid = Long.Parse(xUentry.Item("id").InnerText)
3384 post.Name = xUentry.Item("screen_name").InnerText
3385 post.Nickname = xUentry.Item("name").InnerText
3386 post.ImageUrl = xUentry.Item("profile_image_url").InnerText
3387 post.IsProtect = Boolean.Parse(xUentry.Item("protected").InnerText)
3388 post.IsMe = post.Name.ToLower.Equals(_uid)
3391 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
3392 post.Data = HttpUtility.HtmlDecode(post.Data)
3393 post.Data = post.Data.Replace("<3", "♡")
3395 If post.Source.StartsWith("<") Then
3396 Dim rgS As New Regex(">(?<source>.+)<")
3397 Dim mS As Match = rgS.Match(post.Source)
3399 post.Source = mS.Result("${source}")
3404 If gType = WORKERTYPE.Timeline Then
3405 post.IsReply = post.ReplyToList.Contains(_uid)
3413 If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.Uid)
3415 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
3418 Catch ex As Exception
3420 'MessageBox.Show("不正なXMLです。(TL-Parse)")
3424 '非同期アイコン取得&StatusDictionaryに追加
3426 dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
3427 ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
3431 For i As Integer = 0 To arIdx
3433 dlgt(i).EndInvoke(ar(i))
3434 Catch ex As Exception
3435 '最後までendinvoke回す(ゾンビ化回避)
3436 ex.Data("IsTerminatePermission") = False
3441 'If _ApiMethod = MySocket.REQ_TYPE.ReqGetAPI Then _remainCountApi = sck.RemainCountApi
3446 Public Function GetSearch(ByVal read As Boolean, _
3447 ByVal tab As TabClass, _
3448 ByVal more As Boolean) As String
3450 If _endingFlag Then Return ""
3452 Dim res As HttpStatusCode
3453 Dim content As String = ""
3454 Dim page As Integer = 0
3455 If more Then page = tab.SearchPage
3457 res = twCon.Search(tab.SearchWords, tab.SearchLang, 40, page, content)
3458 Catch ex As Exception
3459 Return "Err:" + ex.Message
3462 Case HttpStatusCode.BadRequest
3463 Return "Invalid query"
3464 Case HttpStatusCode.NotFound
3465 Return "Invalid query"
3466 Case HttpStatusCode.PaymentRequired 'API Documentには420と書いてあるが、該当コードがないので402にしてある
3467 Return "Search API Limit?"
3468 Case HttpStatusCode.OK
3470 Return "Err:" + res.ToString
3473 If Not TabInformations.GetInstance.ContainsTab(tab) Then Return ""
3475 Dim arIdx As Integer = -1
3476 Dim dlgt(40) As GetIconImageDelegate 'countQueryに合わせる
3477 Dim ar(40) As IAsyncResult 'countQueryに合わせる
3478 Dim xdoc As New XmlDocument
3480 xdoc.LoadXml(content)
3481 Catch ex As Exception
3483 Return "Invalid ATOM!"
3485 Dim nsmgr As New XmlNamespaceManager(xdoc.NameTable)
3486 nsmgr.AddNamespace("search", "http://www.w3.org/2005/Atom")
3487 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/search:feed/search:entry", nsmgr)
3488 Dim xentry As XmlElement = CType(xentryNode, XmlElement)
3489 Dim post As New PostClass
3491 post.Id = Long.Parse(xentry.Item("id").InnerText.Split(":"c)(2))
3492 If TabInformations.GetInstance.ContainsKey(post.Id, tab.TabName) Then Continue For
3493 post.PDate = DateTime.Parse(xentry.Item("published").InnerText)
3495 post.Data = xentry.Item("title").InnerText
3496 'Source取得(htmlの場合は、中身を取り出し)
3497 post.Source = xentry.Item("twitter:source").InnerText
3498 post.InReplyToId = 0
3499 post.InReplyToUser = ""
3503 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./search:author", nsmgr), XmlElement)
3505 post.Name = xUentry.Item("name").InnerText.Split(" "c)(0).Trim
3506 post.Nickname = xUentry.Item("name").InnerText.Substring(post.Name.Length).Trim
3507 If post.Nickname.Length > 2 Then
3508 post.Nickname = post.Nickname.Substring(1, post.Nickname.Length - 2)
3510 post.Nickname = post.Name
3512 post.ImageUrl = CType(xentry.SelectSingleNode("./search:link[@type='image/png']", nsmgr), XmlElement).GetAttribute("href")
3513 post.IsProtect = False
3514 post.IsMe = post.Name.ToLower.Equals(_uid)
3517 post.OriginalData = CreateHtmlAnchor(HttpUtility.HtmlEncode(post.Data), post.ReplyToList)
3518 post.Data = HttpUtility.HtmlDecode(post.Data)
3520 If post.Source.StartsWith("<") Then
3521 Dim rgS As New Regex(">(?<source>.+)<")
3522 Dim mS As Match = rgS.Match(post.Source)
3524 post.Source = mS.Result("${source}")
3529 post.IsReply = post.ReplyToList.Contains(_uid)
3532 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
3534 post.SearchTabName = tab.TabName
3535 Catch ex As Exception
3540 '非同期アイコン取得&StatusDictionaryに追加
3542 dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
3543 ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
3547 '' 遡るための情報max_idやnext_pageの情報を保持する
3550 For i As Integer = 0 To arIdx
3552 dlgt(i).EndInvoke(ar(i))
3553 Catch ex As Exception
3554 '最後までendinvoke回す(ゾンビ化回避)
3555 ex.Data("IsTerminatePermission") = False
3563 Public Function GetDirectMessageApi(ByVal read As Boolean, _
3564 ByVal gType As WORKERTYPE, _
3565 ByVal more As Boolean) As String
3566 If _endingFlag Then Return ""
3568 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
3570 Dim res As HttpStatusCode
3571 Dim content As String = ""
3574 If gType = WORKERTYPE.DirectMessegeRcv Then
3576 res = twCon.DirectMessages(20, minDirectmessage, 0, content)
3578 res = twCon.DirectMessages(20, 0, 0, content)
3582 res = twCon.DirectMessagesSent(20, minDirectmessageSent, 0, content)
3584 res = twCon.DirectMessagesSent(20, 0, 0, content)
3587 Catch ex As Exception
3588 Return "Err:" + ex.Message
3592 Case HttpStatusCode.OK
3593 Case HttpStatusCode.Unauthorized
3594 Twitter.AccountState = ACCOUNT_STATE.Invalid
3595 Return "Check your Username/Password."
3596 Case HttpStatusCode.BadRequest
3597 Return "Err:API Limits?"
3599 Return "Err:" + res.ToString()
3602 Dim arIdx As Integer = -1
3603 Dim dlgt(20) As GetIconImageDelegate 'countQueryに合わせる
3604 Dim ar(20) As IAsyncResult 'countQueryに合わせる
3605 Dim xdoc As New XmlDocument
3607 xdoc.LoadXml(content)
3608 Catch ex As Exception
3610 'MessageBox.Show("不正なXMLです。(DM-LoadXml)")
3611 Return "Invalid XML!"
3614 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("./direct_message")
3615 Dim xentry As XmlElement = CType(xentryNode, XmlElement)
3616 Dim post As New PostClass
3618 post.Id = Long.Parse(xentry.Item("id").InnerText)
3619 If gType = WORKERTYPE.DirectMessegeRcv Then
3620 If minDirectmessage > post.Id Then minDirectmessage = post.Id
3622 If minDirectmessageSent > post.Id Then minDirectmessageSent = post.Id
3626 If TabInformations.GetInstance.GetTabByType(TabUsageType.DirectMessage).Contains(post.Id) Then Continue For
3630 post.PDate = DateTime.ParseExact(xentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
3632 post.Data = xentry.Item("text").InnerText
3634 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
3635 post.Data = HttpUtility.HtmlDecode(post.Data)
3636 post.Data = post.Data.Replace("<3", "♡")
3639 If gType = WORKERTYPE.DirectMessegeRcv Then
3646 Dim xUentry As XmlElement
3647 If gType = WORKERTYPE.DirectMessegeRcv Then
3648 xUentry = CType(xentry.SelectSingleNode("./sender"), XmlElement)
3651 xUentry = CType(xentry.SelectSingleNode("./recipient"), XmlElement)
3654 post.Uid = Long.Parse(xUentry.Item("id").InnerText)
3655 post.Name = xUentry.Item("screen_name").InnerText
3656 post.Nickname = xUentry.Item("name").InnerText
3657 post.ImageUrl = xUentry.Item("profile_image_url").InnerText
3658 post.IsProtect = Boolean.Parse(xUentry.Item("protected").InnerText)
3659 Catch ex As Exception
3661 'MessageBox.Show("不正なXMLです。(DM-Parse)")
3666 post.IsReply = False
3669 '非同期アイコン取得&StatusDictionaryに追加
3671 dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
3672 ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
3676 For i As Integer = 0 To arIdx
3678 dlgt(i).EndInvoke(ar(i))
3679 Catch ex As Exception
3680 '最後までendinvoke回す(ゾンビ化回避)
3681 ex.Data("IsTerminatePermission") = False
3686 '_remainCountApi = sck.RemainCountApi
3687 'If _ApiMethod = MySocket.REQ_TYPE.ReqGetAPI Then _remainCountApi = sck.RemainCountApi
3692 Public Function GetFavoritesApi(ByVal read As Boolean, _
3693 ByVal gType As WORKERTYPE) As String
3695 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
3697 If _endingFlag Then Return ""
3699 Dim res As HttpStatusCode
3700 Dim content As String = ""
3702 res = twCon.Favorites(_countApi, content)
3703 Catch ex As Exception
3704 Return "Err:" + ex.Message
3708 Case HttpStatusCode.OK
3709 Case HttpStatusCode.Unauthorized
3710 Twitter.AccountState = ACCOUNT_STATE.Invalid
3711 Return "Check your Username/Password."
3712 Case HttpStatusCode.BadRequest
3713 Return "Err:API Limits?"
3715 Return "Err:" + res.ToString()
3718 Dim arIdx As Integer = -1
3719 Dim dlgt(_countApi) As GetIconImageDelegate 'countQueryに合わせる
3720 Dim ar(_countApi) As IAsyncResult 'countQueryに合わせる
3721 Dim xdoc As New XmlDocument
3723 xdoc.LoadXml(content)
3724 Catch ex As Exception
3726 'MessageBox.Show("不正なXMLです。(TL-LoadXml)")
3727 Return "Invalid XML!"
3730 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("./status")
3731 Dim xentry As XmlElement = CType(xentryNode, XmlElement)
3732 Dim post As New PostClass
3734 post.Id = Long.Parse(xentry.Item("id").InnerText)
3735 If minFavorites > post.Id Then minFavorites = post.Id
3738 If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
3741 Dim xRnode As XmlNode = xentry.SelectSingleNode("./retweeted_status")
3742 If xRnode IsNot Nothing Then
3743 Dim xRentry As XmlElement = CType(xRnode, XmlElement)
3744 post.PDate = DateTime.ParseExact(xRentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
3746 post.RetweetedId = Long.Parse(xRentry.Item("id").InnerText)
3748 post.Data = xRentry.Item("text").InnerText
3749 'Source取得(htmlの場合は、中身を取り出し)
3750 post.Source = xRentry.Item("source").InnerText
3752 Long.TryParse(xRentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
3753 post.InReplyToUser = xRentry.Item("in_reply_to_screen_name").InnerText
3754 'in_reply_to_user_idを使うか?
3755 post.IsFav = Boolean.Parse(xRentry.Item("favorited").InnerText)
3758 Dim xRUentry As XmlElement = CType(xRentry.SelectSingleNode("./user"), XmlElement)
3759 post.Uid = Long.Parse(xRUentry.Item("id").InnerText)
3760 post.Name = xRUentry.Item("screen_name").InnerText
3761 post.Nickname = xRUentry.Item("name").InnerText
3762 post.ImageUrl = xRUentry.Item("profile_image_url").InnerText
3763 post.IsProtect = Boolean.Parse(xRUentry.Item("protected").InnerText)
3764 post.IsMe = post.Name.ToLower.Equals(_uid)
3767 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
3768 post.RetweetedBy = xUentry.Item("screen_name").InnerText
3770 post.PDate = DateTime.ParseExact(xentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
3772 post.Data = xentry.Item("text").InnerText
3773 'Source取得(htmlの場合は、中身を取り出し)
3774 post.Source = xentry.Item("source").InnerText
3775 Long.TryParse(xentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
3776 post.InReplyToUser = xentry.Item("in_reply_to_screen_name").InnerText
3777 'in_reply_to_user_idを使うか?
3778 post.IsFav = Boolean.Parse(xentry.Item("favorited").InnerText)
3781 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
3782 post.Uid = Long.Parse(xUentry.Item("id").InnerText)
3783 post.Name = xUentry.Item("screen_name").InnerText
3784 post.Nickname = xUentry.Item("name").InnerText
3785 post.ImageUrl = xUentry.Item("profile_image_url").InnerText
3786 post.IsProtect = Boolean.Parse(xUentry.Item("protected").InnerText)
3787 post.IsMe = post.Name.ToLower.Equals(_uid)
3790 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
3791 post.Data = HttpUtility.HtmlDecode(post.Data)
3792 post.Data = post.Data.Replace("<3", "♡")
3794 If post.Source.StartsWith("<") Then
3795 Dim rgS As New Regex(">(?<source>.+)<")
3796 Dim mS As Match = rgS.Match(post.Source)
3798 post.Source = mS.Result("${source}")
3803 post.IsReply = post.ReplyToList.Contains(_uid)
3808 If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.Uid)
3812 Catch ex As Exception
3814 'MessageBox.Show("不正なXMLです。(TL-Parse)")
3818 '非同期アイコン取得&StatusDictionaryに追加
3820 dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
3821 ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
3825 For i As Integer = 0 To arIdx
3827 dlgt(i).EndInvoke(ar(i))
3828 Catch ex As Exception
3829 '最後までendinvoke回す(ゾンビ化回避)
3830 ex.Data("IsTerminatePermission") = False
3835 '_remainCountApi = sck.RemainCountApi
3836 'If _ApiMethod = MySocket.REQ_TYPE.ReqGetAPI Then _remainCountApi = sck.RemainCountApi
3841 Public Function GetFollowersApi() As String
3842 If _endingFlag Then Return ""
3843 Dim cursor As Long = -1
3844 Dim tmpFollower As New List(Of Long)(followerId)
3848 Dim ret As String = FollowerApi(cursor)
3851 followerId.AddRange(tmpFollower)
3854 Loop While cursor > 0
3856 TabInformations.GetInstance.RefreshOwl(followerId)
3861 Private Function FollowerApi(ByRef cursor As Long) As String
3862 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
3864 Dim res As HttpStatusCode
3865 Dim content As String = ""
3867 res = twCon.FollowerIds(cursor, content)
3868 Catch ex As Exception
3869 Return "Err:" + ex.Message
3873 Case HttpStatusCode.OK
3874 Case HttpStatusCode.Unauthorized
3875 Twitter.AccountState = ACCOUNT_STATE.Invalid
3876 Return "Check your Username/Password."
3877 Case HttpStatusCode.BadRequest
3878 Return "Err:API Limits?"
3880 Return "Err:" + res.ToString()
3883 Dim xdoc As New XmlDocument
3885 xdoc.LoadXml(content)
3886 Catch ex As Exception
3888 Return "Invalid XML!"
3892 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/id_list/ids/id")
3893 followerId.Add(Long.Parse(xentryNode.InnerText))
3895 cursor = Long.Parse(xdoc.DocumentElement.SelectSingleNode("/id_list/next_cursor").InnerText)
3896 Catch ex As Exception
3898 Return "Invalid XML!"
3905 Private Function CreateHtmlAnchor(ByVal Text As String, ByVal AtList As List(Of String)) As String
3906 'Dim retStr As String = HttpUtility.HtmlEncode(Text) '要検証(デコードされて取得されるので再エンコード)
3907 'Dim retStr As String = HttpUtility.HtmlDecode(Text)
3908 Dim retStr As String = ""
3910 'Dim rgUrl As Regex = New Regex("(?<![0-9A-Za-z=])(?:https?|shttp|ftps?)://(?:(?:[-_.!~*'()a-zA-Z0-9;:&=+$,]|%[0-9A-Fa-f" + _
3911 ' "][0-9A-Fa-f])*@)?(?:(?:[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?\.)" + _
3912 ' "*[a-zA-Z](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?\.?|[0-9]+\.[0-9]+\.[0-9]+\." + _
3913 ' "[0-9]+)(?::[0-9]*)?(?:/(?:[-_.!~*'()a-zA-Z0-9:@&=+$,]|%[0-9A-Fa-f]" + _
3914 ' "[0-9A-Fa-f])*(?:;(?:[-_.!~*'()a-zA-Z0-9:@&=+$,]|%[0-9A-Fa-f][0-9A-" + _
3915 ' "Fa-f])*)*(?:/(?:[-_.!~*'()a-zA-Z0-9:@&=+$,]|%[0-9A-Fa-f][0-9A-Fa-f" + _
3916 ' "])*(?:;(?:[-_.!~*'()a-zA-Z0-9:@&=+$,]|%[0-9A-Fa-f][0-9A-Fa-f])*)*)" + _
3917 ' "*)?(?:\?(?:[-_.!~*'()a-zA-Z0-9;/?:@&=+$,]|%[0-9A-Fa-f][0-9A-Fa-f])" + _
3918 ' "*)?(?:#(?:[-_.!~*'()a-zA-Z0-9;/?:@&=+$,]|%[0-9A-Fa-f][0-9A-Fa-f])*)?")
3919 Dim rgUrl As Regex = New Regex("(?<before>(?:[^\/""':!=]|^|\:))" + _
3920 "(?<url>(?<protocol>https?://|www\.)" + _
3921 "(?<domain>(?:[\.-]|[^\p{P}])+\.[a-z]{2,}(?::[0-9]+)?)" + _
3922 "(?<path>/[a-z0-9!*'();:&=+$/%#\[\]\-_.,~]*[a-z0-9)=#/]?)?" + _
3923 "(?<query>\?[a-z0-9!*'();:&=+$/%#\[\]\-_.,~]*[a-z0-9_&=#])?)", RegexOptions.IgnoreCase Or RegexOptions.Compiled)
3925 retStr = rgUrl.Replace(Text, New MatchEvaluator(AddressOf AutoLinkUrl))
3928 'Dim rg As New Regex("(^|[ -/:-@[-^`{-~])@([a-zA-Z0-9_]{1,20}/[a-zA-Z0-9_\-]{1,24}[a-zA-Z0-9_])")
3929 Dim rg As New Regex("(^|[^a-zA-Z0-9_])[@@]([a-zA-Z0-9_]{1,20}/[a-zA-Z0-9_\-]{1,79}[a-zA-Z0-9_])", RegexOptions.Compiled)
3930 Dim m As Match = rg.Match(retStr)
3932 retStr = rg.Replace(retStr, "$1@<a href=""/$2"">$2</a>")
3934 'rg = New Regex("(^|[ -/:-@[-^`{-~])@([a-zA-Z0-9_]{1,20})")
3935 rg = New Regex("(^|[^a-zA-Z0-9_])[@@]([a-zA-Z0-9_]{1,20})", RegexOptions.Compiled)
3936 m = rg.Match(retStr)
3938 AtList.Add(m.Result("$2").ToLower)
3942 retStr = rg.Replace(retStr, "$1@<a href=""/$2"">$2</a>")
3945 'Dim rgh As New Regex("(^|[ .!,\-:;<>?])#([^] !""#$%&'()*+,.:;<=>?@\-[\^`{|}~\r\n]+)")
3946 Dim rgh As New Regex("(^|[^a-zA-Z0-9_/&])[##]([a-zA-Z0-9_]+)", RegexOptions.Compiled)
3947 Dim mhs As MatchCollection = rgh.Matches(retStr)
3948 For Each mt As Match In mhs
3949 If Not IsNumeric(mt.Result("$2")) Then
3950 'retStr = retStr.Replace(mt.Result("$1") + mt.Result("$2"), "<a href=""" + _protocol + "twitter.com/search?q=%23" + mt.Result("$2") + """>#" + mt.Result("$2") + "</a>")
3952 _hashList.Add("#" + mt.Result("$2"))
3956 retStr = rgh.Replace(retStr, New MatchEvaluator(AddressOf AutoLinkHashtag))
3958 retStr = AdjustHtml(ShortUrlResolve(PreProcessUrl(retStr))) 'IDN置換、短縮Uri解決、@リンクを相対→絶対にしてtarget属性付与
3962 Private Function AutoLinkUrl(ByVal m As Match) As String
3963 Dim sb As New StringBuilder(m.Result("${before}<a href="""))
3964 If m.Result("${protocol}").StartsWith("w", StringComparison.OrdinalIgnoreCase) Then
3965 sb.Append("http://")
3967 sb.Append(m.Result("${url}"">")).Append(m.Result("${url}")).Append("</a>")
3971 Private Function AutoLinkHashtag(ByVal m As Match) As String
3972 If IsNumeric(m.Result("$2")) Then Return m.Result("$1#$2")
3973 Dim sb As New StringBuilder(m.Result("$1<a href="""))
3974 Return sb.Append(_protocol).Append("twitter.com/search?q=%23").Append(m.Result("$2"">#$2</a>")).ToString
3977 Public ReadOnly Property RemainCountApi() As Integer
3979 Return twCon.RemainCountApi
3983 Public Function GetInfoApi(ByRef info As ApiInfo) As Boolean
3984 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return True
3986 If _endingFlag Then Return True
3988 'info.MaxCount = twCon.UpperCountApi
3989 'info.RemainCount = twCon.RemainCountApi
3990 'info.ResetTime = twCon.ResetTimeApi
3992 Dim res As HttpStatusCode
3993 Dim content As String = ""
3995 res = twCon.RateLimitStatus(content)
3996 Catch ex As Exception
4000 If res <> HttpStatusCode.OK Then Return False
4002 Dim xdoc As New XmlDocument
4004 xdoc.LoadXml(content)
4005 info.MaxCount = Integer.Parse(xdoc.SelectSingleNode("/hash/hourly-limit").InnerText)
4006 info.RemainCount = Integer.Parse(xdoc.SelectSingleNode("/hash/remaining-hits").InnerText)
4007 info.ResetTime = DateTime.Parse(xdoc.SelectSingleNode("/hash/reset-time").InnerText)
4008 'info.ResetTimeInSeconds = Integer.Parse(xdoc.SelectSingleNode("/hash/reset-time-in-seconds").InnerText)
4010 Catch ex As Exception
4015 Public Function GetHashList() As String()
4016 Dim hashArray As String()
4018 hashArray = _hashList.ToArray
4024 '#Region "デバッグモード解析キー自動生成"
4026 ' Public Sub GenerateAnalyzeKey()
4027 ' '解析キー情報部分のソースをwedataから作成する
4028 ' '生成したソースはプロジェクトのディレクトリにコピーする
4029 ' Dim sw As New System.IO.StreamWriter(".\AnalyzeKey.vb", _
4031 ' System.Text.Encoding.UTF8)
4033 ' sw.WriteLine("Public Module AnalyzeKey")
4034 ' sw.WriteLine("' このファイルはデバッグビルドのTweenにより自動作成されました 作成日時 " + DateAndTime.Now.ToString())
4037 ' sw.WriteLine(" Public _splitPost As String = " + Chr(34) + _splitPost.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4038 ' sw.WriteLine(" Public _splitPostRecent As String = " + Chr(34) + _splitPostRecent.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4039 ' sw.WriteLine(" Public _statusIdTo As String = " + Chr(34) + _statusIdTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4040 ' sw.WriteLine(" Public _splitDM As String = " + Chr(34) + _splitDM.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4041 ' sw.WriteLine(" Public _parseName As String = " + Chr(34) + _parseName.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4042 ' sw.WriteLine(" Public _parseNameTo As String = " + Chr(34) + _parseNameTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4043 ' sw.WriteLine(" Public _parseNick As String = " + Chr(34) + _parseNick.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4044 ' sw.WriteLine(" Public _parseNickTo As String = " + Chr(34) + _parseNickTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4045 ' sw.WriteLine(" Public _parseImg As String = " + Chr(34) + _parseImg.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4046 ' sw.WriteLine(" Public _parseImgTo As String = " + Chr(34) + _parseImgTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4047 ' sw.WriteLine(" Public _parseMsg1 As String = " + Chr(34) + _parseMsg1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4048 ' sw.WriteLine(" Public _parseMsg2 As String = " + Chr(34) + _parseMsg2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4049 ' sw.WriteLine(" Public _parseDM1 As String = " + Chr(34) + _parseDM1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4050 ' sw.WriteLine(" Public _parseDM11 As String = " + Chr(34) + _parseDM11.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4051 ' sw.WriteLine(" Public _parseDM2 As String = " + Chr(34) + _parseDM2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4052 ' sw.WriteLine(" Public _parseDate As String = " + Chr(34) + _parseDate.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4053 ' sw.WriteLine(" Public _parseDateTo As String = " + Chr(34) + _parseDateTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4054 ' sw.WriteLine(" Public _getAuthKey As String = " + Chr(34) + _getAuthKey.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4055 ' sw.WriteLine(" Public _getAuthKeyTo As String = " + Chr(34) + _getAuthKeyTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4056 ' 'sw.WriteLine(" Public _parseStar As String = " + Chr(34) + _parseStar.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4057 ' 'sw.WriteLine(" Public _parseStarTo As String = " + Chr(34) + _parseStarTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4058 ' 'sw.WriteLine(" Public _parseStarEmpty As String = " + Chr(34) + _parseStarEmpty.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4059 ' sw.WriteLine(" Public _followerList As String = " + Chr(34) + _followerList.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4060 ' sw.WriteLine(" Public _followerMbr1 As String = " + Chr(34) + _followerMbr1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4061 ' sw.WriteLine(" Public _followerMbr2 As String = " + Chr(34) + _followerMbr2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4062 ' sw.WriteLine(" Public _followerMbr3 As String = " + Chr(34) + _followerMbr3.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4063 ' sw.WriteLine(" Public _getInfoTwitter As String = " + Chr(34) + _getInfoTwitter.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4064 ' sw.WriteLine(" Public _getInfoTwitterTo As String = " + Chr(34) + _getInfoTwitterTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4065 ' sw.WriteLine(" Public _isProtect As String = " + Chr(34) + _isProtect.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4066 ' sw.WriteLine(" Public _isReplyEng As String = " + Chr(34) + _isReplyEng.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4067 ' sw.WriteLine(" Public _isReplyJpn As String = " + Chr(34) + _isReplyJpn.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4068 ' sw.WriteLine(" Public _isReplyTo As String = " + Chr(34) + _isReplyTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4069 ' sw.WriteLine(" Public _parseProtectMsg1 As String = " + Chr(34) + _parseProtectMsg1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4070 ' sw.WriteLine(" Public _parseProtectMsg2 As String = " + Chr(34) + _parseProtectMsg2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4071 ' sw.WriteLine(" Public _parseDMcountFrom As String = " + Chr(34) + _parseDMcountFrom.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4072 ' sw.WriteLine(" Public _parseDMcountTo As String = " + Chr(34) + _parseDMcountTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4073 ' sw.WriteLine(" Public _parseSourceFrom As String = " + Chr(34) + _parseSourceFrom.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4074 ' sw.WriteLine(" Public _parseSource2 As String = " + Chr(34) + _parseSource2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4075 ' sw.WriteLine(" Public _parseSourceTo As String = " + Chr(34) + _parseSourceTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4076 ' sw.WriteLine(" Public _removeClass As String = " + Chr(34) + _removeClass.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4077 ' sw.WriteLine("End Module")
4080 ' 'MessageBox.Show("解析キー情報定義ファイル AnalyzeKey.vbを生成しました")
4086 Public ReadOnly Property AccessToken() As String
4088 Return twCon.AccessToken
4092 Public ReadOnly Property AccessTokenSecret() As String
4094 Return twCon.AccessTokenSecret