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
268 Public Function PreProcessUrl(ByVal orgData As String) As String
270 Dim posl2 As Integer = 0
271 'Dim IDNConveter As IdnMapping = New IdnMapping()
272 Dim href As String = "<a href="""
275 If orgData.IndexOf(href, posl2, StringComparison.Ordinal) > -1 Then
276 Dim urlStr As String = ""
278 posl1 = orgData.IndexOf(href, posl2, StringComparison.Ordinal)
280 posl2 = orgData.IndexOf("""", posl1, StringComparison.Ordinal)
281 urlStr = orgData.Substring(posl1, posl2 - posl1)
283 If Not urlStr.StartsWith("http://") AndAlso Not urlStr.StartsWith("https://") AndAlso Not urlStr.StartsWith("ftp://") Then
287 Dim replacedUrl As String = IDNDecode(urlStr)
288 If replacedUrl Is Nothing Then Continue Do
289 If replacedUrl = urlStr Then Continue Do
291 orgData = orgData.Replace("<a href=""" + urlStr, "<a href=""" + replacedUrl)
300 Private Function GetPlainText(ByVal orgData As String) As String
301 Return HttpUtility.HtmlDecode(Regex.Replace(orgData, "(?<tagStart><a [^>]+>)(?<text>[^<]+)(?<tagEnd></a>)", "${text}"))
304 ' htmlの簡易サニタイズ(詳細表示に不要なタグの除去)
306 Private Function SanitizeHtml(ByVal orgdata As String) As String
307 Dim retdata As String = orgdata
309 retdata = Regex.Replace(retdata, "<(script|object|applet|image|frameset|fieldset|legend|style).*" & _
310 "</(script|object|applet|image|frameset|fieldset|legend|style)>", "", RegexOptions.IgnoreCase)
312 retdata = Regex.Replace(retdata, "<(frame|link|iframe|img)>", "", RegexOptions.IgnoreCase)
317 Private Function AdjustHtml(ByVal orgData As String) As String
318 Dim retStr As String = orgData
319 'Dim m As Match = Regex.Match(retStr, "<a [^>]+>[#|#](?<1>[a-zA-Z0-9_]+)</a>")
322 ' _hashList.Add("#" + m.Groups(1).Value)
326 retStr = Regex.Replace(retStr, "<a [^>]*href=""/", "<a href=""" + _protocol + "twitter.com/")
327 retStr = retStr.Replace("<a href=", "<a target=""_self"" href=")
328 retStr = retStr.Replace(vbLf, "<br>")
330 '半角スペースを置換(Thanks @anis774)
331 Dim ret As Boolean = False
333 ret = EscapeSpace(retStr)
336 Return SanitizeHtml(retStr)
339 Private Function EscapeSpace(ByRef html As String) As Boolean
340 '半角スペースを置換(Thanks @anis774)
341 Dim isTag As Boolean = False
342 For i As Integer = 0 To html.Length - 1
343 If html(i) = "<"c Then
346 If html(i) = ">"c Then
350 If (Not isTag) AndAlso (html(i) = " "c) Then
351 html = html.Remove(i, 1)
352 html = html.Insert(i, " ")
359 Private Structure PostInfo
360 Public CreatedAt As String
362 Public Text As String
363 Public UserId As String
364 Public Sub New(ByVal Created As String, ByVal IdStr As String, ByVal txt As String, ByVal uid As String)
370 Public Shadows Function Equals(ByVal dst As PostInfo) As Boolean
371 If Me.CreatedAt = dst.CreatedAt AndAlso Me.Id = dst.Id AndAlso Me.Text = dst.Text AndAlso Me.UserId = dst.UserId Then
379 Private Function IsPostRestricted(ByVal status As TwitterDataModel.Status) As Boolean
380 Static _prev As New PostInfo("", "", "", "")
381 Dim _current As New PostInfo("", "", "", "")
383 _current.CreatedAt = status.CreatedAt
384 _current.Id = status.IdStr
385 If status.Text Is Nothing Then
388 _current.Text = status.Text
390 _current.UserId = status.User.IdStr
392 If _current.Equals(_prev) Then
395 _prev.CreatedAt = _current.CreatedAt
396 _prev.Id = _current.Id
397 _prev.Text = _current.Text
398 _prev.UserId = _current.UserId
403 Public Function PostStatus(ByVal postStr As String, ByVal reply_to As Long) As String
405 If _endingFlag Then Return ""
407 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
409 postStr = postStr.Trim()
411 If Regex.Match(postStr, "^DM? +(?<id>[a-zA-Z0-9_]+) +(?<body>.+)", RegexOptions.IgnoreCase Or RegexOptions.Singleline).Success Then
412 Return SendDirectMessage(postStr)
415 Google.GASender.GetInstance().TrackEventWithCategory("post", "status", Me.UserId)
417 Dim res As HttpStatusCode
418 Dim content As String = ""
420 res = twCon.UpdateStatus(postStr, reply_to, content)
421 Catch ex As Exception
422 Return "Err:" + ex.Message
426 Case HttpStatusCode.OK
427 Twitter.AccountState = ACCOUNT_STATE.Valid
428 Dim status As TwitterDataModel.Status
430 status = CreateDataFromJson(Of TwitterDataModel.Status)(content)
431 Catch ex As SerializationException
432 TraceOut(ex.Message + Environment.NewLine + content)
433 Return "Err:Json Parse Error(DataContractJsonSerializer)"
434 Catch ex As Exception
435 TraceOut(ex, GetCurrentMethod.Name & " " & content)
436 Return "Err:Invalid Json!"
438 _followersCount = status.User.FollowersCount
439 _friendsCount = status.User.FriendsCount
440 _statusesCount = status.User.StatusesCount
441 _location = status.User.Location
442 _bio = status.User.Description
444 If IsPostRestricted(status) Then
445 Return "OK:Delaying?"
447 If op.Post(postStr.Length) Then
450 Return "Outputz:Failed"
452 Case HttpStatusCode.NotFound
454 Case HttpStatusCode.Forbidden, HttpStatusCode.BadRequest
455 Dim errMsg As String = GetErrorMessageJson(content)
456 If String.IsNullOrEmpty(errMsg) Then
457 Return "Warn:" + res.ToString
459 Return "Warn:" + errMsg
461 Case HttpStatusCode.Conflict, _
462 HttpStatusCode.ExpectationFailed, _
463 HttpStatusCode.Gone, _
464 HttpStatusCode.LengthRequired, _
465 HttpStatusCode.MethodNotAllowed, _
466 HttpStatusCode.NotAcceptable, _
467 HttpStatusCode.NotFound, _
468 HttpStatusCode.PaymentRequired, _
469 HttpStatusCode.PreconditionFailed, _
470 HttpStatusCode.RequestedRangeNotSatisfiable, _
471 HttpStatusCode.RequestEntityTooLarge, _
472 HttpStatusCode.RequestTimeout, _
473 HttpStatusCode.RequestUriTooLong
474 '仕様書にない400系エラー。サーバまでは到達しているのでリトライしない
475 Return "Warn:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
476 Case HttpStatusCode.Unauthorized
477 Twitter.AccountState = ACCOUNT_STATE.Invalid
478 Dim errMsg As String = GetErrorMessageJson(content)
479 If String.IsNullOrEmpty(errMsg) Then
480 Return My.Resources.Unauthorized
482 Return "Auth err:" + errMsg
485 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
489 Public Function PostStatusWithMedia(ByVal postStr As String, ByVal reply_to As Long, ByVal mediaFile As FileInfo) As String
491 If _endingFlag Then Return ""
493 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
495 postStr = postStr.Trim()
497 Google.GASender.GetInstance().TrackEventWithCategory("post", "status_with_media", Me.UserId)
499 Dim res As HttpStatusCode
500 Dim content As String = ""
502 res = twCon.UpdateStatusWithMedia(postStr, reply_to, mediaFile, content)
503 Catch ex As Exception
504 Return "Err:" + ex.Message
508 Case HttpStatusCode.OK
509 Twitter.AccountState = ACCOUNT_STATE.Valid
510 Dim status As TwitterDataModel.Status
512 status = CreateDataFromJson(Of TwitterDataModel.Status)(content)
513 Catch ex As SerializationException
514 TraceOut(ex.Message + Environment.NewLine + content)
515 Return "Err:Json Parse Error(DataContractJsonSerializer)"
516 Catch ex As Exception
517 TraceOut(ex, GetCurrentMethod.Name & " " & content)
518 Return "Err:Invalid Json!"
520 _followersCount = status.User.FollowersCount
521 _friendsCount = status.User.FriendsCount
522 _statusesCount = status.User.StatusesCount
523 _location = status.User.Location
524 _bio = status.User.Description
526 If IsPostRestricted(status) Then
527 Return "OK:Delaying?"
529 If op.Post(postStr.Length) Then
532 Return "Outputz:Failed"
534 Case HttpStatusCode.NotFound
536 Case HttpStatusCode.Forbidden, HttpStatusCode.BadRequest
537 Dim errMsg As String = GetErrorMessageJson(content)
538 If String.IsNullOrEmpty(errMsg) Then
539 Return "Warn:" + res.ToString
541 Return "Warn:" + errMsg
543 Case HttpStatusCode.Conflict, _
544 HttpStatusCode.ExpectationFailed, _
545 HttpStatusCode.Gone, _
546 HttpStatusCode.LengthRequired, _
547 HttpStatusCode.MethodNotAllowed, _
548 HttpStatusCode.NotAcceptable, _
549 HttpStatusCode.NotFound, _
550 HttpStatusCode.PaymentRequired, _
551 HttpStatusCode.PreconditionFailed, _
552 HttpStatusCode.RequestedRangeNotSatisfiable, _
553 HttpStatusCode.RequestEntityTooLarge, _
554 HttpStatusCode.RequestTimeout, _
555 HttpStatusCode.RequestUriTooLong
556 '仕様書にない400系エラー。サーバまでは到達しているのでリトライしない
557 Return "Warn:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
558 Case HttpStatusCode.Unauthorized
559 Twitter.AccountState = ACCOUNT_STATE.Invalid
560 Dim errMsg As String = GetErrorMessageJson(content)
561 If String.IsNullOrEmpty(errMsg) Then
562 Return My.Resources.Unauthorized
564 Return "Auth err:" + errMsg
567 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
571 Public Function SendDirectMessage(ByVal postStr As String) As String
573 If _endingFlag Then Return ""
575 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
576 If Not TwitterApiInfo.IsDirectMessagePermission Then Return "Auth Err:try to re-authorization."
578 Google.GASender.GetInstance().TrackEventWithCategory("post", "direct_message", Me.UserId)
580 postStr = postStr.Trim()
582 Dim res As HttpStatusCode
583 Dim content As String = ""
585 Dim mc As Match = Regex.Match(postStr, "^DM? +(?<id>[a-zA-Z0-9_]+) +(?<body>.+)", RegexOptions.IgnoreCase Or RegexOptions.Singleline)
588 res = twCon.SendDirectMessage(mc.Groups("body").Value, mc.Groups("id").Value, content)
589 Catch ex As Exception
590 Return "Err:" + ex.Message
594 Case HttpStatusCode.OK
595 Twitter.AccountState = ACCOUNT_STATE.Valid
596 Dim status As TwitterDataModel.Directmessage
598 status = CreateDataFromJson(Of TwitterDataModel.Directmessage)(content)
599 Catch ex As SerializationException
600 TraceOut(ex.Message + Environment.NewLine + content)
601 Return "Err:Json Parse Error(DataContractJsonSerializer)"
602 Catch ex As Exception
603 TraceOut(ex, GetCurrentMethod.Name & " " & content)
604 Return "Err:Invalid Json!"
606 _followersCount = status.Sender.FollowersCount
607 _friendsCount = status.Sender.FriendsCount
608 _statusesCount = status.Sender.StatusesCount
609 _location = status.Sender.Location
610 _bio = status.Sender.Description
612 If op.Post(postStr.Length) Then
615 Return "Outputz:Failed"
617 Case HttpStatusCode.Forbidden, HttpStatusCode.BadRequest
618 Dim errMsg As String = GetErrorMessageJson(content)
619 If String.IsNullOrEmpty(errMsg) Then
620 Return "Warn:" + res.ToString
622 Return "Warn:" + errMsg
624 Case HttpStatusCode.Conflict, _
625 HttpStatusCode.ExpectationFailed, _
626 HttpStatusCode.Gone, _
627 HttpStatusCode.LengthRequired, _
628 HttpStatusCode.MethodNotAllowed, _
629 HttpStatusCode.NotAcceptable, _
630 HttpStatusCode.NotFound, _
631 HttpStatusCode.PaymentRequired, _
632 HttpStatusCode.PreconditionFailed, _
633 HttpStatusCode.RequestedRangeNotSatisfiable, _
634 HttpStatusCode.RequestEntityTooLarge, _
635 HttpStatusCode.RequestTimeout, _
636 HttpStatusCode.RequestUriTooLong
637 '仕様書にない400系エラー。サーバまでは到達しているのでリトライしない
638 Return "Warn:" + res.ToString
639 Case HttpStatusCode.Unauthorized
640 Twitter.AccountState = ACCOUNT_STATE.Invalid
641 Dim errMsg As String = GetErrorMessageJson(content)
642 If String.IsNullOrEmpty(errMsg) Then
643 Return My.Resources.Unauthorized
645 Return "Auth err:" + errMsg
648 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
652 Public Function RemoveStatus(ByVal id As Long) As String
653 If _endingFlag Then Return ""
655 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
657 Google.GASender.GetInstance().TrackEventWithCategory("post", "destroy", Me.UserId)
658 Dim res As HttpStatusCode
661 res = twCon.DestroyStatus(id)
662 Catch ex As Exception
663 Return "Err:" + ex.Message
667 Case HttpStatusCode.OK
668 Twitter.AccountState = ACCOUNT_STATE.Valid
670 Case HttpStatusCode.Unauthorized
671 Twitter.AccountState = ACCOUNT_STATE.Invalid
672 Return My.Resources.Unauthorized
673 Case HttpStatusCode.NotFound
676 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
681 Public Function PostRetweet(ByVal id As Long, ByVal read As Boolean) As String
682 If _endingFlag Then Return ""
683 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
686 Dim target As Long = id
687 If TabInformations.GetInstance.Item(id).RetweetedId > 0 Then
688 target = TabInformations.GetInstance.Item(id).RetweetedId '再RTの場合は元発言をRT
691 Google.GASender.GetInstance().TrackEventWithCategory("post", "retweet", Me.UserId)
692 Dim res As HttpStatusCode
693 Dim content As String = ""
695 res = twCon.RetweetStatus(target, content)
696 Catch ex As Exception
697 Return "Err:" + ex.Message
701 Case HttpStatusCode.Unauthorized
702 'Blockユーザーの発言をRTすると認証エラー返る
703 'Twitter.AccountState = ACCOUNT_STATE.Invalid
704 Return My.Resources.Unauthorized + " or blocked user."
705 Case Is <> HttpStatusCode.OK
706 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
709 Twitter.AccountState = ACCOUNT_STATE.Valid
711 Dim status As TwitterDataModel.Status
713 status = CreateDataFromJson(Of TwitterDataModel.Status)(content)
714 Catch ex As SerializationException
715 TraceOut(ex.Message + Environment.NewLine + content)
716 Return "Err:Json Parse Error(DataContractJsonSerializer)"
717 Catch ex As Exception
718 TraceOut(ex, GetCurrentMethod.Name & " " & content)
719 Return "Err:Invalid Json!"
723 Dim post As PostClass = CreatePostsFromStatusData(status)
724 If post Is Nothing Then Return "Invalid Json!"
728 If TabInformations.GetInstance.ContainsKey(post.StatusId) Then Return ""
731 If post.RetweetedId = 0 Then Return "Invalid Json!"
737 If _readOwnPost Then post.IsRead = True
740 TabInformations.GetInstance.AddPost(post)
745 Public Function RemoveDirectMessage(ByVal id As Long, ByVal post As PostClass) As String
746 If _endingFlag Then Return ""
748 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
749 If Not TwitterApiInfo.IsDirectMessagePermission Then Return "Auth Err:try to re-authorization."
751 Google.GASender.GetInstance().TrackEventWithCategory("post", "destroy_direct_message", Me.UserId)
752 Dim res As HttpStatusCode
755 ' _deletemessages.Add(post)
758 res = twCon.DestroyDirectMessage(id)
759 Catch ex As Exception
760 Return "Err:" + ex.Message
764 Case HttpStatusCode.OK
765 Twitter.AccountState = ACCOUNT_STATE.Valid
767 Case HttpStatusCode.Unauthorized
768 Twitter.AccountState = ACCOUNT_STATE.Invalid
769 Return My.Resources.Unauthorized
770 Case HttpStatusCode.NotFound
773 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
777 Public Function PostFollowCommand(ByVal screenName As String) As String
779 If _endingFlag Then Return ""
781 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
783 Google.GASender.GetInstance().TrackEventWithCategory("post", "follow", Me.UserId)
784 Dim res As HttpStatusCode
785 Dim content As String = ""
788 res = twCon.CreateFriendships(screenName, content)
789 Catch ex As Exception
790 Return "Err:" + ex.Message
794 Case HttpStatusCode.OK
795 Twitter.AccountState = ACCOUNT_STATE.Valid
797 Case HttpStatusCode.Unauthorized
798 Twitter.AccountState = ACCOUNT_STATE.Invalid
799 Return My.Resources.Unauthorized
800 Case HttpStatusCode.Forbidden
801 Dim errMsg As String = GetErrorMessageJson(content)
802 If String.IsNullOrEmpty(errMsg) Then
803 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
805 Return "Err:" + errMsg
808 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
812 Public Function PostRemoveCommand(ByVal screenName As String) As String
814 If _endingFlag Then Return ""
816 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
818 Google.GASender.GetInstance().TrackEventWithCategory("post", "destroy_friendships", Me.UserId)
819 Dim res As HttpStatusCode
820 Dim content As String = ""
823 res = twCon.DestroyFriendships(screenName, content)
824 Catch ex As Exception
825 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
829 Case HttpStatusCode.OK
830 Twitter.AccountState = ACCOUNT_STATE.Valid
832 Case HttpStatusCode.Unauthorized
833 Twitter.AccountState = ACCOUNT_STATE.Invalid
834 Return My.Resources.Unauthorized
835 Case HttpStatusCode.Forbidden
836 Dim errMsg As String = GetErrorMessageJson(content)
837 If String.IsNullOrEmpty(errMsg) Then
838 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
840 Return "Err:" + errMsg
843 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
847 Public Function PostCreateBlock(ByVal screenName As String) As String
849 If _endingFlag Then Return ""
851 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
853 Google.GASender.GetInstance().TrackEventWithCategory("post", "block", Me.UserId)
854 Dim res As HttpStatusCode
855 Dim content As String = ""
858 res = twCon.CreateBlock(screenName, content)
859 Catch ex As Exception
860 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
864 Case HttpStatusCode.OK
865 Twitter.AccountState = ACCOUNT_STATE.Valid
867 Case HttpStatusCode.Unauthorized
868 Twitter.AccountState = ACCOUNT_STATE.Invalid
869 Return My.Resources.Unauthorized
870 Case HttpStatusCode.Forbidden
871 Dim errMsg As String = GetErrorMessageJson(content)
872 If String.IsNullOrEmpty(errMsg) Then
873 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
875 Return "Err:" + errMsg
878 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
882 Public Function PostDestroyBlock(ByVal screenName As String) As String
884 If _endingFlag Then Return ""
886 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
888 Google.GASender.GetInstance().TrackEventWithCategory("post", "destroy_block", Me.UserId)
889 Dim res As HttpStatusCode
890 Dim content As String = ""
893 res = twCon.DestroyBlock(screenName, content)
894 Catch ex As Exception
895 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
899 Case HttpStatusCode.OK
900 Twitter.AccountState = ACCOUNT_STATE.Valid
902 Case HttpStatusCode.Unauthorized
903 Twitter.AccountState = ACCOUNT_STATE.Invalid
904 Return My.Resources.Unauthorized
905 Case HttpStatusCode.Forbidden
906 Dim errMsg As String = GetErrorMessageJson(content)
907 If String.IsNullOrEmpty(errMsg) Then
908 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
910 Return "Err:" + errMsg
913 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
917 Public Function PostReportSpam(ByVal screenName As String) As String
919 If _endingFlag Then Return ""
921 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
923 Google.GASender.GetInstance().TrackEventWithCategory("post", "spam", Me.UserId)
924 Dim res As HttpStatusCode
925 Dim content As String = ""
928 res = twCon.ReportSpam(screenName, content)
929 Catch ex As Exception
930 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
934 Case HttpStatusCode.OK
935 Twitter.AccountState = ACCOUNT_STATE.Valid
937 Case HttpStatusCode.Unauthorized
938 Twitter.AccountState = ACCOUNT_STATE.Invalid
939 Return My.Resources.Unauthorized
940 Case HttpStatusCode.Forbidden
941 Dim errMsg As String = GetErrorMessageJson(content)
942 If String.IsNullOrEmpty(errMsg) Then
943 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
945 Return "Err:" + errMsg
948 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
952 Public Function GetFriendshipInfo(ByVal screenName As String, ByRef isFollowing As Boolean, ByRef isFollowed As Boolean) As String
954 If _endingFlag Then Return ""
956 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
958 Google.GASender.GetInstance().TrackPage("/friendships", Me.UserId)
959 Dim res As HttpStatusCode
960 Dim content As String = ""
962 res = twCon.ShowFriendships(_uname, screenName, content)
963 Catch ex As Exception
964 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
968 Case HttpStatusCode.OK
970 Dim relation = CreateDataFromJson(Of TwitterDataModel.Relationship)(content)
971 isFollowing = relation.Relationship.Source.Following
972 isFollowed = relation.Relationship.Source.FollowedBy
974 Catch ex As SerializationException
975 TraceOut(ex.Message + Environment.NewLine + content)
976 Return "Err:Json Parse Error(DataContractJsonSerializer)"
977 Catch ex As Exception
978 TraceOut(ex, GetCurrentMethod.Name & " " & content)
979 Return "Err:Invalid Json!"
981 Case HttpStatusCode.BadRequest
982 Return "Err:API Limits?"
983 Case HttpStatusCode.Unauthorized
984 Twitter.AccountState = ACCOUNT_STATE.Invalid
985 Return My.Resources.Unauthorized
987 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
991 Public Function GetUserInfo(ByVal screenName As String, ByRef user As TwitterDataModel.User) As String
993 If _endingFlag Then Return ""
995 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
997 Google.GASender.GetInstance().TrackPage("/showuser", Me.UserId)
998 Dim res As HttpStatusCode
999 Dim content As String = ""
1002 res = twCon.ShowUserInfo(screenName, content)
1003 Catch ex As Exception
1004 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
1008 Case HttpStatusCode.OK
1009 Twitter.AccountState = ACCOUNT_STATE.Valid
1011 user = CreateDataFromJson(Of TwitterDataModel.User)(content)
1012 Catch ex As SerializationException
1013 TraceOut(ex.Message + Environment.NewLine + content)
1014 Return "Err:Json Parse Error(DataContractJsonSerializer)"
1015 Catch ex As Exception
1016 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1017 Return "Err:Invalid Json!"
1020 Case HttpStatusCode.BadRequest
1021 Return "Err:API Limits?"
1022 Case HttpStatusCode.Unauthorized
1023 Twitter.AccountState = ACCOUNT_STATE.Invalid
1024 Dim errMsg As String = GetErrorMessageJson(content)
1025 If String.IsNullOrEmpty(errMsg) Then
1026 Return My.Resources.Unauthorized
1028 Return "Auth err:" + errMsg
1031 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1035 Public Function GetStatus_Retweeted_Count(ByVal StatusId As Long, ByRef retweeted_count As Integer) As String
1037 If _endingFlag Then Return ""
1039 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1041 Google.GASender.GetInstance().TrackPage("/retweet_count", Me.UserId)
1042 Dim res As HttpStatusCode
1043 Dim content As String = ""
1044 Dim xmlBuf As String = ""
1048 ' 注:dev.twitter.comに記述されているcountパラメータは間違い。100が正しい
1049 For i As Integer = 1 To 100
1052 res = twCon.Statusid_retweeted_by_ids(StatusId, 100, i, content)
1053 Catch ex As Exception
1054 Return "Err:" + ex.Message
1058 Case HttpStatusCode.OK
1060 Dim ids As Int64() = CreateDataFromJson(Of Int64())(content)
1061 retweeted_count += ids.Length
1062 If ids.Length < 100 Then Exit For
1063 Catch ex As SerializationException
1064 retweeted_count = -1
1065 TraceOut(ex.Message + Environment.NewLine + content)
1066 Return "Err:Json Parse Error(DataContractJsonSerializer)"
1067 Catch ex As Exception
1068 retweeted_count = -1
1069 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1070 Return "Err:Invalid Json!"
1072 Case HttpStatusCode.BadRequest
1073 retweeted_count = -1
1074 Return "Err:API Limits?"
1075 Case HttpStatusCode.Unauthorized
1076 retweeted_count = -1
1077 Twitter.AccountState = ACCOUNT_STATE.Invalid
1078 Return My.Resources.Unauthorized
1080 retweeted_count = -1
1081 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1087 Public Function PostFavAdd(ByVal id As Long) As String
1088 If _endingFlag Then Return ""
1090 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1092 Google.GASender.GetInstance().TrackEventWithCategory("post", "favorites", Me.UserId)
1093 Dim res As HttpStatusCode
1094 Dim content As String = ""
1096 res = twCon.CreateFavorites(id, content)
1097 Catch ex As Exception
1098 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
1102 Case HttpStatusCode.OK
1103 Twitter.AccountState = ACCOUNT_STATE.Valid
1104 If Not _restrictFavCheck Then Return ""
1105 Case HttpStatusCode.Unauthorized
1106 Twitter.AccountState = ACCOUNT_STATE.Invalid
1107 Return My.Resources.Unauthorized
1108 Case HttpStatusCode.Forbidden
1109 Dim errMsg As String = GetErrorMessageJson(content)
1110 If String.IsNullOrEmpty(errMsg) Then
1111 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
1113 Return "Err:" + errMsg
1116 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1119 'http://twitter.com/statuses/show/id.xml APIを発行して本文を取得
1121 'Dim content As String = ""
1124 res = twCon.ShowStatuses(id, content)
1125 Catch ex As Exception
1126 Return "Err:" + ex.Message
1130 Case HttpStatusCode.OK
1131 Twitter.AccountState = ACCOUNT_STATE.Valid
1132 Dim status As TwitterDataModel.Status
1134 status = CreateDataFromJson(Of TwitterDataModel.Status)(content)
1135 Catch ex As SerializationException
1136 TraceOut(ex.Message + Environment.NewLine + content)
1137 Return "Err:Json Parse Error(DataContractJsonSerializer)"
1138 Catch ex As Exception
1139 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1140 Return "Err:Invalid Json!"
1142 If status.Favorited Then
1145 Return "NG(Restricted?)"
1147 Case HttpStatusCode.Unauthorized
1148 Twitter.AccountState = ACCOUNT_STATE.Invalid
1149 Return My.Resources.Unauthorized
1150 Case HttpStatusCode.BadRequest
1151 Return "Err:API Limits?"
1153 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1158 Public Function PostFavRemove(ByVal id As Long) As String
1159 If _endingFlag Then Return ""
1161 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1163 Google.GASender.GetInstance().TrackEventWithCategory("post", "destroy_favorites", Me.UserId)
1164 Dim res As HttpStatusCode
1165 Dim content As String = ""
1167 res = twCon.DestroyFavorites(id, content)
1168 Catch ex As Exception
1169 Return "Err:" + ex.Message
1173 Case HttpStatusCode.OK
1174 Twitter.AccountState = ACCOUNT_STATE.Valid
1176 Case HttpStatusCode.Unauthorized
1177 Twitter.AccountState = ACCOUNT_STATE.Invalid
1178 Return My.Resources.Unauthorized
1179 Case HttpStatusCode.Forbidden
1180 Dim errMsg As String = GetErrorMessageJson(content)
1181 If String.IsNullOrEmpty(errMsg) Then
1182 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
1184 Return "Err:" + errMsg
1187 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1191 Public Function PostUpdateProfile(ByVal name As String, ByVal url As String, ByVal location As String, ByVal description As String) As String
1192 If _endingFlag Then Return ""
1194 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1196 Google.GASender.GetInstance().TrackEventWithCategory("post", "update_profile", Me.UserId)
1197 Dim res As HttpStatusCode
1198 Dim content As String = ""
1200 res = twCon.UpdateProfile(name, url, location, description, content)
1201 Catch ex As Exception
1202 Return "Err:" + ex.Message
1206 Case HttpStatusCode.OK
1207 Twitter.AccountState = ACCOUNT_STATE.Valid
1209 Case HttpStatusCode.Unauthorized
1210 Twitter.AccountState = ACCOUNT_STATE.Invalid
1211 Return My.Resources.Unauthorized
1212 Case HttpStatusCode.Forbidden
1213 Dim errMsg As String = GetErrorMessageJson(content)
1214 If String.IsNullOrEmpty(errMsg) Then
1215 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
1217 Return "Err:" + errMsg
1220 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1224 Public Function PostUpdateProfileImage(ByVal filename As String) As String
1225 If _endingFlag Then Return ""
1227 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1229 Google.GASender.GetInstance().TrackEventWithCategory("post", "update_profile_image", Me.UserId)
1230 Dim res As HttpStatusCode
1231 Dim content As String = ""
1233 res = twCon.UpdateProfileImage(New FileInfo(filename), content)
1234 Catch ex As Exception
1235 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
1239 Case HttpStatusCode.OK
1240 Twitter.AccountState = ACCOUNT_STATE.Valid
1242 Case HttpStatusCode.Unauthorized
1243 Twitter.AccountState = ACCOUNT_STATE.Invalid
1244 Return My.Resources.Unauthorized
1245 Case HttpStatusCode.Forbidden
1246 Dim errMsg As String = GetErrorMessageJson(content)
1247 If String.IsNullOrEmpty(errMsg) Then
1248 Return "Err:Forbidden(" + GetCurrentMethod.Name + ")"
1250 Return "Err:" + errMsg
1253 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1257 Public ReadOnly Property Username() As String
1259 Return twCon.AuthenticatedUsername
1263 Public ReadOnly Property UserId As Long
1265 Return twCon.AuthenticatedUserId
1269 Public ReadOnly Property Password() As String
1271 Return twCon.Password
1275 Private Shared _accountState As ACCOUNT_STATE = ACCOUNT_STATE.Valid
1276 Public Shared Property AccountState() As ACCOUNT_STATE
1278 Return _accountState
1280 Set(ByVal value As ACCOUNT_STATE)
1281 _accountState = value
1285 Public WriteOnly Property GetIcon() As Boolean
1286 Set(ByVal value As Boolean)
1291 Public WriteOnly Property TinyUrlResolve() As Boolean
1292 Set(ByVal value As Boolean)
1293 _tinyUrlResolve = value
1297 Public WriteOnly Property RestrictFavCheck() As Boolean
1298 Set(ByVal value As Boolean)
1299 _restrictFavCheck = value
1303 Public WriteOnly Property IconSize() As Integer
1304 Set(ByVal value As Integer)
1310 Public Function GetVersionInfo() As String
1311 Dim content As String = ""
1312 If Not (New HttpVarious).GetData("http://tween.sourceforge.jp/version.txt?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), Nothing, content, GetUserAgentString()) Then
1313 Throw New Exception("GetVersionInfo Failed")
1318 Public Function GetTweenBinary(ByVal strVer As String) As String
1319 Google.GASender.GetInstance().TrackPage("/newversion", Me.UserId)
1322 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/Tween" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1323 Path.Combine(MyCommon.settingPath, "TweenNew.exe")) Then
1324 Return "Err:Download failed"
1327 If Not Directory.Exists(Path.Combine(MyCommon.settingPath, "en")) Then
1328 Directory.CreateDirectory(Path.Combine(MyCommon.settingPath, "en"))
1330 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenResEn" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1331 Path.Combine(Path.Combine(MyCommon.settingPath, "en"), "Tween.resourcesNew.dll")) Then
1332 Return "Err:Download failed"
1334 'その他言語圏のリソース。取得失敗しても継続
1336 Dim curCul As String = ""
1337 If Not Thread.CurrentThread.CurrentUICulture.IsNeutralCulture Then
1338 Dim idx As Integer = Thread.CurrentThread.CurrentUICulture.Name.LastIndexOf("-"c)
1340 curCul = Thread.CurrentThread.CurrentUICulture.Name.Substring(0, idx)
1342 curCul = Thread.CurrentThread.CurrentUICulture.Name
1345 curCul = Thread.CurrentThread.CurrentUICulture.Name
1347 If Not String.IsNullOrEmpty(curCul) AndAlso curCul <> "en" AndAlso curCul <> "ja" Then
1348 If Not Directory.Exists(Path.Combine(MyCommon.settingPath, curCul)) Then
1349 Directory.CreateDirectory(Path.Combine(MyCommon.settingPath, curCul))
1351 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenRes" + curCul + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1352 Path.Combine(Path.Combine(MyCommon.settingPath, curCul), "Tween.resourcesNew.dll")) Then
1353 'Return "Err:Download failed"
1357 Dim curCul2 As String
1358 If Not Thread.CurrentThread.CurrentCulture.IsNeutralCulture Then
1359 Dim idx As Integer = Thread.CurrentThread.CurrentCulture.Name.LastIndexOf("-"c)
1361 curCul2 = Thread.CurrentThread.CurrentCulture.Name.Substring(0, idx)
1363 curCul2 = Thread.CurrentThread.CurrentCulture.Name
1366 curCul2 = Thread.CurrentThread.CurrentCulture.Name
1368 If Not String.IsNullOrEmpty(curCul2) AndAlso curCul2 <> "en" AndAlso curCul2 <> curCul Then
1369 If Not Directory.Exists(Path.Combine(MyCommon.settingPath, curCul2)) Then
1370 Directory.CreateDirectory(Path.Combine(MyCommon.settingPath, curCul2))
1372 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenRes" + curCul2 + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1373 Path.Combine(Path.Combine(MyCommon.settingPath, curCul2), "Tween.resourcesNew.dll")) Then
1374 'Return "Err:Download failed"
1379 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenUp3.gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1380 Path.Combine(MyCommon.settingPath, "TweenUp3.exe")) Then
1381 Return "Err:Download failed"
1384 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenDll" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1385 Path.Combine(MyCommon.settingPath, "TweenNew.XmlSerializers.dll")) Then
1386 Return "Err:Download failed"
1389 Catch ex As Exception
1390 Return "Err:Download failed"
1395 Public Property DetailIcon() As IDictionary(Of String, Image)
1399 Set(ByVal value As IDictionary(Of String, Image))
1404 Public Property ReadOwnPost() As Boolean
1408 Set(ByVal value As Boolean)
1409 _readOwnPost = value
1413 Public ReadOnly Property FollowersCount() As Integer
1415 Return _followersCount
1419 Public ReadOnly Property FriendsCount() As Integer
1421 Return _friendsCount
1425 Public ReadOnly Property StatusesCount() As Integer
1427 Return _statusesCount
1431 Public ReadOnly Property Location() As String
1437 Public ReadOnly Property Bio() As String
1443 Public WriteOnly Property UseSsl() As Boolean
1444 Set(ByVal value As Boolean)
1445 HttpTwitter.UseSsl = value
1447 _protocol = "https://"
1449 _protocol = "http://"
1454 Public Function GetTimelineApi(ByVal read As Boolean, _
1455 ByVal gType As WORKERTYPE, _
1456 ByVal more As Boolean, _
1457 ByVal startup As Boolean) As String
1459 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1461 If _endingFlag Then Return ""
1463 Dim res As HttpStatusCode
1464 Dim content As String = ""
1465 Dim count As Integer = AppendSettingDialog.Instance.CountApi
1466 If gType = WORKERTYPE.Reply Then count = AppendSettingDialog.Instance.CountApiReply()
1467 If AppendSettingDialog.Instance.UseAdditionalCount Then
1468 If more AndAlso AppendSettingDialog.Instance.MoreCountApi <> 0 Then
1469 count = AppendSettingDialog.Instance.MoreCountApi
1470 ElseIf startup AndAlso AppendSettingDialog.Instance.FirstCountApi <> 0 AndAlso gType = WORKERTYPE.Timeline Then
1471 count = AppendSettingDialog.Instance.FirstCountApi
1475 If gType = WORKERTYPE.Timeline Then
1477 res = twCon.HomeTimeline(count, Me.minHomeTimeline, 0, content)
1479 res = twCon.HomeTimeline(count, 0, 0, content)
1483 res = twCon.Mentions(count, Me.minMentions, 0, content)
1485 res = twCon.Mentions(count, 0, 0, content)
1488 Catch ex As Exception
1489 Return "Err:" + ex.Message
1492 Case HttpStatusCode.OK
1493 Twitter.AccountState = ACCOUNT_STATE.Valid
1494 Case HttpStatusCode.Unauthorized
1495 Twitter.AccountState = ACCOUNT_STATE.Invalid
1496 Return My.Resources.Unauthorized
1497 Case HttpStatusCode.BadRequest
1498 Return "Err:API Limits?"
1500 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1503 If gType = WORKERTYPE.Timeline Then
1504 Return CreatePostsFromJson(content, gType, Nothing, read, count, Me.minHomeTimeline)
1506 Return CreatePostsFromJson(content, gType, Nothing, read, count, Me.minMentions)
1510 Public Function GetUserTimelineApi(ByVal read As Boolean,
1511 ByVal count As Integer,
1512 ByVal userName As String,
1513 ByVal tab As TabClass,
1514 ByVal more As Boolean) As String
1516 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1518 If _endingFlag Then Return ""
1520 Dim res As HttpStatusCode
1521 Dim content As String = ""
1523 If count = 0 Then count = 20
1525 If String.IsNullOrEmpty(userName) Then
1526 Dim target As String = tab.User
1527 If target Is Nothing Then Return ""
1528 res = twCon.UserTimeline(0, target, count, 0, 0, content)
1531 res = twCon.UserTimeline(0, userName, count, tab.OldestId, 0, content)
1533 res = twCon.UserTimeline(0, userName, count, 0, 0, content)
1536 Catch ex As Exception
1537 Return "Err:" + ex.Message
1540 Case HttpStatusCode.OK
1541 Twitter.AccountState = ACCOUNT_STATE.Valid
1542 Case HttpStatusCode.Unauthorized
1543 Twitter.AccountState = ACCOUNT_STATE.Valid
1544 Return "Err:@" + userName + "'s Tweets are protected."
1545 Case HttpStatusCode.BadRequest
1546 Return "Err:API Limits?"
1548 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1551 Dim items As List(Of TwitterDataModel.Status)
1553 items = CreateDataFromJson(Of List(Of TwitterDataModel.Status))(content)
1554 Catch ex As SerializationException
1555 TraceOut(ex.Message + Environment.NewLine + content)
1556 Return "Json Parse Error(DataContractJsonSerializer)"
1557 Catch ex As Exception
1558 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1559 Return "Invalid Json!"
1562 For Each status As TwitterDataModel.Status In items
1563 Dim item As PostClass = CreatePostsFromStatusData(status)
1564 If item Is Nothing Then Continue For
1565 If item.StatusId < tab.OldestId Then tab.OldestId = item.StatusId
1567 If item.IsMe AndAlso Not read AndAlso _readOwnPost Then item.IsRead = True
1568 If tab IsNot Nothing Then item.RelTabName = tab.TabName
1569 '非同期アイコン取得&StatusDictionaryに追加
1570 TabInformations.GetInstance.AddPost(item)
1576 Public Function GetStatusApi(ByVal read As Boolean,
1578 ByRef post As PostClass) As String
1579 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1581 If _endingFlag Then Return ""
1583 Google.GASender.GetInstance().TrackPage("/showstatus", Me.UserId)
1584 Dim res As HttpStatusCode
1585 Dim content As String = ""
1588 res = twCon.ShowStatuses(id, content)
1589 Catch ex As Exception
1590 Return "Err:" + ex.Message
1593 Case HttpStatusCode.OK
1594 Twitter.AccountState = ACCOUNT_STATE.Valid
1595 Case HttpStatusCode.Unauthorized
1596 Twitter.AccountState = ACCOUNT_STATE.Invalid
1597 Return My.Resources.Unauthorized
1598 Case HttpStatusCode.BadRequest
1599 Return "Err:API Limits?"
1600 Case HttpStatusCode.Forbidden
1601 Return "Err:Protected user's tweet"
1603 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1606 Dim status As TwitterDataModel.Status
1608 status = CreateDataFromJson(Of TwitterDataModel.Status)(content)
1609 Catch ex As SerializationException
1610 TraceOut(ex.Message + Environment.NewLine + content)
1611 Return "Json Parse Error(DataContractJsonSerializer)"
1612 Catch ex As Exception
1613 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1614 Return "Invalid Json!"
1617 Dim item As PostClass = CreatePostsFromStatusData(status)
1618 If item Is Nothing Then Return "Err:Can't create post"
1620 If item.IsMe AndAlso Not read AndAlso _readOwnPost Then item.IsRead = True
1626 Public Function GetStatusApi(ByVal read As Boolean,
1628 ByVal tab As TabClass) As String
1629 Dim post As PostClass = Nothing
1630 Dim r As String = Me.GetStatusApi(read, id, post)
1633 If tab IsNot Nothing Then post.RelTabName = tab.TabName
1634 '非同期アイコン取得&StatusDictionaryに追加
1635 TabInformations.GetInstance.AddPost(post)
1641 Private Function CreatePostsFromStatusData(ByVal status As TwitterDataModel.Status) As PostClass
1642 Dim post As New PostClass
1643 Dim entities As TwitterDataModel.Entities
1645 post.StatusId = status.Id
1646 If status.RetweetedStatus IsNot Nothing Then
1647 Dim retweeted As TwitterDataModel.RetweetedStatus = status.RetweetedStatus
1649 post.CreatedAt = DateTimeParse(retweeted.CreatedAt)
1652 post.RetweetedId = retweeted.Id
1654 post.TextFromApi = retweeted.Text
1655 entities = retweeted.Entities
1656 'Source取得(htmlの場合は、中身を取り出し)
1657 post.Source = retweeted.Source
1659 Long.TryParse(retweeted.InReplyToStatusId, post.InReplyToStatusId)
1660 post.InReplyToUser = retweeted.InReplyToScreenName
1661 Long.TryParse(status.InReplyToUserId, post.InReplyToUserId)
1662 post.IsFav = TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.RetweetedId)
1663 If retweeted.Geo IsNot Nothing Then post.PostGeo = New PostClass.StatusGeo() With {.Lat = retweeted.Geo.Coordinates(0), .Lng = retweeted.Geo.Coordinates(1)}
1666 Dim user As TwitterDataModel.User = retweeted.User
1668 If user.ScreenName Is Nothing OrElse status.User.ScreenName Is Nothing Then Return Nothing
1670 post.UserId = user.Id
1671 post.ScreenName = user.ScreenName
1672 post.Nickname = user.Name.Trim()
1673 post.ImageUrl = user.ProfileImageUrl
1674 post.IsProtect = user.Protected
1677 post.RetweetedBy = status.User.ScreenName
1678 post.RetweetedByUserId = status.User.Id
1679 post.IsMe = post.RetweetedBy.ToLower.Equals(_uname)
1681 post.CreatedAt = DateTimeParse(status.CreatedAt)
1683 post.TextFromApi = status.Text
1684 entities = status.Entities
1685 'Source取得(htmlの場合は、中身を取り出し)
1686 post.Source = status.Source
1687 Long.TryParse(status.InReplyToStatusId, post.InReplyToStatusId)
1688 post.InReplyToUser = status.InReplyToScreenName
1689 Long.TryParse(status.InReplyToUserId, post.InReplyToUserId)
1691 post.IsFav = status.Favorited
1692 If status.Geo IsNot Nothing Then post.PostGeo = New PostClass.StatusGeo() With {.Lat = status.Geo.Coordinates(0), .Lng = status.Geo.Coordinates(1)}
1695 Dim user As TwitterDataModel.User = status.User
1697 If user.ScreenName Is Nothing Then Return Nothing
1699 post.UserId = user.Id
1700 post.ScreenName = user.ScreenName
1701 post.Nickname = user.Name.Trim()
1702 post.ImageUrl = user.ProfileImageUrl
1703 post.IsProtect = user.Protected
1704 post.IsMe = post.ScreenName.ToLower.Equals(_uname)
1707 post.Text = CreateHtmlAnchor(post.TextFromApi, post.ReplyToList, entities, post.Media)
1708 post.TextFromApi = Me.ReplaceTextFromApi(post.TextFromApi, entities)
1709 post.TextFromApi = HttpUtility.HtmlDecode(post.TextFromApi)
1710 post.TextFromApi = post.TextFromApi.Replace("<3", "♡")
1715 post.IsReply = post.ReplyToList.Contains(_uname)
1716 post.IsExcludeReply = False
1721 If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.UserId)
1728 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
1729 Dim items As List(Of TwitterDataModel.Status)
1731 items = CreateDataFromJson(Of List(Of TwitterDataModel.Status))(content)
1732 Catch ex As SerializationException
1733 TraceOut(ex.Message + Environment.NewLine + content)
1734 Return "Json Parse Error(DataContractJsonSerializer)"
1735 Catch ex As Exception
1736 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1737 Return "Invalid Json!"
1740 For Each status As TwitterDataModel.Status In items
1741 Dim post As PostClass = Nothing
1742 post = CreatePostsFromStatusData(status)
1743 If post Is Nothing Then Continue For
1745 If minimumId > post.StatusId Then minimumId = post.StatusId
1748 If tab Is Nothing Then
1749 If TabInformations.GetInstance.ContainsKey(post.StatusId) Then Continue For
1751 If TabInformations.GetInstance.ContainsKey(post.StatusId, tab.TabName) Then Continue For
1756 If post.RetweetedId > 0 AndAlso Me.noRTId.Contains(post.RetweetedByUserId) Then Continue For
1759 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
1761 If tab IsNot Nothing Then post.RelTabName = tab.TabName
1762 '非同期アイコン取得&StatusDictionaryに追加
1763 TabInformations.GetInstance.AddPost(post)
1769 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
1770 Dim items As TwitterDataModel.SearchResult
1772 items = CreateDataFromJson(Of TwitterDataModel.SearchResult)(content)
1773 Catch ex As SerializationException
1774 TraceOut(ex.Message + Environment.NewLine + content)
1775 Return "Json Parse Error(DataContractJsonSerializer)"
1776 Catch ex As Exception
1777 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1778 Return "Invalid Json!"
1781 nextPageQuery = items.NextPage
1783 For Each status As TwitterDataModel.Status In items.Statuses
1784 Dim post As PostClass = Nothing
1785 post = CreatePostsFromStatusData(status)
1786 If post Is Nothing Then Continue For
1788 If minimumId > post.StatusId Then minimumId = post.StatusId
1791 If tab Is Nothing Then
1792 If TabInformations.GetInstance.ContainsKey(post.StatusId) Then Continue For
1794 If TabInformations.GetInstance.ContainsKey(post.StatusId, tab.TabName) Then Continue For
1799 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
1801 If tab IsNot Nothing Then post.RelTabName = tab.TabName
1802 '非同期アイコン取得&StatusDictionaryに追加
1803 TabInformations.GetInstance.AddPost(post)
1806 Return If(String.IsNullOrEmpty(items.ErrMsg), "", "Err:" + items.ErrMsg)
1809 Public Overloads Function GetListStatus(ByVal read As Boolean, _
1810 ByVal tab As TabClass, _
1811 ByVal more As Boolean, _
1812 ByVal startup As Boolean) As String
1814 If _endingFlag Then Return ""
1816 Dim res As HttpStatusCode
1817 Dim content As String = ""
1818 Dim page As Integer = 0
1819 Dim count As Integer
1820 If AppendSettingDialog.Instance.UseAdditionalCount Then
1821 count = AppendSettingDialog.Instance.ListCountApi
1823 If more AndAlso AppendSettingDialog.Instance.MoreCountApi <> 0 Then
1824 count = AppendSettingDialog.Instance.MoreCountApi
1825 ElseIf startup AndAlso AppendSettingDialog.Instance.FirstCountApi <> 0 Then
1826 count = AppendSettingDialog.Instance.FirstCountApi
1828 count = AppendSettingDialog.Instance.CountApi
1832 count = AppendSettingDialog.Instance.CountApi
1836 res = twCon.GetListsStatuses(tab.ListInfo.UserId, tab.ListInfo.Id, count, tab.OldestId, 0, AppendSettingDialog.Instance.IsListStatusesIncludeRts, content)
1838 res = twCon.GetListsStatuses(tab.ListInfo.UserId, tab.ListInfo.Id, count, 0, 0, AppendSettingDialog.Instance.IsListStatusesIncludeRts, content)
1840 Catch ex As Exception
1841 Return "Err:" + ex.Message
1844 Case HttpStatusCode.OK
1845 Twitter.AccountState = ACCOUNT_STATE.Valid
1846 Case HttpStatusCode.Unauthorized
1847 Twitter.AccountState = ACCOUNT_STATE.Invalid
1848 Return My.Resources.Unauthorized
1849 Case HttpStatusCode.BadRequest
1850 Return "Err:API Limits?"
1852 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1855 Return CreatePostsFromJson(content, WORKERTYPE.List, tab, read, count, tab.OldestId)
1859 Private Function CheckReplyToPost(ByVal relPosts As List(Of PostClass)) As PostClass
1860 Dim tmpPost As PostClass = relPosts(0)
1861 Dim lastPost As PostClass = Nothing
1862 Do While tmpPost IsNot Nothing
1863 If tmpPost.InReplyToStatusId = 0 Then Return Nothing
1865 Dim replyToPost = From p In relPosts
1866 Where p.StatusId = tmpPost.InReplyToStatusId
1868 tmpPost = replyToPost.FirstOrDefault()
1873 Public Function GetRelatedResult(ByVal read As Boolean, ByVal tab As TabClass) As String
1874 Google.GASender.GetInstance().TrackPage("/related_statuses", Me.UserId)
1875 Dim rslt As String = ""
1876 Dim relPosts As New List(Of PostClass)
1877 If tab.RelationTargetPost.TextFromApi.Contains("@") AndAlso tab.RelationTargetPost.InReplyToStatusId = 0 Then
1879 Dim p As PostClass = TabInformations.GetInstance.Item(tab.RelationTargetPost.StatusId)
1880 If p IsNot Nothing AndAlso p.InReplyToStatusId > 0 Then
1881 tab.RelationTargetPost = p
1883 rslt = Me.GetStatusApi(read, tab.RelationTargetPost.StatusId, p)
1884 If Not String.IsNullOrEmpty(rslt) Then Return rslt
1885 tab.RelationTargetPost = p
1888 relPosts.Add(tab.RelationTargetPost.Copy)
1889 Dim tmpPost As PostClass = relPosts(0)
1891 rslt = Me.GetRelatedResultsApi(read, tmpPost, tab, relPosts)
1892 If Not String.IsNullOrEmpty(rslt) Then Exit Do
1893 tmpPost = CheckReplyToPost(relPosts)
1894 Loop While tmpPost IsNot Nothing
1896 relPosts.ForEach(Sub(p) TabInformations.GetInstance.AddPost(p))
1900 Private Function GetRelatedResultsApi(ByVal read As Boolean,
1901 ByVal post As PostClass,
1902 ByVal tab As TabClass,
1903 ByVal relatedPosts As List(Of PostClass)) As String
1905 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1907 If _endingFlag Then Return ""
1909 Dim res As HttpStatusCode
1910 Dim content As String = ""
1912 If post.RetweetedId > 0 Then
1913 res = twCon.GetRelatedResults(post.RetweetedId, content)
1915 res = twCon.GetRelatedResults(post.StatusId, content)
1917 Catch ex As Exception
1918 Return "Err:" + ex.Message
1921 Case HttpStatusCode.OK
1922 Twitter.AccountState = ACCOUNT_STATE.Valid
1923 Case HttpStatusCode.Unauthorized
1924 Twitter.AccountState = ACCOUNT_STATE.Invalid
1925 Return My.Resources.Unauthorized
1926 Case HttpStatusCode.BadRequest
1927 Return "Err:API Limits?"
1929 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1932 Dim items As List(Of TwitterDataModel.RelatedResult)
1934 items = CreateDataFromJson(Of List(Of TwitterDataModel.RelatedResult))(content)
1935 Catch ex As SerializationException
1936 TraceOut(ex.Message + Environment.NewLine + content)
1937 Return "Json Parse Error(DataContractJsonSerializer)"
1938 Catch ex As Exception
1939 TraceOut(ex, GetCurrentMethod.Name & " " & content)
1940 Return "Invalid Json!"
1943 Dim targetItem As PostClass = post
1944 If targetItem Is Nothing Then
1947 targetItem = targetItem.Copy()
1949 targetItem.RelTabName = tab.TabName
1950 TabInformations.GetInstance.AddPost(targetItem)
1952 Dim replyToItem As PostClass = Nothing
1953 Dim replyToUserName As String = targetItem.InReplyToUser
1954 If targetItem.InReplyToStatusId > 0 AndAlso TabInformations.GetInstance.Item(targetItem.InReplyToStatusId) IsNot Nothing Then
1955 replyToItem = TabInformations.GetInstance.Item(targetItem.InReplyToStatusId).Copy
1956 replyToItem.IsRead = read
1957 If replyToItem.IsMe AndAlso Not read AndAlso _readOwnPost Then replyToItem.IsRead = True
1958 replyToItem.RelTabName = tab.TabName
1961 Dim replyAdded As Boolean = False
1962 For Each relatedData As TwitterDataModel.RelatedResult In items
1963 For Each result As TwitterDataModel.RelatedTweet In relatedData.Results
1964 Dim item As PostClass = CreatePostsFromStatusData(result.Status)
1965 If item Is Nothing Then Continue For
1966 If targetItem.InReplyToStatusId = item.StatusId Then
1967 replyToItem = Nothing
1971 If item.IsMe AndAlso Not read AndAlso _readOwnPost Then item.IsRead = True
1972 If tab IsNot Nothing Then item.RelTabName = tab.TabName
1973 '非同期アイコン取得&StatusDictionaryに追加
1974 relatedPosts.Add(item)
1977 If replyToItem IsNot Nothing Then
1978 relatedPosts.Add(replyToItem)
1979 ElseIf targetItem.InReplyToStatusId > 0 AndAlso Not replyAdded Then
1980 Dim p As PostClass = Nothing
1981 Dim rslt As String = ""
1982 rslt = GetStatusApi(read, targetItem.InReplyToStatusId, p)
1983 If String.IsNullOrEmpty(rslt) Then
1985 p.RelTabName = tab.TabName
1991 '発言者・返信先ユーザーの直近10発言取得
1992 'Dim rslt As String = Me.GetUserTimelineApi(read, 10, "", tab)
1993 'If Not String.IsNullOrEmpty(rslt) Then Return rslt
1994 'If Not String.IsNullOrEmpty(replyToUserName) Then
1995 ' rslt = Me.GetUserTimelineApi(read, 10, replyToUserName, tab)
2000 'MRTとかに対応のためツイート内にあるツイートを指すURLを取り込む
2001 Dim ma As MatchCollection = Regex.Matches(tab.RelationTargetPost.Text, "href=""https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)(/status(es)?/(?<StatusId>[0-9]+))""")
2002 For Each _match As Match In ma
2003 Dim _statusId As Int64
2004 If Int64.TryParse(_match.Groups("StatusId").Value, _statusId) Then
2005 Dim p As PostClass = Nothing
2006 Dim _post As PostClass = TabInformations.GetInstance.Item(_statusId)
2007 If _post Is Nothing Then
2008 Dim rslt = Me.GetStatusApi(read, _statusId, p)
2012 If p IsNot Nothing Then
2014 p.RelTabName = tab.TabName
2022 Public Function GetSearch(ByVal read As Boolean, _
2023 ByVal tab As TabClass, _
2024 ByVal more As Boolean) As String
2026 If _endingFlag Then Return ""
2028 Dim res As HttpStatusCode
2029 Dim content As String = ""
2030 Dim page As Integer = 0
2031 Dim sinceId As Long = 0
2032 Dim count As Integer = 100
2033 If AppendSettingDialog.Instance.UseAdditionalCount AndAlso
2034 AppendSettingDialog.Instance.SearchCountApi <> 0 Then
2035 count = AppendSettingDialog.Instance.SearchCountApi
2037 count = AppendSettingDialog.Instance.CountApi
2040 page = tab.GetSearchPage(count)
2042 sinceId = tab.SinceId
2046 ' TODO:一時的に40>100件に 件数変更UI作成の必要あり
2047 res = twCon.Search(tab.SearchWords, tab.SearchLang, count, page, sinceId, content)
2048 Catch ex As Exception
2049 Return "Err:" + ex.Message
2052 Case HttpStatusCode.BadRequest
2053 Return "Invalid query"
2054 Case HttpStatusCode.NotFound
2055 Return "Invalid query"
2056 Case HttpStatusCode.PaymentRequired 'API Documentには420と書いてあるが、該当コードがないので402にしてある
2057 Return "Search API Limit?"
2058 Case HttpStatusCode.OK
2060 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
2063 If Not TabInformations.GetInstance.ContainsTab(tab) Then Return ""
2064 content = Regex.Replace(content, "[\x00-\x1f-[\x0a\x0d]]+", " ")
2065 Dim xdoc As New XmlDocument
2067 xdoc.LoadXml(content)
2068 Catch ex As Exception
2069 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2070 Return "Invalid ATOM!"
2072 Dim nsmgr As New XmlNamespaceManager(xdoc.NameTable)
2073 nsmgr.AddNamespace("search", "http://www.w3.org/2005/Atom")
2074 nsmgr.AddNamespace("twitter", "http://api.twitter.com/")
2075 nsmgr.AddNamespace("georss", "http://www.georss.org/georss")
2076 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/search:feed/search:entry", nsmgr)
2077 Dim xentry As XmlElement = CType(xentryNode, XmlElement)
2078 Dim post As New PostClass
2080 post.StatusId = Long.Parse(xentry.Item("id").InnerText.Split(":"c)(2))
2081 If TabInformations.GetInstance.ContainsKey(post.StatusId, tab.TabName) Then Continue For
2082 post.CreatedAt = DateTime.Parse(xentry.Item("published").InnerText)
2084 post.TextFromApi = xentry.Item("title").InnerText
2085 'Source取得(htmlの場合は、中身を取り出し)
2086 post.Source = xentry.Item("twitter:source").InnerText
2087 post.InReplyToStatusId = 0
2088 post.InReplyToUser = ""
2089 post.InReplyToUserId = 0
2092 ' Geoが勝手に付加されるバグがいっこうに修正されないので暫定的にGeo情報を無視する
2093 If xentry.Item("twitter:geo").HasChildNodes Then
2094 Dim pnt As String() = CType(xentry.SelectSingleNode("twitter:geo/georss:point", nsmgr), XmlElement).InnerText.Split(" "c)
2095 post.PostGeo = New PostClass.StatusGeo With {.Lat = Double.Parse(pnt(0)), .Lng = Double.Parse(pnt(1))}
2099 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./search:author", nsmgr), XmlElement)
2101 post.ScreenName = xUentry.Item("name").InnerText.Split(" "c)(0).Trim
2102 post.Nickname = xUentry.Item("name").InnerText.Substring(post.ScreenName.Length).Trim
2103 If post.Nickname.Length > 2 Then
2104 post.Nickname = post.Nickname.Substring(1, post.Nickname.Length - 2)
2106 post.Nickname = post.ScreenName
2108 post.ImageUrl = CType(xentry.SelectSingleNode("./search:link[@type='image/png']", nsmgr), XmlElement).GetAttribute("href")
2109 post.IsProtect = False
2110 post.IsMe = post.ScreenName.ToLower.Equals(_uname)
2113 post.Text = CreateHtmlAnchor(HttpUtility.HtmlEncode(post.TextFromApi), post.ReplyToList, post.Media)
2114 post.TextFromApi = HttpUtility.HtmlDecode(post.TextFromApi)
2119 post.IsReply = post.ReplyToList.Contains(_uname)
2120 post.IsExcludeReply = False
2123 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
2125 post.RelTabName = tab.TabName
2126 If Not more AndAlso post.StatusId > tab.SinceId Then tab.SinceId = post.StatusId
2127 Catch ex As Exception
2128 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2132 'Me._dIcon.Add(post.ImageUrl, Nothing)
2133 TabInformations.GetInstance.AddPost(post)
2138 '' 遡るための情報max_idやnext_pageの情報を保持する
2141 Dim xNode As XmlNode = xdoc.DocumentElement.SelectSingleNode("/search:feed/twitter:warning", nsmgr)
2143 If xNode IsNot Nothing Then
2144 Return "Warn:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
2151 Public Function GetPhoenixSearch(ByVal read As Boolean, _
2152 ByVal tab As TabClass, _
2153 ByVal more As Boolean) As String
2155 If _endingFlag Then Return ""
2157 Dim res As HttpStatusCode
2158 Dim content As String = ""
2159 Dim page As Integer = 0
2160 Dim sinceId As Long = 0
2161 Dim count As Integer = 100
2162 Dim querystr As String = ""
2163 If AppendSettingDialog.Instance.UseAdditionalCount AndAlso
2164 AppendSettingDialog.Instance.SearchCountApi <> 0 Then
2165 count = AppendSettingDialog.Instance.SearchCountApi
2168 page = tab.GetSearchPage(count)
2169 If Not String.IsNullOrEmpty(tab.NextPageQuery) Then
2170 querystr = tab.NextPageQuery
2173 sinceId = tab.SinceId
2177 If String.IsNullOrEmpty(querystr) Then
2178 res = twCon.PhoenixSearch(tab.SearchWords, tab.SearchLang, count, page, sinceId, content)
2180 res = twCon.PhoenixSearch(querystr, content)
2182 Catch ex As Exception
2183 Return "Err:" + ex.Message
2186 Case HttpStatusCode.BadRequest
2187 Return "Invalid query"
2188 Case HttpStatusCode.NotFound
2189 Return "Invalid query"
2190 Case HttpStatusCode.PaymentRequired 'API Documentには420と書いてあるが、該当コードがないので402にしてある
2191 Return "Search API Limit?"
2192 Case HttpStatusCode.OK
2194 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
2197 If Not TabInformations.GetInstance.ContainsTab(tab) Then Return ""
2200 '' 遡るための情報max_idやnext_pageの情報を保持する
2202 Return CreatePostsFromPhoenixSearch(content, WORKERTYPE.PublicSearch, tab, read, count, tab.OldestId, tab.NextPageQuery)
2205 Private Function CreateDirectMessagesFromJson(ByVal content As String, ByVal gType As WORKERTYPE, ByVal read As Boolean) As String
2206 Dim item As List(Of TwitterDataModel.Directmessage)
2208 If gType = WORKERTYPE.UserStream Then
2209 Dim itm As List(Of TwitterDataModel.DirectmessageEvent) = CreateDataFromJson(Of List(Of TwitterDataModel.DirectmessageEvent))(content)
2210 item = New List(Of TwitterDataModel.Directmessage)
2211 For Each dat As TwitterDataModel.DirectmessageEvent In itm
2212 item.Add(dat.Directmessage)
2215 item = CreateDataFromJson(Of List(Of TwitterDataModel.Directmessage))(content)
2217 Catch ex As SerializationException
2218 TraceOut(ex.Message + Environment.NewLine + content)
2219 Return "Json Parse Error(DataContractJsonSerializer)"
2220 Catch ex As Exception
2221 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2222 Return "Invalid Json!"
2225 For Each message As TwitterDataModel.Directmessage In item
2226 Dim post As New PostClass
2228 post.StatusId = message.Id
2229 If gType <> WORKERTYPE.UserStream Then
2230 If gType = WORKERTYPE.DirectMessegeRcv Then
2231 If minDirectmessage > post.StatusId Then minDirectmessage = post.StatusId
2233 If minDirectmessageSent > post.StatusId Then minDirectmessageSent = post.StatusId
2239 If TabInformations.GetInstance.GetTabByType(TabUsageType.DirectMessage).Contains(post.StatusId) Then Continue For
2243 post.CreatedAt = DateTimeParse(message.CreatedAt)
2245 post.TextFromApi = message.Text
2247 post.Text = CreateHtmlAnchor(post.TextFromApi, post.ReplyToList, post.Media)
2248 post.TextFromApi = HttpUtility.HtmlDecode(post.TextFromApi)
2249 post.TextFromApi = post.TextFromApi.Replace("<3", "♡")
2253 Dim user As TwitterDataModel.User
2254 If gType = WORKERTYPE.UserStream Then
2255 If twCon.AuthenticatedUsername.Equals(message.Recipient.ScreenName, StringComparison.CurrentCultureIgnoreCase) Then
2256 user = message.Sender
2260 user = message.Recipient
2265 If gType = WORKERTYPE.DirectMessegeRcv Then
2266 user = message.Sender
2270 user = message.Recipient
2276 post.UserId = user.Id
2277 post.ScreenName = user.ScreenName
2278 post.Nickname = user.Name.Trim()
2279 post.ImageUrl = user.ProfileImageUrl
2280 post.IsProtect = user.Protected
2281 Catch ex As Exception
2282 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2283 MessageBox.Show("Parse Error(CreateDirectMessagesFromJson)")
2288 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
2289 post.IsReply = False
2290 post.IsExcludeReply = False
2293 TabInformations.GetInstance.AddPost(post)
2300 Public Function GetDirectMessageApi(ByVal read As Boolean, _
2301 ByVal gType As WORKERTYPE, _
2302 ByVal more As Boolean) As String
2303 If _endingFlag Then Return ""
2305 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2306 If Not TwitterApiInfo.IsDirectMessagePermission Then Return "Auth Err:try to re-authorization."
2308 Dim res As HttpStatusCode
2309 Dim content As String = ""
2312 If gType = WORKERTYPE.DirectMessegeRcv Then
2314 res = twCon.DirectMessages(20, minDirectmessage, 0, content)
2316 res = twCon.DirectMessages(20, 0, 0, content)
2320 res = twCon.DirectMessagesSent(20, minDirectmessageSent, 0, content)
2322 res = twCon.DirectMessagesSent(20, 0, 0, content)
2325 Catch ex As Exception
2326 Return "Err:" + ex.Message
2330 Case HttpStatusCode.OK
2331 Twitter.AccountState = ACCOUNT_STATE.Valid
2332 Case HttpStatusCode.Unauthorized
2333 Twitter.AccountState = ACCOUNT_STATE.Invalid
2334 Return My.Resources.Unauthorized
2335 Case HttpStatusCode.BadRequest
2336 Return "Err:API Limits?"
2338 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2341 Return CreateDirectMessagesFromJson(content, gType, read)
2344 Public Function GetFavoritesApi(ByVal read As Boolean, _
2345 ByVal gType As WORKERTYPE) As String
2347 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2349 If _endingFlag Then Return ""
2351 Dim res As HttpStatusCode
2352 Dim content As String = ""
2353 Dim count As Integer = AppendSettingDialog.Instance.CountApi
2354 If AppendSettingDialog.Instance.UseAdditionalCount AndAlso
2355 AppendSettingDialog.Instance.FavoritesCountApi <> 0 Then
2356 count = AppendSettingDialog.Instance.FavoritesCountApi
2359 res = twCon.Favorites(count, content)
2360 Catch ex As Exception
2361 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2365 Case HttpStatusCode.OK
2366 Twitter.AccountState = ACCOUNT_STATE.Valid
2367 Case HttpStatusCode.Unauthorized
2368 Twitter.AccountState = ACCOUNT_STATE.Invalid
2369 Return My.Resources.Unauthorized
2370 Case HttpStatusCode.BadRequest
2371 Return "Err:API Limits?"
2373 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2376 Dim serializer As New DataContractJsonSerializer(GetType(List(Of TwitterDataModel.Status)))
2377 Dim item As List(Of TwitterDataModel.Status)
2380 item = CreateDataFromJson(Of List(Of TwitterDataModel.Status))(content)
2381 Catch ex As SerializationException
2382 TraceOut(ex.Message + Environment.NewLine + content)
2383 Return "Json Parse Error(DataContractJsonSerializer)"
2384 Catch ex As Exception
2385 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2386 Return "Invalid Json!"
2389 For Each status As TwitterDataModel.Status In item
2390 Dim post As New PostClass
2391 Dim entities As TwitterDataModel.Entities
2394 post.StatusId = status.Id
2397 If TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.StatusId) Then Continue For
2400 If status.RetweetedStatus IsNot Nothing Then
2401 Dim retweeted As TwitterDataModel.RetweetedStatus = status.RetweetedStatus
2402 post.CreatedAt = DateTimeParse(retweeted.CreatedAt)
2405 post.RetweetedId = post.StatusId
2407 post.TextFromApi = retweeted.Text
2408 entities = retweeted.Entities
2409 'Source取得(htmlの場合は、中身を取り出し)
2410 post.Source = retweeted.Source
2412 Long.TryParse(retweeted.InReplyToStatusId, post.InReplyToStatusId)
2413 post.InReplyToUser = retweeted.InReplyToScreenName
2414 Long.TryParse(retweeted.InReplyToUserId, post.InReplyToUserId)
2415 post.IsFav = retweeted.Favorited
2418 Dim user As TwitterDataModel.User = retweeted.User
2419 post.UserId = user.Id
2420 post.ScreenName = user.ScreenName
2421 post.Nickname = user.Name.Trim()
2422 post.ImageUrl = user.ProfileImageUrl
2423 post.IsProtect = user.Protected
2426 post.RetweetedBy = status.User.ScreenName
2427 post.IsMe = post.RetweetedBy.ToLower.Equals(_uname)
2429 post.CreatedAt = DateTimeParse(status.CreatedAt)
2432 post.TextFromApi = status.Text
2433 entities = status.Entities
2434 'Source取得(htmlの場合は、中身を取り出し)
2435 post.Source = status.Source
2436 Long.TryParse(status.InReplyToStatusId, post.InReplyToStatusId)
2437 post.InReplyToUser = status.InReplyToScreenName
2438 Long.TryParse(status.InReplyToUserId, post.InReplyToUserId)
2440 post.IsFav = status.Favorited
2443 Dim user As TwitterDataModel.User = status.User
2444 post.UserId = user.Id
2445 post.ScreenName = user.ScreenName
2446 post.Nickname = user.Name.Trim()
2447 post.ImageUrl = user.ProfileImageUrl
2448 post.IsProtect = user.Protected
2449 post.IsMe = post.ScreenName.ToLower.Equals(_uname)
2452 post.Text = CreateHtmlAnchor(post.TextFromApi, post.ReplyToList, entities, post.Media)
2453 post.TextFromApi = Me.ReplaceTextFromApi(post.TextFromApi, entities)
2454 post.TextFromApi = HttpUtility.HtmlDecode(post.TextFromApi)
2455 post.TextFromApi = post.TextFromApi.Replace("<3", "♡")
2460 post.IsReply = post.ReplyToList.Contains(_uname)
2461 post.IsExcludeReply = False
2466 If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.UserId)
2470 Catch ex As Exception
2471 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2475 TabInformations.GetInstance.AddPost(post)
2482 Private Function ReplaceTextFromApi(ByVal text As String, ByVal entities As TwitterDataModel.Entities) As String
2483 If entities IsNot Nothing Then
2484 If entities.Urls IsNot Nothing Then
2485 For Each m In entities.Urls
2486 If Not String.IsNullOrEmpty(m.DisplayUrl) Then text = text.Replace(m.Url, m.DisplayUrl)
2489 If entities.Media IsNot Nothing Then
2490 For Each m In entities.Media
2491 If Not String.IsNullOrEmpty(m.DisplayUrl) Then text = text.Replace(m.Url, m.DisplayUrl)
2498 Public Function GetFollowersApi() As String
2499 If _endingFlag Then Return ""
2500 Dim cursor As Long = -1
2501 Dim tmpFollower As New List(Of Long)(followerId)
2505 Dim ret As String = FollowerApi(cursor)
2506 If Not String.IsNullOrEmpty(ret) Then
2508 followerId.AddRange(tmpFollower)
2509 _GetFollowerResult = False
2512 Loop While cursor > 0
2514 TabInformations.GetInstance.RefreshOwl(followerId)
2516 _GetFollowerResult = True
2520 Public ReadOnly Property GetFollowersSuccess() As Boolean
2522 Return _GetFollowerResult
2526 Private Function FollowerApi(ByRef cursor As Long) As String
2527 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2529 Dim res As HttpStatusCode
2530 Dim content As String = ""
2532 res = twCon.FollowerIds(cursor, content)
2533 Catch ex As Exception
2534 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2538 Case HttpStatusCode.OK
2539 Twitter.AccountState = ACCOUNT_STATE.Valid
2540 Case HttpStatusCode.Unauthorized
2541 Twitter.AccountState = ACCOUNT_STATE.Invalid
2542 Return My.Resources.Unauthorized
2543 Case HttpStatusCode.BadRequest
2544 Return "Err:API Limits?"
2546 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2550 Dim followers = CreateDataFromJson(Of TwitterDataModel.Ids)(content)
2551 followerId.AddRange(followers.Id)
2552 cursor = followers.NextCursor
2554 Catch ex As SerializationException
2555 TraceOut(ex.Message + Environment.NewLine + content)
2556 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2557 Catch ex As Exception
2558 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2559 Return "Err:Invalid Json!"
2563 Public Function GetNoRetweetIdsApi() As String
2564 If _endingFlag Then Return ""
2565 Dim cursor As Long = -1
2566 Dim tmpIds As New List(Of Long)(noRTId)
2570 Dim ret As String = NoRetweetApi(cursor)
2571 If Not String.IsNullOrEmpty(ret) Then
2573 noRTId.AddRange(tmpIds)
2574 _GetNoRetweetResult = False
2577 Loop While cursor > 0
2579 _GetNoRetweetResult = True
2583 Private Function NoRetweetApi(ByRef cursor As Long) As String
2584 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2586 Dim res As HttpStatusCode
2587 Dim content As String = ""
2589 res = twCon.NoRetweetIds(cursor, content)
2590 Catch ex As Exception
2591 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2595 Case HttpStatusCode.OK
2596 Twitter.AccountState = ACCOUNT_STATE.Valid
2597 Case HttpStatusCode.Unauthorized
2598 Twitter.AccountState = ACCOUNT_STATE.Invalid
2599 Return My.Resources.Unauthorized
2600 Case HttpStatusCode.BadRequest
2601 Return "Err:API Limits?"
2603 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2607 Dim ids = CreateDataFromJson(Of Long())(content)
2608 noRTId.AddRange(ids)
2609 cursor = 0 '0より小さければ何でも良い。
2611 Catch ex As SerializationException
2612 TraceOut(ex.Message + Environment.NewLine + content)
2613 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2614 Catch ex As Exception
2615 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2616 Return "Err:Invalid Json!"
2620 Public ReadOnly Property GetNoRetweetSuccess() As Boolean
2622 Return _GetNoRetweetResult
2626 Public Function ConfigurationApi() As String
2627 Dim res As HttpStatusCode
2628 Dim content As String = ""
2630 res = twCon.GetConfiguration(content)
2631 Catch ex As Exception
2632 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2636 Case HttpStatusCode.OK
2637 Twitter.AccountState = ACCOUNT_STATE.Valid
2638 Case HttpStatusCode.Unauthorized
2639 Twitter.AccountState = ACCOUNT_STATE.Invalid
2640 Return My.Resources.Unauthorized
2641 Case HttpStatusCode.BadRequest
2642 Return "Err:API Limits?"
2644 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2648 AppendSettingDialog.Instance.TwitterConfiguration = CreateDataFromJson(Of TwitterDataModel.Configuration)(content)
2650 Catch ex As SerializationException
2651 TraceOut(ex.Message + Environment.NewLine + content)
2652 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2653 Catch ex As Exception
2654 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2655 Return "Err:Invalid Json!"
2659 Public Function GetListsApi() As String
2660 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2662 Dim res As HttpStatusCode
2663 Dim content As String = ""
2664 Dim cursor As Long = -1
2666 Dim lists As New List(Of ListElement)
2669 res = twCon.GetLists(Me.Username, cursor, content)
2670 Catch ex As Exception
2671 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2675 Case HttpStatusCode.OK
2676 Twitter.AccountState = ACCOUNT_STATE.Valid
2677 Case HttpStatusCode.Unauthorized
2678 Twitter.AccountState = ACCOUNT_STATE.Invalid
2679 Return My.Resources.Unauthorized
2680 Case HttpStatusCode.BadRequest
2681 Return "Err:API Limits?"
2683 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2687 Dim lst = CreateDataFromJson(Of TwitterDataModel.Lists)(content)
2688 lists.AddRange(From le In lst.Lists Select New ListElement(le, Me))
2689 cursor = lst.NextCursor
2690 Catch ex As SerializationException
2691 TraceOut(ex.Message + Environment.NewLine + content)
2692 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2693 Catch ex As Exception
2694 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2695 Return "Err:Invalid Json!"
2697 Loop While cursor <> 0
2703 res = twCon.GetListsSubscriptions(Me.Username, cursor, content)
2704 Catch ex As Exception
2705 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2709 Case HttpStatusCode.OK
2710 Twitter.AccountState = ACCOUNT_STATE.Valid
2711 Case HttpStatusCode.Unauthorized
2712 Twitter.AccountState = ACCOUNT_STATE.Invalid
2713 Return My.Resources.Unauthorized
2714 Case HttpStatusCode.BadRequest
2715 Return "Err:API Limits?"
2717 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2721 Dim lst = CreateDataFromJson(Of TwitterDataModel.Lists)(content)
2722 lists.AddRange(From le In lst.Lists Select New ListElement(le, Me))
2723 cursor = lst.NextCursor
2724 Catch ex As SerializationException
2725 TraceOut(ex.Message + Environment.NewLine + content)
2726 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2727 Catch ex As Exception
2728 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2729 Return "Err:Invalid Json!"
2731 Loop While cursor <> 0
2733 TabInformations.GetInstance.SubscribableLists = lists
2737 Public Function DeleteList(ByVal list_id As String) As String
2738 Dim res As HttpStatusCode
2739 Dim content As String = ""
2741 Google.GASender.GetInstance().TrackEventWithCategory("post", "destroy_list", Me.UserId)
2743 res = twCon.DeleteListID(Me.Username, list_id, content)
2744 Catch ex As Exception
2745 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2749 Case HttpStatusCode.OK
2750 Twitter.AccountState = ACCOUNT_STATE.Valid
2751 Case HttpStatusCode.Unauthorized
2752 Twitter.AccountState = ACCOUNT_STATE.Invalid
2753 Return My.Resources.Unauthorized
2754 Case HttpStatusCode.BadRequest
2755 Return "Err:API Limits?"
2757 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2763 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
2764 Google.GASender.GetInstance().TrackEventWithCategory("get", "update_list", Me.UserId)
2765 Dim res As HttpStatusCode
2766 Dim content As String = ""
2769 res = twCon.UpdateListID(Me.Username, list_id, new_name, isPrivate, description, content)
2770 Catch ex As Exception
2771 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2775 Case HttpStatusCode.OK
2776 Twitter.AccountState = ACCOUNT_STATE.Valid
2777 Case HttpStatusCode.Unauthorized
2778 Twitter.AccountState = ACCOUNT_STATE.Invalid
2779 Return My.Resources.Unauthorized
2780 Case HttpStatusCode.BadRequest
2781 Return "Err:API Limits?"
2783 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2787 Dim le = CreateDataFromJson(Of TwitterDataModel.ListElementData)(content)
2788 Dim newList As New ListElement(le, Me)
2789 list.Description = newList.Description
2790 list.Id = newList.Id
2791 list.IsPublic = newList.IsPublic
2792 list.MemberCount = newList.MemberCount
2793 list.Name = newList.Name
2794 list.SubscriberCount = newList.SubscriberCount
2795 list.Slug = newList.Slug
2796 list.Nickname = newList.Nickname
2797 list.Username = newList.Username
2798 list.UserId = newList.UserId
2800 Catch ex As SerializationException
2801 TraceOut(ex.Message + Environment.NewLine + content)
2802 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2803 Catch ex As Exception
2804 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2805 Return "Err:Invalid Json!"
2810 Public Function GetListMembers(ByVal list_id As String, ByVal lists As List(Of UserInfo), ByRef cursor As Long) As String
2811 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2813 Dim res As HttpStatusCode
2814 Dim content As String = ""
2818 res = twCon.GetListMembers(Me.Username, list_id, cursor, content)
2819 Catch ex As Exception
2820 Return "Err:" + ex.Message
2824 Case HttpStatusCode.OK
2825 Twitter.AccountState = ACCOUNT_STATE.Valid
2826 Case HttpStatusCode.Unauthorized
2827 Twitter.AccountState = ACCOUNT_STATE.Invalid
2828 Return My.Resources.Unauthorized
2829 Case HttpStatusCode.BadRequest
2830 Return "Err:API Limits?"
2832 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2836 Dim users = CreateDataFromJson(Of TwitterDataModel.Users)(content)
2837 Array.ForEach(Of TwitterDataModel.User)(
2839 New Action(Of TwitterDataModel.User)(Sub(u)
2840 lists.Add(New UserInfo(u))
2842 cursor = users.NextCursor
2844 Catch ex As SerializationException
2845 TraceOut(ex.Message + Environment.NewLine + content)
2846 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2847 Catch ex As Exception
2848 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2849 Return "Err:Invalid Json!"
2855 Public Function CreateListApi(ByVal listName As String, ByVal isPrivate As Boolean, ByVal description As String) As String
2856 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2858 Google.GASender.GetInstance().TrackEventWithCategory("post", "create_list", Me.UserId)
2859 Dim res As HttpStatusCode
2860 Dim content As String = ""
2863 res = twCon.CreateLists(listName, isPrivate, description, content)
2864 Catch ex As Exception
2865 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2869 Case HttpStatusCode.OK
2870 Twitter.AccountState = ACCOUNT_STATE.Valid
2871 Case HttpStatusCode.Unauthorized
2872 Twitter.AccountState = ACCOUNT_STATE.Invalid
2873 Return My.Resources.Unauthorized
2874 Case HttpStatusCode.BadRequest
2875 Return "Err:API Limits?"
2877 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2881 Dim le = CreateDataFromJson(Of TwitterDataModel.ListElementData)(content)
2882 TabInformations.GetInstance().SubscribableLists.Add(New ListElement(le, Me))
2884 Catch ex As SerializationException
2885 TraceOut(ex.Message + Environment.NewLine + content)
2886 Return "Err:Json Parse Error(DataContractJsonSerializer)"
2887 Catch ex As Exception
2888 TraceOut(ex, GetCurrentMethod.Name & " " & content)
2889 Return "Err:Invalid Json!"
2893 Public Function ContainsUserAtList(ByVal listId As String, ByVal user As String, ByRef value As Boolean) As String
2896 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2898 Dim res As HttpStatusCode
2899 Dim content As String = ""
2902 res = Me.twCon.ShowListMember(listId, user, content)
2903 Catch ex As Exception
2904 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2908 Case HttpStatusCode.OK
2909 Twitter.AccountState = ACCOUNT_STATE.Valid
2910 Case HttpStatusCode.Unauthorized
2911 Twitter.AccountState = ACCOUNT_STATE.Invalid
2912 Return My.Resources.Unauthorized
2913 Case HttpStatusCode.BadRequest
2914 Return "Err:API Limits?"
2915 Case HttpStatusCode.NotFound
2919 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2923 Dim u = CreateDataFromJson(Of TwitterDataModel.User)(content)
2926 Catch ex As Exception
2932 Public Function AddUserToList(ByVal listId As String, ByVal user As String) As String
2933 Dim content As String = ""
2934 Dim res As HttpStatusCode
2936 Google.GASender.GetInstance().TrackEventWithCategory("post", "add_user_to_list", Me.UserId)
2938 res = twCon.CreateListMembers(listId, user, content)
2939 Catch ex As Exception
2940 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2944 Case HttpStatusCode.OK
2945 Twitter.AccountState = ACCOUNT_STATE.Valid
2946 Case HttpStatusCode.Unauthorized
2947 Twitter.AccountState = ACCOUNT_STATE.Invalid
2948 Return My.Resources.Unauthorized
2949 Case HttpStatusCode.BadRequest
2950 Return "Err:" + GetErrorMessageJson(content)
2952 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2958 Public Function RemoveUserToList(ByVal listId As String, ByVal user As String) As String
2959 Google.GASender.GetInstance().TrackEventWithCategory("post", "remove_user_from_list", Me.UserId)
2961 Dim content As String = ""
2962 Dim res As HttpStatusCode
2965 res = twCon.DeleteListMembers(listId, user, content)
2966 Catch ex As Exception
2967 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2971 Case HttpStatusCode.OK
2972 Twitter.AccountState = ACCOUNT_STATE.Valid
2973 Case HttpStatusCode.Unauthorized
2974 Twitter.AccountState = ACCOUNT_STATE.Invalid
2975 Return My.Resources.Unauthorized
2976 Case HttpStatusCode.BadRequest
2977 Return "Err:" + GetErrorMessageJson(content)
2979 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2986 Public Property fromIndex As Integer
2987 Public Property toIndex As Integer
2988 Public Sub New(ByVal fromIndex As Integer, ByVal toIndex As Integer)
2989 Me.fromIndex = fromIndex
2990 Me.toIndex = toIndex
2993 Public Function CreateHtmlAnchor(ByVal Text As String, ByVal AtList As List(Of String), ByVal media As Dictionary(Of String, String)) As String
2994 If Text Is Nothing Then Return Nothing
2995 Dim retStr As String = Text.Replace(">", "<<<<<tweenだいなり>>>>>").Replace("<", "<<<<<tweenしょうなり>>>>>")
2997 'Const url_valid_domain As String = "(?<domain>(?:[^\p{P}\s][\.\-_](?=[^\p{P}\s])|[^\p{P}\s]){1,}\.[a-z]{2,}(?::[0-9]+)?)"
2998 'Const url_valid_general_path_chars As String = "[a-z0-9!*';:=+$/%#\[\]\-_,~]"
2999 'Const url_balance_parens As String = "(?:\(" + url_valid_general_path_chars + "+\))"
3000 'Const url_valid_url_path_ending_chars As String = "(?:[a-z0-9=_#/\-\+]+|" + url_balance_parens + ")"
3001 'Const pth As String = "(?:" + url_balance_parens +
3002 ' "|@" + url_valid_general_path_chars + "+/" +
3003 ' "|[.,]?" + url_valid_general_path_chars + "+" +
3005 'Const pth2 As String = "(/(?:" +
3006 ' pth + "+" + url_valid_url_path_ending_chars + "|" +
3007 ' pth + "+" + url_valid_url_path_ending_chars + "?|" +
3008 ' url_valid_url_path_ending_chars +
3010 'Const qry As String = "(?<query>\?[a-z0-9!*'();:&=+$/%#\[\]\-_.,~]*[a-z0-9_&=#])?"
3011 'Const rgUrl As String = "(?<before>(?:[^\""':!=#]|^|\:/))" +
3012 ' "(?<url>(?<protocol>https?://)" +
3013 ' url_valid_domain +
3017 'Const rgUrl As String = "(?<before>(?:[^\""':!=#]|^|\:/))" +
3018 ' "(?<url>(?<protocol>https?://|www\.)" +
3019 ' url_valid_domain +
3024 retStr = Regex.Replace(retStr,
3026 New MatchEvaluator(Function(mu As Match)
3027 Dim sb As New StringBuilder(mu.Result("${before}<a href="""))
3028 'If mu.Result("${protocol}").StartsWith("w", StringComparison.OrdinalIgnoreCase) Then
3029 ' sb.Append("http://")
3031 Dim url As String = mu.Result("${url}")
3032 Dim title As String = ShortUrl.ResolveMedia(url, True)
3033 If url <> title Then
3034 title = ShortUrl.ResolveMedia(title, False)
3036 sb.Append(url + """ title=""" + title + """>").Append(url).Append("</a>")
3037 If media IsNot Nothing AndAlso Not media.ContainsKey(url) Then media.Add(url, title)
3040 RegexOptions.IgnoreCase)
3043 retStr = Regex.Replace(retStr,
3044 "(^|[^a-zA-Z0-9_/])([@@]+)([a-zA-Z0-9_]{1,20}/[a-zA-Z][a-zA-Z0-9\p{IsLatin-1Supplement}\-]{0,79})",
3045 "$1$2<a href=""/$3"">$3</a>")
3047 Dim m As Match = Regex.Match(retStr, "(^|[^a-zA-Z0-9_])[@@]([a-zA-Z0-9_]{1,20})")
3049 If Not AtList.Contains(m.Result("$2").ToLower) Then AtList.Add(m.Result("$2").ToLower)
3053 retStr = Regex.Replace(retStr,
3054 "(^|[^a-zA-Z0-9_/])([@@])([a-zA-Z0-9_]{1,20})",
3055 "$1$2<a href=""/$3"">$3</a>")
3058 Dim anchorRange As New List(Of range)
3059 For i As Integer = 0 To retStr.Length - 1
3060 Dim index As Integer = retStr.IndexOf("<a ", i)
3061 If index > -1 AndAlso index < retStr.Length Then
3063 Dim toIndex As Integer = retStr.IndexOf("</a>", index)
3064 If toIndex > -1 Then
3065 anchorRange.Add(New range(index, toIndex + 3))
3070 'retStr = Regex.Replace(retStr,
3071 ' "(^|[^a-zA-Z0-9/&])([##])([0-9a-zA-Z_]*[a-zA-Z_]+[a-zA-Z0-9_\xc0-\xd6\xd8-\xf6\xf8-\xff]*)",
3072 ' New MatchEvaluator(Function(mh As Match)
3073 ' For Each rng As range In anchorRange
3074 ' If mh.Index >= rng.fromIndex AndAlso
3075 ' mh.Index <= rng.toIndex Then Return mh.Result("$0")
3077 ' If IsNumeric(mh.Result("$3")) Then Return mh.Result("$0")
3079 ' _hashList.Add("#" + mh.Result("$3"))
3081 ' Return mh.Result("$1") + "<a href=""" & _protocol & "twitter.com/search?q=%23" + mh.Result("$3") + """>" + mh.Result("$2$3") + "</a>"
3083 ' RegexOptions.IgnoreCase)
3084 retStr = Regex.Replace(retStr,
3086 New MatchEvaluator(Function(mh As Match)
3087 For Each rng As range In anchorRange
3088 If mh.Index >= rng.fromIndex AndAlso
3089 mh.Index <= rng.toIndex Then Return mh.Result("$0")
3092 _hashList.Add("#" + mh.Result("$3"))
3094 Return mh.Result("$1") + "<a href=""" & _protocol & "twitter.com/search?q=%23" + mh.Result("$3") + """>" + mh.Result("$2$3") + "</a>"
3096 RegexOptions.IgnoreCase)
3099 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>")
3101 retStr = retStr.Replace("<<<<<tweenだいなり>>>>>", ">").Replace("<<<<<tweenしょうなり>>>>>", "<")
3103 'retStr = AdjustHtml(ShortUrl.Resolve(PreProcessUrl(retStr), True)) 'IDN置換、短縮Uri解決、@リンクを相対→絶対にしてtarget属性付与
3104 retStr = AdjustHtml(PreProcessUrl(retStr)) 'IDN置換、短縮Uri解決、@リンクを相対→絶対にしてtarget属性付与
3108 Private Class EntityInfo
3109 Public Property StartIndex As Integer
3110 Public Property EndIndex As Integer
3111 Public Property Text As String
3112 Public Property Html As String
3113 Public Property Display As String
3115 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
3116 Dim ret As String = Text
3118 If entities IsNot Nothing Then
3119 Dim etInfo As New SortedList(Of Integer, EntityInfo)
3121 If entities.Urls IsNot Nothing Then
3122 For Each ent In entities.Urls
3123 If String.IsNullOrEmpty(ent.DisplayUrl) Then
3124 etInfo.Add(ent.Indices(0),
3125 New EntityInfo With {.StartIndex = ent.Indices(0),
3126 .EndIndex = ent.Indices(1),
3128 .Html = "<a href=""" + ent.Url + """>" + ent.Url + "</a>"})
3130 Dim expanded As String = ShortUrl.ResolveMedia(ent.ExpandedUrl, False)
3131 etInfo.Add(ent.Indices(0),
3132 New EntityInfo With {.StartIndex = ent.Indices(0),
3133 .EndIndex = ent.Indices(1),
3135 .Html = "<a href=""" + ent.Url + """ title=""" + expanded + """>" + ent.DisplayUrl + "</a>",
3136 .Display = ent.DisplayUrl})
3137 If media IsNot Nothing AndAlso Not media.ContainsKey(ent.Url) Then media.Add(ent.Url, expanded)
3141 If entities.Hashtags IsNot Nothing Then
3142 For Each ent In entities.Hashtags
3143 Dim hash As String = Text.Substring(ent.Indices(0), ent.Indices(1) - ent.Indices(0))
3144 etInfo.Add(ent.Indices(0),
3145 New EntityInfo With {.StartIndex = ent.Indices(0),
3146 .EndIndex = ent.Indices(1),
3148 .Html = "<a href=""" & _protocol & "twitter.com/search?q=%23" + ent.Text + """>" + hash + "</a>"})
3150 _hashList.Add("#" + ent.Text)
3154 If entities.UserMentions IsNot Nothing Then
3155 For Each ent In entities.UserMentions
3156 Dim screenName As String = Text.Substring(ent.Indices(0) + 1, ent.Indices(1) - ent.Indices(0) - 1)
3157 etInfo.Add(ent.Indices(0) + 1,
3158 New EntityInfo With {.StartIndex = ent.Indices(0) + 1,
3159 .EndIndex = ent.Indices(1),
3160 .Text = ent.ScreenName,
3161 .Html = "<a href=""/" + ent.ScreenName + """>" + screenName + "</a>"})
3162 If Not AtList.Contains(ent.ScreenName.ToLower) Then AtList.Add(ent.ScreenName.ToLower)
3165 If entities.Media IsNot Nothing Then
3166 For Each ent In entities.Media
3167 If ent.Type = "photo" Then
3168 etInfo.Add(ent.Indices(0),
3169 New EntityInfo With {.StartIndex = ent.Indices(0),
3170 .EndIndex = ent.Indices(1),
3172 .Html = "<a href=""" + ent.Url + """ title=""" + ent.ExpandedUrl + """>" + ent.DisplayUrl + "</a>",
3173 .Display = ent.DisplayUrl})
3174 If media IsNot Nothing AndAlso Not media.ContainsKey(ent.Url) Then media.Add(ent.Url, ent.MediaUrl)
3178 If etInfo.Count > 0 Then
3179 Dim idx As Integer = 0
3181 For Each et In etInfo
3182 ret += Text.Substring(idx, et.Key - idx) + et.Value.Html
3183 idx = et.Value.EndIndex
3185 ret += Text.Substring(idx)
3189 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>")
3190 ret = AdjustHtml(ShortUrl.Resolve(PreProcessUrl(ret), False)) 'IDN置換、短縮Uri解決、@リンクを相対→絶対にしてtarget属性付与
3196 Private Sub CreateSource(ByRef post As PostClass)
3197 If post.Source.StartsWith("<") Then
3198 If Not post.Source.Contains("</a>") Then
3199 post.Source += "</a>"
3201 Dim mS As Match = Regex.Match(post.Source, ">(?<source>.+)<")
3203 post.SourceHtml = String.Copy(ShortUrl.Resolve(PreProcessUrl(post.Source), False))
3204 post.Source = HttpUtility.HtmlDecode(mS.Result("${source}"))
3207 post.SourceHtml = ""
3210 If post.Source = "web" Then
3211 post.SourceHtml = My.Resources.WebSourceString
3212 ElseIf post.Source = "Keitai Mail" Then
3213 post.SourceHtml = My.Resources.KeitaiMailSourceString
3215 post.SourceHtml = String.Copy(post.Source)
3220 Public Function GetInfoApi(ByVal info As ApiInfo) As Boolean
3221 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return True
3223 If _endingFlag Then Return True
3225 Dim res As HttpStatusCode
3226 Dim content As String = ""
3228 res = twCon.RateLimitStatus(content)
3229 Catch ex As Exception
3230 TwitterApiInfo.Initialize()
3234 If res <> HttpStatusCode.OK Then Return False
3237 Dim limit = CreateDataFromJson(Of TwitterDataModel.RateLimitStatus)(content)
3238 Dim arg As New ApiInformationChangedEventArgs
3239 arg.ApiInfo.MaxCount = limit.HourlyLimit
3240 arg.ApiInfo.RemainCount = limit.RemainingHits
3241 arg.ApiInfo.ResetTime = DateTimeParse(limit.RestTime)
3242 arg.ApiInfo.ResetTimeInSeconds = limit.RestTimeInSeconds
3243 If info IsNot Nothing Then
3244 arg.ApiInfo.UsingCount = info.UsingCount
3246 info.MaxCount = arg.ApiInfo.MaxCount
3247 info.RemainCount = arg.ApiInfo.RemainCount
3248 info.ResetTime = arg.ApiInfo.ResetTime
3249 info.ResetTimeInSeconds = arg.ApiInfo.ResetTimeInSeconds
3252 RaiseEvent ApiInformationChanged(Me, arg)
3253 TwitterApiInfo.WriteBackEventArgs(arg)
3255 Catch ex As Exception
3256 TraceOut(ex, GetCurrentMethod.Name & " " & content)
3257 TwitterApiInfo.Initialize()
3261 Public Function GetBlockUserIds() As String
3262 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
3264 Dim res As HttpStatusCode
3265 Dim content As String = ""
3268 res = twCon.GetBlockUserIds(content)
3269 Catch ex As Exception
3270 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
3274 Case HttpStatusCode.OK
3275 Twitter.AccountState = ACCOUNT_STATE.Valid
3276 Case HttpStatusCode.Unauthorized
3277 Twitter.AccountState = ACCOUNT_STATE.Invalid
3278 Return My.Resources.Unauthorized
3279 Case HttpStatusCode.BadRequest
3280 Return "Err:API Limits?"
3282 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
3286 Dim Ids = CreateDataFromJson(Of Long())(content)
3287 TabInformations.GetInstance.BlockIds.AddRange(Ids)
3289 Catch ex As SerializationException
3290 TraceOut(ex.Message + Environment.NewLine + content)
3291 Return "Err:Json Parse Error(DataContractJsonSerializer)"
3292 Catch ex As Exception
3293 TraceOut(ex, GetCurrentMethod.Name & " " & content)
3294 Return "Err:Invalid Json!"
3299 Public Function GetHashList() As String()
3300 Dim hashArray As String()
3302 hashArray = _hashList.ToArray
3308 Public ReadOnly Property AccessToken() As String
3310 Return twCon.AccessToken
3314 Public ReadOnly Property AccessTokenSecret() As String
3316 Return twCon.AccessTokenSecret
3320 Public Event ApiInformationChanged(ByVal sender As Object, ByVal e As ApiInformationChangedEventArgs)
3322 Private Sub Twitter_ApiInformationChanged(ByVal sender As Object, ByVal e As ApiInformationChangedEventArgs) Handles Me.ApiInformationChanged
3325 #Region "UserStream"
3326 Public Property TrackWord As String = ""
3327 Public Property AllAtReply As Boolean = False
3329 Public Event NewPostFromStream()
3330 Public Event UserStreamStarted()
3331 Public Event UserStreamStopped()
3332 Public Event UserStreamGetFriendsList()
3333 Public Event PostDeleted(ByVal id As Long)
3334 Public Event UserStreamEventReceived(ByVal eventType As FormattedEvent)
3335 Private _lastUserstreamDataReceived As DateTime
3336 Private WithEvents userStream As TwitterUserstream
3338 Public Class FormattedEvent
3339 Public Property Eventtype As EVENTTYPE
3340 Public Property CreatedAt As DateTime
3341 Public Property [Event] As String
3342 Public Property Username As String
3343 Public Property Target As String
3344 Public Property Id As Int64
3345 Public Property IsMe As Boolean
3348 Public Property StoredEvent As New List(Of FormattedEvent)
3350 Private Class EventTypeTableElement
3351 Public Name As String
3352 Public Type As EVENTTYPE
3354 Public Sub New(ByVal name As String, ByVal type As EVENTTYPE)
3360 Private EventTable As EventTypeTableElement() = {
3361 New EventTypeTableElement("favorite", EVENTTYPE.Favorite), _
3362 New EventTypeTableElement("unfavorite", EVENTTYPE.Unfavorite), _
3363 New EventTypeTableElement("follow", EVENTTYPE.Follow), _
3364 New EventTypeTableElement("list_member_added", EVENTTYPE.ListMemberAdded), _
3365 New EventTypeTableElement("list_member_removed", EVENTTYPE.ListMemberRemoved), _
3366 New EventTypeTableElement("block", EVENTTYPE.Block), _
3367 New EventTypeTableElement("unblock", EVENTTYPE.Unblock), _
3368 New EventTypeTableElement("user_update", EVENTTYPE.UserUpdate), _
3369 New EventTypeTableElement("deleted", EVENTTYPE.Deleted), _
3370 New EventTypeTableElement("list_created", EVENTTYPE.ListCreated), _
3371 New EventTypeTableElement("list_updated", EVENTTYPE.ListUpdated)
3374 Public Function EventNameToEventType(ByVal EventName As String) As EVENTTYPE
3375 Return (From tbl In EventTable Where tbl.Name.Equals(EventName) Select tbl.Type).FirstOrDefault()
3378 Public ReadOnly Property IsUserstreamDataReceived As Boolean
3380 Return Now.Subtract(Me._lastUserstreamDataReceived).TotalSeconds < 31
3384 Private Sub userStream_StatusArrived(ByVal line As String) Handles userStream.StatusArrived
3385 Me._lastUserstreamDataReceived = Now
3386 If String.IsNullOrEmpty(line) Then Exit Sub
3388 Dim isDm As Boolean = False
3391 Using jsonReader As XmlDictionaryReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(line), XmlDictionaryReaderQuotas.Max)
3392 Dim xElm As XElement = XElement.Load(jsonReader)
3393 If xElm.Element("friends") IsNot Nothing Then
3394 Debug.Print("friends")
3396 ElseIf xElm.Element("delete") IsNot Nothing Then
3397 Debug.Print("delete")
3399 If xElm.Element("delete").Element("direct_message") IsNot Nothing AndAlso
3400 xElm.Element("delete").Element("direct_message").Element("id") IsNot Nothing Then
3401 id = CLng(xElm.Element("delete").Element("direct_message").Element("id").Value)
3402 RaiseEvent PostDeleted(id)
3403 ElseIf xElm.Element("delete").Element("status") IsNot Nothing AndAlso
3404 xElm.Element("delete").Element("status").Element("id") IsNot Nothing Then
3405 id = CLng(xElm.Element("delete").Element("status").Element("id").Value)
3406 RaiseEvent PostDeleted(id)
3408 TraceOut("delete:" + line)
3411 For i As Integer = Me.StoredEvent.Count - 1 To 0 Step -1
3412 Dim sEvt As FormattedEvent = Me.StoredEvent(i)
3413 If sEvt.Id = id AndAlso (sEvt.Event = "favorite" OrElse sEvt.Event = "unfavorite") Then
3414 Me.StoredEvent.RemoveAt(i)
3418 ElseIf xElm.Element("limit") IsNot Nothing Then
3421 ElseIf xElm.Element("event") IsNot Nothing Then
3422 Debug.Print("event: " + xElm.Element("event").Value)
3423 CreateEventFromJson(line)
3425 ElseIf xElm.Element("direct_message") IsNot Nothing Then
3426 Debug.Print("direct_message")
3428 ElseIf xElm.Element("scrub_geo") IsNot Nothing Then
3430 TabInformations.GetInstance.ScrubGeoReserve(Long.Parse(xElm.Element("scrub_geo").Element("user_id").Value),
3431 Long.Parse(xElm.Element("scrub_geo").Element("up_to_status_id").Value))
3432 Catch ex As Exception
3433 TraceOut("scrub_geo:" + line)
3439 Dim res As New StringBuilder
3446 CreateDirectMessagesFromJson(res.ToString, WORKERTYPE.UserStream, False)
3448 CreatePostsFromJson(res.ToString, WORKERTYPE.Timeline, Nothing, False, Nothing, Nothing)
3450 Catch ex As NullReferenceException
3451 TraceOut("NullRef StatusArrived: " + line)
3454 RaiseEvent NewPostFromStream()
3457 Private Sub CreateEventFromJson(ByVal content As String)
3458 Dim eventData As TwitterDataModel.EventData = Nothing
3460 eventData = CreateDataFromJson(Of TwitterDataModel.EventData)(content)
3461 Catch ex As SerializationException
3462 TraceOut(ex, "Event Serialize Exception!" + Environment.NewLine + content)
3463 Catch ex As Exception
3464 TraceOut(ex, "Event Exception!" + Environment.NewLine + content)
3467 Dim evt As New FormattedEvent
3468 evt.CreatedAt = DateTimeParse(eventData.CreatedAt)
3469 evt.Event = eventData.Event
3470 evt.Username = eventData.Source.ScreenName
3471 evt.IsMe = evt.Username.ToLower().Equals(Me.Username.ToLower())
3472 evt.Eventtype = EventNameToEventType(evt.Event)
3473 Select Case eventData.Event
3475 If eventData.Target.ScreenName.ToLower.Equals(_uname) Then
3476 If Not Me.followerId.Contains(eventData.Source.Id) Then Me.followerId.Add(eventData.Source.Id)
3478 Exit Sub 'Block後のUndoをすると、SourceとTargetが逆転したfollowイベントが帰ってくるため。
3481 Case "favorite", "unfavorite"
3482 evt.Target = "@" + eventData.TargetObject.User.ScreenName + ":" + HttpUtility.HtmlDecode(eventData.TargetObject.Text)
3483 evt.Id = eventData.TargetObject.Id
3484 If TabInformations.GetInstance.ContainsKey(eventData.TargetObject.Id) Then
3485 Dim post As PostClass = TabInformations.GetInstance.Item(eventData.TargetObject.Id)
3486 If eventData.Event = "favorite" Then
3487 If evt.Username.ToLower.Equals(_uname) Then
3489 TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Add(post.StatusId, post.IsRead, False)
3491 post.FavoritedCount += 1
3492 If Not TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.StatusId) Then
3493 If TweenMain.GetInstance().FavEventChangeUnread AndAlso post.IsRead Then
3496 TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Add(post.StatusId, post.IsRead, False)
3498 If TweenMain.GetInstance().FavEventChangeUnread Then
3499 TabInformations.GetInstance.SetRead(False, TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).TabName, TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).IndexOf(post.StatusId))
3504 If evt.Username.ToLower.Equals(_uname) Then
3507 post.FavoritedCount -= 1
3508 If post.FavoritedCount < 0 Then post.FavoritedCount = 0
3512 Case "list_member_added", "list_member_removed", "list_updated"
3513 evt.Target = eventData.TargetObject.FullName
3515 If Not TabInformations.GetInstance.BlockIds.Contains(eventData.Target.Id) Then TabInformations.GetInstance.BlockIds.Add(eventData.Target.Id)
3518 If TabInformations.GetInstance.BlockIds.Contains(eventData.Target.Id) Then TabInformations.GetInstance.BlockIds.Remove(eventData.Target.Id)
3525 TraceOut("Unknown Event:" + evt.Event + Environment.NewLine + content)
3527 Me.StoredEvent.Insert(0, evt)
3528 RaiseEvent UserStreamEventReceived(evt)
3531 Private Sub userStream_Started() Handles userStream.Started
3532 Google.GASender.GetInstance().TrackPage("/userstream", Me.UserId)
3533 RaiseEvent UserStreamStarted()
3536 Private Sub userStream_Stopped() Handles userStream.Stopped
3537 RaiseEvent UserStreamStopped()
3540 Public ReadOnly Property UserStreamEnabled As Boolean
3542 Return If(userStream Is Nothing, False, userStream.Enabled)
3546 Public Sub StartUserStream()
3547 If userStream IsNot Nothing Then
3550 userStream = New TwitterUserstream(twCon)
3551 userStream.Start(Me.AllAtReply, Me.TrackWord)
3554 Public Sub StopUserStream()
3555 If userStream IsNot Nothing Then userStream.Dispose()
3556 userStream = Nothing
3557 If Not _endingFlag Then RaiseEvent UserStreamStopped()
3560 Public Sub ReconnectUserStream()
3561 If userStream IsNot Nothing Then
3562 Me.StartUserStream()
3566 Private Class TwitterUserstream
3567 Implements IDisposable
3569 Public Event StatusArrived(ByVal status As String)
3570 Public Event Stopped()
3571 Public Event Started()
3572 Private twCon As HttpTwitter
3574 Private _streamThread As Thread
3575 Private _streamActive As Boolean
3577 Private _allAtreplies As Boolean = False
3578 Private _trackwords As String = ""
3580 Public Sub New(ByVal twitterConnection As HttpTwitter)
3581 twCon = DirectCast(twitterConnection.Clone(), HttpTwitter)
3584 Public Sub Start(ByVal allAtReplies As Boolean, ByVal trackwords As String)
3585 Me.AllAtReplies = allAtReplies
3586 Me.TrackWords = trackwords
3587 _streamActive = True
3588 If _streamThread IsNot Nothing AndAlso _streamThread.IsAlive Then Exit Sub
3589 _streamThread = New Thread(AddressOf UserStreamLoop)
3590 _streamThread.Name = "UserStreamReceiver"
3591 _streamThread.IsBackground = True
3592 _streamThread.Start()
3595 Public ReadOnly Property Enabled() As Boolean
3597 Return _streamActive
3601 Public Property AllAtReplies As Boolean
3603 Return _allAtreplies
3605 Set(ByVal value As Boolean)
3606 _allAtreplies = value
3610 Public Property TrackWords As String
3614 Set(ByVal value As String)
3619 Private Sub UserStreamLoop()
3620 Dim st As Stream = Nothing
3621 Dim sr As StreamReader = Nothing
3622 Dim sleepSec As Integer = 0
3625 If Not MyCommon.IsNetworkAvailable() Then
3626 Thread.Sleep(30 * 1000)
3630 RaiseEvent Started()
3631 Dim res As HttpStatusCode = twCon.UserStream(st, _allAtreplies, _trackwords, GetUserAgentString())
3634 Case HttpStatusCode.OK
3635 Twitter.AccountState = ACCOUNT_STATE.Valid
3636 Case HttpStatusCode.Unauthorized
3637 Twitter.AccountState = ACCOUNT_STATE.Invalid
3642 If st Is Nothing Then
3644 'TraceOut("Stop:stream is Nothing")
3648 sr = New StreamReader(st)
3650 Do While _streamActive AndAlso Not sr.EndOfStream AndAlso Twitter.AccountState = ACCOUNT_STATE.Valid
3651 RaiseEvent StatusArrived(sr.ReadLine())
3655 If sr.EndOfStream OrElse Twitter.AccountState = ACCOUNT_STATE.Invalid Then
3657 'TraceOut("Stop:EndOfStream")
3661 Catch ex As WebException
3662 If ex.Status = WebExceptionStatus.Timeout Then
3663 sleepSec = 30 'TraceOut("Stop:Timeout")
3664 ElseIf ex.Response IsNot Nothing AndAlso CType(ex.Response, HttpWebResponse).StatusCode = 420 Then
3665 'TraceOut("Stop:Connection Limit")
3669 'TraceOut("Stop:WebException " & ex.Status.ToString)
3671 Catch ex As ThreadAbortException
3673 Catch ex As IOException
3675 'TraceOut("Stop:IOException with Active." + Environment.NewLine + ex.Message)
3676 Catch ex As ArgumentException
3677 'System.ArgumentException: ストリームを読み取れませんでした。
3678 'サーバー側もしくは通信経路上で切断された場合?タイムアウト頻発後発生
3680 TraceOut(ex, "Stop:ArgumentException")
3681 Catch ex As Exception
3682 TraceOut("Stop:Exception." + Environment.NewLine + ex.Message)
3686 If _streamActive Then RaiseEvent Stopped()
3687 twCon.RequestAbort()
3688 If sr IsNot Nothing Then sr.Close()
3689 If st IsNot Nothing Then st.Close()
3690 If sleepSec > 0 AndAlso Me._streamActive Then Thread.Sleep(sleepSec * 1000)
3693 Loop While Me._streamActive
3695 If _streamActive Then RaiseEvent Stopped()
3696 TraceOut("Stop:EndLoop")
3699 #Region "IDisposable Support"
3700 Private disposedValue As Boolean ' 重複する呼び出しを検出するには
3703 Protected Overridable Sub Dispose(ByVal disposing As Boolean)
3704 If Not Me.disposedValue Then
3706 ' TODO: マネージ状態を破棄します (マネージ オブジェクト)。
3707 _streamActive = False
3708 If _streamThread IsNot Nothing AndAlso _streamThread.IsAlive Then
3709 _streamThread.Abort()
3713 ' TODO: アンマネージ リソース (アンマネージ オブジェクト) を解放し、下の Finalize() をオーバーライドします。
3714 ' TODO: 大きなフィールドを null に設定します。
3716 Me.disposedValue = True
3719 ' TODO: 上の Dispose(ByVal disposing As Boolean) にアンマネージ リソースを解放するコードがある場合にのみ、Finalize() をオーバーライドします。
3720 'Protected Overrides Sub Finalize()
3721 ' ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
3726 ' このコードは、破棄可能なパターンを正しく実装できるように Visual Basic によって追加されました。
3727 Public Sub Dispose() Implements IDisposable.Dispose
3728 ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
3730 GC.SuppressFinalize(Me)
3737 #Region "IDisposable Support"
3738 Private disposedValue As Boolean ' 重複する呼び出しを検出するには
3741 Protected Overridable Sub Dispose(ByVal disposing As Boolean)
3742 If Not Me.disposedValue Then
3744 ' TODO: マネージ状態を破棄します (マネージ オブジェクト)。
3748 ' TODO: アンマネージ リソース (アンマネージ オブジェクト) を解放し、下の Finalize() をオーバーライドします。
3749 ' TODO: 大きなフィールドを null に設定します。
3751 Me.disposedValue = True
3754 ' TODO: 上の Dispose(ByVal disposing As Boolean) にアンマネージ リソースを解放するコードがある場合にのみ、Finalize() をオーバーライドします。
3755 'Protected Overrides Sub Finalize()
3756 ' ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
3761 ' このコードは、破棄可能なパターンを正しく実装できるように Visual Basic によって追加されました。
3762 Public Sub Dispose() Implements IDisposable.Dispose
3763 ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
3765 GC.SuppressFinalize(Me)