OSDN Git Service

DM日付形式変更はTwitter側不具合だったため、rev1097の変更を取り消し
[opentween/open-tween.git] / Tween / Twitter.vb
1 ' Tween - Client of Twitter
2 ' Copyright (c) 2007-2010 kiri_feather (@kiri_feather) <kiri_feather@gmail.com>
3 '           (c) 2008-2010 Moz (@syo68k) <http://iddy.jp/profile/moz/>
4 '           (c) 2008-2010 takeshik (@takeshik) <http://www.takeshik.org/>
5 ' All rights reserved.
6
7 ' This file is part of Tween.
8
9 ' This program is free software; you can redistribute it and/or modify it
10 ' under the terms of the GNU General Public License as published by the Free
11 ' Software Foundation; either version 3 of the License, or (at your option)
12 ' any later version.
13
14 ' This program is distributed in the hope that it will be useful, but
15 ' WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 ' or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 ' for more details. 
18
19 ' You should have received a copy of the GNU General Public License along
20 ' with this program. If not, see <http://www.gnu.org/licenses/>, or write to
21 ' the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
22 ' Boston, MA 02110-1301, USA.
23
24 Imports System.Web
25 Imports System.Xml
26 Imports System.Text
27 Imports System.Threading
28 Imports System.IO
29 Imports System.Text.RegularExpressions
30 Imports System.Globalization
31 Imports System.Diagnostics
32 Imports System.Net
33 Imports System.Reflection
34 Imports System.Reflection.MethodBase
35
36
37 Public Class Twitter
38     Delegate Sub GetIconImageDelegate(ByVal post As PostClass)
39     Private ReadOnly LockObj As New Object
40     Private followerId As New List(Of Long)
41     Private _GetFollowerResult As Boolean = False
42
43     Private _followersCount As Integer = 0
44     Private _friendsCount As Integer = 0
45     Private _statusesCount As Integer = 0
46     Private _location As String = ""
47     Private _bio As String = ""
48     Private _userinfoxml As String = ""
49     Private _protocol As String = "https://"
50
51     'プロパティからアクセスされる共通情報
52     Private _uid As String
53     Private _iconSz As Integer
54     Private _getIcon As Boolean
55     Private _dIcon As IDictionary(Of String, Image)
56
57     Private _tinyUrlResolve As Boolean
58     Private _restrictFavCheck As Boolean
59
60     Private _hubServer As String
61     'Private _countApi As Integer
62     'Private _countApiReply As Integer
63     Private _readOwnPost As Boolean
64     Private _hashList As New List(Of String)
65
66     '共通で使用する状態
67     Private _remainCountApi As Integer = -1
68
69     Private op As New Outputz
70     'max_idで古い発言を取得するために保持(lists分は個別タブで管理)
71     Private minHomeTimeline As Long = Long.MaxValue
72     Private minMentions As Long = Long.MaxValue
73     Private minDirectmessage As Long = Long.MaxValue
74     Private minDirectmessageSent As Long = Long.MaxValue
75
76     Private twCon As New HttpTwitter
77
78     Public Function Authenticate(ByVal username As String, ByVal password As String) As String
79
80         Dim res As HttpStatusCode
81         Dim content As String = ""
82
83         TwitterApiInfo.Initialize()
84         Try
85             res = twCon.AuthUserAndPass(username, password)
86         Catch ex As Exception
87             Return "Err:" + ex.Message
88         End Try
89
90         Select Case res
91             Case HttpStatusCode.OK
92                 Twitter.AccountState = ACCOUNT_STATE.Valid
93                 _uid = username.ToLower
94                 Return ""
95             Case HttpStatusCode.Unauthorized
96                 Twitter.AccountState = ACCOUNT_STATE.Invalid
97                 Return "Check your Username/Password."
98             Case HttpStatusCode.Forbidden
99                 Dim xd As XmlDocument = New XmlDocument
100                 Try
101                     xd.LoadXml(content)
102                     Dim xNode As XmlNode = Nothing
103                     xNode = xd.SelectSingleNode("/hash/error")
104                     Return "Err:" + xNode.InnerText
105                 Catch ex As Exception
106                     Return "Err:Forbidden"
107                 End Try
108             Case Else
109                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
110         End Select
111
112     End Function
113
114     Public Sub ClearAuthInfo()
115         Twitter.AccountState = ACCOUNT_STATE.Invalid
116         twCon.ClearAuthInfo()
117         _UserIdNo = ""
118     End Sub
119
120     Public Sub Initialize(ByVal token As String, ByVal tokenSecret As String, ByVal username As String)
121         'xAuth認証
122         If String.IsNullOrEmpty(token) OrElse String.IsNullOrEmpty(tokenSecret) OrElse String.IsNullOrEmpty(username) Then
123             Twitter.AccountState = ACCOUNT_STATE.Invalid
124         End If
125         TwitterApiInfo.Initialize()
126         twCon.Initialize(token, tokenSecret, username)
127         _uid = username.ToLower
128         _UserIdNo = ""
129     End Sub
130
131     Public Sub Initialize(ByVal username As String, ByVal password As String)
132         'BASIC認証
133         If String.IsNullOrEmpty(username) OrElse String.IsNullOrEmpty(password) Then
134             Twitter.AccountState = ACCOUNT_STATE.Invalid
135         End If
136         TwitterApiInfo.Initialize()
137         twCon.Initialize(username, password)
138         _uid = username.ToLower
139         _UserIdNo = ""
140     End Sub
141
142     Public Function PreProcessUrl(ByVal orgData As String) As String
143         Dim posl1 As Integer
144         Dim posl2 As Integer = 0
145         'Dim IDNConveter As IdnMapping = New IdnMapping()
146         Dim href As String = "<a href="""
147
148         Do While True
149             If orgData.IndexOf(href, posl2, StringComparison.Ordinal) > -1 Then
150                 Dim urlStr As String = ""
151                 ' IDN展開
152                 posl1 = orgData.IndexOf(href, posl2, StringComparison.Ordinal)
153                 posl1 += href.Length
154                 posl2 = orgData.IndexOf("""", posl1, StringComparison.Ordinal)
155                 urlStr = orgData.Substring(posl1, posl2 - posl1)
156
157                 If Not urlStr.StartsWith("http://") AndAlso Not urlStr.StartsWith("https://") AndAlso Not urlStr.StartsWith("ftp://") Then
158                     Continue Do
159                 End If
160
161                 Dim replacedUrl As String = IDNDecode(urlStr)
162                 If replacedUrl Is Nothing Then Continue Do
163                 If replacedUrl = urlStr Then Continue Do
164
165                 orgData = orgData.Replace("<a href=""" + urlStr, "<a href=""" + replacedUrl)
166                 posl2 = 0
167             Else
168                 Exit Do
169             End If
170         Loop
171         Return orgData
172     End Function
173
174     Private Function GetPlainText(ByVal orgData As String) As String
175         Return HttpUtility.HtmlDecode(Regex.Replace(orgData, "(?<tagStart><a [^>]+>)(?<text>[^<]+)(?<tagEnd></a>)", "${text}"))
176     End Function
177
178     ' htmlの簡易サニタイズ(詳細表示に不要なタグの除去)
179
180     Private Function SanitizeHtml(ByVal orgdata As String) As String
181         Dim retdata As String = orgdata
182
183         retdata = Regex.Replace(retdata, "<(script|object|applet|image|frameset|fieldset|legend|style).*" & _
184             "</(script|object|applet|image|frameset|fieldset|legend|style)>", "", RegexOptions.IgnoreCase)
185
186         retdata = Regex.Replace(retdata, "<(frame|link|iframe|img)>", "", RegexOptions.IgnoreCase)
187
188         Return retdata
189     End Function
190
191     Private Function AdjustHtml(ByVal orgData As String) As String
192         Dim retStr As String = orgData
193         Dim m As Match = Regex.Match(retStr, "<a [^>]+>[#|#](?<1>[a-zA-Z0-9_]+)</a>")
194         While m.Success
195             SyncLock LockObj
196                 _hashList.Add("#" + m.Groups(1).Value)
197             End SyncLock
198             m = m.NextMatch
199         End While
200         retStr = Regex.Replace(retStr, "<a [^>]*href=""/", "<a href=""" + _protocol + "twitter.com/")
201         retStr = retStr.Replace("<a href=", "<a target=""_self"" href=")
202         retStr = retStr.Replace(vbLf, "<br>")
203
204         '半角スペースを置換(Thanks @anis774)
205         Dim ret As Boolean = False
206         Do
207             ret = EscapeSpace(retStr)
208         Loop While Not ret
209
210         Return SanitizeHtml(retStr)
211     End Function
212
213     Private Function EscapeSpace(ByRef html As String) As Boolean
214         '半角スペースを置換(Thanks @anis774)
215         Dim isTag As Boolean = False
216         For i As Integer = 0 To html.Length - 1
217             If html(i) = "<"c Then
218                 isTag = True
219             End If
220             If html(i) = ">"c Then
221                 isTag = False
222             End If
223
224             If (Not isTag) AndAlso (html(i) = " "c) Then
225                 html = html.Remove(i, 1)
226                 html = html.Insert(i, "&nbsp;")
227                 Return False
228             End If
229         Next
230         Return True
231     End Function
232
233     Private Sub GetIconImage(ByVal post As PostClass)
234         Dim img As Image
235
236         Try
237             If Not _getIcon Then
238                 post.ImageUrl = Nothing
239                 TabInformations.GetInstance.AddPost(post)
240                 Exit Sub
241             End If
242
243             If _dIcon.ContainsKey(post.ImageUrl) Then
244                 TabInformations.GetInstance.AddPost(post)
245                 Exit Sub
246             End If
247
248             Dim httpVar As New HttpVarious
249             img = httpVar.GetIconImage(post.ImageUrl, 10000)
250             If img Is Nothing Then
251                 TabInformations.GetInstance.AddPost(post)
252                 Exit Sub
253             End If
254
255             If _endingFlag Then Exit Sub
256
257             SyncLock LockObj
258                 If Not _dIcon.ContainsKey(post.ImageUrl) Then
259                     Try
260                         _dIcon.Add(post.ImageUrl, img)
261                     Catch ex As InvalidOperationException
262                         'タイミングにより追加できない場合がある?(キー重複ではない)
263                     Catch ex As System.OverflowException
264                         '不正なアイコン?DrawImageに失敗する場合あり
265                     Catch ex As OutOfMemoryException
266                         'DrawImageで発生
267                     End Try
268                 End If
269             End SyncLock
270             TabInformations.GetInstance.AddPost(post)
271         Catch ex As ArgumentException
272             'タイミングによってはキー重複
273         Finally
274             img = Nothing
275             post = Nothing
276         End Try
277     End Sub
278
279     Private Structure PostInfo
280         Public CreatedAt As String
281         Public Id As String
282         Public Text As String
283         Public UserId As String
284         Public Sub New(ByVal Created As String, ByVal IdStr As String, ByVal txt As String, ByVal uid As String)
285             CreatedAt = Created
286             Id = IdStr
287             Text = txt
288             UserId = uid
289         End Sub
290         Public Shadows Function Equals(ByVal dst As PostInfo) As Boolean
291             If Me.CreatedAt = dst.CreatedAt AndAlso Me.Id = dst.Id AndAlso Me.Text = dst.Text AndAlso Me.UserId = dst.UserId Then
292                 Return True
293             Else
294                 Return False
295             End If
296         End Function
297     End Structure
298
299     Private Function IsPostRestricted(ByRef resMsg As String) As Boolean
300         Static _prev As New PostInfo("", "", "", "")
301         Dim _current As New PostInfo("", "", "", "")
302
303
304         Dim xd As XmlDocument = New XmlDocument()
305         Try
306             xd.LoadXml(resMsg)
307             _current.CreatedAt = xd.SelectSingleNode("/status/created_at/text()").Value
308             _current.Id = xd.SelectSingleNode("/status/id/text()").Value
309             If xd.SelectSingleNode("/status/text/text()") Is Nothing Then
310                 '制御文字のみ投稿した場合はNothing
311                 _current.Text = ""
312             Else
313                 _current.Text = xd.SelectSingleNode("/status/text/text()").Value
314             End If
315             _current.UserId = xd.SelectSingleNode("/status/user/id/text()").Value
316
317             If _current.Equals(_prev) Then
318                 Return True
319             End If
320             _prev.CreatedAt = _current.CreatedAt
321             _prev.Id = _current.Id
322             _prev.Text = _current.Text
323             _prev.UserId = _current.UserId
324         Catch ex As XmlException
325             Return False
326         End Try
327
328         Return False
329     End Function
330
331     Public Function PostStatus(ByVal postStr As String, ByVal reply_to As Long) As String
332
333         If _endingFlag Then Return ""
334
335         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
336
337         postStr = postStr.Trim()
338
339         If Regex.Match(postStr, "^DM? +(?<id>[a-zA-Z0-9_]+) +(?<body>.+)", RegexOptions.IgnoreCase Or RegexOptions.Singleline).Success Then
340             Return SendDirectMessage(postStr)
341         End If
342
343         Dim res As HttpStatusCode
344         Dim content As String = ""
345         Try
346             res = twCon.UpdateStatus(postStr, reply_to, content)
347         Catch ex As Exception
348             Return "Err:" + ex.Message
349         End Try
350
351         Select Case res
352             Case HttpStatusCode.OK
353                 Twitter.AccountState = ACCOUNT_STATE.Valid
354                 Dim xd As XmlDocument = New XmlDocument()
355                 Try
356                     xd.LoadXml(content)
357                     Dim xNode As XmlNode = Nothing
358                     xNode = xd.SelectSingleNode("/status/user/followers_count/text()")
359                     If xNode IsNot Nothing Then _followersCount = Integer.Parse(xNode.Value)
360                     xNode = xd.SelectSingleNode("/status/user/friends_count/text()")
361                     If xNode IsNot Nothing Then _friendsCount = Integer.Parse(xNode.Value)
362                     xNode = xd.SelectSingleNode("/status/user/statuses_count/text()")
363                     If xNode IsNot Nothing Then _statusesCount = Integer.Parse(xNode.Value)
364                     xNode = xd.SelectSingleNode("/status/user/location/text()")
365                     If xNode IsNot Nothing Then _location = xNode.Value
366                     xNode = xd.SelectSingleNode("/status/user/description/text()")
367                     If xNode IsNot Nothing Then _bio = xNode.Value
368                     xNode = xd.SelectSingleNode("/status/user/id/text()")
369                     If xNode IsNot Nothing Then _UserIdNo = xNode.Value
370
371                     _userinfoxml = String.Copy(content)
372                 Catch ex As Exception
373                     _userinfoxml = ""
374                     Return ""
375                 End Try
376
377                 If Not postStr.StartsWith("D ", StringComparison.OrdinalIgnoreCase) AndAlso _
378                         Not postStr.StartsWith("DM ", StringComparison.OrdinalIgnoreCase) AndAlso _
379                         IsPostRestricted(content) Then
380                     Return "OK:Delaying?"
381                 End If
382                 If op.Post(postStr.Length) Then
383                     Return ""
384                 Else
385                     Return "Outputz:Failed"
386                 End If
387             Case HttpStatusCode.Forbidden, HttpStatusCode.BadRequest
388                 Dim xd As XmlDocument = New XmlDocument
389                 Try
390                     xd.LoadXml(content)
391                     Dim xNode As XmlNode = Nothing
392                     xNode = xd.SelectSingleNode("/hash/error")
393                     Return "Warn:" + xNode.InnerText
394                 Catch ex As Exception
395                 End Try
396                 Return "Warn:" + res.ToString
397             Case HttpStatusCode.Conflict, _
398                 HttpStatusCode.ExpectationFailed, _
399                 HttpStatusCode.Gone, _
400                 HttpStatusCode.LengthRequired, _
401                 HttpStatusCode.MethodNotAllowed, _
402                 HttpStatusCode.NotAcceptable, _
403                 HttpStatusCode.NotFound, _
404                 HttpStatusCode.PaymentRequired, _
405                 HttpStatusCode.PreconditionFailed, _
406                 HttpStatusCode.RequestedRangeNotSatisfiable, _
407                 HttpStatusCode.RequestEntityTooLarge, _
408                 HttpStatusCode.RequestTimeout, _
409                 HttpStatusCode.RequestUriTooLong
410                 '仕様書にない400系エラー。サーバまでは到達しているのでリトライしない
411                 Return "Warn:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
412             Case HttpStatusCode.Unauthorized
413                 Twitter.AccountState = ACCOUNT_STATE.Invalid
414                 Return "Check your Username/Password."
415             Case Else
416                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
417         End Select
418     End Function
419
420     Public Function SendDirectMessage(ByVal postStr As String) As String
421
422         If _endingFlag Then Return ""
423
424         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
425
426         postStr = postStr.Trim()
427
428         Dim res As HttpStatusCode
429         Dim content As String = ""
430
431         Dim mc As Match = Regex.Match(postStr, "^DM? +(?<id>[a-zA-Z0-9_]+) +(?<body>.+)", RegexOptions.IgnoreCase Or RegexOptions.Singleline)
432
433         Try
434             res = twCon.SendDirectMessage(mc.Groups("body").Value, mc.Groups("id").Value, content)
435         Catch ex As Exception
436             Return "Err:" + ex.Message
437         End Try
438
439         Select Case res
440             Case HttpStatusCode.OK
441                 Twitter.AccountState = ACCOUNT_STATE.Valid
442                 Dim xd As XmlDocument = New XmlDocument()
443                 Try
444                     xd.LoadXml(content)
445                     Dim xNode As XmlNode = Nothing
446                     xNode = xd.SelectSingleNode("/status/user/followers_count/text()")
447                     If xNode IsNot Nothing Then _followersCount = Integer.Parse(xNode.Value)
448                     xNode = xd.SelectSingleNode("/status/user/friends_count/text()")
449                     If xNode IsNot Nothing Then _friendsCount = Integer.Parse(xNode.Value)
450                     xNode = xd.SelectSingleNode("/status/user/statuses_count/text()")
451                     If xNode IsNot Nothing Then _statusesCount = Integer.Parse(xNode.Value)
452                     xNode = xd.SelectSingleNode("/status/user/location/text()")
453                     If xNode IsNot Nothing Then _location = xNode.Value
454                     xNode = xd.SelectSingleNode("/status/user/description/text()")
455                     If xNode IsNot Nothing Then _bio = xNode.Value
456                     xNode = xd.SelectSingleNode("/status/user/id/text()")
457                     If xNode IsNot Nothing Then _userIdNo = xNode.Value
458                 Catch ex As Exception
459                     Return ""
460                 End Try
461
462                 If op.Post(postStr.Length) Then
463                     Return ""
464                 Else
465                     Return "Outputz:Failed"
466                 End If
467             Case HttpStatusCode.Forbidden, HttpStatusCode.BadRequest
468                 Dim xd As XmlDocument = New XmlDocument
469                 Try
470                     xd.LoadXml(content)
471                     Dim xNode As XmlNode = Nothing
472                     xNode = xd.SelectSingleNode("/hash/error")
473                     Return "Warn:" + xNode.InnerText
474                 Catch ex As Exception
475                 End Try
476                 Return "Warn:" + res.ToString
477             Case HttpStatusCode.Conflict, _
478                 HttpStatusCode.ExpectationFailed, _
479                 HttpStatusCode.Gone, _
480                 HttpStatusCode.LengthRequired, _
481                 HttpStatusCode.MethodNotAllowed, _
482                 HttpStatusCode.NotAcceptable, _
483                 HttpStatusCode.NotFound, _
484                 HttpStatusCode.PaymentRequired, _
485                 HttpStatusCode.PreconditionFailed, _
486                 HttpStatusCode.RequestedRangeNotSatisfiable, _
487                 HttpStatusCode.RequestEntityTooLarge, _
488                 HttpStatusCode.RequestTimeout, _
489                 HttpStatusCode.RequestUriTooLong
490                 '仕様書にない400系エラー。サーバまでは到達しているのでリトライしない
491                 Return "Warn:" + res.ToString
492             Case HttpStatusCode.Unauthorized
493                 Twitter.AccountState = ACCOUNT_STATE.Invalid
494                 Return "Check your Username/Password."
495             Case Else
496                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
497         End Select
498     End Function
499
500     Public Function RemoveStatus(ByVal id As Long) As String
501         If _endingFlag Then Return ""
502
503         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
504
505         Dim res As HttpStatusCode
506
507         Try
508             res = twCon.DestroyStatus(id)
509         Catch ex As Exception
510             Return "Err:" + ex.Message
511         End Try
512
513         Select Case res
514             Case HttpStatusCode.OK
515                 Twitter.AccountState = ACCOUNT_STATE.Valid
516                 Return ""
517             Case HttpStatusCode.Unauthorized
518                 Twitter.AccountState = ACCOUNT_STATE.Invalid
519                 Return "Check your Username/Password."
520             Case HttpStatusCode.NotFound
521                 Return ""
522             Case Else
523                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
524         End Select
525
526     End Function
527
528     Public Function PostRetweet(ByVal id As Long, ByVal read As Boolean) As String
529         If _endingFlag Then Return ""
530         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
531
532         'データ部分の生成
533         Dim target As Long = id
534         If TabInformations.GetInstance.Item(id).RetweetedId > 0 Then
535             target = TabInformations.GetInstance.Item(id).RetweetedId '再RTの場合は元発言をRT
536         End If
537
538         Dim res As HttpStatusCode
539         Dim content As String = ""
540         Try
541             res = twCon.RetweetStatus(target, content)
542         Catch ex As Exception
543             Return "Err:" + ex.Message
544         End Try
545
546         Select Case res
547             Case HttpStatusCode.Unauthorized
548                 Twitter.AccountState = ACCOUNT_STATE.Invalid
549                 Return "Check your Username/Password."
550             Case Is <> HttpStatusCode.OK
551                 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
552         End Select
553
554         Twitter.AccountState = ACCOUNT_STATE.Valid
555
556         Dim dlgt As GetIconImageDelegate    'countQueryに合わせる
557         Dim ar As IAsyncResult              'countQueryに合わせる
558         Dim xdoc As New XmlDocument
559         Try
560             xdoc.LoadXml(content)
561         Catch ex As Exception
562             TraceOut(content)
563             'MessageBox.Show("不正なXMLです。(TL-LoadXml)")
564             Return "Invalid XML!"
565         End Try
566
567         'ReTweetしたものをTLに追加
568         Dim xentryNode As XmlNode = xdoc.DocumentElement.SelectSingleNode("/status")
569         If xentryNode Is Nothing Then Return "Invalid XML!"
570         Dim xentry As XmlElement = CType(xentryNode, XmlElement)
571         Dim post As New PostClass
572         Try
573             post.Id = Long.Parse(xentry.Item("id").InnerText)
574             '二重取得回避
575             SyncLock LockObj
576                 If TabInformations.GetInstance.ContainsKey(post.Id) Then Return ""
577             End SyncLock
578             'Retweet判定
579             Dim xRnode As XmlNode = xentry.SelectSingleNode("./retweeted_status")
580             If xRnode Is Nothing Then Return "Invalid XML!"
581
582             Dim xRentry As XmlElement = CType(xRnode, XmlElement)
583             post.PDate = DateTime.ParseExact(xRentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
584             'Id
585             post.RetweetedId = Long.Parse(xRentry.Item("id").InnerText)
586             '本文
587             post.Data = xRentry.Item("text").InnerText
588             'Source取得(htmlの場合は、中身を取り出し)
589             post.Source = xRentry.Item("source").InnerText
590             'Reply先
591             Long.TryParse(xRentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
592             post.InReplyToUser = xRentry.Item("in_reply_to_screen_name").InnerText
593             post.IsFav = TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.RetweetedId)
594
595             '以下、ユーザー情報
596             Dim xRUentry As XmlElement = CType(xRentry.SelectSingleNode("./user"), XmlElement)
597             post.Uid = Long.Parse(xRUentry.Item("id").InnerText)
598             post.Name = xRUentry.Item("screen_name").InnerText
599             post.Nickname = xRUentry.Item("name").InnerText
600             post.ImageUrl = xRUentry.Item("profile_image_url").InnerText
601             post.IsProtect = Boolean.Parse(xRUentry.Item("protected").InnerText)
602             post.IsMe = True
603
604             'Retweetした人(自分のはず)
605             Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
606             post.RetweetedBy = xUentry.Item("screen_name").InnerText
607
608             'HTMLに整形
609             post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
610             post.Data = HttpUtility.HtmlDecode(post.Data)
611             post.Data = post.Data.Replace("<3", "♡")
612             'Source整形
613             CreateSource(post)
614
615             post.IsRead = read
616             post.IsReply = post.ReplyToList.Contains(_uid)
617             post.IsExcludeReply = False
618
619             If post.IsMe Then
620                 post.IsOwl = False
621             Else
622                 If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.Uid)
623             End If
624             If post.IsMe AndAlso _readOwnPost Then post.IsRead = True
625
626             post.IsDm = False
627         Catch ex As Exception
628             TraceOut(content)
629             'MessageBox.Show("不正なXMLです。(TL-Parse)")
630             Return "Invalid XML!"
631         End Try
632
633         '非同期アイコン取得&StatusDictionaryに追加
634         dlgt = New GetIconImageDelegate(AddressOf GetIconImage)
635         ar = dlgt.BeginInvoke(post, Nothing, Nothing)
636
637         'アイコン取得完了待ち
638         Try
639             dlgt.EndInvoke(ar)
640         Catch ex As Exception
641             '最後までendinvoke回す(ゾンビ化回避)
642             ex.Data("IsTerminatePermission") = False
643             Throw
644         End Try
645
646         Return ""
647     End Function
648
649     Public Function RemoveDirectMessage(ByVal id As Long) As String
650         If _endingFlag Then Return ""
651
652         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
653
654         Dim res As HttpStatusCode
655
656         Try
657             res = twCon.DestroyDirectMessage(id)
658         Catch ex As Exception
659             Return "Err:" + ex.Message
660         End Try
661
662         Select Case res
663             Case HttpStatusCode.OK
664                 Twitter.AccountState = ACCOUNT_STATE.Valid
665                 Return ""
666             Case HttpStatusCode.Unauthorized
667                 Twitter.AccountState = ACCOUNT_STATE.Invalid
668                 Return "Check your Username/Password."
669             Case HttpStatusCode.NotFound
670                 Return ""
671             Case Else
672                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
673         End Select
674     End Function
675
676     Public Function PostFollowCommand(ByVal screenName As String) As String
677
678         If _endingFlag Then Return ""
679
680         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
681
682         Dim res As HttpStatusCode
683         Dim content As String = ""
684
685         Try
686             res = twCon.CreateFriendships(screenName, content)
687         Catch ex As Exception
688             Return "Err:" + ex.Message
689         End Try
690
691         Select Case res
692             Case HttpStatusCode.OK
693                 Twitter.AccountState = ACCOUNT_STATE.Valid
694                 Return ""
695             Case HttpStatusCode.Unauthorized
696                 Twitter.AccountState = ACCOUNT_STATE.Invalid
697                 Return "Check your Username/Password."
698             Case HttpStatusCode.Forbidden
699                 Dim xd As XmlDocument = New XmlDocument
700                 Try
701                     xd.LoadXml(content)
702                     Dim xNode As XmlNode = Nothing
703                     xNode = xd.SelectSingleNode("/hash/error")
704                     Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
705                 Catch ex As Exception
706                     Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
707                 End Try
708             Case Else
709                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
710         End Select
711     End Function
712
713     Public Function PostRemoveCommand(ByVal screenName As String) As String
714
715         If _endingFlag Then Return ""
716
717         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
718
719         Dim res As HttpStatusCode
720         Dim content As String = ""
721
722         Try
723             res = twCon.DestroyFriendships(screenName, content)
724         Catch ex As Exception
725             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
726         End Try
727
728         Select Case res
729             Case HttpStatusCode.OK
730                 Twitter.AccountState = ACCOUNT_STATE.Valid
731                 Return ""
732             Case HttpStatusCode.Unauthorized
733                 Twitter.AccountState = ACCOUNT_STATE.Invalid
734                 Return "Check your Username/Password."
735             Case HttpStatusCode.Forbidden
736                 Dim xd As XmlDocument = New XmlDocument
737                 Try
738                     xd.LoadXml(content)
739                     Dim xNode As XmlNode = Nothing
740                     xNode = xd.SelectSingleNode("/hash/error")
741                     Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
742                 Catch ex As Exception
743                     Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
744                 End Try
745             Case Else
746                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
747         End Select
748     End Function
749
750     Public Function PostCreateBlock(ByVal screenName As String) As String
751
752         If _endingFlag Then Return ""
753
754         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
755
756         Dim res As HttpStatusCode
757         Dim content As String = ""
758
759         Try
760             res = twCon.CreateBlock(screenName, content)
761         Catch ex As Exception
762             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
763         End Try
764
765         Select Case res
766             Case HttpStatusCode.OK
767                 Twitter.AccountState = ACCOUNT_STATE.Valid
768                 Return ""
769             Case HttpStatusCode.Unauthorized
770                 Twitter.AccountState = ACCOUNT_STATE.Invalid
771                 Return "Check your Username/Password."
772             Case HttpStatusCode.Forbidden
773                 Dim xd As XmlDocument = New XmlDocument
774                 Try
775                     xd.LoadXml(content)
776                     Dim xNode As XmlNode = Nothing
777                     xNode = xd.SelectSingleNode("/hash/error")
778                     Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
779                 Catch ex As Exception
780                     Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
781                 End Try
782             Case Else
783                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
784         End Select
785     End Function
786
787     Public Function PostDestroyBlock(ByVal screenName As String) As String
788
789         If _endingFlag Then Return ""
790
791         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
792
793         Dim res As HttpStatusCode
794         Dim content As String = ""
795
796         Try
797             res = twCon.DestroyBlock(screenName, content)
798         Catch ex As Exception
799             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
800         End Try
801
802         Select Case res
803             Case HttpStatusCode.OK
804                 Twitter.AccountState = ACCOUNT_STATE.Valid
805                 Return ""
806             Case HttpStatusCode.Unauthorized
807                 Twitter.AccountState = ACCOUNT_STATE.Invalid
808                 Return "Check your Username/Password."
809             Case HttpStatusCode.Forbidden
810                 Dim xd As XmlDocument = New XmlDocument
811                 Try
812                     xd.LoadXml(content)
813                     Dim xNode As XmlNode = Nothing
814                     xNode = xd.SelectSingleNode("/hash/error")
815                     Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
816                 Catch ex As Exception
817                     Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
818                 End Try
819             Case Else
820                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
821         End Select
822     End Function
823
824     Public Function PostReportSpam(ByVal screenName As String) As String
825
826         If _endingFlag Then Return ""
827
828         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
829
830         Dim res As HttpStatusCode
831         Dim content As String = ""
832
833         Try
834             res = twCon.ReportSpam(screenName, content)
835         Catch ex As Exception
836             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
837         End Try
838
839         Select Case res
840             Case HttpStatusCode.OK
841                 Twitter.AccountState = ACCOUNT_STATE.Valid
842                 Return ""
843             Case HttpStatusCode.Unauthorized
844                 Twitter.AccountState = ACCOUNT_STATE.Invalid
845                 Return "Check your Username/Password."
846             Case HttpStatusCode.Forbidden
847                 Dim xd As XmlDocument = New XmlDocument
848                 Try
849                     xd.LoadXml(content)
850                     Dim xNode As XmlNode = Nothing
851                     xNode = xd.SelectSingleNode("/hash/error")
852                     Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
853                 Catch ex As Exception
854                     Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
855                 End Try
856             Case Else
857                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
858         End Select
859     End Function
860
861     Public Function GetFriendshipInfo(ByVal screenName As String, ByRef isFollowing As Boolean, ByRef isFollowed As Boolean) As String
862
863         If _endingFlag Then Return ""
864
865         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
866
867         Dim res As HttpStatusCode
868         Dim content As String = ""
869         Try
870             res = twCon.ShowFriendships(_uid, screenName, content)
871         Catch ex As Exception
872             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
873         End Try
874
875         Select Case res
876             Case HttpStatusCode.OK
877                 Dim xdoc As New XmlDocument
878                 Dim result As String = ""
879                 Twitter.AccountState = ACCOUNT_STATE.Valid
880                 Try
881                     xdoc.LoadXml(content)
882                     isFollowing = Boolean.Parse(xdoc.SelectSingleNode("/relationship/source/following").InnerText)
883                     isFollowed = Boolean.Parse(xdoc.SelectSingleNode("/relationship/source/followed_by").InnerText)
884                 Catch ex As Exception
885                     result = "Err:Invalid XML."
886                 End Try
887                 Return result
888             Case HttpStatusCode.BadRequest
889                 Return "Err:API Limits?"
890             Case HttpStatusCode.Unauthorized
891                 Twitter.AccountState = ACCOUNT_STATE.Invalid
892                 Return "Check your Username/Password."
893             Case Else
894                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
895         End Select
896     End Function
897
898     Public Function GetUserInfo(ByVal screenName As String, ByRef xmlBuf As String) As String
899
900         If _endingFlag Then Return ""
901
902         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
903
904         Dim res As HttpStatusCode
905         Dim content As String = ""
906         xmlBuf = Nothing
907         Try
908             res = twCon.ShowUserInfo(screenName, content)
909         Catch ex As Exception
910             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
911         End Try
912
913         Select Case res
914             Case HttpStatusCode.OK
915                 Dim xdoc As New XmlDocument
916                 Dim result As String = ""
917                 Twitter.AccountState = ACCOUNT_STATE.Valid
918                 Try
919                     xdoc.LoadXml(content)
920                     xmlBuf = content
921                 Catch ex As Exception
922                     result = "Err:Invalid XML."
923                     xmlBuf = Nothing
924                 End Try
925                 Return result
926             Case HttpStatusCode.BadRequest
927                 Return "Err:API Limits?"
928             Case HttpStatusCode.Unauthorized
929                 Twitter.AccountState = ACCOUNT_STATE.Invalid
930                 Return "Check your Username/Password."
931             Case Else
932                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
933         End Select
934     End Function
935
936     Public Function GetStatus_Retweeted_Count(ByVal StatusId As Long, ByRef retweeted_count As Integer) As String
937
938         If _endingFlag Then Return ""
939
940         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
941
942         Dim res As HttpStatusCode
943         Dim content As String = ""
944         Dim xmlBuf As String = ""
945
946         retweeted_count = 0
947
948         ' 注:dev.twitter.comに記述されているcountパラメータは間違い。100が正しい
949         For i As Integer = 1 To 100
950
951             Try
952                 res = twCon.Statusid_retweeted_by_ids(StatusId, 100, i, content)
953             Catch ex As Exception
954                 Return "Err:" + ex.Message
955             End Try
956
957             Select Case res
958                 Case HttpStatusCode.OK
959                     Dim xdoc As New XmlDocument
960                     Dim xnode As XmlNodeList
961                     Dim result As String = ""
962                     Twitter.AccountState = ACCOUNT_STATE.Valid
963                     Try
964                         xdoc.LoadXml(content)
965                         xnode = xdoc.GetElementsByTagName("ids")
966                         retweeted_count += xnode.ItemOf(0).ChildNodes.Count
967                         If xnode.ItemOf(0).ChildNodes.Count < 100 Then Exit For
968                     Catch ex As Exception
969                         retweeted_count = -1
970                         result = "Err:Invalid XML."
971                         xmlBuf = Nothing
972                     End Try
973                 Case HttpStatusCode.BadRequest
974                     retweeted_count = -1
975                     Return "Err:API Limits?"
976                 Case HttpStatusCode.Unauthorized
977                     retweeted_count = -1
978                     Twitter.AccountState = ACCOUNT_STATE.Invalid
979                     Return "Check your Username/Password."
980                 Case Else
981                     retweeted_count = -1
982                     Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
983             End Select
984         Next
985         Return ""
986     End Function
987
988     Public Function PostFavAdd(ByVal id As Long) As String
989         If _endingFlag Then Return ""
990
991         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
992
993         Dim res As HttpStatusCode
994         Dim content As String = ""
995         Try
996             res = twCon.CreateFavorites(id, content)
997         Catch ex As Exception
998             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
999         End Try
1000
1001         Select Case res
1002             Case HttpStatusCode.OK
1003                 Twitter.AccountState = ACCOUNT_STATE.Valid
1004                 If Not _restrictFavCheck Then Return ""
1005             Case HttpStatusCode.Unauthorized
1006                 Twitter.AccountState = ACCOUNT_STATE.Invalid
1007                 Return "Check your Username/Password."
1008             Case HttpStatusCode.Forbidden
1009                 Dim xd As XmlDocument = New XmlDocument
1010                 Try
1011                     xd.LoadXml(content)
1012                     Dim xNode As XmlNode = Nothing
1013                     xNode = xd.SelectSingleNode("/hash/error")
1014                     Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
1015                 Catch ex As Exception
1016                     Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
1017                 End Try
1018             Case Else
1019                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1020         End Select
1021
1022         'http://twitter.com/statuses/show/id.xml APIを発行して本文を取得
1023
1024         'Dim content As String = ""
1025         content = ""
1026         Try
1027             res = twCon.ShowStatuses(id, content)
1028         Catch ex As Exception
1029             Return "Err:" + ex.Message
1030         End Try
1031
1032         Select Case res
1033             Case HttpStatusCode.OK
1034                 Twitter.AccountState = ACCOUNT_STATE.Valid
1035                 Try
1036                     Using rd As Xml.XmlTextReader = New Xml.XmlTextReader(New System.IO.StringReader(content))
1037                         rd.Read()
1038                         While rd.EOF = False
1039                             If rd.IsStartElement("favorited") Then
1040                                 If rd.ReadElementContentAsBoolean() = True Then
1041                                     Return ""  '正常にふぁぼれている
1042                                 Else
1043                                     Return "NG(Restricted?)"  '正常応答なのにふぁぼれてないので制限っぽい
1044                                 End If
1045                             Else
1046                                 rd.Read()
1047                             End If
1048                         End While
1049                         rd.Close()
1050                         Return "Err:Invalid XML!"
1051                     End Using
1052                 Catch ex As XmlException
1053                     Return ""
1054                 End Try
1055             Case HttpStatusCode.Unauthorized
1056                 Twitter.AccountState = ACCOUNT_STATE.Invalid
1057                 Return "Check your Username/Password."
1058             Case HttpStatusCode.BadRequest
1059                 Return "Err:API Limits?"
1060             Case Else
1061                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1062         End Select
1063
1064     End Function
1065
1066     Public Function PostFavRemove(ByVal id As Long) As String
1067         If _endingFlag Then Return ""
1068
1069         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1070
1071         Dim res As HttpStatusCode
1072         Dim content As String = ""
1073         Try
1074             res = twCon.DestroyFavorites(id, content)
1075         Catch ex As Exception
1076             Return "Err:" + ex.Message
1077         End Try
1078
1079         Select Case res
1080             Case HttpStatusCode.OK
1081                 Twitter.AccountState = ACCOUNT_STATE.Valid
1082                 Return ""
1083             Case HttpStatusCode.Unauthorized
1084                 Twitter.AccountState = ACCOUNT_STATE.Invalid
1085                 Return "Check your Username/Password."
1086             Case HttpStatusCode.Forbidden
1087                 Dim xd As XmlDocument = New XmlDocument
1088                 Try
1089                     xd.LoadXml(content)
1090                     Dim xNode As XmlNode = Nothing
1091                     xNode = xd.SelectSingleNode("/hash/error")
1092                     Return "Err:" + xNode.InnerText
1093                 Catch ex As Exception
1094                     Return "Err:Forbidden"
1095                 End Try
1096             Case Else
1097                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1098         End Select
1099     End Function
1100
1101     Public Function PostUpdateProfile(ByVal name As String, ByVal url As String, ByVal location As String, ByVal description As String) As String
1102         If _endingFlag Then Return ""
1103
1104         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1105
1106         Dim res As HttpStatusCode
1107         Dim content As String = ""
1108         Try
1109             res = twCon.UpdateProfile(name, url, location, description, content)
1110         Catch ex As Exception
1111             Return "Err:" + ex.Message
1112         End Try
1113
1114         Select Case res
1115             Case HttpStatusCode.OK
1116                 Twitter.AccountState = ACCOUNT_STATE.Valid
1117                 Return ""
1118             Case HttpStatusCode.Unauthorized
1119                 Twitter.AccountState = ACCOUNT_STATE.Invalid
1120                 Return "Check your Username/Password."
1121             Case HttpStatusCode.Forbidden
1122                 Dim xd As XmlDocument = New XmlDocument
1123                 Try
1124                     xd.LoadXml(content)
1125                     Dim xNode As XmlNode = Nothing
1126                     xNode = xd.SelectSingleNode("/hash/error")
1127                     Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
1128                 Catch ex As Exception
1129                     Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
1130                 End Try
1131             Case Else
1132                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1133         End Select
1134     End Function
1135
1136     Public Function PostUpdateProfileImage(ByVal filename As String) As String
1137         If _endingFlag Then Return ""
1138
1139         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1140
1141         Dim res As HttpStatusCode
1142         Dim content As String = ""
1143         Try
1144             res = twCon.UpdateProfileImage(New FileInfo(filename), content)
1145         Catch ex As Exception
1146             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
1147         End Try
1148
1149         Select Case res
1150             Case HttpStatusCode.OK
1151                 Twitter.AccountState = ACCOUNT_STATE.Valid
1152                 Return ""
1153             Case HttpStatusCode.Unauthorized
1154                 Twitter.AccountState = ACCOUNT_STATE.Invalid
1155                 Return "Check your Username/Password."
1156             Case HttpStatusCode.Forbidden
1157                 Dim xd As XmlDocument = New XmlDocument
1158                 Try
1159                     xd.LoadXml(content)
1160                     Dim xNode As XmlNode = Nothing
1161                     xNode = xd.SelectSingleNode("/hash/error")
1162                     Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
1163                 Catch ex As Exception
1164                     Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
1165                 End Try
1166             Case Else
1167                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1168         End Select
1169     End Function
1170
1171     Public ReadOnly Property Username() As String
1172         Get
1173             Return twCon.AuthenticatedUsername
1174         End Get
1175     End Property
1176
1177     Public ReadOnly Property Password() As String
1178         Get
1179             Return twCon.Password
1180         End Get
1181     End Property
1182
1183     Private Shared _accountState As ACCOUNT_STATE = ACCOUNT_STATE.Valid
1184     Public Shared Property AccountState() As ACCOUNT_STATE
1185         Get
1186             Return _accountState
1187         End Get
1188         Set(ByVal value As ACCOUNT_STATE)
1189             _accountState = value
1190         End Set
1191     End Property
1192
1193     Public WriteOnly Property GetIcon() As Boolean
1194         Set(ByVal value As Boolean)
1195             _getIcon = value
1196         End Set
1197     End Property
1198
1199     Public WriteOnly Property TinyUrlResolve() As Boolean
1200         Set(ByVal value As Boolean)
1201             _tinyUrlResolve = value
1202         End Set
1203     End Property
1204
1205     Public WriteOnly Property RestrictFavCheck() As Boolean
1206         Set(ByVal value As Boolean)
1207             _restrictFavCheck = value
1208         End Set
1209     End Property
1210
1211     Public WriteOnly Property IconSize() As Integer
1212         Set(ByVal value As Integer)
1213             _iconSz = value
1214         End Set
1215     End Property
1216
1217 #Region "バージョンアップ"
1218     Public Function GetVersionInfo() As String
1219         Dim content As String = ""
1220         If Not (New HttpVarious).GetData("http://tween.sourceforge.jp/version2.txt?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), Nothing, content) Then
1221             Throw New Exception("GetVersionInfo Failed")
1222         End If
1223         Return content
1224     End Function
1225
1226     Public Function GetTweenBinary(ByVal strVer As String) As String
1227         Try
1228             If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/Tween" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1229                                                 Path.Combine(Application.StartupPath(), "TweenNew.exe")) Then
1230                 Return "Err:Download failed"
1231             End If
1232             If Directory.Exists(Path.Combine(Application.StartupPath(), "en")) = False Then
1233                 Directory.CreateDirectory(Path.Combine(Application.StartupPath(), "en"))
1234             End If
1235             If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenRes" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1236                                                 Path.Combine(Application.StartupPath(), "en\Tween.resourcesNew.dll")) Then
1237                 Return "Err:Download failed"
1238             End If
1239             If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenUp.gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1240                                                 Path.Combine(Application.StartupPath(), "TweenUp.exe")) Then
1241                 Return "Err:Download failed"
1242             End If
1243             If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenDll" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1244                                                 Path.Combine(Application.StartupPath(), "TweenNew.XmlSerializers.dll")) Then
1245                 Return "Err:Download failed"
1246             End If
1247             Return ""
1248         Catch ex As Exception
1249             Return "Err:Download failed"
1250         End Try
1251     End Function
1252 #End Region
1253
1254     Public Property DetailIcon() As IDictionary(Of String, Image)
1255         Get
1256             Return _dIcon
1257         End Get
1258         Set(ByVal value As IDictionary(Of String, Image))
1259             _dIcon = value
1260         End Set
1261     End Property
1262
1263     'Public WriteOnly Property CountApi() As Integer
1264     '    'API時の取得件数
1265     '    Set(ByVal value As Integer)
1266     '        _countApi = value
1267     '    End Set
1268     'End Property
1269
1270     'Public WriteOnly Property CountApiReply() As Integer
1271     '    'API時のMentions取得件数
1272     '    Set(ByVal value As Integer)
1273     '        _countApiReply = value
1274     '    End Set
1275     'End Property
1276
1277     Public Property ReadOwnPost() As Boolean
1278         Get
1279             Return _readOwnPost
1280         End Get
1281         Set(ByVal value As Boolean)
1282             _readOwnPost = value
1283         End Set
1284     End Property
1285
1286     Public ReadOnly Property FollowersCount() As Integer
1287         Get
1288             Return _followersCount
1289         End Get
1290     End Property
1291
1292     Public ReadOnly Property FriendsCount() As Integer
1293         Get
1294             Return _friendsCount
1295         End Get
1296     End Property
1297
1298     Public ReadOnly Property StatusesCount() As Integer
1299         Get
1300             Return _statusesCount
1301         End Get
1302     End Property
1303
1304     Public ReadOnly Property Location() As String
1305         Get
1306             Return _location
1307         End Get
1308     End Property
1309
1310     Public ReadOnly Property Bio() As String
1311         Get
1312             Return _bio
1313         End Get
1314     End Property
1315
1316     Public ReadOnly Property UserInfoXml As String
1317         Get
1318             Return _userinfoxml
1319         End Get
1320     End Property
1321
1322     Public WriteOnly Property UseSsl() As Boolean
1323         Set(ByVal value As Boolean)
1324             HttpTwitter.UseSsl = value
1325             If value Then
1326                 _protocol = "https://"
1327             Else
1328                 _protocol = "http://"
1329             End If
1330         End Set
1331     End Property
1332
1333     'Public Overloads Function GetTimelineApi(ByVal read As Boolean, _
1334     '                ByVal gType As WORKERTYPE, _
1335     '                ByVal more As Boolean) As String
1336
1337     '    Return GetTimelineApi(read, gType, more, -1)
1338     'End Function
1339
1340
1341     Public Overloads Function GetTimelineApi(ByVal read As Boolean, _
1342                             ByVal gType As WORKERTYPE, _
1343                             ByVal more As Boolean, _
1344                             ByVal startup As Boolean) As String
1345
1346         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1347
1348         If _endingFlag Then Return ""
1349
1350         Dim res As HttpStatusCode
1351         Dim content As String = ""
1352         Dim count As Integer = Setting.Instance.CountApi
1353         If gType = WORKERTYPE.Reply Then count = Setting.Instance.CountApiReply
1354         If Setting.Instance.UseAdditionalCount Then
1355             If more AndAlso Setting.Instance.MoreCountApi <> 0 Then
1356                 count = Setting.Instance.MoreCountApi
1357             ElseIf startup AndAlso Setting.Instance.FirstCountApi <> 0 AndAlso gType = WORKERTYPE.Timeline Then
1358                 count = Setting.Instance.FirstCountApi
1359             End If
1360         End If
1361         Try
1362             If gType = WORKERTYPE.Timeline Then
1363                 If more Then
1364                     res = twCon.HomeTimeline(count, Me.minHomeTimeline, 0, content)
1365                 Else
1366                     res = twCon.HomeTimeline(count, 0, 0, content)
1367                 End If
1368             Else
1369                 If more Then
1370                     res = twCon.Mentions(count, Me.minMentions, 0, content)
1371                 Else
1372                     res = twCon.Mentions(count, 0, 0, content)
1373                 End If
1374             End If
1375         Catch ex As Exception
1376             Return "Err:" + ex.Message
1377         End Try
1378         Select Case res
1379             Case HttpStatusCode.OK
1380                 Twitter.AccountState = ACCOUNT_STATE.Valid
1381             Case HttpStatusCode.Unauthorized
1382                 Twitter.AccountState = ACCOUNT_STATE.Invalid
1383                 Return "Check your Username/Password."
1384             Case HttpStatusCode.BadRequest
1385                 Return "Err:API Limits?"
1386             Case Else
1387                 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1388         End Select
1389
1390         If gType = WORKERTYPE.Timeline Then
1391             Return CreatePostsFromXml(content, gType, Nothing, read, count, Me.minHomeTimeline)
1392         Else
1393             Return CreatePostsFromXml(content, gType, Nothing, read, count, Me.minMentions)
1394         End If
1395     End Function
1396
1397     'Public Overloads Function GetListStatus(ByVal read As Boolean, _
1398     '                        ByVal tab As TabClass, _
1399     '                        ByVal more As Boolean) As String
1400
1401     '    Return GetListStatus(read, tab, more, -1)
1402     'End Function
1403
1404     Public Overloads Function GetListStatus(ByVal read As Boolean, _
1405                             ByVal tab As TabClass, _
1406                             ByVal more As Boolean, _
1407                             ByVal startup As Boolean) As String
1408
1409         If _endingFlag Then Return ""
1410
1411         Dim res As HttpStatusCode
1412         Dim content As String = ""
1413         Dim page As Integer = 0
1414         Dim count As Integer = Setting.Instance.CountApi
1415         If Setting.Instance.UseAdditionalCount Then
1416             If more AndAlso Setting.Instance.MoreCountApi <> 0 Then
1417                 count = Setting.Instance.MoreCountApi
1418             ElseIf startup AndAlso Setting.Instance.FirstCountApi <> 0 Then
1419                 count = Setting.Instance.FirstCountApi
1420             End If
1421         End If
1422         Try
1423             If more Then
1424                 res = twCon.GetListsStatuses(tab.ListInfo.UserId.ToString, tab.ListInfo.Id.ToString, count, tab.OldestId, 0, content)
1425             Else
1426                 res = twCon.GetListsStatuses(tab.ListInfo.UserId.ToString, tab.ListInfo.Id.ToString, count, 0, 0, content)
1427             End If
1428         Catch ex As Exception
1429             Return "Err:" + ex.Message
1430         End Try
1431         Select Case res
1432             Case HttpStatusCode.OK
1433                 Twitter.AccountState = ACCOUNT_STATE.Valid
1434             Case HttpStatusCode.Unauthorized
1435                 Twitter.AccountState = ACCOUNT_STATE.Invalid
1436                 Return "Check your Username/Password."
1437             Case HttpStatusCode.BadRequest
1438                 Return "Err:API Limits?"
1439             Case Else
1440                 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1441         End Select
1442
1443         Return CreatePostsFromXml(content, WORKERTYPE.List, tab, read, count, tab.OldestId)
1444     End Function
1445
1446     Private Function CreatePostsFromXml(ByVal content As String, ByVal gType As WORKERTYPE, ByVal tab As TabClass, ByVal read As Boolean, ByVal count As Integer, ByRef minimumId As Long) As String
1447         Dim arIdx As Integer = -1
1448         Dim dlgt(300) As GetIconImageDelegate    'countQueryに合わせる
1449         Dim ar(300) As IAsyncResult              'countQueryに合わせる
1450         Dim xdoc As New XmlDocument
1451         Try
1452             xdoc.LoadXml(content)
1453         Catch ex As Exception
1454             TraceOut(content)
1455             'MessageBox.Show("不正なXMLです。(TL-LoadXml)")
1456             Return "Invalid XML!"
1457         End Try
1458
1459         For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("./status")
1460             Dim xentry As XmlElement = CType(xentryNode, XmlElement)
1461             Dim post As New PostClass
1462             Try
1463                 post.Id = Long.Parse(xentry.Item("id").InnerText)
1464                 If minimumId > post.Id Then minimumId = post.Id
1465                 '二重取得回避
1466                 SyncLock LockObj
1467                     If tab Is Nothing Then
1468                         If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
1469                     Else
1470                         If TabInformations.GetInstance.ContainsKey(post.Id, tab.TabName) Then Continue For
1471                     End If
1472                 End SyncLock
1473                 'Retweet判定
1474                 Dim xRnode As XmlNode = xentry.SelectSingleNode("./retweeted_status")
1475                 If xRnode IsNot Nothing Then
1476                     Dim xRentry As XmlElement = CType(xRnode, XmlElement)
1477                     post.PDate = DateTime.ParseExact(xRentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
1478                     'Id
1479                     post.RetweetedId = Long.Parse(xRentry.Item("id").InnerText)
1480                     '本文
1481                     post.Data = xRentry.Item("text").InnerText
1482                     'Source取得(htmlの場合は、中身を取り出し)
1483                     post.Source = xRentry.Item("source").InnerText
1484                     'Reply先
1485                     Long.TryParse(xRentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
1486                     post.InReplyToUser = xRentry.Item("in_reply_to_screen_name").InnerText
1487                     post.IsFav = TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.RetweetedId)
1488                     'post.IsFav = Boolean.Parse(xentry.Item("favorited").InnerText)
1489
1490                     '以下、ユーザー情報
1491                     Dim xRUentry As XmlElement = CType(xRentry.SelectSingleNode("./user"), XmlElement)
1492                     post.Uid = Long.Parse(xRUentry.Item("id").InnerText)
1493                     post.Name = xRUentry.Item("screen_name").InnerText
1494                     post.Nickname = xRUentry.Item("name").InnerText
1495                     post.ImageUrl = xRUentry.Item("profile_image_url").InnerText
1496                     post.IsProtect = Boolean.Parse(xRUentry.Item("protected").InnerText)
1497                     post.IsMe = post.Name.ToLower.Equals(_uid)
1498                     If post.IsMe Then _UserIdNo = post.Uid.ToString()
1499
1500                     'Retweetした人
1501                     Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
1502                     post.RetweetedBy = xUentry.Item("screen_name").InnerText
1503                 Else
1504                     post.PDate = DateTime.ParseExact(xentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
1505                     '本文
1506                     post.Data = xentry.Item("text").InnerText
1507                     'Source取得(htmlの場合は、中身を取り出し)
1508                     post.Source = xentry.Item("source").InnerText
1509                     Long.TryParse(xentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
1510                     post.InReplyToUser = xentry.Item("in_reply_to_screen_name").InnerText
1511                     'in_reply_to_user_idを使うか?
1512                     post.IsFav = Boolean.Parse(xentry.Item("favorited").InnerText)
1513
1514                     '以下、ユーザー情報
1515                     Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
1516                     post.Uid = Long.Parse(xUentry.Item("id").InnerText)
1517                     post.Name = xUentry.Item("screen_name").InnerText
1518                     post.Nickname = xUentry.Item("name").InnerText
1519                     post.ImageUrl = xUentry.Item("profile_image_url").InnerText
1520                     post.IsProtect = Boolean.Parse(xUentry.Item("protected").InnerText)
1521                     post.IsMe = post.Name.ToLower.Equals(_uid)
1522                     If post.IsMe Then _UserIdNo = post.Uid.ToString()
1523                 End If
1524                 'HTMLに整形
1525                 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
1526                 post.Data = HttpUtility.HtmlDecode(post.Data)
1527                 post.Data = post.Data.Replace("<3", "♡")
1528                 'Source整形
1529                 CreateSource(post)
1530
1531                 post.IsRead = read
1532                 If gType = WORKERTYPE.Timeline OrElse tab IsNot Nothing Then
1533                     post.IsReply = post.ReplyToList.Contains(_uid)
1534                 Else
1535                     post.IsReply = True
1536                 End If
1537                 post.IsExcludeReply = False
1538
1539                 If post.IsMe Then
1540                     post.IsOwl = False
1541                 Else
1542                     If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.Uid)
1543                 End If
1544                 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
1545
1546                 post.IsDm = False
1547                 If tab IsNot Nothing Then post.RelTabName = tab.TabName
1548             Catch ex As Exception
1549                 TraceOut(content)
1550                 'MessageBox.Show("不正なXMLです。(TL-Parse)")
1551                 Continue For
1552             End Try
1553
1554             '非同期アイコン取得&StatusDictionaryに追加
1555             arIdx += 1
1556             If arIdx > dlgt.Length - 1 Then
1557                 arIdx -= 1
1558                 Exit For
1559             End If
1560             dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
1561             ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
1562         Next
1563
1564         'アイコン取得完了待ち
1565         For i As Integer = 0 To arIdx
1566             Try
1567                 dlgt(i).EndInvoke(ar(i))
1568             Catch ex As IndexOutOfRangeException
1569                 Throw New IndexOutOfRangeException(String.Format("i={0},dlgt.Length={1},ar.Length={2},arIdx={3}", i, dlgt.Length, ar.Length, arIdx))
1570             Catch ex As Exception
1571                 '最後までendinvoke回す(ゾンビ化回避)
1572                 ex.Data("IsTerminatePermission") = False
1573                 Throw
1574             End Try
1575         Next
1576
1577         Return ""
1578     End Function
1579
1580     Public Function GetSearch(ByVal read As Boolean, _
1581                             ByVal tab As TabClass, _
1582                             ByVal more As Boolean) As String
1583
1584         If _endingFlag Then Return ""
1585
1586         Dim res As HttpStatusCode
1587         Dim content As String = ""
1588         Dim page As Integer = 0
1589         Dim sinceId As Long = 0
1590         Dim count As Integer = 100
1591         If Setting.Instance.UseAdditionalCount AndAlso
1592             Setting.Instance.SearchCountApi <> 0 Then
1593             count = Setting.Instance.SearchCountApi
1594         End If
1595         If more Then
1596             page = tab.GetSearchPage(count)
1597         Else
1598             sinceId = tab.SinceId
1599         End If
1600
1601         Try
1602             ' TODO:一時的に40>100件に 件数変更UI作成の必要あり
1603             res = twCon.Search(tab.SearchWords, tab.SearchLang, count, page, sinceId, content)
1604         Catch ex As Exception
1605             Return "Err:" + ex.Message
1606         End Try
1607         Select Case res
1608             Case HttpStatusCode.BadRequest
1609                 Return "Invalid query"
1610             Case HttpStatusCode.NotFound
1611                 Return "Invalid query"
1612             Case HttpStatusCode.PaymentRequired 'API Documentには420と書いてあるが、該当コードがないので402にしてある
1613                 Return "Search API Limit?"
1614             Case HttpStatusCode.OK
1615             Case Else
1616                 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1617         End Select
1618
1619         If Not TabInformations.GetInstance.ContainsTab(tab) Then Return ""
1620
1621         Dim arIdx As Integer = -1
1622         Dim dlgt(300) As GetIconImageDelegate    'countQueryに合わせる
1623         Dim ar(300) As IAsyncResult              'countQueryに合わせる
1624         Dim xdoc As New XmlDocument
1625         Try
1626             xdoc.LoadXml(content)
1627         Catch ex As Exception
1628             TraceOut(content)
1629             Return "Invalid ATOM!"
1630         End Try
1631         Dim nsmgr As New XmlNamespaceManager(xdoc.NameTable)
1632         nsmgr.AddNamespace("search", "http://www.w3.org/2005/Atom")
1633         nsmgr.AddNamespace("twitter", "http://api.twitter.com/")
1634         For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/search:feed/search:entry", nsmgr)
1635             Dim xentry As XmlElement = CType(xentryNode, XmlElement)
1636             Dim post As New PostClass
1637             Try
1638                 post.Id = Long.Parse(xentry.Item("id").InnerText.Split(":"c)(2))
1639                 If TabInformations.GetInstance.ContainsKey(post.Id, tab.TabName) Then Continue For
1640                 post.PDate = DateTime.Parse(xentry.Item("published").InnerText)
1641                 '本文
1642                 post.Data = xentry.Item("title").InnerText
1643                 'Source取得(htmlの場合は、中身を取り出し)
1644                 post.Source = xentry.Item("twitter:source").InnerText
1645                 post.InReplyToId = 0
1646                 post.InReplyToUser = ""
1647                 post.IsFav = False
1648
1649                 '以下、ユーザー情報
1650                 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./search:author", nsmgr), XmlElement)
1651                 post.Uid = 0
1652                 post.Name = xUentry.Item("name").InnerText.Split(" "c)(0).Trim
1653                 post.Nickname = xUentry.Item("name").InnerText.Substring(post.Name.Length).Trim
1654                 If post.Nickname.Length > 2 Then
1655                     post.Nickname = post.Nickname.Substring(1, post.Nickname.Length - 2)
1656                 Else
1657                     post.Nickname = post.Name
1658                 End If
1659                 post.ImageUrl = CType(xentry.SelectSingleNode("./search:link[@type='image/png']", nsmgr), XmlElement).GetAttribute("href")
1660                 post.IsProtect = False
1661                 post.IsMe = post.Name.ToLower.Equals(_uid)
1662
1663                 'HTMLに整形
1664                 post.OriginalData = CreateHtmlAnchor(HttpUtility.HtmlEncode(post.Data), post.ReplyToList)
1665                 post.Data = HttpUtility.HtmlDecode(post.Data)
1666                 'Source整形
1667                 CreateSource(post)
1668
1669                 post.IsRead = read
1670                 post.IsReply = post.ReplyToList.Contains(_uid)
1671                 post.IsExcludeReply = False
1672
1673                 post.IsOwl = False
1674                 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
1675                 post.IsDm = False
1676                 post.RelTabName = tab.TabName
1677                 If Not more AndAlso post.Id > tab.SinceId Then tab.SinceId = post.Id
1678             Catch ex As Exception
1679                 TraceOut(content)
1680                 Continue For
1681             End Try
1682
1683             '非同期アイコン取得&StatusDictionaryに追加
1684             arIdx += 1
1685             dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
1686             ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
1687         Next
1688
1689         '' TODO
1690         '' 遡るための情報max_idやnext_pageの情報を保持する
1691
1692         'アイコン取得完了待ち
1693         For i As Integer = 0 To arIdx
1694             Try
1695                 dlgt(i).EndInvoke(ar(i))
1696             Catch ex As Exception
1697                 '最後までendinvoke回す(ゾンビ化回避)
1698                 ex.Data("IsTerminatePermission") = False
1699                 Throw
1700             End Try
1701         Next
1702
1703 #If 0 Then
1704         Dim xNode As XmlNode = xdoc.DocumentElement.SelectSingleNode("/search:feed/twitter:warning", nsmgr)
1705
1706         If xNode IsNot Nothing Then
1707             Return "Warn:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
1708         End If
1709 #End If
1710
1711         Return ""
1712     End Function
1713
1714     Public Function GetDirectMessageApi(ByVal read As Boolean, _
1715                             ByVal gType As WORKERTYPE, _
1716                             ByVal more As Boolean) As String
1717         If _endingFlag Then Return ""
1718
1719         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1720
1721         Dim res As HttpStatusCode
1722         Dim content As String = ""
1723
1724         Try
1725             If gType = WORKERTYPE.DirectMessegeRcv Then
1726                 If more Then
1727                     res = twCon.DirectMessages(20, minDirectmessage, 0, content)
1728                 Else
1729                     res = twCon.DirectMessages(20, 0, 0, content)
1730                 End If
1731             Else
1732                 If more Then
1733                     res = twCon.DirectMessagesSent(20, minDirectmessageSent, 0, content)
1734                 Else
1735                     res = twCon.DirectMessagesSent(20, 0, 0, content)
1736                 End If
1737             End If
1738         Catch ex As Exception
1739             Return "Err:" + ex.Message
1740         End Try
1741
1742         Select Case res
1743             Case HttpStatusCode.OK
1744                 Twitter.AccountState = ACCOUNT_STATE.Valid
1745             Case HttpStatusCode.Unauthorized
1746                 Twitter.AccountState = ACCOUNT_STATE.Invalid
1747                 Return "Check your Username/Password."
1748             Case HttpStatusCode.BadRequest
1749                 Return "Err:API Limits?"
1750             Case Else
1751                 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1752         End Select
1753
1754         Dim arIdx As Integer = -1
1755         Dim dlgt(300) As GetIconImageDelegate    'countQueryに合わせる
1756         Dim ar(300) As IAsyncResult              'countQueryに合わせる
1757         Dim xdoc As New XmlDocument
1758         Try
1759             xdoc.LoadXml(content)
1760         Catch ex As Exception
1761             TraceOut(content)
1762             'MessageBox.Show("不正なXMLです。(DM-LoadXml)")
1763             Return "Invalid XML!"
1764         End Try
1765
1766         For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("./direct_message")
1767             Dim xentry As XmlElement = CType(xentryNode, XmlElement)
1768             Dim post As New PostClass
1769             Try
1770                 post.Id = Long.Parse(xentry.Item("id").InnerText)
1771                 If gType = WORKERTYPE.DirectMessegeRcv Then
1772                     If minDirectmessage > post.Id Then minDirectmessage = post.Id
1773                 Else
1774                     If minDirectmessageSent > post.Id Then minDirectmessageSent = post.Id
1775                 End If
1776                 '二重取得回避
1777                 SyncLock LockObj
1778                     If TabInformations.GetInstance.GetTabByType(TabUsageType.DirectMessage).Contains(post.Id) Then Continue For
1779                 End SyncLock
1780                 'sender_id
1781                 'recipient_id
1782                 post.PDate = DateTime.ParseExact(xentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
1783                 '本文
1784                 post.Data = xentry.Item("text").InnerText
1785                 'HTMLに整形
1786                 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
1787                 post.Data = HttpUtility.HtmlDecode(post.Data)
1788                 post.Data = post.Data.Replace("<3", "♡")
1789                 post.IsFav = False
1790                 '受信DMかの判定で使用
1791                 If gType = WORKERTYPE.DirectMessegeRcv Then
1792                     post.IsOwl = True
1793                 Else
1794                     post.IsOwl = False
1795                 End If
1796
1797                 '以下、ユーザー情報
1798                 Dim xUentry As XmlElement
1799                 If gType = WORKERTYPE.DirectMessegeRcv Then
1800                     xUentry = CType(xentry.SelectSingleNode("./sender"), XmlElement)
1801                     post.IsMe = False
1802                 Else
1803                     xUentry = CType(xentry.SelectSingleNode("./recipient"), XmlElement)
1804                     post.IsMe = True
1805                 End If
1806                 post.Uid = Long.Parse(xUentry.Item("id").InnerText)
1807                 post.Name = xUentry.Item("screen_name").InnerText
1808                 post.Nickname = xUentry.Item("name").InnerText
1809                 post.ImageUrl = xUentry.Item("profile_image_url").InnerText
1810                 post.IsProtect = Boolean.Parse(xUentry.Item("protected").InnerText)
1811             Catch ex As Exception
1812                 TraceOut(content)
1813                 'MessageBox.Show("不正なXMLです。(DM-Parse)")
1814                 Continue For
1815             End Try
1816
1817             post.IsRead = read
1818             If gType = WORKERTYPE.DirectMessegeSnt AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
1819             post.IsReply = False
1820             post.IsExcludeReply = False
1821             post.IsDm = True
1822
1823             '非同期アイコン取得&StatusDictionaryに追加
1824             arIdx += 1
1825             dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
1826             ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
1827         Next
1828
1829         'アイコン取得完了待ち
1830         For i As Integer = 0 To arIdx
1831             Try
1832                 dlgt(i).EndInvoke(ar(i))
1833             Catch ex As Exception
1834                 '最後までendinvoke回す(ゾンビ化回避)
1835                 ex.Data("IsTerminatePermission") = False
1836                 Throw
1837             End Try
1838         Next
1839
1840         Return ""
1841     End Function
1842
1843     Public Function GetFavoritesApi(ByVal read As Boolean, _
1844                         ByVal gType As WORKERTYPE) As String
1845
1846         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1847
1848         If _endingFlag Then Return ""
1849
1850         Dim res As HttpStatusCode
1851         Dim content As String = ""
1852         Dim count As Integer = Setting.Instance.CountApi
1853         If Setting.Instance.UseAdditionalCount AndAlso
1854             Setting.Instance.FavoritesCountApi <> 0 Then
1855             count = Setting.Instance.FavoritesCountApi
1856         End If
1857         Try
1858             res = twCon.Favorites(count, content)
1859         Catch ex As Exception
1860             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
1861         End Try
1862
1863         Select Case res
1864             Case HttpStatusCode.OK
1865                 Twitter.AccountState = ACCOUNT_STATE.Valid
1866             Case HttpStatusCode.Unauthorized
1867                 Twitter.AccountState = ACCOUNT_STATE.Invalid
1868                 Return "Check your Username/Password."
1869             Case HttpStatusCode.BadRequest
1870                 Return "Err:API Limits?"
1871             Case Else
1872                 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1873         End Select
1874
1875         Dim arIdx As Integer = -1
1876         Dim dlgt(300) As GetIconImageDelegate    'countQueryに合わせる
1877         Dim ar(300) As IAsyncResult              'countQueryに合わせる
1878         Dim xdoc As New XmlDocument
1879         Try
1880             xdoc.LoadXml(content)
1881         Catch ex As Exception
1882             TraceOut(content)
1883             'MessageBox.Show("不正なXMLです。(TL-LoadXml)")
1884             Return "Invalid XML!"
1885         End Try
1886
1887         For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("./status")
1888             Dim xentry As XmlElement = CType(xentryNode, XmlElement)
1889             Dim post As New PostClass
1890             Try
1891                 post.Id = Long.Parse(xentry.Item("id").InnerText)
1892                 '二重取得回避
1893                 SyncLock LockObj
1894                     'If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
1895                     If TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.Id) Then Continue For
1896                 End SyncLock
1897                 'Retweet判定
1898                 Dim xRnode As XmlNode = xentry.SelectSingleNode("./retweeted_status")
1899                 If xRnode IsNot Nothing Then
1900                     Dim xRentry As XmlElement = CType(xRnode, XmlElement)
1901                     post.PDate = DateTime.ParseExact(xRentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
1902                     'Id
1903                     post.RetweetedId = Long.Parse(xRentry.Item("id").InnerText)
1904                     '本文
1905                     post.Data = xRentry.Item("text").InnerText
1906                     'Source取得(htmlの場合は、中身を取り出し)
1907                     post.Source = xRentry.Item("source").InnerText
1908                     'Reply先
1909                     Long.TryParse(xRentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
1910                     post.InReplyToUser = xRentry.Item("in_reply_to_screen_name").InnerText
1911                     'in_reply_to_user_idを使うか?
1912                     post.IsFav = Boolean.Parse(xRentry.Item("favorited").InnerText)
1913
1914                     '以下、ユーザー情報
1915                     Dim xRUentry As XmlElement = CType(xRentry.SelectSingleNode("./user"), XmlElement)
1916                     post.Uid = Long.Parse(xRUentry.Item("id").InnerText)
1917                     post.Name = xRUentry.Item("screen_name").InnerText
1918                     post.Nickname = xRUentry.Item("name").InnerText
1919                     post.ImageUrl = xRUentry.Item("profile_image_url").InnerText
1920                     post.IsProtect = Boolean.Parse(xRUentry.Item("protected").InnerText)
1921                     post.IsMe = post.Name.ToLower.Equals(_uid)
1922                     If post.IsMe Then _UserIdNo = post.Uid.ToString()
1923
1924                     'Retweetした人
1925                     Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
1926                     post.RetweetedBy = xUentry.Item("screen_name").InnerText
1927                 Else
1928                     post.PDate = DateTime.ParseExact(xentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
1929                     '本文
1930                     post.Data = xentry.Item("text").InnerText
1931                     'Source取得(htmlの場合は、中身を取り出し)
1932                     post.Source = xentry.Item("source").InnerText
1933                     Long.TryParse(xentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
1934                     post.InReplyToUser = xentry.Item("in_reply_to_screen_name").InnerText
1935                     'in_reply_to_user_idを使うか?
1936                     post.IsFav = Boolean.Parse(xentry.Item("favorited").InnerText)
1937
1938                     '以下、ユーザー情報
1939                     Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
1940                     post.Uid = Long.Parse(xUentry.Item("id").InnerText)
1941                     post.Name = xUentry.Item("screen_name").InnerText
1942                     post.Nickname = xUentry.Item("name").InnerText
1943                     post.ImageUrl = xUentry.Item("profile_image_url").InnerText
1944                     post.IsProtect = Boolean.Parse(xUentry.Item("protected").InnerText)
1945                     post.IsMe = post.Name.ToLower.Equals(_uid)
1946                     If post.IsMe Then _UserIdNo = post.Uid.ToString()
1947                 End If
1948                 'HTMLに整形
1949                 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
1950                 post.Data = HttpUtility.HtmlDecode(post.Data)
1951                 post.Data = post.Data.Replace("<3", "♡")
1952                 'Source整形
1953                 CreateSource(post)
1954
1955                 post.IsRead = read
1956                 post.IsReply = post.ReplyToList.Contains(_uid)
1957                 post.IsExcludeReply = False
1958
1959                 If post.IsMe Then
1960                     post.IsOwl = False
1961                 Else
1962                     If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.Uid)
1963                 End If
1964
1965                 post.IsDm = False
1966             Catch ex As Exception
1967                 TraceOut(content)
1968                 'MessageBox.Show("不正なXMLです。(TL-Parse)")
1969                 Continue For
1970             End Try
1971
1972             '非同期アイコン取得&StatusDictionaryに追加
1973             arIdx += 1
1974             dlgt(arIdx) = New GetIconImageDelegate(AddressOf GetIconImage)
1975             ar(arIdx) = dlgt(arIdx).BeginInvoke(post, Nothing, Nothing)
1976         Next
1977
1978         'アイコン取得完了待ち
1979         For i As Integer = 0 To arIdx
1980             Try
1981                 dlgt(i).EndInvoke(ar(i))
1982             Catch ex As Exception
1983                 '最後までendinvoke回す(ゾンビ化回避)
1984                 ex.Data("IsTerminatePermission") = False
1985                 Throw
1986             End Try
1987         Next
1988
1989         Return ""
1990     End Function
1991
1992     Public Function GetFollowersApi() As String
1993         If _endingFlag Then Return ""
1994         Dim cursor As Long = -1
1995         Dim tmpFollower As New List(Of Long)(followerId)
1996
1997         followerId.Clear()
1998         Do
1999             Dim ret As String = FollowerApi(cursor)
2000             If Not String.IsNullOrEmpty(ret) Then
2001                 followerId.Clear()
2002                 followerId.AddRange(tmpFollower)
2003                 _GetFollowerResult = False
2004                 Return ret
2005             End If
2006         Loop While cursor > 0
2007
2008         TabInformations.GetInstance.RefreshOwl(followerId)
2009
2010         _GetFollowerResult = True
2011         Return ""
2012     End Function
2013
2014     Public ReadOnly Property GetFollowersSuccess() As Boolean
2015         Get
2016             Return _GetFollowerResult
2017         End Get
2018     End Property
2019
2020     Private Function FollowerApi(ByRef cursor As Long) As String
2021         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2022
2023         Dim res As HttpStatusCode
2024         Dim content As String = ""
2025         Try
2026             res = twCon.FollowerIds(cursor, content)
2027         Catch ex As Exception
2028             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2029         End Try
2030
2031         Select Case res
2032             Case HttpStatusCode.OK
2033                 Twitter.AccountState = ACCOUNT_STATE.Valid
2034             Case HttpStatusCode.Unauthorized
2035                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2036                 Return "Check your Username/Password."
2037             Case HttpStatusCode.BadRequest
2038                 Return "Err:API Limits?"
2039             Case Else
2040                 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2041         End Select
2042
2043         Dim xdoc As New XmlDocument
2044         Try
2045             xdoc.LoadXml(content)
2046         Catch ex As Exception
2047             TraceOut(content)
2048             Return "Invalid XML!"
2049         End Try
2050
2051         Try
2052             For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/id_list/ids/id")
2053                 followerId.Add(Long.Parse(xentryNode.InnerText))
2054             Next
2055             cursor = Long.Parse(xdoc.DocumentElement.SelectSingleNode("/id_list/next_cursor").InnerText)
2056         Catch ex As Exception
2057             TraceOut(content)
2058             Return "Invalid XML!"
2059         End Try
2060
2061         Return ""
2062
2063     End Function
2064
2065     Public Function GetListsApi() As String
2066         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2067
2068         Dim res As HttpStatusCode
2069         Dim content As String = ""
2070         Dim cursor As Long = -1
2071
2072         Dim lists As New List(Of ListElement)
2073         Do
2074             Try
2075                 res = twCon.GetLists(Me.Username, cursor, content)
2076             Catch ex As Exception
2077                 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2078             End Try
2079
2080             Select Case res
2081                 Case HttpStatusCode.OK
2082                     Twitter.AccountState = ACCOUNT_STATE.Valid
2083                 Case HttpStatusCode.Unauthorized
2084                     Twitter.AccountState = ACCOUNT_STATE.Invalid
2085                     Return "Check your Username/Password."
2086                 Case HttpStatusCode.BadRequest
2087                     Return "Err:API Limits?"
2088                 Case Else
2089                     Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2090             End Select
2091
2092             Dim xdoc As New XmlDocument
2093             Try
2094                 xdoc.LoadXml(content)
2095             Catch ex As Exception
2096                 TraceOut(content)
2097                 Return "Invalid XML!"
2098             End Try
2099
2100             Try
2101                 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/lists_list/lists/list")
2102                     lists.Add(New ListElement(xentryNode, Me))
2103                 Next
2104                 cursor = Long.Parse(xdoc.DocumentElement.SelectSingleNode("/lists_list/next_cursor").InnerText)
2105             Catch ex As Exception
2106                 TraceOut(content)
2107                 Return "Invalid XML!"
2108             End Try
2109         Loop While cursor <> 0
2110
2111         cursor = -1
2112         content = ""
2113         Do
2114             Try
2115                 res = twCon.GetListsSubscriptions(Me.Username, cursor, content)
2116             Catch ex As Exception
2117                 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2118             End Try
2119
2120             Select Case res
2121                 Case HttpStatusCode.OK
2122                     Twitter.AccountState = ACCOUNT_STATE.Valid
2123                 Case HttpStatusCode.Unauthorized
2124                     Twitter.AccountState = ACCOUNT_STATE.Invalid
2125                     Return "Check your Username/Password."
2126                 Case HttpStatusCode.BadRequest
2127                     Return "Err:API Limits?"
2128                 Case Else
2129                     Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2130             End Select
2131
2132             Dim xdoc As New XmlDocument
2133             Try
2134                 xdoc.LoadXml(content)
2135             Catch ex As Exception
2136                 TraceOut(content)
2137                 Return "Invalid XML!"
2138             End Try
2139
2140             Try
2141                 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/lists_list/lists/list")
2142                     lists.Add(New ListElement(xentryNode, Me))
2143                 Next
2144                 cursor = Long.Parse(xdoc.DocumentElement.SelectSingleNode("/lists_list/next_cursor").InnerText)
2145             Catch ex As Exception
2146                 TraceOut(content)
2147                 Return "Invalid XML!"
2148             End Try
2149         Loop While cursor <> 0
2150
2151         TabInformations.GetInstance.SubscribableLists = lists
2152         Return ""
2153     End Function
2154
2155     Public Function DeleteList(ByVal list_id As String) As String
2156         Dim res As HttpStatusCode
2157         Dim content As String = ""
2158
2159         Try
2160             res = twCon.DeleteListID(Me.Username, list_id, content)
2161         Catch ex As Exception
2162             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2163         End Try
2164
2165         Select Case res
2166             Case HttpStatusCode.OK
2167                 Twitter.AccountState = ACCOUNT_STATE.Valid
2168             Case HttpStatusCode.Unauthorized
2169                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2170                 Return "Check your Username/Password."
2171             Case HttpStatusCode.BadRequest
2172                 Return "Err:API Limits?"
2173             Case Else
2174                 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2175         End Select
2176
2177         Return ""
2178     End Function
2179
2180     Public Function EditList(ByVal list_id As String, ByVal new_name As String, ByVal isPrivate As Boolean, ByVal description As String, ByRef list As ListElement) As String
2181         Dim res As HttpStatusCode
2182         Dim content As String = ""
2183         Dim modeString As String = "public"
2184         If isPrivate Then
2185             modeString = "private"
2186         End If
2187
2188         Try
2189             res = twCon.PostListID(Me.Username, list_id, new_name, modeString, description, content)
2190         Catch ex As Exception
2191             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2192         End Try
2193
2194         Select Case res
2195             Case HttpStatusCode.OK
2196                 Twitter.AccountState = ACCOUNT_STATE.Valid
2197             Case HttpStatusCode.Unauthorized
2198                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2199                 Return "Check your Username/Password."
2200             Case HttpStatusCode.BadRequest
2201                 Return "Err:API Limits?"
2202             Case Else
2203                 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2204         End Select
2205
2206         Dim xdoc As New XmlDocument
2207         Try
2208             xdoc.LoadXml(content)
2209             Dim newList As New ListElement(xdoc.DocumentElement, Me)
2210             list.Description = newList.Description
2211             list.Id = newList.Id
2212             list.IsPublic = newList.IsPublic
2213             list.MemberCount = newList.MemberCount
2214             list.Name = newList.Name
2215             list.SubscriberCount = newList.SubscriberCount
2216             list.Slug = newList.Slug
2217             list.Nickname = newList.Nickname
2218             list.Username = newList.Username
2219             list.UserId = newList.UserId
2220         Catch ex As Exception
2221             TraceOut(content)
2222             Return "Invalid XML!"
2223         End Try
2224
2225         Return ""
2226     End Function
2227
2228     Public Function GetListMembers(ByVal list_id As String, ByVal lists As List(Of UserInfo), ByRef cursor As Long) As String
2229         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2230
2231         Dim res As HttpStatusCode
2232         Dim content As String = ""
2233         'Dim cursor As Long = -1
2234
2235         'Do
2236         Try
2237             res = twCon.GetListMembers(Me.Username, list_id, cursor, content)
2238         Catch ex As Exception
2239             Return "Err:" + ex.Message
2240         End Try
2241
2242         Select Case res
2243             Case HttpStatusCode.OK
2244                 Twitter.AccountState = ACCOUNT_STATE.Valid
2245             Case HttpStatusCode.Unauthorized
2246                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2247                 Return "Check your Username/Password."
2248             Case HttpStatusCode.BadRequest
2249                 Return "Err:API Limits?"
2250             Case Else
2251                 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2252         End Select
2253
2254         Dim xdoc As New XmlDocument
2255         Try
2256             xdoc.LoadXml(content)
2257         Catch ex As Exception
2258             TraceOut(content)
2259             Return "Invalid XML!"
2260         End Try
2261
2262         Try
2263             For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/users_list/users/user")
2264                 lists.Add(New UserInfo(xentryNode))
2265             Next
2266             cursor = Long.Parse(xdoc.DocumentElement.SelectSingleNode("/users_list/next_cursor").InnerText)
2267         Catch ex As Exception
2268             TraceOut(content)
2269             Return "Invalid XML!"
2270         End Try
2271         'Loop While cursor <> 0
2272
2273         Return ""
2274     End Function
2275
2276     Public Function CreateListApi(ByVal listName As String, ByVal isPrivate As Boolean, ByVal description As String) As String
2277         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2278
2279         Dim res As HttpStatusCode
2280         Dim content As String = ""
2281
2282         Try
2283             res = twCon.PostLists(Me.Username, listName, isPrivate, description, content)
2284         Catch ex As Exception
2285             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2286         End Try
2287
2288         Select Case res
2289             Case HttpStatusCode.OK
2290                 Twitter.AccountState = ACCOUNT_STATE.Valid
2291             Case HttpStatusCode.Unauthorized
2292                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2293                 Return "Check your Username/Password."
2294             Case HttpStatusCode.BadRequest
2295                 Return "Err:API Limits?"
2296             Case Else
2297                 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2298         End Select
2299
2300         Dim xdoc As New XmlDocument
2301         Try
2302             xdoc.LoadXml(content)
2303
2304             TabInformations.GetInstance().SubscribableLists.Add(New ListElement(xdoc.DocumentElement, Me))
2305         Catch ex As Exception
2306             TraceOut(content)
2307             Return "Invalid XML!"
2308         End Try
2309
2310         Return ""
2311     End Function
2312
2313     Public Function ContainsUserAtList(ByVal list_name As String, ByVal user As String, ByRef value As Boolean) As String
2314         value = False
2315
2316         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2317
2318         Dim res As HttpStatusCode
2319         Dim content As String = ""
2320
2321         Try
2322             res = Me.twCon.GetListMembersID(Me.Username, list_name, user, content)
2323         Catch ex As Exception
2324             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2325         End Try
2326
2327         Select Case res
2328             Case HttpStatusCode.OK
2329                 Twitter.AccountState = ACCOUNT_STATE.Valid
2330             Case HttpStatusCode.Unauthorized
2331                 Twitter.AccountState = ACCOUNT_STATE.Invalid
2332                 Return "Check your Username/Password."
2333             Case HttpStatusCode.BadRequest
2334                 Return "Err:API Limits?"
2335             Case HttpStatusCode.NotFound
2336                 value = False
2337                 Return ""
2338             Case Else
2339                 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2340         End Select
2341
2342         Dim xdoc As New XmlDocument
2343         Try
2344             xdoc.LoadXml(content)
2345             value = xdoc.DocumentElement.Name = "user"
2346         Catch ex As Exception
2347             TraceOut(content)
2348             Return "Invalid XML!"
2349         End Try
2350
2351         Return ""
2352     End Function
2353
2354     Public Function AddUserToList(ByVal list_name As String, ByVal user As String) As String
2355         Dim content As String = ""
2356         Dim res As HttpStatusCode
2357
2358         Try
2359             res = twCon.PostListMembers(Me.Username, list_name, user, content)
2360         Catch ex As Exception
2361             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2362         End Try
2363
2364         Return ""
2365     End Function
2366
2367     Public Function RemoveUserToList(ByVal list_name As String, ByVal user As String) As String
2368         Dim content As String = ""
2369         Dim res As HttpStatusCode
2370
2371         Try
2372             res = twCon.DeleteListMembers(Me.Username, list_name, user, content)
2373         Catch ex As Exception
2374             Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2375         End Try
2376
2377         Return ""
2378     End Function
2379
2380     Private Class range
2381         Public Property fromIndex As Integer
2382         Public Property toIndex As Integer
2383         Public Sub New(ByVal fromIndex As Integer, ByVal toIndex As Integer)
2384             Me.fromIndex = fromIndex
2385             Me.toIndex = toIndex
2386         End Sub
2387     End Class
2388     Public Function CreateHtmlAnchor(ByVal Text As String, ByVal AtList As List(Of String)) As String
2389         Dim retStr As String = Text.Replace("&gt;", "<<<<<tweenだいなり>>>>>").Replace("&lt;", "<<<<<tweenしょうなり>>>>>")
2390         'uriの正規表現
2391         'Const rgUrl As String = "(?<before>(?:[^\""':!=]|^|\:))" + _
2392         '                            "(?<url>(?<protocol>https?://|www\.)" + _
2393         '                            "(?<domain>(?:[\.-]|[^\p{P}\s])+\.[a-z]{2,}(?::[0-9]+)?)" + _
2394         '                            "(?<path>/[a-z0-9!*'();:&=+$/%#\[\]\-_.,~@^]*[a-z0-9)=#/]?)?" + _
2395         '                            "(?<query>\?[a-z0-9!*'();:&=+$/%#\[\]\-_.,~]*[a-z0-9_&=#])?)"
2396         Const url_valid_general_path_chars As String = "[a-z0-9!*';:=+$/%#\[\]\-_,~]"
2397         Const url_valid_url_path_ending_chars As String = "[a-z0-9=#/]"
2398         Const pth As String = "(?<path>/(?:(?:\(" + url_valid_general_path_chars + "+\))" +
2399             "|@" + url_valid_general_path_chars + "+/" +
2400             "|[.,]?" + url_valid_general_path_chars +
2401             ")*" +
2402             url_valid_url_path_ending_chars + "?)?"
2403         Const qry As String = "(?<query>\?[a-z0-9!*'();:&=+$/%#\[\]\-_.,~]*[a-z0-9_&=#])?"
2404         Const rgUrl As String = "(?<before>(?:[^\""':!=]|^|\:))" +
2405                                     "(?<url>(?<protocol>https?://|www\.)" +
2406                                     "(?<domain>(?:[\.-]|[^\p{P}\s])+\.[a-z]{2,}(?::[0-9]+)?)" +
2407                                     pth +
2408                                     qry +
2409                                     ")"
2410         '絶対パス表現のUriをリンクに置換
2411         retStr = Regex.Replace(retStr,
2412                                rgUrl,
2413                                New MatchEvaluator(Function(mu As Match)
2414                                                       Dim sb As New StringBuilder(mu.Result("${before}<a href="""))
2415                                                       If mu.Result("${protocol}").StartsWith("w", StringComparison.OrdinalIgnoreCase) Then
2416                                                           sb.Append("http://")
2417                                                       End If
2418                                                       sb.Append(mu.Result("${url}"">")).Append(mu.Result("${url}")).Append("</a>")
2419                                                       Return sb.ToString
2420                                                   End Function),
2421                                RegexOptions.IgnoreCase)
2422
2423         '@先をリンクに置換(リスト)
2424         retStr = Regex.Replace(retStr,
2425                                "(^|[^a-zA-Z0-9_/])([@@]+)([a-zA-Z0-9_]{1,20}/[a-zA-Z][a-zA-Z0-9\p{IsLatin-1Supplement}\-]{0,79})",
2426                                "$1$2<a href=""/$3"">$3</a>")
2427
2428         Dim m As Match = Regex.Match(retStr, "(^|[^a-zA-Z0-9_])[@@]([a-zA-Z0-9_]{1,20})")
2429         While m.Success
2430             If Not AtList.Contains(m.Result("$2").ToLower) Then AtList.Add(m.Result("$2").ToLower)
2431             m = m.NextMatch
2432         End While
2433         '@先をリンクに置換
2434         retStr = Regex.Replace(retStr,
2435                                "(^|[^a-zA-Z0-9_/])([@@])([a-zA-Z0-9_]{1,20})",
2436                                "$1$2<a href=""/$3"">$3</a>")
2437
2438         'ハッシュタグを抽出し、リンクに置換
2439         Dim anchorRange As New List(Of range)
2440         For i As Integer = 0 To retStr.Length - 1
2441             Dim index As Integer = retStr.IndexOf("<a ", i)
2442             If index > -1 AndAlso index < retStr.Length Then
2443                 i = index
2444                 Dim toIndex As Integer = retStr.IndexOf("</a>", index)
2445                 If toIndex > -1 Then
2446                     anchorRange.Add(New range(index, toIndex + 3))
2447                     i = toIndex
2448                 End If
2449             End If
2450         Next
2451         retStr = Regex.Replace(retStr,
2452                                "(^|[^a-zA-Z0-9/&])([##])([0-9a-zA-Z_]*[a-zA-Z_]+[a-zA-Z0-9_\xc0-\xd6\xd8-\xf6\xf8-\xff]*)",
2453                                New MatchEvaluator(Function(mh As Match)
2454                                                       For Each rng As range In anchorRange
2455                                                           If mh.Index >= rng.fromIndex AndAlso
2456                                                            mh.Index <= rng.toIndex Then Return mh.Result("$0")
2457                                                       Next
2458                                                       If IsNumeric(mh.Result("$3")) Then Return mh.Result("$0")
2459                                                       SyncLock LockObj
2460                                                           _hashList.Add("#" + mh.Result("$3"))
2461                                                       End SyncLock
2462                                                       Return mh.Result("$1") + "<a href=""" & _protocol & "twitter.com/search?q=%23" + mh.Result("$3") + """>" + mh.Result("$2$3") + "</a>"
2463                                                   End Function),
2464                                               RegexOptions.IgnoreCase)
2465
2466         'Dim mhs As MatchCollection = Regex.Matches(retStr, "(^|[^a-zA-Z0-9/&])[##]([0-9a-zA-Z_]*[a-zA-Z_]+[a-zA-Z_\xc0-\xd6\xd8-\xf6\xf8-\xff]*)")
2467         'For Each mt As Match In mhs
2468         '    If Not IsNumeric(mt.Result("$2")) Then
2469         '        'retStr = retStr.Replace(mt.Result("$1") + mt.Result("$2"), "<a href=""" + _protocol + "twitter.com/search?q=%23" + mt.Result("$2") + """>#" + mt.Result("$2") + "</a>")
2470         '        SyncLock LockObj
2471         '            _hashList.Add("#" + mt.Result("$2"))
2472         '        End SyncLock
2473         '    End If
2474         'Next
2475         'retStr = Regex.Replace(retStr, "(^|[^a-zA-Z0-9/&])([##])([0-9a-zA-Z_]*[a-zA-Z_]+[a-zA-Z0-9_\xc0-\xd6\xd8-\xf6\xf8-\xff]*)", "$1<a href=""" & _protocol & "twitter.com/search?q=%23$3"">$2$3</a>")
2476
2477         retStr = Regex.Replace(retStr, "(^|[^a-zA-Z0-9_/&##@@>=.])(sm|nm)([0-9]{1,10})", "$1<a href=""http://www.nicovideo.jp/watch/$2$3"">$2$3</a>")
2478
2479         retStr = retStr.Replace("<<<<<tweenだいなり>>>>>", "&gt;").Replace("<<<<<tweenしょうなり>>>>>", "&lt;")
2480
2481         retStr = AdjustHtml(ShortUrl.Resolve(PreProcessUrl(retStr))) 'IDN置換、短縮Uri解決、@リンクを相対→絶対にしてtarget属性付与
2482         Return retStr
2483     End Function
2484
2485     'Source整形
2486     Private Sub CreateSource(ByRef post As PostClass)
2487         If post.Source.StartsWith("<") Then
2488             If Not post.Source.Contains("</a>") Then
2489                 post.Source += "</a>"
2490             End If
2491             post.SourceHtml = String.Copy(ShortUrl.Resolve(PreProcessUrl(post.Source)))
2492             Dim mS As Match = Regex.Match(post.Source, ">(?<source>.+)<")
2493             If mS.Success Then
2494                 post.Source = HttpUtility.HtmlDecode(mS.Result("${source}"))
2495             End If
2496         Else
2497             If post.Source = "web" Then
2498                 post.SourceHtml = My.Resources.WebSourceString
2499             ElseIf post.Source = "Keitai Mail" Then
2500                 post.SourceHtml = My.Resources.KeitaiMailSourceString
2501             Else
2502                 post.SourceHtml = String.Copy(post.Source)
2503             End If
2504         End If
2505     End Sub
2506
2507     Public Function GetInfoApi(ByVal info As ApiInfo) As Boolean
2508         If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return True
2509
2510         If _endingFlag Then Return True
2511
2512         Dim res As HttpStatusCode
2513         Dim content As String = ""
2514         Try
2515             res = twCon.RateLimitStatus(content)
2516         Catch ex As Exception
2517             TwitterApiInfo.Initialize()
2518             Return False
2519         End Try
2520
2521         If res <> HttpStatusCode.OK Then Return False
2522
2523         Dim xdoc As New XmlDocument
2524         Try
2525             xdoc.LoadXml(content)
2526             Dim arg As New ApiInformationChangedEventArgs
2527
2528             arg.ApiInfo.MaxCount = Integer.Parse(xdoc.SelectSingleNode("/hash/hourly-limit").InnerText)
2529             arg.ApiInfo.RemainCount = Integer.Parse(xdoc.SelectSingleNode("/hash/remaining-hits").InnerText)
2530             arg.ApiInfo.ResetTime = DateTime.Parse(xdoc.SelectSingleNode("/hash/reset-time").InnerText)
2531             arg.ApiInfo.ResetTimeInSeconds = Integer.Parse(xdoc.SelectSingleNode("/hash/reset-time-in-seconds").InnerText)
2532             If info IsNot Nothing Then
2533                 arg.ApiInfo.UsingCount = info.UsingCount
2534
2535                 info.MaxCount = arg.ApiInfo.MaxCount
2536                 info.RemainCount = arg.ApiInfo.RemainCount
2537                 info.ResetTime = arg.ApiInfo.ResetTime
2538                 info.ResetTimeInSeconds = arg.ApiInfo.ResetTimeInSeconds
2539             End If
2540
2541             RaiseEvent ApiInformationChanged(Me, arg)
2542             TwitterApiInfo.WriteBackEventArgs(arg)
2543             Return True
2544         Catch ex As Exception
2545             TwitterApiInfo.Initialize()
2546             Return False
2547         End Try
2548     End Function
2549
2550     Public Function GetHashList() As String()
2551         Dim hashArray As String()
2552         SyncLock LockObj
2553             hashArray = _hashList.ToArray
2554             _hashList.Clear()
2555         End SyncLock
2556         Return hashArray
2557     End Function
2558
2559     Public ReadOnly Property AccessToken() As String
2560         Get
2561             Return twCon.AccessToken
2562         End Get
2563     End Property
2564
2565     Public ReadOnly Property AccessTokenSecret() As String
2566         Get
2567             Return twCon.AccessTokenSecret
2568         End Get
2569     End Property
2570
2571     Public Property UserIdNo As String
2572
2573     Public Event ApiInformationChanged(ByVal sender As Object, ByVal e As ApiInformationChangedEventArgs)
2574
2575     Private Sub Twitter_ApiInformationChanged(ByVal sender As Object, ByVal e As ApiInformationChangedEventArgs) Handles Me.ApiInformationChanged
2576     End Sub
2577 End Class