OSDN Git Service

listsの発言を無条件に返信扱いしていたバグ修正
[opentween/open-tween.git] / Tween / Twitter.vb
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/>
5 ' All rights reserved.
6
7 ' This file is part of Tween.
8
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)
12 ' any later version.
13
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
17 ' for more details. 
18
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.
23
24 Imports System.Web
25 Imports System.Xml
26 Imports System.Text
27 Imports System.Threading
28 Imports System.IO
29 Imports System.Text.RegularExpressions
30 Imports System.Globalization
31 Imports System.Diagnostics
32 Imports System.Net
33
34 Public Class Twitter
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)
47
48     'Private follower As New List(Of String)
49     Private followerId As New List(Of Long)
50     'Private tmpFollower As New List(Of String)
51
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 = ""
61
62     'プロパティからアクセスされる共通情報
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
70
71     'Private _nextThreshold As Integer
72     'Private _nextPages As Integer
73
74     Private _iconSz As Integer
75     Private _getIcon As Boolean
76     Private _lIcon As ImageList
77     Private _dIcon As Dictionary(Of String, Image)
78
79     Private _tinyUrlResolve As Boolean
80     Private _restrictFavCheck As Boolean
81     'Private _useAPI As Boolean
82
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)
91
92     '共通で使用する状態
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
99
100     Private _ShortUrlService() As String = { _
101             "http://tinyurl.com/", _
102             "http://is.gd/", _
103             "http://snipurl.com/", _
104             "http://snurl.com/", _
105             "http://nsfw.in/", _
106             "http://qurlyq.com/", _
107             "http://dwarfurl.com/", _
108             "http://icanhaz.com/", _
109             "http://tiny.cc/", _
110             "http://urlenco.de/", _
111             "http://bit.ly/", _
112             "http://piurl.com/", _
113             "http://linkbee.com/", _
114             "http://traceurl.com/", _
115             "http://twurl.nl/", _
116             "http://cli.gs/", _
117             "http://rubyurl.com/", _
118             "http://budurl.com/", _
119             "http://ff.im/", _
120             "http://twitthis.com/", _
121             "http://blip.fm/", _
122             "http://tumblr.com/", _
123             "http://www.qurl.com/", _
124             "http://digg.com/", _
125             "http://u.nu/", _
126             "http://ustre.am/", _
127             "http://pic.gd/", _
128             "http://airme.us/", _
129             "http://qurl.com/", _
130             "http://bctiny.com/", _
131             "http://j.mp/", _
132             "http://goo.gl/", _
133             "http://ow.ly/", _
134             "http://bkite.com/", _
135             "http://youtu.be/", _
136             "http://dlvr.it/", _
137             "http://p.tl/", _
138             "http://flic.kr/" _
139         }
140
141     Private Const _apiHost As String = "api."
142     Private Const _baseUrlStr As String = "twitter.com"
143     'Private Const _loginPath As String = "/sessions"
144     'Private Const _homePath As String = "/home"
145     'Private Const _replyPath As String = "/replies"
146     'Private Const _DMPathRcv As String = "/inbox"
147     'Private Const _DMPathSnt As String = "/sent"
148     Private Const _DMDestroyPath As String = "/1/direct_messages/destroy/"
149     Private Const _StDestroyPath As String = "/1/statuses/destroy/"
150     Private Const _postRetweetPath As String = "/1/statuses/retweet/"
151     Private Const _uidHeader As String = "session[username_or_email]="
152     Private Const _pwdHeader As String = "session[password]="
153     Private Const _pageQry As String = "?page="
154     Private Const _cursorQry As String = "?cursor="
155     Private Const _statusHeader As String = "status="
156     Private Const _statusUpdatePathAPI As String = "/1/statuses/update.xml"
157     'Private Const _linkToOld As String = "class=""section_links"" rel=""prev"""
158     Private Const _postFavAddPath As String = "/1/favorites/create/"
159     Private Const _postFavRemovePath As String = "/1/favorites/destroy/"
160     'Private Const _authKeyHeader As String = "authenticity_token="
161     'Private Const _parseLink1 As String = "<a href="""
162     'Private Const _parseLink2 As String = """>"
163     'Private Const _parseLink3 As String = "</a>"
164     Private Const _GetFollowers As String = "/1/statuses/followers.xml"
165     Private Const _ShowStatus As String = "/1/statuses/show/"
166     Private Const _rateLimitStatus As String = "/1/account/rate_limit_status.xml"
167     Private Const FOLLOWER_PATH As String = "/1/followers/ids.xml"
168     Private Const RECEIVE_PATH As String = "/1/direct_messages.xml"
169     Private Const SENT_PATH As String = "/1/direct_messages/sent.xml"
170     Private Const COUNT_QUERY As String = "count="
171     Private Const FAV_PATH As String = "/1/favorites.xml"
172     Private Const PATH_FRIENDSHIP As String = "/1/friendships/show.xml?source_screen_name="
173     Private Const QUERY_TARGET As String = "&target_screen_name="
174     Private Const FRIEND_PATH As String = "/1/statuses/home_timeline.xml"
175     Private Const REPLY_PATH As String = "/1/statuses/mentions.xml"
176     Private Const PATH_FOLLOW As String = "/1/friendships/create.xml?screen_name="
177     Private Const PATH_REMOVE As String = "/1/friendships/destroy.xml?screen_name="
178
179
180
181     '''<summary>
182     '''OAuthのアクセストークン取得先URI
183     '''</summary>
184     Private Const AccessTokenUrl As String = "http://twitter.com/oauth/access_token"
185
186     '''<summary>
187     '''OAuthのリクエストトークン取得先URI
188     '''</summary>
189     Private Const RequestTokenUrl As String = "http://twitter.com/oauth/request_token"
190
191     '''<summary>
192     '''OAuthのユーザー認証用ページURI
193     '''</summary>
194     '''<remarks>
195     '''クエリ「oauth_token=リクエストトークン」を付加して、このURIをブラウザで開く。ユーザーが承認操作を行うとPINコードが表示される。
196     '''</remarks>
197     Private Const AuthorizeUrl As String = "http://twitter.com/oauth/authorize"
198
199     ''''Wedata対応
200     'Private Const wedataUrl As String = "http://wedata.net/databases/Tween/items.json"
201
202     Private op As New Outputz
203     'max_idで古い発言を取得するために保持(lists分は個別タブで管理)
204     Private minHomeTimeline As Long = Long.MaxValue
205     Private minMentions As Long = Long.MaxValue
206     Private minDirectmessage As Long = Long.MaxValue
207     Private minDirectmessageSent As Long = Long.MaxValue
208     Private minFavorites As Long = Long.MaxValue
209
210     Private twCon As New HttpTwitter
211
212     Public Function Authenticate(ByVal username As String, ByVal password As String) As Boolean
213         Try
214             Dim rslt As Boolean = twCon.AuthUserAndPass(username, password)
215             If rslt Then
216                 _uid = twCon.AuthenticatedUsername.ToLower
217             End If
218             Return rslt
219         Catch ex As Exception
220             Return False
221         End Try
222     End Function
223
224     Public Sub ClearAuthInfo()
225         twCon.ClearAuthInfo()
226     End Sub
227
228     Public Sub Initialize(ByVal token As String, ByVal tokenSecret As String, ByVal username As String)
229         'xAuth認証
230         twCon.Initialize(token, tokenSecret, username)
231         _uid = username.ToLower
232     End Sub
233
234     Public Sub Initialize(ByVal username As String, ByVal password As String)
235         'BASIC認証
236         twCon.Initialize(username, password)
237         _uid = username.ToLower
238     End Sub
239
240     'Private Function SignIn() As String
241     '    If _endingFlag Then Return ""
242
243     '    'ユーザー情報からデータ部分の生成
244     '    Dim account As String = ""
245     '    Static skipCount As Integer = 0
246
247     '    SyncLock LockObj
248     '        If _signed Then Return ""
249     '        If Twitter.AccountState <> ACCOUNT_STATE.Valid AndAlso skipCount < 10 Then
250     '            skipCount += 1
251     '            Return "SignIn -> Check Username/Password in setting."
252     '        End If
253     '        skipCount = 0
254
255     '        '未認証
256     '        _signed = False
257
258     '        MySocket.ResetCookie()
259
260     '        Dim resStatus As String = ""
261     '        Dim resMsg As String = ""
262
263     '        '設定によらずログイン処理はhttps固定
264     '        resMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + "/login", resStatus, MySocket.REQ_TYPE.ReqGET), String)
265     '        If resMsg.Length = 0 Then
266     '            'Twitter.AccountState = ACCOUNT_STATE.Invalid
267     '            Return "SignIn -> " + resStatus
268     '        End If
269     '        Dim authToken As String = ""
270     '        Dim rg As New Regex("authenticity_token"" type=""hidden"" value=""(?<auth>[a-z0-9]+)""")
271     '        Dim m As Match = rg.Match(resMsg)
272     '        If m.Success Then
273     '            authToken = m.Result("${auth}")
274     '        Else
275     '            Return "SignIn -> Can't get token."
276     '        End If
277
278     '        account = _authKeyHeader + authToken + "&" + _uidHeader + _uid + "&" + _pwdHeader + HttpUtility.UrlEncode(_pwd) + "&" + "remember_me=1"
279
280     '        'https固定
281     '        resMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _loginPath, resStatus, MySocket.REQ_TYPE.ReqPOST, account), String)
282     '        If resStatus.StartsWith("OK") Then
283     '            'OK (username/passwordが合致しない)
284     '            Dim msg As String = resStatus
285     '            If resMsg.Contains("Wrong Username/Email and password combination.") Then
286     '                msg = "Wrong Username or password."
287     '            Else
288     '                '未知の応答(May be required Chapta)
289     '                msg = "Wrong Username or password. Try from web."
290     '            End If
291     '            Twitter.AccountState = ACCOUNT_STATE.Invalid
292     '            Return "SignIn Failed -> " + msg
293     '        ElseIf resMsg.Contains("https://twitter.com/account/locked") Then   '302 FOUND
294     '            Dim msg As String = "You account is Locked Out."
295     '            Twitter.AccountState = ACCOUNT_STATE.Invalid
296     '            Return "SignIn Failed -> " + msg
297     '        ElseIf resMsg.Contains("https://twitter.com:443/") Then '302 FOUND
298     '            'OK
299     '        ElseIf resMsg.Contains("https://twitter.com/") OrElse _
300     '               resMsg.Contains("http://twitter.com/") Then '302 FOUND
301     '            'OK
302     '        ElseIf resStatus.StartsWith("Err:") Then
303     '            ' その他プロトコルエラー
304     '            Return "SignIn Failed"
305     '        Else
306     '            '応答がOK でありサインインできていない場合の未知の応答
307     '            'TraceOut(True, "SignIn Failed." + vbCrLf + "resStatus:" + resStatus + vbCrLf + "resMsg:" + vbCrLf + resMsg)
308     '            Twitter.AccountState = ACCOUNT_STATE.Invalid
309     '            Return "SignIn Failed -> " + "Unknown problems."
310     '        End If
311     '        Twitter.AccountState = ACCOUNT_STATE.Valid
312     '        _signed = True
313     '        Return ""
314     '    End SyncLock
315     'End Function
316
317     'Public Function GetTimeline(ByVal page As Integer, _
318     '                            ByVal read As Boolean, _
319     '                            ByRef endPage As Integer, _
320     '                            ByVal gType As WORKERTYPE, _
321     '                            ByRef getDM As Boolean) As String
322
323     '    If endPage = 0 Then
324     '        '通常モード
325     '        Dim epage As Integer = page
326     '        GetTmSemaphore.WaitOne()
327     '        Dim trslt As String = ""
328     '        trslt = GetTimelineThread(page, read, epage, gType, getDM)
329     '        If trslt.Length > 0 Then Return trslt
330     '        page += 1
331     '        If epage < page OrElse gType = WORKERTYPE.Reply Then Return ""
332     '        endPage = epage
333     '    End If
334     '    '起動時モード or 通常モードの読み込み継続 -> 複数ページ同時取得
335     '    Dim num As Integer = endPage - page
336     '    Dim ar(num) As IAsyncResult
337     '    Dim dlgt(num) As GetTimelineDelegate
338
339     '    For idx As Integer = 0 To num
340     '        dlgt(idx) = New GetTimelineDelegate(AddressOf GetTimelineThread)
341     '        GetTmSemaphore.WaitOne()
342     '        ar(idx) = dlgt(idx).BeginInvoke(page + idx, read, endPage + idx, gType, getDM, Nothing, Nothing)
343     '    Next
344     '    Dim rslt As String = ""
345     '    For idx As Integer = 0 To num
346     '        Dim epage As Integer = 0
347     '        Dim dm As Boolean = False
348     '        Dim trslt As String = ""
349     '        Try
350     '            trslt = dlgt(idx).EndInvoke(epage, dm, ar(idx))
351     '        Catch ex As Exception
352     '            '最後までendinvoke回す(ゾンビ化回避)
353     '            ex.Data("IsTerminatePermission") = False
354     '            Throw
355     '            rslt = "GetTimelineErr"
356     '        End Try
357     '        If trslt.Length > 0 AndAlso rslt.Length = 0 Then rslt = trslt
358     '        If dm Then getDM = True
359     '    Next
360     '    Return rslt
361     'End Function
362
363     '    Private Function GetTimelineThread(ByVal page As Integer, _
364     '                                ByVal read As Boolean, _
365     '                                ByRef endPage As Integer, _
366     '                                ByVal gType As WORKERTYPE, _
367     '                                ByRef getDM As Boolean) As String
368     '        Try
369     '            If _endingFlag Then Return ""
370
371     '            Dim retMsg As String = ""
372     '            Dim resStatus As String = ""
373
374     '            Static redirectToTimeline As String = ""
375     '            Static redirectToReply As String = ""
376
377     '            If _signed = False Then
378     '                retMsg = SignIn()
379     '                If retMsg.Length > 0 Then
380     '                    Return retMsg
381     '                End If
382     '            End If
383
384     '            If _endingFlag Then Return ""
385
386     '            'リクエストメッセージを作成する
387     '            Dim pageQuery As String
388
389     '            If page = 1 Then
390     '                pageQuery = ""
391     '            Else
392     '                pageQuery = _pageQry + page.ToString
393     '            End If
394
395     '            If gType = WORKERTYPE.Timeline Then
396     '                retMsg = DirectCast(CreateSocket.GetWebResponse(_protocol + _hubServer + _homePath + pageQuery, resStatus, MySocket.REQ_TYPE.ReqGetApp), String)
397     '            Else
398     '                retMsg = DirectCast(CreateSocket.GetWebResponse(_protocol + _hubServer + _replyPath + pageQuery, resStatus, MySocket.REQ_TYPE.ReqGetApp), String)
399     '            End If
400
401     '            If retMsg.Length = 0 Then
402     '                _signed = False
403     '                Return resStatus
404     '            End If
405
406     '            ' tr 要素の class 属性を消去
407     '            retMsg = Regex.Replace(retMsg, "(?<tagStart><li)(?<cls>\s+class=""[^""]+""\s+)", "${tagStart} ")
408     '            'Do
409     '            '    Try
410     '            '        Dim idx As Integer = retMsg.IndexOf(_removeClass, StringComparison.Ordinal)
411     '            '        If idx = -1 Then Exit Do
412     '            '        Dim idx2 As Integer = retMsg.IndexOf("""", idx + _removeClass.Length, StringComparison.Ordinal) - idx + 1 - 3
413     '            '        If idx2 > 0 Then retMsg = retMsg.Remove(idx + 3, idx2)
414     '            '    Catch ex As Exception
415     '            '        _signed = False
416     '            '        TraceOut("TM-Remove: " + retMsg)
417     '            '        Return "GetTimeline -> Err: Can't parse data."
418     '            '    End Try
419     '            'Loop
420
421     '            If _endingFlag Then Return ""
422
423     '            '各メッセージに分割可能か?
424     '            Dim strSepTmp As String
425     '            If gType = WORKERTYPE.Timeline Then
426     '                strSepTmp = _splitPostRecent
427     '            Else
428     '                strSepTmp = _splitPost
429     '            End If
430
431     '            Dim pos1 As Integer
432     '            Dim pos2 As Integer
433
434     '            pos1 = retMsg.IndexOf(strSepTmp, StringComparison.Ordinal)
435     '            If pos1 = -1 Then
436     '                '0件 or 取得失敗
437     '                _signed = False
438     '                Return "GetTimeline -> Err: tweets count is 0."
439     '            End If
440
441     '            Dim strSep() As String = {strSepTmp}
442     '            Dim posts() As String = retMsg.Split(strSep, StringSplitOptions.RemoveEmptyEntries)
443     '            Dim intCnt As Integer = 0
444     '            Dim listCnt As Integer = 0
445     '            SyncLock LockObj
446     '                listCnt = TabInformations.GetInstance.ItemCount
447     '            End SyncLock
448     '            Dim dlgt(20) As GetIconImageDelegate
449     '            Dim ar(20) As IAsyncResult
450     '            Dim arIdx As Integer = -1
451     '            Dim rg As Regex
452     '            Dim m As Match
453
454     '            For Each strPost As String In posts
455     '                intCnt += 1
456
457     '                If intCnt = 1 Then
458     '                    If page = 1 And gType = WORKERTYPE.Timeline Then
459     '                        ''siv取得
460     '                        'pos1 = strPost.IndexOf(_getSiv, 0)
461     '                        'If pos1 > 0 Then
462     '                        '    pos2 = strPost.IndexOf(_getSivTo, pos1 + _getSiv.Length)
463     '                        '    If pos2 > -1 Then
464     '                        '        _authSiv = strPost.Substring(pos1 + _getSiv.Length, pos2 - pos1 - _getSiv.Length)
465     '                        '    Else
466     '                        '        '取得失敗
467     '                        '        _signed = False
468     '                        '        Return "GetTimeline -> Err: Can't get Siv."
469     '                        '    End If
470     '                        'Else
471     '                        '    '取得失敗
472     '                        '    _signed = False
473     '                        '    Return "GetTimeline -> Err: Can't get Siv."
474     '                        'End If
475
476     '                        'AuthKeyの取得
477     '                        If GetAuthKey(retMsg) < 0 Then
478     '                            _signed = False
479     '                            Return "GetTimeline -> Err: Can't get auth token."
480     '                        End If
481
482     '                        'TwitterInfoの取得
483     '                        pos1 = retMsg.IndexOf(_getInfoTwitter, StringComparison.Ordinal)
484     '                        If pos1 > -1 Then
485     '                            pos2 = retMsg.IndexOf(_getInfoTwitterTo, pos1, StringComparison.Ordinal)
486     '                            If pos2 > -1 Then
487     '                                _infoTwitter = retMsg.Substring(pos1 + _getInfoTwitter.Length, pos2 - pos1 - _getInfoTwitter.Length)
488     '                            Else
489     '                                _infoTwitter = ""
490     '                            End If
491     '                        Else
492     '                            _infoTwitter = ""
493     '                        End If
494     '                    End If
495     '                Else
496
497     '                    Dim post As New PostClass
498
499     '                    pos1 = strPost.IndexOf("</ol>")
500     '                    If pos1 > -1 Then
501     '                        strPost = strPost.Substring(0, pos1)
502     '                    End If
503
504     '                    Try
505     '                        'Get ID
506     '                        pos1 = 0
507     '                        pos2 = strPost.IndexOf(_statusIdTo, 0, StringComparison.Ordinal)
508     '                        post.Id = Long.Parse(HttpUtility.HtmlDecode(strPost.Substring(0, pos2)))
509     '                    Catch ex As Exception
510     '                        _signed = False
511     '                        TraceOut("TM-ID:" + strPost)
512     '                        Return "GetTimeline -> Err: Can't get ID."
513     '                    End Try
514     '                    'Get Name
515     '                    Try
516     '                        pos1 = strPost.IndexOf(_parseName, pos2, StringComparison.Ordinal)
517     '                        pos2 = strPost.IndexOf(_parseNameTo, pos1, StringComparison.Ordinal)
518     '                        post.Name = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseName.Length, pos2 - pos1 - _parseName.Length))
519     '                    Catch ex As Exception
520     '                        _signed = False
521     '                        TraceOut("TM-Name:" + strPost)
522     '                        Return "GetTimeline -> Err: Can't get Name."
523     '                    End Try
524     '                    'Get Nick
525     '                    '''バレンタイン対応
526     '                    If strPost.IndexOf("twitter.com/images/heart.png", pos2, StringComparison.Ordinal) > -1 Then
527     '                        post.Nickname = post.Name
528     '                    Else
529     '                        Try
530     '                            pos1 = strPost.IndexOf(_parseNick, pos2, StringComparison.Ordinal)
531     '                            pos2 = strPost.IndexOf(_parseNickTo, pos1 + _parseNick.Length, StringComparison.Ordinal)
532     '                            post.Nickname = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseNick.Length, pos2 - pos1 - _parseNick.Length))
533     '                        Catch ex As Exception
534     '                            _signed = False
535     '                            TraceOut("TM-Nick:" + strPost)
536     '                            Return "GetTimeline -> Err: Can't get Nick."
537     '                        End Try
538     '                    End If
539
540     '                    '二重取得回避
541     '                    SyncLock LockObj
542     '                        If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
543     '                    End SyncLock
544
545     '                    Dim orgData As String = ""
546     '                    'バレンタイン
547     '                    If strPost.IndexOf("<form action=""/status/update"" id=""heartForm", 0, StringComparison.Ordinal) > -1 Then
548     '                        Try
549     '                            pos1 = strPost.IndexOf("<strong>", 0, StringComparison.Ordinal)
550     '                            pos2 = strPost.IndexOf("</strong>", pos1, StringComparison.Ordinal)
551     '                            orgData = strPost.Substring(pos1 + 8, pos2 - pos1 - 8)
552     '                        Catch ex As Exception
553     '                            _signed = False
554     '                            TraceOut("TM-VBody:" + strPost)
555     '                            Return "GetTimeline -> Err: Can't get Valentine body."
556     '                        End Try
557     '                    End If
558
559
560     '                    'Get ImagePath
561     '                    Try
562     '                        pos1 = strPost.IndexOf(_parseImg, pos2, StringComparison.Ordinal)
563     '                        pos2 = strPost.IndexOf(_parseImgTo, pos1 + _parseImg.Length, StringComparison.Ordinal)
564     '                        post.ImageUrl = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseImg.Length, pos2 - pos1 - _parseImg.Length))
565     '                    Catch ex As Exception
566     '                        _signed = False
567     '                        TraceOut("TM-Img:" + strPost)
568     '                        Return "GetTimeline -> Err: Can't get ImagePath."
569     '                    End Try
570
571     '                    'Protect
572     '                    If strPost.IndexOf(_isProtect, pos2, StringComparison.Ordinal) > -1 Then
573     '                        post.IsProtect = True
574     '                    End If
575
576     '                    'RetweetedBy
577     '                    If strPost.IndexOf("class=""big-retweet-icon""") > -1 Then
578     '                        rg = New Regex("class=""shared-content"".+<a href=""/(?<name>[a-zA-Z0-9_]+)""")
579     '                        m = rg.Match(strPost)
580     '                        If m.Success Then
581     '                            post.RetweetedBy = m.Result("${name}")
582     '                        Else
583     '                            post.RetweetedBy = ""
584     '                        End If
585     '                        rg = New Regex("&in_reply_to_status_id=(?<id>[0-9]+)&in_reply_to=")
586     '                        m = rg.Match(strPost)
587     '                        If m.Success Then
588     '                            post.RetweetedId = Long.Parse(m.Result("${id}"))
589     '                        Else
590     '                            post.RetweetedId = 0
591     '                        End If
592     '                    End If
593
594     '                    'Get Message
595     '                    pos1 = strPost.IndexOf(_parseMsg1, pos2, StringComparison.Ordinal)
596     '                    If pos1 < 0 Then
597     '                        'Valentine対応その2
598     '                        Try
599     '                            If strPost.IndexOf("<div id=""doyouheart", pos2, StringComparison.Ordinal) > -1 Then
600     '                                'バレンタイン
601     '                                orgData += " <3 you! Do you <3 "
602     '                                pos1 = strPost.IndexOf("<a href", pos2, StringComparison.Ordinal)
603     '                                pos2 = strPost.IndexOf("?", pos1, StringComparison.Ordinal)
604     '                                orgData += strPost.Substring(pos1, pos2 - pos1 + 1)
605     '                            Else
606     '                                pos1 = strPost.IndexOf(_parseProtectMsg1, pos2, StringComparison.Ordinal)
607     '                                If pos1 = -1 Then
608     '                                    'バレンタイン
609     '                                    orgData += " <3 's "
610     '                                    pos1 = strPost.IndexOf("<a href", pos2, StringComparison.Ordinal)
611     '                                    If pos1 > -1 Then
612     '                                        pos2 = strPost.IndexOf("!", pos1, StringComparison.Ordinal)
613     '                                        orgData += strPost.Substring(pos1, pos2 - pos1 + 1)
614     '                                    End If
615     '                                Else
616     '                                    'プロテクトメッセージ
617     '                                    pos2 = strPost.IndexOf(_parseProtectMsg2, pos1, StringComparison.Ordinal)
618     '                                    orgData = strPost.Substring(pos1 + _parseProtectMsg1.Length, pos2 - pos1 - _parseProtectMsg1.Length).Trim()
619     '                                End If
620     '                            End If
621     '                        Catch ex As Exception
622     '                            _signed = False
623     '                            TraceOut("TM-VBody2:" + strPost)
624     '                            Return "GetTimeline -> Err: Can't get Valentine body2."
625     '                        End Try
626     '                    Else
627     '                        '通常メッセージ
628     '                        Try
629     '                            pos2 = strPost.IndexOf(_parseMsg2, pos1, StringComparison.Ordinal)
630     '                            orgData = strPost.Substring(pos1 + _parseMsg1.Length, pos2 - pos1 - _parseMsg1.Length).Trim()
631     '                        Catch ex As Exception
632     '                            _signed = False
633     '                            TraceOut("TM-Body:" + strPost)
634     '                            Return "GetTimeline -> Err: Can't get body."
635     '                        End Try
636     '                        '#If 0 Then
637     '                        '                        '原文リンク削除
638     '                        '                        orgData = Regex.Replace(orgData, "<a href=""https://twitter\.com/" + post.Name + "/status/[0-9]+"">\.\.\.</a>$", "")
639     '                        '#End If
640     '                        'ハート変換
641     '                        orgData = orgData.Replace("&lt;3", "♡")
642     '                    End If
643
644     '                    'URL前処理(IDNデコードなど)
645     '                    orgData = PreProcessUrl(orgData)
646
647     '                    '短縮URL解決処理(orgData書き換え)
648     '                    orgData = ShortUrlResolve(orgData)
649
650     '                    '表示用にhtml整形
651     '                    post.OriginalData = AdjustHtml(orgData)
652
653     '                    '単純テキストの取り出し(リンクタグ除去)
654     '                    Try
655     '                        post.Data = GetPlainText(orgData)
656     '                    Catch ex As Exception
657     '                        _signed = False
658     '                        TraceOut("TM-Link:" + strPost)
659     '                        Return "GetTimeline -> Err: Can't parse links."
660     '                    End Try
661
662     '                    ' Imageタグ除去(ハロウィン)
663     '                    Dim ImgTag As New Regex("<img src=.*?/>", RegexOptions.IgnoreCase)
664     '                    If ImgTag.IsMatch(post.Data) Then post.Data = ImgTag.Replace(post.Data, "<img>")
665
666     '                    'Get Date
667     '#If 1 Then
668     '                    Try
669     '                        pos1 = strPost.IndexOf(_parseDate, pos2, StringComparison.Ordinal)
670     '                        If pos1 > -1 Then
671     '                            pos2 = strPost.IndexOf(_parseDateTo, pos1 + _parseDate.Length, StringComparison.Ordinal)
672     '                            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)
673     '                        Else
674     '                            post.PDate = Now()
675     '                        End If
676     '                    Catch ex As Exception
677     '                        _signed = False
678     '                        TraceOut("TM-Date:" + strPost)
679     '                        Return "GetTimeline -> Err: Can't get date."
680     '                    End Try
681     '#Else
682     '                    '取得できなくなったため暫定対応(2/26)
683     '                    post.PDate = Now()
684     '#End If
685
686
687     '                    'from Sourceの取得
688     '                    'ToDo: _parseSourceFromを正規表現へ。wedataからの取得へ変更(次版より)
689     '                    rg = New Regex("<span>.+>(?<name>.+)</a>.*</span>")
690     '                    m = rg.Match(strPost)
691     '                    If m.Success Then
692     '                        post.Source = m.Result("${name}")
693     '                    Else
694     '                        post.Source = "Web"
695     '                    End If
696     '                    'Try
697     '                    '    pos1 = strPost.IndexOf(_parseSourceFrom, pos2, StringComparison.Ordinal)
698     '                    '    If pos1 = -1 Then pos1 = strPost.IndexOf(_parseSourceFrom2, pos2, StringComparison.Ordinal)
699     '                    '    If pos1 > -1 Then
700     '                    '        pos1 = strPost.IndexOf(_parseSource2, pos1 + 19, StringComparison.Ordinal)
701     '                    '        pos2 = strPost.IndexOf(_parseSourceTo, pos1 + 2, StringComparison.Ordinal)
702     '                    '        post.Source = HttpUtility.HtmlDecode(strPost.Substring(pos1 + 2, pos2 - pos1 - 2))
703     '                    '    Else
704     '                    '        post.Source = "Web"
705     '                    '    End If
706     '                    'Catch ex As Exception
707     '                    '    _signed = False
708     '                    '    TraceOut("TM-Src:" + strPost)
709     '                    '    Return "GetTimeline -> Err: Can't get src."
710     '                    'End Try
711
712     '                    'Get Reply(in_reply_to_user/id)
713     '                    'ToDo: _isReplyEngを正規表現へ。wedataからの取得へ変更(次版より)
714     '                    rg = New Regex("<a href=""https?:\/\/twitter\.com\/(?<name>[a-zA-Z0-9_]+)\/status\/(?<id>[0-9]+)"">(in reply to )*\k<name>")
715     '                    m = rg.Match(strPost)
716     '                    If m.Success Then
717     '                        post.InReplyToUser = m.Result("${name}")
718     '                        post.InReplyToId = Long.Parse(m.Result("${id}"))
719     '                        post.IsReply = post.InReplyToUser.Equals(_uid, StringComparison.OrdinalIgnoreCase)
720     '                    End If
721
722     '                    '@先リスト作成
723     '                    rg = New Regex("@<a [^>]*href=""\/(?<1>[a-zA-Z0-9_]+)[^a-zA-Z0-9_]")
724     '                    m = rg.Match(orgData)
725     '                    While m.Success
726     '                        post.ReplyToList.Add(m.Groups(1).Value.ToLower())
727     '                        m = m.NextMatch
728     '                    End While
729     '                    If Not post.IsReply Then post.IsReply = post.ReplyToList.Contains(_uid)
730
731     '                    If gType = WORKERTYPE.Reply Then post.IsReply = True
732
733     '                    'Get Fav
734     '                    If strPost.IndexOf("class=""fav-action fav""") > -1 Then
735     '                        post.IsFav = True
736     '                    Else
737     '                        post.IsFav = False
738     '                    End If
739     '                    'pos1 = strPost.IndexOf(_parseStar, pos2, StringComparison.Ordinal)
740     '                    'If pos1 > -1 Then
741     '                    '    Try
742     '                    '        pos2 = strPost.IndexOf(_parseStarTo, pos1 + _parseStar.Length, StringComparison.Ordinal)
743     '                    '        If strPost.Substring(pos1 + _parseStar.Length, pos2 - pos1 - _parseStar.Length) = _parseStarEmpty Then
744     '                    '            post.IsFav = False
745     '                    '        Else
746     '                    '            post.IsFav = True
747     '                    '        End If
748     '                    '    Catch ex As Exception
749     '                    '        _signed = False
750     '                    '        TraceOut("TM-Fav:" + strPost)
751     '                    '        Return "GetTimeline -> Err: Can't get fav status."
752     '                    '    End Try
753     '                    'Else
754     '                    '    post.IsFav = False
755     '                    'End If
756
757     '                    If _endingFlag Then Return ""
758
759     '                    post.IsMe = post.Name.Equals(_uid, StringComparison.OrdinalIgnoreCase)
760     '                    SyncLock LockObj
761     '                        If follower.Count > 1 Then
762     '                            post.IsOwl = Not follower.Contains(post.Name.ToLower())
763     '                        Else
764     '                            post.IsOwl = False
765     '                        End If
766     '                    End SyncLock
767     '                    post.IsRead = read
768     '                    If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
769
770     '                    arIdx += 1
771     '                    dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
772     '                    ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
773
774     '                End If
775
776     '                'テスト実装:DMカウント取得
777     '                If intCnt = posts.Length AndAlso gType = WORKERTYPE.Timeline AndAlso page = 1 Then
778     '                    pos1 = strPost.IndexOf(_parseDMcountFrom, pos2, StringComparison.Ordinal)
779     '                    If pos1 > -1 Then
780     '                        Try
781     '                            pos2 = strPost.IndexOf(_parseDMcountTo, pos1 + _parseDMcountFrom.Length, StringComparison.Ordinal)
782     '                            Dim dmCnt As Integer = Integer.Parse(strPost.Substring(pos1 + _parseDMcountFrom.Length, pos2 - pos1 - _parseDMcountFrom.Length))
783     '                            If dmCnt > _dmCount Then
784     '                                _dmCount = dmCnt
785     '                                _getDm = True
786     '                            End If
787     '                        Catch ex As Exception
788     '                            Return "GetTimeline -> Err: Can't get DM count."
789     '                        End Try
790     '                    End If
791     '                End If
792     '                getDM = _getDm
793     '            Next
794
795     '            For i As Integer = 0 To arIdx
796     '                Try
797     '                    dlgt(i).EndInvoke(ar(i))
798     '                Catch ex As Exception
799     '                    '最後までendinvoke回す(ゾンビ化回避)
800     '                    ex.Data("IsTerminatePermission") = False
801     '                    Throw
802     '                End Try
803     '            Next
804
805     '            SyncLock LockObj
806     '                If page = 1 AndAlso (TabInformations.GetInstance.ItemCount - listCnt) >= _nextThreshold Then
807     '                    '新着が閾値の件数以上なら、次のページも念のため読み込み
808     '                    endPage = _nextPages + 1
809     '                End If
810     '            End SyncLock
811
812     '            Return ""
813     '        Finally
814     '            GetTmSemaphore.Release()
815     '        End Try
816     '    End Function
817
818     '    Public Function GetDirectMessage(ByVal page As Integer, _
819     '                                    ByVal read As Boolean, _
820     '                                    ByVal endPage As Integer, _
821     '                                    ByVal gType As WORKERTYPE) As String
822
823     '        If endPage = 0 Then
824     '            '通常モード(DMはモード関係なし)
825     '            endPage = 1
826     '        End If
827     '        '起動時モード 
828     '        Dim num As Integer = endPage - page
829     '        Dim ar(num) As IAsyncResult
830     '        Dim dlgt(num) As GetDirectMessageDelegate
831
832     '        For idx As Integer = 0 To num
833     '            gType = WORKERTYPE.DirectMessegeRcv
834     '            dlgt(idx) = New GetDirectMessageDelegate(AddressOf GetDirectMessageThread)
835     '            GetTmSemaphore.WaitOne()
836     '            ar(idx) = dlgt(idx).BeginInvoke(page + idx, read, endPage + idx, gType, Nothing, Nothing)
837     '        Next
838     '        Dim rslt As String = ""
839     '        For idx As Integer = 0 To num
840     '            Dim trslt As String = ""
841     '            Try
842     '                trslt = dlgt(idx).EndInvoke(ar(idx))
843     '            Catch ex As Exception
844     '                '最後までendinvoke回す(ゾンビ化回避)
845     '                ex.Data("IsTerminatePermission") = False
846     '                Throw
847     '                rslt = "GetDirectMessageErr"
848     '            End Try
849     '            If trslt.Length > 0 AndAlso rslt.Length = 0 Then rslt = trslt
850     '        Next
851     '        For idx As Integer = 0 To num
852     '            gType = WORKERTYPE.DirectMessegeSnt
853     '            dlgt(idx) = New GetDirectMessageDelegate(AddressOf GetDirectMessageThread)
854     '            GetTmSemaphore.WaitOne()
855     '            ar(idx) = dlgt(idx).BeginInvoke(page + idx, read, endPage + idx, gType, Nothing, Nothing)
856     '        Next
857     '        For idx As Integer = 0 To num
858     '            Dim trslt As String = ""
859     '            Try
860     '                trslt = dlgt(idx).EndInvoke(ar(idx))
861     '            Catch ex As Exception
862     '                '最後までendinvoke回す(ゾンビ化回避)
863     '                ex.Data("IsTerminatePermission") = False
864     '                Throw
865     '                rslt = "GetDirectMessageErr"
866     '            End Try
867     '            If trslt.Length > 0 AndAlso rslt.Length = 0 Then rslt = trslt
868     '        Next
869     '        Return rslt
870     '    End Function
871
872     '    Private Function GetDirectMessageThread(ByVal page As Integer, _
873     '                                    ByVal read As Boolean, _
874     '                                    ByVal endPage As Integer, _
875     '                                    ByVal gType As WORKERTYPE) As String
876     '        Try
877     '            If _endingFlag Then Return ""
878
879     '            Dim retMsg As String = ""
880     '            Dim resStatus As String = ""
881
882     '            Static redirectToDmRcv As String = ""
883     '            Static redirectToDmSnd As String = ""
884
885     '            _getDm = False
886
887     '            If _signed = False Then
888     '                retMsg = SignIn()
889     '                If retMsg.Length > 0 Then
890     '                    Return retMsg
891     '                End If
892     '            End If
893
894     '            If _endingFlag Then Return ""
895
896     '            'リクエストメッセージを作成する
897     '            Dim pageQuery As String = _pageQry + page.ToString
898     '            If gType = WORKERTYPE.DirectMessegeRcv Then
899     '                retMsg = DirectCast(CreateSocket.GetWebResponse(_protocol + _hubServer + _DMPathRcv + pageQuery, resStatus, MySocket.REQ_TYPE.ReqGetApp), String)
900     '            Else
901     '                retMsg = DirectCast(CreateSocket.GetWebResponse(_protocol + _hubServer + _DMPathSnt + pageQuery, resStatus, MySocket.REQ_TYPE.ReqGetApp), String)
902     '            End If
903
904     '            If retMsg.Length = 0 Then
905     '                _signed = False
906     '                Return resStatus
907     '            End If
908
909     '            ' tr 要素の class 属性を消去
910     '            retMsg = Regex.Replace(retMsg, "(?<tagStart><li)(?<cls>\s+class=""[^""]+""\s+)", "${tagStart} ")
911     '            'Do
912     '            '    Try
913     '            '        Dim idx As Integer = retMsg.IndexOf(_removeClass, StringComparison.Ordinal)
914     '            '        If idx = -1 Then Exit Do
915     '            '        Dim idx2 As Integer = retMsg.IndexOf("""", idx + _removeClass.Length, StringComparison.Ordinal) - idx + 1 - 3
916     '            '        If idx2 > 0 Then retMsg = retMsg.Remove(idx + 3, idx2)
917     '            '    Catch ex As Exception
918     '            '        _signed = False
919     '            '        TraceOut("DM-Remove: " + retMsg)
920     '            '        Return "GetDm -> Err: Can't parse data."
921     '            '    End Try
922     '            'Loop
923
924     '            If _endingFlag Then Return ""
925
926     '            ''AuthKeyの取得
927     '            'If GetAuthKeyDM(retMsg) < 0 Then
928     '            '    _signed = False
929     '            '    Return "GetDirectMessage -> Err: Busy(1)"
930     '            'End If
931
932     '            Dim pos1 As Integer
933     '            Dim pos2 As Integer
934
935     '            '各メッセージに分割可能か?
936     '            pos1 = retMsg.IndexOf(_splitDM, StringComparison.Ordinal)
937     '            If pos1 = -1 Then
938     '                '0件(メッセージなし。エラーの場合もありうるが判別できないので正常として戻す)
939     '                Return ""
940     '            End If
941
942     '            Dim strSep() As String = {_splitDM}
943     '            Dim posts() As String = retMsg.Split(strSep, StringSplitOptions.RemoveEmptyEntries)
944     '            Dim intCnt As Integer = 0   'カウンタ
945     '            'Dim listCnt As Integer = 0
946     '            'SyncLock LockObj
947     '            '    listCnt = TabInformations.GetInstance.ItemCount
948     '            'End SyncLock
949     '            Dim dlgt(20) As GetIconImageDelegate
950     '            Dim ar(20) As IAsyncResult
951     '            Dim arIdx As Integer = -1
952
953     '            For Each strPost As String In posts
954     '                intCnt += 1
955
956     '                If intCnt > 1 Then  '1件目はヘッダなので無視
957     '                    'Dim lItem As New MyListItem
958     '                    Dim post As New PostClass()
959
960     '                    pos1 = strPost.IndexOf("</ol>")
961     '                    If pos1 > -1 Then
962     '                        strPost = strPost.Substring(0, pos1)
963     '                    End If
964
965     '                    'Get ID
966     '                    Try
967     '                        pos1 = 0
968     '                        pos2 = strPost.IndexOf("""", 0, StringComparison.Ordinal)
969     '                        post.Id = Long.Parse(HttpUtility.HtmlDecode(strPost.Substring(0, pos2)))
970     '                    Catch ex As Exception
971     '                        _signed = False
972     '                        TraceOut("DM-ID:" + strPost)
973     '                        Return "GetDirectMessage -> Err: Can't get ID"
974     '                    End Try
975
976     '                    'Get Name
977     '                    Try
978     '                        pos1 = strPost.IndexOf(_parseName, pos2, StringComparison.Ordinal)
979     '                        pos2 = strPost.IndexOf(_parseNameTo, pos1, StringComparison.Ordinal)
980     '                        post.Name = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseName.Length, pos2 - pos1 - _parseName.Length))
981     '                    Catch ex As Exception
982     '                        _signed = False
983     '                        TraceOut("DM-Name:" + strPost)
984     '                        Return "GetDirectMessage -> Err: Can't get Name"
985     '                    End Try
986
987     '                    'Get Nick
988     '                    Try
989     '                        pos1 = strPost.IndexOf(_parseNick, pos2, StringComparison.Ordinal)
990     '                        pos2 = strPost.IndexOf(_parseNickTo, pos1 + _parseNick.Length, StringComparison.Ordinal)
991     '                        post.Nickname = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseNick.Length, pos2 - pos1 - _parseNick.Length))
992     '                    Catch ex As Exception
993     '                        _signed = False
994     '                        TraceOut("DM-Nick:" + strPost)
995     '                        Return "GetDirectMessage -> Err: Can't get Nick."
996     '                    End Try
997
998     '                    SyncLock LockObj
999     '                        If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
1000     '                    End SyncLock
1001
1002     '                    'Get ImagePath
1003     '                    Try
1004     '                        pos1 = strPost.IndexOf(_parseImg, pos2, StringComparison.Ordinal)
1005     '                        pos2 = strPost.IndexOf(_parseImgTo, pos1 + _parseImg.Length, StringComparison.Ordinal)
1006     '                        post.ImageUrl = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseImg.Length, pos2 - pos1 - _parseImg.Length))
1007     '                    Catch ex As Exception
1008     '                        _signed = False
1009     '                        TraceOut("DM-Img:" + strPost)
1010     '                        Return "GetDirectMessage -> Err: Can't get ImagePath"
1011     '                    End Try
1012
1013     '                    'Get Protect 
1014     '                    Try
1015     '                        pos1 = strPost.IndexOf(_isProtect, pos2, StringComparison.Ordinal)
1016     '                        If pos1 > -1 Then post.IsProtect = True
1017     '                    Catch ex As Exception
1018     '                        _signed = False
1019     '                        TraceOut("DM-Protect:" + strPost)
1020     '                        Return "GetDirectMessage -> Err: Can't get Protect"
1021     '                    End Try
1022
1023     '                    Dim orgData As String = ""
1024
1025     '                    'Get Message
1026     '                    Try
1027     '                        pos1 = strPost.IndexOf(_parseDM1, pos2, StringComparison.Ordinal)
1028     '                        If pos1 > -1 Then
1029     '                            pos2 = strPost.IndexOf(_parseDM2, pos1, StringComparison.Ordinal)
1030     '                            orgData = strPost.Substring(pos1 + _parseDM1.Length, pos2 - pos1 - _parseDM1.Length).Trim()
1031     '                        Else
1032     '                            pos1 = strPost.IndexOf(_parseDM11, pos2, StringComparison.Ordinal)
1033     '                            pos2 = strPost.IndexOf(_parseDM2, pos1, StringComparison.Ordinal)
1034     '                            orgData = strPost.Substring(pos1 + _parseDM11.Length, pos2 - pos1 - _parseDM11.Length).Trim()
1035     '                        End If
1036     '                        'orgData = Regex.Replace(orgData, "<a href=""https://twitter\.com/" + post.Name + "/status/[0-9]+"">\.\.\.</a>$", "")
1037     '                        orgData = orgData.Replace("&lt;3", "♡")
1038     '                    Catch ex As Exception
1039     '                        _signed = False
1040     '                        TraceOut("DM-Body:" + strPost)
1041     '                        Return "GetDirectMessage -> Err: Can't get body"
1042     '                    End Try
1043
1044     '                    'URL前処理(IDNデコードなど)
1045     '                    orgData = PreProcessUrl(orgData)
1046
1047     '                    '短縮URL解決処理(orgData書き換え)
1048     '                    orgData = ShortUrlResolve(orgData)
1049
1050     '                    '表示用にhtml整形
1051     '                    post.OriginalData = AdjustHtml(orgData)
1052
1053     '                    '単純テキストの取り出し(リンクタグ除去)
1054     '                    Try
1055     '                        post.Data = GetPlainText(orgData)
1056     '                    Catch ex As Exception
1057     '                        _signed = False
1058     '                        TraceOut("DM-Link:" + strPost)
1059     '                        Return "GetDirectMessage -> Err: Can't parse links"
1060     '                    End Try
1061
1062     '#If 1 Then
1063     '                    'Get Date
1064     '                    Try
1065     '                        pos1 = strPost.IndexOf(_parseDate, pos2, StringComparison.Ordinal)
1066     '                        If pos1 > -1 Then
1067     '                            pos2 = strPost.IndexOf(_parseDateTo, pos1 + _parseDate.Length, StringComparison.Ordinal)
1068     '                            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)
1069     '                        Else
1070     '                            post.PDate = Now()
1071     '                        End If
1072     '                    Catch ex As Exception
1073     '                        _signed = False
1074     '                        TraceOut("DM-Date:" + strPost)
1075     '                        Return "GetDirectMessage -> Err: Can't get date."
1076     '                    End Try
1077     '#Else
1078     '                    '取得できなくなったため暫定対応(2/26)
1079     '                    post.PDate = Now()
1080     '#End If
1081
1082     '                    'Get Fav
1083     '                    'pos1 = strPost.IndexOf(_parseStar, pos2)
1084     '                    'pos2 = strPost.IndexOf("""", pos1 + _parseStar.Length)
1085     '                    'If strPost.Substring(pos1 + _parseStar.Length, pos2 - pos1 - _parseStar.Length) = "empty" Then
1086     '                    '    lItem.Fav = False
1087     '                    'Else
1088     '                    '    lItem.Fav = True
1089     '                    'End If
1090     '                    post.IsFav = False
1091
1092
1093     '                    If _endingFlag Then Return ""
1094
1095     '                    '受信DMかの判定で使用
1096     '                    If gType = WORKERTYPE.DirectMessegeRcv Then
1097     '                        post.IsOwl = False
1098     '                    Else
1099     '                        post.IsOwl = True
1100     '                    End If
1101
1102     '                    post.IsRead = read
1103     '                    post.IsDm = True
1104
1105     '                    'Imageの取得
1106     '                    arIdx += 1
1107     '                    dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
1108     '                    ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
1109     '                End If
1110     '            Next
1111
1112     '            For i As Integer = 0 To arIdx
1113     '                Try
1114     '                    dlgt(i).EndInvoke(ar(i))
1115     '                Catch ex As Exception
1116     '                    ex.Data("IsTerminatePermission") = False
1117     '                    Throw
1118     '                End Try
1119     '            Next
1120
1121     '            Return ""
1122
1123     '        Finally
1124     '            GetTmSemaphore.Release()
1125     '        End Try
1126     '    End Function
1127
1128     '    Public Function GetFavorites(ByVal page As Integer, _
1129     '                                ByVal read As Boolean, _
1130     '                                ByRef endPage As Integer, _
1131     '                                ByVal gType As WORKERTYPE, _
1132     '                                ByRef getDM As Boolean) As String
1133
1134     '        GetTmSemaphore.WaitOne()
1135     '        Try
1136     '            If _endingFlag Then Return ""
1137
1138     '            Dim retMsg As String = ""
1139     '            Dim resStatus As String = ""
1140
1141     '            Static redirectToFav As String = ""
1142     '            Const FAV_PATH As String = "/favorites"
1143
1144     '            If _signed = False Then
1145     '                retMsg = SignIn()
1146     '                If retMsg.Length > 0 Then
1147     '                    Return retMsg
1148     '                End If
1149     '            End If
1150
1151     '            If _endingFlag Then Return ""
1152
1153     '            'リクエストメッセージを作成する
1154     '            Dim pageQuery As String
1155
1156     '            If page = 1 Then
1157     '                pageQuery = ""
1158     '            Else
1159     '                pageQuery = _pageQry + page.ToString
1160     '            End If
1161
1162     '            retMsg = DirectCast(CreateSocket.GetWebResponse(_protocol + _hubServer + FAV_PATH + pageQuery, resStatus, MySocket.REQ_TYPE.ReqGetApp), String)
1163
1164     '            If retMsg.Length = 0 Then
1165     '                _signed = False
1166     '                Return resStatus
1167     '            End If
1168
1169     '            ' tr 要素の class 属性を消去
1170     '            retMsg = Regex.Replace(retMsg, "(?<tagStart><li)(?<cls>\s+class=""[^""]+""\s+)", "${tagStart} ")
1171     '            'Do
1172     '            '    Try
1173     '            '        Dim idx As Integer = retMsg.IndexOf(_removeClass, StringComparison.Ordinal)
1174     '            '        If idx = -1 Then Exit Do
1175     '            '        Dim idx2 As Integer = retMsg.IndexOf("""", idx + _removeClass.Length, StringComparison.Ordinal) - idx + 1 - 3
1176     '            '        If idx2 > 0 Then retMsg = retMsg.Remove(idx + 3, idx2)
1177     '            '    Catch ex As Exception
1178     '            '        _signed = False
1179     '            '        TraceOut("GetFav-Remove: " + retMsg)
1180     '            '        Return "GetFav -> Err: Can't parse data."
1181     '            '    End Try
1182     '            'Loop
1183
1184     '            If _endingFlag Then Return ""
1185
1186     '            '各メッセージに分割可能か?
1187     '            Dim strSepTmp As String
1188     '            strSepTmp = _splitPostRecent
1189
1190     '            Dim pos1 As Integer
1191     '            Dim pos2 As Integer
1192
1193     '            pos1 = retMsg.IndexOf(strSepTmp, StringComparison.Ordinal)
1194     '            If pos1 = -1 Then
1195     '                '0件 or 取得失敗
1196     '                _signed = False
1197     '                Return "GetTimeline -> Err: tweets count is 0."
1198     '            End If
1199
1200     '            Dim strSep() As String = {strSepTmp}
1201     '            Dim posts() As String = retMsg.Split(strSep, StringSplitOptions.RemoveEmptyEntries)
1202     '            Dim intCnt As Integer = 0
1203     '            'Dim listCnt As Integer = 0
1204     '            'SyncLock LockObj
1205     '            '    listCnt = TabInformations.GetInstance.ItemCount
1206     '            'End SyncLock
1207     '            Dim dlgt(20) As GetIconImageDelegate
1208     '            Dim ar(20) As IAsyncResult
1209     '            Dim arIdx As Integer = -1
1210     '            Dim rg As Regex
1211     '            Dim m As Match
1212
1213     '            For Each strPost As String In posts
1214     '                intCnt += 1
1215
1216     '                If intCnt = 1 Then
1217     '                    Continue For
1218     '                Else
1219
1220     '                    Dim post As New PostClass
1221
1222     '                    pos1 = strPost.IndexOf("</ol>")
1223     '                    If pos1 > -1 Then
1224     '                        strPost = strPost.Substring(0, pos1)
1225     '                    End If
1226
1227     '                    Try
1228     '                        'Get ID
1229     '                        pos1 = 0
1230     '                        pos2 = strPost.IndexOf(_statusIdTo, 0, StringComparison.Ordinal)
1231     '                        post.Id = Long.Parse(HttpUtility.HtmlDecode(strPost.Substring(0, pos2)))
1232     '                    Catch ex As Exception
1233     '                        _signed = False
1234     '                        TraceOut("TM-ID:" + strPost)
1235     '                        Return "GetTimeline -> Err: Can't get ID."
1236     '                    End Try
1237     '                    'Get Name
1238     '                    Try
1239     '                        pos1 = strPost.IndexOf(_parseName, pos2, StringComparison.Ordinal)
1240     '                        pos2 = strPost.IndexOf(_parseNameTo, pos1, StringComparison.Ordinal)
1241     '                        post.Name = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseName.Length, pos2 - pos1 - _parseName.Length))
1242     '                    Catch ex As Exception
1243     '                        _signed = False
1244     '                        TraceOut("TM-Name:" + strPost)
1245     '                        Return "GetTimeline -> Err: Can't get Name."
1246     '                    End Try
1247     '                    'Get Nick
1248     '                    '''バレンタイン対応
1249     '                    If strPost.IndexOf("twitter.com/images/heart.png", pos2, StringComparison.Ordinal) > -1 Then
1250     '                        post.Nickname = post.Name
1251     '                    Else
1252     '                        Try
1253     '                            pos1 = strPost.IndexOf(_parseNick, pos2, StringComparison.Ordinal)
1254     '                            pos2 = strPost.IndexOf(_parseNickTo, pos1 + _parseNick.Length, StringComparison.Ordinal)
1255     '                            post.Nickname = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseNick.Length, pos2 - pos1 - _parseNick.Length))
1256     '                        Catch ex As Exception
1257     '                            _signed = False
1258     '                            TraceOut("TM-Nick:" + strPost)
1259     '                            Return "GetTimeline -> Err: Can't get Nick."
1260     '                        End Try
1261     '                    End If
1262
1263     '                    ''二重取得回避
1264     '                    'SyncLock LockObj
1265     '                    '    If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
1266     '                    'End SyncLock
1267
1268     '                    Dim orgData As String = ""
1269     '                    'バレンタイン
1270     '                    If strPost.IndexOf("<form action=""/status/update"" id=""heartForm", 0, StringComparison.Ordinal) > -1 Then
1271     '                        Try
1272     '                            pos1 = strPost.IndexOf("<strong>", 0, StringComparison.Ordinal)
1273     '                            pos2 = strPost.IndexOf("</strong>", pos1, StringComparison.Ordinal)
1274     '                            orgData = strPost.Substring(pos1 + 8, pos2 - pos1 - 8)
1275     '                        Catch ex As Exception
1276     '                            _signed = False
1277     '                            TraceOut("TM-VBody:" + strPost)
1278     '                            Return "GetTimeline -> Err: Can't get Valentine body."
1279     '                        End Try
1280     '                    End If
1281
1282
1283     '                    'Get ImagePath
1284     '                    Try
1285     '                        pos1 = strPost.IndexOf(_parseImg, pos2, StringComparison.Ordinal)
1286     '                        pos2 = strPost.IndexOf(_parseImgTo, pos1 + _parseImg.Length, StringComparison.Ordinal)
1287     '                        post.ImageUrl = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseImg.Length, pos2 - pos1 - _parseImg.Length))
1288     '                    Catch ex As Exception
1289     '                        _signed = False
1290     '                        TraceOut("TM-Img:" + strPost)
1291     '                        Return "GetTimeline -> Err: Can't get ImagePath."
1292     '                    End Try
1293
1294     '                    'Protect
1295     '                    If strPost.IndexOf(_isProtect, pos2, StringComparison.Ordinal) > -1 Then
1296     '                        post.IsProtect = True
1297     '                    End If
1298
1299     '                    'RetweetedBy
1300     '                    If strPost.IndexOf("class=""big-retweet-icon""") > -1 Then
1301     '                        rg = New Regex("class=""shared-content"".+<a href=""/(?<name>[a-zA-Z0-9_]+)""")
1302     '                        m = rg.Match(strPost)
1303     '                        If m.Success Then
1304     '                            post.RetweetedBy = m.Result("${name}")
1305     '                        Else
1306     '                            post.RetweetedBy = ""
1307     '                        End If
1308     '                        rg = New Regex("&in_reply_to_status_id=(?<id>[0-9]+)&in_reply_to=")
1309     '                        m = rg.Match(strPost)
1310     '                        If m.Success Then
1311     '                            post.RetweetedId = Long.Parse(m.Result("${id}"))
1312     '                        Else
1313     '                            post.RetweetedId = 0
1314     '                        End If
1315     '                    End If
1316
1317     '                    'Get Message
1318     '                    pos1 = strPost.IndexOf(_parseMsg1, pos2, StringComparison.Ordinal)
1319     '                    If pos1 < 0 Then
1320     '                        'Valentine対応その2
1321     '                        Try
1322     '                            If strPost.IndexOf("<div id=""doyouheart", pos2, StringComparison.Ordinal) > -1 Then
1323     '                                'バレンタイン
1324     '                                orgData += " <3 you! Do you <3 "
1325     '                                pos1 = strPost.IndexOf("<a href", pos2, StringComparison.Ordinal)
1326     '                                pos2 = strPost.IndexOf("?", pos1, StringComparison.Ordinal)
1327     '                                orgData += strPost.Substring(pos1, pos2 - pos1 + 1)
1328     '                            Else
1329     '                                pos1 = strPost.IndexOf(_parseProtectMsg1, pos2, StringComparison.Ordinal)
1330     '                                If pos1 = -1 Then
1331     '                                    'バレンタイン
1332     '                                    orgData += " <3 's "
1333     '                                    pos1 = strPost.IndexOf("<a href", pos2, StringComparison.Ordinal)
1334     '                                    If pos1 > -1 Then
1335     '                                        pos2 = strPost.IndexOf("!", pos1, StringComparison.Ordinal)
1336     '                                        orgData += strPost.Substring(pos1, pos2 - pos1 + 1)
1337     '                                    End If
1338     '                                Else
1339     '                                    'プロテクトメッセージ
1340     '                                    pos2 = strPost.IndexOf(_parseProtectMsg2, pos1, StringComparison.Ordinal)
1341     '                                    orgData = strPost.Substring(pos1 + _parseProtectMsg1.Length, pos2 - pos1 - _parseProtectMsg1.Length).Trim()
1342     '                                End If
1343     '                            End If
1344     '                        Catch ex As Exception
1345     '                            _signed = False
1346     '                            TraceOut("TM-VBody2:" + strPost)
1347     '                            Return "GetTimeline -> Err: Can't get Valentine body2."
1348     '                        End Try
1349     '                    Else
1350     '                        '通常メッセージ
1351     '                        Try
1352     '                            pos2 = strPost.IndexOf(_parseMsg2, pos1, StringComparison.Ordinal)
1353     '                            orgData = strPost.Substring(pos1 + _parseMsg1.Length, pos2 - pos1 - _parseMsg1.Length).Trim()
1354     '                        Catch ex As Exception
1355     '                            _signed = False
1356     '                            TraceOut("TM-Body:" + strPost)
1357     '                            Return "GetTimeline -> Err: Can't get body."
1358     '                        End Try
1359     '                        '#If 0 Then
1360     '                        '                        '原文リンク削除
1361     '                        '                        orgData = Regex.Replace(orgData, "<a href=""https://twitter\.com/" + post.Name + "/status/[0-9]+"">\.\.\.</a>$", "")
1362     '                        '#End If
1363     '                        'ハート変換
1364     '                        orgData = orgData.Replace("&lt;3", "♡")
1365     '                    End If
1366
1367     '                    'URL前処理(IDNデコードなど)
1368     '                    orgData = PreProcessUrl(orgData)
1369
1370     '                    '短縮URL解決処理(orgData書き換え)
1371     '                    orgData = ShortUrlResolve(orgData)
1372
1373     '                    '表示用にhtml整形
1374     '                    post.OriginalData = AdjustHtml(orgData)
1375
1376     '                    '単純テキストの取り出し(リンクタグ除去)
1377     '                    Try
1378     '                        post.Data = GetPlainText(orgData)
1379     '                    Catch ex As Exception
1380     '                        _signed = False
1381     '                        TraceOut("TM-Link:" + strPost)
1382     '                        Return "GetTimeline -> Err: Can't parse links."
1383     '                    End Try
1384
1385     '                    ' Imageタグ除去(ハロウィン)
1386     '                    Dim ImgTag As New Regex("<img src=.*?/>", RegexOptions.IgnoreCase)
1387     '                    If ImgTag.IsMatch(post.Data) Then post.Data = ImgTag.Replace(post.Data, "<img>")
1388
1389     '                    'Get Date
1390     '#If 1 Then
1391     '                    Try
1392     '                        pos1 = strPost.IndexOf(_parseDate, pos2, StringComparison.Ordinal)
1393     '                        If pos1 > -1 Then
1394     '                            pos2 = strPost.IndexOf(_parseDateTo, pos1 + _parseDate.Length, StringComparison.Ordinal)
1395     '                            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)
1396     '                        Else
1397     '                            post.PDate = Now()
1398     '                        End If
1399     '                    Catch ex As Exception
1400     '                        _signed = False
1401     '                        TraceOut("TM-Date:" + strPost)
1402     '                        Return "GetTimeline -> Err: Can't get date."
1403     '                    End Try
1404     '#Else
1405     '                    '取得できなくなったため暫定対応(2/26)
1406     '                    post.PDate = Now()
1407     '#End If
1408
1409
1410     '                    'from Sourceの取得
1411     '                    'ToDo: _parseSourceFromを正規表現へ。wedataからの取得へ変更(次版より)
1412     '                    rg = New Regex("<span>.+>(?<name>.+)</a>.*</span>")
1413     '                    m = rg.Match(strPost)
1414     '                    If m.Success Then
1415     '                        post.Source = m.Result("${name}")
1416     '                    Else
1417     '                        post.Source = "Web"
1418     '                    End If
1419     '                    'Try
1420     '                    '    pos1 = strPost.IndexOf(_parseSourceFrom, pos2, StringComparison.Ordinal)
1421     '                    '    If pos1 = -1 Then pos1 = strPost.IndexOf(_parseSourceFrom2, pos2, StringComparison.Ordinal)
1422     '                    '    If pos1 > -1 Then
1423     '                    '        pos1 = strPost.IndexOf(_parseSource2, pos1 + 19, StringComparison.Ordinal)
1424     '                    '        pos2 = strPost.IndexOf(_parseSourceTo, pos1 + 2, StringComparison.Ordinal)
1425     '                    '        post.Source = HttpUtility.HtmlDecode(strPost.Substring(pos1 + 2, pos2 - pos1 - 2))
1426     '                    '    Else
1427     '                    '        post.Source = "Web"
1428     '                    '    End If
1429     '                    'Catch ex As Exception
1430     '                    '    _signed = False
1431     '                    '    TraceOut("TM-Src:" + strPost)
1432     '                    '    Return "GetTimeline -> Err: Can't get src."
1433     '                    'End Try
1434
1435     '                    'Get Reply(in_reply_to_user/id)
1436     '                    'ToDo: _isReplyEngを正規表現へ。wedataからの取得へ変更(次版より)
1437     '                    rg = New Regex("<a href=""https?:\/\/twitter\.com\/(?<name>[a-zA-Z0-9_]+)\/status\/(?<id>[0-9]+)"">(in reply to )*\k<name>")
1438     '                    m = rg.Match(strPost)
1439     '                    If m.Success Then
1440     '                        post.InReplyToUser = m.Result("${name}")
1441     '                        post.InReplyToId = Long.Parse(m.Result("${id}"))
1442     '                        post.IsReply = post.InReplyToUser.Equals(_uid, StringComparison.OrdinalIgnoreCase)
1443     '                    End If
1444
1445     '                    '@先リスト作成
1446     '                    rg = New Regex("@<a [^>]*href=""\/(?<1>[a-zA-Z0-9_]+)[^a-zA-Z0-9_]")
1447     '                    m = rg.Match(orgData)
1448     '                    While m.Success
1449     '                        post.ReplyToList.Add(m.Groups(1).Value.ToLower())
1450     '                        m = m.NextMatch
1451     '                    End While
1452     '                    If Not post.IsReply Then post.IsReply = post.ReplyToList.Contains(_uid)
1453
1454     '                    'Get Fav
1455     '                    post.IsFav = True
1456
1457     '                    If _endingFlag Then Return ""
1458
1459     '                    post.IsMe = post.Name.Equals(_uid, StringComparison.OrdinalIgnoreCase)
1460     '                    SyncLock LockObj
1461     '                        If follower.Count > 1 Then
1462     '                            post.IsOwl = Not follower.Contains(post.Name.ToLower())
1463     '                        Else
1464     '                            post.IsOwl = False
1465     '                        End If
1466     '                    End SyncLock
1467     '                    post.IsRead = read
1468
1469     '                    arIdx += 1
1470     '                    dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
1471     '                    ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
1472
1473     '                End If
1474
1475     '            Next
1476
1477     '            For i As Integer = 0 To arIdx
1478     '                Try
1479     '                    dlgt(i).EndInvoke(ar(i))
1480     '                Catch ex As Exception
1481     '                    '最後までendinvoke回す(ゾンビ化回避)
1482     '                    ex.Data("IsTerminatePermission") = False
1483     '                    Throw
1484     '                End Try
1485     '            Next
1486
1487     '            Return ""
1488     '        Finally
1489     '            GetTmSemaphore.Release()
1490     '        End Try
1491     '    End Function
1492
1493     Private Function PreProcessUrl(ByVal orgData As String) As String
1494         Dim posl1 As Integer
1495         Dim posl2 As Integer = 0
1496         Dim IDNConveter As IdnMapping = New IdnMapping()
1497         Dim href As String = "<a href="""
1498
1499         Do While True
1500             If orgData.IndexOf(href, posl2, StringComparison.Ordinal) > -1 Then
1501                 Dim urlStr As String = ""
1502                 ' IDN展開
1503                 posl1 = orgData.IndexOf(href, posl2, StringComparison.Ordinal)
1504                 posl1 += href.Length
1505                 posl2 = orgData.IndexOf("""", posl1, StringComparison.Ordinal)
1506                 urlStr = orgData.Substring(posl1, posl2 - posl1)
1507
1508                 If Not urlStr.StartsWith("http://") AndAlso Not urlStr.StartsWith("https://") AndAlso Not urlStr.StartsWith("ftp://") Then
1509                     Continue Do
1510                 End If
1511
1512                 Dim replacedUrl As String = IDNDecode(urlStr)
1513                 If replacedUrl Is Nothing Then Continue Do
1514                 If replacedUrl = urlStr Then Continue Do
1515
1516                 orgData = orgData.Replace("<a href=""" + urlStr, "<a href=""" + replacedUrl)
1517                 posl2 = 0
1518             Else
1519                 Exit Do
1520             End If
1521         Loop
1522         Return orgData
1523     End Function
1524     '#If 0 Then
1525     '    Private Function doShortUrlResolve(ByRef orgData As String) As Boolean
1526     '        Dim replaced As Boolean = False
1527     '        For Each _svc As String In _ShortUrlService
1528     '            Dim svc As String = _svc
1529     '            Dim posl1 As Integer
1530     '            Dim posl2 As Integer = 0
1531
1532     '            Do While True
1533     '                If orgData.IndexOf("<a href=""" + svc, posl2, StringComparison.Ordinal) > -1 Then
1534     '                    Dim urlStr As String = ""
1535     '                    Try
1536     '                        posl1 = orgData.IndexOf("<a href=""" + svc, posl2, StringComparison.Ordinal)
1537     '                        posl1 = orgData.IndexOf(svc, posl1, StringComparison.Ordinal)
1538     '                        posl2 = orgData.IndexOf("""", posl1, StringComparison.Ordinal)
1539     '                        urlStr = New Uri(urlEncodeMultibyteChar(orgData.Substring(posl1, posl2 - posl1))).GetLeftPart(UriPartial.Path)
1540     '                        Dim Response As String = ""
1541     '                        Dim retUrlStr As String = ""
1542     '                        Dim tmpurlStr As String = urlStr
1543     '                        Dim SchemeAndDomain As Regex = New Regex("http://.+?/+?")
1544     '                        Dim tmpSchemeAndDomain As String = ""
1545     '                        For i As Integer = 0 To 4   'とりあえず5回試す
1546     '                            retUrlStr = urlEncodeMultibyteChar(DirectCast(CreateSocket.GetWebResponse(tmpurlStr, Response, MySocket.REQ_TYPE.ReqGETForwardTo), String))
1547     '                            If retUrlStr.Length > 0 Then
1548     '                                ' 転送先URLが返された (まだ転送されるかもしれないので返値を引数にしてもう一度)
1549     '                                ' 取得試行回数オーバーの場合は取得結果を転送先とする
1550     '                                Dim scd As Match = SchemeAndDomain.Match(retUrlStr)
1551     '                                If scd.Success AndAlso scd.Value <> svc Then
1552     '                                    svc = scd.Value()
1553     '                                End If
1554     '                                tmpurlStr = retUrlStr
1555     '                                Continue For
1556     '                            Else
1557     '                                ' 転送先URLが返されなかった
1558     '                                If tmpurlStr <> urlStr Then
1559     '                                    '少なくとも一度以上転送されている (前回の結果を転送先とする)
1560     '                                    retUrlStr = tmpurlStr
1561     '                                Else
1562     '                                    ' 一度も転送されていない
1563     '                                    retUrlStr = ""
1564     '                                End If
1565     '                                Exit For
1566     '                            End If
1567     '                        Next
1568     '                        If retUrlStr.Length > 0 Then
1569     '                            If Not retUrlStr.StartsWith("http") Then
1570     '                                If retUrlStr.StartsWith("/") Then
1571     '                                    retUrlStr = urlEncodeMultibyteChar(svc + retUrlStr.Substring(1))
1572     '                                ElseIf retUrlStr.StartsWith("data:") Then
1573     '                                    '
1574     '                                Else
1575     '                                    retUrlStr = urlEncodeMultibyteChar(retUrlStr.Insert(0, svc))
1576     '                                End If
1577     '                            Else
1578     '                                retUrlStr = urlEncodeMultibyteChar(retUrlStr)
1579     '                            End If
1580     '                            orgData = orgData.Replace("<a href=""" + urlStr, "<a href=""" + retUrlStr)
1581     '                            posl2 = 0   '置換した場合は頭から再探索(複数同時置換での例外対応)
1582     '                            replaced = True
1583     '                        End If
1584     '                    Catch ex As Exception
1585     '                        '_signed = False
1586     '                        'Return "GetTimeline -> Err: Can't get tinyurl."
1587     '                    End Try
1588     '                Else
1589     '                    Exit Do
1590     '                End If
1591     '            Loop
1592     '        Next
1593     '        Return replaced
1594     '    End Function
1595     '#Else
1596
1597     '    Private Sub doShortUrlResolve(ByRef orgData As String)
1598     '        'Dim replaced As Boolean = False
1599     '        'Dim svc As String
1600     '        'Dim posl1 As Integer
1601     '        'Dim posl2 As Integer = 0
1602     '        Static urlCache As New Specialized.StringDictionary()
1603     '        If urlCache.Count > 500 Then urlCache.Clear() '定期的にリセット
1604
1605     '        Dim rx As New Regex("<a href=""(?<svc>http://.+?/)(?<path>[^""]+)""", RegexOptions.IgnoreCase)
1606     '        Dim m As MatchCollection = rx.Matches(orgData)
1607     '        Dim urlList As New List(Of String)
1608     '        For Each orgUrlMatch As Match In m
1609     '            Dim orgUrl As String = orgUrlMatch.Result("${svc}")
1610     '            Dim orgUrlPath As String = orgUrlMatch.Result("${path}")
1611     '            If Array.IndexOf(_ShortUrlService, orgUrl) > -1 AndAlso _
1612     '               Not urlList.Contains(orgUrl + orgUrlPath) Then
1613     '                urlList.Add(orgUrl + orgUrlPath)
1614     '            End If
1615     '        Next
1616     '        For Each orgUrl As String In urlList
1617     '            If urlCache.ContainsKey(orgUrl) Then
1618     '                Try
1619     '                    orgData = orgData.Replace("<a href=""" + orgUrl + """", "<a href=""" + urlCache(orgUrl) + """")
1620     '                Catch ex As Exception
1621     '                    'Through
1622     '                End Try
1623     '            Else
1624     '                Try
1625     '                    'urlとして生成できない場合があるらしい
1626     '                    'Dim urlstr As String = New Uri(urlEncodeMultibyteChar(orgUrl)).GetLeftPart(UriPartial.Path)
1627     '                    Dim retUrlStr As String = ""
1628     '                    Dim tmpurlStr As String = New Uri(urlEncodeMultibyteChar(orgUrl)).GetLeftPart(UriPartial.Path)
1629     '                    Dim httpVar As New HttpVarious
1630     '                    retUrlStr = urlEncodeMultibyteChar(httpVar.GetRedirectTo(tmpurlStr))
1631     '                    If retUrlStr.StartsWith("http") Then
1632     '                        retUrlStr = retUrlStr.Replace("""", "%22")  'ダブルコーテーションがあるとURL終端と判断されるため、これだけ再エンコード
1633     '                        orgData = orgData.Replace("<a href=""" + orgUrl + """", "<a href=""" + retUrlStr + """")
1634     '                        urlCache.Add(orgUrl, retUrlStr)
1635     '                    End If
1636     '                Catch ex As Exception
1637     '                    'Through
1638     '                End Try
1639     '            End If
1640     '        Next
1641
1642     '        'For Each ma As Match In m
1643     '        '    svc = ma.Result("${svc}")
1644     '        '    posl1 = ma.Index
1645     '        '    If orgData.IndexOf("<a href=""" + svc, posl2, StringComparison.Ordinal) > -1 Then
1646     '        '        Dim urlStr As String = ""
1647     '        '        Try
1648     '        '            posl1 = orgData.IndexOf("<a href=""" + svc, posl2, StringComparison.Ordinal)
1649     '        '            posl1 = orgData.IndexOf(svc, posl1, StringComparison.Ordinal)
1650     '        '            posl2 = orgData.IndexOf("""", posl1, StringComparison.Ordinal)
1651     '        '            urlStr = New Uri(urlEncodeMultibyteChar(orgData.Substring(posl1, posl2 - posl1))).GetLeftPart(UriPartial.Path)
1652     '        '            Dim Response As String = ""
1653     '        '            Dim retUrlStr As String = ""
1654     '        '            Dim tmpurlStr As String = urlStr
1655     '        '            Dim SchemeAndDomain As Regex = New Regex("http://.+?/+?")
1656     '        '            Dim tmpSchemeAndDomain As String = ""
1657     '        '            For i As Integer = 0 To 4   'とりあえず5回試す
1658     '        '                retUrlStr = urlEncodeMultibyteChar(DirectCast(CreateSocket.GetWebResponse(tmpurlStr, Response, MySocket.REQ_TYPE.ReqGETForwardTo, timeOut:=2000), String))
1659     '        '                If retUrlStr.Length > 0 Then
1660     '        '                    ' 転送先URLが返された (まだ転送されるかもしれないので返値を引数にしてもう一度)
1661     '        '                    ' 取得試行回数オーバーの場合は取得結果を転送先とする
1662     '        '                    Dim scd As Match = SchemeAndDomain.Match(retUrlStr)
1663     '        '                    If scd.Success AndAlso scd.Value <> svc Then
1664     '        '                        svc = scd.Value()
1665     '        '                    End If
1666     '        '                    tmpurlStr = retUrlStr
1667     '        '                    Continue For
1668     '        '                Else
1669     '        '                    ' 転送先URLが返されなかった
1670     '        '                    If tmpurlStr <> urlStr Then
1671     '        '                        '少なくとも一度以上転送されている (前回の結果を転送先とする)
1672     '        '                        retUrlStr = tmpurlStr
1673     '        '                    Else
1674     '        '                        ' 一度も転送されていない
1675     '        '                        retUrlStr = ""
1676     '        '                    End If
1677     '        '                    Exit For
1678     '        '                End If
1679     '        '            Next
1680     '        '            If retUrlStr.Length > 0 Then
1681     '        '                If Not retUrlStr.StartsWith("http") Then
1682     '        '                    If retUrlStr.StartsWith("/") Then
1683     '        '                        retUrlStr = urlEncodeMultibyteChar(svc + retUrlStr.Substring(1))
1684     '        '                    ElseIf retUrlStr.StartsWith("data:") Then
1685     '        '                        '
1686     '        '                    Else
1687     '        '                        retUrlStr = urlEncodeMultibyteChar(retUrlStr.Insert(0, svc))
1688     '        '                    End If
1689     '        '                Else
1690     '        '                    retUrlStr = urlEncodeMultibyteChar(retUrlStr)
1691     '        '                End If
1692     '        '                orgData = orgData.Replace("<a href=""" + urlStr, "<a href=""" + retUrlStr)
1693     '        '                posl2 = 0   '置換した場合は頭から再探索(複数同時置換での例外対応)
1694     '        '                replaced = True
1695     '        '            End If
1696     '        '        Catch ex As Exception
1697     '        '            '_signed = False
1698     '        '            'Return "GetTimeline -> Err: Can't get tinyurl."
1699     '        '        End Try
1700     '        '    Else
1701     '        '        Exit For
1702     '        '    End If
1703     '        'Next
1704     '        'Return replaced
1705     '    End Sub
1706     '#End If
1707
1708     Private Function ShortUrlResolve(ByVal orgData As String) As String
1709         If _tinyUrlResolve Then
1710             Static urlCache As New Specialized.StringDictionary()
1711             If urlCache.Count > 500 Then urlCache.Clear() '定期的にリセット
1712
1713             'Dim rx As New Regex("<a href=""(?<svc>http://.+?/)(?<path>[^""]+)""", RegexOptions.IgnoreCase)
1714             Dim m As MatchCollection = Regex.Matches(orgData, "<a href=""(?<svc>http://.+?/)(?<path>[^""]+)""", RegexOptions.IgnoreCase)
1715             Dim urlList As New List(Of String)
1716             For Each orgUrlMatch As Match In m
1717                 Dim orgUrl As String = orgUrlMatch.Result("${svc}")
1718                 Dim orgUrlPath As String = orgUrlMatch.Result("${path}")
1719                 If Array.IndexOf(_ShortUrlService, orgUrl) > -1 AndAlso _
1720                    Not urlList.Contains(orgUrl + orgUrlPath) Then
1721                     urlList.Add(orgUrl + orgUrlPath)
1722                 End If
1723             Next
1724             For Each orgUrl As String In urlList
1725                 If urlCache.ContainsKey(orgUrl) Then
1726                     Try
1727                         orgData = orgData.Replace("<a href=""" + orgUrl + """", "<a href=""" + urlCache(orgUrl) + """")
1728                     Catch ex As Exception
1729                         'Through
1730                     End Try
1731                 Else
1732                     Try
1733                         'urlとして生成できない場合があるらしい
1734                         'Dim urlstr As String = New Uri(urlEncodeMultibyteChar(orgUrl)).GetLeftPart(UriPartial.Path)
1735                         Dim retUrlStr As String = ""
1736                         Dim tmpurlStr As String = New Uri(urlEncodeMultibyteChar(orgUrl)).GetLeftPart(UriPartial.Path)
1737                         Dim httpVar As New HttpVarious
1738                         retUrlStr = urlEncodeMultibyteChar(httpVar.GetRedirectTo(tmpurlStr))
1739                         If retUrlStr.StartsWith("http") Then
1740                             retUrlStr = retUrlStr.Replace("""", "%22")  'ダブルコーテーションがあるとURL終端と判断されるため、これだけ再エンコード
1741                             orgData = orgData.Replace("<a href=""" + orgUrl + """", "<a href=""" + retUrlStr + """")
1742                             urlCache.Add(orgUrl, retUrlStr)
1743                         End If
1744                     Catch ex As Exception
1745                         'Through
1746                     End Try
1747                 End If
1748             Next
1749         End If
1750         Return orgData
1751     End Function
1752
1753     Private Function GetPlainText(ByVal orgData As String) As String
1754         Return HttpUtility.HtmlDecode(Regex.Replace(orgData, "(?<tagStart><a [^>]+>)(?<text>[^<]+)(?<tagEnd></a>)", "${text}"))
1755         '不具合緊急対応で上記へ変更
1756         ''単純テキストの取り出し(リンクタグ除去)
1757         'If orgData.IndexOf(_parseLink1, StringComparison.Ordinal) = -1 Then
1758         '    retStr = HttpUtility.HtmlDecode(orgData)
1759         'Else
1760         '    Dim posl1 As Integer
1761         '    Dim posl2 As Integer
1762         '    Dim posl3 As Integer = 0
1763
1764         '    retStr = ""
1765
1766         '    posl3 = 0
1767         '    Do While True
1768         '        posl1 = orgData.IndexOf(_parseLink1, posl3, StringComparison.Ordinal)
1769         '        If posl1 = -1 Then Exit Do
1770
1771         '        If (posl3 + _parseLink3.Length <> posl1) Or posl3 = 0 Then
1772         '            If posl3 <> 0 Then
1773         '                retStr += HttpUtility.HtmlDecode(orgData.Substring(posl3 + _parseLink3.Length, posl1 - posl3 - _parseLink3.Length))
1774         '            Else
1775         '                retStr += HttpUtility.HtmlDecode(orgData.Substring(0, posl1))
1776         '            End If
1777         '        End If
1778         '        posl2 = orgData.IndexOf(_parseLink2, posl1, StringComparison.Ordinal)
1779         '        posl3 = orgData.IndexOf(_parseLink3, posl2, StringComparison.Ordinal)
1780         '        retStr += HttpUtility.HtmlDecode(orgData.Substring(posl2 + _parseLink2.Length, posl3 - posl2 - _parseLink2.Length))
1781         '    Loop
1782         '    retStr += HttpUtility.HtmlDecode(orgData.Substring(posl3 + _parseLink3.Length))
1783         'End If
1784
1785         'Return retStr
1786     End Function
1787
1788     ' htmlの簡易サニタイズ(詳細表示に不要なタグの除去)
1789
1790     Private Function SanitizeHtml(ByVal orgdata As String) As String
1791         Dim retdata As String = orgdata
1792
1793         '  <script ~ </script>
1794         'Dim rx As Regex = New Regex( _
1795         '    "<(script|object|applet|image|frameset|fieldset|legend|style).*" & _
1796         '    "</(script|object|applet|image|frameset|fieldset|legend|style)>", RegexOptions.IgnoreCase)
1797         retdata = Regex.Replace(retdata, "<(script|object|applet|image|frameset|fieldset|legend|style).*" & _
1798             "</(script|object|applet|image|frameset|fieldset|legend|style)>", "", RegexOptions.IgnoreCase)
1799
1800         ' <frame src="...">
1801         'rx = New Regex("<(frame|link|iframe|img)>", RegexOptions.IgnoreCase)
1802         retdata = Regex.Replace(retdata, "<(frame|link|iframe|img)>", "", RegexOptions.IgnoreCase)
1803
1804         Return retdata
1805     End Function
1806
1807     Private Function AdjustHtml(ByVal orgData As String) As String
1808         Dim retStr As String = orgData
1809         'Dim hash As New Regex("<a [^>]+>[#|#](?<1>[a-zA-Z0-9_]+)</a>")
1810         Dim m As Match = Regex.Match(retStr, "<a [^>]+>[#|#](?<1>[a-zA-Z0-9_]+)</a>")
1811         While m.Success
1812             SyncLock LockObj
1813                 _hashList.Add("#" + m.Groups(1).Value)
1814             End SyncLock
1815             m = m.NextMatch
1816         End While
1817         retStr = Regex.Replace(retStr, "<a [^>]*href=""/", "<a href=""" + _protocol + "twitter.com/")
1818         retStr = retStr.Replace("<a href=", "<a target=""_self"" href=")
1819         retStr = retStr.Replace(vbLf, "<br>")
1820
1821         '半角スペースを置換(Thanks @anis774)
1822         Dim ret As Boolean = False
1823         Do
1824             ret = EscapeSpace(retStr)
1825         Loop While Not ret
1826         'Dim isTag As Boolean = False
1827         'For i As Integer = 0 To retStr.Length - 1
1828         '    If retStr(i) = "<"c Then
1829         '        isTag = True
1830         '    End If
1831         '    If retStr(i) = ">"c Then
1832         '        isTag = False
1833         '    End If
1834
1835         '    If (Not isTag) AndAlso (retStr(i) = " "c) Then
1836         '        retStr = retStr.Remove(i, 1)
1837         '        retStr = retStr.Insert(i, "&nbsp;")
1838         '    End If
1839         'Next
1840
1841         Return SanitizeHtml(retStr)
1842     End Function
1843
1844     Private Function EscapeSpace(ByRef html As String) As Boolean
1845         '半角スペースを置換(Thanks @anis774)
1846         Dim isTag As Boolean = False
1847         For i As Integer = 0 To html.Length - 1
1848             If html(i) = "<"c Then
1849                 isTag = True
1850             End If
1851             If html(i) = ">"c Then
1852                 isTag = False
1853             End If
1854
1855             If (Not isTag) AndAlso (html(i) = " "c) Then
1856                 html = html.Remove(i, 1)
1857                 html = html.Insert(i, "&nbsp;")
1858                 Return False
1859             End If
1860         Next
1861         Return True
1862     End Function
1863
1864     Private Sub GetIconImage(ByVal post As PostClass)
1865         Dim img As Image
1866         Dim bmp2 As Bitmap
1867
1868         Try
1869             If Not _getIcon Then
1870                 post.ImageIndex = -1
1871                 TabInformations.GetInstance.AddPost(post)
1872                 Exit Sub
1873             End If
1874
1875             SyncLock LockObj
1876                 post.ImageIndex = _lIcon.Images.IndexOfKey(post.ImageUrl)
1877             End SyncLock
1878
1879             If post.ImageIndex > -1 Then
1880                 TabInformations.GetInstance.AddPost(post)
1881                 Exit Sub
1882             End If
1883
1884             Dim httpVar As New HttpVarious
1885             img = httpVar.GetImage(post.ImageUrl)
1886             If img Is Nothing Then
1887                 post.ImageIndex = -1
1888                 TabInformations.GetInstance.AddPost(post)
1889                 Exit Sub
1890             End If
1891
1892             If _endingFlag Then Exit Sub
1893
1894             bmp2 = New Bitmap(_iconSz, _iconSz)
1895             Using g As Graphics = Graphics.FromImage(bmp2)
1896                 g.InterpolationMode = Drawing2D.InterpolationMode.High
1897                 g.DrawImage(img, 0, 0, _iconSz, _iconSz)
1898                 g.Dispose()
1899             End Using
1900
1901             SyncLock LockObj
1902                 post.ImageIndex = _lIcon.Images.IndexOfKey(post.ImageUrl)
1903                 If post.ImageIndex = -1 Then
1904                     Try
1905                         If img.RawFormat.Guid = Imaging.ImageFormat.Gif.Guid Then
1906                             Dim fd As New System.Drawing.Imaging.FrameDimension(img.FrameDimensionsList(0))
1907                             Dim fd_count As Integer = img.GetFrameCount(fd)
1908                             If fd_count > 1 Then
1909                                 Try
1910                                     For i As Integer = 0 To fd_count - 1
1911                                         img.SelectActiveFrame(fd, i)
1912                                     Next
1913                                     _dIcon.Add(post.ImageUrl, img)  '詳細表示用ディクショナリに追加
1914                                 Catch ex As Exception
1915                                     Dim bmp As New Bitmap(48, 48)
1916                                     Using g As Graphics = Graphics.FromImage(bmp)
1917                                         g.InterpolationMode = Drawing2D.InterpolationMode.High
1918                                         g.DrawImage(img, 0, 0, 48, 48)
1919                                     End Using
1920                                     _dIcon.Add(post.ImageUrl, bmp)  '詳細表示用ディクショナリに追加
1921                                     img.Dispose()
1922                                 End Try
1923                             Else
1924                                 _dIcon.Add(post.ImageUrl, img)  '詳細表示用ディクショナリに追加
1925                             End If
1926                             _lIcon.Images.Add(post.ImageUrl, bmp2)
1927                             post.ImageIndex = _lIcon.Images.IndexOfKey(post.ImageUrl)
1928                         Else
1929                             _dIcon.Add(post.ImageUrl, img)
1930                             _lIcon.Images.Add(post.ImageUrl, bmp2)
1931                             post.ImageIndex = _lIcon.Images.IndexOfKey(post.ImageUrl)
1932                         End If
1933                     Catch ex As InvalidOperationException
1934                         'タイミングにより追加できない場合がある?(キー重複ではない)
1935                         post.ImageIndex = -1
1936                     End Try
1937                 End If
1938             End SyncLock
1939             TabInformations.GetInstance.AddPost(post)
1940         Catch ex As ArgumentException
1941             'タイミングによってはキー重複
1942         Finally
1943             img = Nothing
1944             bmp2 = Nothing
1945             post = Nothing
1946         End Try
1947     End Sub
1948
1949     'Private Function GetAuthKey(ByVal resMsg As String) As Integer
1950     '    Dim pos1 As Integer
1951     '    Dim pos2 As Integer
1952
1953     '    pos1 = resMsg.IndexOf(_getAuthKey, StringComparison.Ordinal)
1954     '    If pos1 < 0 Then
1955     '        'データ不正?
1956     '        Return -7
1957     '    End If
1958     '    pos2 = resMsg.IndexOf(_getAuthKeyTo, pos1 + _getAuthKey.Length, StringComparison.Ordinal)
1959     '    If pos2 > -1 Then
1960     '        _authKey = resMsg.Substring(pos1 + _getAuthKey.Length, pos2 - pos1 - _getAuthKey.Length)
1961     '    Else
1962     '        Return -7
1963     '    End If
1964
1965     '    Return 0
1966     'End Function
1967
1968     'Private Function GetAuthKeyDM(ByVal resMsg As String) As Integer
1969     '    Dim pos1 As Integer
1970     '    Dim pos2 As Integer
1971
1972     '    pos1 = resMsg.IndexOf(_getAuthKey, StringComparison.Ordinal)
1973     '    If pos1 < 0 Then
1974     '        'データ不正?
1975     '        Return -7
1976     '    End If
1977     '    pos2 = resMsg.IndexOf("""", pos1 + _getAuthKey.Length, StringComparison.Ordinal)
1978     '    _authKeyDM = resMsg.Substring(pos1 + _getAuthKey.Length, pos2 - pos1 - _getAuthKey.Length)
1979
1980     '    Return 0
1981     'End Function
1982
1983     Private Structure PostInfo
1984         Public CreatedAt As String
1985         Public Id As String
1986         Public Text As String
1987         Public UserId As String
1988         Public Sub New(ByVal Created As String, ByVal IdStr As String, ByVal txt As String, ByVal uid As String)
1989             CreatedAt = Created
1990             Id = IdStr
1991             Text = txt
1992             UserId = uid
1993         End Sub
1994         Public Shadows Function Equals(ByVal dst As PostInfo) As Boolean
1995             If Me.CreatedAt = dst.CreatedAt AndAlso Me.Id = dst.Id AndAlso Me.Text = dst.Text AndAlso Me.UserId = dst.UserId Then
1996                 Return True
1997             Else
1998                 Return False
1999             End If
2000         End Function
2001     End Structure
2002
2003     Private Function IsPostRestricted(ByRef resMsg As String) As Boolean
2004         Static _prev As New PostInfo("", "", "", "")
2005         Dim _current As New PostInfo("", "", "", "")
2006
2007
2008         Dim xd As XmlDocument = New XmlDocument()
2009         Try
2010             xd.LoadXml(resMsg)
2011             _current.CreatedAt = xd.SelectSingleNode("/status/created_at/text()").Value
2012             _current.Id = xd.SelectSingleNode("/status/id/text()").Value
2013             _current.Text = xd.SelectSingleNode("/status/text/text()").Value
2014             _current.UserId = xd.SelectSingleNode("/status/user/id/text()").Value
2015
2016             If _current.Equals(_prev) Then
2017                 Return True
2018             End If
2019             _prev.CreatedAt = _current.CreatedAt
2020             _prev.Id = _current.Id
2021             _prev.Text = _current.Text
2022             _prev.UserId = _current.UserId
2023         Catch ex As XmlException
2024             Return False
2025         End Try
2026
2027         Return False
2028     End Function
2029
2030     Public Function PostStatus(ByVal postStr As String, ByVal reply_to As Long) As String
2031
2032         If _endingFlag Then Return ""
2033
2034         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2035
2036         postStr = postStr.Trim()
2037
2038         Dim res As HttpStatusCode
2039         Dim content As String = ""
2040         Try
2041             res = twCon.UpdateStatus(postStr, reply_to, content)
2042         Catch ex As Exception
2043             Return "Err:" + ex.Message
2044         End Try
2045
2046         Select Case res
2047             Case HttpStatusCode.OK
2048                 Dim xd As XmlDocument = New XmlDocument()
2049                 Try
2050                     xd.LoadXml(content)
2051                     Dim xNode As XmlNode = Nothing
2052                     xNode = xd.SelectSingleNode("/status/user/followers_count/text()")
2053                     If xNode IsNot Nothing Then _followersCount = Integer.Parse(xNode.Value)
2054                     xNode = xd.SelectSingleNode("/status/user/friends_count/text()")
2055                     If xNode IsNot Nothing Then _friendsCount = Integer.Parse(xNode.Value)
2056                     xNode = xd.SelectSingleNode("/status/user/statuses_count/text()")
2057                     If xNode IsNot Nothing Then _statusesCount = Integer.Parse(xNode.Value)
2058                     xNode = xd.SelectSingleNode("/status/user/location/text()")
2059                     If xNode IsNot Nothing Then _location = xNode.Value
2060                     xNode = xd.SelectSingleNode("/status/user/description/text()")
2061                     If xNode IsNot Nothing Then _bio = xNode.Value
2062                 Catch ex As Exception
2063                     Return ""
2064                 End Try
2065
2066                 If Not postStr.StartsWith("D ", StringComparison.OrdinalIgnoreCase) AndAlso _
2067                         Not postStr.StartsWith("DM ", StringComparison.OrdinalIgnoreCase) AndAlso _
2068                         IsPostRestricted(content) Then
2069                     Return "OK:Delaying?"
2070                 End If
2071                 If op.Post(postStr.Length) Then
2072                     Return ""
2073                 Else
2074                     Return "Outputz:Failed"
2075                 End If
2076             Case HttpStatusCode.Forbidden
2077                 Dim xd As XmlDocument = New XmlDocument
2078                 Try
2079                     xd.LoadXml(content)
2080                     Dim xNode As XmlNode = Nothing
2081                     xNode = xd.SelectSingleNode("/hash/error")
2082                     Return "OK:" + xNode.InnerText
2083                 Catch ex As Exception
2084                 End Try
2085                 Return "Err:Update Limits?"
2086             Case HttpStatusCode.Unauthorized
2087                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2088                 Return "Check your Username/Password."
2089             Case Else
2090                 Return "Err:" + res.ToString
2091         End Select
2092     End Function
2093
2094     Public Function RemoveStatus(ByVal id As Long) As String
2095         If _endingFlag Then Return ""
2096
2097         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2098
2099         Dim res As HttpStatusCode
2100
2101         Try
2102             res = twCon.DestroyStatus(id)
2103         Catch ex As Exception
2104             Return "Err:" + ex.Message
2105         End Try
2106
2107         Select Case res
2108             Case HttpStatusCode.OK
2109                 Return ""
2110             Case HttpStatusCode.Unauthorized
2111                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2112                 Return "Check your Username/Password."
2113             Case HttpStatusCode.NotFound
2114                 Return ""
2115             Case Else
2116                 Return "Err:" + res.ToString
2117         End Select
2118
2119     End Function
2120
2121     Public Function PostRetweet(ByVal id As Long, ByVal read As Boolean) As String
2122         If _endingFlag Then Return ""
2123         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2124
2125         'データ部分の生成
2126         Dim target As Long = id
2127         If TabInformations.GetInstance.Item(id).RetweetedId > 0 Then
2128             target = TabInformations.GetInstance.Item(id).RetweetedId '再RTの場合は元発言をRT
2129         End If
2130
2131         Dim res As HttpStatusCode
2132         Dim content As String = ""
2133         Try
2134             res = twCon.RetweetStatus(target, content)
2135         Catch ex As Exception
2136             Return "Err:" + ex.Message
2137         End Try
2138
2139         Select Case res
2140             Case HttpStatusCode.Unauthorized
2141                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2142                 Return "Check your Username/Password."
2143             Case Is <> HttpStatusCode.OK
2144                 Return "Err:" + res.ToString()
2145         End Select
2146
2147         Dim dlgt As GetIconImageDelegate    'countQueryに合わせる
2148         Dim ar As IAsyncResult              'countQueryに合わせる
2149         Dim xdoc As New XmlDocument
2150         Try
2151             xdoc.LoadXml(content)
2152         Catch ex As Exception
2153             TraceOut(content)
2154             'MessageBox.Show("不正なXMLです。(TL-LoadXml)")
2155             Return "Invalid XML!"
2156         End Try
2157
2158         'ReTweetしたものをTLに追加
2159         Dim xentryNode As XmlNode = xdoc.DocumentElement.SelectSingleNode("/status")
2160         If xentryNode Is Nothing Then Return "Invalid XML!"
2161         Dim xentry As XmlElement = CType(xentryNode, XmlElement)
2162         Dim post As New PostClass
2163         Try
2164             post.Id = Long.Parse(xentry.Item("id").InnerText)
2165             '二重取得回避
2166             SyncLock LockObj
2167                 If TabInformations.GetInstance.ContainsKey(post.Id) Then Return ""
2168             End SyncLock
2169             'Retweet判定
2170             Dim xRnode As XmlNode = xentry.SelectSingleNode("./retweeted_status")
2171             If xRnode Is Nothing Then Return "Invalid XML!"
2172
2173             Dim xRentry As XmlElement = CType(xRnode, XmlElement)
2174             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)
2175             'Id
2176             post.RetweetedId = Long.Parse(xRentry.Item("id").InnerText)
2177             '本文
2178             post.Data = xRentry.Item("text").InnerText
2179             'Source取得(htmlの場合は、中身を取り出し)
2180             post.Source = xRentry.Item("source").InnerText
2181             'Reply先
2182             Long.TryParse(xRentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
2183             post.InReplyToUser = xRentry.Item("in_reply_to_screen_name").InnerText
2184             post.IsFav = TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.RetweetedId)
2185
2186             '以下、ユーザー情報
2187             Dim xRUentry As XmlElement = CType(xRentry.SelectSingleNode("./user"), XmlElement)
2188             post.Uid = Long.Parse(xRUentry.Item("id").InnerText)
2189             post.Name = xRUentry.Item("screen_name").InnerText
2190             post.Nickname = xRUentry.Item("name").InnerText
2191             post.ImageUrl = xRUentry.Item("profile_image_url").InnerText
2192             post.IsProtect = Boolean.Parse(xRUentry.Item("protected").InnerText)
2193             'post.IsMe = post.Name.ToLower.Equals(_uid)
2194             post.IsMe = True
2195
2196             'Retweetした人(自分のはず)
2197             Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
2198             post.RetweetedBy = xUentry.Item("screen_name").InnerText
2199
2200             'HTMLに整形
2201             post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
2202             post.Data = HttpUtility.HtmlDecode(post.Data)
2203             post.Data = post.Data.Replace("<3", "♡")
2204             'Source整形
2205             If post.Source.StartsWith("<") Then
2206                 'Dim rgS As New Regex(">(?<source>.+)<")
2207                 Dim mS As Match = Regex.Match(post.Source, ">(?<source>.+)<")
2208                 If mS.Success Then
2209                     post.Source = mS.Result("${source}")
2210                 End If
2211             End If
2212
2213             post.IsRead = read
2214             post.IsReply = post.ReplyToList.Contains(_uid)
2215
2216             If post.IsMe Then
2217                 post.IsOwl = False
2218             Else
2219                 If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.Uid)
2220             End If
2221             If post.IsMe AndAlso _readOwnPost Then post.IsRead = True
2222
2223             post.IsDm = False
2224         Catch ex As Exception
2225             TraceOut(content)
2226             'MessageBox.Show("不正なXMLです。(TL-Parse)")
2227             Return "Invalid XML!"
2228         End Try
2229
2230         '非同期アイコン取得&StatusDictionaryに追加
2231         dlgt = New GetIconImageDelegate(AddressOf GetIconImage)
2232         ar = dlgt.BeginInvoke(post, Nothing, Nothing)
2233
2234         'アイコン取得完了待ち
2235         Try
2236             dlgt.EndInvoke(ar)
2237         Catch ex As Exception
2238             '最後までendinvoke回す(ゾンビ化回避)
2239             ex.Data("IsTerminatePermission") = False
2240             Throw
2241         End Try
2242
2243         Return ""
2244     End Function
2245
2246     Public Function RemoveDirectMessage(ByVal id As Long) As String
2247         If _endingFlag Then Return ""
2248
2249         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2250
2251         Dim res As HttpStatusCode
2252
2253         Try
2254             res = twCon.DestroyDirectMessage(id)
2255         Catch ex As Exception
2256             Return "Err:" + ex.Message
2257         End Try
2258
2259         Select Case res
2260             Case HttpStatusCode.OK
2261                 Return ""
2262             Case HttpStatusCode.Unauthorized
2263                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2264                 Return "Check your Username/Password."
2265             Case HttpStatusCode.NotFound
2266                 Return ""
2267             Case Else
2268                 Return "Err:" + res.ToString
2269         End Select
2270     End Function
2271
2272     Public Function PostFollowCommand(ByVal screenName As String) As String
2273
2274         If _endingFlag Then Return ""
2275
2276         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2277
2278         Dim res As HttpStatusCode
2279
2280         Try
2281             res = twCon.CreateFriendships(screenName)
2282         Catch ex As Exception
2283             Return "Err:" + ex.Message
2284         End Try
2285
2286         Select Case res
2287             Case HttpStatusCode.OK
2288                 Return ""
2289             Case HttpStatusCode.Unauthorized
2290                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2291                 Return "Check your Username/Password."
2292             Case HttpStatusCode.Forbidden
2293                 Return "Err:Update Limits?"
2294             Case Else
2295                 Return "Err:" + res.ToString
2296         End Select
2297     End Function
2298
2299     Public Function PostRemoveCommand(ByVal screenName As String) As String
2300
2301         If _endingFlag Then Return ""
2302
2303         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2304
2305         Dim res As HttpStatusCode
2306
2307         Try
2308             res = twCon.DestroyFriendships(screenName)
2309         Catch ex As Exception
2310             Return "Err:" + ex.Message
2311         End Try
2312
2313         Select Case res
2314             Case HttpStatusCode.OK
2315                 Return ""
2316             Case HttpStatusCode.Unauthorized
2317                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2318                 Return "Check your Username/Password."
2319             Case Else
2320                 Return "Err:" + res.ToString
2321         End Select
2322     End Function
2323
2324     Public Function GetFriendshipInfo(ByVal screenName As String, ByRef isFollowing As Boolean, ByRef isFollowed As Boolean) As String
2325
2326         If _endingFlag Then Return ""
2327
2328         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2329
2330         Dim res As HttpStatusCode
2331         Dim content As String = ""
2332         Try
2333             res = twCon.ShowFriendships(_uid, screenName, content)
2334         Catch ex As Exception
2335             Return "Err:" + ex.Message
2336         End Try
2337
2338         Select Case res
2339             Case HttpStatusCode.OK
2340                 Dim xdoc As New XmlDocument
2341                 Dim result As String = ""
2342                 Try
2343                     xdoc.LoadXml(content)
2344                     isFollowing = Boolean.Parse(xdoc.SelectSingleNode("/relationship/source/following").InnerText)
2345                     isFollowed = Boolean.Parse(xdoc.SelectSingleNode("/relationship/source/followed_by").InnerText)
2346                 Catch ex As Exception
2347                     result = "Err:Invalid XML."
2348                 End Try
2349                 Return result
2350             Case HttpStatusCode.BadRequest
2351                 Return "Err:API Limits?"
2352             Case HttpStatusCode.Unauthorized
2353                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2354                 Return "Check your Username/Password."
2355             Case Else
2356                 Return "Err:" + res.ToString
2357         End Select
2358     End Function
2359
2360     Public Function PostFavAdd(ByVal id As Long) As String
2361         If _endingFlag Then Return ""
2362
2363         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2364
2365         Dim res As HttpStatusCode
2366
2367         Try
2368             res = twCon.CreateFavorites(id)
2369         Catch ex As Exception
2370             Return "Err:" + ex.Message
2371         End Try
2372
2373         Select Case res
2374             Case HttpStatusCode.OK
2375                 If Not _restrictFavCheck Then Return ""
2376             Case HttpStatusCode.Unauthorized
2377                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2378                 Return "Check your Username/Password."
2379             Case HttpStatusCode.Forbidden
2380                 Return "Err:Update Limits?"
2381             Case Else
2382                 Return "Err:" + res.ToString
2383         End Select
2384
2385         'http://twitter.com/statuses/show/id.xml APIを発行して本文を取得
2386
2387         Dim content As String = ""
2388         Try
2389             res = twCon.ShowStatuses(id, content)
2390         Catch ex As Exception
2391             Return "Err:" + ex.Message
2392         End Try
2393
2394         Select Case res
2395             Case HttpStatusCode.OK
2396                 Try
2397                     Using rd As Xml.XmlTextReader = New Xml.XmlTextReader(New System.IO.StringReader(content))
2398                         rd.Read()
2399                         While rd.EOF = False
2400                             If rd.IsStartElement("favorited") Then
2401                                 If rd.ReadElementContentAsBoolean() = True Then
2402                                     Return ""  '正常にふぁぼれている
2403                                 Else
2404                                     Return "NG(Restricted?)"  '正常応答なのにふぁぼれてないので制限っぽい
2405                                 End If
2406                             Else
2407                                 rd.Read()
2408                             End If
2409                         End While
2410                         rd.Close()
2411                         Return "Err:Invalid XML!"
2412                     End Using
2413                 Catch ex As XmlException
2414                     Return ""
2415                 End Try
2416             Case HttpStatusCode.Unauthorized
2417                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2418                 Return "Check your Username/Password."
2419             Case HttpStatusCode.BadRequest
2420                 Return "Err:API Limits?"
2421             Case Else
2422                 Return "Err:" + res.ToString
2423         End Select
2424
2425     End Function
2426
2427     Public Function PostFavRemove(ByVal id As Long) As String
2428         If _endingFlag Then Return ""
2429
2430         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2431
2432         Dim res As HttpStatusCode
2433
2434         Try
2435             res = twCon.DestroyFavorites(id)
2436         Catch ex As Exception
2437             Return "Err:" + ex.Message
2438         End Try
2439
2440         Select Case res
2441             Case HttpStatusCode.OK
2442                 Return ""
2443             Case HttpStatusCode.Unauthorized
2444                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2445                 Return "Check your Username/Password."
2446             Case HttpStatusCode.Forbidden
2447                 Return "Err:Update Limits?"
2448             Case Else
2449                 Return "Err:" + res.ToString
2450         End Select
2451     End Function
2452
2453     '#Region "follower取得"
2454     '    'Delegate Function GetFollowersDelegate(ByVal Query As Integer) As String
2455     '    'Private semaphore As Threading.Semaphore = Nothing
2456     '    'Private threadNum As Integer = 0
2457     '    Private _threadErr As Boolean = False
2458
2459     '    Private Function GetFollowersMethod() As String
2460     '        Dim resStatus As String = ""
2461     '        Dim resMsg As String = ""
2462     '        Dim lineCount As Integer = 0
2463     '        Dim page As Long = -1
2464
2465     '        Do
2466     '            If _endingFlag Then Exit Do
2467     '            resMsg = DirectCast(CreateSocket.GetWebResponse(_protocol + _apiHost + _hubServer + _GetFollowers + _cursorQry + page.ToString, resStatus, MySocket.REQ_TYPE.ReqGetAPI), String)
2468     '            If resStatus.StartsWith("OK") = False Then
2469     '                Debug.WriteLine(page.ToString)
2470     '                _threadErr = True
2471     '                Return resStatus
2472     '            End If
2473     '            Try
2474     '                Using rd As Xml.XmlTextReader = New Xml.XmlTextReader(New System.IO.StringReader(resMsg))
2475     '                    lineCount = 0
2476     '                    rd.Read()
2477     '                    While rd.EOF = False
2478     '                        If rd.IsStartElement("screen_name") Then
2479     '                            Dim tmp As String = rd.ReadElementString("screen_name").ToLower()
2480     '                            SyncLock LockObj
2481     '                                If Not tmpFollower.Contains(tmp) Then
2482     '                                    tmpFollower.Add(tmp)
2483     '                                End If
2484     '                            End SyncLock
2485     '                            lineCount += 1
2486     '                        ElseIf rd.IsStartElement("next_cursor") Then
2487     '                            page = Long.Parse(rd.ReadElementString("next_cursor"))
2488     '                            If page = 0 Then Exit Do
2489     '                            Exit While
2490     '                        Else
2491     '                            rd.Read()
2492     '                        End If
2493     '                    End While
2494     '                End Using
2495     '            Catch ex As Exception
2496     '                _threadErr = True
2497     '                TraceOut("NG(XmlException)")
2498     '                Return "NG(XmlException)"
2499     '            End Try
2500     '        Loop While lineCount > 0
2501
2502     '        Return ""
2503     '    End Function
2504
2505     'Private Sub GetFollowersCallback(ByVal ar As IAsyncResult)
2506     '    Dim dlgt As GetFollowersDelegate = DirectCast(ar.AsyncState, GetFollowersDelegate)
2507
2508     '    Try
2509     '        Dim ret As String = dlgt.EndInvoke(ar)
2510     '        If Not ret.Equals("") AndAlso Not _threadErr Then
2511     '            TraceOut(ret)
2512     '            _threadErr = True
2513     '        End If
2514     '    Catch ex As Exception
2515     '        _threadErr = True
2516     '        ex.Data("IsTerminatePermission") = False
2517     '        Throw
2518     '    Finally
2519     '        GetTmSemaphore.Release()                     ' セマフォから出る
2520     '        Interlocked.Decrement(threadNum)        ' スレッド数カウンタを-1
2521     '    End Try
2522
2523     'End Sub
2524
2525     '' キャッシュの検証と読み込み -1を渡した場合は読み込みのみ行う(APIエラーでFollowersCountが取得できなかったとき)
2526     'Private Function ValidateCache() As Integer
2527
2528     '    follower.Clear()
2529     '    Try
2530     '        Dim setting As SettingFollower = SettingFollower.Load()
2531     '        follower = setting.Follower
2532     '        If follower.Count = 0 OrElse Not follower(0).Equals(_uid.ToLower()) Then
2533     '            ' 別IDの場合はキャッシュ破棄して読み直し
2534     '            Return -1
2535     '        End If
2536     '    Catch ex As XmlException
2537     '        ' 不正なxmlの場合は読み直し
2538     '        Return -1
2539     '    Catch ex As InvalidOperationException
2540     '        'XMLが壊れている場合
2541     '        Return -1
2542     '    End Try
2543
2544     '    'If _FollowersCount = -1 Then Return tmpFollower.Count
2545     '    Return follower.Count
2546
2547     '    'If (_FollowersCount + 1) = tmpFollower.Count Then
2548     '    '    '変動がないので読み込みの必要なし
2549     '    '    Return 0
2550     '    'ElseIf (_FollowersCount + 1) < tmpFollower.Count Then
2551     '    '    '減っている場合はどこが抜けているのかわからないので全部破棄して読み直し
2552     '    '    tmpFollower.Clear()
2553     '    '    tmpFollower.Add(_uid.ToLower())
2554     '    '    Return _FollowersCount
2555     '    'End If
2556
2557     '    '' 増えた場合は差分だけ読む
2558
2559     '    'Return _FollowersCount - tmpFollower.Count
2560
2561     'End Function
2562
2563     'Private Sub UpdateCache()
2564     '    Dim setting As New SettingFollower(follower)
2565     '    setting.Save()
2566     'End Sub
2567
2568     '    Public Function GetFollowers(ByVal CacheInvalidate As Boolean) As String
2569     '#If DEBUG Then
2570     '        Dim sw As New System.Diagnostics.Stopwatch
2571     '        sw.Start()
2572     '#End If
2573
2574     '        If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2575
2576     '        'Dim resStatus As String = ""
2577     '        'Dim resMsg As String = ""
2578     '        'Dim i As Integer = 0
2579     '        'Dim DelegateInstance As GetFollowersDelegate = New GetFollowersDelegate(AddressOf GetFollowersMethod)
2580     '        'Dim threadMax As Integer = 4            ' 最大スレッド数
2581     '        'Dim followersCount As Integer = 0
2582
2583     '        'Interlocked.Exchange(threadNum, 0)      ' スレッド数カウンタ初期化
2584     '        _threadErr = False
2585     '        'follower.Clear()
2586     '        tmpFollower.Clear()
2587     '        'follower.Add(_uid.ToLower())
2588     '        tmpFollower.Add(_uid.ToLower())
2589
2590     '        'resMsg = DirectCast(CreateSocket.GetWebResponse("https://twitter.com/users/show/" + _uid + ".xml", resStatus, MySocket.REQ_TYPE.ReqGetAPI), String)
2591     '        'If resMsg = "" Then
2592     '        '    If resStatus.StartsWith("Err: BadRequest") Then
2593     '        '        Return "Maybe, the requests reached API limit."
2594     '        '    ElseIf resStatus.StartsWith("Err: Unauthorized") Then
2595     '        '        Twitter.AccountState = ACCOUNT_STATE.Invalid
2596     '        '        Return "Check your Username/Password."
2597     '        '    Else
2598     '        '        Return resStatus
2599     '        '    End If
2600     '        'End If
2601
2602     '        'Dim xd As XmlDocument = New XmlDocument()
2603     '        'Try
2604     '        '    xd.LoadXml(resMsg)
2605     '        '    followersCount = Integer.Parse(xd.SelectSingleNode("/user/followers_count/text()").Value)
2606     '        'Catch ex As Exception
2607     '        '    'If CacheInvalidate OrElse ValidateCache(-1) < 0 Then
2608     '        '    If ValidateCache(-1) < 0 Then
2609     '        '        ' FollowersカウントがAPIで取得できず、なおかつキャッシュから読めなかった
2610     '        '        SyncLock LockObj
2611     '        '            follower.Clear()
2612     '        '            follower.Add(_uid.ToLower())
2613     '        '        End SyncLock
2614     '        '        Return "Can't get followers_count and invalid cache."
2615     '        '    Else
2616     '        '        'キャッシュを読み出せたのでキャッシュを使う
2617     '        '        SyncLock LockObj
2618     '        '            follower = tmpFollower
2619     '        '        End SyncLock
2620     '        '        Return ""
2621     '        '    End If
2622     '        'End Try
2623
2624     '        'Dim tmp As Integer
2625
2626     '        ''If CacheInvalidate Then
2627     '        'tmp = followersCount
2628     '        ''Else
2629     '        ''tmp = ValidateCache(followersCount)
2630     '        ''End If
2631
2632
2633     '        'If tmp <> 0 Then
2634     '        '    i = (tmp + 100) \ 100  ' Followersカウント取得しページ単位に切り上げる。1ページ余分に読む
2635     '        'Else
2636     '        '    '            ' キャッシュの件数に変化がなかった
2637     '        '    '#If DEBUG Then
2638     '        '    '            sw.Stop()
2639     '        '    '            Console.WriteLine(sw.ElapsedMilliseconds)
2640     '        '    '#End If
2641     '        '    '            SyncLock LockObj
2642     '        '    '                follower = tmpFollower
2643     '        '    '            End SyncLock
2644     '        '    'Return ""
2645     '        '    Return ""   'ユーザー情報のフォロワー数が0
2646     '        'End If
2647
2648
2649     '        ''semaphore = New System.Threading.Semaphore(threadMax, threadMax) 'スレッド最大数
2650
2651     '        'For cnt As Integer = 0 To i
2652     '        '    If _endingFlag Then Exit For
2653     '        '    'semaphore.WaitOne()                     'セマフォ取得 threadMax以上ならここでブロックされる
2654     '        '    GetTmSemaphore.WaitOne()
2655     '        '    'Interlocked.Increment(threadNum)        'スレッド数カウンタを+1
2656     '        '    'DelegateInstance.BeginInvoke(cnt + 1, New System.AsyncCallback(AddressOf GetFollowersCallback), DelegateInstance)
2657     '        '    Dim ret As String = GetFollowersMethod(cnt + 1)
2658     '        '    'Interlocked.Decrement(threadNum)        'スレッド数カウンタを-1
2659     '        '    GetTmSemaphore.Release()
2660     '        '    If _threadErr Then Exit For
2661     '        'Next
2662
2663     '        '''全てのスレッドの終了を待つ(スレッド数カウンタが0になるまで待機)
2664     '        ''Do
2665     '        ''    Thread.Sleep(50)
2666     '        ''Loop Until Interlocked.Add(threadNum, 0) = 0
2667
2668     '        ''semaphore.Close()
2669
2670     '        Dim ret As String = GetFollowersMethod()
2671     '        If _endingFlag Then Return ""
2672
2673     '        If _threadErr Then
2674     '            If ValidateCache() > 0 Then
2675     '                SyncLock LockObj
2676     '                    For Each name As String In tmpFollower
2677     '                        If Not follower.Contains(name) Then follower.Add(name)
2678     '                    Next
2679     '                End SyncLock
2680     '                If Not _endingFlag AndAlso follower.Count > 1 Then UpdateCache()
2681     '                ret = "Can't get followers. Use cache."
2682     '            Else
2683     '                ' エラーが発生しているならFollowersリストクリア
2684     '                SyncLock LockObj
2685     '                    follower.Clear()
2686     '                    follower.Add(_uid.ToLower())
2687     '                End SyncLock
2688     '                ret = "Can't get followers."
2689     '            End If
2690     '        Else
2691     '            SyncLock LockObj
2692     '                follower = tmpFollower
2693     '            End SyncLock
2694     '            ret = ""
2695     '        End If
2696
2697     '        If Not _endingFlag AndAlso follower.Count > 1 Then UpdateCache()
2698
2699     '#If DEBUG Then
2700     '        sw.Stop()
2701     '        'Console.WriteLine(sw.ElapsedMilliseconds)
2702     '#End If
2703
2704     '        TabInformations.GetInstance.RefreshOwl(follower)
2705     '        Return ret
2706     '    End Function
2707
2708     '#End Region
2709
2710     'Public Sub RefreshOwl()
2711     '    TabInformations.GetInstance.RefreshOwl(follower)
2712     'End Sub
2713
2714     'Public Sub RefreshOwlApi()
2715     '    TabInformations.GetInstance.RefreshOwl(followerId)
2716     'End Sub
2717
2718     Public ReadOnly Property Username() As String
2719         Get
2720             Return twCon.AuthenticatedUsername
2721         End Get
2722     End Property
2723
2724     Public ReadOnly Property Password() As String
2725         Get
2726             Return twCon.Password
2727         End Get
2728     End Property
2729
2730     Private Shared _accountState As ACCOUNT_STATE = ACCOUNT_STATE.Valid
2731     Public Shared Property AccountState() As ACCOUNT_STATE
2732         Get
2733             Return _accountState
2734         End Get
2735         Set(ByVal value As ACCOUNT_STATE)
2736             _accountState = value
2737         End Set
2738     End Property
2739
2740     'Public Property NextThreshold() As Integer
2741     '    Get
2742     '        Return _nextThreshold
2743     '    End Get
2744     '    Set(ByVal value As Integer)
2745     '        _nextThreshold = value
2746     '    End Set
2747     'End Property
2748
2749     'Public Property NextPages() As Integer
2750     '    Get
2751     '        Return _nextPages
2752     '    End Get
2753     '    Set(ByVal value As Integer)
2754     '        _nextPages = value
2755     '    End Set
2756     'End Property
2757
2758     Public ReadOnly Property InfoTwitter() As String
2759         Get
2760             Return _infoTwitter
2761         End Get
2762     End Property
2763
2764     'Public Property UseAPI() As Boolean
2765     '    Get
2766     '        Return _useAPI
2767     '    End Get
2768     '    Set(ByVal value As Boolean)
2769     '        _useAPI = value
2770     '    End Set
2771     'End Property
2772
2773     '    Public Sub GetWedata()
2774     '        Dim resStatus As String = ""
2775     '        Dim resMsg As String = ""
2776
2777     '        resMsg = DirectCast(CreateSocket.GetWebResponse(wedataUrl, resStatus, timeOut:=10 * 1000), String) 'タイムアウト時間を10秒に設定
2778     '        If resMsg.Length = 0 Then Exit Sub
2779
2780     '        Dim rs As New System.IO.StringReader(resMsg)
2781
2782     '        Dim mode As Integer = 0 '0:search name 1:search data 2:read data
2783     '        Dim name As String = ""
2784
2785     '        'ストリームの末端まで繰り返す
2786     '        Dim ln As String
2787     '        While rs.Peek() > -1
2788     '            ln = rs.ReadLine
2789
2790     '            Select Case mode
2791     '                Case 0
2792     '                    If ln.StartsWith("    ""name"": ") Then
2793     '                        name = ln.Substring(13, ln.Length - 2 - 13)
2794     '                        mode += 1
2795     '                    End If
2796     '                Case 1
2797     '                    If ln = "    ""data"": {" Then
2798     '                        mode += 1
2799     '                    End If
2800     '                Case 2
2801     '                    If ln = "    }," Then
2802     '                        mode = 0
2803     '                    Else
2804     '                        If ln.EndsWith(",") Then ln = ln.Substring(0, ln.Length - 1)
2805     '                        Select Case name
2806     '                            Case "SplitPostReply"
2807     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2808     '                                    _splitPost = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2809     '                                End If
2810     '                            Case "SplitPostRecent"
2811     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2812     '                                    _splitPostRecent = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2813     '                                End If
2814     '                            Case "StatusID"
2815     '                                If ln.StartsWith("      ""tagto"": """) Then
2816     '                                    _statusIdTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2817     '                                End If
2818     '                            Case "IsProtect"
2819     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2820     '                                    _isProtect = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2821     '                                End If
2822     '                            Case "IsReply"
2823     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2824     '                                    _isReplyEng = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2825     '                                End If
2826     '                                If ln.StartsWith("      ""tagfrom2"": """) Then
2827     '                                    _isReplyJpn = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
2828     '                                End If
2829     '                                If ln.StartsWith("      ""tagto"": """) Then
2830     '                                    _isReplyTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2831     '                                End If
2832     '                                'Case "GetStar"
2833     '                                '    If ln.StartsWith("      ""tagfrom"": """) Then
2834     '                                '        _parseStar = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2835     '                                '    End If
2836     '                                '    If ln.StartsWith("      ""tagfrom2"": """) Then
2837     '                                '        _parseStarEmpty = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
2838     '                                '    End If
2839     '                                '    If ln.StartsWith("      ""tagto"": """) Then
2840     '                                '        _parseStarTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2841     '                                '    End If
2842     '                            Case "Follower"
2843     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2844     '                                    _followerList = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2845     '                                End If
2846     '                                If ln.StartsWith("      ""tagfrom2"": """) Then
2847     '                                    _followerMbr1 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
2848     '                                End If
2849     '                                If ln.StartsWith("      ""tagfrom3"": """) Then
2850     '                                    _followerMbr2 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
2851     '                                End If
2852     '                                If ln.StartsWith("      ""tagto"": """) Then
2853     '                                    _followerMbr3 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2854     '                                End If
2855     '                            Case "SplitDM"
2856     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2857     '                                    _splitDM = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2858     '                                End If
2859     '                            Case "GetMsgDM"
2860     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2861     '                                    _parseDM1 = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2862     '                                End If
2863     '                                If ln.StartsWith("      ""tagfrom2"": """) Then
2864     '                                    _parseDM11 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
2865     '                                End If
2866     '                                If ln.StartsWith("      ""tagto"": """) Then
2867     '                                    _parseDM2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2868     '                                End If
2869     '                            Case "GetDate"
2870     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2871     '                                    _parseDate = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2872     '                                End If
2873     '                                If ln.StartsWith("      ""tagto"": """) Then
2874     '                                    _parseDateTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2875     '                                End If
2876     '                            Case "GetMsg"
2877     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2878     '                                    _parseMsg1 = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2879     '                                End If
2880     '                                If ln.StartsWith("      ""tagto"": """) Then
2881     '                                    _parseMsg2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2882     '                                End If
2883     '                            Case "GetImagePath"
2884     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2885     '                                    _parseImg = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2886     '                                End If
2887     '                                If ln.StartsWith("      ""tagto"": """) Then
2888     '                                    _parseImgTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2889     '                                End If
2890     '                            Case "GetNick"
2891     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2892     '                                    _parseNick = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2893     '                                End If
2894     '                                If ln.StartsWith("      ""tagto"": """) Then
2895     '                                    _parseNickTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2896     '                                End If
2897     '                            Case "GetName"
2898     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2899     '                                    _parseName = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2900     '                                End If
2901     '                                If ln.StartsWith("      ""tagto"": """) Then
2902     '                                    _parseNameTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2903     '                                End If
2904     '                                'Case "GetSiv"
2905     '                                '    If ln.StartsWith("      ""tagfrom"": """) Then
2906     '                                '        _getSiv = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2907     '                                '    End If
2908     '                                '    If ln.StartsWith("      ""tagto"": """) Then
2909     '                                '        _getSivTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2910     '                                '    End If
2911     '                            Case "AuthKey"
2912     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2913     '                                    _getAuthKey = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2914     '                                End If
2915     '                                If ln.StartsWith("      ""tagto"": """) Then
2916     '                                    _getAuthKeyTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2917     '                                End If
2918     '                            Case "InfoTwitter"
2919     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2920     '                                    _getInfoTwitter = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2921     '                                End If
2922     '                                If ln.StartsWith("      ""tagto"": """) Then
2923     '                                    _getInfoTwitterTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2924     '                                End If
2925     '                            Case "GetProtectMsg"
2926     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2927     '                                    _parseProtectMsg1 = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2928     '                                End If
2929     '                                If ln.StartsWith("      ""tagto"": """) Then
2930     '                                    _parseProtectMsg2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2931     '                                End If
2932     '                            Case "GetDMCount"
2933     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2934     '                                    _parseDMcountFrom = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2935     '                                End If
2936     '                                If ln.StartsWith("      ""tagto"": """) Then
2937     '                                    _parseDMcountTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2938     '                                End If
2939     '                            Case "GetSource"
2940     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2941     '                                    _parseSourceFrom = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2942     '                                End If
2943     '                                If ln.StartsWith("      ""tagfrom2"": """) Then
2944     '                                    _parseSource2 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
2945     '                                End If
2946     '                                If ln.StartsWith("      ""tagto"": """) Then
2947     '                                    _parseSource2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
2948     '                                End If
2949     '                            Case "RemoveClass"
2950     '                                If ln.StartsWith("      ""tagfrom"": """) Then
2951     '                                    _removeClass = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
2952     '                                End If
2953     '                        End Select
2954     '                    End If
2955     '            End Select
2956     '        End While
2957
2958     '        rs.Close()
2959
2960     '#If DEBUG Then
2961     '        GenerateAnalyzeKey()
2962     '#End If
2963     '    End Sub
2964
2965     Public WriteOnly Property GetIcon() As Boolean
2966         Set(ByVal value As Boolean)
2967             _getIcon = value
2968         End Set
2969     End Property
2970
2971     Public WriteOnly Property TinyUrlResolve() As Boolean
2972         Set(ByVal value As Boolean)
2973             _tinyUrlResolve = value
2974         End Set
2975     End Property
2976
2977     'Public WriteOnly Property SelectedProxyType() As ProxyType
2978     '    Set(ByVal value As ProxyType)
2979     '        _proxyType = value
2980     '    End Set
2981     'End Property
2982
2983     'Public WriteOnly Property ProxyAddress() As String
2984     '    Set(ByVal value As String)
2985     '        _proxyAddress = value
2986     '    End Set
2987     'End Property
2988
2989     'Public WriteOnly Property ProxyPort() As Integer
2990     '    Set(ByVal value As Integer)
2991     '        _proxyPort = value
2992     '    End Set
2993     'End Property
2994
2995     'Public WriteOnly Property ProxyUser() As String
2996     '    Set(ByVal value As String)
2997     '        _proxyUser = value
2998     '    End Set
2999     'End Property
3000
3001     'Public WriteOnly Property ProxyPassword() As String
3002     '    Set(ByVal value As String)
3003     '        _proxyPassword = value
3004     '    End Set
3005     'End Property
3006
3007     Public WriteOnly Property RestrictFavCheck() As Boolean
3008         Set(ByVal value As Boolean)
3009             _restrictFavCheck = value
3010         End Set
3011     End Property
3012
3013     Public WriteOnly Property IconSize() As Integer
3014         Set(ByVal value As Integer)
3015             _iconSz = value
3016         End Set
3017     End Property
3018
3019     Public Function MakeShortUrl(ByVal ConverterType As UrlConverter, ByVal SrcUrl As String) As String
3020         Dim src As String = urlEncodeMultibyteChar(SrcUrl)
3021         Dim param As New Dictionary(Of String, String)
3022         Dim content As String = ""
3023
3024         For Each svc As String In _ShortUrlService
3025             If SrcUrl.StartsWith(svc) Then
3026                 Return "Can't convert"
3027             End If
3028         Next
3029
3030         'nico.msは短縮しない
3031         If SrcUrl.StartsWith("http://nico.ms/") Then Return "Can't convert"
3032
3033         SrcUrl = HttpUtility.UrlEncode(SrcUrl)
3034
3035         Select Case ConverterType
3036             Case UrlConverter.TinyUrl       'tinyurl
3037                 If SrcUrl.StartsWith("http") Then
3038                     If "http://tinyurl.com/xxxxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
3039                         ' 明らかに長くなると推測できる場合は圧縮しない
3040                         content = src
3041                         Exit Select
3042                     End If
3043                     If Not (New HttpVarious).PostData("http://tinyurl.com/api-create.php?url=" + SrcUrl, Nothing, content) Then
3044                         Return "Can't convert"
3045                     End If
3046                 End If
3047                 If Not content.StartsWith("http://tinyurl.com/") Then
3048                     Return "Can't convert"
3049                 End If
3050             Case UrlConverter.Isgd
3051                 If SrcUrl.StartsWith("http") Then
3052                     If "http://is.gd/xxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
3053                         ' 明らかに長くなると推測できる場合は圧縮しない
3054                         content = src
3055                         Exit Select
3056                     End If
3057                     If Not (New HttpVarious).PostData("http://is.gd/api.php?longurl=" + SrcUrl, Nothing, content) Then
3058                         Return "Can't convert"
3059                     End If
3060                 End If
3061                 If Not content.StartsWith("http://is.gd/") Then
3062                     Return "Can't convert"
3063                 End If
3064             Case UrlConverter.Twurl
3065                 If SrcUrl.StartsWith("http") Then
3066                     If "http://twurl.nl/xxxxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
3067                         ' 明らかに長くなると推測できる場合は圧縮しない
3068                         content = src
3069                         Exit Select
3070                     End If
3071                     param.Add("link[url]", SrcUrl)
3072                     If Not (New HttpVarious).PostData("http://tweetburner.com/links", param, content) Then
3073                         Return "Can't convert"
3074                     End If
3075                 End If
3076                 If Not content.StartsWith("http://twurl.nl/") Then
3077                     Return "Can't convert"
3078                 End If
3079             Case UrlConverter.Unu
3080                 If SrcUrl.StartsWith("http") Then
3081                     If "http://u.nu/xxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
3082                         ' 明らかに長くなると推測できる場合は圧縮しない
3083                         content = src
3084                         Exit Select
3085                     End If
3086                     If Not (New HttpVarious).PostData("http://u.nu/unu-api-simple?url=" + SrcUrl, Nothing, content) Then
3087                         Return "Can't convert"
3088                     End If
3089                 End If
3090                 If Not content.StartsWith("http://u.nu") Then
3091                     Return "Can't convert"
3092                 End If
3093             Case UrlConverter.Bitly, UrlConverter.Jmp
3094                 Dim BitlyLogin As String = "tweenapi"
3095                 Dim BitlyApiKey As String = "R_c5ee0e30bdfff88723c4457cc331886b"
3096                 If _bitlyId <> "" Then
3097                     BitlyLogin = _bitlyId
3098                     BitlyApiKey = _bitlyKey
3099                 End If
3100                 Const BitlyApiVersion As String = "2.0.1"
3101                 If SrcUrl.StartsWith("http") Then
3102                     If "http://bit.ly/xxxx".Length > src.Length AndAlso Not src.Contains("?") AndAlso Not src.Contains("#") Then
3103                         ' 明らかに長くなると推測できる場合は圧縮しない
3104                         content = src
3105                         Exit Select
3106                     End If
3107                     Dim req As String = ""
3108                     If ConverterType = UrlConverter.Bitly Then
3109                         req = "http://api.bit.ly/shorten?version="
3110                     Else
3111                         req = "http://api.j.mp/shorten?version="
3112                     End If
3113                     req += BitlyApiVersion + _
3114                         "&login=" + BitlyLogin + _
3115                         "&apiKey=" + BitlyApiKey + _
3116                         "&longUrl=" + SrcUrl
3117                     If BitlyLogin <> "tweenapi" Then req += "&history=1"
3118                     If Not (New HttpVarious).PostData(req, Nothing, content) Then
3119                         Return "Can't convert"
3120                     Else
3121                         'Dim rx As Regex = New Regex("""shortUrl"": ""(?<ShortUrl>.*?)""")
3122                         If Regex.Match(content, """shortUrl"": ""(?<ShortUrl>.*?)""").Success Then
3123                             content = Regex.Match(content, """shortUrl"": ""(?<ShortUrl>.*?)""").Groups("ShortUrl").Value
3124                         End If
3125                     End If
3126                 End If
3127                 If Not content.StartsWith("http://bit.ly") AndAlso Not content.StartsWith("http://j.mp") Then
3128                     Return "Can't convert"
3129                 End If
3130         End Select
3131         '変換結果から改行を除去
3132         Dim ch As Char() = {ControlChars.Cr, ControlChars.Lf}
3133         content = content.TrimEnd(ch)
3134         If src.Length < content.Length Then content = src ' 圧縮の結果逆に長くなった場合は圧縮前のURLを返す
3135         Return content
3136     End Function
3137
3138     'Public Function MakeShortNicoms(ByVal SrcUrl As String) As String
3139     '    Dim content As String = ""
3140
3141     '    If Not (New HttpVarious).GetData("http://nico.ms/q/" + SrcUrl, Nothing, content) Then
3142     '        Return "Can't convert"
3143     '    End If
3144
3145     '    If content.StartsWith("http") Then
3146     '        Return content
3147     '    Else
3148     '        Return "Can't convert"
3149     '    End If
3150
3151     'End Function
3152
3153 #Region "バージョンアップ"
3154     Public Function GetVersionInfo() As String
3155         Dim content As String = ""
3156         If Not (New HttpVarious).GetData("http://tween.sourceforge.jp/version2.txt?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), Nothing, content) Then
3157             Throw New Exception("GetVersionInfo Failed")
3158         End If
3159         Return content
3160     End Function
3161
3162     Public Function GetTweenBinary(ByVal strVer As String) As String
3163         Try
3164             If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/Tween" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
3165                                                 Path.Combine(Application.StartupPath(), "TweenNew.exe")) Then
3166                 Return "Err:Download failed"
3167             End If
3168             If Directory.Exists(Path.Combine(Application.StartupPath(), "en")) = False Then
3169                 Directory.CreateDirectory(Path.Combine(Application.StartupPath(), "en"))
3170             End If
3171             If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenRes" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
3172                                                 Path.Combine(Application.StartupPath(), "en\Tween.resourcesNew.dll")) Then
3173                 Return "Err:Download failed"
3174             End If
3175             If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenUp.gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
3176                                                 Path.Combine(Application.StartupPath(), "TweenUp.exe")) Then
3177                 Return "Err:Download failed"
3178             End If
3179             If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenDll" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
3180                                                 Path.Combine(Application.StartupPath(), "TweenNew.XmlSerializers.dll")) Then
3181                 Return "Err:Download failed"
3182             End If
3183             Return ""
3184         Catch ex As Exception
3185             Return "Err:Download failed"
3186         End Try
3187     End Function
3188 #End Region
3189
3190     Public WriteOnly Property ListIcon() As ImageList
3191         Set(ByVal value As ImageList)
3192             _lIcon = value
3193         End Set
3194     End Property
3195
3196     Public WriteOnly Property DetailIcon() As Dictionary(Of String, Image)
3197         Set(ByVal value As Dictionary(Of String, Image))
3198             _dIcon = value
3199         End Set
3200     End Property
3201
3202     'Public Property DefaultTimeOut() As Integer
3203     '    Get
3204     '        Return _defaultTimeOut
3205     '    End Get
3206     '    Set(ByVal value As Integer)
3207     '        _defaultTimeOut = value
3208     '    End Set
3209     'End Property
3210
3211     Public WriteOnly Property CountApi() As Integer
3212         'API時の取得件数
3213         Set(ByVal value As Integer)
3214             _countApi = value
3215         End Set
3216     End Property
3217
3218     Public WriteOnly Property CountApiReply() As Integer
3219         'API時のMentions取得件数
3220         Set(ByVal value As Integer)
3221             _countApiReply = value
3222         End Set
3223     End Property
3224
3225     '    Public WriteOnly Property UsePostMethod() As Boolean
3226     '        Set(ByVal value As Boolean)
3227     '            _usePostMethod = False
3228     '#If 0 Then
3229     '            'POSTメソッドが弾かれるためGETに固定(2009/4/9)
3230     '            If value Then
3231     '                _ApiMethod = MySocket.REQ_TYPE.ReqPOSTAPI
3232     '            Else
3233     '                _ApiMethod = MySocket.REQ_TYPE.ReqGetAPI
3234     '            End If
3235     '#Else
3236     '            _ApiMethod = MySocket.REQ_TYPE.ReqGetAPI
3237     '#End If
3238     '        End Set
3239     '    End Property
3240
3241     Public Property ReadOwnPost() As Boolean
3242         Get
3243             Return _readOwnPost
3244         End Get
3245         Set(ByVal value As Boolean)
3246             _readOwnPost = value
3247         End Set
3248     End Property
3249
3250     Public ReadOnly Property FollowersCount() As Integer
3251         Get
3252             Return _followersCount
3253         End Get
3254     End Property
3255
3256     Public ReadOnly Property FriendsCount() As Integer
3257         Get
3258             Return _friendsCount
3259         End Get
3260     End Property
3261
3262     Public ReadOnly Property StatusesCount() As Integer
3263         Get
3264             Return _statusesCount
3265         End Get
3266     End Property
3267
3268     Public ReadOnly Property Location() As String
3269         Get
3270             Return _location
3271         End Get
3272     End Property
3273
3274     Public ReadOnly Property Bio() As String
3275         Get
3276             Return _bio
3277         End Get
3278     End Property
3279
3280     Public WriteOnly Property UseSsl() As Boolean
3281         Set(ByVal value As Boolean)
3282             HttpTwitter.UseSsl = value
3283             If value Then
3284                 _protocol = "https://"
3285             Else
3286                 _protocol = "http://"
3287             End If
3288         End Set
3289     End Property
3290
3291     Public WriteOnly Property BitlyId() As String
3292         Set(ByVal value As String)
3293             _bitlyId = value
3294         End Set
3295     End Property
3296
3297     Public WriteOnly Property BitlyKey() As String
3298         Set(ByVal value As String)
3299             _bitlyKey = value
3300         End Set
3301     End Property
3302
3303     Public Function GetTimelineApi(ByVal read As Boolean, _
3304                             ByVal gType As WORKERTYPE, _
3305                             ByVal more As Boolean) As String
3306
3307         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
3308
3309         If _endingFlag Then Return ""
3310
3311         Dim countQuery As Integer
3312         Dim res As HttpStatusCode
3313         Dim content As String = ""
3314         Try
3315             If gType = WORKERTYPE.Timeline Then
3316                 If more Then
3317                     res = twCon.HomeTimeline(_countApi, minHomeTimeline, 0, content)
3318                 Else
3319                     res = twCon.HomeTimeline(_countApi, 0, 0, content)
3320                 End If
3321                 countQuery = _countApi
3322             Else
3323                 If more Then
3324                     res = twCon.Mentions(_countApiReply, minMentions, 0, content)
3325                 Else
3326                     res = twCon.Mentions(_countApiReply, 0, 0, content)
3327                 End If
3328                 countQuery = _countApiReply
3329             End If
3330         Catch ex As Exception
3331             Return "Err:" + ex.Message
3332         End Try
3333         Select Case res
3334             Case HttpStatusCode.OK
3335             Case HttpStatusCode.Unauthorized
3336                 Twitter.AccountState = ACCOUNT_STATE.Invalid
3337                 Return "Check your Username/Password."
3338             Case HttpStatusCode.BadRequest
3339                 Return "Err:API Limits?"
3340             Case Else
3341                 Return "Err:" + res.ToString()
3342         End Select
3343
3344         If gType = WORKERTYPE.Timeline Then
3345             Return CreatePostsFromXml(content, gType, Nothing, read, countQuery, Me.minHomeTimeline)
3346         Else
3347             Return CreatePostsFromXml(content, gType, Nothing, read, countQuery, Me.minMentions)
3348         End If
3349     End Function
3350
3351     Public Function GetListStatus(ByVal read As Boolean, _
3352                             ByVal tab As TabClass, _
3353                             ByVal more As Boolean) As String
3354
3355         If _endingFlag Then Return ""
3356
3357         Dim res As HttpStatusCode
3358         Dim content As String = ""
3359         Dim page As Integer = 0
3360         Dim countQuery As Integer = 0
3361         Try
3362             If more Then
3363                 res = twCon.GetListsStatuses(tab.ListInfo.UserId.ToString, tab.ListInfo.Id.ToString, _countApi, tab.OldestId, 0, content)
3364             Else
3365                 res = twCon.GetListsStatuses(tab.ListInfo.UserId.ToString, tab.ListInfo.Id.ToString, _countApi, 0, 0, content)
3366             End If
3367             countQuery = _countApi
3368         Catch ex As Exception
3369             Return "Err:" + ex.Message
3370         End Try
3371         Select Case res
3372             Case HttpStatusCode.OK
3373             Case HttpStatusCode.Unauthorized
3374                 Twitter.AccountState = ACCOUNT_STATE.Invalid
3375                 Return "Check your Username/Password."
3376             Case HttpStatusCode.BadRequest
3377                 Return "Err:API Limits?"
3378             Case Else
3379                 Return "Err:" + res.ToString()
3380         End Select
3381
3382         Return CreatePostsFromXml(content, WORKERTYPE.List, tab, read, countQuery, tab.OldestId)
3383     End Function
3384
3385     Private Function CreatePostsFromXml(ByVal content As String, ByVal gType As WORKERTYPE, ByVal tab As TabClass, ByVal read As Boolean, ByVal count As Integer, ByRef minimumId As Long) As String
3386         Dim arIdx As Integer = -1
3387         Dim dlgt(count) As GetIconImageDelegate    'countQueryに合わせる
3388         Dim ar(count) As IAsyncResult              'countQueryに合わせる
3389         Dim xdoc As New XmlDocument
3390         Try
3391             xdoc.LoadXml(content)
3392         Catch ex As Exception
3393             TraceOut(content)
3394             'MessageBox.Show("不正なXMLです。(TL-LoadXml)")
3395             Return "Invalid XML!"
3396         End Try
3397
3398         For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("./status")
3399             Dim xentry As XmlElement = CType(xentryNode, XmlElement)
3400             Dim post As New PostClass
3401             Try
3402                 post.Id = Long.Parse(xentry.Item("id").InnerText)
3403                 If minimumId > post.Id Then minimumId = post.Id
3404                 '二重取得回避
3405                 SyncLock LockObj
3406                     If tab Is Nothing Then
3407                         If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
3408                     Else
3409                         If TabInformations.GetInstance.ContainsKey(post.Id, tab.TabName) Then Continue For
3410                     End If
3411                 End SyncLock
3412                 'Retweet判定
3413                 Dim xRnode As XmlNode = xentry.SelectSingleNode("./retweeted_status")
3414                 If xRnode IsNot Nothing Then
3415                     Dim xRentry As XmlElement = CType(xRnode, XmlElement)
3416                     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)
3417                     'Id
3418                     post.RetweetedId = Long.Parse(xRentry.Item("id").InnerText)
3419                     '本文
3420                     post.Data = xRentry.Item("text").InnerText
3421                     'Source取得(htmlの場合は、中身を取り出し)
3422                     post.Source = xRentry.Item("source").InnerText
3423                     'Reply先
3424                     Long.TryParse(xRentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
3425                     post.InReplyToUser = xRentry.Item("in_reply_to_screen_name").InnerText
3426                     'post.IsFav = TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.RetweetedId)
3427                     post.IsFav = Boolean.Parse(xentry.Item("favorited").InnerText)
3428
3429                     '以下、ユーザー情報
3430                     Dim xRUentry As XmlElement = CType(xRentry.SelectSingleNode("./user"), XmlElement)
3431                     post.Uid = Long.Parse(xRUentry.Item("id").InnerText)
3432                     post.Name = xRUentry.Item("screen_name").InnerText
3433                     post.Nickname = xRUentry.Item("name").InnerText
3434                     post.ImageUrl = xRUentry.Item("profile_image_url").InnerText
3435                     post.IsProtect = Boolean.Parse(xRUentry.Item("protected").InnerText)
3436                     post.IsMe = post.Name.ToLower.Equals(_uid)
3437
3438                     'Retweetした人
3439                     Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
3440                     post.RetweetedBy = xUentry.Item("screen_name").InnerText
3441                 Else
3442                     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)
3443                     '本文
3444                     post.Data = xentry.Item("text").InnerText
3445                     'Source取得(htmlの場合は、中身を取り出し)
3446                     post.Source = xentry.Item("source").InnerText
3447                     Long.TryParse(xentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
3448                     post.InReplyToUser = xentry.Item("in_reply_to_screen_name").InnerText
3449                     'in_reply_to_user_idを使うか?
3450                     post.IsFav = Boolean.Parse(xentry.Item("favorited").InnerText)
3451
3452                     '以下、ユーザー情報
3453                     Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
3454                     post.Uid = Long.Parse(xUentry.Item("id").InnerText)
3455                     post.Name = xUentry.Item("screen_name").InnerText
3456                     post.Nickname = xUentry.Item("name").InnerText
3457                     post.ImageUrl = xUentry.Item("profile_image_url").InnerText
3458                     post.IsProtect = Boolean.Parse(xUentry.Item("protected").InnerText)
3459                     post.IsMe = post.Name.ToLower.Equals(_uid)
3460                 End If
3461                 'HTMLに整形
3462                 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
3463                 post.Data = HttpUtility.HtmlDecode(post.Data)
3464                 post.Data = post.Data.Replace("<3", "♡")
3465                 'Source整形
3466                 If post.Source.StartsWith("<") Then
3467                     'Dim rgS As New Regex(">(?<source>.+)<")
3468                     Dim mS As Match = Regex.Match(post.Source, ">(?<source>.+)<")
3469                     If mS.Success Then
3470                         post.Source = mS.Result("${source}")
3471                     End If
3472                 End If
3473
3474                 post.IsRead = read
3475                 If gType = WORKERTYPE.Timeline OrElse tab IsNot Nothing Then
3476                     post.IsReply = post.ReplyToList.Contains(_uid)
3477                 Else
3478                     post.IsReply = True
3479                 End If
3480
3481                 If post.IsMe Then
3482                     post.IsOwl = False
3483                 Else
3484                     If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.Uid)
3485                 End If
3486                 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
3487
3488                 post.IsDm = False
3489                 If tab IsNot Nothing Then post.RelTabName = tab.TabName
3490             Catch ex As Exception
3491                 TraceOut(content)
3492                 'MessageBox.Show("不正なXMLです。(TL-Parse)")
3493                 Continue For
3494             End Try
3495
3496             '非同期アイコン取得&StatusDictionaryに追加
3497             arIdx += 1
3498             dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
3499             ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
3500         Next
3501
3502         'アイコン取得完了待ち
3503         For i As Integer = 0 To arIdx
3504             Try
3505                 dlgt(i).EndInvoke(ar(i))
3506             Catch ex As Exception
3507                 '最後までendinvoke回す(ゾンビ化回避)
3508                 ex.Data("IsTerminatePermission") = False
3509                 Throw
3510             End Try
3511         Next
3512
3513         'If _ApiMethod = MySocket.REQ_TYPE.ReqGetAPI Then _remainCountApi = sck.RemainCountApi
3514
3515         Return ""
3516     End Function
3517     Public Function GetSearch(ByVal read As Boolean, _
3518                             ByVal tab As TabClass, _
3519                             ByVal more As Boolean) As String
3520
3521         If _endingFlag Then Return ""
3522
3523         Dim res As HttpStatusCode
3524         Dim content As String = ""
3525         Dim page As Integer = 0
3526         If more Then page = tab.SearchPage
3527         Try
3528             res = twCon.Search(tab.SearchWords, tab.SearchLang, 40, page, content)
3529         Catch ex As Exception
3530             Return "Err:" + ex.Message
3531         End Try
3532         Select Case res
3533             Case HttpStatusCode.BadRequest
3534                 Return "Invalid query"
3535             Case HttpStatusCode.NotFound
3536                 Return "Invalid query"
3537             Case HttpStatusCode.PaymentRequired 'API Documentには420と書いてあるが、該当コードがないので402にしてある
3538                 Return "Search API Limit?"
3539             Case HttpStatusCode.OK
3540             Case Else
3541                 Return "Err:" + res.ToString
3542         End Select
3543
3544         If Not TabInformations.GetInstance.ContainsTab(tab) Then Return ""
3545
3546         Dim arIdx As Integer = -1
3547         Dim dlgt(40) As GetIconImageDelegate    'countQueryに合わせる
3548         Dim ar(40) As IAsyncResult              'countQueryに合わせる
3549         Dim xdoc As New XmlDocument
3550         Try
3551             xdoc.LoadXml(content)
3552         Catch ex As Exception
3553             TraceOut(content)
3554             Return "Invalid ATOM!"
3555         End Try
3556         Dim nsmgr As New XmlNamespaceManager(xdoc.NameTable)
3557         nsmgr.AddNamespace("search", "http://www.w3.org/2005/Atom")
3558         For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/search:feed/search:entry", nsmgr)
3559             Dim xentry As XmlElement = CType(xentryNode, XmlElement)
3560             Dim post As New PostClass
3561             Try
3562                 post.Id = Long.Parse(xentry.Item("id").InnerText.Split(":"c)(2))
3563                 If TabInformations.GetInstance.ContainsKey(post.Id, tab.TabName) Then Continue For
3564                 post.PDate = DateTime.Parse(xentry.Item("published").InnerText)
3565                 '本文
3566                 post.Data = xentry.Item("title").InnerText
3567                 'Source取得(htmlの場合は、中身を取り出し)
3568                 post.Source = xentry.Item("twitter:source").InnerText
3569                 post.InReplyToId = 0
3570                 post.InReplyToUser = ""
3571                 post.IsFav = False
3572
3573                 '以下、ユーザー情報
3574                 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./search:author", nsmgr), XmlElement)
3575                 post.Uid = 0
3576                 post.Name = xUentry.Item("name").InnerText.Split(" "c)(0).Trim
3577                 post.Nickname = xUentry.Item("name").InnerText.Substring(post.Name.Length).Trim
3578                 If post.Nickname.Length > 2 Then
3579                     post.Nickname = post.Nickname.Substring(1, post.Nickname.Length - 2)
3580                 Else
3581                     post.Nickname = post.Name
3582                 End If
3583                 post.ImageUrl = CType(xentry.SelectSingleNode("./search:link[@type='image/png']", nsmgr), XmlElement).GetAttribute("href")
3584                 post.IsProtect = False
3585                 post.IsMe = post.Name.ToLower.Equals(_uid)
3586
3587                 'HTMLに整形
3588                 post.OriginalData = CreateHtmlAnchor(HttpUtility.HtmlEncode(post.Data), post.ReplyToList)
3589                 post.Data = HttpUtility.HtmlDecode(post.Data)
3590                 'Source整形
3591                 If post.Source.StartsWith("<") Then
3592                     'Dim rgS As New Regex(">(?<source>.+)<")
3593                     Dim mS As Match = Regex.Match(post.Source, ">(?<source>.+)<")
3594                     If mS.Success Then
3595                         post.Source = mS.Result("${source}")
3596                     End If
3597                 End If
3598
3599                 post.IsRead = read
3600                 post.IsReply = post.ReplyToList.Contains(_uid)
3601
3602                 post.IsOwl = False
3603                 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
3604                 post.IsDm = False
3605                 post.RelTabName = tab.TabName
3606             Catch ex As Exception
3607                 TraceOut(content)
3608                 Continue For
3609             End Try
3610
3611             '非同期アイコン取得&StatusDictionaryに追加
3612             arIdx += 1
3613             dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
3614             ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
3615         Next
3616
3617         '' TODO
3618         '' 遡るための情報max_idやnext_pageの情報を保持する
3619
3620         'アイコン取得完了待ち
3621         For i As Integer = 0 To arIdx
3622             Try
3623                 dlgt(i).EndInvoke(ar(i))
3624             Catch ex As Exception
3625                 '最後までendinvoke回す(ゾンビ化回避)
3626                 ex.Data("IsTerminatePermission") = False
3627                 Throw
3628             End Try
3629         Next
3630
3631         Return ""
3632     End Function
3633
3634     Public Function GetDirectMessageApi(ByVal read As Boolean, _
3635                             ByVal gType As WORKERTYPE, _
3636                             ByVal more As Boolean) As String
3637         If _endingFlag Then Return ""
3638
3639         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
3640
3641         Dim res As HttpStatusCode
3642         Dim content As String = ""
3643
3644         Try
3645             If gType = WORKERTYPE.DirectMessegeRcv Then
3646                 If more Then
3647                     res = twCon.DirectMessages(20, minDirectmessage, 0, content)
3648                 Else
3649                     res = twCon.DirectMessages(20, 0, 0, content)
3650                 End If
3651             Else
3652                 If more Then
3653                     res = twCon.DirectMessagesSent(20, minDirectmessageSent, 0, content)
3654                 Else
3655                     res = twCon.DirectMessagesSent(20, 0, 0, content)
3656                 End If
3657             End If
3658         Catch ex As Exception
3659             Return "Err:" + ex.Message
3660         End Try
3661
3662         Select Case res
3663             Case HttpStatusCode.OK
3664             Case HttpStatusCode.Unauthorized
3665                 Twitter.AccountState = ACCOUNT_STATE.Invalid
3666                 Return "Check your Username/Password."
3667             Case HttpStatusCode.BadRequest
3668                 Return "Err:API Limits?"
3669             Case Else
3670                 Return "Err:" + res.ToString()
3671         End Select
3672
3673         Dim arIdx As Integer = -1
3674         Dim dlgt(20) As GetIconImageDelegate    'countQueryに合わせる
3675         Dim ar(20) As IAsyncResult              'countQueryに合わせる
3676         Dim xdoc As New XmlDocument
3677         Try
3678             xdoc.LoadXml(content)
3679         Catch ex As Exception
3680             TraceOut(content)
3681             'MessageBox.Show("不正なXMLです。(DM-LoadXml)")
3682             Return "Invalid XML!"
3683         End Try
3684
3685         For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("./direct_message")
3686             Dim xentry As XmlElement = CType(xentryNode, XmlElement)
3687             Dim post As New PostClass
3688             Try
3689                 post.Id = Long.Parse(xentry.Item("id").InnerText)
3690                 If gType = WORKERTYPE.DirectMessegeRcv Then
3691                     If minDirectmessage > post.Id Then minDirectmessage = post.Id
3692                 Else
3693                     If minDirectmessageSent > post.Id Then minDirectmessageSent = post.Id
3694                 End If
3695                 '二重取得回避
3696                 SyncLock LockObj
3697                     If TabInformations.GetInstance.GetTabByType(TabUsageType.DirectMessage).Contains(post.Id) Then Continue For
3698                 End SyncLock
3699                 'sender_id
3700                 'recipient_id
3701                 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)
3702                 '本文
3703                 post.Data = xentry.Item("text").InnerText
3704                 'HTMLに整形
3705                 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
3706                 post.Data = HttpUtility.HtmlDecode(post.Data)
3707                 post.Data = post.Data.Replace("<3", "♡")
3708                 post.IsFav = False
3709                 '受信DMかの判定で使用
3710                 If gType = WORKERTYPE.DirectMessegeRcv Then
3711                     post.IsOwl = False
3712                 Else
3713                     post.IsOwl = True
3714                 End If
3715
3716                 '以下、ユーザー情報
3717                 Dim xUentry As XmlElement
3718                 If gType = WORKERTYPE.DirectMessegeRcv Then
3719                     xUentry = CType(xentry.SelectSingleNode("./sender"), XmlElement)
3720                     post.IsMe = False
3721                 Else
3722                     xUentry = CType(xentry.SelectSingleNode("./recipient"), XmlElement)
3723                     post.IsMe = True
3724                 End If
3725                 post.Uid = Long.Parse(xUentry.Item("id").InnerText)
3726                 post.Name = xUentry.Item("screen_name").InnerText
3727                 post.Nickname = xUentry.Item("name").InnerText
3728                 post.ImageUrl = xUentry.Item("profile_image_url").InnerText
3729                 post.IsProtect = Boolean.Parse(xUentry.Item("protected").InnerText)
3730             Catch ex As Exception
3731                 TraceOut(content)
3732                 'MessageBox.Show("不正なXMLです。(DM-Parse)")
3733                 Continue For
3734             End Try
3735
3736             post.IsRead = read
3737             post.IsReply = False
3738             post.IsDm = True
3739
3740             '非同期アイコン取得&StatusDictionaryに追加
3741             arIdx += 1
3742             dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
3743             ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
3744         Next
3745
3746         'アイコン取得完了待ち
3747         For i As Integer = 0 To arIdx
3748             Try
3749                 dlgt(i).EndInvoke(ar(i))
3750             Catch ex As Exception
3751                 '最後までendinvoke回す(ゾンビ化回避)
3752                 ex.Data("IsTerminatePermission") = False
3753                 Throw
3754             End Try
3755         Next
3756
3757         '_remainCountApi = sck.RemainCountApi
3758         'If _ApiMethod = MySocket.REQ_TYPE.ReqGetAPI Then _remainCountApi = sck.RemainCountApi
3759
3760         Return ""
3761     End Function
3762
3763     Public Function GetFavoritesApi(ByVal read As Boolean, _
3764                         ByVal gType As WORKERTYPE) As String
3765
3766         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
3767
3768         If _endingFlag Then Return ""
3769
3770         Dim res As HttpStatusCode
3771         Dim content As String = ""
3772         Try
3773             res = twCon.Favorites(_countApi, content)
3774         Catch ex As Exception
3775             Return "Err:" + ex.Message
3776         End Try
3777
3778         Select Case res
3779             Case HttpStatusCode.OK
3780             Case HttpStatusCode.Unauthorized
3781                 Twitter.AccountState = ACCOUNT_STATE.Invalid
3782                 Return "Check your Username/Password."
3783             Case HttpStatusCode.BadRequest
3784                 Return "Err:API Limits?"
3785             Case Else
3786                 Return "Err:" + res.ToString()
3787         End Select
3788
3789         Dim arIdx As Integer = -1
3790         Dim dlgt(_countApi) As GetIconImageDelegate    'countQueryに合わせる
3791         Dim ar(_countApi) As IAsyncResult              'countQueryに合わせる
3792         Dim xdoc As New XmlDocument
3793         Try
3794             xdoc.LoadXml(content)
3795         Catch ex As Exception
3796             TraceOut(content)
3797             'MessageBox.Show("不正なXMLです。(TL-LoadXml)")
3798             Return "Invalid XML!"
3799         End Try
3800
3801         For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("./status")
3802             Dim xentry As XmlElement = CType(xentryNode, XmlElement)
3803             Dim post As New PostClass
3804             Try
3805                 post.Id = Long.Parse(xentry.Item("id").InnerText)
3806                 If minFavorites > post.Id Then minFavorites = post.Id
3807                 '二重取得回避
3808                 SyncLock LockObj
3809                     If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
3810                 End SyncLock
3811                 'Retweet判定
3812                 Dim xRnode As XmlNode = xentry.SelectSingleNode("./retweeted_status")
3813                 If xRnode IsNot Nothing Then
3814                     Dim xRentry As XmlElement = CType(xRnode, XmlElement)
3815                     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)
3816                     'Id
3817                     post.RetweetedId = Long.Parse(xRentry.Item("id").InnerText)
3818                     '本文
3819                     post.Data = xRentry.Item("text").InnerText
3820                     'Source取得(htmlの場合は、中身を取り出し)
3821                     post.Source = xRentry.Item("source").InnerText
3822                     'Reply先
3823                     Long.TryParse(xRentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
3824                     post.InReplyToUser = xRentry.Item("in_reply_to_screen_name").InnerText
3825                     'in_reply_to_user_idを使うか?
3826                     post.IsFav = Boolean.Parse(xRentry.Item("favorited").InnerText)
3827
3828                     '以下、ユーザー情報
3829                     Dim xRUentry As XmlElement = CType(xRentry.SelectSingleNode("./user"), XmlElement)
3830                     post.Uid = Long.Parse(xRUentry.Item("id").InnerText)
3831                     post.Name = xRUentry.Item("screen_name").InnerText
3832                     post.Nickname = xRUentry.Item("name").InnerText
3833                     post.ImageUrl = xRUentry.Item("profile_image_url").InnerText
3834                     post.IsProtect = Boolean.Parse(xRUentry.Item("protected").InnerText)
3835                     post.IsMe = post.Name.ToLower.Equals(_uid)
3836
3837                     'Retweetした人
3838                     Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
3839                     post.RetweetedBy = xUentry.Item("screen_name").InnerText
3840                 Else
3841                     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)
3842                     '本文
3843                     post.Data = xentry.Item("text").InnerText
3844                     'Source取得(htmlの場合は、中身を取り出し)
3845                     post.Source = xentry.Item("source").InnerText
3846                     Long.TryParse(xentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
3847                     post.InReplyToUser = xentry.Item("in_reply_to_screen_name").InnerText
3848                     'in_reply_to_user_idを使うか?
3849                     post.IsFav = Boolean.Parse(xentry.Item("favorited").InnerText)
3850
3851                     '以下、ユーザー情報
3852                     Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
3853                     post.Uid = Long.Parse(xUentry.Item("id").InnerText)
3854                     post.Name = xUentry.Item("screen_name").InnerText
3855                     post.Nickname = xUentry.Item("name").InnerText
3856                     post.ImageUrl = xUentry.Item("profile_image_url").InnerText
3857                     post.IsProtect = Boolean.Parse(xUentry.Item("protected").InnerText)
3858                     post.IsMe = post.Name.ToLower.Equals(_uid)
3859                 End If
3860                 'HTMLに整形
3861                 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
3862                 post.Data = HttpUtility.HtmlDecode(post.Data)
3863                 post.Data = post.Data.Replace("<3", "♡")
3864                 'Source整形
3865                 If post.Source.StartsWith("<") Then
3866                     'Dim rgS As New Regex(">(?<source>.+)<")
3867                     Dim mS As Match = Regex.Match(post.Source, ">(?<source>.+)<")
3868                     If mS.Success Then
3869                         post.Source = mS.Result("${source}")
3870                     End If
3871                 End If
3872
3873                 post.IsRead = read
3874                 post.IsReply = post.ReplyToList.Contains(_uid)
3875
3876                 If post.IsMe Then
3877                     post.IsOwl = False
3878                 Else
3879                     If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.Uid)
3880                 End If
3881
3882                 post.IsDm = False
3883             Catch ex As Exception
3884                 TraceOut(content)
3885                 'MessageBox.Show("不正なXMLです。(TL-Parse)")
3886                 Continue For
3887             End Try
3888
3889             '非同期アイコン取得&StatusDictionaryに追加
3890             arIdx += 1
3891             dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
3892             ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
3893         Next
3894
3895         'アイコン取得完了待ち
3896         For i As Integer = 0 To arIdx
3897             Try
3898                 dlgt(i).EndInvoke(ar(i))
3899             Catch ex As Exception
3900                 '最後までendinvoke回す(ゾンビ化回避)
3901                 ex.Data("IsTerminatePermission") = False
3902                 Throw
3903             End Try
3904         Next
3905
3906         '_remainCountApi = sck.RemainCountApi
3907         'If _ApiMethod = MySocket.REQ_TYPE.ReqGetAPI Then _remainCountApi = sck.RemainCountApi
3908
3909         Return ""
3910     End Function
3911
3912     Public Function GetFollowersApi() As String
3913         If _endingFlag Then Return ""
3914         Dim cursor As Long = -1
3915         Dim tmpFollower As New List(Of Long)(followerId)
3916
3917         followerId.Clear()
3918         Do
3919             Dim ret As String = FollowerApi(cursor)
3920             If ret <> "" Then
3921                 followerId.Clear()
3922                 followerId.AddRange(tmpFollower)
3923                 Return ret
3924             End If
3925         Loop While cursor > 0
3926
3927         TabInformations.GetInstance.RefreshOwl(followerId)
3928
3929         Return ""
3930     End Function
3931
3932     Private Function FollowerApi(ByRef cursor As Long) As String
3933         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
3934
3935         Dim res As HttpStatusCode
3936         Dim content As String = ""
3937         Try
3938             res = twCon.FollowerIds(cursor, content)
3939         Catch ex As Exception
3940             Return "Err:" + ex.Message
3941         End Try
3942
3943         Select Case res
3944             Case HttpStatusCode.OK
3945             Case HttpStatusCode.Unauthorized
3946                 Twitter.AccountState = ACCOUNT_STATE.Invalid
3947                 Return "Check your Username/Password."
3948             Case HttpStatusCode.BadRequest
3949                 Return "Err:API Limits?"
3950             Case Else
3951                 Return "Err:" + res.ToString()
3952         End Select
3953
3954         Dim xdoc As New XmlDocument
3955         Try
3956             xdoc.LoadXml(content)
3957         Catch ex As Exception
3958             TraceOut(content)
3959             Return "Invalid XML!"
3960         End Try
3961
3962         Try
3963             For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/id_list/ids/id")
3964                 followerId.Add(Long.Parse(xentryNode.InnerText))
3965             Next
3966             cursor = Long.Parse(xdoc.DocumentElement.SelectSingleNode("/id_list/next_cursor").InnerText)
3967         Catch ex As Exception
3968             TraceOut(content)
3969             Return "Invalid XML!"
3970         End Try
3971
3972         Return ""
3973
3974     End Function
3975
3976     Public Function GetListsApi() As String
3977         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
3978
3979         Dim res As HttpStatusCode
3980         Dim content As String = ""
3981         Dim cursor As Long = -1
3982
3983         Dim lists As New List(Of ListElement)
3984         Do
3985             Try
3986                 res = twCon.GetLists(Me.Username, cursor, content)
3987             Catch ex As Exception
3988                 Return "Err:" + ex.Message
3989             End Try
3990
3991             Select Case res
3992                 Case HttpStatusCode.OK
3993                 Case HttpStatusCode.Unauthorized
3994                     Twitter.AccountState = ACCOUNT_STATE.Invalid
3995                     Return "Check your Username/Password."
3996                 Case HttpStatusCode.BadRequest
3997                     Return "Err:API Limits?"
3998                 Case Else
3999                     Return "Err:" + res.ToString()
4000             End Select
4001
4002             Dim xdoc As New XmlDocument
4003             Try
4004                 xdoc.LoadXml(content)
4005             Catch ex As Exception
4006                 TraceOut(content)
4007                 Return "Invalid XML!"
4008             End Try
4009
4010             Try
4011                 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/lists_list/lists/list")
4012                     Dim xentry As XmlElement = CType(xentryNode, XmlElement)
4013                     Dim lst As New ListElement
4014                     lst.Description = xentry.Item("description").InnerText
4015                     lst.Id = Long.Parse(xentry.Item("id").InnerText)
4016                     lst.IsPublic = (xentry.Item("mode").InnerText = "public")
4017                     lst.MemberCount = Integer.Parse(xentry.Item("member_count").InnerText)
4018                     lst.Name = xentry.Item("name").InnerText
4019                     lst.SubscriberCount = Integer.Parse(xentry.Item("subscriber_count").InnerText)
4020                     lst.Slug = xentry.Item("slug").InnerText
4021                     Dim xUserEntry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
4022                     lst.Nickname = xUserEntry.Item("name").InnerText
4023                     lst.Username = xUserEntry.Item("screen_name").InnerText
4024                     lst.UserId = Long.Parse(xUserEntry.Item("id").InnerText)
4025                     lists.Add(lst)
4026                 Next
4027                 cursor = Long.Parse(xdoc.DocumentElement.SelectSingleNode("/lists_list/next_cursor").InnerText)
4028             Catch ex As Exception
4029                 TraceOut(content)
4030                 Return "Invalid XML!"
4031             End Try
4032         Loop While cursor <> 0
4033
4034         cursor = -1
4035         content = ""
4036         Do
4037             Try
4038                 res = twCon.GetListsSubscriptions(Me.Username, cursor, content)
4039             Catch ex As Exception
4040                 Return "Err:" + ex.Message
4041             End Try
4042
4043             Select Case res
4044                 Case HttpStatusCode.OK
4045                 Case HttpStatusCode.Unauthorized
4046                     Twitter.AccountState = ACCOUNT_STATE.Invalid
4047                     Return "Check your Username/Password."
4048                 Case HttpStatusCode.BadRequest
4049                     Return "Err:API Limits?"
4050                 Case Else
4051                     Return "Err:" + res.ToString()
4052             End Select
4053
4054             Dim xdoc As New XmlDocument
4055             Try
4056                 xdoc.LoadXml(content)
4057             Catch ex As Exception
4058                 TraceOut(content)
4059                 Return "Invalid XML!"
4060             End Try
4061
4062             Try
4063                 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/lists_list/lists/list")
4064                     Dim xentry As XmlElement = CType(xentryNode, XmlElement)
4065                     Dim lst As New ListElement
4066                     lst.Description = xentry.Item("description").InnerText
4067                     lst.Id = Long.Parse(xentry.Item("id").InnerText)
4068                     lst.IsPublic = (xentry.Item("mode").InnerText = "public")
4069                     lst.MemberCount = Integer.Parse(xentry.Item("member_count").InnerText)
4070                     lst.Name = xentry.Item("name").InnerText
4071                     lst.SubscriberCount = Integer.Parse(xentry.Item("subscriber_count").InnerText)
4072                     lst.Slug = xentry.Item("slug").InnerText
4073                     Dim xUserEntry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
4074                     lst.Nickname = xUserEntry.Item("name").InnerText
4075                     lst.Username = xUserEntry.Item("screen_name").InnerText
4076                     lst.UserId = Long.Parse(xUserEntry.Item("id").InnerText)
4077                     lists.Add(lst)
4078                 Next
4079                 cursor = Long.Parse(xdoc.DocumentElement.SelectSingleNode("/lists_list/next_cursor").InnerText)
4080             Catch ex As Exception
4081                 TraceOut(content)
4082                 Return "Invalid XML!"
4083             End Try
4084         Loop While cursor <> 0
4085
4086         TabInformations.GetInstance.SubscribableLists = lists
4087         Return ""
4088
4089     End Function
4090
4091     Private Function CreateHtmlAnchor(ByVal Text As String, ByVal AtList As List(Of String)) As String
4092         'Dim retStr As String = HttpUtility.HtmlEncode(Text)     '要検証(デコードされて取得されるので再エンコード)
4093         'Dim retStr As String = HttpUtility.HtmlDecode(Text)
4094         Dim retStr As String = ""
4095         'uriの正規表現
4096         'Dim rgUrl As Regex = New Regex("(?<![0-9A-Za-z=])(?:https?|shttp|ftps?)://(?:(?:[-_.!~*'()a-zA-Z0-9;:&=+$,]|%[0-9A-Fa-f" + _
4097         '                 "][0-9A-Fa-f])*@)?(?:(?:[a-zA-Z0-9](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?\.)" + _
4098         '                 "*[a-zA-Z](?:[-a-zA-Z0-9]*[a-zA-Z0-9])?\.?|[0-9]+\.[0-9]+\.[0-9]+\." + _
4099         '                 "[0-9]+)(?::[0-9]*)?(?:/(?:[-_.!~*'()a-zA-Z0-9:@&=+$,]|%[0-9A-Fa-f]" + _
4100         '                 "[0-9A-Fa-f])*(?:;(?:[-_.!~*'()a-zA-Z0-9:@&=+$,]|%[0-9A-Fa-f][0-9A-" + _
4101         '                 "Fa-f])*)*(?:/(?:[-_.!~*'()a-zA-Z0-9:@&=+$,]|%[0-9A-Fa-f][0-9A-Fa-f" + _
4102         '                 "])*(?:;(?:[-_.!~*'()a-zA-Z0-9:@&=+$,]|%[0-9A-Fa-f][0-9A-Fa-f])*)*)" + _
4103         '                 "*)?(?:\?(?:[-_.!~*'()a-zA-Z0-9;/?:@&=+$,]|%[0-9A-Fa-f][0-9A-Fa-f])" + _
4104         '                 "*)?(?:#(?:[-_.!~*'()a-zA-Z0-9;/?:@&=+$,]|%[0-9A-Fa-f][0-9A-Fa-f])*)?")
4105         Const rgUrl As String = "(?<before>(?:[^\/""':!=]|^|\:))" + _
4106                                     "(?<url>(?<protocol>https?://|www\.)" + _
4107                                     "(?<domain>(?:[\.-]|[^\p{P}])+\.[a-z]{2,}(?::[0-9]+)?)" + _
4108                                     "(?<path>/[a-z0-9!*'();:&=+$/%#\[\]\-_.,~@]*[a-z0-9)=#/]?)?" + _
4109                                     "(?<query>\?[a-z0-9!*'();:&=+$/%#\[\]\-_.,~]*[a-z0-9_&=#])?)"
4110         '絶対パス表現のUriをリンクに置換
4111         retStr = Regex.Replace(Text, rgUrl, New MatchEvaluator(AddressOf AutoLinkUrl), RegexOptions.IgnoreCase)
4112
4113         '@返信を抽出し、@先リスト作成
4114         'Dim rg As New Regex("(^|[ -/:-@[-^`{-~])@([a-zA-Z0-9_]{1,20}/[a-zA-Z0-9_\-]{1,24}[a-zA-Z0-9_])")
4115         '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)
4116         'Dim m As Match = Regex.Match(retStr, "(^|[^a-zA-Z0-9_])[@@]([a-zA-Z0-9_]{1,20}/[a-zA-Z0-9_\-]{1,79}[a-zA-Z0-9_])")
4117         '@先をリンクに置換(リスト)
4118         retStr = Regex.Replace(retStr, "(^|[^a-zA-Z0-9_])[@@]([a-zA-Z0-9_]{1,20}/[a-zA-Z0-9_\-]{1,79}[a-zA-Z0-9_])", "$1@<a href=""/$2"">$2</a>")
4119
4120         'rg = New Regex("(^|[ -/:-@[-^`{-~])@([a-zA-Z0-9_]{1,20})")
4121         'rg = New Regex("(^|[^a-zA-Z0-9_])[@@]([a-zA-Z0-9_]{1,20})", RegexOptions.Compiled)
4122         Dim m As Match = Regex.Match(retStr, "(^|[^a-zA-Z0-9_])[@@]([a-zA-Z0-9_]{1,20})")
4123         While m.Success
4124             AtList.Add(m.Result("$2").ToLower)
4125             m = m.NextMatch
4126         End While
4127         '@先をリンクに置換
4128         retStr = Regex.Replace(retStr, "(^|[^a-zA-Z0-9_])[@@]([a-zA-Z0-9_]{1,20})", "$1@<a href=""/$2"">$2</a>")
4129
4130         'ハッシュタグを抽出し、リンクに置換
4131         'Dim rgh As New Regex("(^|[ .!,\-:;<>?])#([^] !""#$%&'()*+,.:;<=>?@\-[\^`{|}~\r\n]+)")
4132         'Dim rgh As New Regex("(^|[^a-zA-Z0-9_/&])[##]([a-zA-Z0-9_]+)", RegexOptions.Compiled)
4133         Dim mhs As MatchCollection = Regex.Matches(retStr, "(^|[^a-zA-Z0-9_/&])[##]([a-zA-Z0-9_]+)")
4134         For Each mt As Match In mhs
4135             If Not IsNumeric(mt.Result("$2")) Then
4136                 'retStr = retStr.Replace(mt.Result("$1") + mt.Result("$2"), "<a href=""" + _protocol + "twitter.com/search?q=%23" + mt.Result("$2") + """>#" + mt.Result("$2") + "</a>")
4137                 SyncLock LockObj
4138                     _hashList.Add("#" + mt.Result("$2"))
4139                 End SyncLock
4140             End If
4141         Next
4142         retStr = Regex.Replace(retStr, "(^|[^a-zA-Z0-9_/&])[##]([a-zA-Z0-9_]+)", New MatchEvaluator(AddressOf AutoLinkHashtag))
4143
4144         retStr = Regex.Replace(retStr, "(^|[^a-zA-Z0-9_/&##@@])sm([0-9]{4,10})", "$1<a href=""http://www.nicovideo.jp/watch/sm$2"">sm$2</a>")
4145
4146         retStr = AdjustHtml(ShortUrlResolve(PreProcessUrl(retStr))) 'IDN置換、短縮Uri解決、@リンクを相対→絶対にしてtarget属性付与
4147         Return retStr
4148     End Function
4149
4150     Private Function AutoLinkUrl(ByVal m As Match) As String
4151         Dim sb As New StringBuilder(m.Result("${before}<a href="""))
4152         If m.Result("${protocol}").StartsWith("w", StringComparison.OrdinalIgnoreCase) Then
4153             sb.Append("http://")
4154         End If
4155         sb.Append(m.Result("${url}"">")).Append(m.Result("${url}")).Append("</a>")
4156         Return sb.ToString
4157     End Function
4158
4159     Private Function AutoLinkHashtag(ByVal m As Match) As String
4160         If IsNumeric(m.Result("$2")) Then Return m.Result("$1#$2")
4161         Dim sb As New StringBuilder(m.Result("$1<a href="""))
4162         Return sb.Append(_protocol).Append("twitter.com/search?q=%23").Append(m.Result("$2"">#$2</a>")).ToString
4163     End Function
4164
4165     Public ReadOnly Property RemainCountApi() As Integer
4166         Get
4167             Return twCon.RemainCountApi
4168         End Get
4169     End Property
4170
4171     Public Function GetInfoApi(ByRef info As ApiInfo) As Boolean
4172         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return True
4173
4174         If _endingFlag Then Return True
4175
4176         'info.MaxCount = twCon.UpperCountApi
4177         'info.RemainCount = twCon.RemainCountApi
4178         'info.ResetTime = twCon.ResetTimeApi
4179         'Return True
4180         Dim res As HttpStatusCode
4181         Dim content As String = ""
4182         Try
4183             res = twCon.RateLimitStatus(content)
4184         Catch ex As Exception
4185             Return False
4186         End Try
4187
4188         If res <> HttpStatusCode.OK Then Return False
4189
4190         Dim xdoc As New XmlDocument
4191         Try
4192             xdoc.LoadXml(content)
4193             info.MaxCount = Integer.Parse(xdoc.SelectSingleNode("/hash/hourly-limit").InnerText)
4194             info.RemainCount = Integer.Parse(xdoc.SelectSingleNode("/hash/remaining-hits").InnerText)
4195             info.ResetTime = DateTime.Parse(xdoc.SelectSingleNode("/hash/reset-time").InnerText)
4196             'info.ResetTimeInSeconds = Integer.Parse(xdoc.SelectSingleNode("/hash/reset-time-in-seconds").InnerText)
4197             Return True
4198         Catch ex As Exception
4199             Return False
4200         End Try
4201     End Function
4202
4203     Public Function GetHashList() As String()
4204         Dim hashArray As String()
4205         SyncLock LockObj
4206             hashArray = _hashList.ToArray
4207             _hashList.Clear()
4208         End SyncLock
4209         Return hashArray
4210     End Function
4211
4212     '#Region "デバッグモード解析キー自動生成"
4213     '#If DEBUG Then
4214     '    Public Sub GenerateAnalyzeKey()
4215     '        '解析キー情報部分のソースをwedataから作成する
4216     '        '生成したソースはプロジェクトのディレクトリにコピーする
4217     '        Dim sw As New System.IO.StreamWriter(".\AnalyzeKey.vb", _
4218     '            False, _
4219     '            System.Text.Encoding.UTF8)
4220
4221     '        sw.WriteLine("Public Module AnalyzeKey")
4222     '        sw.WriteLine("'    このファイルはデバッグビルドのTweenにより自動作成されました   作成日時  " + DateAndTime.Now.ToString())
4223     '        sw.WriteLine("")
4224
4225     '        sw.WriteLine("    Public _splitPost As String = " + Chr(34) + _splitPost.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4226     '        sw.WriteLine("    Public _splitPostRecent As String = " + Chr(34) + _splitPostRecent.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4227     '        sw.WriteLine("    Public _statusIdTo As String = " + Chr(34) + _statusIdTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4228     '        sw.WriteLine("    Public _splitDM As String = " + Chr(34) + _splitDM.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4229     '        sw.WriteLine("    Public _parseName As String = " + Chr(34) + _parseName.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4230     '        sw.WriteLine("    Public _parseNameTo As String = " + Chr(34) + _parseNameTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4231     '        sw.WriteLine("    Public _parseNick As String = " + Chr(34) + _parseNick.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4232     '        sw.WriteLine("    Public _parseNickTo As String = " + Chr(34) + _parseNickTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4233     '        sw.WriteLine("    Public _parseImg As String = " + Chr(34) + _parseImg.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4234     '        sw.WriteLine("    Public _parseImgTo As String = " + Chr(34) + _parseImgTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4235     '        sw.WriteLine("    Public _parseMsg1 As String = " + Chr(34) + _parseMsg1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4236     '        sw.WriteLine("    Public _parseMsg2 As String = " + Chr(34) + _parseMsg2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4237     '        sw.WriteLine("    Public _parseDM1 As String = " + Chr(34) + _parseDM1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4238     '        sw.WriteLine("    Public _parseDM11 As String = " + Chr(34) + _parseDM11.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4239     '        sw.WriteLine("    Public _parseDM2 As String = " + Chr(34) + _parseDM2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4240     '        sw.WriteLine("    Public _parseDate As String = " + Chr(34) + _parseDate.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4241     '        sw.WriteLine("    Public _parseDateTo As String = " + Chr(34) + _parseDateTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4242     '        sw.WriteLine("    Public _getAuthKey As String = " + Chr(34) + _getAuthKey.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4243     '        sw.WriteLine("    Public _getAuthKeyTo As String = " + Chr(34) + _getAuthKeyTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4244     '        'sw.WriteLine("    Public _parseStar As String = " + Chr(34) + _parseStar.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4245     '        'sw.WriteLine("    Public _parseStarTo As String = " + Chr(34) + _parseStarTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4246     '        'sw.WriteLine("    Public _parseStarEmpty As String = " + Chr(34) + _parseStarEmpty.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4247     '        sw.WriteLine("    Public _followerList As String = " + Chr(34) + _followerList.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4248     '        sw.WriteLine("    Public _followerMbr1 As String = " + Chr(34) + _followerMbr1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4249     '        sw.WriteLine("    Public _followerMbr2 As String = " + Chr(34) + _followerMbr2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4250     '        sw.WriteLine("    Public _followerMbr3 As String = " + Chr(34) + _followerMbr3.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4251     '        sw.WriteLine("    Public _getInfoTwitter As String = " + Chr(34) + _getInfoTwitter.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4252     '        sw.WriteLine("    Public _getInfoTwitterTo As String = " + Chr(34) + _getInfoTwitterTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4253     '        sw.WriteLine("    Public _isProtect As String = " + Chr(34) + _isProtect.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4254     '        sw.WriteLine("    Public _isReplyEng As String = " + Chr(34) + _isReplyEng.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4255     '        sw.WriteLine("    Public _isReplyJpn As String = " + Chr(34) + _isReplyJpn.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4256     '        sw.WriteLine("    Public _isReplyTo As String = " + Chr(34) + _isReplyTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4257     '        sw.WriteLine("    Public _parseProtectMsg1 As String = " + Chr(34) + _parseProtectMsg1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4258     '        sw.WriteLine("    Public _parseProtectMsg2 As String = " + Chr(34) + _parseProtectMsg2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4259     '        sw.WriteLine("    Public _parseDMcountFrom As String = " + Chr(34) + _parseDMcountFrom.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4260     '        sw.WriteLine("    Public _parseDMcountTo As String = " + Chr(34) + _parseDMcountTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4261     '        sw.WriteLine("    Public _parseSourceFrom As String = " + Chr(34) + _parseSourceFrom.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4262     '        sw.WriteLine("    Public _parseSource2 As String = " + Chr(34) + _parseSource2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4263     '        sw.WriteLine("    Public _parseSourceTo As String = " + Chr(34) + _parseSourceTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4264     '        sw.WriteLine("    Public _removeClass As String = " + Chr(34) + _removeClass.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
4265     '        sw.WriteLine("End Module")
4266
4267     '        sw.Close()
4268     '        'MessageBox.Show("解析キー情報定義ファイル AnalyzeKey.vbを生成しました")
4269
4270     '    End Sub
4271     '#End If
4272     '#End Region
4273
4274     Public ReadOnly Property AccessToken() As String
4275         Get
4276             Return twCon.AccessToken
4277         End Get
4278     End Property
4279
4280     Public ReadOnly Property AccessTokenSecret() As String
4281         Get
4282             Return twCon.AccessTokenSecret
4283         End Get
4284     End Property
4285
4286 End Class