root/lang/vb2005/Tween/Tween/Twitter.vb @ 29115

Revision 29115, 167.3 kB (checked in by syo68k, 5 years ago)

GetFollowers周り調整

Line 
1' Tween - Client of Twitter
2' Copyright © 2007-2009 kiri_feather (@kiri_feather) <kiri_feather@gmail.com>
3'           © 2008-2009 Moz (@syo68k) <http://iddy.jp/profile/moz/>
4'           © 2008-2009 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
24Imports System.Web
25Imports System.Xml
26Imports System.Text
27Imports System.Threading
28Imports System.IO
29Imports System.Text.RegularExpressions
30
31Public Module Twitter
32    Delegate Sub GetIconImageDelegate(ByVal post As PostClass)
33    Delegate Function GetTimelineDelegate(ByVal page As Integer, _
34                                ByVal read As Boolean, _
35                                ByRef endPage As Integer, _
36                                ByVal gType As WORKERTYPE, _
37                                ByRef getDM As Boolean) As String
38    Delegate Function GetDirectMessageDelegate(ByVal page As Integer, _
39                                    ByVal read As Boolean, _
40                                    ByVal endPage As Integer, _
41                                    ByVal gType As WORKERTYPE) As String
42    Private ReadOnly LockObj As New Object
43    Private GetTmSemaphore As New Threading.Semaphore(8, 8)
44
45    Private links As New List(Of Long)
46    Private follower As New Collections.Specialized.StringCollection
47
48    'プロパティからアクセスされる共通情報
49    Private _uid As String
50    Private _pwd As String
51    Private _proxyType As ProxyTypeEnum
52    Private _proxyAddress As String
53    Private _proxyPort As Integer
54    Private _proxyUser As String
55    Private _proxyPassword As String
56
57    Private _nextThreshold As Integer
58    Private _nextPages As Integer
59
60    Private _iconSz As Integer
61    Private _getIcon As Boolean
62
63    Private _tinyUrlResolve As Boolean
64    Private _restrictFavCheck As Boolean
65    Private _useAPI As Boolean
66
67    Private _hubServer As String
68
69    Private _owner As TweenMain
70
71    '共通で使用する状態
72    Private _authKey As String              'StatusUpdate、発言削除で使用
73    Private _authKeyDM As String              'DM送信、DM削除で使用
74    Private _signed As Boolean
75    Private _endingFlag As Boolean
76    Private _infoTwitter As String = ""
77    Private _dmCount As Integer
78    Private _getDm As Boolean
79
80    Private _ShortUrlService() As String = { _
81            "http://tinyurl.com/", _
82            "http://is.gd/", _
83            "http://snipurl.com/", _
84            "http://snurl.com/", _
85            "http://nsfw.in/", _
86            "http://qurlyq.com/", _
87            "http://dwarfurl.com/", _
88            "http://icanhaz.com/", _
89            "http://tiny.cc/", _
90            "http://urlenco.de/", _
91            "http://bit.ly/", _
92            "http://piurl.com/", _
93            "http://linkbee.com/", _
94            "http://traceurl.com/", _
95            "http://twurl.nl/", _
96            "http://cli.gs/", _
97            "http://rubyurl.com/", _
98            "http://budurl.com/" _
99        }
100
101    Private Const _baseUrlStr As String = "twitter.com"
102    Private Const _loginPath As String = "/sessions"
103    Private Const _homePath As String = "/home"
104    Private Const _replyPath As String = "/replies"
105    Private Const _DMPathRcv As String = "/direct_messages"
106    Private Const _DMPathSnt As String = "/direct_messages/sent"
107    Private Const _DMDestroyPath As String = "/direct_messages/destroy/"
108    Private Const _StDestroyPath As String = "/status/destroy/"
109    Private Const _uidHeader As String = "session[username_or_email]="
110    Private Const _pwdHeader As String = "session[password]="
111    Private Const _pageQry As String = "?page="
112    Private Const _statusHeader As String = "status="
113    Private Const _statusUpdatePath As String = "/status/update?page=1&tab=home"
114    Private Const _statusUpdatePathAPI As String = "/statuses/update.xml"
115    Private Const _linkToOld As String = "class=""section_links"" rel=""prev"""
116    Private Const _postFavAddPath As String = "/favourings/create/"
117    Private Const _postFavRemovePath As String = "/favourings/destroy/"
118    Private Const _authKeyHeader As String = "authenticity_token="
119    Private Const _parseLink1 As String = "<a href="""
120    Private Const _parseLink2 As String = """>"
121    Private Const _parseLink3 As String = "</a>"
122    Private Const _GetFollowers As String = "/statuses/followers.xml"
123    Private Const _ShowStatus As String = "/statuses/show/"
124
125
126    '''Wedata対応
127    Private Const wedataUrl As String = "http://wedata.net/databases/Tween/items.json"
128    'テーブル
129    Private Const tbGetMsgDM As String = "GetMsgDM"
130    Private Const tbSplitDM As String = "SplitDM"
131    Private Const tbFollower As String = "Follower"
132    Private Const tbGetStar As String = "GetStar"
133    Private Const tbIsReply As String = "IsReply"
134    Private Const tbGetDate As String = "GetDate"
135    Private Const tbGetMsg As String = "GetMsg"
136    Private Const tbIsProtect As String = "IsProtect"
137    Private Const tbGetImagePath As String = "GetImagePath"
138    Private Const tbGetNick As String = "GetNick"
139    Private Const tbGetName As String = "GetName"
140    'Private Const tbGetSiv As String = "GetSiv"
141    Private Const tbStatusID As String = "StatusID"
142    Private Const tbSplitPostRecent As String = "SplitPostRecent"
143    Private Const tbAuthKey As String = "AuthKey"
144    Private Const tbInfoTwitter As String = "InfoTwitter"
145    Private Const tbSplitPostReply As String = "SplitPostReply"
146    Private Const tbGetDMCount As String = "GetDMCount"
147    '属性
148    Private Const tbTagFrom As String = "tagfrom"
149    Private Const tbTagTo As String = "tagto"
150    Private Const tbTag As String = "tag"
151    Private Const tbTagMbrFrom As String = "tagmbrfrom"
152    Private Const tbTagMbrFrom2 As String = "tagmbrfrom2"
153    Private Const tbTagMbrTo As String = "tagmbrto"
154    Private Const tbTagStatus As String = "status"
155    Private Const tbTagJpnFrom As String = "tagjpnfrom"
156    Private Const tbTagEngFrom As String = "tagengfrom"
157
158    'Public Sub New(ByVal Username As String, _
159    '            ByVal Password As String, _
160    '            ByVal ProxyType As ProxyTypeEnum, _
161    '            ByVal ProxyAddress As String, _
162    '            ByVal ProxyPort As Integer, _
163    '            ByVal ProxyUser As String, _
164    '            ByVal ProxyPassword As String)
165    '    _mySock = New MySocket("UTF-8", Username, Password, ProxyType, ProxyAddress, ProxyPort, ProxyUser, ProxyPassword)
166    '    _uid = Username
167    '    _pwd = Password
168    '    'follower.Add(_uid)
169    '    _proxyType = ProxyType
170    '    _proxyAddress = ProxyAddress
171    '    _proxyPort = ProxyPort
172    '    _proxyUser = ProxyUser
173    '    _proxyPassword = ProxyPassword
174
175    '    '発言保持クラス
176    '    _statuses = TabInformations.GetInstance()
177    'End Sub
178
179    Private Function SignIn() As String
180        If _endingFlag Then Return ""
181
182        'ユーザー情報からデータ部分の生成
183        Dim account As String = ""
184
185        SyncLock LockObj
186            If _signed Then Return ""
187
188            '未認証
189            _signed = False
190
191            MySocket.ResetCookie()
192
193            Dim resStatus As String = ""
194            Dim resMsg As String = ""
195
196            resMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + "/", resStatus, MySocket.REQ_TYPE.ReqGET), String)
197            If resMsg.Length = 0 Then
198                Return "SignIn -> " + resStatus
199            End If
200            Dim authToken As String = ""
201            Dim rg As New Regex("authenticity_token"" type=""hidden"" value=""(?<auth>[a-z0-9]+)""")
202            Dim m As Match = rg.Match(resMsg)
203            If m.Success Then
204                authToken = m.Result("${auth}")
205            Else
206                Return "SignIn -> Can't get token."
207            End If
208
209            account = _authKeyHeader + authToken + "&" + _uidHeader + _uid + "&" + _pwdHeader + _pwd + "&" + "remember_me=1"
210
211            resMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _loginPath, resStatus, MySocket.REQ_TYPE.ReqPOST, account), String)
212            If resMsg.Length = 0 Then
213                Return "SignIn -> " + resStatus
214            End If
215
216            _signed = True
217            Return ""
218        End SyncLock
219    End Function
220
221    Public Function GetTimeline(ByVal page As Integer, _
222                                ByVal read As Boolean, _
223                                ByRef endPage As Integer, _
224                                ByVal gType As WORKERTYPE, _
225                                ByRef getDM As Boolean) As String
226
227        If endPage = 0 Then
228            '通常モード
229            Dim epage As Integer = page
230            GetTmSemaphore.WaitOne()
231            Dim trslt As String = ""
232            trslt = GetTimelineThread(page, read, epage, gType, getDM)
233            If trslt.Length > 0 Then Return trslt
234            page += 1
235            If epage < page OrElse gType = WORKERTYPE.Reply Then Return ""
236            endPage = epage
237        End If
238        '起動時モード or 通常モードの読み込み継続 -> 複数ページ同時取得
239        Dim num As Integer = endPage - page
240        Dim ar(num) As IAsyncResult
241        Dim dlgt(num) As GetTimelineDelegate
242
243        For idx As Integer = 0 To num
244            dlgt(idx) = New GetTimelineDelegate(AddressOf GetTimelineThread)
245            GetTmSemaphore.WaitOne()
246            ar(idx) = dlgt(idx).BeginInvoke(page + idx, read, endPage + idx, gType, getDM, Nothing, Nothing)
247        Next
248        Dim rslt As String = ""
249        For idx As Integer = 0 To num
250            Dim epage As Integer = 0
251            Dim dm As Boolean = False
252            Dim trslt As String = ""
253            trslt = dlgt(idx).EndInvoke(epage, dm, ar(idx))
254            If trslt.Length > 0 AndAlso rslt.Length = 0 Then rslt = trslt
255            If dm Then getDM = True
256        Next
257        Return rslt
258    End Function
259
260    Private Function GetTimelineThread(ByVal page As Integer, _
261                                ByVal read As Boolean, _
262                                ByRef endPage As Integer, _
263                                ByVal gType As WORKERTYPE, _
264                                ByRef getDM As Boolean) As String
265        Try
266            If _endingFlag Then Return ""
267
268            Dim retMsg As String = ""
269            Dim resStatus As String = ""
270
271            If _signed = False Then
272                retMsg = SignIn()
273                If retMsg.Length > 0 Then
274                    Return retMsg
275                End If
276            End If
277
278            'リクエストメッセージを作成する
279            Dim pageQuery As String
280
281            If page = 1 Then
282                pageQuery = ""
283            Else
284                pageQuery = _pageQry + page.ToString
285            End If
286
287            If gType = WORKERTYPE.Timeline Then
288                retMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _homePath + pageQuery, resStatus), String)
289            Else
290                retMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _replyPath + pageQuery, resStatus), String)
291            End If
292
293            If retMsg.Length = 0 Then
294                _signed = False
295                Return resStatus
296            End If
297
298            ' tr 要素の class 属性を消去
299            Do
300                Dim idx As Integer = retMsg.IndexOf("<tr class=""", StringComparison.Ordinal)
301                If idx = -1 Then Exit Do
302                retMsg = retMsg.Remove(idx + 4, retMsg.IndexOf("""", idx + 11 + 1, StringComparison.Ordinal) - idx - 2) ' 11 = "<tr class=""".Length
303            Loop
304
305            If _endingFlag Then Return ""
306
307            '各メッセージに分割可能か?
308            Dim strSepTmp As String
309            If gType = WORKERTYPE.Timeline Then
310                strSepTmp = _splitPostRecent
311            Else
312                strSepTmp = _splitPost
313            End If
314
315            Dim pos1 As Integer
316            Dim pos2 As Integer
317
318            pos1 = retMsg.IndexOf(strSepTmp, StringComparison.Ordinal)
319            If pos1 = -1 Then
320                '0件 or 取得失敗
321                _signed = False
322                Return "GetTimeline -> Err: tweets count is 0."
323            End If
324
325            Dim strSep() As String = {strSepTmp}
326            Dim posts() As String = retMsg.Split(strSep, StringSplitOptions.RemoveEmptyEntries)
327            Dim intCnt As Integer = 0
328            Dim listCnt As Integer = 0
329            SyncLock LockObj
330                listCnt = links.Count
331            End SyncLock
332            Dim dlgt(20) As GetIconImageDelegate
333            Dim ar(20) As IAsyncResult
334            Dim arIdx As Integer = -1
335
336            For Each strPost As String In posts
337                intCnt += 1
338
339                If intCnt = 1 Then
340                    If page = 1 And gType = WORKERTYPE.Timeline Then
341                        ''siv取得
342                        'pos1 = strPost.IndexOf(_getSiv, 0)
343                        'If pos1 > 0 Then
344                        '    pos2 = strPost.IndexOf(_getSivTo, pos1 + _getSiv.Length)
345                        '    If pos2 > -1 Then
346                        '        _authSiv = strPost.Substring(pos1 + _getSiv.Length, pos2 - pos1 - _getSiv.Length)
347                        '    Else
348                        '        '取得失敗
349                        '        _signed = False
350                        '        Return "GetTimeline -> Err: Can't get Siv."
351                        '    End If
352                        'Else
353                        '    '取得失敗
354                        '    _signed = False
355                        '    Return "GetTimeline -> Err: Can't get Siv."
356                        'End If
357
358                        'AuthKeyの取得
359                        If GetAuthKey(retMsg) < 0 Then
360                            _signed = False
361                            Return "GetTimeline -> Err: Can't get auth token."
362                        End If
363
364                        'TwitterInfoの取得
365                        pos1 = retMsg.IndexOf(_getInfoTwitter, StringComparison.Ordinal)
366                        If pos1 > -1 Then
367                            pos2 = retMsg.IndexOf(_getInfoTwitterTo, pos1, StringComparison.Ordinal)
368                            If pos2 > -1 Then
369                                _infoTwitter = retMsg.Substring(pos1 + _getInfoTwitter.Length, pos2 - pos1 - _getInfoTwitter.Length)
370                            Else
371                                _infoTwitter = ""
372                            End If
373                        Else
374                            _infoTwitter = ""
375                        End If
376                    End If
377                Else
378
379                    Dim post As New PostClass
380
381                    Try
382                        'Get ID
383                        pos1 = 0
384                        pos2 = strPost.IndexOf(_statusIdTo, 0, StringComparison.Ordinal)
385                        post.Id = Long.Parse(HttpUtility.HtmlDecode(strPost.Substring(0, pos2)))
386                    Catch ex As Exception
387                        _signed = False
388                        TraceOut("TM-ID:" + strPost)
389                        Return "GetTimeline -> Err: Can't get ID."
390                    End Try
391                    'Get Name
392                    Try
393                        pos1 = strPost.IndexOf(_parseName, pos2, StringComparison.Ordinal)
394                        pos2 = strPost.IndexOf(_parseNameTo, pos1, StringComparison.Ordinal)
395                        post.Name = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseName.Length, pos2 - pos1 - _parseName.Length))
396                    Catch ex As Exception
397                        _signed = False
398                        TraceOut("TM-Name:" + strPost)
399                        Return "GetTimeline -> Err: Can't get Name."
400                    End Try
401                    'Get Nick
402                    '''バレンタイン対応
403                    If strPost.IndexOf("twitter.com/images/heart.png", pos2, StringComparison.Ordinal) > -1 Then
404                        post.Nickname = post.Name
405                    Else
406                        Try
407                            pos1 = strPost.IndexOf(_parseNick, pos2, StringComparison.Ordinal)
408                            pos2 = strPost.IndexOf(_parseNickTo, pos1 + _parseNick.Length, StringComparison.Ordinal)
409                            post.Nickname = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseNick.Length, pos2 - pos1 - _parseNick.Length))
410                        Catch ex As Exception
411                            _signed = False
412                            TraceOut("TM-Nick:" + strPost)
413                            Return "GetTimeline -> Err: Can't get Nick."
414                        End Try
415                    End If
416
417                    '二重取得回避
418                    SyncLock LockObj
419                        If links.Contains(post.Id) Then Continue For
420                    End SyncLock
421
422                    Dim orgData As String = ""
423                    'バレンタイン
424                    If strPost.IndexOf("<form action=""/status/update"" id=""heartForm", 0, StringComparison.Ordinal) > -1 Then
425                        Try
426                            pos1 = strPost.IndexOf("<strong>", 0, StringComparison.Ordinal)
427                            pos2 = strPost.IndexOf("</strong>", pos1, StringComparison.Ordinal)
428                            orgData = strPost.Substring(pos1 + 8, pos2 - pos1 - 8)
429                        Catch ex As Exception
430                            _signed = False
431                            TraceOut("TM-VBody:" + strPost)
432                            Return "GetTimeline -> Err: Can't get Valentine body."
433                        End Try
434                    End If
435
436
437                    'Get ImagePath
438                    Try
439                        pos1 = strPost.IndexOf(_parseImg, pos2, StringComparison.Ordinal)
440                        pos2 = strPost.IndexOf(_parseImgTo, pos1 + _parseImg.Length, StringComparison.Ordinal)
441                        post.ImageUrl = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseImg.Length, pos2 - pos1 - _parseImg.Length))
442                    Catch ex As Exception
443                        _signed = False
444                        TraceOut("TM-Img:" + strPost)
445                        Return "GetTimeline -> Err: Can't get ImagePath."
446                    End Try
447
448                    'Protect
449                    If strPost.IndexOf(_isProtect, pos2, StringComparison.Ordinal) > -1 Then
450                        post.IsProtect = True
451                    End If
452
453                    'Get Message
454                    pos1 = strPost.IndexOf(_parseMsg1, pos2, StringComparison.Ordinal)
455                    If pos1 < 0 Then
456                        'Valentine対応その2
457                        Try
458                            If strPost.IndexOf("<div id=""doyouheart", pos2, StringComparison.Ordinal) > -1 Then
459                                'バレンタイン
460                                orgData += " <3 you! Do you <3 "
461                                pos1 = strPost.IndexOf("<a href", pos2, StringComparison.Ordinal)
462                                pos2 = strPost.IndexOf("?", pos1, StringComparison.Ordinal)
463                                orgData += strPost.Substring(pos1, pos2 - pos1 + 1)
464                            Else
465                                pos1 = strPost.IndexOf(_parseProtectMsg1, pos2, StringComparison.Ordinal)
466                                If pos1 = -1 Then
467                                    'バレンタイン
468                                    orgData += " <3 's "
469                                    pos1 = strPost.IndexOf("<a href", pos2, StringComparison.Ordinal)
470                                    If pos1 > -1 Then
471                                        pos2 = strPost.IndexOf("!", pos1, StringComparison.Ordinal)
472                                        orgData += strPost.Substring(pos1, pos2 - pos1 + 1)
473                                    End If
474                                Else
475                                    'プロテクトメッセージ
476                                    pos2 = strPost.IndexOf(_parseProtectMsg2, pos1, StringComparison.Ordinal)
477                                    orgData = strPost.Substring(pos1 + _parseProtectMsg1.Length, pos2 - pos1 - _parseProtectMsg1.Length).Trim()
478                                End If
479                            End If
480                        Catch ex As Exception
481                            _signed = False
482                            TraceOut("TM-VBody2:" + strPost)
483                            Return "GetTimeline -> Err: Can't get Valentine body2."
484                        End Try
485                    Else
486                        '通常メッセージ
487                        Try
488                            pos2 = strPost.IndexOf(_parseMsg2, pos1, StringComparison.Ordinal)
489                            orgData = strPost.Substring(pos1 + _parseMsg1.Length, pos2 - pos1 - _parseMsg1.Length).Trim()
490                        Catch ex As Exception
491                            _signed = False
492                            TraceOut("TM-Body:" + strPost)
493                            Return "GetTimeline -> Err: Can't get body."
494                        End Try
495                        '原文リンク削除
496                        orgData = Regex.Replace(orgData, "<a href=""https://twitter\.com/" + post.Name + "/status/[0-9]+"">\.\.\.</a>$", "")
497                        'ハート変換
498                        orgData = orgData.Replace("&lt;3", "♡")
499                    End If
500
501                    '短縮URL解決処理(orgData書き換え)
502                    orgData = ShortUrlResolve(orgData)
503
504                    '表示用にhtml整形
505                    post.OriginalData = AdjustHtml(orgData)
506
507                    '単純テキストの取り出し(リンクタグ除去)
508                    Try
509                        post.Data = GetPlainText(orgData)
510                    Catch ex As Exception
511                        _signed = False
512                        TraceOut("TM-Link:" + strPost)
513                        Return "GetTimeline -> Err: Can't parse links."
514                    End Try
515
516                    ' Imageタグ除去(ハロウィン)
517                    Dim ImgTag As New Regex("<img src=.*?/>", RegexOptions.IgnoreCase)
518                    If ImgTag.IsMatch(post.Data) Then post.Data = ImgTag.Replace(post.Data, "<img>")
519
520                    'Get Date
521                    Try
522                        pos1 = strPost.IndexOf(_parseDate, pos2, StringComparison.Ordinal)
523                        pos2 = strPost.IndexOf(_parseDateTo, pos1 + _parseDate.Length, StringComparison.Ordinal)
524                        post.PDate = DateTime.ParseExact(strPost.Substring(pos1 + _parseDate.Length, pos2 - pos1 - _parseDate.Length), "yyyy'-'MM'-'dd'T'HH':'mm':'sszzz", System.Globalization.DateTimeFormatInfo.InvariantInfo, Globalization.DateTimeStyles.None)
525                    Catch ex As Exception
526                        _signed = False
527                        TraceOut("TM-Date:" + strPost)
528                        Return "GetTimeline -> Err: Can't get date."
529                    End Try
530
531                    'from Sourceの取得
532                    Try
533                        pos1 = strPost.IndexOf(_parseSourceFrom, pos2, StringComparison.Ordinal)
534                        If pos1 > -1 Then
535                            pos1 = strPost.IndexOf(_parseSource2, pos1 + 19, StringComparison.Ordinal)
536                            pos2 = strPost.IndexOf(_parseSourceTo, pos1 + 2, StringComparison.Ordinal)
537                            post.Source = HttpUtility.HtmlDecode(strPost.Substring(pos1 + 2, pos2 - pos1 - 2))
538                        Else
539                            post.Source = "Web"
540                        End If
541                    Catch ex As Exception
542                        _signed = False
543                        TraceOut("TM-Src:" + strPost)
544                        Return "GetTimeline -> Err: Can't get src."
545                    End Try
546
547                    'Get Reply(in_reply_to_user/id)
548                    Dim rg As New Regex("<a href=""https?:\/\/twitter\.com\/(?<name>[a-zA-Z0-9_]+)\/status\/(?<id>[0-9]+)"">(?:in reply to |u8fd4u4fe1: )")
549                    Dim m As Match = rg.Match(strPost)
550                    If m.Success Then
551                        post.InReplyToUser = m.Result("${name}")
552                        post.InReplyToId = Long.Parse(m.Result("${id}"))
553                        post.IsReply = post.InReplyToUser.Equals(_uid, StringComparison.OrdinalIgnoreCase)
554                    End If
555
556                    '@先リスト作成
557                    rg = New Regex("@<a href=""\/(?<1>[a-zA-Z0-9_]+)""")
558                    m = rg.Match(orgData)
559                    While m.Success
560                        post.ReplyToList.Add(m.Groups(1).Value.ToLower())
561                        m = m.NextMatch
562                    End While
563                    If Not post.IsReply Then post.IsReply = post.ReplyToList.Contains(_uid.ToLower())
564
565                    'Get Fav
566                    pos1 = strPost.IndexOf(_parseStar, pos2, StringComparison.Ordinal)
567                    If pos1 > -1 Then
568                        Try
569                            pos2 = strPost.IndexOf(_parseStarTo, pos1 + _parseStar.Length, StringComparison.Ordinal)
570                            If strPost.Substring(pos1 + _parseStar.Length, pos2 - pos1 - _parseStar.Length) = _parseStarEmpty Then
571                                post.IsFav = False
572                            Else
573                                post.IsFav = True
574                            End If
575                        Catch ex As Exception
576                            _signed = False
577                            TraceOut("TM-Fav:" + strPost)
578                            Return "GetTimeline -> Err: Can't get fav status."
579                        End Try
580                    Else
581                        post.IsFav = False
582                    End If
583
584
585                    If _endingFlag Then Return ""
586
587                    SyncLock LockObj
588                        links.Add(post.Id)
589                    End SyncLock
590
591                    post.IsMe = post.Name.Equals(_uid, StringComparison.OrdinalIgnoreCase)
592                    SyncLock LockObj
593                        If follower.Count > 1 Then
594                            post.IsOwl = Not follower.Contains(post.Name.ToLower())
595                        Else
596                            post.IsOwl = False
597                        End If
598                    End SyncLock
599                    post.IsRead = read
600
601                    arIdx += 1
602                    dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
603                    ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
604
605                End If
606
607                'テスト実装:DMカウント取得
608                If intCnt = posts.Length AndAlso gType = WORKERTYPE.Timeline AndAlso page = 1 Then
609                    pos1 = strPost.IndexOf(_parseDMcountFrom, pos2, StringComparison.Ordinal)
610                    If pos1 > -1 Then
611                        Try
612                            pos2 = strPost.IndexOf(_parseDMcountTo, pos1 + _parseDMcountFrom.Length, StringComparison.Ordinal)
613                            Dim dmCnt As Integer = Integer.Parse(strPost.Substring(pos1 + _parseDMcountFrom.Length, pos2 - pos1 - _parseDMcountFrom.Length))
614                            If dmCnt > _dmCount Then
615                                _dmCount = dmCnt
616                                _getDm = True
617                            End If
618                        Catch ex As Exception
619                        End Try
620                    End If
621                End If
622                getDM = _getDm
623            Next
624
625            For i As Integer = 0 To arIdx
626                dlgt(i).EndInvoke(ar(i))
627            Next
628
629            SyncLock LockObj
630                If page = 1 AndAlso (links.Count - listCnt) >= _nextThreshold Then
631                    '新着が閾値の件数以上なら、次のページも念のため読み込み
632                    endPage = _nextPages + 1
633                End If
634            End SyncLock
635
636            Return ""
637        Finally
638            GetTmSemaphore.Release()
639        End Try
640    End Function
641
642    Public Function GetDirectMessage(ByVal page As Integer, _
643                                    ByVal read As Boolean, _
644                                    ByVal endPage As Integer, _
645                                    ByVal gType As WORKERTYPE) As String
646        If endPage = 0 Then
647            '通常モード(DMはモード関係なし)
648            endPage = 1
649        End If
650        '起動時モード
651        Dim num As Integer = (endPage - page + 1) * 2 - 1
652        Dim ar(num) As IAsyncResult
653        Dim dlgt(num) As GetDirectMessageDelegate
654
655        For idx As Integer = 0 To num
656            If idx Mod 2 = 0 Then
657                gType = WORKERTYPE.DirectMessegeRcv
658            Else
659                gType = WORKERTYPE.DirectMessegeSnt
660            End If
661            dlgt(idx) = New GetDirectMessageDelegate(AddressOf GetDirectMessageThread)
662            GetTmSemaphore.WaitOne()
663            ar(idx) = dlgt(idx).BeginInvoke(page + idx, read, endPage + idx, gType, Nothing, Nothing)
664        Next
665        Dim rslt As String = ""
666        For idx As Integer = 0 To num
667            Dim trslt As String = ""
668            trslt = dlgt(idx).EndInvoke(ar(idx))
669            If trslt.Length > 0 AndAlso rslt.Length = 0 Then rslt = trslt
670        Next
671        Return rslt
672    End Function
673
674    Private Function GetDirectMessageThread(ByVal page As Integer, _
675                                    ByVal read As Boolean, _
676                                    ByVal endPage As Integer, _
677                                    ByVal gType As WORKERTYPE) As String
678        Try
679            If _endingFlag Then Return ""
680
681            Dim retMsg As String = ""
682            Dim resStatus As String = ""
683
684            _getDm = False
685            'endPage = page
686
687            If _signed = False Then
688                retMsg = SignIn()
689                If retMsg.Length > 0 Then
690                    Return retMsg
691                End If
692            End If
693
694            If _endingFlag Then Return ""
695
696            'リクエストメッセージを作成する
697            Dim pageQuery As String = _pageQry + page.ToString
698
699            If gType = WORKERTYPE.DirectMessegeRcv Then
700                retMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _DMPathRcv + pageQuery, resStatus), String)
701            Else
702                retMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _DMPathSnt + pageQuery, resStatus), String)
703            End If
704
705            If retMsg.Length = 0 Then
706                _signed = False
707                Return resStatus
708            End If
709
710            ' tr 要素の class 属性を消去
711            Do
712                Dim idx As Integer = retMsg.IndexOf("<tr class=""", StringComparison.Ordinal)
713                If idx = -1 Then Exit Do
714                retMsg = retMsg.Remove(idx + 4, retMsg.IndexOf("""", idx + 11 + 1, StringComparison.Ordinal) - idx - 2) ' 11 = "<tr class=""".Length
715            Loop
716
717            If _endingFlag Then Return ""
718
719            ''AuthKeyの取得
720            'If GetAuthKeyDM(retMsg) < 0 Then
721            '    _signed = False
722            '    Return "GetDirectMessage -> Err: Busy(1)"
723            'End If
724
725            Dim pos1 As Integer
726            Dim pos2 As Integer
727
728            ''Followerの抽出(Webのあて先リストがおかしいのでコメントアウト)
729            'If page = 1 And gType = GetTypes.GET_DMRCV Then
730            '    pos1 = retMsg.IndexOf(_followerList)
731            '    If pos1 = -1 Then
732            '        If follower.Count = 0 Then follower.Add(_uid)
733            '        '取得失敗
734            '        _signed = False
735            '        Return "GetDirectMessage -> Err: Busy(3)"
736            '    End If
737            '    follower.Clear()
738            '    follower.Add(_uid)
739            '    pos1 += _followerList.Length
740            '    pos1 = retMsg.IndexOf(_followerMbr1, pos1)
741            '    Try
742            '        Do While pos1 > -1
743            '            pos2 = retMsg.IndexOf(_followerMbr2, pos1)
744            '            pos1 = retMsg.IndexOf(_followerMbr3, pos2)
745            '            follower.Add(retMsg.Substring(pos2 + _followerMbr2.Length, pos1 - pos2 - _followerMbr2.Length))
746            '            pos1 = retMsg.IndexOf(_followerMbr1, pos1)
747            '        Loop
748            '        follower.RemoveAt(follower.Count - 1)
749            '    Catch ex As Exception
750            '        _signed = False
751            '        Return "GetDirectMessage -> Err: Can't get followers"
752            '    End Try
753            'End If
754
755            '各メッセージに分割可能か?
756            pos1 = retMsg.IndexOf(_splitDM, StringComparison.Ordinal)
757            If pos1 = -1 Then
758                '0件(メッセージなし。エラーの場合もありうるが判別できないので正常として戻す)
759                Return ""
760            End If
761
762            Dim strSep() As String = {_splitDM}
763            Dim posts() As String = retMsg.Split(strSep, StringSplitOptions.RemoveEmptyEntries)
764            Dim intCnt As Integer = 0   'カウンタ
765            Dim listCnt As Integer = 0
766            SyncLock LockObj
767                listCnt = links.Count
768            End SyncLock
769            Dim dlgt(20) As GetIconImageDelegate
770            Dim ar(20) As IAsyncResult
771            Dim arIdx As Integer = -1
772
773            For Each strPost As String In posts
774                intCnt += 1
775
776                If intCnt > 1 Then  '1件目はヘッダなので無視
777                    'Dim lItem As New MyListItem
778                    Dim post As New PostClass()
779
780                    'Get ID
781                    Try
782                        pos1 = 0
783                        pos2 = strPost.IndexOf("""", 0, StringComparison.Ordinal)
784                        post.Id = Long.Parse(HttpUtility.HtmlDecode(strPost.Substring(0, pos2)))
785                    Catch ex As Exception
786                        _signed = False
787                        TraceOut("DM-ID:" + strPost)
788                        Return "GetDirectMessage -> Err: Can't get ID"
789                    End Try
790
791                    'Get Name
792                    Try
793                        pos1 = strPost.IndexOf(_parseName, pos2, StringComparison.Ordinal)
794                        pos2 = strPost.IndexOf(_parseNameTo, pos1, StringComparison.Ordinal)
795                        post.Name = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseName.Length, pos2 - pos1 - _parseName.Length))
796                    Catch ex As Exception
797                        _signed = False
798                        TraceOut("DM-Name:" + strPost)
799                        Return "GetDirectMessage -> Err: Can't get Name"
800                    End Try
801
802                    'Get Nick
803                    Try
804                        pos1 = strPost.IndexOf(_parseNick, pos2, StringComparison.Ordinal)
805                        pos2 = strPost.IndexOf(_parseNickTo, pos1 + _parseNick.Length, StringComparison.Ordinal)
806                        post.Nickname = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseNick.Length, pos2 - pos1 - _parseNick.Length))
807                    Catch ex As Exception
808                        _signed = False
809                        TraceOut("DM-Nick:" + strPost)
810                        Return "GetDirectMessage -> Err: Can't get Nick."
811                    End Try
812
813                    SyncLock LockObj
814                        If links.Contains(post.Id) Then Continue For
815                    End SyncLock
816
817                    'Get ImagePath
818                    Try
819                        pos1 = strPost.IndexOf(_parseImg, pos2, StringComparison.Ordinal)
820                        pos2 = strPost.IndexOf(_parseImgTo, pos1 + _parseImg.Length, StringComparison.Ordinal)
821                        post.ImageUrl = HttpUtility.HtmlDecode(strPost.Substring(pos1 + _parseImg.Length, pos2 - pos1 - _parseImg.Length))
822                    Catch ex As Exception
823                        _signed = False
824                        TraceOut("DM-Img:" + strPost)
825                        Return "GetDirectMessage -> Err: Can't get ImagePath"
826                    End Try
827
828                    'Get Protect
829                    Try
830                        pos1 = strPost.IndexOf(_isProtect, pos2, StringComparison.Ordinal)
831                        If pos1 > -1 Then post.IsProtect = True
832                    Catch ex As Exception
833                        _signed = False
834                        TraceOut("DM-Protect:" + strPost)
835                        Return "GetDirectMessage -> Err: Can't get Protect"
836                    End Try
837
838                    Dim orgData As String = ""
839
840                    'Get Message
841                    Try
842                        pos1 = strPost.IndexOf(_parseDM1, pos2, StringComparison.Ordinal)
843                        If pos1 > -1 Then
844                            pos2 = strPost.IndexOf(_parseDM2, pos1, StringComparison.Ordinal)
845                            orgData = strPost.Substring(pos1 + _parseDM1.Length, pos2 - pos1 - _parseDM1.Length).Trim()
846                        Else
847                            pos1 = strPost.IndexOf(_parseDM11, pos2, StringComparison.Ordinal)
848                            pos2 = strPost.IndexOf(_parseDM2, pos1, StringComparison.Ordinal)
849                            orgData = strPost.Substring(pos1 + _parseDM11.Length, pos2 - pos1 - _parseDM11.Length).Trim()
850                        End If
851                        orgData = Regex.Replace(orgData, "<a href=""https://twitter\.com/" + post.Name + "/status/[0-9]+"">\.\.\.</a>$", "")
852                        orgData = orgData.Replace("&lt;3", "♡")
853                    Catch ex As Exception
854                        _signed = False
855                        TraceOut("DM-Body:" + strPost)
856                        Return "GetDirectMessage -> Err: Can't get body"
857                    End Try
858
859                    '短縮URL解決処理(orgData書き換え)
860                    orgData = ShortUrlResolve(orgData)
861
862                    '表示用にhtml整形
863                    post.OriginalData = AdjustHtml(orgData)
864
865                    '単純テキストの取り出し(リンクタグ除去)
866                    Try
867                        post.Data = GetPlainText(orgData)
868                    Catch ex As Exception
869                        _signed = False
870                        TraceOut("DM-Link:" + strPost)
871                        Return "GetDirectMessage -> Err: Can't parse links"
872                    End Try
873
874                    'Get Date
875                    Try
876                        pos1 = strPost.IndexOf(_parseDate, pos2, StringComparison.Ordinal)
877                        pos2 = strPost.IndexOf(_parseDateTo, pos1 + _parseDate.Length, StringComparison.Ordinal)
878                        post.PDate = DateTime.ParseExact(strPost.Substring(pos1 + _parseDate.Length, pos2 - pos1 - _parseDate.Length), "yyyy'-'MM'-'dd'T'HH':'mm':'sszzz", System.Globalization.DateTimeFormatInfo.InvariantInfo, Globalization.DateTimeStyles.None)
879                    Catch ex As Exception
880                        _signed = False
881                        TraceOut("DM-Date:" + strPost)
882                        Return "GetTimeline -> Err: Can't get date."
883                    End Try
884
885
886                    'Get Fav
887                    'pos1 = strPost.IndexOf(_parseStar, pos2)
888                    'pos2 = strPost.IndexOf("""", pos1 + _parseStar.Length)
889                    'If strPost.Substring(pos1 + _parseStar.Length, pos2 - pos1 - _parseStar.Length) = "empty" Then
890                    '    lItem.Fav = False
891                    'Else
892                    '    lItem.Fav = True
893                    'End If
894                    post.IsFav = False
895
896
897                    If _endingFlag Then Return ""
898
899                    SyncLock LockObj
900                        links.Add(post.Id)
901                    End SyncLock
902
903                    '受信DMかの判定で使用
904                    If gType = WORKERTYPE.DirectMessegeRcv Then
905                        post.IsOwl = False
906                    Else
907                        post.IsOwl = True
908                    End If
909
910                    post.IsRead = read
911                    post.IsDm = True
912
913                    'Imageの取得
914                    arIdx += 1
915                    dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
916                    ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
917                End If
918            Next
919
920            'For i As Integer = 0 To arIdx
921            '    dlgt(i).EndInvoke(ar(i))
922            'Next
923
924            Return ""
925
926        Finally
927            GetTmSemaphore.Release()
928        End Try
929    End Function
930
931    Private Function ShortUrlResolve(ByVal orgData As String) As String
932        If _tinyUrlResolve Then
933            For Each svc As String In _ShortUrlService
934                Dim posl1 As Integer
935                Dim posl2 As Integer = 0
936
937                Do While True
938                    If orgData.IndexOf("<a href=""" + svc, posl2, StringComparison.Ordinal) > -1 Then
939                        Dim urlStr As String = ""
940                        Try
941                            posl1 = orgData.IndexOf("<a href=""" + svc, posl2, StringComparison.Ordinal)
942                            posl1 = orgData.IndexOf(svc, posl1, StringComparison.Ordinal)
943                            posl2 = orgData.IndexOf("""", posl1, StringComparison.Ordinal)
944                            urlStr = orgData.Substring(posl1, posl2 - posl1)
945                            Dim Response As String = ""
946                            Dim retUrlStr As String = ""
947                            retUrlStr = DirectCast(CreateSocket.GetWebResponse(urlStr, Response, MySocket.REQ_TYPE.ReqGETForwardTo), String)
948                            If retUrlStr.Length > 0 Then
949                                If Not retUrlStr.StartsWith("http") Then Exit Do
950                                Dim uri As Uri = New Uri(retUrlStr)
951                                Dim sb As StringBuilder = New StringBuilder(uri.Scheme + uri.SchemeDelimiter + uri.Host + uri.AbsolutePath, 256)
952                                For Each c As Char In retUrlStr.Substring(sb.Length)
953                                    If Convert.ToInt32(c) > 127 Then
954                                        sb.Append("%" + Convert.ToInt16(c).ToString("X2"))
955                                    Else
956                                        sb.Append(c)
957                                    End If
958                                Next
959                                orgData = orgData.Replace("<a href=""" + urlStr, "<a href=""" + sb.ToString())
960                            End If
961                        Catch ex As Exception
962                            '_signed = False
963                            'Return "GetTimeline -> Err: Can't get tinyurl."
964                        End Try
965                    Else
966                        Exit Do
967                    End If
968                Loop
969            Next
970        End If
971        Return orgData
972    End Function
973
974    Private Function GetPlainText(ByVal orgData As String) As String
975        Dim retStr As String
976
977        '単純テキストの取り出し(リンクタグ除去)
978        If orgData.IndexOf(_parseLink1, StringComparison.Ordinal) = -1 Then
979            retStr = HttpUtility.HtmlDecode(orgData)
980        Else
981            Dim posl1 As Integer
982            Dim posl2 As Integer
983            Dim posl3 As Integer = 0
984
985            retStr = ""
986
987            posl3 = 0
988            Do While True
989                posl1 = orgData.IndexOf(_parseLink1, posl3, StringComparison.Ordinal)
990                If posl1 = -1 Then Exit Do
991
992                If (posl3 + _parseLink3.Length <> posl1) Or posl3 = 0 Then
993                    If posl3 <> 0 Then
994                        retStr += HttpUtility.HtmlDecode(orgData.Substring(posl3 + _parseLink3.Length, posl1 - posl3 - _parseLink3.Length))
995                    Else
996                        retStr += HttpUtility.HtmlDecode(orgData.Substring(0, posl1))
997                    End If
998                End If
999                posl2 = orgData.IndexOf(_parseLink2, posl1, StringComparison.Ordinal)
1000                posl3 = orgData.IndexOf(_parseLink3, posl2, StringComparison.Ordinal)
1001                retStr += HttpUtility.HtmlDecode(orgData.Substring(posl2 + _parseLink2.Length, posl3 - posl2 - _parseLink2.Length))
1002            Loop
1003            retStr += HttpUtility.HtmlDecode(orgData.Substring(posl3 + _parseLink3.Length))
1004        End If
1005
1006        Return retStr
1007    End Function
1008
1009    Private Function AdjustHtml(ByVal orgData As String) As String
1010        Dim retStr As String = orgData
1011        retStr = retStr.Replace("<a href=""/", "<a href=""https://twitter.com/")
1012        retStr = retStr.Replace("<a href=", "<a target=""_self"" href=")
1013        retStr = retStr.Replace(vbLf, "<br>")
1014        Return retStr
1015    End Function
1016
1017    Private Sub GetIconImage(ByVal post As PostClass)
1018        If _endingFlag Then Exit Sub
1019
1020        If Not _getIcon Then
1021            post.ImageIndex = -1
1022            TabInformations.GetInstance.AddPost(post)
1023            Exit Sub
1024        End If
1025
1026        Dim dlgt As New TweenMain.GetImageIndexDelegate(AddressOf _owner.GetImageIndex)
1027        post.ImageIndex = DirectCast(_owner.Invoke(dlgt, post), Integer)
1028        If post.ImageIndex > -1 Then
1029            TabInformations.GetInstance.AddPost(post)
1030            Exit Sub
1031        End If
1032
1033        Dim resStatus As String = ""
1034        Dim img As Image = DirectCast(CreateSocket.GetWebResponse(post.ImageUrl, resStatus, MySocket.REQ_TYPE.ReqGETBinary), System.Drawing.Image)
1035        If img Is Nothing Then
1036            post.ImageIndex = -1
1037            TabInformations.GetInstance.AddPost(post)
1038            Exit Sub
1039        End If
1040
1041        Dim bmp2 As New Bitmap(_iconSz, _iconSz)
1042        Using g As Graphics = Graphics.FromImage(bmp2)
1043            g.InterpolationMode = Drawing2D.InterpolationMode.High
1044            g.DrawImage(img, 0, 0, _iconSz, _iconSz)
1045        End Using
1046
1047        Dim dlgt2 As New TweenMain.SetImageDelegate(AddressOf _owner.SetImage)
1048        _owner.Invoke(dlgt2, New Object() {post, img, bmp2})
1049        TabInformations.GetInstance.AddPost(post)
1050    End Sub
1051
1052    Private Function GetAuthKey(ByVal resMsg As String) As Integer
1053        Dim pos1 As Integer
1054        Dim pos2 As Integer
1055
1056        pos1 = resMsg.IndexOf(_getAuthKey, StringComparison.Ordinal)
1057        If pos1 < 0 Then
1058            'データ不正?
1059            Return -7
1060        End If
1061        pos2 = resMsg.IndexOf(_getAuthKeyTo, pos1 + _getAuthKey.Length, StringComparison.Ordinal)
1062        If pos2 > -1 Then
1063            _authKey = resMsg.Substring(pos1 + _getAuthKey.Length, pos2 - pos1 - _getAuthKey.Length)
1064        Else
1065            Return -7
1066        End If
1067
1068        Return 0
1069    End Function
1070
1071    Private Function GetAuthKeyDM(ByVal resMsg As String) As Integer
1072        Dim pos1 As Integer
1073        Dim pos2 As Integer
1074
1075        pos1 = resMsg.IndexOf(_getAuthKey, StringComparison.Ordinal)
1076        If pos1 < 0 Then
1077            'データ不正?
1078            Return -7
1079        End If
1080        pos2 = resMsg.IndexOf("""", pos1 + _getAuthKey.Length, StringComparison.Ordinal)
1081        _authKeyDM = resMsg.Substring(pos1 + _getAuthKey.Length, pos2 - pos1 - _getAuthKey.Length)
1082
1083        Return 0
1084    End Function
1085
1086    Public Function PostStatus(ByVal postStr As String, ByVal reply_to As Long) As String
1087
1088        If _endingFlag Then Return ""
1089
1090        postStr = postStr.Trim()
1091
1092        'データ部分の生成
1093        Dim dataStr As String
1094        If reply_to = 0 Then
1095            dataStr = _statusHeader + HttpUtility.UrlEncode(postStr) + "&source=Tween"
1096        Else
1097            dataStr = _statusHeader + HttpUtility.UrlEncode(postStr) + "&source=Tween" + "&in_reply_to_status_id=" + HttpUtility.UrlEncode(reply_to.ToString)
1098        End If
1099
1100        Dim resStatus As String = ""
1101        Dim resMsg As String = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _statusUpdatePathAPI, resStatus, MySocket.REQ_TYPE.ReqPOSTAPI, dataStr), String)
1102
1103        If resStatus.StartsWith("OK") Then
1104            resStatus = Outputz.Post(CreateSocket, postStr.Length)
1105            If resStatus.Length > 0 Then
1106                Return "Outputz:" + resStatus
1107            Else
1108                Return ""
1109            End If
1110        Else
1111            Return resStatus
1112        End If
1113    End Function
1114
1115    Public Function RemoveStatus(ByVal id As Long) As String
1116        If _endingFlag Then Return ""
1117
1118        'データ部分の生成
1119        Dim resStatus As String = ""
1120        Dim resMsg As String = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _StDestroyPath + id.ToString + ".xml", resStatus, MySocket.REQ_TYPE.ReqPOSTAPI), String)
1121
1122        If resMsg.StartsWith("<?xml") = False OrElse resStatus.StartsWith("OK") = False Then
1123            Return resStatus
1124        End If
1125
1126        Return ""
1127    End Function
1128
1129    Public Function RemoveDirectMessage(ByVal id As Long) As String
1130        If _endingFlag Then Return ""
1131
1132        'データ部分の生成
1133        Dim dataStr As String = _authKeyHeader + HttpUtility.UrlEncode(_authKey)
1134        Dim resStatus As String = ""
1135        Dim resMsg As String = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _DMDestroyPath + id.ToString, resStatus, MySocket.REQ_TYPE.ReqPOSTEncodeProtoVer3, dataStr, "https://" + _baseUrlStr + _DMPathRcv), String)
1136
1137        If resMsg <> " " OrElse resStatus.StartsWith("OK") = False Then
1138            Return resStatus
1139        End If
1140
1141        Return ""
1142    End Function
1143
1144    ' Contributed by shuyoko <http://twitter.com/shuyoko> BEGIN:
1145    Public Function GetBlackFavId(ByVal id As Long, ByRef blackid As Long) As String
1146        Dim dataStr As String = _authKeyHeader + HttpUtility.UrlEncode(_authKey)
1147        Dim resStatus As String = ""
1148        Dim resMsg As String = DirectCast(CreateSocket.GetWebResponse("http://blavotter.hocha.org/blackfav/getblack.php?format=simple&id=" + id.ToString(), resStatus, MySocket.REQ_TYPE.ReqGET), String)
1149
1150        If resStatus.StartsWith("OK") = False Then
1151            Return resStatus
1152        End If
1153
1154        blackid = Long.Parse(resMsg)
1155
1156        Return ""
1157
1158    End Function
1159    ' Contributed by shuyoko <http://twitter.com/shuyoko> END.
1160
1161    Public Function PostFavAdd(ByVal id As Long) As String
1162        If _endingFlag Then Return ""
1163
1164        'データ部分の生成
1165        Dim dataStr As String = _authKeyHeader + HttpUtility.UrlEncode(_authKey)
1166        Dim resStatus As String = ""
1167        Dim resMsg As String = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _postFavAddPath + id.ToString(), resStatus, MySocket.REQ_TYPE.ReqPOSTEncodeProtoVer2, dataStr), String)
1168
1169        If resMsg.StartsWith("$") = False And resMsg <> " " Then
1170            Return resStatus
1171        End If
1172
1173        If _restrictFavCheck = False Then Return ""
1174
1175        'http://twitter.com/statuses/show/id.xml APIを発行して本文を取得
1176
1177        resMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _ShowStatus + id.ToString() + ".xml", resStatus, MySocket.REQ_TYPE.ReqPOSTEncodeProtoVer2), String)
1178
1179        Try
1180            Using rd As Xml.XmlTextReader = New Xml.XmlTextReader(New System.IO.StringReader(resMsg))
1181                rd.Read()
1182                While rd.EOF = False
1183                    If rd.IsStartElement("favorited") Then
1184                        If rd.ReadElementContentAsBoolean() = True Then
1185                            Return ""  '正常にふぁぼれている
1186                        Else
1187                            Return "NG(Restricted?)"  '正常応答なのにふぁぼれてないので制限っぽい
1188                        End If
1189                    Else
1190                        rd.Read()
1191                    End If
1192                End While
1193                rd.Close()
1194            End Using
1195        Catch ex As XmlException
1196            '
1197        End Try
1198
1199        Return ""
1200    End Function
1201
1202    Public Function PostFavRemove(ByVal id As Long) As String
1203        If _endingFlag Then Return ""
1204
1205        'データ部分の生成
1206        Dim dataStr As String = _authKeyHeader + HttpUtility.UrlEncode(_authKey)
1207        Dim resStatus As String = ""
1208        Dim resMsg As String = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _postFavRemovePath + id.ToString(), resStatus, MySocket.REQ_TYPE.ReqPOSTEncodeProtoVer2, dataStr), String)
1209
1210        If resMsg.StartsWith("$") = False And resMsg <> " " Then
1211            Return resStatus
1212        End If
1213
1214        Return ""
1215    End Function
1216
1217    Delegate Function GetFollowersDelegate(ByVal Query As Integer) As String
1218
1219    Private Function GetFollowersMethod(ByVal Query As Integer) As String
1220        Dim resStatus As String = ""
1221        Dim resMsg As String = ""
1222
1223        Try
1224            resMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _GetFollowers + _pageQry + Query.ToString, resStatus, MySocket.REQ_TYPE.ReqPOSTAPI), String)
1225            If resStatus.StartsWith("OK") = False Then
1226                IsThreadError = True
1227                Return resStatus
1228            End If
1229            Using rd As Xml.XmlTextReader = New Xml.XmlTextReader(New System.IO.StringReader(resMsg))
1230                Dim lc As Integer = 0
1231                rd.Read()
1232                While rd.EOF = False
1233                    If rd.IsStartElement("screen_name") Then
1234                        Dim tmp As String = rd.ReadElementString("screen_name").ToLower()
1235                        SyncLock LockObj
1236                            If Not follower.Contains(tmp) Then
1237                                follower.Add(tmp)
1238                            End If
1239                        End SyncLock
1240                        lc += 1
1241                    Else
1242                        rd.Read()
1243                    End If
1244                End While
1245            End Using
1246        Catch ex As XmlException
1247            IsThreadError = True
1248            TraceOut("NG(XmlException)")
1249            Return "NG(XmlException)"
1250        Catch ex As Exception
1251            IsThreadError = True
1252            ExceptionOut(ex)
1253            Return "NG OtherError:" + ex.Message
1254        End Try
1255
1256        Return ""
1257    End Function
1258
1259    Private _threadErr As Boolean = False
1260
1261    Private Property IsThreadError() As Boolean
1262        Get
1263            Return _threadErr
1264        End Get
1265        Set(ByVal value As Boolean)
1266            _threadErr = value
1267        End Set
1268    End Property
1269
1270    Private Sub GetFollowersCallback(ByVal ar As IAsyncResult)
1271        Dim dlgt As GetFollowersDelegate = DirectCast(ar.AsyncState, GetFollowersDelegate)
1272
1273        Try
1274            Dim ret As String = dlgt.EndInvoke(ar)
1275            If Not ret.Equals("") AndAlso Not IsThreadError Then
1276                TraceOut(ret)
1277                IsThreadError = True
1278            End If
1279        Catch ex As Exception
1280            ExceptionOut(ex)
1281        Finally
1282            semaphore.Release()                     ' セマフォから出る
1283            Interlocked.Decrement(threadNum)        ' スレッド数カウンタを-1
1284        End Try
1285
1286    End Sub
1287
1288    ' キャッシュの検証と読み込み -1を渡した場合は読み込みのみ行う(APIエラーでFollowersCountが取得できなかったとき)
1289
1290    Private Function ValidateCache(ByVal _FollowersCount As Integer) As Integer
1291        Dim CacheFileName As String = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "FollowersCache")
1292
1293        If Not File.Exists(CacheFileName) Then
1294            ' 存在しない場合はそのまま帰る
1295            Return _FollowersCount
1296        End If
1297
1298        Dim serializer As Xml.Serialization.XmlSerializer = New Xml.Serialization.XmlSerializer(follower.GetType())
1299
1300        Try
1301            Using fs As New IO.FileStream(CacheFileName, FileMode.Open)
1302                follower = CType(serializer.Deserialize(fs), Specialized.StringCollection)
1303            End Using
1304        Catch ex As XmlException
1305            ' 不正なxmlの場合は読み直し
1306            follower.Clear()
1307            follower.Add(_uid.ToLower())
1308            Return _FollowersCount
1309        End Try
1310
1311        If _FollowersCount = -1 Then Return follower.Count
1312
1313        If (_FollowersCount + 1) = follower.Count Then
1314            '変動がないので読み込みの必要なし
1315            Return 0
1316        ElseIf (_FollowersCount + 1) < follower.Count Then
1317            '減っている場合はどこが抜けているのかわからないので全部破棄して読み直し
1318            follower.Clear()
1319            follower.Add(_uid.ToLower())
1320            Return _FollowersCount
1321        End If
1322
1323        ' 増えた場合は差分だけ読む
1324
1325        Return _FollowersCount - follower.Count
1326
1327    End Function
1328
1329    Private Sub UpdateCache()
1330        Dim CacheFileName As String = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "FollowersCache")
1331
1332        Dim serializer As Xml.Serialization.XmlSerializer = New Xml.Serialization.XmlSerializer(follower.GetType())
1333
1334        Using fs As New IO.FileStream(CacheFileName, FileMode.Create)
1335            serializer.Serialize(fs, follower)
1336        End Using
1337
1338    End Sub
1339
1340    Private semaphore As Threading.Semaphore = Nothing
1341    Private threadNum As Integer = 0
1342
1343    Private Function doGetFollowers(ByVal CacheInvalidate As Boolean) As String
1344#If DEBUG Then
1345        Dim sw As New System.Diagnostics.Stopwatch
1346        sw.Start()
1347#End If
1348        Dim resStatus As String = ""
1349        Dim resMsg As String = ""
1350        Dim i As Integer = 0
1351        Dim DelegateInstance As GetFollowersDelegate = New GetFollowersDelegate(AddressOf GetFollowersMethod)
1352        Dim threadMax As Integer = 4            ' 最大スレッド数
1353        Dim followersCount As Integer = 0
1354
1355        Interlocked.Exchange(threadNum, 0)      ' スレッド数カウンタ初期化
1356        IsThreadError = False
1357        follower.Clear()
1358        follower.Add(_uid.ToLower())
1359
1360        resMsg = DirectCast(CreateSocket.GetWebResponse("https://twitter.com/users/show/" + _uid + ".xml", resStatus, MySocket.REQ_TYPE.ReqPOSTAPI), String)
1361        Dim xd As XmlDocument = New XmlDocument()
1362        Try
1363            xd.LoadXml(resMsg)
1364            followersCount = Integer.Parse(xd.SelectSingleNode("/user/followers_count/text()").Value)
1365        Catch ex As XmlException
1366            If CacheInvalidate OrElse ValidateCache(-1) < 0 Then
1367                ' FollowersカウントがAPIで取得できず、なおかつキャッシュから読めなかった
1368                Return "NG"
1369            Else
1370                'キャッシュを読み出せたのでキャッシュを使う
1371                Return ""
1372            End If
1373        End Try
1374
1375        Dim tmp As Integer
1376
1377        If CacheInvalidate Then
1378            tmp = followersCount
1379        Else
1380            tmp = ValidateCache(followersCount)
1381        End If
1382
1383
1384        If tmp <> 0 Then
1385            i = (tmp + 100) \ 100 - 1 ' Followersカウント取得しページ単位に切り上げる
1386        Else
1387            ' キャッシュの件数に変化がなかった
1388#If DEBUG Then
1389            sw.Stop()
1390            Console.WriteLine(sw.ElapsedMilliseconds)
1391#End If
1392            Return ""
1393        End If
1394
1395
1396        semaphore = New System.Threading.Semaphore(threadMax, threadMax) 'スレッド最大数
1397
1398        For cnt As Integer = 0 To i
1399            semaphore.WaitOne()                     'セマフォ取得 threadMax以上ならここでブロックされる
1400            Interlocked.Increment(threadNum)        'スレッド数カウンタを+1
1401            DelegateInstance.BeginInvoke(cnt + 1, New System.AsyncCallback(AddressOf GetFollowersCallback), DelegateInstance)
1402        Next
1403
1404        '全てのスレッドの終了を待つ(スレッド数カウンタが0になるまで待機)
1405        Do
1406            Thread.Sleep(50)
1407        Loop Until Interlocked.Add(threadNum, 0) = 0
1408
1409        semaphore.Close()
1410
1411        ' エラーが発生しているならFollowersリストクリア
1412
1413        If IsThreadError Then
1414            ' エラーが発生しているならFollowersリストクリア
1415            SyncLock LockObj
1416                follower.Clear()
1417                follower.Add(_uid.ToLower())
1418            End SyncLock
1419            Return "NG"
1420        End If
1421
1422        UpdateCache()
1423
1424#If DEBUG Then
1425        sw.Stop()
1426        Console.WriteLine(sw.ElapsedMilliseconds)
1427#End If
1428
1429        Return ""
1430    End Function
1431
1432    Public Function GetFollowers(ByVal CacheInvalidate As Boolean) As String
1433        Dim retMsg As String = ""
1434        If _signed = False Then
1435            retMsg = SignIn()
1436            If retMsg.Length > 0 Then
1437                Return retMsg
1438            End If
1439        End If
1440
1441        Return doGetFollowers(CacheInvalidate)
1442    End Function
1443
1444    Public Property Username() As String
1445        Get
1446            Return _uid
1447        End Get
1448        Set(ByVal value As String)
1449            _uid = value
1450        End Set
1451    End Property
1452
1453    Public Property Password() As String
1454        Get
1455            Return _pwd
1456        End Get
1457        Set(ByVal value As String)
1458            _pwd = value
1459        End Set
1460    End Property
1461
1462    Public Property NextThreshold() As Integer
1463        Get
1464            Return _nextThreshold
1465        End Get
1466        Set(ByVal value As Integer)
1467            _nextThreshold = value
1468        End Set
1469    End Property
1470
1471    Public Property NextPages() As Integer
1472        Get
1473            Return _nextPages
1474        End Get
1475        Set(ByVal value As Integer)
1476            _nextPages = value
1477        End Set
1478    End Property
1479
1480    Public Property Ending() As Boolean
1481        Get
1482            Return _endingFlag
1483        End Get
1484        Set(ByVal value As Boolean)
1485            _endingFlag = value
1486        End Set
1487    End Property
1488
1489    Public ReadOnly Property InfoTwitter() As String
1490        Get
1491            Return _infoTwitter
1492        End Get
1493    End Property
1494
1495    Public Property UseAPI() As Boolean
1496        Get
1497            Return _useAPI
1498        End Get
1499        Set(ByVal value As Boolean)
1500            _useAPI = value
1501        End Set
1502    End Property
1503
1504    Public Property HubServer() As String
1505        Get
1506            Return _hubServer
1507        End Get
1508        Set(ByVal value As String)
1509            _hubServer = value
1510        End Set
1511    End Property
1512
1513    Public Sub GetWedata()
1514        Dim resStatus As String = ""
1515        Dim resMsg As String = ""
1516
1517        resMsg = DirectCast(CreateSocket.GetWebResponse(wedataUrl, resStatus, timeOut:=10 * 1000), String) 'タイムアウト時間を10秒に設定
1518        If resMsg.Length = 0 Then Exit Sub
1519
1520        Dim rs As New System.IO.StringReader(resMsg)
1521
1522        Dim mode As Integer = 0 '0:search name 1:search data 2:read data
1523        Dim name As String = ""
1524
1525        'ストリームの末端まで繰り返す
1526        Dim ln As String
1527        While rs.Peek() > -1
1528            ln = rs.ReadLine
1529
1530            Select Case mode
1531                Case 0
1532                    If ln.StartsWith("    ""name"": ") Then
1533                        name = ln.Substring(13, ln.Length - 2 - 13)
1534                        mode += 1
1535                    End If
1536                Case 1
1537                    If ln = "    ""data"": {" Then
1538                        mode += 1
1539                    End If
1540                Case 2
1541                    If ln = "    }," Then
1542                        mode = 0
1543                    Else
1544                        If ln.EndsWith(",") Then ln = ln.Substring(0, ln.Length - 1)
1545                        Select Case name
1546                            Case "SplitPostReply"
1547                                If ln.StartsWith("      ""tagfrom"": """) Then
1548                                    _splitPost = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1549                                End If
1550                            Case "SplitPostRecent"
1551                                If ln.StartsWith("      ""tagfrom"": """) Then
1552                                    _splitPostRecent = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1553                                End If
1554                            Case "StatusID"
1555                                If ln.StartsWith("      ""tagto"": """) Then
1556                                    _statusIdTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1557                                End If
1558                            Case "IsProtect"
1559                                If ln.StartsWith("      ""tagfrom"": """) Then
1560                                    _isProtect = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1561                                End If
1562                            Case "IsReply"
1563                                If ln.StartsWith("      ""tagfrom"": """) Then
1564                                    _isReplyEng = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1565                                End If
1566                                If ln.StartsWith("      ""tagfrom2"": """) Then
1567                                    _isReplyJpn = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
1568                                End If
1569                                If ln.StartsWith("      ""tagto"": """) Then
1570                                    _isReplyTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1571                                End If
1572                            Case "GetStar"
1573                                If ln.StartsWith("      ""tagfrom"": """) Then
1574                                    _parseStar = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1575                                End If
1576                                If ln.StartsWith("      ""tagfrom2"": """) Then
1577                                    _parseStarEmpty = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
1578                                End If
1579                                If ln.StartsWith("      ""tagto"": """) Then
1580                                    _parseStarTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1581                                End If
1582                            Case "Follower"
1583                                If ln.StartsWith("      ""tagfrom"": """) Then
1584                                    _followerList = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1585                                End If
1586                                If ln.StartsWith("      ""tagfrom2"": """) Then
1587                                    _followerMbr1 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
1588                                End If
1589                                If ln.StartsWith("      ""tagfrom3"": """) Then
1590                                    _followerMbr2 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
1591                                End If
1592                                If ln.StartsWith("      ""tagto"": """) Then
1593                                    _followerMbr3 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1594                                End If
1595                            Case "SplitDM"
1596                                If ln.StartsWith("      ""tagfrom"": """) Then
1597                                    _splitDM = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1598                                End If
1599                            Case "GetMsgDM"
1600                                If ln.StartsWith("      ""tagfrom"": """) Then
1601                                    _parseDM1 = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1602                                End If
1603                                If ln.StartsWith("      ""tagfrom2"": """) Then
1604                                    _parseDM11 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
1605                                End If
1606                                If ln.StartsWith("      ""tagto"": """) Then
1607                                    _parseDM2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1608                                End If
1609                            Case "GetDate"
1610                                If ln.StartsWith("      ""tagfrom"": """) Then
1611                                    _parseDate = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1612                                End If
1613                                If ln.StartsWith("      ""tagto"": """) Then
1614                                    _parseDateTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1615                                End If
1616                            Case "GetMsg"
1617                                If ln.StartsWith("      ""tagfrom"": """) Then
1618                                    _parseMsg1 = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1619                                End If
1620                                If ln.StartsWith("      ""tagto"": """) Then
1621                                    _parseMsg2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1622                                End If
1623                            Case "GetImagePath"
1624                                If ln.StartsWith("      ""tagfrom"": """) Then
1625                                    _parseImg = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1626                                End If
1627                                If ln.StartsWith("      ""tagto"": """) Then
1628                                    _parseImgTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1629                                End If
1630                            Case "GetNick"
1631                                If ln.StartsWith("      ""tagfrom"": """) Then
1632                                    _parseNick = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1633                                End If
1634                                If ln.StartsWith("      ""tagto"": """) Then
1635                                    _parseNickTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1636                                End If
1637                            Case "GetName"
1638                                If ln.StartsWith("      ""tagfrom"": """) Then
1639                                    _parseName = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1640                                End If
1641                                If ln.StartsWith("      ""tagto"": """) Then
1642                                    _parseNameTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1643                                End If
1644                                'Case "GetSiv"
1645                                '    If ln.StartsWith("      ""tagfrom"": """) Then
1646                                '        _getSiv = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1647                                '    End If
1648                                '    If ln.StartsWith("      ""tagto"": """) Then
1649                                '        _getSivTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1650                                '    End If
1651                            Case "AuthKey"
1652                                If ln.StartsWith("      ""tagfrom"": """) Then
1653                                    _getAuthKey = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1654                                End If
1655                                If ln.StartsWith("      ""tagto"": """) Then
1656                                    _getAuthKeyTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1657                                End If
1658                            Case "InfoTwitter"
1659                                If ln.StartsWith("      ""tagfrom"": """) Then
1660                                    _getInfoTwitter = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1661                                End If
1662                                If ln.StartsWith("      ""tagto"": """) Then
1663                                    _getInfoTwitterTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1664                                End If
1665                            Case "GetProtectMsg"
1666                                If ln.StartsWith("      ""tagfrom"": """) Then
1667                                    _parseProtectMsg1 = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1668                                End If
1669                                If ln.StartsWith("      ""tagto"": """) Then
1670                                    _parseProtectMsg2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1671                                End If
1672                            Case "GetDMCount"
1673                                If ln.StartsWith("      ""tagfrom"": """) Then
1674                                    _parseDMcountFrom = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1675                                End If
1676                                If ln.StartsWith("      ""tagto"": """) Then
1677                                    _parseDMcountTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1678                                End If
1679                            Case "GetSource"
1680                                If ln.StartsWith("      ""tagfrom"": """) Then
1681                                    _parseSourceFrom = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1682                                End If
1683                                If ln.StartsWith("      ""tagfrom2"": """) Then
1684                                    _parseSource2 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
1685                                End If
1686                                If ln.StartsWith("      ""tagto"": """) Then
1687                                    _parseSource2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1688                                End If
1689                        End Select
1690                    End If
1691            End Select
1692        End While
1693
1694        rs.Close()
1695
1696#If DEBUG Then
1697        GenerateAnalyzeKey()
1698#End If
1699    End Sub
1700
1701    Public WriteOnly Property GetIcon() As Boolean
1702        Set(ByVal value As Boolean)
1703            _getIcon = value
1704        End Set
1705    End Property
1706
1707    Public WriteOnly Property TinyUrlResolve() As Boolean
1708        Set(ByVal value As Boolean)
1709            _tinyUrlResolve = value
1710        End Set
1711    End Property
1712
1713    Public WriteOnly Property ProxyType() As ProxyTypeEnum
1714        Set(ByVal value As ProxyTypeEnum)
1715            _proxyType = value
1716        End Set
1717    End Property
1718
1719    Public WriteOnly Property ProxyAddress() As String
1720        Set(ByVal value As String)
1721            _proxyAddress = value
1722        End Set
1723    End Property
1724
1725    Public WriteOnly Property ProxyPort() As Integer
1726        Set(ByVal value As Integer)
1727            _proxyPort = value
1728        End Set
1729    End Property
1730
1731    Public WriteOnly Property ProxyUser() As String
1732        Set(ByVal value As String)
1733            _proxyUser = value
1734        End Set
1735    End Property
1736
1737    Public WriteOnly Property ProxyPassword() As String
1738        Set(ByVal value As String)
1739            _proxyPassword = value
1740        End Set
1741    End Property
1742
1743    Public WriteOnly Property RestrictFavCheck() As Boolean
1744        Set(ByVal value As Boolean)
1745            _restrictFavCheck = value
1746        End Set
1747    End Property
1748
1749    Public WriteOnly Property IconSize() As Integer
1750        Set(ByVal value As Integer)
1751            _iconSz = value
1752        End Set
1753    End Property
1754
1755    Public Function MakeShortUrl(ByVal ConverterType As UrlConverter, ByVal SrcUrl As String) As String
1756        Dim ret As String = ""
1757        Dim resStatus As String = ""
1758
1759        For Each svc As String In _ShortUrlService
1760            If SrcUrl.StartsWith(svc) Then
1761                Return "Can't convert"
1762            End If
1763        Next
1764
1765        SrcUrl = HttpUtility.UrlEncode(SrcUrl)
1766        Select Case ConverterType
1767            Case UrlConverter.TinyUrl       'tinyurl
1768                If SrcUrl.StartsWith("http") Then
1769                    If SrcUrl.StartsWith("http://tinyurl.com/") Then
1770                        Return "Can't convert"
1771                    End If
1772                    Try
1773                        ret = DirectCast(CreateSocket.GetWebResponse("http://tinyurl.com/api-create.php?url=" + SrcUrl, resStatus, MySocket.REQ_TYPE.ReqPOSTEncode), String)
1774                    Catch ex As Exception
1775                        Return "Can't convert"
1776                    End Try
1777                End If
1778                If Not ret.StartsWith("http://tinyurl.com/") Then
1779                    Return "Can't convert"
1780                End If
1781            Case UrlConverter.Isgd
1782                If SrcUrl.StartsWith("http") Then
1783                    If SrcUrl.StartsWith("http://is.gd/") Then
1784                        Return "Can't convert"
1785                    End If
1786                    Try
1787                        ret = DirectCast(CreateSocket.GetWebResponse("http://is.gd/api.php?longurl=" + SrcUrl, resStatus, MySocket.REQ_TYPE.ReqPOSTEncode), String)
1788                    Catch ex As Exception
1789                        Return "Can't convert"
1790                    End Try
1791                End If
1792                If Not ret.StartsWith("http://is.gd/") Then
1793                    Return "Can't convert"
1794                End If
1795        End Select
1796
1797        Return ret
1798    End Function
1799
1800    Public Function GetVersionInfo() As String
1801        Dim resStatus As String = ""
1802        Return DirectCast(CreateSocket.GetWebResponse("http://tween.sourceforge.jp/version2.txt?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), resStatus), String)
1803    End Function
1804
1805    Public Function GetTweenBinary(ByVal strVer As String) As String
1806        Dim resStatus As String = ""
1807        Dim ret As String = ""
1808        ret = DirectCast(CreateSocket.GetWebResponse("http://tween.sourceforge.jp/Tween" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), resStatus, MySocket.REQ_TYPE.ReqGETFile), String)
1809        If ret.Length = 0 Then
1810            '取得OKなら、続いてresources.dllダウンロード
1811            Return GetTweenResourcesDll(strVer)
1812        Else
1813            Return ret
1814        End If
1815    End Function
1816
1817    Public Function GetTweenUpBinary() As String
1818        Dim resStatus As String = ""
1819        Return DirectCast(CreateSocket.GetWebResponse("http://tween.sourceforge.jp/TweenUp.gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), resStatus, MySocket.REQ_TYPE.ReqGETFileUp), String)
1820    End Function
1821
1822    Public Function GetTweenResourcesDll(ByVal strver As String) As String
1823        Dim resStatus As String = ""
1824        Return DirectCast(CreateSocket.GetWebResponse("http://tween.sourceforge.jp/TweenRes" + strver + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), resStatus, MySocket.REQ_TYPE.ReqGETFileRes), String)
1825    End Function
1826
1827    Private Function CreateSocket() As MySocket
1828        Return New MySocket("UTF-8", _uid, _pwd, _proxyType, _proxyAddress, _proxyPort, _proxyUser, _proxyPassword)
1829    End Function
1830
1831    Public WriteOnly Property Owner() As TweenMain
1832        Set(ByVal value As TweenMain)
1833            _owner = value
1834        End Set
1835    End Property
1836
1837#If DEBUG Then
1838    Public Sub GenerateAnalyzeKey()
1839        '解析キー情報部分のソースをwedataから作成する
1840        '生成したソースはプロジェクトのディレクトリにコピーする
1841        Dim sw As New System.IO.StreamWriter(".\AnalyzeKey.vb", _
1842            False, _
1843            System.Text.Encoding.UTF8)
1844
1845        sw.WriteLine("Public Module AnalyzeKey")
1846        sw.WriteLine("'    このファイルはデバッグビルドのTweenにより自動作成されました   作成日時  " + DateAndTime.Now.ToString())
1847        sw.WriteLine("")
1848
1849        sw.WriteLine("    Public _splitPost As String = " + Chr(34) + _splitPost.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1850        sw.WriteLine("    Public _splitPostRecent As String = " + Chr(34) + _splitPostRecent.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1851        sw.WriteLine("    Public _statusIdTo As String = " + Chr(34) + _statusIdTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1852        sw.WriteLine("    Public _splitDM As String = " + Chr(34) + _splitDM.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1853        sw.WriteLine("    Public _parseName As String = " + Chr(34) + _parseName.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1854        sw.WriteLine("    Public _parseNameTo As String = " + Chr(34) + _parseNameTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1855        sw.WriteLine("    Public _parseNick As String = " + Chr(34) + _parseNick.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1856        sw.WriteLine("    Public _parseNickTo As String = " + Chr(34) + _parseNickTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1857        sw.WriteLine("    Public _parseImg As String = " + Chr(34) + _parseImg.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1858        sw.WriteLine("    Public _parseImgTo As String = " + Chr(34) + _parseImgTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1859        sw.WriteLine("    Public _parseMsg1 As String = " + Chr(34) + _parseMsg1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1860        sw.WriteLine("    Public _parseMsg2 As String = " + Chr(34) + _parseMsg2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1861        sw.WriteLine("    Public _parseDM1 As String = " + Chr(34) + _parseDM1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1862        sw.WriteLine("    Public _parseDM11 As String = " + Chr(34) + _parseDM11.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1863        sw.WriteLine("    Public _parseDM2 As String = " + Chr(34) + _parseDM2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1864        sw.WriteLine("    Public _parseDate As String = " + Chr(34) + _parseDate.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1865        sw.WriteLine("    Public _parseDateTo As String = " + Chr(34) + _parseDateTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1866        sw.WriteLine("    Public _getAuthKey As String = " + Chr(34) + _getAuthKey.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1867        sw.WriteLine("    Public _getAuthKeyTo As String = " + Chr(34) + _getAuthKeyTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1868        sw.WriteLine("    Public _parseStar As String = " + Chr(34) + _parseStar.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1869        sw.WriteLine("    Public _parseStarTo As String = " + Chr(34) + _parseStarTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1870        sw.WriteLine("    Public _parseStarEmpty As String = " + Chr(34) + _parseStarEmpty.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1871        sw.WriteLine("    Public _followerList As String = " + Chr(34) + _followerList.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1872        sw.WriteLine("    Public _followerMbr1 As String = " + Chr(34) + _followerMbr1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1873        sw.WriteLine("    Public _followerMbr2 As String = " + Chr(34) + _followerMbr2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1874        sw.WriteLine("    Public _followerMbr3 As String = " + Chr(34) + _followerMbr3.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1875        sw.WriteLine("    Public _getInfoTwitter As String = " + Chr(34) + _getInfoTwitter.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1876        sw.WriteLine("    Public _getInfoTwitterTo As String = " + Chr(34) + _getInfoTwitterTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1877        sw.WriteLine("    Public _isProtect As String = " + Chr(34) + _isProtect.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1878        sw.WriteLine("    Public _isReplyEng As String = " + Chr(34) + _isReplyEng.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1879        sw.WriteLine("    Public _isReplyJpn As String = " + Chr(34) + _isReplyJpn.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1880        sw.WriteLine("    Public _isReplyTo As String = " + Chr(34) + _isReplyTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1881        sw.WriteLine("    Public _parseProtectMsg1 As String = " + Chr(34) + _parseProtectMsg1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1882        sw.WriteLine("    Public _parseProtectMsg2 As String = " + Chr(34) + _parseProtectMsg2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1883        sw.WriteLine("    Public _parseDMcountFrom As String = " + Chr(34) + _parseDMcountFrom.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1884        sw.WriteLine("    Public _parseDMcountTo As String = " + Chr(34) + _parseDMcountTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1885        sw.WriteLine("    Public _parseSourceFrom As String = " + Chr(34) + _parseSourceFrom.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1886        sw.WriteLine("    Public _parseSource2 As String = " + Chr(34) + _parseSource2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1887        sw.WriteLine("    Public _parseSourceTo As String = " + Chr(34) + _parseSourceTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1888        sw.WriteLine("End Module")
1889
1890        sw.Close()
1891        MessageBox.Show("解析キー情報定義ファイル AnalyzeKey.vbを生成しました")
1892
1893    End Sub
1894#End If
1895End Module
Note: See TracBrowser for help on using the browser.