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

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

ログ保存で落ちるバグ修正と終了時処理手直しその1

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        Try
1049            If Not _endingFlag Then _owner.Invoke(dlgt2, New Object() {post, img, bmp2})
1050        Catch ex As Exception
1051
1052        End Try
1053        TabInformations.GetInstance.AddPost(post)
1054    End Sub
1055
1056    Private Function GetAuthKey(ByVal resMsg As String) As Integer
1057        Dim pos1 As Integer
1058        Dim pos2 As Integer
1059
1060        pos1 = resMsg.IndexOf(_getAuthKey, StringComparison.Ordinal)
1061        If pos1 < 0 Then
1062            'データ不正?
1063            Return -7
1064        End If
1065        pos2 = resMsg.IndexOf(_getAuthKeyTo, pos1 + _getAuthKey.Length, StringComparison.Ordinal)
1066        If pos2 > -1 Then
1067            _authKey = resMsg.Substring(pos1 + _getAuthKey.Length, pos2 - pos1 - _getAuthKey.Length)
1068        Else
1069            Return -7
1070        End If
1071
1072        Return 0
1073    End Function
1074
1075    Private Function GetAuthKeyDM(ByVal resMsg As String) As Integer
1076        Dim pos1 As Integer
1077        Dim pos2 As Integer
1078
1079        pos1 = resMsg.IndexOf(_getAuthKey, StringComparison.Ordinal)
1080        If pos1 < 0 Then
1081            'データ不正?
1082            Return -7
1083        End If
1084        pos2 = resMsg.IndexOf("""", pos1 + _getAuthKey.Length, StringComparison.Ordinal)
1085        _authKeyDM = resMsg.Substring(pos1 + _getAuthKey.Length, pos2 - pos1 - _getAuthKey.Length)
1086
1087        Return 0
1088    End Function
1089
1090    Public Function PostStatus(ByVal postStr As String, ByVal reply_to As Long) As String
1091
1092        If _endingFlag Then Return ""
1093
1094        postStr = postStr.Trim()
1095
1096        'データ部分の生成
1097        Dim dataStr As String
1098        If reply_to = 0 Then
1099            dataStr = _statusHeader + HttpUtility.UrlEncode(postStr) + "&source=Tween"
1100        Else
1101            dataStr = _statusHeader + HttpUtility.UrlEncode(postStr) + "&source=Tween" + "&in_reply_to_status_id=" + HttpUtility.UrlEncode(reply_to.ToString)
1102        End If
1103
1104        Dim resStatus As String = ""
1105        Dim resMsg As String = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _statusUpdatePathAPI, resStatus, MySocket.REQ_TYPE.ReqPOSTAPI, dataStr), String)
1106
1107        If resStatus.StartsWith("OK") Then
1108            resStatus = Outputz.Post(CreateSocket, postStr.Length)
1109            If resStatus.Length > 0 Then
1110                Return "Outputz:" + resStatus
1111            Else
1112                Return ""
1113            End If
1114        Else
1115            Return resStatus
1116        End If
1117    End Function
1118
1119    Public Function RemoveStatus(ByVal id As Long) As String
1120        If _endingFlag Then Return ""
1121
1122        'データ部分の生成
1123        Dim resStatus As String = ""
1124        Dim resMsg As String = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _StDestroyPath + id.ToString + ".xml", resStatus, MySocket.REQ_TYPE.ReqPOSTAPI), String)
1125
1126        If resMsg.StartsWith("<?xml") = False OrElse resStatus.StartsWith("OK") = False Then
1127            Return resStatus
1128        End If
1129
1130        Return ""
1131    End Function
1132
1133    Public Function RemoveDirectMessage(ByVal id As Long) As String
1134        If _endingFlag Then Return ""
1135
1136        'データ部分の生成
1137        Dim dataStr As String = _authKeyHeader + HttpUtility.UrlEncode(_authKey)
1138        Dim resStatus As String = ""
1139        Dim resMsg As String = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _DMDestroyPath + id.ToString, resStatus, MySocket.REQ_TYPE.ReqPOSTEncodeProtoVer3, dataStr, "https://" + _baseUrlStr + _DMPathRcv), String)
1140
1141        If resMsg <> " " OrElse resStatus.StartsWith("OK") = False Then
1142            Return resStatus
1143        End If
1144
1145        Return ""
1146    End Function
1147
1148    ' Contributed by shuyoko <http://twitter.com/shuyoko> BEGIN:
1149    Public Function GetBlackFavId(ByVal id As Long, ByRef blackid As Long) As String
1150        Dim dataStr As String = _authKeyHeader + HttpUtility.UrlEncode(_authKey)
1151        Dim resStatus As String = ""
1152        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)
1153
1154        If resStatus.StartsWith("OK") = False Then
1155            Return resStatus
1156        End If
1157
1158        blackid = Long.Parse(resMsg)
1159
1160        Return ""
1161
1162    End Function
1163    ' Contributed by shuyoko <http://twitter.com/shuyoko> END.
1164
1165    Public Function PostFavAdd(ByVal id As Long) As String
1166        If _endingFlag Then Return ""
1167
1168        'データ部分の生成
1169        Dim dataStr As String = _authKeyHeader + HttpUtility.UrlEncode(_authKey)
1170        Dim resStatus As String = ""
1171        Dim resMsg As String = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _postFavAddPath + id.ToString(), resStatus, MySocket.REQ_TYPE.ReqPOSTEncodeProtoVer2, dataStr), String)
1172
1173        If resMsg.StartsWith("$") = False And resMsg <> " " Then
1174            Return resStatus
1175        End If
1176
1177        If _restrictFavCheck = False Then Return ""
1178
1179        'http://twitter.com/statuses/show/id.xml APIを発行して本文を取得
1180
1181        resMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _ShowStatus + id.ToString() + ".xml", resStatus, MySocket.REQ_TYPE.ReqPOSTEncodeProtoVer2), String)
1182
1183        Try
1184            Using rd As Xml.XmlTextReader = New Xml.XmlTextReader(New System.IO.StringReader(resMsg))
1185                rd.Read()
1186                While rd.EOF = False
1187                    If rd.IsStartElement("favorited") Then
1188                        If rd.ReadElementContentAsBoolean() = True Then
1189                            Return ""  '正常にふぁぼれている
1190                        Else
1191                            Return "NG(Restricted?)"  '正常応答なのにふぁぼれてないので制限っぽい
1192                        End If
1193                    Else
1194                        rd.Read()
1195                    End If
1196                End While
1197                rd.Close()
1198            End Using
1199        Catch ex As XmlException
1200            '
1201        End Try
1202
1203        Return ""
1204    End Function
1205
1206    Public Function PostFavRemove(ByVal id As Long) As String
1207        If _endingFlag Then Return ""
1208
1209        'データ部分の生成
1210        Dim dataStr As String = _authKeyHeader + HttpUtility.UrlEncode(_authKey)
1211        Dim resStatus As String = ""
1212        Dim resMsg As String = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _postFavRemovePath + id.ToString(), resStatus, MySocket.REQ_TYPE.ReqPOSTEncodeProtoVer2, dataStr), String)
1213
1214        If resMsg.StartsWith("$") = False And resMsg <> " " Then
1215            Return resStatus
1216        End If
1217
1218        Return ""
1219    End Function
1220
1221    Delegate Function GetFollowersDelegate(ByVal Query As Integer) As String
1222
1223    Private Function GetFollowersMethod(ByVal Query As Integer) As String
1224        Dim resStatus As String = ""
1225        Dim resMsg As String = ""
1226
1227        Try
1228            resMsg = DirectCast(CreateSocket.GetWebResponse("https://" + _hubServer + _GetFollowers + _pageQry + Query.ToString, resStatus, MySocket.REQ_TYPE.ReqPOSTAPI), String)
1229            If resStatus.StartsWith("OK") = False Then
1230                IsThreadError = True
1231                Return resStatus
1232            End If
1233            Using rd As Xml.XmlTextReader = New Xml.XmlTextReader(New System.IO.StringReader(resMsg))
1234                Dim lc As Integer = 0
1235                rd.Read()
1236                While rd.EOF = False
1237                    If rd.IsStartElement("screen_name") Then
1238                        Dim tmp As String = rd.ReadElementString("screen_name").ToLower()
1239                        SyncLock LockObj
1240                            If Not follower.Contains(tmp) Then
1241                                follower.Add(tmp)
1242                            End If
1243                        End SyncLock
1244                        lc += 1
1245                    Else
1246                        rd.Read()
1247                    End If
1248                End While
1249            End Using
1250        Catch ex As XmlException
1251            IsThreadError = True
1252            TraceOut("NG(XmlException)")
1253            Return "NG(XmlException)"
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            IsThreadError = True
1281            ExceptionOut(ex)
1282        Finally
1283            semaphore.Release()                     ' セマフォから出る
1284            Interlocked.Decrement(threadNum)        ' スレッド数カウンタを-1
1285        End Try
1286
1287    End Sub
1288
1289    ' キャッシュの検証と読み込み -1を渡した場合は読み込みのみ行う(APIエラーでFollowersCountが取得できなかったとき)
1290
1291    Private Function ValidateCache(ByVal _FollowersCount As Integer) As Integer
1292        Dim CacheFileName As String = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "FollowersCache")
1293
1294        If Not File.Exists(CacheFileName) Then
1295            ' 存在しない場合はそのまま帰る
1296            Return _FollowersCount
1297        End If
1298
1299        Dim serializer As Xml.Serialization.XmlSerializer = New Xml.Serialization.XmlSerializer(follower.GetType())
1300
1301        Try
1302            Using fs As New IO.FileStream(CacheFileName, FileMode.Open)
1303                follower = CType(serializer.Deserialize(fs), Specialized.StringCollection)
1304            End Using
1305        Catch ex As XmlException
1306            ' 不正なxmlの場合は読み直し
1307            follower.Clear()
1308            follower.Add(_uid.ToLower())
1309            Return _FollowersCount
1310        End Try
1311
1312        If _FollowersCount = -1 Then Return follower.Count
1313
1314        If (_FollowersCount + 1) = follower.Count Then
1315            '変動がないので読み込みの必要なし
1316            Return 0
1317        ElseIf (_FollowersCount + 1) < follower.Count Then
1318            '減っている場合はどこが抜けているのかわからないので全部破棄して読み直し
1319            follower.Clear()
1320            follower.Add(_uid.ToLower())
1321            Return _FollowersCount
1322        End If
1323
1324        ' 増えた場合は差分だけ読む
1325
1326        Return _FollowersCount - follower.Count
1327
1328    End Function
1329
1330    Private Sub UpdateCache()
1331        Dim CacheFileName As String = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "FollowersCache")
1332
1333        Dim serializer As Xml.Serialization.XmlSerializer = New Xml.Serialization.XmlSerializer(follower.GetType())
1334
1335        Using fs As New IO.FileStream(CacheFileName, FileMode.Create)
1336            serializer.Serialize(fs, follower)
1337        End Using
1338
1339    End Sub
1340
1341    Private semaphore As Threading.Semaphore = Nothing
1342    Private threadNum As Integer = 0
1343
1344    Private Function doGetFollowers(ByVal CacheInvalidate As Boolean) As String
1345#If DEBUG Then
1346        Dim sw As New System.Diagnostics.Stopwatch
1347        sw.Start()
1348#End If
1349        Dim resStatus As String = ""
1350        Dim resMsg As String = ""
1351        Dim i As Integer = 0
1352        Dim DelegateInstance As GetFollowersDelegate = New GetFollowersDelegate(AddressOf GetFollowersMethod)
1353        Dim threadMax As Integer = 4            ' 最大スレッド数
1354        Dim followersCount As Integer = 0
1355
1356        Interlocked.Exchange(threadNum, 0)      ' スレッド数カウンタ初期化
1357        IsThreadError = False
1358        follower.Clear()
1359        follower.Add(_uid.ToLower())
1360
1361        resMsg = DirectCast(CreateSocket.GetWebResponse("https://twitter.com/users/show/" + _uid + ".xml", resStatus, MySocket.REQ_TYPE.ReqPOSTAPI), String)
1362        Dim xd As XmlDocument = New XmlDocument()
1363        Try
1364            xd.LoadXml(resMsg)
1365            followersCount = Integer.Parse(xd.SelectSingleNode("/user/followers_count/text()").Value)
1366        Catch ex As XmlException
1367            If CacheInvalidate OrElse ValidateCache(-1) < 0 Then
1368                ' FollowersカウントがAPIで取得できず、なおかつキャッシュから読めなかった
1369                Return "NG"
1370            Else
1371                'キャッシュを読み出せたのでキャッシュを使う
1372                Return ""
1373            End If
1374        End Try
1375
1376        Dim tmp As Integer
1377
1378        If CacheInvalidate Then
1379            tmp = followersCount
1380        Else
1381            tmp = ValidateCache(followersCount)
1382        End If
1383
1384
1385        If tmp <> 0 Then
1386            i = (tmp + 100) \ 100 - 1 ' Followersカウント取得しページ単位に切り上げる
1387        Else
1388            ' キャッシュの件数に変化がなかった
1389#If DEBUG Then
1390            sw.Stop()
1391            Console.WriteLine(sw.ElapsedMilliseconds)
1392#End If
1393            Return ""
1394        End If
1395
1396
1397        semaphore = New System.Threading.Semaphore(threadMax, threadMax) 'スレッド最大数
1398
1399        For cnt As Integer = 0 To i
1400            semaphore.WaitOne()                     'セマフォ取得 threadMax以上ならここでブロックされる
1401            Interlocked.Increment(threadNum)        'スレッド数カウンタを+1
1402            DelegateInstance.BeginInvoke(cnt + 1, New System.AsyncCallback(AddressOf GetFollowersCallback), DelegateInstance)
1403        Next
1404
1405        '全てのスレッドの終了を待つ(スレッド数カウンタが0になるまで待機)
1406        Do
1407            Thread.Sleep(50)
1408        Loop Until Interlocked.Add(threadNum, 0) = 0
1409
1410        semaphore.Close()
1411
1412        ' エラーが発生しているならFollowersリストクリア
1413
1414        If IsThreadError Then
1415            ' エラーが発生しているならFollowersリストクリア
1416            SyncLock LockObj
1417                follower.Clear()
1418                follower.Add(_uid.ToLower())
1419            End SyncLock
1420            Return "NG"
1421        End If
1422
1423        UpdateCache()
1424
1425#If DEBUG Then
1426        sw.Stop()
1427        Console.WriteLine(sw.ElapsedMilliseconds)
1428#End If
1429
1430        Return ""
1431    End Function
1432
1433    Public Function GetFollowers(ByVal CacheInvalidate As Boolean) As String
1434        Dim retMsg As String = ""
1435        If _signed = False Then
1436            retMsg = SignIn()
1437            If retMsg.Length > 0 Then
1438                Return retMsg
1439            End If
1440        End If
1441
1442        Return doGetFollowers(CacheInvalidate)
1443    End Function
1444
1445    Public Property Username() As String
1446        Get
1447            Return _uid
1448        End Get
1449        Set(ByVal value As String)
1450            _uid = value
1451        End Set
1452    End Property
1453
1454    Public Property Password() As String
1455        Get
1456            Return _pwd
1457        End Get
1458        Set(ByVal value As String)
1459            _pwd = value
1460        End Set
1461    End Property
1462
1463    Public Property NextThreshold() As Integer
1464        Get
1465            Return _nextThreshold
1466        End Get
1467        Set(ByVal value As Integer)
1468            _nextThreshold = value
1469        End Set
1470    End Property
1471
1472    Public Property NextPages() As Integer
1473        Get
1474            Return _nextPages
1475        End Get
1476        Set(ByVal value As Integer)
1477            _nextPages = value
1478        End Set
1479    End Property
1480
1481    Public Property Ending() As Boolean
1482        Get
1483            Return _endingFlag
1484        End Get
1485        Set(ByVal value As Boolean)
1486            _endingFlag = value
1487        End Set
1488    End Property
1489
1490    Public ReadOnly Property InfoTwitter() As String
1491        Get
1492            Return _infoTwitter
1493        End Get
1494    End Property
1495
1496    Public Property UseAPI() As Boolean
1497        Get
1498            Return _useAPI
1499        End Get
1500        Set(ByVal value As Boolean)
1501            _useAPI = value
1502        End Set
1503    End Property
1504
1505    Public Property HubServer() As String
1506        Get
1507            Return _hubServer
1508        End Get
1509        Set(ByVal value As String)
1510            _hubServer = value
1511        End Set
1512    End Property
1513
1514    Public Sub GetWedata()
1515        Dim resStatus As String = ""
1516        Dim resMsg As String = ""
1517
1518        resMsg = DirectCast(CreateSocket.GetWebResponse(wedataUrl, resStatus, timeOut:=10 * 1000), String) 'タイムアウト時間を10秒に設定
1519        If resMsg.Length = 0 Then Exit Sub
1520
1521        Dim rs As New System.IO.StringReader(resMsg)
1522
1523        Dim mode As Integer = 0 '0:search name 1:search data 2:read data
1524        Dim name As String = ""
1525
1526        'ストリームの末端まで繰り返す
1527        Dim ln As String
1528        While rs.Peek() > -1
1529            ln = rs.ReadLine
1530
1531            Select Case mode
1532                Case 0
1533                    If ln.StartsWith("    ""name"": ") Then
1534                        name = ln.Substring(13, ln.Length - 2 - 13)
1535                        mode += 1
1536                    End If
1537                Case 1
1538                    If ln = "    ""data"": {" Then
1539                        mode += 1
1540                    End If
1541                Case 2
1542                    If ln = "    }," Then
1543                        mode = 0
1544                    Else
1545                        If ln.EndsWith(",") Then ln = ln.Substring(0, ln.Length - 1)
1546                        Select Case name
1547                            Case "SplitPostReply"
1548                                If ln.StartsWith("      ""tagfrom"": """) Then
1549                                    _splitPost = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1550                                End If
1551                            Case "SplitPostRecent"
1552                                If ln.StartsWith("      ""tagfrom"": """) Then
1553                                    _splitPostRecent = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1554                                End If
1555                            Case "StatusID"
1556                                If ln.StartsWith("      ""tagto"": """) Then
1557                                    _statusIdTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1558                                End If
1559                            Case "IsProtect"
1560                                If ln.StartsWith("      ""tagfrom"": """) Then
1561                                    _isProtect = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1562                                End If
1563                            Case "IsReply"
1564                                If ln.StartsWith("      ""tagfrom"": """) Then
1565                                    _isReplyEng = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1566                                End If
1567                                If ln.StartsWith("      ""tagfrom2"": """) Then
1568                                    _isReplyJpn = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
1569                                End If
1570                                If ln.StartsWith("      ""tagto"": """) Then
1571                                    _isReplyTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1572                                End If
1573                            Case "GetStar"
1574                                If ln.StartsWith("      ""tagfrom"": """) Then
1575                                    _parseStar = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1576                                End If
1577                                If ln.StartsWith("      ""tagfrom2"": """) Then
1578                                    _parseStarEmpty = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
1579                                End If
1580                                If ln.StartsWith("      ""tagto"": """) Then
1581                                    _parseStarTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1582                                End If
1583                            Case "Follower"
1584                                If ln.StartsWith("      ""tagfrom"": """) Then
1585                                    _followerList = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1586                                End If
1587                                If ln.StartsWith("      ""tagfrom2"": """) Then
1588                                    _followerMbr1 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
1589                                End If
1590                                If ln.StartsWith("      ""tagfrom3"": """) Then
1591                                    _followerMbr2 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
1592                                End If
1593                                If ln.StartsWith("      ""tagto"": """) Then
1594                                    _followerMbr3 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1595                                End If
1596                            Case "SplitDM"
1597                                If ln.StartsWith("      ""tagfrom"": """) Then
1598                                    _splitDM = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1599                                End If
1600                            Case "GetMsgDM"
1601                                If ln.StartsWith("      ""tagfrom"": """) Then
1602                                    _parseDM1 = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1603                                End If
1604                                If ln.StartsWith("      ""tagfrom2"": """) Then
1605                                    _parseDM11 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
1606                                End If
1607                                If ln.StartsWith("      ""tagto"": """) Then
1608                                    _parseDM2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1609                                End If
1610                            Case "GetDate"
1611                                If ln.StartsWith("      ""tagfrom"": """) Then
1612                                    _parseDate = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1613                                End If
1614                                If ln.StartsWith("      ""tagto"": """) Then
1615                                    _parseDateTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1616                                End If
1617                            Case "GetMsg"
1618                                If ln.StartsWith("      ""tagfrom"": """) Then
1619                                    _parseMsg1 = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1620                                End If
1621                                If ln.StartsWith("      ""tagto"": """) Then
1622                                    _parseMsg2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1623                                End If
1624                            Case "GetImagePath"
1625                                If ln.StartsWith("      ""tagfrom"": """) Then
1626                                    _parseImg = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1627                                End If
1628                                If ln.StartsWith("      ""tagto"": """) Then
1629                                    _parseImgTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1630                                End If
1631                            Case "GetNick"
1632                                If ln.StartsWith("      ""tagfrom"": """) Then
1633                                    _parseNick = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1634                                End If
1635                                If ln.StartsWith("      ""tagto"": """) Then
1636                                    _parseNickTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1637                                End If
1638                            Case "GetName"
1639                                If ln.StartsWith("      ""tagfrom"": """) Then
1640                                    _parseName = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1641                                End If
1642                                If ln.StartsWith("      ""tagto"": """) Then
1643                                    _parseNameTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1644                                End If
1645                                'Case "GetSiv"
1646                                '    If ln.StartsWith("      ""tagfrom"": """) Then
1647                                '        _getSiv = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1648                                '    End If
1649                                '    If ln.StartsWith("      ""tagto"": """) Then
1650                                '        _getSivTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1651                                '    End If
1652                            Case "AuthKey"
1653                                If ln.StartsWith("      ""tagfrom"": """) Then
1654                                    _getAuthKey = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1655                                End If
1656                                If ln.StartsWith("      ""tagto"": """) Then
1657                                    _getAuthKeyTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1658                                End If
1659                            Case "InfoTwitter"
1660                                If ln.StartsWith("      ""tagfrom"": """) Then
1661                                    _getInfoTwitter = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1662                                End If
1663                                If ln.StartsWith("      ""tagto"": """) Then
1664                                    _getInfoTwitterTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1665                                End If
1666                            Case "GetProtectMsg"
1667                                If ln.StartsWith("      ""tagfrom"": """) Then
1668                                    _parseProtectMsg1 = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1669                                End If
1670                                If ln.StartsWith("      ""tagto"": """) Then
1671                                    _parseProtectMsg2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1672                                End If
1673                            Case "GetDMCount"
1674                                If ln.StartsWith("      ""tagfrom"": """) Then
1675                                    _parseDMcountFrom = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1676                                End If
1677                                If ln.StartsWith("      ""tagto"": """) Then
1678                                    _parseDMcountTo = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1679                                End If
1680                            Case "GetSource"
1681                                If ln.StartsWith("      ""tagfrom"": """) Then
1682                                    _parseSourceFrom = ln.Substring(18, ln.Length - 1 - 18).Replace("\", "")
1683                                End If
1684                                If ln.StartsWith("      ""tagfrom2"": """) Then
1685                                    _parseSource2 = ln.Substring(19, ln.Length - 1 - 19).Replace("\", "")
1686                                End If
1687                                If ln.StartsWith("      ""tagto"": """) Then
1688                                    _parseSource2 = ln.Substring(16, ln.Length - 1 - 16).Replace("\", "")
1689                                End If
1690                        End Select
1691                    End If
1692            End Select
1693        End While
1694
1695        rs.Close()
1696
1697#If DEBUG Then
1698        GenerateAnalyzeKey()
1699#End If
1700    End Sub
1701
1702    Public WriteOnly Property GetIcon() As Boolean
1703        Set(ByVal value As Boolean)
1704            _getIcon = value
1705        End Set
1706    End Property
1707
1708    Public WriteOnly Property TinyUrlResolve() As Boolean
1709        Set(ByVal value As Boolean)
1710            _tinyUrlResolve = value
1711        End Set
1712    End Property
1713
1714    Public WriteOnly Property ProxyType() As ProxyTypeEnum
1715        Set(ByVal value As ProxyTypeEnum)
1716            _proxyType = value
1717        End Set
1718    End Property
1719
1720    Public WriteOnly Property ProxyAddress() As String
1721        Set(ByVal value As String)
1722            _proxyAddress = value
1723        End Set
1724    End Property
1725
1726    Public WriteOnly Property ProxyPort() As Integer
1727        Set(ByVal value As Integer)
1728            _proxyPort = value
1729        End Set
1730    End Property
1731
1732    Public WriteOnly Property ProxyUser() As String
1733        Set(ByVal value As String)
1734            _proxyUser = value
1735        End Set
1736    End Property
1737
1738    Public WriteOnly Property ProxyPassword() As String
1739        Set(ByVal value As String)
1740            _proxyPassword = value
1741        End Set
1742    End Property
1743
1744    Public WriteOnly Property RestrictFavCheck() As Boolean
1745        Set(ByVal value As Boolean)
1746            _restrictFavCheck = value
1747        End Set
1748    End Property
1749
1750    Public WriteOnly Property IconSize() As Integer
1751        Set(ByVal value As Integer)
1752            _iconSz = value
1753        End Set
1754    End Property
1755
1756    Public Function MakeShortUrl(ByVal ConverterType As UrlConverter, ByVal SrcUrl As String) As String
1757        Dim ret As String = ""
1758        Dim resStatus As String = ""
1759
1760        For Each svc As String In _ShortUrlService
1761            If SrcUrl.StartsWith(svc) Then
1762                Return "Can't convert"
1763            End If
1764        Next
1765
1766        SrcUrl = HttpUtility.UrlEncode(SrcUrl)
1767        Select Case ConverterType
1768            Case UrlConverter.TinyUrl       'tinyurl
1769                If SrcUrl.StartsWith("http") Then
1770                    If SrcUrl.StartsWith("http://tinyurl.com/") Then
1771                        Return "Can't convert"
1772                    End If
1773                    Try
1774                        ret = DirectCast(CreateSocket.GetWebResponse("http://tinyurl.com/api-create.php?url=" + SrcUrl, resStatus, MySocket.REQ_TYPE.ReqPOSTEncode), String)
1775                    Catch ex As Exception
1776                        Return "Can't convert"
1777                    End Try
1778                End If
1779                If Not ret.StartsWith("http://tinyurl.com/") Then
1780                    Return "Can't convert"
1781                End If
1782            Case UrlConverter.Isgd
1783                If SrcUrl.StartsWith("http") Then
1784                    If SrcUrl.StartsWith("http://is.gd/") Then
1785                        Return "Can't convert"
1786                    End If
1787                    Try
1788                        ret = DirectCast(CreateSocket.GetWebResponse("http://is.gd/api.php?longurl=" + SrcUrl, resStatus, MySocket.REQ_TYPE.ReqPOSTEncode), String)
1789                    Catch ex As Exception
1790                        Return "Can't convert"
1791                    End Try
1792                End If
1793                If Not ret.StartsWith("http://is.gd/") Then
1794                    Return "Can't convert"
1795                End If
1796        End Select
1797
1798        Return ret
1799    End Function
1800
1801    Public Function GetVersionInfo() As String
1802        Dim resStatus As String = ""
1803        Return DirectCast(CreateSocket.GetWebResponse("http://tween.sourceforge.jp/version2.txt?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), resStatus), String)
1804    End Function
1805
1806    Public Function GetTweenBinary(ByVal strVer As String) As String
1807        Dim resStatus As String = ""
1808        Dim ret As String = ""
1809        ret = DirectCast(CreateSocket.GetWebResponse("http://tween.sourceforge.jp/Tween" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), resStatus, MySocket.REQ_TYPE.ReqGETFile), String)
1810        If ret.Length = 0 Then
1811            '取得OKなら、続いてresources.dllダウンロード
1812            Return GetTweenResourcesDll(strVer)
1813        Else
1814            Return ret
1815        End If
1816    End Function
1817
1818    Public Function GetTweenUpBinary() As String
1819        Dim resStatus As String = ""
1820        Return DirectCast(CreateSocket.GetWebResponse("http://tween.sourceforge.jp/TweenUp.gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), resStatus, MySocket.REQ_TYPE.ReqGETFileUp), String)
1821    End Function
1822
1823    Public Function GetTweenResourcesDll(ByVal strver As String) As String
1824        Dim resStatus As String = ""
1825        Return DirectCast(CreateSocket.GetWebResponse("http://tween.sourceforge.jp/TweenRes" + strver + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), resStatus, MySocket.REQ_TYPE.ReqGETFileRes), String)
1826    End Function
1827
1828    Private Function CreateSocket() As MySocket
1829        Return New MySocket("UTF-8", _uid, _pwd, _proxyType, _proxyAddress, _proxyPort, _proxyUser, _proxyPassword)
1830    End Function
1831
1832    Public WriteOnly Property Owner() As TweenMain
1833        Set(ByVal value As TweenMain)
1834            _owner = value
1835        End Set
1836    End Property
1837
1838#If DEBUG Then
1839    Public Sub GenerateAnalyzeKey()
1840        '解析キー情報部分のソースをwedataから作成する
1841        '生成したソースはプロジェクトのディレクトリにコピーする
1842        Dim sw As New System.IO.StreamWriter(".\AnalyzeKey.vb", _
1843            False, _
1844            System.Text.Encoding.UTF8)
1845
1846        sw.WriteLine("Public Module AnalyzeKey")
1847        sw.WriteLine("'    このファイルはデバッグビルドのTweenにより自動作成されました   作成日時  " + DateAndTime.Now.ToString())
1848        sw.WriteLine("")
1849
1850        sw.WriteLine("    Public _splitPost As String = " + Chr(34) + _splitPost.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1851        sw.WriteLine("    Public _splitPostRecent As String = " + Chr(34) + _splitPostRecent.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1852        sw.WriteLine("    Public _statusIdTo As String = " + Chr(34) + _statusIdTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1853        sw.WriteLine("    Public _splitDM As String = " + Chr(34) + _splitDM.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1854        sw.WriteLine("    Public _parseName As String = " + Chr(34) + _parseName.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1855        sw.WriteLine("    Public _parseNameTo As String = " + Chr(34) + _parseNameTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1856        sw.WriteLine("    Public _parseNick As String = " + Chr(34) + _parseNick.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1857        sw.WriteLine("    Public _parseNickTo As String = " + Chr(34) + _parseNickTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1858        sw.WriteLine("    Public _parseImg As String = " + Chr(34) + _parseImg.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1859        sw.WriteLine("    Public _parseImgTo As String = " + Chr(34) + _parseImgTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1860        sw.WriteLine("    Public _parseMsg1 As String = " + Chr(34) + _parseMsg1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1861        sw.WriteLine("    Public _parseMsg2 As String = " + Chr(34) + _parseMsg2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1862        sw.WriteLine("    Public _parseDM1 As String = " + Chr(34) + _parseDM1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1863        sw.WriteLine("    Public _parseDM11 As String = " + Chr(34) + _parseDM11.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1864        sw.WriteLine("    Public _parseDM2 As String = " + Chr(34) + _parseDM2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1865        sw.WriteLine("    Public _parseDate As String = " + Chr(34) + _parseDate.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1866        sw.WriteLine("    Public _parseDateTo As String = " + Chr(34) + _parseDateTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1867        sw.WriteLine("    Public _getAuthKey As String = " + Chr(34) + _getAuthKey.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1868        sw.WriteLine("    Public _getAuthKeyTo As String = " + Chr(34) + _getAuthKeyTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1869        sw.WriteLine("    Public _parseStar As String = " + Chr(34) + _parseStar.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1870        sw.WriteLine("    Public _parseStarTo As String = " + Chr(34) + _parseStarTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1871        sw.WriteLine("    Public _parseStarEmpty As String = " + Chr(34) + _parseStarEmpty.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1872        sw.WriteLine("    Public _followerList As String = " + Chr(34) + _followerList.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1873        sw.WriteLine("    Public _followerMbr1 As String = " + Chr(34) + _followerMbr1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1874        sw.WriteLine("    Public _followerMbr2 As String = " + Chr(34) + _followerMbr2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1875        sw.WriteLine("    Public _followerMbr3 As String = " + Chr(34) + _followerMbr3.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1876        sw.WriteLine("    Public _getInfoTwitter As String = " + Chr(34) + _getInfoTwitter.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1877        sw.WriteLine("    Public _getInfoTwitterTo As String = " + Chr(34) + _getInfoTwitterTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1878        sw.WriteLine("    Public _isProtect As String = " + Chr(34) + _isProtect.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1879        sw.WriteLine("    Public _isReplyEng As String = " + Chr(34) + _isReplyEng.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1880        sw.WriteLine("    Public _isReplyJpn As String = " + Chr(34) + _isReplyJpn.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1881        sw.WriteLine("    Public _isReplyTo As String = " + Chr(34) + _isReplyTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1882        sw.WriteLine("    Public _parseProtectMsg1 As String = " + Chr(34) + _parseProtectMsg1.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1883        sw.WriteLine("    Public _parseProtectMsg2 As String = " + Chr(34) + _parseProtectMsg2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1884        sw.WriteLine("    Public _parseDMcountFrom As String = " + Chr(34) + _parseDMcountFrom.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1885        sw.WriteLine("    Public _parseDMcountTo As String = " + Chr(34) + _parseDMcountTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1886        sw.WriteLine("    Public _parseSourceFrom As String = " + Chr(34) + _parseSourceFrom.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1887        sw.WriteLine("    Public _parseSource2 As String = " + Chr(34) + _parseSource2.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1888        sw.WriteLine("    Public _parseSourceTo As String = " + Chr(34) + _parseSourceTo.Replace(Chr(34), Chr(34) + Chr(34)) + Chr(34))
1889        sw.WriteLine("End Module")
1890
1891        sw.Close()
1892        MessageBox.Show("解析キー情報定義ファイル AnalyzeKey.vbを生成しました")
1893
1894    End Sub
1895#End If
1896End Module
Note: See TracBrowser for help on using the browser.