OSDN Git Service

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