1 ' Tween - Client of Twitter
2 ' Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 ' (c) 2008-2011 Moz (@syo68k)
4 ' (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 ' (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 ' (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
9 ' This file is part of Tween.
11 ' This program is free software; you can redistribute it and/or modify it
12 ' under the terms of the GNU General Public License as published by the Free
13 ' Software Foundation; either version 3 of the License, or (at your option)
16 ' This program is distributed in the hope that it will be useful, but
17 ' WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 ' or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 ' You should have received a copy of the GNU General Public License along
22 ' with this program. If not, see <http://www.gnu.org/licenses/>, or write to
23 ' the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
24 ' Boston, MA 02110-1301, USA.
26 Imports System.Diagnostics
30 Imports System.Reflection.MethodBase
31 Imports System.Runtime.Serialization
32 Imports System.Runtime.Serialization.Json
34 Imports System.Text.RegularExpressions
35 Imports System.Threading
38 Imports System.Xml.Linq
41 Implements IDisposable
44 Private Const LATIN_ACCENTS As String = "\xc0-\xd6\xd8-\xf6\xf8-\xff"
45 Private Const NON_LATIN_HASHTAG_CHARS As String = "\u0400-\u04ff\u0500-\u0527\u1100-\u11ff\u3130-\u3185\uA960-\uA97F\uAC00-\uD7AF\uD7B0-\uD7FF"
46 'Private Const CJ_HASHTAG_CHARACTERS As String = "\u30A1-\u30FA\uFF66-\uFF9F\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\u3041-\u3096\u3400-\u4DBF\u4E00-\u9FFF\u20000-\u2A6DF\u2A700-\u2B73F\u2B740-\u2B81F\u2F800-\u2FA1F"
47 Private Const CJ_HASHTAG_CHARACTERS As String = "\u30A1-\u30FA\u30FC\u3005\uFF66-\uFF9F\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\u3041-\u309A\u3400-\u4DBF\p{IsCJKUnifiedIdeographs}"
48 Private Const HASHTAG_BOUNDARY As String = "^|$|\s|「|」|。|\.|!"
49 Private Const HASHTAG_ALPHA As String = "[a-z_" + LATIN_ACCENTS + NON_LATIN_HASHTAG_CHARS + CJ_HASHTAG_CHARACTERS + "]"
50 Private Const HASHTAG_ALPHANUMERIC As String = "[a-z0-9_" + LATIN_ACCENTS + NON_LATIN_HASHTAG_CHARS + CJ_HASHTAG_CHARACTERS + "]"
51 Private Const HASHTAG_TERMINATOR As String = "[^a-z0-9_" + LATIN_ACCENTS + NON_LATIN_HASHTAG_CHARS + CJ_HASHTAG_CHARACTERS + "]"
52 Public Const HASHTAG As String = "(" + HASHTAG_BOUNDARY + ")(#|#)(" + HASHTAG_ALPHANUMERIC + "*" + HASHTAG_ALPHA + HASHTAG_ALPHANUMERIC + "*)(?=" + HASHTAG_TERMINATOR + "|" + HASHTAG_BOUNDARY + ")"
54 Private Const url_valid_domain As String = "(?<domain>(?:[^\p{P}\s][\.\-_](?=[^\p{P}\s])|[^\p{P}\s]){1,}\.[a-z]{2,}(?::[0-9]+)?)"
55 Private Const url_valid_general_path_chars As String = "[a-z0-9!*';:=+$/%#\[\]\-_,~]"
56 Private Const url_balance_parens As String = "(?:\(" + url_valid_general_path_chars + "+\))"
57 Private Const url_valid_url_path_ending_chars As String = "(?:[a-z0-9=_#/\-\+]+|" + url_balance_parens + ")"
58 Private Const pth As String = "(?:" + url_balance_parens +
59 "|@" + url_valid_general_path_chars + "+/" +
60 "|[.,]?" + url_valid_general_path_chars + "+" +
62 Private Const pth2 As String = "(/(?:" +
63 pth + "+" + url_valid_url_path_ending_chars + "|" +
64 pth + "+" + url_valid_url_path_ending_chars + "?|" +
65 url_valid_url_path_ending_chars +
67 Private Const qry As String = "(?<query>\?[a-z0-9!*'();:&=+$/%#\[\]\-_.,~]*[a-z0-9_&=#])?"
68 Public Const rgUrl As String = "(?<before>(?:[^\""':!=#]|^|\:/))" +
69 "(?<url>(?<protocol>https?://)" +
74 Delegate Sub GetIconImageDelegate(ByVal post As PostClass)
75 Private ReadOnly LockObj As New Object
76 Private followerId As New List(Of Long)
77 Private _GetFollowerResult As Boolean = False
78 Private noRTId As New List(Of Long)
79 Private _GetNoRetweetResult As Boolean = False
81 Private _followersCount As Integer = 0
82 Private _friendsCount As Integer = 0
83 Private _statusesCount As Integer = 0
84 Private _location As String = ""
85 Private _bio As String = ""
86 Private _protocol As String = "https://"
89 Private _uname As String
90 Private _iconSz As Integer
91 Private _getIcon As Boolean
92 Private _dIcon As IDictionary(Of String, Image)
94 Private _tinyUrlResolve As Boolean
95 Private _restrictFavCheck As Boolean
97 Private _hubServer As String
98 Private _readOwnPost As Boolean
99 Private _hashList As New List(Of String)
102 Private _remainCountApi As Integer = -1
104 Private op As New Outputz
105 'max_idで古い発言を取得するために保持(lists分は個別タブで管理)
106 Private minHomeTimeline As Long = Long.MaxValue
107 Private minMentions As Long = Long.MaxValue
108 Private minDirectmessage As Long = Long.MaxValue
109 Private minDirectmessageSent As Long = Long.MaxValue
111 Private twCon As New HttpTwitter
113 Public Event UserIdChanged()
115 'Private _deletemessages As New List(Of PostClass)
117 Public Overloads Function Authenticate(ByVal username As String, ByVal password As String) As String
119 Dim res As HttpStatusCode
120 Dim content As String = ""
122 TwitterApiInfo.Initialize()
124 res = twCon.AuthUserAndPass(username, password, content)
125 Catch ex As Exception
126 Return "Err:" + ex.Message
130 Case HttpStatusCode.OK
131 Twitter.AccountState = ACCOUNT_STATE.Valid
132 _uname = username.ToLower
133 If AppendSettingDialog.Instance.UserstreamStartup Then Me.ReconnectUserStream()
135 Case HttpStatusCode.Unauthorized
136 Twitter.AccountState = ACCOUNT_STATE.Invalid
137 Dim errMsg As String = GetErrorMessageJson(content)
138 If String.IsNullOrEmpty(errMsg) Then
139 Return My.Resources.Unauthorized + Environment.NewLine + content
141 Return "Auth error:" + errMsg
143 Case HttpStatusCode.Forbidden
144 Dim errMsg As String = GetErrorMessageJson(content)
145 If String.IsNullOrEmpty(errMsg) Then
146 Return "Err:Forbidden"
148 Return "Err:" + errMsg
151 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
156 Public Function StartAuthentication(ByRef pinPageUrl As String) As String
159 Dim content As String = ""
161 TwitterApiInfo.Initialize()
163 res = twCon.AuthGetRequestToken(pinPageUrl)
164 Catch ex As Exception
165 Return "Err:" + "Failed to access auth server."
171 Public Overloads Function Authenticate(ByVal pinCode As String) As String
173 Dim res As HttpStatusCode
174 Dim content As String = ""
176 TwitterApiInfo.Initialize()
178 res = twCon.AuthGetAccessToken(pinCode)
179 Catch ex As Exception
180 Return "Err:" + "Failed to access auth acc server."
184 Case HttpStatusCode.OK
185 Twitter.AccountState = ACCOUNT_STATE.Valid
186 _uname = Username.ToLower
187 If AppendSettingDialog.Instance.UserstreamStartup Then Me.ReconnectUserStream()
188 Google.GASender.GetInstance().TrackEventWithCategory("post", "authenticate", Me.UserId)
190 Case HttpStatusCode.Unauthorized
191 Twitter.AccountState = ACCOUNT_STATE.Invalid
192 Dim errMsg As String = GetErrorMessageJson(content)
193 If String.IsNullOrEmpty(errMsg) Then
194 Return "Check the PIN or retry." + Environment.NewLine + content
196 Return "Auth error:" + errMsg
198 Case HttpStatusCode.Forbidden
199 Dim errMsg As String = GetErrorMessageJson(content)
200 If String.IsNullOrEmpty(errMsg) Then
201 Return "Err:Forbidden"
203 Return "Err:" + errMsg
206 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
211 Public Sub ClearAuthInfo()
212 Twitter.AccountState = ACCOUNT_STATE.Invalid
213 TwitterApiInfo.Initialize()
214 twCon.ClearAuthInfo()
217 Public Sub VerifyCredentials()
218 Dim res As HttpStatusCode
219 Dim content As String = ""
222 res = twCon.VerifyCredentials(content)
223 Catch ex As Exception
227 If res = HttpStatusCode.OK Then
228 Twitter.AccountState = ACCOUNT_STATE.Valid
229 Dim user As TwitterDataModel.User
231 user = CreateDataFromJson(Of TwitterDataModel.User)(content)
232 Catch ex As SerializationException
235 twCon.AuthenticatedUserId = user.Id
239 Private Function GetErrorMessageJson(ByVal content As String) As String
241 If Not String.IsNullOrEmpty(content) Then
242 Using jsonReader As XmlDictionaryReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(content), XmlDictionaryReaderQuotas.Max)
243 Dim xElm As XElement = XElement.Load(jsonReader)
244 If xElm.Element("error") IsNot Nothing Then
245 Return xElm.Element("error").Value
253 Catch ex As Exception
258 Public Sub Initialize(ByVal token As String, ByVal tokenSecret As String, ByVal username As String, ByVal userId As Long)
260 If String.IsNullOrEmpty(token) OrElse String.IsNullOrEmpty(tokenSecret) OrElse String.IsNullOrEmpty(username) Then
261 Twitter.AccountState = ACCOUNT_STATE.Invalid
263 TwitterApiInfo.Initialize()
264 twCon.Initialize(token, tokenSecret, username, userId)
265 _uname = username.ToLower
266 If AppendSettingDialog.Instance.UserstreamStartup Then Me.ReconnectUserStream()
269 Public Function PreProcessUrl(ByVal orgData As String) As String
271 Dim posl2 As Integer = 0
272 'Dim IDNConveter As IdnMapping = New IdnMapping()
273 Dim href As String = "<a href="""
276 If orgData.IndexOf(href, posl2, StringComparison.Ordinal) > -1 Then
277 Dim urlStr As String = ""
279 posl1 = orgData.IndexOf(href, posl2, StringComparison.Ordinal)
281 posl2 = orgData.IndexOf("""", posl1, StringComparison.Ordinal)
282 urlStr = orgData.Substring(posl1, posl2 - posl1)
284 If Not urlStr.StartsWith("http://") AndAlso Not urlStr.StartsWith("https://") AndAlso Not urlStr.StartsWith("ftp://") Then
288 Dim replacedUrl As String = IDNDecode(urlStr)
289 If replacedUrl Is Nothing Then Continue Do
290 If replacedUrl = urlStr Then Continue Do
292 orgData = orgData.Replace("<a href=""" + urlStr, "<a href=""" + replacedUrl)
301 Private Function GetPlainText(ByVal orgData As String) As String
302 Return HttpUtility.HtmlDecode(Regex.Replace(orgData, "(?<tagStart><a [^>]+>)(?<text>[^<]+)(?<tagEnd></a>)", "${text}"))
305 ' htmlの簡易サニタイズ(詳細表示に不要なタグの除去)
307 Private Function SanitizeHtml(ByVal orgdata As String) As String
308 Dim retdata As String = orgdata
310 retdata = Regex.Replace(retdata, "<(script|object|applet|image|frameset|fieldset|legend|style).*" & _
311 "</(script|object|applet|image|frameset|fieldset|legend|style)>", "", RegexOptions.IgnoreCase)
313 retdata = Regex.Replace(retdata, "<(frame|link|iframe|img)>", "", RegexOptions.IgnoreCase)
318 Private Function AdjustHtml(ByVal orgData As String) As String
319 Dim retStr As String = orgData
320 'Dim m As Match = Regex.Match(retStr, "<a [^>]+>[#|#](?<1>[a-zA-Z0-9_]+)</a>")
323 ' _hashList.Add("#" + m.Groups(1).Value)
327 retStr = Regex.Replace(retStr, "<a [^>]*href=""/", "<a href=""" + _protocol + "twitter.com/")
328 retStr = retStr.Replace("<a href=", "<a target=""_self"" href=")
329 retStr = retStr.Replace(vbLf, "<br>")
331 '半角スペースを置換(Thanks @anis774)
332 Dim ret As Boolean = False
334 ret = EscapeSpace(retStr)
337 Return SanitizeHtml(retStr)
340 Private Function EscapeSpace(ByRef html As String) As Boolean
341 '半角スペースを置換(Thanks @anis774)
342 Dim isTag As Boolean = False
343 For i As Integer = 0 To html.Length - 1
344 If html(i) = "<"c Then
347 If html(i) = ">"c Then
351 If (Not isTag) AndAlso (html(i) = " "c) Then
352 html = html.Remove(i, 1)
353 html = html.Insert(i, " ")
360 Private Structure PostInfo
361 Public CreatedAt As String
363 Public Text As String
364 Public UserId As String
365 Public Sub New(ByVal Created As String, ByVal IdStr As String, ByVal txt As String, ByVal uid As String)
371 Public Shadows Function Equals(ByVal dst As PostInfo) As Boolean
372 If Me.CreatedAt = dst.CreatedAt AndAlso Me.Id = dst.Id AndAlso Me.Text = dst.Text AndAlso Me.UserId = dst.UserId Then
380 Private Function IsPostRestricted(ByVal status As TwitterDataModel.Status) As Boolean
381 Static _prev As New PostInfo("", "", "", "")
382 Dim _current As New PostInfo("", "", "", "")
384 _current.CreatedAt = status.CreatedAt
385 _current.Id = status.IdStr
386 If status.Text Is Nothing Then
389 _current.Text = status.Text
391 _current.UserId = status.User.IdStr
393 If _current.Equals(_prev) Then
396 _prev.CreatedAt = _current.CreatedAt
397 _prev.Id = _current.Id
398 _prev.Text = _current.Text
399 _prev.UserId = _current.UserId
404 Public Function PostStatus(ByVal postStr As String, ByVal reply_to As Long) As String
406 If _endingFlag Then Return ""
408 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
410 postStr = postStr.Trim()
412 If Regex.Match(postStr, "^DM? +(?<id>[a-zA-Z0-9_]+) +(?<body>.+)", RegexOptions.IgnoreCase Or RegexOptions.Singleline).Success Then
413 Return SendDirectMessage(postStr)
416 Google.GASender.GetInstance().TrackEventWithCategory("post", "status", Me.UserId)
418 Dim res As HttpStatusCode
419 Dim content As String = ""
421 res = twCon.UpdateStatus(postStr, reply_to, content)
422 Catch ex As Exception
423 Return "Err:" + ex.Message
427 Case HttpStatusCode.OK
428 Twitter.AccountState = ACCOUNT_STATE.Valid
429 Dim status As TwitterDataModel.Status
431 status = CreateDataFromJson(Of TwitterDataModel.Status)(content)
432 Catch ex As SerializationException
433 TraceOut(ex.Message + Environment.NewLine + content)
434 Return "Err:Json Parse Error(DataContractJsonSerializer)"
435 Catch ex As Exception
436 TraceOut(ex, GetCurrentMethod.Name & " " & content)
437 Return "Err:Invalid Json!"
439 _followersCount = status.User.FollowersCount
440 _friendsCount = status.User.FriendsCount
441 _statusesCount = status.User.StatusesCount
442 _location = status.User.Location
443 _bio = status.User.Description
445 If IsPostRestricted(status) Then
446 Return "OK:Delaying?"
448 If op.Post(postStr.Length) Then
451 Return "Outputz:Failed"
453 Case HttpStatusCode.NotFound
455 Case HttpStatusCode.Forbidden, HttpStatusCode.BadRequest
456 Dim errMsg As String = GetErrorMessageJson(content)
457 If String.IsNullOrEmpty(errMsg) Then
458 Return "Warn:" + res.ToString
460 Return "Warn:" + errMsg
462 Case HttpStatusCode.Conflict, _
463 HttpStatusCode.ExpectationFailed, _
464 HttpStatusCode.Gone, _
465 HttpStatusCode.LengthRequired, _
466 HttpStatusCode.MethodNotAllowed, _
467 HttpStatusCode.NotAcceptable, _
468 HttpStatusCode.NotFound, _
469 HttpStatusCode.PaymentRequired, _
470 HttpStatusCode.PreconditionFailed, _
471 HttpStatusCode.RequestedRangeNotSatisfiable, _
472 HttpStatusCode.RequestEntityTooLarge, _
473 HttpStatusCode.RequestTimeout, _
474 HttpStatusCode.RequestUriTooLong
475 '仕様書にない400系エラー。サーバまでは到達しているのでリトライしない
476 Return "Warn:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
477 Case HttpStatusCode.Unauthorized
478 Twitter.AccountState = ACCOUNT_STATE.Invalid
479 Dim errMsg As String = GetErrorMessageJson(content)
480 If String.IsNullOrEmpty(errMsg) Then
481 Return My.Resources.Unauthorized
483 Return "Auth err:" + errMsg
486 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
490 Public Function PostStatusWithMedia(ByVal postStr As String, ByVal reply_to As Long, ByVal mediaFile As FileInfo) As String
492 If _endingFlag Then Return ""
494 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
496 postStr = postStr.Trim()
498 Google.GASender.GetInstance().TrackEventWithCategory("post", "status_with_media", Me.UserId)
500 Dim res As HttpStatusCode
501 Dim content As String = ""
503 res = twCon.UpdateStatusWithMedia(postStr, reply_to, mediaFile, content)
504 Catch ex As Exception
505 Return "Err:" + ex.Message
509 Case HttpStatusCode.OK
510 Twitter.AccountState = ACCOUNT_STATE.Valid
511 Dim status As TwitterDataModel.Status
513 status = CreateDataFromJson(Of TwitterDataModel.Status)(content)
514 Catch ex As SerializationException
515 TraceOut(ex.Message + Environment.NewLine + content)
516 Return "Err:Json Parse Error(DataContractJsonSerializer)"
517 Catch ex As Exception
518 TraceOut(ex, GetCurrentMethod.Name & " " & content)
519 Return "Err:Invalid Json!"
521 _followersCount = status.User.FollowersCount
522 _friendsCount = status.User.FriendsCount
523 _statusesCount = status.User.StatusesCount
524 _location = status.User.Location
525 _bio = status.User.Description
527 If IsPostRestricted(status) Then
528 Return "OK:Delaying?"
530 If op.Post(postStr.Length) Then
533 Return "Outputz:Failed"
535 Case HttpStatusCode.NotFound
537 Case HttpStatusCode.Forbidden, HttpStatusCode.BadRequest
538 Dim errMsg As String = GetErrorMessageJson(content)
539 If String.IsNullOrEmpty(errMsg) Then
540 Return "Warn:" + res.ToString
542 Return "Warn:" + errMsg
544 Case HttpStatusCode.Conflict, _
545 HttpStatusCode.ExpectationFailed, _
546 HttpStatusCode.Gone, _
547 HttpStatusCode.LengthRequired, _
548 HttpStatusCode.MethodNotAllowed, _
549 HttpStatusCode.NotAcceptable, _
550 HttpStatusCode.NotFound, _
551 HttpStatusCode.PaymentRequired, _
552 HttpStatusCode.PreconditionFailed, _
553 HttpStatusCode.RequestedRangeNotSatisfiable, _
554 HttpStatusCode.RequestEntityTooLarge, _
555 HttpStatusCode.RequestTimeout, _
556 HttpStatusCode.RequestUriTooLong
557 '仕様書にない400系エラー。サーバまでは到達しているのでリトライしない
558 Return "Warn:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
559 Case HttpStatusCode.Unauthorized
560 Twitter.AccountState = ACCOUNT_STATE.Invalid
561 Dim errMsg As String = GetErrorMessageJson(content)
562 If String.IsNullOrEmpty(errMsg) Then
563 Return My.Resources.Unauthorized
565 Return "Auth err:" + errMsg
568 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
572 Public Function SendDirectMessage(ByVal postStr As String) As String
574 If _endingFlag Then Return ""
576 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
577 If Not TwitterApiInfo.IsDirectMessagePermission Then Return "Auth Err:try to re-authorization."
579 Google.GASender.GetInstance().TrackEventWithCategory("post", "direct_message", Me.UserId)
581 postStr = postStr.Trim()
583 Dim res As HttpStatusCode
584 Dim content As String = ""
586 Dim mc As Match = Regex.Match(postStr, "^DM? +(?<id>[a-zA-Z0-9_]+) +(?<body>.+)", RegexOptions.IgnoreCase Or RegexOptions.Singleline)
589 res = twCon.SendDirectMessage(mc.Groups("body").Value, mc.Groups("id").Value, content)
590 Catch ex As Exception
591 Return "Err:" + ex.Message
595 Case HttpStatusCode.OK
596 Twitter.AccountState = ACCOUNT_STATE.Valid
597 Dim status As TwitterDataModel.Directmessage
599 status = CreateDataFromJson(Of TwitterDataModel.Directmessage)(content)
600 Catch ex As SerializationException
601 TraceOut(ex.Message + Environment.NewLine + content)
602 Return "Err:Json Parse Error(DataContractJsonSerializer)"
603 Catch ex As Exception
604 TraceOut(ex, GetCurrentMethod.Name & " " & content)
605 Return "Err:Invalid Json!"
607 _followersCount = status.Sender.FollowersCount
608 _friendsCount = status.Sender.FriendsCount
609 _statusesCount = status.Sender.StatusesCount
610 _location = status.Sender.Location
611 _bio = status.Sender.Description
613 If op.Post(postStr.Length) Then
616 Return "Outputz:Failed"
618 Case HttpStatusCode.Forbidden, HttpStatusCode.BadRequest
619 Dim errMsg As String = GetErrorMessageJson(content)
620 If String.IsNullOrEmpty(errMsg) Then
621 Return "Warn:" + res.ToString
623 Return "Warn:" + errMsg
625 Case HttpStatusCode.Conflict, _
626 HttpStatusCode.ExpectationFailed, _
627 HttpStatusCode.Gone, _
628 HttpStatusCode.LengthRequired, _
629 HttpStatusCode.MethodNotAllowed, _
630 HttpStatusCode.NotAcceptable, _
631 HttpStatusCode.NotFound, _
632 HttpStatusCode.PaymentRequired, _
633 HttpStatusCode.PreconditionFailed, _
634 HttpStatusCode.RequestedRangeNotSatisfiable, _
635 HttpStatusCode.RequestEntityTooLarge, _
636 HttpStatusCode.RequestTimeout, _
637 HttpStatusCode.RequestUriTooLong
638 '仕様書にない400系エラー。サーバまでは到達しているのでリトライしない
639 Return "Warn:" + res.ToString
640 Case HttpStatusCode.Unauthorized
641 Twitter.AccountState = ACCOUNT_STATE.Invalid
642 Dim errMsg As String = GetErrorMessageJson(content)
643 If String.IsNullOrEmpty(errMsg) Then
644 Return My.Resources.Unauthorized
646 Return "Auth err:" + errMsg
649 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
653 Public Function RemoveStatus(ByVal id As Long) As String
654 If _endingFlag Then Return ""
656 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
658 Google.GASender.GetInstance().TrackEventWithCategory("post", "destroy", Me.UserId)
659 Dim res As HttpStatusCode
662 res = twCon.DestroyStatus(id)
663 Catch ex As Exception
664 Return "Err:" + ex.Message
668 Case HttpStatusCode.OK
669 Twitter.AccountState = ACCOUNT_STATE.Valid
671 Case HttpStatusCode.Unauthorized
672 Twitter.AccountState = ACCOUNT_STATE.Invalid
673 Return My.Resources.Unauthorized
674 Case HttpStatusCode.NotFound
677 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
682 Public Function PostRetweet(ByVal id As Long, ByVal read As Boolean) As String
683 If _endingFlag Then Return ""
684 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
687 Dim target As Long = id
688 Dim post As PostClass = TabInformations.GetInstance.Item(id)
689 If post Is Nothing Then
690 Return "Err:Target isn't found."
692 If TabInformations.GetInstance.Item(id).RetweetedId > 0 Then
693 target = TabInformations.GetInstance.Item(id).RetweetedId '再RTの場合は元発言をRT
696 Google.GASender.GetInstance().TrackEventWithCategory("post", "retweet", Me.UserId)
697 Dim res As HttpStatusCode
698 Dim content As String = ""
700 res = twCon.RetweetStatus(target, content)
701 Catch ex As Exception
702 Return "Err:" + ex.Message
706 Case HttpStatusCode.Unauthorized
707 'Blockユーザーの発言をRTすると認証エラー返る
708 'Twitter.AccountState = ACCOUNT_STATE.Invalid
709 Return My.Resources.Unauthorized + " or blocked user."
710 Case Is <> HttpStatusCode.OK
711 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
714 Twitter.AccountState = ACCOUNT_STATE.Valid
716 Dim status As TwitterDataModel.Status
718 status = CreateDataFromJson(Of TwitterDataModel.Status)(content)
719 Catch ex As SerializationException
720 TraceOut(ex.Message + Environment.NewLine + content)
721 Return "Err:Json Parse Error(DataContractJsonSerializer)"
722 Catch ex As Exception
723 TraceOut(ex, GetCurrentMethod.Name & " " & content)
724 Return "Err:Invalid Json!"
728 post = CreatePostsFromStatusData(status)
729 If post Is Nothing Then Return "Invalid Json!"
733 If TabInformations.GetInstance.ContainsKey(post.StatusId) Then Return ""
736 If post.RetweetedId = 0 Then Return "Invalid Json!"
742 If _readOwnPost Then post.IsRead = True
745 TabInformations.GetInstance.AddPost(post)
750 Public Function RemoveDirectMessage(ByVal id As Long, ByVal post As PostClass) As String
751 If _endingFlag Then Return ""
753 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
754 If Not TwitterApiInfo.IsDirectMessagePermission Then Return "Auth Err:try to re-authorization."
756 Google.GASender.GetInstance().TrackEventWithCategory("post", "destroy_direct_message", Me.UserId)
757 Dim res As HttpStatusCode
760 ' _deletemessages.Add(post)
763 res = twCon.DestroyDirectMessage(id)
764 Catch ex As Exception
765 Return "Err:" + ex.Message
769 Case HttpStatusCode.OK
770 Twitter.AccountState = ACCOUNT_STATE.Valid
772 Case HttpStatusCode.Unauthorized
773 Twitter.AccountState = ACCOUNT_STATE.Invalid
774 Return My.Resources.Unauthorized
775 Case HttpStatusCode.NotFound
778 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
782 Public Function PostFollowCommand(ByVal screenName As String) As String
784 If _endingFlag Then Return ""
786 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
788 Google.GASender.GetInstance().TrackEventWithCategory("post", "follow", Me.UserId)
789 Dim res As HttpStatusCode
790 Dim content As String = ""
793 res = twCon.CreateFriendships(screenName, content)
794 Catch ex As Exception
795 Return "Err:" + ex.Message
799 Case HttpStatusCode.OK
800 Twitter.AccountState = ACCOUNT_STATE.Valid
802 Case HttpStatusCode.Unauthorized
803 Twitter.AccountState = ACCOUNT_STATE.Invalid
804 Return My.Resources.Unauthorized
805 Case HttpStatusCode.Forbidden
806 Dim errMsg As String = GetErrorMessageJson(content)
807 If String.IsNullOrEmpty(errMsg) Then
808 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
810 Return "Err:" + errMsg
813 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
817 Public Function PostRemoveCommand(ByVal screenName As String) As String
819 If _endingFlag Then Return ""
821 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
823 Google.GASender.GetInstance().TrackEventWithCategory("post", "destroy_friendships", Me.UserId)
824 Dim res As HttpStatusCode
825 Dim content As String = ""
828 res = twCon.DestroyFriendships(screenName, content)
829 Catch ex As Exception
830 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
834 Case HttpStatusCode.OK
835 Twitter.AccountState = ACCOUNT_STATE.Valid
837 Case HttpStatusCode.Unauthorized
838 Twitter.AccountState = ACCOUNT_STATE.Invalid
839 Return My.Resources.Unauthorized
840 Case HttpStatusCode.Forbidden
841 Dim errMsg As String = GetErrorMessageJson(content)
842 If String.IsNullOrEmpty(errMsg) Then
843 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
845 Return "Err:" + errMsg
848 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
852 Public Function PostCreateBlock(ByVal screenName As String) As String
854 If _endingFlag Then Return ""
856 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
858 Google.GASender.GetInstance().TrackEventWithCategory("post", "block", Me.UserId)
859 Dim res As HttpStatusCode
860 Dim content As String = ""
863 res = twCon.CreateBlock(screenName, content)
864 Catch ex As Exception
865 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
869 Case HttpStatusCode.OK
870 Twitter.AccountState = ACCOUNT_STATE.Valid
872 Case HttpStatusCode.Unauthorized
873 Twitter.AccountState = ACCOUNT_STATE.Invalid
874 Return My.Resources.Unauthorized
875 Case HttpStatusCode.Forbidden
876 Dim errMsg As String = GetErrorMessageJson(content)
877 If String.IsNullOrEmpty(errMsg) Then
878 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
880 Return "Err:" + errMsg
883 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
887 Public Function PostDestroyBlock(ByVal screenName As String) As String
889 If _endingFlag Then Return ""
891 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
893 Google.GASender.GetInstance().TrackEventWithCategory("post", "destroy_block", Me.UserId)
894 Dim res As HttpStatusCode
895 Dim content As String = ""
898 res = twCon.DestroyBlock(screenName, content)
899 Catch ex As Exception
900 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
904 Case HttpStatusCode.OK
905 Twitter.AccountState = ACCOUNT_STATE.Valid
907 Case HttpStatusCode.Unauthorized
908 Twitter.AccountState = ACCOUNT_STATE.Invalid
909 Return My.Resources.Unauthorized
910 Case HttpStatusCode.Forbidden
911 Dim errMsg As String = GetErrorMessageJson(content)
912 If String.IsNullOrEmpty(errMsg) Then
913 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
915 Return "Err:" + errMsg
918 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
922 Public Function PostReportSpam(ByVal screenName As String) As String
924 If _endingFlag Then Return ""
926 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
928 Google.GASender.GetInstance().TrackEventWithCategory("post", "spam", Me.UserId)
929 Dim res As HttpStatusCode
930 Dim content As String = ""
933 res = twCon.ReportSpam(screenName, content)
934 Catch ex As Exception
935 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
939 Case HttpStatusCode.OK
940 Twitter.AccountState = ACCOUNT_STATE.Valid
942 Case HttpStatusCode.Unauthorized
943 Twitter.AccountState = ACCOUNT_STATE.Invalid
944 Return My.Resources.Unauthorized
945 Case HttpStatusCode.Forbidden
946 Dim errMsg As String = GetErrorMessageJson(content)
947 If String.IsNullOrEmpty(errMsg) Then
948 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
950 Return "Err:" + errMsg
953 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
957 Public Function GetFriendshipInfo(ByVal screenName As String, ByRef isFollowing As Boolean, ByRef isFollowed As Boolean) As String
959 If _endingFlag Then Return ""
961 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
963 Google.GASender.GetInstance().TrackPage("/friendships", Me.UserId)
964 Dim res As HttpStatusCode
965 Dim content As String = ""
967 res = twCon.ShowFriendships(_uname, screenName, content)
968 Catch ex As Exception
969 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
973 Case HttpStatusCode.OK
975 Dim relation = CreateDataFromJson(Of TwitterDataModel.Relationship)(content)
976 isFollowing = relation.Relationship.Source.Following
977 isFollowed = relation.Relationship.Source.FollowedBy
979 Catch ex As SerializationException
980 TraceOut(ex.Message + Environment.NewLine + content)
981 Return "Err:Json Parse Error(DataContractJsonSerializer)"
982 Catch ex As Exception
983 TraceOut(ex, GetCurrentMethod.Name & " " & content)
984 Return "Err:Invalid Json!"
986 Case HttpStatusCode.BadRequest
987 Return "Err:API Limits?"
988 Case HttpStatusCode.Unauthorized
989 Twitter.AccountState = ACCOUNT_STATE.Invalid
990 Return My.Resources.Unauthorized
992 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
996 Public Function GetUserInfo(ByVal screenName As String, ByRef user As TwitterDataModel.User) As String
998 If _endingFlag Then Return ""
1000 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1002 Google.GASender.GetInstance().TrackPage("/showuser", Me.UserId)
1003 Dim res As HttpStatusCode
1004 Dim content As String = ""
1007 res = twCon.ShowUserInfo(screenName, content)
1008 Catch ex As Exception
1009 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
1013 Case HttpStatusCode.OK
1014 Twitter.AccountState = ACCOUNT_STATE.Valid
1016 user = CreateDataFromJson(Of TwitterDataModel.User)(content)
1017 Catch ex As SerializationException
1018 TraceOut(ex.Message + Environment.NewLine + content)
1019 Return "Err:Json Parse Error(DataContractJsonSerializer)"
1020 Catch ex As Exception
1021 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1022 Return "Err:Invalid Json!"
1025 Case HttpStatusCode.BadRequest
1026 Return "Err:API Limits?"
1027 Case HttpStatusCode.Unauthorized
1028 Twitter.AccountState = ACCOUNT_STATE.Invalid
1029 Dim errMsg As String = GetErrorMessageJson(content)
1030 If String.IsNullOrEmpty(errMsg) Then
1031 Return My.Resources.Unauthorized
1033 Return "Auth err:" + errMsg
1036 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1040 Public Function GetStatus_Retweeted_Count(ByVal StatusId As Long, ByRef retweeted_count As Integer) As String
1042 If _endingFlag Then Return ""
1044 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1046 Google.GASender.GetInstance().TrackPage("/retweet_count", Me.UserId)
1047 Dim res As HttpStatusCode
1048 Dim content As String = ""
1049 Dim xmlBuf As String = ""
1053 ' 注:dev.twitter.comに記述されているcountパラメータは間違い。100が正しい
1054 For i As Integer = 1 To 100
1057 res = twCon.Statusid_retweeted_by_ids(StatusId, 100, i, content)
1058 Catch ex As Exception
1059 Return "Err:" + ex.Message
1063 Case HttpStatusCode.OK
1065 Dim ids As Int64() = CreateDataFromJson(Of Int64())(content)
1066 retweeted_count += ids.Length
1067 If ids.Length < 100 Then Exit For
1068 Catch ex As SerializationException
1069 retweeted_count = -1
1070 TraceOut(ex.Message + Environment.NewLine + content)
1071 Return "Err:Json Parse Error(DataContractJsonSerializer)"
1072 Catch ex As Exception
1073 retweeted_count = -1
1074 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1075 Return "Err:Invalid Json!"
1077 Case HttpStatusCode.BadRequest
1078 retweeted_count = -1
1079 Return "Err:API Limits?"
1080 Case HttpStatusCode.Unauthorized
1081 retweeted_count = -1
1082 Twitter.AccountState = ACCOUNT_STATE.Invalid
1083 Return My.Resources.Unauthorized
1085 retweeted_count = -1
1086 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1092 Public Function PostFavAdd(ByVal id As Long) As String
1093 If _endingFlag Then Return ""
1095 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1097 Google.GASender.GetInstance().TrackEventWithCategory("post", "favorites", Me.UserId)
1098 Dim res As HttpStatusCode
1099 Dim content As String = ""
1101 res = twCon.CreateFavorites(id, content)
1102 Catch ex As Exception
1103 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
1107 Case HttpStatusCode.OK
1108 Twitter.AccountState = ACCOUNT_STATE.Valid
1109 If Not _restrictFavCheck Then Return ""
1110 Case HttpStatusCode.Unauthorized
1111 Twitter.AccountState = ACCOUNT_STATE.Invalid
1112 Return My.Resources.Unauthorized
1113 Case HttpStatusCode.Forbidden
1114 Dim errMsg As String = GetErrorMessageJson(content)
1115 If String.IsNullOrEmpty(errMsg) Then
1116 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
1118 Return "Err:" + errMsg
1121 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1124 'http://twitter.com/statuses/show/id.xml APIを発行して本文を取得
1126 'Dim content As String = ""
1129 res = twCon.ShowStatuses(id, content)
1130 Catch ex As Exception
1131 Return "Err:" + ex.Message
1135 Case HttpStatusCode.OK
1136 Twitter.AccountState = ACCOUNT_STATE.Valid
1137 Dim status As TwitterDataModel.Status
1139 status = CreateDataFromJson(Of TwitterDataModel.Status)(content)
1140 Catch ex As SerializationException
1141 TraceOut(ex.Message + Environment.NewLine + content)
1142 Return "Err:Json Parse Error(DataContractJsonSerializer)"
1143 Catch ex As Exception
1144 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1145 Return "Err:Invalid Json!"
1147 If status.Favorited Then
1150 Return "NG(Restricted?)"
1152 Case HttpStatusCode.Unauthorized
1153 Twitter.AccountState = ACCOUNT_STATE.Invalid
1154 Return My.Resources.Unauthorized
1155 Case HttpStatusCode.BadRequest
1156 Return "Err:API Limits?"
1158 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1163 Public Function PostFavRemove(ByVal id As Long) As String
1164 If _endingFlag Then Return ""
1166 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1168 Google.GASender.GetInstance().TrackEventWithCategory("post", "destroy_favorites", Me.UserId)
1169 Dim res As HttpStatusCode
1170 Dim content As String = ""
1172 res = twCon.DestroyFavorites(id, content)
1173 Catch ex As Exception
1174 Return "Err:" + ex.Message
1178 Case HttpStatusCode.OK
1179 Twitter.AccountState = ACCOUNT_STATE.Valid
1181 Case HttpStatusCode.Unauthorized
1182 Twitter.AccountState = ACCOUNT_STATE.Invalid
1183 Return My.Resources.Unauthorized
1184 Case HttpStatusCode.Forbidden
1185 Dim errMsg As String = GetErrorMessageJson(content)
1186 If String.IsNullOrEmpty(errMsg) Then
1187 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
1189 Return "Err:" + errMsg
1192 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1196 Public Function PostUpdateProfile(ByVal name As String, ByVal url As String, ByVal location As String, ByVal description As String) As String
1197 If _endingFlag Then Return ""
1199 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1201 Google.GASender.GetInstance().TrackEventWithCategory("post", "update_profile", Me.UserId)
1202 Dim res As HttpStatusCode
1203 Dim content As String = ""
1205 res = twCon.UpdateProfile(name, url, location, description, content)
1206 Catch ex As Exception
1207 Return "Err:" + ex.Message
1211 Case HttpStatusCode.OK
1212 Twitter.AccountState = ACCOUNT_STATE.Valid
1214 Case HttpStatusCode.Unauthorized
1215 Twitter.AccountState = ACCOUNT_STATE.Invalid
1216 Return My.Resources.Unauthorized
1217 Case HttpStatusCode.Forbidden
1218 Dim errMsg As String = GetErrorMessageJson(content)
1219 If String.IsNullOrEmpty(errMsg) Then
1220 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
1222 Return "Err:" + errMsg
1225 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1229 Public Function PostUpdateProfileImage(ByVal filename As String) As String
1230 If _endingFlag Then Return ""
1232 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1234 Google.GASender.GetInstance().TrackEventWithCategory("post", "update_profile_image", Me.UserId)
1235 Dim res As HttpStatusCode
1236 Dim content As String = ""
1238 res = twCon.UpdateProfileImage(New FileInfo(filename), content)
1239 Catch ex As Exception
1240 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
1244 Case HttpStatusCode.OK
1245 Twitter.AccountState = ACCOUNT_STATE.Valid
1247 Case HttpStatusCode.Unauthorized
1248 Twitter.AccountState = ACCOUNT_STATE.Invalid
1249 Return My.Resources.Unauthorized
1250 Case HttpStatusCode.Forbidden
1251 Dim errMsg As String = GetErrorMessageJson(content)
1252 If String.IsNullOrEmpty(errMsg) Then
1253 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
1255 Return "Err:" + errMsg
1258 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1262 Public ReadOnly Property Username() As String
1264 Return twCon.AuthenticatedUsername
1268 Public ReadOnly Property UserId As Long
1270 Return twCon.AuthenticatedUserId
1274 Public ReadOnly Property Password() As String
1276 Return twCon.Password
1280 Private Shared _accountState As ACCOUNT_STATE = ACCOUNT_STATE.Valid
1281 Public Shared Property AccountState() As ACCOUNT_STATE
1283 Return _accountState
1285 Set(ByVal value As ACCOUNT_STATE)
1286 _accountState = value
1290 Public WriteOnly Property GetIcon() As Boolean
1291 Set(ByVal value As Boolean)
1296 Public WriteOnly Property TinyUrlResolve() As Boolean
1297 Set(ByVal value As Boolean)
1298 _tinyUrlResolve = value
1302 Public WriteOnly Property RestrictFavCheck() As Boolean
1303 Set(ByVal value As Boolean)
1304 _restrictFavCheck = value
1308 Public WriteOnly Property IconSize() As Integer
1309 Set(ByVal value As Integer)
1315 Public Function GetVersionInfo() As String
1316 Dim content As String = ""
1317 If Not (New HttpVarious).GetData("http://tween.sourceforge.jp/version.txt?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), Nothing, content, GetUserAgentString()) Then
1318 Throw New Exception("GetVersionInfo Failed")
1323 Public Function GetTweenBinary(ByVal strVer As String) As String
1324 Google.GASender.GetInstance().TrackPage("/newversion", Me.UserId)
1327 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/Tween" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1328 Path.Combine(MyCommon.settingPath, "TweenNew.exe")) Then
1329 Return "Err:Download failed"
1332 If Not Directory.Exists(Path.Combine(MyCommon.settingPath, "en")) Then
1333 Directory.CreateDirectory(Path.Combine(MyCommon.settingPath, "en"))
1335 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenResEn" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1336 Path.Combine(Path.Combine(MyCommon.settingPath, "en"), "Tween.resourcesNew.dll")) Then
1337 Return "Err:Download failed"
1339 'その他言語圏のリソース。取得失敗しても継続
1341 Dim curCul As String = ""
1342 If Not Thread.CurrentThread.CurrentUICulture.IsNeutralCulture Then
1343 Dim idx As Integer = Thread.CurrentThread.CurrentUICulture.Name.LastIndexOf("-"c)
1345 curCul = Thread.CurrentThread.CurrentUICulture.Name.Substring(0, idx)
1347 curCul = Thread.CurrentThread.CurrentUICulture.Name
1350 curCul = Thread.CurrentThread.CurrentUICulture.Name
1352 If Not String.IsNullOrEmpty(curCul) AndAlso curCul <> "en" AndAlso curCul <> "ja" Then
1353 If Not Directory.Exists(Path.Combine(MyCommon.settingPath, curCul)) Then
1354 Directory.CreateDirectory(Path.Combine(MyCommon.settingPath, curCul))
1356 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenRes" + curCul + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1357 Path.Combine(Path.Combine(MyCommon.settingPath, curCul), "Tween.resourcesNew.dll")) Then
1358 'Return "Err:Download failed"
1362 Dim curCul2 As String
1363 If Not Thread.CurrentThread.CurrentCulture.IsNeutralCulture Then
1364 Dim idx As Integer = Thread.CurrentThread.CurrentCulture.Name.LastIndexOf("-"c)
1366 curCul2 = Thread.CurrentThread.CurrentCulture.Name.Substring(0, idx)
1368 curCul2 = Thread.CurrentThread.CurrentCulture.Name
1371 curCul2 = Thread.CurrentThread.CurrentCulture.Name
1373 If Not String.IsNullOrEmpty(curCul2) AndAlso curCul2 <> "en" AndAlso curCul2 <> curCul Then
1374 If Not Directory.Exists(Path.Combine(MyCommon.settingPath, curCul2)) Then
1375 Directory.CreateDirectory(Path.Combine(MyCommon.settingPath, curCul2))
1377 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenRes" + curCul2 + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1378 Path.Combine(Path.Combine(MyCommon.settingPath, curCul2), "Tween.resourcesNew.dll")) Then
1379 'Return "Err:Download failed"
1384 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenUp3.gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1385 Path.Combine(MyCommon.settingPath, "TweenUp3.exe")) Then
1386 Return "Err:Download failed"
1389 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenDll" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1390 Path.Combine(MyCommon.settingPath, "TweenNew.XmlSerializers.dll")) Then
1391 Return "Err:Download failed"
1394 Catch ex As Exception
1395 Return "Err:Download failed"
1400 Public Property DetailIcon() As IDictionary(Of String, Image)
1404 Set(ByVal value As IDictionary(Of String, Image))
1409 Public Property ReadOwnPost() As Boolean
1413 Set(ByVal value As Boolean)
1414 _readOwnPost = value
1418 Public ReadOnly Property FollowersCount() As Integer
1420 Return _followersCount
1424 Public ReadOnly Property FriendsCount() As Integer
1426 Return _friendsCount
1430 Public ReadOnly Property StatusesCount() As Integer
1432 Return _statusesCount
1436 Public ReadOnly Property Location() As String
1442 Public ReadOnly Property Bio() As String
1448 Public WriteOnly Property UseSsl() As Boolean
1449 Set(ByVal value As Boolean)
1450 HttpTwitter.UseSsl = value
1452 _protocol = "https://"
1454 _protocol = "http://"
1459 Public Function GetTimelineApi(ByVal read As Boolean, _
1460 ByVal gType As WORKERTYPE, _
1461 ByVal more As Boolean, _
1462 ByVal startup As Boolean) As String
1464 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1466 If _endingFlag Then Return ""
1468 Dim res As HttpStatusCode
1469 Dim content As String = ""
1470 Dim count As Integer = AppendSettingDialog.Instance.CountApi
1471 If gType = WORKERTYPE.Reply Then count = AppendSettingDialog.Instance.CountApiReply()
1472 If AppendSettingDialog.Instance.UseAdditionalCount Then
1473 If more AndAlso AppendSettingDialog.Instance.MoreCountApi <> 0 Then
1474 count = AppendSettingDialog.Instance.MoreCountApi
1475 ElseIf startup AndAlso AppendSettingDialog.Instance.FirstCountApi <> 0 AndAlso gType = WORKERTYPE.Timeline Then
1476 count = AppendSettingDialog.Instance.FirstCountApi
1480 If gType = WORKERTYPE.Timeline Then
1482 res = twCon.HomeTimeline(count, Me.minHomeTimeline, 0, content)
1484 res = twCon.HomeTimeline(count, 0, 0, content)
1488 res = twCon.Mentions(count, Me.minMentions, 0, content)
1490 res = twCon.Mentions(count, 0, 0, content)
1493 Catch ex As Exception
1494 Return "Err:" + ex.Message
1497 Case HttpStatusCode.OK
1498 Twitter.AccountState = ACCOUNT_STATE.Valid
1499 Case HttpStatusCode.Unauthorized
1500 Twitter.AccountState = ACCOUNT_STATE.Invalid
1501 Return My.Resources.Unauthorized
1502 Case HttpStatusCode.BadRequest
1503 Return "Err:API Limits?"
1505 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1508 If gType = WORKERTYPE.Timeline Then
1509 Return CreatePostsFromJson(content, gType, Nothing, read, count, Me.minHomeTimeline)
1511 Return CreatePostsFromJson(content, gType, Nothing, read, count, Me.minMentions)
1515 Public Function GetUserTimelineApi(ByVal read As Boolean,
1516 ByVal count As Integer,
1517 ByVal userName As String,
1518 ByVal tab As TabClass,
1519 ByVal more As Boolean) As String
1521 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1523 If _endingFlag Then Return ""
1525 Dim res As HttpStatusCode
1526 Dim content As String = ""
1528 If count = 0 Then count = 20
1530 If String.IsNullOrEmpty(userName) Then
1531 Dim target As String = tab.User
1532 If target Is Nothing Then Return ""
1533 res = twCon.UserTimeline(0, target, count, 0, 0, content)
1536 res = twCon.UserTimeline(0, userName, count, tab.OldestId, 0, content)
1538 res = twCon.UserTimeline(0, userName, count, 0, 0, content)
1541 Catch ex As Exception
1542 Return "Err:" + ex.Message
1545 Case HttpStatusCode.OK
1546 Twitter.AccountState = ACCOUNT_STATE.Valid
1547 Case HttpStatusCode.Unauthorized
1548 Twitter.AccountState = ACCOUNT_STATE.Valid
1549 Return "Err:@" + userName + "'s Tweets are protected."
1550 Case HttpStatusCode.BadRequest
1551 Return "Err:API Limits?"
1553 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1556 Dim items As List(Of TwitterDataModel.Status)
1558 items = CreateDataFromJson(Of List(Of TwitterDataModel.Status))(content)
1559 Catch ex As SerializationException
1560 TraceOut(ex.Message + Environment.NewLine + content)
1561 Return "Json Parse Error(DataContractJsonSerializer)"
1562 Catch ex As Exception
1563 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1564 Return "Invalid Json!"
1567 For Each status As TwitterDataModel.Status In items
1568 Dim item As PostClass = CreatePostsFromStatusData(status)
1569 If item Is Nothing Then Continue For
1570 If item.StatusId < tab.OldestId Then tab.OldestId = item.StatusId
1572 If item.IsMe AndAlso Not read AndAlso _readOwnPost Then item.IsRead = True
1573 If tab IsNot Nothing Then item.RelTabName = tab.TabName
1574 '非同期アイコン取得&StatusDictionaryに追加
1575 TabInformations.GetInstance.AddPost(item)
1581 Public Function GetStatusApi(ByVal read As Boolean,
1583 ByRef post As PostClass) As String
1584 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1586 If _endingFlag Then Return ""
1588 Google.GASender.GetInstance().TrackPage("/showstatus", Me.UserId)
1589 Dim res As HttpStatusCode
1590 Dim content As String = ""
1593 res = twCon.ShowStatuses(id, content)
1594 Catch ex As Exception
1595 Return "Err:" + ex.Message
1598 Case HttpStatusCode.OK
1599 Twitter.AccountState = ACCOUNT_STATE.Valid
1600 Case HttpStatusCode.Unauthorized
1601 Twitter.AccountState = ACCOUNT_STATE.Invalid
1602 Return My.Resources.Unauthorized
1603 Case HttpStatusCode.BadRequest
1604 Return "Err:API Limits?"
1605 Case HttpStatusCode.Forbidden
1606 Return "Err:Protected user's tweet"
1608 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1611 Dim status As TwitterDataModel.Status
1613 status = CreateDataFromJson(Of TwitterDataModel.Status)(content)
1614 Catch ex As SerializationException
1615 TraceOut(ex.Message + Environment.NewLine + content)
1616 Return "Json Parse Error(DataContractJsonSerializer)"
1617 Catch ex As Exception
1618 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1619 Return "Invalid Json!"
1622 Dim item As PostClass = CreatePostsFromStatusData(status)
1623 If item Is Nothing Then Return "Err:Can't create post"
1625 If item.IsMe AndAlso Not read AndAlso _readOwnPost Then item.IsRead = True
1631 Public Function GetStatusApi(ByVal read As Boolean,
1633 ByVal tab As TabClass) As String
1634 Dim post As PostClass = Nothing
1635 Dim r As String = Me.GetStatusApi(read, id, post)
1638 If tab IsNot Nothing Then post.RelTabName = tab.TabName
1639 '非同期アイコン取得&StatusDictionaryに追加
1640 TabInformations.GetInstance.AddPost(post)
1646 Private Function CreatePostsFromStatusData(ByVal status As TwitterDataModel.Status) As PostClass
1647 Dim post As New PostClass
1648 Dim entities As TwitterDataModel.Entities
1650 post.StatusId = status.Id
1651 If status.RetweetedStatus IsNot Nothing Then
1652 Dim retweeted As TwitterDataModel.RetweetedStatus = status.RetweetedStatus
1654 post.CreatedAt = DateTimeParse(retweeted.CreatedAt)
1657 post.RetweetedId = retweeted.Id
1659 post.TextFromApi = retweeted.Text
1660 entities = retweeted.Entities
1661 'Source取得(htmlの場合は、中身を取り出し)
1662 post.Source = retweeted.Source
1664 Long.TryParse(retweeted.InReplyToStatusId, post.InReplyToStatusId)
1665 post.InReplyToUser = retweeted.InReplyToScreenName
1666 Long.TryParse(status.InReplyToUserId, post.InReplyToUserId)
1667 post.IsFav = TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.RetweetedId)
1668 If retweeted.Geo IsNot Nothing Then post.PostGeo = New PostClass.StatusGeo() With {.Lat = retweeted.Geo.Coordinates(0), .Lng = retweeted.Geo.Coordinates(1)}
1671 Dim user As TwitterDataModel.User = retweeted.User
1673 If user.ScreenName Is Nothing OrElse status.User.ScreenName Is Nothing Then Return Nothing
1675 post.UserId = user.Id
1676 post.ScreenName = user.ScreenName
1677 post.Nickname = user.Name.Trim()
1678 post.ImageUrl = user.ProfileImageUrl
1679 post.IsProtect = user.Protected
1682 post.RetweetedBy = status.User.ScreenName
1683 post.RetweetedByUserId = status.User.Id
1684 post.IsMe = post.RetweetedBy.ToLower.Equals(_uname)
1686 post.CreatedAt = DateTimeParse(status.CreatedAt)
1688 post.TextFromApi = status.Text
1689 entities = status.Entities
1690 'Source取得(htmlの場合は、中身を取り出し)
1691 post.Source = status.Source
1692 Long.TryParse(status.InReplyToStatusId, post.InReplyToStatusId)
1693 post.InReplyToUser = status.InReplyToScreenName
1694 Long.TryParse(status.InReplyToUserId, post.InReplyToUserId)
1696 post.IsFav = status.Favorited
1697 If status.Geo IsNot Nothing Then post.PostGeo = New PostClass.StatusGeo() With {.Lat = status.Geo.Coordinates(0), .Lng = status.Geo.Coordinates(1)}
1700 Dim user As TwitterDataModel.User = status.User
1702 If user.ScreenName Is Nothing Then Return Nothing
1704 post.UserId = user.Id
1705 post.ScreenName = user.ScreenName
1706 post.Nickname = user.Name.Trim()
1707 post.ImageUrl = user.ProfileImageUrl
1708 post.IsProtect = user.Protected
1709 post.IsMe = post.ScreenName.ToLower.Equals(_uname)
1712 post.Text = CreateHtmlAnchor(post.TextFromApi, post.ReplyToList, entities, post.Media)
1713 post.TextFromApi = Me.ReplaceTextFromApi(post.TextFromApi, entities)
1714 post.TextFromApi = HttpUtility.HtmlDecode(post.TextFromApi)
1715 post.TextFromApi = post.TextFromApi.Replace("<3", "♡")
1720 post.IsReply = post.ReplyToList.Contains(_uname)
1721 post.IsExcludeReply = False
1726 If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.UserId)
1733 Private Function CreatePostsFromJson(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
1734 Dim items As List(Of TwitterDataModel.Status)
1736 items = CreateDataFromJson(Of List(Of TwitterDataModel.Status))(content)
1737 Catch ex As SerializationException
1738 TraceOut(ex.Message + Environment.NewLine + content)
1739 Return "Json Parse Error(DataContractJsonSerializer)"
1740 Catch ex As Exception
1741 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1742 Return "Invalid Json!"
1745 For Each status As TwitterDataModel.Status In items
1746 Dim post As PostClass = Nothing
1747 post = CreatePostsFromStatusData(status)
1748 If post Is Nothing Then Continue For
1750 If minimumId > post.StatusId Then minimumId = post.StatusId
1753 If tab Is Nothing Then
1754 If TabInformations.GetInstance.ContainsKey(post.StatusId) Then Continue For
1756 If TabInformations.GetInstance.ContainsKey(post.StatusId, tab.TabName) Then Continue For
1761 If post.RetweetedId > 0 AndAlso Me.noRTId.Contains(post.RetweetedByUserId) Then Continue For
1764 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
1766 If tab IsNot Nothing Then post.RelTabName = tab.TabName
1767 '非同期アイコン取得&StatusDictionaryに追加
1768 TabInformations.GetInstance.AddPost(post)
1774 Private Function CreatePostsFromPhoenixSearch(ByVal content As String, ByVal gType As WORKERTYPE, ByVal tab As TabClass, ByVal read As Boolean, ByVal count As Integer, ByRef minimumId As Long, ByRef nextPageQuery As String) As String
1775 Dim items As TwitterDataModel.SearchResult
1777 items = CreateDataFromJson(Of TwitterDataModel.SearchResult)(content)
1778 Catch ex As SerializationException
1779 TraceOut(ex.Message + Environment.NewLine + content)
1780 Return "Json Parse Error(DataContractJsonSerializer)"
1781 Catch ex As Exception
1782 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1783 Return "Invalid Json!"
1786 nextPageQuery = items.NextPage
1788 For Each status As TwitterDataModel.Status In items.Statuses
1789 Dim post As PostClass = Nothing
1790 post = CreatePostsFromStatusData(status)
1791 If post Is Nothing Then Continue For
1793 If minimumId > post.StatusId Then minimumId = post.StatusId
1796 If tab Is Nothing Then
1797 If TabInformations.GetInstance.ContainsKey(post.StatusId) Then Continue For
1799 If TabInformations.GetInstance.ContainsKey(post.StatusId, tab.TabName) Then Continue For
1804 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
1806 If tab IsNot Nothing Then post.RelTabName = tab.TabName
1807 '非同期アイコン取得&StatusDictionaryに追加
1808 TabInformations.GetInstance.AddPost(post)
1811 Return If(String.IsNullOrEmpty(items.ErrMsg), "", "Err:" + items.ErrMsg)
1814 Public Overloads Function GetListStatus(ByVal read As Boolean, _
1815 ByVal tab As TabClass, _
1816 ByVal more As Boolean, _
1817 ByVal startup As Boolean) As String
1819 If _endingFlag Then Return ""
1821 Dim res As HttpStatusCode
1822 Dim content As String = ""
1823 Dim page As Integer = 0
1824 Dim count As Integer
1825 If AppendSettingDialog.Instance.UseAdditionalCount Then
1826 count = AppendSettingDialog.Instance.ListCountApi
1828 If more AndAlso AppendSettingDialog.Instance.MoreCountApi <> 0 Then
1829 count = AppendSettingDialog.Instance.MoreCountApi
1830 ElseIf startup AndAlso AppendSettingDialog.Instance.FirstCountApi <> 0 Then
1831 count = AppendSettingDialog.Instance.FirstCountApi
1833 count = AppendSettingDialog.Instance.CountApi
1837 count = AppendSettingDialog.Instance.CountApi
1841 res = twCon.GetListsStatuses(tab.ListInfo.UserId, tab.ListInfo.Id, count, tab.OldestId, 0, AppendSettingDialog.Instance.IsListStatusesIncludeRts, content)
1843 res = twCon.GetListsStatuses(tab.ListInfo.UserId, tab.ListInfo.Id, count, 0, 0, AppendSettingDialog.Instance.IsListStatusesIncludeRts, content)
1845 Catch ex As Exception
1846 Return "Err:" + ex.Message
1849 Case HttpStatusCode.OK
1850 Twitter.AccountState = ACCOUNT_STATE.Valid
1851 Case HttpStatusCode.Unauthorized
1852 Twitter.AccountState = ACCOUNT_STATE.Invalid
1853 Return My.Resources.Unauthorized
1854 Case HttpStatusCode.BadRequest
1855 Return "Err:API Limits?"
1857 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1860 Return CreatePostsFromJson(content, WORKERTYPE.List, tab, read, count, tab.OldestId)
1864 Private Function CheckReplyToPost(ByVal relPosts As List(Of PostClass)) As PostClass
1865 Dim tmpPost As PostClass = relPosts(0)
1866 Dim lastPost As PostClass = Nothing
1867 Do While tmpPost IsNot Nothing
1868 If tmpPost.InReplyToStatusId = 0 Then Return Nothing
1870 Dim replyToPost = From p In relPosts
1871 Where p.StatusId = tmpPost.InReplyToStatusId
1873 tmpPost = replyToPost.FirstOrDefault()
1878 Public Function GetRelatedResult(ByVal read As Boolean, ByVal tab As TabClass) As String
1879 Google.GASender.GetInstance().TrackPage("/related_statuses", Me.UserId)
1880 Dim rslt As String = ""
1881 Dim relPosts As New List(Of PostClass)
1882 If tab.RelationTargetPost.TextFromApi.Contains("@") AndAlso tab.RelationTargetPost.InReplyToStatusId = 0 Then
1884 Dim p As PostClass = TabInformations.GetInstance.Item(tab.RelationTargetPost.StatusId)
1885 If p IsNot Nothing AndAlso p.InReplyToStatusId > 0 Then
1886 tab.RelationTargetPost = p
1888 rslt = Me.GetStatusApi(read, tab.RelationTargetPost.StatusId, p)
1889 If Not String.IsNullOrEmpty(rslt) Then Return rslt
1890 tab.RelationTargetPost = p
1893 relPosts.Add(tab.RelationTargetPost.Copy)
1894 Dim tmpPost As PostClass = relPosts(0)
1896 rslt = Me.GetRelatedResultsApi(read, tmpPost, tab, relPosts)
1897 If Not String.IsNullOrEmpty(rslt) Then Exit Do
1898 tmpPost = CheckReplyToPost(relPosts)
1899 Loop While tmpPost IsNot Nothing
1901 relPosts.ForEach(Sub(p) TabInformations.GetInstance.AddPost(p))
1905 Private Function GetRelatedResultsApi(ByVal read As Boolean,
1906 ByVal post As PostClass,
1907 ByVal tab As TabClass,
1908 ByVal relatedPosts As List(Of PostClass)) As String
1910 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1912 If _endingFlag Then Return ""
1914 Dim res As HttpStatusCode
1915 Dim content As String = ""
1917 If post.RetweetedId > 0 Then
1918 res = twCon.GetRelatedResults(post.RetweetedId, content)
1920 res = twCon.GetRelatedResults(post.StatusId, content)
1922 Catch ex As Exception
1923 Return "Err:" + ex.Message
1926 Case HttpStatusCode.OK
1927 Twitter.AccountState = ACCOUNT_STATE.Valid
1928 Case HttpStatusCode.Unauthorized
1929 Twitter.AccountState = ACCOUNT_STATE.Invalid
1930 Return My.Resources.Unauthorized
1931 Case HttpStatusCode.BadRequest
1932 Return "Err:API Limits?"
1934 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1937 Dim items As List(Of TwitterDataModel.RelatedResult)
1939 items = CreateDataFromJson(Of List(Of TwitterDataModel.RelatedResult))(content)
1940 Catch ex As SerializationException
1941 TraceOut(ex.Message + Environment.NewLine + content)
1942 Return "Json Parse Error(DataContractJsonSerializer)"
1943 Catch ex As Exception
1944 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1945 Return "Invalid Json!"
1948 Dim targetItem As PostClass = post
1949 If targetItem Is Nothing Then
1952 targetItem = targetItem.Copy()
1954 targetItem.RelTabName = tab.TabName
1955 TabInformations.GetInstance.AddPost(targetItem)
1957 Dim replyToItem As PostClass = Nothing
1958 Dim replyToUserName As String = targetItem.InReplyToUser
1959 If targetItem.InReplyToStatusId > 0 AndAlso TabInformations.GetInstance.Item(targetItem.InReplyToStatusId) IsNot Nothing Then
1960 replyToItem = TabInformations.GetInstance.Item(targetItem.InReplyToStatusId).Copy
1961 replyToItem.IsRead = read
1962 If replyToItem.IsMe AndAlso Not read AndAlso _readOwnPost Then replyToItem.IsRead = True
1963 replyToItem.RelTabName = tab.TabName
1966 Dim replyAdded As Boolean = False
1967 For Each relatedData As TwitterDataModel.RelatedResult In items
1968 For Each result As TwitterDataModel.RelatedTweet In relatedData.Results
1969 Dim item As PostClass = CreatePostsFromStatusData(result.Status)
1970 If item Is Nothing Then Continue For
1971 If targetItem.InReplyToStatusId = item.StatusId Then
1972 replyToItem = Nothing
1976 If item.IsMe AndAlso Not read AndAlso _readOwnPost Then item.IsRead = True
1977 If tab IsNot Nothing Then item.RelTabName = tab.TabName
1978 '非同期アイコン取得&StatusDictionaryに追加
1979 relatedPosts.Add(item)
1982 If replyToItem IsNot Nothing Then
1983 relatedPosts.Add(replyToItem)
1984 ElseIf targetItem.InReplyToStatusId > 0 AndAlso Not replyAdded Then
1985 Dim p As PostClass = Nothing
1986 Dim rslt As String = ""
1987 rslt = GetStatusApi(read, targetItem.InReplyToStatusId, p)
1988 If String.IsNullOrEmpty(rslt) Then
1990 p.RelTabName = tab.TabName
1996 '発言者・返信先ユーザーの直近10発言取得
1997 'Dim rslt As String = Me.GetUserTimelineApi(read, 10, "", tab)
1998 'If Not String.IsNullOrEmpty(rslt) Then Return rslt
1999 'If Not String.IsNullOrEmpty(replyToUserName) Then
2000 ' rslt = Me.GetUserTimelineApi(read, 10, replyToUserName, tab)
2005 'MRTとかに対応のためツイート内にあるツイートを指すURLを取り込む
2006 Dim ma As MatchCollection = Regex.Matches(tab.RelationTargetPost.Text, "href=""https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)(/status(es)?/(?<StatusId>[0-9]+))""")
2007 For Each _match As Match In ma
2008 Dim _statusId As Int64
2009 If Int64.TryParse(_match.Groups("StatusId").Value, _statusId) Then
2010 Dim p As PostClass = Nothing
2011 Dim _post As PostClass = TabInformations.GetInstance.Item(_statusId)
2012 If _post Is Nothing Then
2013 Dim rslt = Me.GetStatusApi(read, _statusId, p)
2017 If p IsNot Nothing Then
2019 p.RelTabName = tab.TabName
2027 Public Function GetSearch(ByVal read As Boolean, _
2028 ByVal tab As TabClass, _
2029 ByVal more As Boolean) As String
2031 If _endingFlag Then Return ""
2033 Dim res As HttpStatusCode
2034 Dim content As String = ""
2035 Dim page As Integer = 0
2036 Dim sinceId As Long = 0
2037 Dim count As Integer = 100
2038 If AppendSettingDialog.Instance.UseAdditionalCount AndAlso
2039 AppendSettingDialog.Instance.SearchCountApi <> 0 Then
2040 count = AppendSettingDialog.Instance.SearchCountApi
2042 count = AppendSettingDialog.Instance.CountApi
2045 page = tab.GetSearchPage(count)
2047 sinceId = tab.SinceId
2051 ' TODO:一時的に40>100件に 件数変更UI作成の必要あり
2052 res = twCon.Search(tab.SearchWords, tab.SearchLang, count, page, sinceId, content)
2053 Catch ex As Exception
2054 Return "Err:" + ex.Message
2057 Case HttpStatusCode.BadRequest
2058 Return "Invalid query"
2059 Case HttpStatusCode.NotFound
2060 Return "Invalid query"
2061 Case HttpStatusCode.PaymentRequired 'API Documentには420と書いてあるが、該当コードがないので402にしてある
2062 Return "Search API Limit?"
2063 Case HttpStatusCode.OK
2065 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
2068 If Not TabInformations.GetInstance.ContainsTab(tab) Then Return ""
2069 content = Regex.Replace(content, "[\x00-\x1f-[\x0a\x0d]]+", " ")
2070 Dim xdoc As New XmlDocument
2072 xdoc.LoadXml(content)
2073 Catch ex As Exception
2074 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2075 Return "Invalid ATOM!"
2077 Dim nsmgr As New XmlNamespaceManager(xdoc.NameTable)
2078 nsmgr.AddNamespace("search", "http://www.w3.org/2005/Atom")
2079 nsmgr.AddNamespace("twitter", "http://api.twitter.com/")
2080 nsmgr.AddNamespace("georss", "http://www.georss.org/georss")
2081 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/search:feed/search:entry", nsmgr)
2082 Dim xentry As XmlElement = CType(xentryNode, XmlElement)
2083 Dim post As New PostClass
2085 post.StatusId = Long.Parse(xentry.Item("id").InnerText.Split(":"c)(2))
2086 If TabInformations.GetInstance.ContainsKey(post.StatusId, tab.TabName) Then Continue For
2087 post.CreatedAt = DateTime.Parse(xentry.Item("published").InnerText)
2089 post.TextFromApi = xentry.Item("title").InnerText
2090 'Source取得(htmlの場合は、中身を取り出し)
2091 post.Source = xentry.Item("twitter:source").InnerText
2092 post.InReplyToStatusId = 0
2093 post.InReplyToUser = ""
2094 post.InReplyToUserId = 0
2097 ' Geoが勝手に付加されるバグがいっこうに修正されないので暫定的にGeo情報を無視する
2098 If xentry.Item("twitter:geo").HasChildNodes Then
2099 Dim pnt As String() = CType(xentry.SelectSingleNode("twitter:geo/georss:point", nsmgr), XmlElement).InnerText.Split(" "c)
2100 post.PostGeo = New PostClass.StatusGeo With {.Lat = Double.Parse(pnt(0)), .Lng = Double.Parse(pnt(1))}
2104 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./search:author", nsmgr), XmlElement)
2106 post.ScreenName = xUentry.Item("name").InnerText.Split(" "c)(0).Trim
2107 post.Nickname = xUentry.Item("name").InnerText.Substring(post.ScreenName.Length).Trim
2108 If post.Nickname.Length > 2 Then
2109 post.Nickname = post.Nickname.Substring(1, post.Nickname.Length - 2)
2111 post.Nickname = post.ScreenName
2113 post.ImageUrl = CType(xentry.SelectSingleNode("./search:link[@type='image/png']", nsmgr), XmlElement).GetAttribute("href")
2114 post.IsProtect = False
2115 post.IsMe = post.ScreenName.ToLower.Equals(_uname)
2118 post.Text = CreateHtmlAnchor(HttpUtility.HtmlEncode(post.TextFromApi), post.ReplyToList, post.Media)
2119 post.TextFromApi = HttpUtility.HtmlDecode(post.TextFromApi)
2124 post.IsReply = post.ReplyToList.Contains(_uname)
2125 post.IsExcludeReply = False
2128 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
2130 post.RelTabName = tab.TabName
2131 If Not more AndAlso post.StatusId > tab.SinceId Then tab.SinceId = post.StatusId
2132 Catch ex As Exception
2133 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2137 'Me._dIcon.Add(post.ImageUrl, Nothing)
2138 TabInformations.GetInstance.AddPost(post)
2143 '' 遡るための情報max_idやnext_pageの情報を保持する
2146 Dim xNode As XmlNode = xdoc.DocumentElement.SelectSingleNode("/search:feed/twitter:warning", nsmgr)
2148 If xNode IsNot Nothing Then
2149 Return "Warn:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
2156 Public Function GetPhoenixSearch(ByVal read As Boolean, _
2157 ByVal tab As TabClass, _
2158 ByVal more As Boolean) As String
2160 If _endingFlag Then Return ""
2162 Dim res As HttpStatusCode
2163 Dim content As String = ""
2164 Dim page As Integer = 0
2165 Dim sinceId As Long = 0
2166 Dim count As Integer = 100
2167 Dim querystr As String = ""
2168 If AppendSettingDialog.Instance.UseAdditionalCount AndAlso
2169 AppendSettingDialog.Instance.SearchCountApi <> 0 Then
2170 count = AppendSettingDialog.Instance.SearchCountApi
2173 page = tab.GetSearchPage(count)
2174 If Not String.IsNullOrEmpty(tab.NextPageQuery) Then
2175 querystr = tab.NextPageQuery
2178 sinceId = tab.SinceId
2182 If String.IsNullOrEmpty(querystr) Then
2183 res = twCon.PhoenixSearch(tab.SearchWords, tab.SearchLang, count, page, sinceId, content)
2185 res = twCon.PhoenixSearch(querystr, content)
2187 Catch ex As Exception
2188 Return "Err:" + ex.Message
2191 Case HttpStatusCode.BadRequest
2192 Return "Invalid query"
2193 Case HttpStatusCode.NotFound
2194 Return "Invalid query"
2195 Case HttpStatusCode.PaymentRequired 'API Documentには420と書いてあるが、該当コードがないので402にしてある
2196 Return "Search API Limit?"
2197 Case HttpStatusCode.OK
2199 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
2202 If Not TabInformations.GetInstance.ContainsTab(tab) Then Return ""
2205 '' 遡るための情報max_idやnext_pageの情報を保持する
2207 Return CreatePostsFromPhoenixSearch(content, WORKERTYPE.PublicSearch, tab, read, count, tab.OldestId, tab.NextPageQuery)
2210 Private Function CreateDirectMessagesFromJson(ByVal content As String, ByVal gType As WORKERTYPE, ByVal read As Boolean) As String
2211 Dim item As List(Of TwitterDataModel.Directmessage)
2213 If gType = WORKERTYPE.UserStream Then
2214 Dim itm As List(Of TwitterDataModel.DirectmessageEvent) = CreateDataFromJson(Of List(Of TwitterDataModel.DirectmessageEvent))(content)
2215 item = New List(Of TwitterDataModel.Directmessage)
2216 For Each dat As TwitterDataModel.DirectmessageEvent In itm
2217 item.Add(dat.Directmessage)
2220 item = CreateDataFromJson(Of List(Of TwitterDataModel.Directmessage))(content)
2222 Catch ex As SerializationException
2223 TraceOut(ex.Message + Environment.NewLine + content)
2224 Return "Json Parse Error(DataContractJsonSerializer)"
2225 Catch ex As Exception
2226 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2227 Return "Invalid Json!"
2230 For Each message As TwitterDataModel.Directmessage In item
2231 Dim post As New PostClass
2233 post.StatusId = message.Id
2234 If gType <> WORKERTYPE.UserStream Then
2235 If gType = WORKERTYPE.DirectMessegeRcv Then
2236 If minDirectmessage > post.StatusId Then minDirectmessage = post.StatusId
2238 If minDirectmessageSent > post.StatusId Then minDirectmessageSent = post.StatusId
2244 If TabInformations.GetInstance.GetTabByType(TabUsageType.DirectMessage).Contains(post.StatusId) Then Continue For
2248 post.CreatedAt = DateTimeParse(message.CreatedAt)
2250 post.TextFromApi = message.Text
2252 post.Text = CreateHtmlAnchor(post.TextFromApi, post.ReplyToList, post.Media)
2253 post.TextFromApi = HttpUtility.HtmlDecode(post.TextFromApi)
2254 post.TextFromApi = post.TextFromApi.Replace("<3", "♡")
2258 Dim user As TwitterDataModel.User
2259 If gType = WORKERTYPE.UserStream Then
2260 If twCon.AuthenticatedUsername.Equals(message.Recipient.ScreenName, StringComparison.CurrentCultureIgnoreCase) Then
2261 user = message.Sender
2265 user = message.Recipient
2270 If gType = WORKERTYPE.DirectMessegeRcv Then
2271 user = message.Sender
2275 user = message.Recipient
2281 post.UserId = user.Id
2282 post.ScreenName = user.ScreenName
2283 post.Nickname = user.Name.Trim()
2284 post.ImageUrl = user.ProfileImageUrl
2285 post.IsProtect = user.Protected
2286 Catch ex As Exception
2287 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2288 MessageBox.Show("Parse Error(CreateDirectMessagesFromJson)")
2293 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
2294 post.IsReply = False
2295 post.IsExcludeReply = False
2298 TabInformations.GetInstance.AddPost(post)
2305 Public Function GetDirectMessageApi(ByVal read As Boolean, _
2306 ByVal gType As WORKERTYPE, _
2307 ByVal more As Boolean) As String
2308 If _endingFlag Then Return ""
2310 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2311 If Not TwitterApiInfo.IsDirectMessagePermission Then Return "Auth Err:try to re-authorization."
2313 Dim res As HttpStatusCode
2314 Dim content As String = ""
2317 If gType = WORKERTYPE.DirectMessegeRcv Then
2319 res = twCon.DirectMessages(20, minDirectmessage, 0, content)
2321 res = twCon.DirectMessages(20, 0, 0, content)
2325 res = twCon.DirectMessagesSent(20, minDirectmessageSent, 0, content)
2327 res = twCon.DirectMessagesSent(20, 0, 0, content)
2330 Catch ex As Exception
2331 Return "Err:" + ex.Message
2335 Case HttpStatusCode.OK
2336 Twitter.AccountState = ACCOUNT_STATE.Valid
2337 Case HttpStatusCode.Unauthorized
2338 Twitter.AccountState = ACCOUNT_STATE.Invalid
2339 Return My.Resources.Unauthorized
2340 Case HttpStatusCode.BadRequest
2341 Return "Err:API Limits?"
2343 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2346 Return CreateDirectMessagesFromJson(content, gType, read)
2349 Public Function GetFavoritesApi(ByVal read As Boolean, _
2350 ByVal gType As WORKERTYPE) As String
2352 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2354 If _endingFlag Then Return ""
2356 Dim res As HttpStatusCode
2357 Dim content As String = ""
2358 Dim count As Integer = AppendSettingDialog.Instance.CountApi
2359 If AppendSettingDialog.Instance.UseAdditionalCount AndAlso
2360 AppendSettingDialog.Instance.FavoritesCountApi <> 0 Then
2361 count = AppendSettingDialog.Instance.FavoritesCountApi
2364 res = twCon.Favorites(count, content)
2365 Catch ex As Exception
2366 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2370 Case HttpStatusCode.OK
2371 Twitter.AccountState = ACCOUNT_STATE.Valid
2372 Case HttpStatusCode.Unauthorized
2373 Twitter.AccountState = ACCOUNT_STATE.Invalid
2374 Return My.Resources.Unauthorized
2375 Case HttpStatusCode.BadRequest
2376 Return "Err:API Limits?"
2378 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2381 Dim serializer As New DataContractJsonSerializer(GetType(List(Of TwitterDataModel.Status)))
2382 Dim item As List(Of TwitterDataModel.Status)
2385 item = CreateDataFromJson(Of List(Of TwitterDataModel.Status))(content)
2386 Catch ex As SerializationException
2387 TraceOut(ex.Message + Environment.NewLine + content)
2388 Return "Json Parse Error(DataContractJsonSerializer)"
2389 Catch ex As Exception
2390 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2391 Return "Invalid Json!"
2394 For Each status As TwitterDataModel.Status In item
2395 Dim post As New PostClass
2396 Dim entities As TwitterDataModel.Entities
2399 post.StatusId = status.Id
2402 If TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.StatusId) Then Continue For
2405 If status.RetweetedStatus IsNot Nothing Then
2406 Dim retweeted As TwitterDataModel.RetweetedStatus = status.RetweetedStatus
2407 post.CreatedAt = DateTimeParse(retweeted.CreatedAt)
2410 post.RetweetedId = post.StatusId
2412 post.TextFromApi = retweeted.Text
2413 entities = retweeted.Entities
2414 'Source取得(htmlの場合は、中身を取り出し)
2415 post.Source = retweeted.Source
2417 Long.TryParse(retweeted.InReplyToStatusId, post.InReplyToStatusId)
2418 post.InReplyToUser = retweeted.InReplyToScreenName
2419 Long.TryParse(retweeted.InReplyToUserId, post.InReplyToUserId)
2420 post.IsFav = retweeted.Favorited
2423 Dim user As TwitterDataModel.User = retweeted.User
2424 post.UserId = user.Id
2425 post.ScreenName = user.ScreenName
2426 post.Nickname = user.Name.Trim()
2427 post.ImageUrl = user.ProfileImageUrl
2428 post.IsProtect = user.Protected
2431 post.RetweetedBy = status.User.ScreenName
2432 post.IsMe = post.RetweetedBy.ToLower.Equals(_uname)
2434 post.CreatedAt = DateTimeParse(status.CreatedAt)
2437 post.TextFromApi = status.Text
2438 entities = status.Entities
2439 'Source取得(htmlの場合は、中身を取り出し)
2440 post.Source = status.Source
2441 Long.TryParse(status.InReplyToStatusId, post.InReplyToStatusId)
2442 post.InReplyToUser = status.InReplyToScreenName
2443 Long.TryParse(status.InReplyToUserId, post.InReplyToUserId)
2445 post.IsFav = status.Favorited
2448 Dim user As TwitterDataModel.User = status.User
2449 post.UserId = user.Id
2450 post.ScreenName = user.ScreenName
2451 post.Nickname = user.Name.Trim()
2452 post.ImageUrl = user.ProfileImageUrl
2453 post.IsProtect = user.Protected
2454 post.IsMe = post.ScreenName.ToLower.Equals(_uname)
2457 post.Text = CreateHtmlAnchor(post.TextFromApi, post.ReplyToList, entities, post.Media)
2458 post.TextFromApi = Me.ReplaceTextFromApi(post.TextFromApi, entities)
2459 post.TextFromApi = HttpUtility.HtmlDecode(post.TextFromApi)
2460 post.TextFromApi = post.TextFromApi.Replace("<3", "♡")
2465 post.IsReply = post.ReplyToList.Contains(_uname)
2466 post.IsExcludeReply = False
2471 If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.UserId)
2475 Catch ex As Exception
2476 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2480 TabInformations.GetInstance.AddPost(post)
2487 Private Function ReplaceTextFromApi(ByVal text As String, ByVal entities As TwitterDataModel.Entities) As String
2488 If entities IsNot Nothing Then
2489 If entities.Urls IsNot Nothing Then
2490 For Each m In entities.Urls
2491 If Not String.IsNullOrEmpty(m.DisplayUrl) Then text = text.Replace(m.Url, m.DisplayUrl)
2494 If entities.Media IsNot Nothing Then
2495 For Each m In entities.Media
2496 If Not String.IsNullOrEmpty(m.DisplayUrl) Then text = text.Replace(m.Url, m.DisplayUrl)
2503 Public Function GetFollowersApi() As String
2504 If _endingFlag Then Return ""
2505 Dim cursor As Long = -1
2506 Dim tmpFollower As New List(Of Long)(followerId)
2510 Dim ret As String = FollowerApi(cursor)
2511 If Not String.IsNullOrEmpty(ret) Then
2513 followerId.AddRange(tmpFollower)
2514 _GetFollowerResult = False
2517 Loop While cursor > 0
2519 TabInformations.GetInstance.RefreshOwl(followerId)
2521 _GetFollowerResult = True
2525 Public ReadOnly Property GetFollowersSuccess() As Boolean
2527 Return _GetFollowerResult
2531 Private Function FollowerApi(ByRef cursor As Long) As String
2532 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2534 Dim res As HttpStatusCode
2535 Dim content As String = ""
2537 res = twCon.FollowerIds(cursor, content)
2538 Catch ex As Exception
2539 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2543 Case HttpStatusCode.OK
2544 Twitter.AccountState = ACCOUNT_STATE.Valid
2545 Case HttpStatusCode.Unauthorized
2546 Twitter.AccountState = ACCOUNT_STATE.Invalid
2547 Return My.Resources.Unauthorized
2548 Case HttpStatusCode.BadRequest
2549 Return "Err:API Limits?"
2551 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2555 Dim followers = CreateDataFromJson(Of TwitterDataModel.Ids)(content)
2556 followerId.AddRange(followers.Id)
2557 cursor = followers.NextCursor
2559 Catch ex As SerializationException
2560 TraceOut(ex.Message + Environment.NewLine + content)
2561 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2562 Catch ex As Exception
2563 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2564 Return "Err:Invalid Json!"
2568 Public Function GetNoRetweetIdsApi() As String
2569 If _endingFlag Then Return ""
2570 Dim cursor As Long = -1
2571 Dim tmpIds As New List(Of Long)(noRTId)
2575 Dim ret As String = NoRetweetApi(cursor)
2576 If Not String.IsNullOrEmpty(ret) Then
2578 noRTId.AddRange(tmpIds)
2579 _GetNoRetweetResult = False
2582 Loop While cursor > 0
2584 _GetNoRetweetResult = True
2588 Private Function NoRetweetApi(ByRef cursor As Long) As String
2589 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2591 Dim res As HttpStatusCode
2592 Dim content As String = ""
2594 res = twCon.NoRetweetIds(cursor, content)
2595 Catch ex As Exception
2596 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2600 Case HttpStatusCode.OK
2601 Twitter.AccountState = ACCOUNT_STATE.Valid
2602 Case HttpStatusCode.Unauthorized
2603 Twitter.AccountState = ACCOUNT_STATE.Invalid
2604 Return My.Resources.Unauthorized
2605 Case HttpStatusCode.BadRequest
2606 Return "Err:API Limits?"
2608 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2612 Dim ids = CreateDataFromJson(Of Long())(content)
2613 noRTId.AddRange(ids)
2614 cursor = 0 '0より小さければ何でも良い。
2616 Catch ex As SerializationException
2617 TraceOut(ex.Message + Environment.NewLine + content)
2618 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2619 Catch ex As Exception
2620 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2621 Return "Err:Invalid Json!"
2625 Public ReadOnly Property GetNoRetweetSuccess() As Boolean
2627 Return _GetNoRetweetResult
2631 Public Function ConfigurationApi() As String
2632 Dim res As HttpStatusCode
2633 Dim content As String = ""
2635 res = twCon.GetConfiguration(content)
2636 Catch ex As Exception
2637 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2641 Case HttpStatusCode.OK
2642 Twitter.AccountState = ACCOUNT_STATE.Valid
2643 Case HttpStatusCode.Unauthorized
2644 Twitter.AccountState = ACCOUNT_STATE.Invalid
2645 Return My.Resources.Unauthorized
2646 Case HttpStatusCode.BadRequest
2647 Return "Err:API Limits?"
2649 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2653 AppendSettingDialog.Instance.TwitterConfiguration = CreateDataFromJson(Of TwitterDataModel.Configuration)(content)
2655 Catch ex As SerializationException
2656 TraceOut(ex.Message + Environment.NewLine + content)
2657 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2658 Catch ex As Exception
2659 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2660 Return "Err:Invalid Json!"
2664 Public Function GetListsApi() As String
2665 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2667 Dim res As HttpStatusCode
2668 Dim content As String = ""
2669 Dim cursor As Long = -1
2671 Dim lists As New List(Of ListElement)
2674 res = twCon.GetLists(Me.Username, cursor, content)
2675 Catch ex As Exception
2676 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2680 Case HttpStatusCode.OK
2681 Twitter.AccountState = ACCOUNT_STATE.Valid
2682 Case HttpStatusCode.Unauthorized
2683 Twitter.AccountState = ACCOUNT_STATE.Invalid
2684 Return My.Resources.Unauthorized
2685 Case HttpStatusCode.BadRequest
2686 Return "Err:API Limits?"
2688 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2692 Dim lst = CreateDataFromJson(Of TwitterDataModel.Lists)(content)
2693 lists.AddRange(From le In lst.Lists Select New ListElement(le, Me))
2694 cursor = lst.NextCursor
2695 Catch ex As SerializationException
2696 TraceOut(ex.Message + Environment.NewLine + content)
2697 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2698 Catch ex As Exception
2699 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2700 Return "Err:Invalid Json!"
2702 Loop While cursor <> 0
2708 res = twCon.GetListsSubscriptions(Me.Username, cursor, content)
2709 Catch ex As Exception
2710 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2714 Case HttpStatusCode.OK
2715 Twitter.AccountState = ACCOUNT_STATE.Valid
2716 Case HttpStatusCode.Unauthorized
2717 Twitter.AccountState = ACCOUNT_STATE.Invalid
2718 Return My.Resources.Unauthorized
2719 Case HttpStatusCode.BadRequest
2720 Return "Err:API Limits?"
2722 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2726 Dim lst = CreateDataFromJson(Of TwitterDataModel.Lists)(content)
2727 lists.AddRange(From le In lst.Lists Select New ListElement(le, Me))
2728 cursor = lst.NextCursor
2729 Catch ex As SerializationException
2730 TraceOut(ex.Message + Environment.NewLine + content)
2731 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2732 Catch ex As Exception
2733 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2734 Return "Err:Invalid Json!"
2736 Loop While cursor <> 0
2738 TabInformations.GetInstance.SubscribableLists = lists
2742 Public Function DeleteList(ByVal list_id As String) As String
2743 Dim res As HttpStatusCode
2744 Dim content As String = ""
2746 Google.GASender.GetInstance().TrackEventWithCategory("post", "destroy_list", Me.UserId)
2748 res = twCon.DeleteListID(Me.Username, list_id, content)
2749 Catch ex As Exception
2750 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2754 Case HttpStatusCode.OK
2755 Twitter.AccountState = ACCOUNT_STATE.Valid
2756 Case HttpStatusCode.Unauthorized
2757 Twitter.AccountState = ACCOUNT_STATE.Invalid
2758 Return My.Resources.Unauthorized
2759 Case HttpStatusCode.BadRequest
2760 Return "Err:API Limits?"
2762 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2768 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
2769 Google.GASender.GetInstance().TrackEventWithCategory("get", "update_list", Me.UserId)
2770 Dim res As HttpStatusCode
2771 Dim content As String = ""
2774 res = twCon.UpdateListID(Me.Username, list_id, new_name, isPrivate, description, content)
2775 Catch ex As Exception
2776 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2780 Case HttpStatusCode.OK
2781 Twitter.AccountState = ACCOUNT_STATE.Valid
2782 Case HttpStatusCode.Unauthorized
2783 Twitter.AccountState = ACCOUNT_STATE.Invalid
2784 Return My.Resources.Unauthorized
2785 Case HttpStatusCode.BadRequest
2786 Return "Err:API Limits?"
2788 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2792 Dim le = CreateDataFromJson(Of TwitterDataModel.ListElementData)(content)
2793 Dim newList As New ListElement(le, Me)
2794 list.Description = newList.Description
2795 list.Id = newList.Id
2796 list.IsPublic = newList.IsPublic
2797 list.MemberCount = newList.MemberCount
2798 list.Name = newList.Name
2799 list.SubscriberCount = newList.SubscriberCount
2800 list.Slug = newList.Slug
2801 list.Nickname = newList.Nickname
2802 list.Username = newList.Username
2803 list.UserId = newList.UserId
2805 Catch ex As SerializationException
2806 TraceOut(ex.Message + Environment.NewLine + content)
2807 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2808 Catch ex As Exception
2809 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2810 Return "Err:Invalid Json!"
2815 Public Function GetListMembers(ByVal list_id As String, ByVal lists As List(Of UserInfo), ByRef cursor As Long) As String
2816 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2818 Dim res As HttpStatusCode
2819 Dim content As String = ""
2823 res = twCon.GetListMembers(Me.Username, list_id, cursor, content)
2824 Catch ex As Exception
2825 Return "Err:" + ex.Message
2829 Case HttpStatusCode.OK
2830 Twitter.AccountState = ACCOUNT_STATE.Valid
2831 Case HttpStatusCode.Unauthorized
2832 Twitter.AccountState = ACCOUNT_STATE.Invalid
2833 Return My.Resources.Unauthorized
2834 Case HttpStatusCode.BadRequest
2835 Return "Err:API Limits?"
2837 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2841 Dim users = CreateDataFromJson(Of TwitterDataModel.Users)(content)
2842 Array.ForEach(Of TwitterDataModel.User)(
2844 New Action(Of TwitterDataModel.User)(Sub(u)
2845 lists.Add(New UserInfo(u))
2847 cursor = users.NextCursor
2849 Catch ex As SerializationException
2850 TraceOut(ex.Message + Environment.NewLine + content)
2851 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2852 Catch ex As Exception
2853 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2854 Return "Err:Invalid Json!"
2860 Public Function CreateListApi(ByVal listName As String, ByVal isPrivate As Boolean, ByVal description As String) As String
2861 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2863 Google.GASender.GetInstance().TrackEventWithCategory("post", "create_list", Me.UserId)
2864 Dim res As HttpStatusCode
2865 Dim content As String = ""
2868 res = twCon.CreateLists(listName, isPrivate, description, content)
2869 Catch ex As Exception
2870 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2874 Case HttpStatusCode.OK
2875 Twitter.AccountState = ACCOUNT_STATE.Valid
2876 Case HttpStatusCode.Unauthorized
2877 Twitter.AccountState = ACCOUNT_STATE.Invalid
2878 Return My.Resources.Unauthorized
2879 Case HttpStatusCode.BadRequest
2880 Return "Err:API Limits?"
2882 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2886 Dim le = CreateDataFromJson(Of TwitterDataModel.ListElementData)(content)
2887 TabInformations.GetInstance().SubscribableLists.Add(New ListElement(le, Me))
2889 Catch ex As SerializationException
2890 TraceOut(ex.Message + Environment.NewLine + content)
2891 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2892 Catch ex As Exception
2893 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2894 Return "Err:Invalid Json!"
2898 Public Function ContainsUserAtList(ByVal listId As String, ByVal user As String, ByRef value As Boolean) As String
2901 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2903 Dim res As HttpStatusCode
2904 Dim content As String = ""
2907 res = Me.twCon.ShowListMember(listId, user, content)
2908 Catch ex As Exception
2909 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2913 Case HttpStatusCode.OK
2914 Twitter.AccountState = ACCOUNT_STATE.Valid
2915 Case HttpStatusCode.Unauthorized
2916 Twitter.AccountState = ACCOUNT_STATE.Invalid
2917 Return My.Resources.Unauthorized
2918 Case HttpStatusCode.BadRequest
2919 Return "Err:API Limits?"
2920 Case HttpStatusCode.NotFound
2924 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2928 Dim u = CreateDataFromJson(Of TwitterDataModel.User)(content)
2931 Catch ex As Exception
2937 Public Function AddUserToList(ByVal listId As String, ByVal user As String) As String
2938 Dim content As String = ""
2939 Dim res As HttpStatusCode
2941 Google.GASender.GetInstance().TrackEventWithCategory("post", "add_user_to_list", Me.UserId)
2943 res = twCon.CreateListMembers(listId, user, content)
2944 Catch ex As Exception
2945 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2949 Case HttpStatusCode.OK
2950 Twitter.AccountState = ACCOUNT_STATE.Valid
2951 Case HttpStatusCode.Unauthorized
2952 Twitter.AccountState = ACCOUNT_STATE.Invalid
2953 Return My.Resources.Unauthorized
2954 Case HttpStatusCode.BadRequest
2955 Return "Err:" + GetErrorMessageJson(content)
2957 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2963 Public Function RemoveUserToList(ByVal listId As String, ByVal user As String) As String
2964 Google.GASender.GetInstance().TrackEventWithCategory("post", "remove_user_from_list", Me.UserId)
2966 Dim content As String = ""
2967 Dim res As HttpStatusCode
2970 res = twCon.DeleteListMembers(listId, user, content)
2971 Catch ex As Exception
2972 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2976 Case HttpStatusCode.OK
2977 Twitter.AccountState = ACCOUNT_STATE.Valid
2978 Case HttpStatusCode.Unauthorized
2979 Twitter.AccountState = ACCOUNT_STATE.Invalid
2980 Return My.Resources.Unauthorized
2981 Case HttpStatusCode.BadRequest
2982 Return "Err:" + GetErrorMessageJson(content)
2984 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2991 Public Property fromIndex As Integer
2992 Public Property toIndex As Integer
2993 Public Sub New(ByVal fromIndex As Integer, ByVal toIndex As Integer)
2994 Me.fromIndex = fromIndex
2995 Me.toIndex = toIndex
2998 Public Function CreateHtmlAnchor(ByVal Text As String, ByVal AtList As List(Of String), ByVal media As Dictionary(Of String, String)) As String
2999 If Text Is Nothing Then Return Nothing
3000 Dim retStr As String = Text.Replace(">", "<<<<<tweenだいなり>>>>>").Replace("<", "<<<<<tweenしょうなり>>>>>")
3002 'Const url_valid_domain As String = "(?<domain>(?:[^\p{P}\s][\.\-_](?=[^\p{P}\s])|[^\p{P}\s]){1,}\.[a-z]{2,}(?::[0-9]+)?)"
3003 'Const url_valid_general_path_chars As String = "[a-z0-9!*';:=+$/%#\[\]\-_,~]"
3004 'Const url_balance_parens As String = "(?:\(" + url_valid_general_path_chars + "+\))"
3005 'Const url_valid_url_path_ending_chars As String = "(?:[a-z0-9=_#/\-\+]+|" + url_balance_parens + ")"
3006 'Const pth As String = "(?:" + url_balance_parens +
3007 ' "|@" + url_valid_general_path_chars + "+/" +
3008 ' "|[.,]?" + url_valid_general_path_chars + "+" +
3010 'Const pth2 As String = "(/(?:" +
3011 ' pth + "+" + url_valid_url_path_ending_chars + "|" +
3012 ' pth + "+" + url_valid_url_path_ending_chars + "?|" +
3013 ' url_valid_url_path_ending_chars +
3015 'Const qry As String = "(?<query>\?[a-z0-9!*'();:&=+$/%#\[\]\-_.,~]*[a-z0-9_&=#])?"
3016 'Const rgUrl As String = "(?<before>(?:[^\""':!=#]|^|\:/))" +
3017 ' "(?<url>(?<protocol>https?://)" +
3018 ' url_valid_domain +
3022 'Const rgUrl As String = "(?<before>(?:[^\""':!=#]|^|\:/))" +
3023 ' "(?<url>(?<protocol>https?://|www\.)" +
3024 ' url_valid_domain +
3029 retStr = Regex.Replace(retStr,
3031 New MatchEvaluator(Function(mu As Match)
3032 Dim sb As New StringBuilder(mu.Result("${before}<a href="""))
3033 'If mu.Result("${protocol}").StartsWith("w", StringComparison.OrdinalIgnoreCase) Then
3034 ' sb.Append("http://")
3036 Dim url As String = mu.Result("${url}")
3037 Dim title As String = ShortUrl.ResolveMedia(url, True)
3038 If url <> title Then
3039 title = ShortUrl.ResolveMedia(title, False)
3041 sb.Append(url + """ title=""" + title + """>").Append(url).Append("</a>")
3042 If media IsNot Nothing AndAlso Not media.ContainsKey(url) Then media.Add(url, title)
3045 RegexOptions.IgnoreCase)
3048 retStr = Regex.Replace(retStr,
3049 "(^|[^a-zA-Z0-9_/])([@@]+)([a-zA-Z0-9_]{1,20}/[a-zA-Z][a-zA-Z0-9\p{IsLatin-1Supplement}\-]{0,79})",
3050 "$1$2<a href=""/$3"">$3</a>")
3052 Dim m As Match = Regex.Match(retStr, "(^|[^a-zA-Z0-9_])[@@]([a-zA-Z0-9_]{1,20})")
3054 If Not AtList.Contains(m.Result("$2").ToLower) Then AtList.Add(m.Result("$2").ToLower)
3058 retStr = Regex.Replace(retStr,
3059 "(^|[^a-zA-Z0-9_/])([@@])([a-zA-Z0-9_]{1,20})",
3060 "$1$2<a href=""/$3"">$3</a>")
3063 Dim anchorRange As New List(Of range)
3064 For i As Integer = 0 To retStr.Length - 1
3065 Dim index As Integer = retStr.IndexOf("<a ", i)
3066 If index > -1 AndAlso index < retStr.Length Then
3068 Dim toIndex As Integer = retStr.IndexOf("</a>", index)
3069 If toIndex > -1 Then
3070 anchorRange.Add(New range(index, toIndex + 3))
3075 'retStr = Regex.Replace(retStr,
3076 ' "(^|[^a-zA-Z0-9/&])([##])([0-9a-zA-Z_]*[a-zA-Z_]+[a-zA-Z0-9_\xc0-\xd6\xd8-\xf6\xf8-\xff]*)",
3077 ' New MatchEvaluator(Function(mh As Match)
3078 ' For Each rng As range In anchorRange
3079 ' If mh.Index >= rng.fromIndex AndAlso
3080 ' mh.Index <= rng.toIndex Then Return mh.Result("$0")
3082 ' If IsNumeric(mh.Result("$3")) Then Return mh.Result("$0")
3084 ' _hashList.Add("#" + mh.Result("$3"))
3086 ' Return mh.Result("$1") + "<a href=""" & _protocol & "twitter.com/search?q=%23" + mh.Result("$3") + """>" + mh.Result("$2$3") + "</a>"
3088 ' RegexOptions.IgnoreCase)
3089 retStr = Regex.Replace(retStr,
3091 New MatchEvaluator(Function(mh As Match)
3092 For Each rng As range In anchorRange
3093 If mh.Index >= rng.fromIndex AndAlso
3094 mh.Index <= rng.toIndex Then Return mh.Result("$0")
3097 _hashList.Add("#" + mh.Result("$3"))
3099 Return mh.Result("$1") + "<a href=""" & _protocol & "twitter.com/search?q=%23" + mh.Result("$3") + """>" + mh.Result("$2$3") + "</a>"
3101 RegexOptions.IgnoreCase)
3104 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>")
3106 retStr = retStr.Replace("<<<<<tweenだいなり>>>>>", ">").Replace("<<<<<tweenしょうなり>>>>>", "<")
3108 'retStr = AdjustHtml(ShortUrl.Resolve(PreProcessUrl(retStr), True)) 'IDN置換、短縮Uri解決、@リンクを相対→絶対にしてtarget属性付与
3109 retStr = AdjustHtml(PreProcessUrl(retStr)) 'IDN置換、短縮Uri解決、@リンクを相対→絶対にしてtarget属性付与
3113 Private Class EntityInfo
3114 Public Property StartIndex As Integer
3115 Public Property EndIndex As Integer
3116 Public Property Text As String
3117 Public Property Html As String
3118 Public Property Display As String
3120 Public Function CreateHtmlAnchor(ByRef Text As String, ByVal AtList As List(Of String), ByVal entities As TwitterDataModel.Entities, ByVal media As Dictionary(Of String, String)) As String
3121 Dim ret As String = Text
3123 If entities IsNot Nothing Then
3124 Dim etInfo As New SortedList(Of Integer, EntityInfo)
3126 If entities.Urls IsNot Nothing Then
3127 For Each ent In entities.Urls
3128 If String.IsNullOrEmpty(ent.DisplayUrl) Then
3129 etInfo.Add(ent.Indices(0),
3130 New EntityInfo With {.StartIndex = ent.Indices(0),
3131 .EndIndex = ent.Indices(1),
3133 .Html = "<a href=""" + ent.Url + """>" + ent.Url + "</a>"})
3135 Dim expanded As String = ShortUrl.ResolveMedia(ent.ExpandedUrl, False)
3136 etInfo.Add(ent.Indices(0),
3137 New EntityInfo With {.StartIndex = ent.Indices(0),
3138 .EndIndex = ent.Indices(1),
3140 .Html = "<a href=""" + ent.Url + """ title=""" + expanded + """>" + ent.DisplayUrl + "</a>",
3141 .Display = ent.DisplayUrl})
3142 If media IsNot Nothing AndAlso Not media.ContainsKey(ent.Url) Then media.Add(ent.Url, expanded)
3146 If entities.Hashtags IsNot Nothing Then
3147 For Each ent In entities.Hashtags
3148 Dim hash As String = Text.Substring(ent.Indices(0), ent.Indices(1) - ent.Indices(0))
3149 etInfo.Add(ent.Indices(0),
3150 New EntityInfo With {.StartIndex = ent.Indices(0),
3151 .EndIndex = ent.Indices(1),
3153 .Html = "<a href=""" & _protocol & "twitter.com/search?q=%23" + ent.Text + """>" + hash + "</a>"})
3155 _hashList.Add("#" + ent.Text)
3159 If entities.UserMentions IsNot Nothing Then
3160 For Each ent In entities.UserMentions
3161 Dim screenName As String = Text.Substring(ent.Indices(0) + 1, ent.Indices(1) - ent.Indices(0) - 1)
3162 etInfo.Add(ent.Indices(0) + 1,
3163 New EntityInfo With {.StartIndex = ent.Indices(0) + 1,
3164 .EndIndex = ent.Indices(1),
3165 .Text = ent.ScreenName,
3166 .Html = "<a href=""/" + ent.ScreenName + """>" + screenName + "</a>"})
3167 If Not AtList.Contains(ent.ScreenName.ToLower) Then AtList.Add(ent.ScreenName.ToLower)
3170 If entities.Media IsNot Nothing Then
3171 For Each ent In entities.Media
3172 If ent.Type = "photo" Then
3173 etInfo.Add(ent.Indices(0),
3174 New EntityInfo With {.StartIndex = ent.Indices(0),
3175 .EndIndex = ent.Indices(1),
3177 .Html = "<a href=""" + ent.Url + """ title=""" + ent.ExpandedUrl + """>" + ent.DisplayUrl + "</a>",
3178 .Display = ent.DisplayUrl})
3179 If media IsNot Nothing AndAlso Not media.ContainsKey(ent.Url) Then media.Add(ent.Url, ent.MediaUrl)
3183 If etInfo.Count > 0 Then
3184 Dim idx As Integer = 0
3186 For Each et In etInfo
3187 ret += Text.Substring(idx, et.Key - idx) + et.Value.Html
3188 idx = et.Value.EndIndex
3190 ret += Text.Substring(idx)
3194 ret = Regex.Replace(ret, "(^|[^a-zA-Z0-9_/&##@@>=.])(sm|nm)([0-9]{1,10})", "$1<a href=""http://www.nicovideo.jp/watch/$2$3"">$2$3</a>")
3195 ret = AdjustHtml(ShortUrl.Resolve(PreProcessUrl(ret), False)) 'IDN置換、短縮Uri解決、@リンクを相対→絶対にしてtarget属性付与
3201 Private Sub CreateSource(ByRef post As PostClass)
3202 If post.Source.StartsWith("<") Then
3203 If Not post.Source.Contains("</a>") Then
3204 post.Source += "</a>"
3206 Dim mS As Match = Regex.Match(post.Source, ">(?<source>.+)<")
3208 post.SourceHtml = String.Copy(ShortUrl.Resolve(PreProcessUrl(post.Source), False))
3209 post.Source = HttpUtility.HtmlDecode(mS.Result("${source}"))
3212 post.SourceHtml = ""
3215 If post.Source = "web" Then
3216 post.SourceHtml = My.Resources.WebSourceString
3217 ElseIf post.Source = "Keitai Mail" Then
3218 post.SourceHtml = My.Resources.KeitaiMailSourceString
3220 post.SourceHtml = String.Copy(post.Source)
3225 Public Function GetInfoApi(ByVal info As ApiInfo) As Boolean
3226 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return True
3228 If _endingFlag Then Return True
3230 Dim res As HttpStatusCode
3231 Dim content As String = ""
3233 res = twCon.RateLimitStatus(content)
3234 Catch ex As Exception
3235 TwitterApiInfo.Initialize()
3239 If res <> HttpStatusCode.OK Then Return False
3242 Dim limit = CreateDataFromJson(Of TwitterDataModel.RateLimitStatus)(content)
3243 Dim arg As New ApiInformationChangedEventArgs
3244 arg.ApiInfo.MaxCount = limit.HourlyLimit
3245 arg.ApiInfo.RemainCount = limit.RemainingHits
3246 arg.ApiInfo.ResetTime = DateTimeParse(limit.RestTime)
3247 arg.ApiInfo.ResetTimeInSeconds = limit.RestTimeInSeconds
3248 If info IsNot Nothing Then
3249 arg.ApiInfo.UsingCount = info.UsingCount
3251 info.MaxCount = arg.ApiInfo.MaxCount
3252 info.RemainCount = arg.ApiInfo.RemainCount
3253 info.ResetTime = arg.ApiInfo.ResetTime
3254 info.ResetTimeInSeconds = arg.ApiInfo.ResetTimeInSeconds
3257 RaiseEvent ApiInformationChanged(Me, arg)
3258 TwitterApiInfo.WriteBackEventArgs(arg)
3260 Catch ex As Exception
3261 TraceOut(ex, GetCurrentMethod.Name & " " & content)
3262 TwitterApiInfo.Initialize()
3266 Public Function GetBlockUserIds() As String
3267 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
3269 Dim res As HttpStatusCode
3270 Dim content As String = ""
3273 res = twCon.GetBlockUserIds(content)
3274 Catch ex As Exception
3275 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
3279 Case HttpStatusCode.OK
3280 Twitter.AccountState = ACCOUNT_STATE.Valid
3281 Case HttpStatusCode.Unauthorized
3282 Twitter.AccountState = ACCOUNT_STATE.Invalid
3283 Return My.Resources.Unauthorized
3284 Case HttpStatusCode.BadRequest
3285 Return "Err:API Limits?"
3287 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
3291 Dim Ids = CreateDataFromJson(Of Long())(content)
3292 TabInformations.GetInstance.BlockIds.AddRange(Ids)
3294 Catch ex As SerializationException
3295 TraceOut(ex.Message + Environment.NewLine + content)
3296 Return "Err:Json Parse Error(DataContractJsonSerializer)"
3297 Catch ex As Exception
3298 TraceOut(ex, GetCurrentMethod.Name & " " & content)
3299 Return "Err:Invalid Json!"
3304 Public Function GetHashList() As String()
3305 Dim hashArray As String()
3307 hashArray = _hashList.ToArray
3313 Public ReadOnly Property AccessToken() As String
3315 Return twCon.AccessToken
3319 Public ReadOnly Property AccessTokenSecret() As String
3321 Return twCon.AccessTokenSecret
3325 Public Event ApiInformationChanged(ByVal sender As Object, ByVal e As ApiInformationChangedEventArgs)
3327 Private Sub Twitter_ApiInformationChanged(ByVal sender As Object, ByVal e As ApiInformationChangedEventArgs) Handles Me.ApiInformationChanged
3330 #Region "UserStream"
3331 Public Property TrackWord As String = ""
3332 Public Property AllAtReply As Boolean = False
3334 Public Event NewPostFromStream()
3335 Public Event UserStreamStarted()
3336 Public Event UserStreamStopped()
3337 Public Event UserStreamGetFriendsList()
3338 Public Event PostDeleted(ByVal id As Long)
3339 Public Event UserStreamEventReceived(ByVal eventType As FormattedEvent)
3340 Private _lastUserstreamDataReceived As DateTime
3341 Private WithEvents userStream As TwitterUserstream
3343 Public Class FormattedEvent
3344 Public Property Eventtype As EVENTTYPE
3345 Public Property CreatedAt As DateTime
3346 Public Property [Event] As String
3347 Public Property Username As String
3348 Public Property Target As String
3349 Public Property Id As Int64
3350 Public Property IsMe As Boolean
3353 Public Property StoredEvent As New List(Of FormattedEvent)
3355 Private Class EventTypeTableElement
3356 Public Name As String
3357 Public Type As EVENTTYPE
3359 Public Sub New(ByVal name As String, ByVal type As EVENTTYPE)
3365 Private EventTable As EventTypeTableElement() = {
3366 New EventTypeTableElement("favorite", EVENTTYPE.Favorite), _
3367 New EventTypeTableElement("unfavorite", EVENTTYPE.Unfavorite), _
3368 New EventTypeTableElement("follow", EVENTTYPE.Follow), _
3369 New EventTypeTableElement("list_member_added", EVENTTYPE.ListMemberAdded), _
3370 New EventTypeTableElement("list_member_removed", EVENTTYPE.ListMemberRemoved), _
3371 New EventTypeTableElement("block", EVENTTYPE.Block), _
3372 New EventTypeTableElement("unblock", EVENTTYPE.Unblock), _
3373 New EventTypeTableElement("user_update", EVENTTYPE.UserUpdate), _
3374 New EventTypeTableElement("deleted", EVENTTYPE.Deleted), _
3375 New EventTypeTableElement("list_created", EVENTTYPE.ListCreated), _
3376 New EventTypeTableElement("list_updated", EVENTTYPE.ListUpdated)
3379 Public Function EventNameToEventType(ByVal EventName As String) As EVENTTYPE
3380 Return (From tbl In EventTable Where tbl.Name.Equals(EventName) Select tbl.Type).FirstOrDefault()
3383 Public ReadOnly Property IsUserstreamDataReceived As Boolean
3385 Return Now.Subtract(Me._lastUserstreamDataReceived).TotalSeconds < 31
3389 Private Sub userStream_StatusArrived(ByVal line As String) Handles userStream.StatusArrived
3390 Me._lastUserstreamDataReceived = Now
3391 If String.IsNullOrEmpty(line) Then Exit Sub
3393 Dim isDm As Boolean = False
3396 Using jsonReader As XmlDictionaryReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(line), XmlDictionaryReaderQuotas.Max)
3397 Dim xElm As XElement = XElement.Load(jsonReader)
3398 If xElm.Element("friends") IsNot Nothing Then
3399 Debug.Print("friends")
3401 ElseIf xElm.Element("delete") IsNot Nothing Then
3402 Debug.Print("delete")
3404 If xElm.Element("delete").Element("direct_message") IsNot Nothing AndAlso
3405 xElm.Element("delete").Element("direct_message").Element("id") IsNot Nothing Then
3406 id = CLng(xElm.Element("delete").Element("direct_message").Element("id").Value)
3407 RaiseEvent PostDeleted(id)
3408 ElseIf xElm.Element("delete").Element("status") IsNot Nothing AndAlso
3409 xElm.Element("delete").Element("status").Element("id") IsNot Nothing Then
3410 id = CLng(xElm.Element("delete").Element("status").Element("id").Value)
3411 RaiseEvent PostDeleted(id)
3413 TraceOut("delete:" + line)
3416 For i As Integer = Me.StoredEvent.Count - 1 To 0 Step -1
3417 Dim sEvt As FormattedEvent = Me.StoredEvent(i)
3418 If sEvt.Id = id AndAlso (sEvt.Event = "favorite" OrElse sEvt.Event = "unfavorite") Then
3419 Me.StoredEvent.RemoveAt(i)
3423 ElseIf xElm.Element("limit") IsNot Nothing Then
3426 ElseIf xElm.Element("event") IsNot Nothing Then
3427 Debug.Print("event: " + xElm.Element("event").Value)
3428 CreateEventFromJson(line)
3430 ElseIf xElm.Element("direct_message") IsNot Nothing Then
3431 Debug.Print("direct_message")
3433 ElseIf xElm.Element("scrub_geo") IsNot Nothing Then
3435 TabInformations.GetInstance.ScrubGeoReserve(Long.Parse(xElm.Element("scrub_geo").Element("user_id").Value),
3436 Long.Parse(xElm.Element("scrub_geo").Element("up_to_status_id").Value))
3437 Catch ex As Exception
3438 TraceOut("scrub_geo:" + line)
3444 Dim res As New StringBuilder
3451 CreateDirectMessagesFromJson(res.ToString, WORKERTYPE.UserStream, False)
3453 CreatePostsFromJson(res.ToString, WORKERTYPE.Timeline, Nothing, False, Nothing, Nothing)
3455 Catch ex As NullReferenceException
3456 TraceOut("NullRef StatusArrived: " + line)
3459 RaiseEvent NewPostFromStream()
3462 Private Sub CreateEventFromJson(ByVal content As String)
3463 Dim eventData As TwitterDataModel.EventData = Nothing
3465 eventData = CreateDataFromJson(Of TwitterDataModel.EventData)(content)
3466 Catch ex As SerializationException
3467 TraceOut(ex, "Event Serialize Exception!" + Environment.NewLine + content)
3468 Catch ex As Exception
3469 TraceOut(ex, "Event Exception!" + Environment.NewLine + content)
3472 Dim evt As New FormattedEvent
3473 evt.CreatedAt = DateTimeParse(eventData.CreatedAt)
3474 evt.Event = eventData.Event
3475 evt.Username = eventData.Source.ScreenName
3476 evt.IsMe = evt.Username.ToLower().Equals(Me.Username.ToLower())
3477 evt.Eventtype = EventNameToEventType(evt.Event)
3478 Select Case eventData.Event
3480 If eventData.Target.ScreenName.ToLower.Equals(_uname) Then
3481 If Not Me.followerId.Contains(eventData.Source.Id) Then Me.followerId.Add(eventData.Source.Id)
3483 Exit Sub 'Block後のUndoをすると、SourceとTargetが逆転したfollowイベントが帰ってくるため。
3486 Case "favorite", "unfavorite"
3487 evt.Target = "@" + eventData.TargetObject.User.ScreenName + ":" + HttpUtility.HtmlDecode(eventData.TargetObject.Text)
3488 evt.Id = eventData.TargetObject.Id
3489 If TabInformations.GetInstance.ContainsKey(eventData.TargetObject.Id) Then
3490 Dim post As PostClass = TabInformations.GetInstance.Item(eventData.TargetObject.Id)
3491 If eventData.Event = "favorite" Then
3492 If evt.Username.ToLower.Equals(_uname) Then
3494 TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Add(post.StatusId, post.IsRead, False)
3496 post.FavoritedCount += 1
3497 If Not TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.StatusId) Then
3498 If TweenMain.GetInstance().FavEventChangeUnread AndAlso post.IsRead Then
3501 TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Add(post.StatusId, post.IsRead, False)
3503 If TweenMain.GetInstance().FavEventChangeUnread Then
3504 TabInformations.GetInstance.SetRead(False, TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).TabName, TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).IndexOf(post.StatusId))
3509 If evt.Username.ToLower.Equals(_uname) Then
3512 post.FavoritedCount -= 1
3513 If post.FavoritedCount < 0 Then post.FavoritedCount = 0
3517 Case "list_member_added", "list_member_removed", "list_updated"
3518 evt.Target = eventData.TargetObject.FullName
3520 If Not TabInformations.GetInstance.BlockIds.Contains(eventData.Target.Id) Then TabInformations.GetInstance.BlockIds.Add(eventData.Target.Id)
3523 If TabInformations.GetInstance.BlockIds.Contains(eventData.Target.Id) Then TabInformations.GetInstance.BlockIds.Remove(eventData.Target.Id)
3530 TraceOut("Unknown Event:" + evt.Event + Environment.NewLine + content)
3532 Me.StoredEvent.Insert(0, evt)
3533 RaiseEvent UserStreamEventReceived(evt)
3536 Private Sub userStream_Started() Handles userStream.Started
3537 Google.GASender.GetInstance().TrackPage("/userstream", Me.UserId)
3538 RaiseEvent UserStreamStarted()
3541 Private Sub userStream_Stopped() Handles userStream.Stopped
3542 RaiseEvent UserStreamStopped()
3545 Public ReadOnly Property UserStreamEnabled As Boolean
3547 Return If(userStream Is Nothing, False, userStream.Enabled)
3551 Public Sub StartUserStream()
3552 If userStream IsNot Nothing Then
3555 userStream = New TwitterUserstream(twCon)
3556 userStream.Start(Me.AllAtReply, Me.TrackWord)
3559 Public Sub StopUserStream()
3560 If userStream IsNot Nothing Then userStream.Dispose()
3561 userStream = Nothing
3562 If Not _endingFlag Then RaiseEvent UserStreamStopped()
3565 Public Sub ReconnectUserStream()
3566 If userStream IsNot Nothing Then
3567 Me.StartUserStream()
3571 Private Class TwitterUserstream
3572 Implements IDisposable
3574 Public Event StatusArrived(ByVal status As String)
3575 Public Event Stopped()
3576 Public Event Started()
3577 Private twCon As HttpTwitter
3579 Private _streamThread As Thread
3580 Private _streamActive As Boolean
3582 Private _allAtreplies As Boolean = False
3583 Private _trackwords As String = ""
3585 Public Sub New(ByVal twitterConnection As HttpTwitter)
3586 twCon = DirectCast(twitterConnection.Clone(), HttpTwitter)
3589 Public Sub Start(ByVal allAtReplies As Boolean, ByVal trackwords As String)
3590 Me.AllAtReplies = allAtReplies
3591 Me.TrackWords = trackwords
3592 _streamActive = True
3593 If _streamThread IsNot Nothing AndAlso _streamThread.IsAlive Then Exit Sub
3594 _streamThread = New Thread(AddressOf UserStreamLoop)
3595 _streamThread.Name = "UserStreamReceiver"
3596 _streamThread.IsBackground = True
3597 _streamThread.Start()
3600 Public ReadOnly Property Enabled() As Boolean
3602 Return _streamActive
3606 Public Property AllAtReplies As Boolean
3608 Return _allAtreplies
3610 Set(ByVal value As Boolean)
3611 _allAtreplies = value
3615 Public Property TrackWords As String
3619 Set(ByVal value As String)
3624 Private Sub UserStreamLoop()
3625 Dim st As Stream = Nothing
3626 Dim sr As StreamReader = Nothing
3627 Dim sleepSec As Integer = 0
3630 If Not MyCommon.IsNetworkAvailable() Then
3631 Thread.Sleep(30 * 1000)
3635 RaiseEvent Started()
3636 Dim res As HttpStatusCode = twCon.UserStream(st, _allAtreplies, _trackwords, GetUserAgentString())
3639 Case HttpStatusCode.OK
3640 Twitter.AccountState = ACCOUNT_STATE.Valid
3641 Case HttpStatusCode.Unauthorized
3642 Twitter.AccountState = ACCOUNT_STATE.Invalid
3647 If st Is Nothing Then
3649 'TraceOut("Stop:stream is Nothing")
3653 sr = New StreamReader(st)
3655 Do While _streamActive AndAlso Not sr.EndOfStream AndAlso Twitter.AccountState = ACCOUNT_STATE.Valid
3656 RaiseEvent StatusArrived(sr.ReadLine())
3660 If sr.EndOfStream OrElse Twitter.AccountState = ACCOUNT_STATE.Invalid Then
3662 'TraceOut("Stop:EndOfStream")
3666 Catch ex As WebException
3667 If ex.Status = WebExceptionStatus.Timeout Then
3668 sleepSec = 30 'TraceOut("Stop:Timeout")
3669 ElseIf ex.Response IsNot Nothing AndAlso CType(ex.Response, HttpWebResponse).StatusCode = 420 Then
3670 'TraceOut("Stop:Connection Limit")
3674 'TraceOut("Stop:WebException " & ex.Status.ToString)
3676 Catch ex As ThreadAbortException
3678 Catch ex As IOException
3680 'TraceOut("Stop:IOException with Active." + Environment.NewLine + ex.Message)
3681 Catch ex As ArgumentException
3682 'System.ArgumentException: ストリームを読み取れませんでした。
3683 'サーバー側もしくは通信経路上で切断された場合?タイムアウト頻発後発生
3685 TraceOut(ex, "Stop:ArgumentException")
3686 Catch ex As Exception
3687 TraceOut("Stop:Exception." + Environment.NewLine + ex.Message)
3691 If _streamActive Then RaiseEvent Stopped()
3692 twCon.RequestAbort()
3693 If sr IsNot Nothing Then sr.Close()
3694 If st IsNot Nothing Then st.Close()
3695 If sleepSec > 0 Then
3696 Dim ms As Integer = 0
3697 Do While _streamActive AndAlso ms < sleepSec * 1000
3704 Loop While Me._streamActive
3706 If _streamActive Then RaiseEvent Stopped()
3707 TraceOut("Stop:EndLoop")
3710 #Region "IDisposable Support"
3711 Private disposedValue As Boolean ' 重複する呼び出しを検出するには
3714 Protected Overridable Sub Dispose(ByVal disposing As Boolean)
3715 If Not Me.disposedValue Then
3717 ' TODO: マネージ状態を破棄します (マネージ オブジェクト)。
3718 _streamActive = False
3719 If _streamThread IsNot Nothing AndAlso _streamThread.IsAlive Then
3720 _streamThread.Abort()
3724 ' TODO: アンマネージ リソース (アンマネージ オブジェクト) を解放し、下の Finalize() をオーバーライドします。
3725 ' TODO: 大きなフィールドを null に設定します。
3727 Me.disposedValue = True
3730 ' TODO: 上の Dispose(ByVal disposing As Boolean) にアンマネージ リソースを解放するコードがある場合にのみ、Finalize() をオーバーライドします。
3731 'Protected Overrides Sub Finalize()
3732 ' ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
3737 ' このコードは、破棄可能なパターンを正しく実装できるように Visual Basic によって追加されました。
3738 Public Sub Dispose() Implements IDisposable.Dispose
3739 ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
3741 GC.SuppressFinalize(Me)
3748 #Region "IDisposable Support"
3749 Private disposedValue As Boolean ' 重複する呼び出しを検出するには
3752 Protected Overridable Sub Dispose(ByVal disposing As Boolean)
3753 If Not Me.disposedValue Then
3755 ' TODO: マネージ状態を破棄します (マネージ オブジェクト)。
3759 ' TODO: アンマネージ リソース (アンマネージ オブジェクト) を解放し、下の Finalize() をオーバーライドします。
3760 ' TODO: 大きなフィールドを null に設定します。
3762 Me.disposedValue = True
3765 ' TODO: 上の Dispose(ByVal disposing As Boolean) にアンマネージ リソースを解放するコードがある場合にのみ、Finalize() をオーバーライドします。
3766 'Protected Overrides Sub Finalize()
3767 ' ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
3772 ' このコードは、破棄可能なパターンを正しく実装できるように Visual Basic によって追加されました。
3773 Public Sub Dispose() Implements IDisposable.Dispose
3774 ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
3776 GC.SuppressFinalize(Me)