1 ' Tween - Client of Twitter
2 ' Copyright (c) 2007-2010 kiri_feather (@kiri_feather) <kiri_feather@gmail.com>
3 ' (c) 2008-2010 Moz (@syo68k) <http://iddy.jp/profile/moz/>
4 ' (c) 2008-2010 takeshik (@takeshik) <http://www.takeshik.org/>
7 ' This file is part of Tween.
9 ' This program is free software; you can redistribute it and/or modify it
10 ' under the terms of the GNU General Public License as published by the Free
11 ' Software Foundation; either version 3 of the License, or (at your option)
14 ' This program is distributed in the hope that it will be useful, but
15 ' WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 ' or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 ' You should have received a copy of the GNU General Public License along
20 ' with this program. If not, see <http://www.gnu.org/licenses/>, or write to
21 ' the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
22 ' Boston, MA 02110-1301, USA.
27 Imports System.Threading
29 Imports System.Text.RegularExpressions
30 Imports System.Globalization
31 Imports System.Diagnostics
33 Imports System.Reflection
34 Imports System.Reflection.MethodBase
35 Imports System.Runtime.Serialization.Json
37 Imports System.Xml.Linq
38 Imports System.Runtime.Serialization
39 Imports System.Net.NetworkInformation
42 Implements IDisposable
44 Delegate Sub GetIconImageDelegate(ByVal post As PostClass)
45 Private ReadOnly LockObj As New Object
46 Private followerId As New List(Of Long)
47 Private _GetFollowerResult As Boolean = False
49 Private _followersCount As Integer = 0
50 Private _friendsCount As Integer = 0
51 Private _statusesCount As Integer = 0
52 Private _location As String = ""
53 Private _bio As String = ""
54 Private _protocol As String = "https://"
57 Private _uid As String
58 Private _iconSz As Integer
59 Private _getIcon As Boolean
60 Private _dIcon As IDictionary(Of String, Image)
62 Private _tinyUrlResolve As Boolean
63 Private _restrictFavCheck As Boolean
65 Private _hubServer As String
66 'Private _countApi As Integer
67 'Private _countApiReply As Integer
68 Private _readOwnPost As Boolean
69 Private _hashList As New List(Of String)
72 Private _remainCountApi As Integer = -1
74 Private op As New Outputz
75 'max_idで古い発言を取得するために保持(lists分は個別タブで管理)
76 Private minHomeTimeline As Long = Long.MaxValue
77 Private minMentions As Long = Long.MaxValue
78 Private minDirectmessage As Long = Long.MaxValue
79 Private minDirectmessageSent As Long = Long.MaxValue
81 Private twCon As New HttpTwitter
83 Private _deletemessages As New List(Of PostClass)
85 Public Function Authenticate(ByVal username As String, ByVal password As String) As String
87 Dim res As HttpStatusCode
88 Dim content As String = ""
90 TwitterApiInfo.Initialize()
92 res = twCon.AuthUserAndPass(username, password, content)
94 Return "Err:" + ex.Message
98 Case HttpStatusCode.OK
99 Twitter.AccountState = ACCOUNT_STATE.Valid
100 _uid = username.ToLower
101 Me.ReconnectUserStream()
103 Case HttpStatusCode.Unauthorized
104 Twitter.AccountState = ACCOUNT_STATE.Invalid
105 Dim errMsg As String = GetErrorMessageJson(content)
106 If String.IsNullOrEmpty(errMsg) Then
107 Return "Check your Username/Password." + Environment.NewLine + content
109 Return "Auth error:" + errMsg
111 Case HttpStatusCode.Forbidden
112 Dim errMsg As String = GetErrorMessageJson(content)
113 If String.IsNullOrEmpty(errMsg) Then
114 Return "Err:Forbidden"
116 Return "Err:" + errMsg
119 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
124 Public Sub ClearAuthInfo()
125 Twitter.AccountState = ACCOUNT_STATE.Invalid
126 TwitterApiInfo.Initialize()
127 twCon.ClearAuthInfo()
131 Private Function GetErrorMessageJson(ByVal content As String) As String
133 If Not String.IsNullOrEmpty(content) Then
134 Using jsonReader As XmlDictionaryReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(content), XmlDictionaryReaderQuotas.Max)
135 Dim xElm As XElement = XElement.Load(jsonReader)
136 If xElm.Element("error") IsNot Nothing Then
137 Return xElm.Element("error").Value
145 Catch ex As Exception
150 Public Sub Initialize(ByVal token As String, ByVal tokenSecret As String, ByVal username As String)
152 If String.IsNullOrEmpty(token) OrElse String.IsNullOrEmpty(tokenSecret) OrElse String.IsNullOrEmpty(username) Then
153 Twitter.AccountState = ACCOUNT_STATE.Invalid
155 TwitterApiInfo.Initialize()
156 twCon.Initialize(token, tokenSecret, username)
157 _uid = username.ToLower
161 Public Sub Initialize(ByVal username As String, ByVal password As String)
163 If String.IsNullOrEmpty(username) OrElse String.IsNullOrEmpty(password) Then
164 Twitter.AccountState = ACCOUNT_STATE.Invalid
166 TwitterApiInfo.Initialize()
167 twCon.Initialize(username, password)
168 _uid = username.ToLower
172 Public Function PreProcessUrl(ByVal orgData As String) As String
174 Dim posl2 As Integer = 0
175 'Dim IDNConveter As IdnMapping = New IdnMapping()
176 Dim href As String = "<a href="""
179 If orgData.IndexOf(href, posl2, StringComparison.Ordinal) > -1 Then
180 Dim urlStr As String = ""
182 posl1 = orgData.IndexOf(href, posl2, StringComparison.Ordinal)
184 posl2 = orgData.IndexOf("""", posl1, StringComparison.Ordinal)
185 urlStr = orgData.Substring(posl1, posl2 - posl1)
187 If Not urlStr.StartsWith("http://") AndAlso Not urlStr.StartsWith("https://") AndAlso Not urlStr.StartsWith("ftp://") Then
191 Dim replacedUrl As String = IDNDecode(urlStr)
192 If replacedUrl Is Nothing Then Continue Do
193 If replacedUrl = urlStr Then Continue Do
195 orgData = orgData.Replace("<a href=""" + urlStr, "<a href=""" + replacedUrl)
204 Private Function GetPlainText(ByVal orgData As String) As String
205 Return HttpUtility.HtmlDecode(Regex.Replace(orgData, "(?<tagStart><a [^>]+>)(?<text>[^<]+)(?<tagEnd></a>)", "${text}"))
208 ' htmlの簡易サニタイズ(詳細表示に不要なタグの除去)
210 Private Function SanitizeHtml(ByVal orgdata As String) As String
211 Dim retdata As String = orgdata
213 retdata = Regex.Replace(retdata, "<(script|object|applet|image|frameset|fieldset|legend|style).*" & _
214 "</(script|object|applet|image|frameset|fieldset|legend|style)>", "", RegexOptions.IgnoreCase)
216 retdata = Regex.Replace(retdata, "<(frame|link|iframe|img)>", "", RegexOptions.IgnoreCase)
221 Private Function AdjustHtml(ByVal orgData As String) As String
222 Dim retStr As String = orgData
223 Dim m As Match = Regex.Match(retStr, "<a [^>]+>[#|#](?<1>[a-zA-Z0-9_]+)</a>")
226 _hashList.Add("#" + m.Groups(1).Value)
230 retStr = Regex.Replace(retStr, "<a [^>]*href=""/", "<a href=""" + _protocol + "twitter.com/")
231 retStr = retStr.Replace("<a href=", "<a target=""_self"" href=")
232 retStr = retStr.Replace(vbLf, "<br>")
234 '半角スペースを置換(Thanks @anis774)
235 Dim ret As Boolean = False
237 ret = EscapeSpace(retStr)
240 Return SanitizeHtml(retStr)
243 Private Function EscapeSpace(ByRef html As String) As Boolean
244 '半角スペースを置換(Thanks @anis774)
245 Dim isTag As Boolean = False
246 For i As Integer = 0 To html.Length - 1
247 If html(i) = "<"c Then
250 If html(i) = ">"c Then
254 If (Not isTag) AndAlso (html(i) = " "c) Then
255 html = html.Remove(i, 1)
256 html = html.Insert(i, " ")
263 'Private Sub GetIconImage(ByVal post As PostClass)
267 ' If Not _getIcon Then
268 ' post.ImageUrl = Nothing
269 ' TabInformations.GetInstance.AddPost(post)
273 ' If _dIcon.ContainsKey(post.ImageUrl) AndAlso _dIcon(post.ImageUrl) IsNot Nothing Then
274 ' TabInformations.GetInstance.AddPost(post)
278 ' Dim httpVar As New HttpVarious
279 ' img = httpVar.GetImage(post.ImageUrl, 10000)
280 ' If img Is Nothing Then
281 ' _dIcon.Add(post.ImageUrl, Nothing)
282 ' TabInformations.GetInstance.AddPost(post)
286 ' If _endingFlag Then Exit Sub
289 ' If Not _dIcon.ContainsKey(post.ImageUrl) Then
291 ' _dIcon.Add(post.ImageUrl, img)
292 ' Catch ex As InvalidOperationException
293 ' 'タイミングにより追加できない場合がある?(キー重複ではない)
294 ' post.ImageUrl = Nothing
295 ' Catch ex As System.OverflowException
296 ' '不正なアイコン?DrawImageに失敗する場合あり
297 ' post.ImageUrl = Nothing
298 ' Catch ex As OutOfMemoryException
300 ' post.ImageUrl = Nothing
304 ' TabInformations.GetInstance.AddPost(post)
305 ' Catch ex As ArgumentException
313 Private Structure PostInfo
314 Public CreatedAt As String
316 Public Text As String
317 Public UserId As String
318 Public Sub New(ByVal Created As String, ByVal IdStr As String, ByVal txt As String, ByVal uid As String)
324 Public Shadows Function Equals(ByVal dst As PostInfo) As Boolean
325 If Me.CreatedAt = dst.CreatedAt AndAlso Me.Id = dst.Id AndAlso Me.Text = dst.Text AndAlso Me.UserId = dst.UserId Then
333 Private Function IsPostRestricted(ByVal status As TwitterDataModel.Status) As Boolean
334 Static _prev As New PostInfo("", "", "", "")
335 Dim _current As New PostInfo("", "", "", "")
337 _current.CreatedAt = status.CreatedAt
338 _current.Id = status.IdStr
339 If status.Text Is Nothing Then
342 _current.Text = status.Text
344 _current.UserId = status.User.IdStr
346 If _current.Equals(_prev) Then
349 _prev.CreatedAt = _current.CreatedAt
350 _prev.Id = _current.Id
351 _prev.Text = _current.Text
352 _prev.UserId = _current.UserId
357 Public Function PostStatus(ByVal postStr As String, ByVal reply_to As Long) As String
359 If _endingFlag Then Return ""
361 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
363 postStr = postStr.Trim()
365 If Regex.Match(postStr, "^DM? +(?<id>[a-zA-Z0-9_]+) +(?<body>.+)", RegexOptions.IgnoreCase Or RegexOptions.Singleline).Success Then
366 Return SendDirectMessage(postStr)
369 Dim res As HttpStatusCode
370 Dim content As String = ""
372 res = twCon.UpdateStatus(postStr, reply_to, content)
373 Catch ex As Exception
374 Return "Err:" + ex.Message
378 Case HttpStatusCode.OK
379 Twitter.AccountState = ACCOUNT_STATE.Valid
380 Dim status As TwitterDataModel.Status
382 status = CreateDataFromJson(Of TwitterDataModel.Status)(content)
383 Catch ex As SerializationException
384 TraceOut(ex.Message + Environment.NewLine + content)
385 Return "Err:Json Parse Error(DataContractJsonSerializer)"
386 Catch ex As Exception
388 Return "Err:Invalid Json!"
390 _followersCount = status.User.FollowersCount
391 _friendsCount = status.User.FriendsCount
392 _statusesCount = status.User.StatusesCount
393 _location = status.User.Location
394 _bio = status.User.Description
395 _UserIdNo = status.User.IdStr
397 If IsPostRestricted(status) Then
398 Return "OK:Delaying?"
400 If op.Post(postStr.Length) Then
403 Return "Outputz:Failed"
405 Case HttpStatusCode.Forbidden, HttpStatusCode.BadRequest
406 Dim errMsg As String = GetErrorMessageJson(content)
407 If String.IsNullOrEmpty(errMsg) Then
408 Return "Warn:" + res.ToString
410 Return "Warn:" + errMsg
412 Case HttpStatusCode.Conflict, _
413 HttpStatusCode.ExpectationFailed, _
414 HttpStatusCode.Gone, _
415 HttpStatusCode.LengthRequired, _
416 HttpStatusCode.MethodNotAllowed, _
417 HttpStatusCode.NotAcceptable, _
418 HttpStatusCode.NotFound, _
419 HttpStatusCode.PaymentRequired, _
420 HttpStatusCode.PreconditionFailed, _
421 HttpStatusCode.RequestedRangeNotSatisfiable, _
422 HttpStatusCode.RequestEntityTooLarge, _
423 HttpStatusCode.RequestTimeout, _
424 HttpStatusCode.RequestUriTooLong
425 '仕様書にない400系エラー。サーバまでは到達しているのでリトライしない
426 Return "Warn:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
427 Case HttpStatusCode.Unauthorized
428 Twitter.AccountState = ACCOUNT_STATE.Invalid
429 Dim errMsg As String = GetErrorMessageJson(content)
430 If String.IsNullOrEmpty(errMsg) Then
431 Return "Check your Username/Password."
433 Return "Auth err:" + errMsg
436 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
440 Public Function SendDirectMessage(ByVal postStr As String) As String
442 If _endingFlag Then Return ""
444 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
446 postStr = postStr.Trim()
448 Dim res As HttpStatusCode
449 Dim content As String = ""
451 Dim mc As Match = Regex.Match(postStr, "^DM? +(?<id>[a-zA-Z0-9_]+) +(?<body>.+)", RegexOptions.IgnoreCase Or RegexOptions.Singleline)
454 res = twCon.SendDirectMessage(mc.Groups("body").Value, mc.Groups("id").Value, content)
455 Catch ex As Exception
456 Return "Err:" + ex.Message
460 Case HttpStatusCode.OK
461 Twitter.AccountState = ACCOUNT_STATE.Valid
462 Dim status As TwitterDataModel.Directmessage
464 status = CreateDataFromJson(Of TwitterDataModel.Directmessage)(content)
465 Catch ex As SerializationException
466 TraceOut(ex.Message + Environment.NewLine + content)
467 Return "Err:Json Parse Error(DataContractJsonSerializer)"
468 Catch ex As Exception
470 Return "Err:Invalid Json!"
472 _followersCount = status.Sender.FollowersCount
473 _friendsCount = status.Sender.FriendsCount
474 _statusesCount = status.Sender.StatusesCount
475 _location = status.Sender.Location
476 _bio = status.Sender.Description
477 _UserIdNo = status.Sender.IdStr
479 If op.Post(postStr.Length) Then
482 Return "Outputz:Failed"
484 Case HttpStatusCode.Forbidden, HttpStatusCode.BadRequest
485 Dim errMsg As String = GetErrorMessageJson(content)
486 If String.IsNullOrEmpty(errMsg) Then
487 Return "Warn:" + res.ToString
489 Return "Warn:" + errMsg
491 Case HttpStatusCode.Conflict, _
492 HttpStatusCode.ExpectationFailed, _
493 HttpStatusCode.Gone, _
494 HttpStatusCode.LengthRequired, _
495 HttpStatusCode.MethodNotAllowed, _
496 HttpStatusCode.NotAcceptable, _
497 HttpStatusCode.NotFound, _
498 HttpStatusCode.PaymentRequired, _
499 HttpStatusCode.PreconditionFailed, _
500 HttpStatusCode.RequestedRangeNotSatisfiable, _
501 HttpStatusCode.RequestEntityTooLarge, _
502 HttpStatusCode.RequestTimeout, _
503 HttpStatusCode.RequestUriTooLong
504 '仕様書にない400系エラー。サーバまでは到達しているのでリトライしない
505 Return "Warn:" + res.ToString
506 Case HttpStatusCode.Unauthorized
507 Twitter.AccountState = ACCOUNT_STATE.Invalid
508 Dim errMsg As String = GetErrorMessageJson(content)
509 If String.IsNullOrEmpty(errMsg) Then
510 Return "Check your Username/Password."
512 Return "Auth err:" + errMsg
515 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
519 Public Function RemoveStatus(ByVal id As Long) As String
520 If _endingFlag Then Return ""
522 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
524 Dim res As HttpStatusCode
527 res = twCon.DestroyStatus(id)
528 Catch ex As Exception
529 Return "Err:" + ex.Message
533 Case HttpStatusCode.OK
534 Twitter.AccountState = ACCOUNT_STATE.Valid
536 Case HttpStatusCode.Unauthorized
537 Twitter.AccountState = ACCOUNT_STATE.Invalid
538 Return "Check your Username/Password."
539 Case HttpStatusCode.NotFound
542 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
547 Public Function PostRetweet(ByVal id As Long, ByVal read As Boolean) As String
548 If _endingFlag Then Return ""
549 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
552 Dim target As Long = id
553 If TabInformations.GetInstance.Item(id).RetweetedId > 0 Then
554 target = TabInformations.GetInstance.Item(id).RetweetedId '再RTの場合は元発言をRT
557 Dim res As HttpStatusCode
558 Dim content As String = ""
560 res = twCon.RetweetStatus(target, content)
561 Catch ex As Exception
562 Return "Err:" + ex.Message
566 Case HttpStatusCode.Unauthorized
567 Twitter.AccountState = ACCOUNT_STATE.Invalid
568 Return "Check your Username/Password."
569 Case Is <> HttpStatusCode.OK
570 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
573 Twitter.AccountState = ACCOUNT_STATE.Valid
575 'Dim dlgt As GetIconImageDelegate 'countQueryに合わせる
576 'Dim ar As IAsyncResult 'countQueryに合わせる
577 Dim xdoc As New XmlDocument
579 xdoc.LoadXml(content)
580 Catch ex As Exception
582 'MessageBox.Show("不正なXMLです。(TL-LoadXml)")
583 Return "Invalid XML!"
587 Dim xentryNode As XmlNode = xdoc.DocumentElement.SelectSingleNode("/status")
588 If xentryNode Is Nothing Then Return "Invalid XML!"
589 Dim xentry As XmlElement = CType(xentryNode, XmlElement)
590 Dim post As New PostClass
592 post.Id = Long.Parse(xentry.Item("id").InnerText)
595 If TabInformations.GetInstance.ContainsKey(post.Id) Then Return ""
598 Dim xRnode As XmlNode = xentry.SelectSingleNode("./retweeted_status")
599 If xRnode Is Nothing Then Return "Invalid XML!"
601 Dim xRentry As XmlElement = CType(xRnode, XmlElement)
602 post.PDate = DateTime.ParseExact(xRentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
604 post.RetweetedId = Long.Parse(xRentry.Item("id").InnerText)
606 post.Data = xRentry.Item("text").InnerText
607 'Source取得(htmlの場合は、中身を取り出し)
608 post.Source = xRentry.Item("source").InnerText
610 Long.TryParse(xRentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
611 post.InReplyToUser = xRentry.Item("in_reply_to_screen_name").InnerText
612 post.IsFav = TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.RetweetedId)
615 Dim xRUentry As XmlElement = CType(xRentry.SelectSingleNode("./user"), XmlElement)
616 post.Uid = Long.Parse(xRUentry.Item("id").InnerText)
617 post.Name = xRUentry.Item("screen_name").InnerText
618 post.Nickname = xRUentry.Item("name").InnerText
619 post.ImageUrl = xRUentry.Item("profile_image_url").InnerText
620 post.IsProtect = Boolean.Parse(xRUentry.Item("protected").InnerText)
624 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
625 post.RetweetedBy = xUentry.Item("screen_name").InnerText
628 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
629 post.Data = HttpUtility.HtmlDecode(post.Data)
630 post.Data = post.Data.Replace("<3", "♡")
635 post.IsReply = post.ReplyToList.Contains(_uid)
636 post.IsExcludeReply = False
641 If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.Uid)
643 If post.IsMe AndAlso _readOwnPost Then post.IsRead = True
646 Catch ex As Exception
648 'MessageBox.Show("不正なXMLです。(TL-Parse)")
649 Return "Invalid XML!"
652 'Me._dIcon.Add(post.ImageUrl, Nothing)
653 TabInformations.GetInstance.AddPost(post)
655 ''非同期アイコン取得&StatusDictionaryに追加
656 'dlgt = New GetIconImageDelegate(AddressOf GetIconImage)
657 'ar = dlgt.BeginInvoke(post, Nothing, Nothing)
662 'Catch ex As Exception
663 ' '最後までendinvoke回す(ゾンビ化回避)
664 ' ex.Data("IsTerminatePermission") = False
671 Public Function RemoveDirectMessage(ByVal id As Long, ByVal post As PostClass) As String
672 If _endingFlag Then Return ""
674 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
676 Dim res As HttpStatusCode
679 _deletemessages.Add(post)
682 res = twCon.DestroyDirectMessage(id)
683 Catch ex As Exception
684 Return "Err:" + ex.Message
688 Case HttpStatusCode.OK
689 Twitter.AccountState = ACCOUNT_STATE.Valid
691 Case HttpStatusCode.Unauthorized
692 Twitter.AccountState = ACCOUNT_STATE.Invalid
693 Return "Check your Username/Password."
694 Case HttpStatusCode.NotFound
697 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
701 Public Function PostFollowCommand(ByVal screenName As String) As String
703 If _endingFlag Then Return ""
705 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
707 Dim res As HttpStatusCode
708 Dim content As String = ""
711 res = twCon.CreateFriendships(screenName, content)
712 Catch ex As Exception
713 Return "Err:" + ex.Message
717 Case HttpStatusCode.OK
718 Twitter.AccountState = ACCOUNT_STATE.Valid
720 Case HttpStatusCode.Unauthorized
721 Twitter.AccountState = ACCOUNT_STATE.Invalid
722 Return "Check your Username/Password."
723 Case HttpStatusCode.Forbidden
724 Dim xd As XmlDocument = New XmlDocument
727 Dim xNode As XmlNode = Nothing
728 xNode = xd.SelectSingleNode("/hash/error")
729 Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
730 Catch ex As Exception
731 Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
734 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
738 Public Function PostRemoveCommand(ByVal screenName As String) As String
740 If _endingFlag Then Return ""
742 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
744 Dim res As HttpStatusCode
745 Dim content As String = ""
748 res = twCon.DestroyFriendships(screenName, content)
749 Catch ex As Exception
750 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
754 Case HttpStatusCode.OK
755 Twitter.AccountState = ACCOUNT_STATE.Valid
757 Case HttpStatusCode.Unauthorized
758 Twitter.AccountState = ACCOUNT_STATE.Invalid
759 Return "Check your Username/Password."
760 Case HttpStatusCode.Forbidden
761 Dim xd As XmlDocument = New XmlDocument
764 Dim xNode As XmlNode = Nothing
765 xNode = xd.SelectSingleNode("/hash/error")
766 Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
767 Catch ex As Exception
768 Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
771 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
775 Public Function PostCreateBlock(ByVal screenName As String) As String
777 If _endingFlag Then Return ""
779 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
781 Dim res As HttpStatusCode
782 Dim content As String = ""
785 res = twCon.CreateBlock(screenName, content)
786 Catch ex As Exception
787 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
791 Case HttpStatusCode.OK
792 Twitter.AccountState = ACCOUNT_STATE.Valid
794 Case HttpStatusCode.Unauthorized
795 Twitter.AccountState = ACCOUNT_STATE.Invalid
796 Return "Check your Username/Password."
797 Case HttpStatusCode.Forbidden
798 Dim xd As XmlDocument = New XmlDocument
801 Dim xNode As XmlNode = Nothing
802 xNode = xd.SelectSingleNode("/hash/error")
803 Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
804 Catch ex As Exception
805 Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
808 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
812 Public Function PostDestroyBlock(ByVal screenName As String) As String
814 If _endingFlag Then Return ""
816 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
818 Dim res As HttpStatusCode
819 Dim content As String = ""
822 res = twCon.DestroyBlock(screenName, content)
823 Catch ex As Exception
824 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
828 Case HttpStatusCode.OK
829 Twitter.AccountState = ACCOUNT_STATE.Valid
831 Case HttpStatusCode.Unauthorized
832 Twitter.AccountState = ACCOUNT_STATE.Invalid
833 Return "Check your Username/Password."
834 Case HttpStatusCode.Forbidden
835 Dim xd As XmlDocument = New XmlDocument
838 Dim xNode As XmlNode = Nothing
839 xNode = xd.SelectSingleNode("/hash/error")
840 Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
841 Catch ex As Exception
842 Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
845 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
849 Public Function PostReportSpam(ByVal screenName As String) As String
851 If _endingFlag Then Return ""
853 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
855 Dim res As HttpStatusCode
856 Dim content As String = ""
859 res = twCon.ReportSpam(screenName, content)
860 Catch ex As Exception
861 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
865 Case HttpStatusCode.OK
866 Twitter.AccountState = ACCOUNT_STATE.Valid
868 Case HttpStatusCode.Unauthorized
869 Twitter.AccountState = ACCOUNT_STATE.Invalid
870 Return "Check your Username/Password."
871 Case HttpStatusCode.Forbidden
872 Dim xd As XmlDocument = New XmlDocument
875 Dim xNode As XmlNode = Nothing
876 xNode = xd.SelectSingleNode("/hash/error")
877 Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
878 Catch ex As Exception
879 Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
882 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
886 Public Function GetFriendshipInfo(ByVal screenName As String, ByRef isFollowing As Boolean, ByRef isFollowed As Boolean) As String
888 If _endingFlag Then Return ""
890 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
892 Dim res As HttpStatusCode
893 Dim content As String = ""
895 res = twCon.ShowFriendships(_uid, screenName, content)
896 Catch ex As Exception
897 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
901 Case HttpStatusCode.OK
902 Dim xdoc As New XmlDocument
903 Dim result As String = ""
904 Twitter.AccountState = ACCOUNT_STATE.Valid
906 xdoc.LoadXml(content)
907 isFollowing = Boolean.Parse(xdoc.SelectSingleNode("/relationship/source/following").InnerText)
908 isFollowed = Boolean.Parse(xdoc.SelectSingleNode("/relationship/source/followed_by").InnerText)
909 Catch ex As Exception
910 result = "Err:Invalid XML."
913 Case HttpStatusCode.BadRequest
914 Return "Err:API Limits?"
915 Case HttpStatusCode.Unauthorized
916 Twitter.AccountState = ACCOUNT_STATE.Invalid
917 Return "Check your Username/Password."
919 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
923 Public Function GetUserInfo(ByVal screenName As String, ByRef user As TwitterDataModel.User) As String
925 If _endingFlag Then Return ""
927 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
929 Dim res As HttpStatusCode
930 Dim content As String = ""
933 res = twCon.ShowUserInfo(screenName, content)
934 Catch ex As Exception
935 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
939 Case HttpStatusCode.OK
940 Twitter.AccountState = ACCOUNT_STATE.Valid
942 user = CreateDataFromJson(Of TwitterDataModel.User)(content)
943 Catch ex As SerializationException
944 TraceOut(ex.Message + Environment.NewLine + content)
945 Return "Err:Json Parse Error(DataContractJsonSerializer)"
946 Catch ex As Exception
948 Return "Err:Invalid Json!"
951 Case HttpStatusCode.BadRequest
952 Return "Err:API Limits?"
953 Case HttpStatusCode.Unauthorized
954 Twitter.AccountState = ACCOUNT_STATE.Invalid
955 Dim errMsg As String = GetErrorMessageJson(content)
956 If String.IsNullOrEmpty(errMsg) Then
957 Return "Check your Username/Password."
959 Return "Auth err:" + errMsg
962 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
966 Public Function GetStatus_Retweeted_Count(ByVal StatusId As Long, ByRef retweeted_count As Integer) As String
968 If _endingFlag Then Return ""
970 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
972 Dim res As HttpStatusCode
973 Dim content As String = ""
974 Dim xmlBuf As String = ""
978 ' 注:dev.twitter.comに記述されているcountパラメータは間違い。100が正しい
979 For i As Integer = 1 To 100
982 res = twCon.Statusid_retweeted_by_ids(StatusId, 100, i, content)
983 Catch ex As Exception
984 Return "Err:" + ex.Message
988 Case HttpStatusCode.OK
989 Dim xdoc As New XmlDocument
990 Dim xnode As XmlNodeList
991 Dim result As String = ""
992 Twitter.AccountState = ACCOUNT_STATE.Valid
994 xdoc.LoadXml(content)
995 xnode = xdoc.GetElementsByTagName("ids")
996 retweeted_count += xnode.ItemOf(0).ChildNodes.Count
997 If xnode.ItemOf(0).ChildNodes.Count < 100 Then Exit For
998 Catch ex As Exception
1000 result = "Err:Invalid XML."
1003 Case HttpStatusCode.BadRequest
1004 retweeted_count = -1
1005 Return "Err:API Limits?"
1006 Case HttpStatusCode.Unauthorized
1007 retweeted_count = -1
1008 Twitter.AccountState = ACCOUNT_STATE.Invalid
1009 Return "Check your Username/Password."
1011 retweeted_count = -1
1012 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1018 Public Function PostFavAdd(ByVal id As Long) As String
1019 If _endingFlag Then Return ""
1021 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1023 Dim res As HttpStatusCode
1024 Dim content As String = ""
1026 res = twCon.CreateFavorites(id, content)
1027 Catch ex As Exception
1028 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
1032 Case HttpStatusCode.OK
1033 Twitter.AccountState = ACCOUNT_STATE.Valid
1034 If Not _restrictFavCheck Then Return ""
1035 Case HttpStatusCode.Unauthorized
1036 Twitter.AccountState = ACCOUNT_STATE.Invalid
1037 Return "Check your Username/Password."
1038 Case HttpStatusCode.Forbidden
1039 Dim xd As XmlDocument = New XmlDocument
1042 Dim xNode As XmlNode = Nothing
1043 xNode = xd.SelectSingleNode("/hash/error")
1044 Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
1045 Catch ex As Exception
1046 Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
1049 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1052 'http://twitter.com/statuses/show/id.xml APIを発行して本文を取得
1054 'Dim content As String = ""
1057 res = twCon.ShowStatuses(id, content)
1058 Catch ex As Exception
1059 Return "Err:" + ex.Message
1063 Case HttpStatusCode.OK
1064 Twitter.AccountState = ACCOUNT_STATE.Valid
1066 Using rd As Xml.XmlTextReader = New Xml.XmlTextReader(New System.IO.StringReader(content))
1068 While rd.EOF = False
1069 If rd.IsStartElement("favorited") Then
1070 If rd.ReadElementContentAsBoolean() = True Then
1071 Return "" '正常にふぁぼれている
1073 Return "NG(Restricted?)" '正常応答なのにふぁぼれてないので制限っぽい
1080 Return "Err:Invalid XML!"
1082 Catch ex As XmlException
1085 Case HttpStatusCode.Unauthorized
1086 Twitter.AccountState = ACCOUNT_STATE.Invalid
1087 Return "Check your Username/Password."
1088 Case HttpStatusCode.BadRequest
1089 Return "Err:API Limits?"
1091 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1096 Public Function PostFavRemove(ByVal id As Long) As String
1097 If _endingFlag Then Return ""
1099 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1101 Dim res As HttpStatusCode
1102 Dim content As String = ""
1104 res = twCon.DestroyFavorites(id, content)
1105 Catch ex As Exception
1106 Return "Err:" + ex.Message
1110 Case HttpStatusCode.OK
1111 Twitter.AccountState = ACCOUNT_STATE.Valid
1113 Case HttpStatusCode.Unauthorized
1114 Twitter.AccountState = ACCOUNT_STATE.Invalid
1115 Return "Check your Username/Password."
1116 Case HttpStatusCode.Forbidden
1117 Dim xd As XmlDocument = New XmlDocument
1120 Dim xNode As XmlNode = Nothing
1121 xNode = xd.SelectSingleNode("/hash/error")
1122 Return "Err:" + xNode.InnerText
1123 Catch ex As Exception
1124 Return "Err:Forbidden"
1127 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1131 Public Function PostUpdateProfile(ByVal name As String, ByVal url As String, ByVal location As String, ByVal description As String) As String
1132 If _endingFlag Then Return ""
1134 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1136 Dim res As HttpStatusCode
1137 Dim content As String = ""
1139 res = twCon.UpdateProfile(name, url, location, description, content)
1140 Catch ex As Exception
1141 Return "Err:" + ex.Message
1145 Case HttpStatusCode.OK
1146 Twitter.AccountState = ACCOUNT_STATE.Valid
1148 Case HttpStatusCode.Unauthorized
1149 Twitter.AccountState = ACCOUNT_STATE.Invalid
1150 Return "Check your Username/Password."
1151 Case HttpStatusCode.Forbidden
1152 Dim xd As XmlDocument = New XmlDocument
1155 Dim xNode As XmlNode = Nothing
1156 xNode = xd.SelectSingleNode("/hash/error")
1157 Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
1158 Catch ex As Exception
1159 Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
1162 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1166 Public Function PostUpdateProfileImage(ByVal filename As String) As String
1167 If _endingFlag Then Return ""
1169 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1171 Dim res As HttpStatusCode
1172 Dim content As String = ""
1174 res = twCon.UpdateProfileImage(New FileInfo(filename), content)
1175 Catch ex As Exception
1176 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
1180 Case HttpStatusCode.OK
1181 Twitter.AccountState = ACCOUNT_STATE.Valid
1183 Case HttpStatusCode.Unauthorized
1184 Twitter.AccountState = ACCOUNT_STATE.Invalid
1185 Return "Check your Username/Password."
1186 Case HttpStatusCode.Forbidden
1187 Dim xd As XmlDocument = New XmlDocument
1190 Dim xNode As XmlNode = Nothing
1191 xNode = xd.SelectSingleNode("/hash/error")
1192 Return "Err:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
1193 Catch ex As Exception
1194 Return "Err:Forbidden" + "(" + GetCurrentMethod.Name + ")"
1197 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1201 Public ReadOnly Property Username() As String
1203 Return twCon.AuthenticatedUsername
1207 Public ReadOnly Property Password() As String
1209 Return twCon.Password
1213 Private Shared _accountState As ACCOUNT_STATE = ACCOUNT_STATE.Valid
1214 Public Shared Property AccountState() As ACCOUNT_STATE
1216 Return _accountState
1218 Set(ByVal value As ACCOUNT_STATE)
1219 _accountState = value
1223 Public WriteOnly Property GetIcon() As Boolean
1224 Set(ByVal value As Boolean)
1229 Public WriteOnly Property TinyUrlResolve() As Boolean
1230 Set(ByVal value As Boolean)
1231 _tinyUrlResolve = value
1235 Public WriteOnly Property RestrictFavCheck() As Boolean
1236 Set(ByVal value As Boolean)
1237 _restrictFavCheck = value
1241 Public WriteOnly Property IconSize() As Integer
1242 Set(ByVal value As Integer)
1248 Public Function GetVersionInfo() As String
1249 Dim content As String = ""
1250 If Not (New HttpVarious).GetData("http://tween.sourceforge.jp/version2.txt?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), Nothing, content) Then
1251 Throw New Exception("GetVersionInfo Failed")
1256 Public Function GetTweenBinary(ByVal strVer As String) As String
1258 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/Tween" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1259 Path.Combine(Application.StartupPath(), "TweenNew.exe")) Then
1260 Return "Err:Download failed"
1262 If Directory.Exists(Path.Combine(Application.StartupPath(), "en")) = False Then
1263 Directory.CreateDirectory(Path.Combine(Application.StartupPath(), "en"))
1265 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenRes" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1266 Path.Combine(Application.StartupPath(), "en\Tween.resourcesNew.dll")) Then
1267 Return "Err:Download failed"
1269 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenUp.gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1270 Path.Combine(Application.StartupPath(), "TweenUp.exe")) Then
1271 Return "Err:Download failed"
1273 If Not (New HttpVarious).GetDataToFile("http://tween.sourceforge.jp/TweenDll" + strVer + ".gz?" + Now.ToString("yyMMddHHmmss") + Environment.TickCount.ToString(), _
1274 Path.Combine(Application.StartupPath(), "TweenNew.XmlSerializers.dll")) Then
1275 Return "Err:Download failed"
1278 Catch ex As Exception
1279 Return "Err:Download failed"
1284 Public Property DetailIcon() As IDictionary(Of String, Image)
1288 Set(ByVal value As IDictionary(Of String, Image))
1293 'Public WriteOnly Property CountApi() As Integer
1295 ' Set(ByVal value As Integer)
1300 'Public WriteOnly Property CountApiReply() As Integer
1301 ' 'API時のMentions取得件数
1302 ' Set(ByVal value As Integer)
1303 ' _countApiReply = value
1307 Public Property ReadOwnPost() As Boolean
1311 Set(ByVal value As Boolean)
1312 _readOwnPost = value
1316 Public ReadOnly Property FollowersCount() As Integer
1318 Return _followersCount
1322 Public ReadOnly Property FriendsCount() As Integer
1324 Return _friendsCount
1328 Public ReadOnly Property StatusesCount() As Integer
1330 Return _statusesCount
1334 Public ReadOnly Property Location() As String
1340 Public ReadOnly Property Bio() As String
1346 Public WriteOnly Property UseSsl() As Boolean
1347 Set(ByVal value As Boolean)
1348 HttpTwitter.UseSsl = value
1350 _protocol = "https://"
1352 _protocol = "http://"
1357 Public Function GetTimelineApi(ByVal read As Boolean, _
1358 ByVal gType As WORKERTYPE, _
1359 ByVal more As Boolean, _
1360 ByVal startup As Boolean) As String
1362 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1364 If _endingFlag Then Return ""
1366 Dim res As HttpStatusCode
1367 Dim content As String = ""
1368 Dim count As Integer = Setting.Instance.CountApi
1369 If gType = WORKERTYPE.Reply Then count = Setting.Instance.CountApiReply
1370 If Setting.Instance.UseAdditionalCount Then
1371 If more AndAlso Setting.Instance.MoreCountApi <> 0 Then
1372 count = Setting.Instance.MoreCountApi
1373 ElseIf startup AndAlso Setting.Instance.FirstCountApi <> 0 AndAlso gType = WORKERTYPE.Timeline Then
1374 count = Setting.Instance.FirstCountApi
1378 If gType = WORKERTYPE.Timeline Then
1380 res = twCon.HomeTimeline(count, Me.minHomeTimeline, 0, content)
1382 res = twCon.HomeTimeline(count, 0, 0, content)
1386 res = twCon.Mentions(count, Me.minMentions, 0, content)
1388 res = twCon.Mentions(count, 0, 0, content)
1391 Catch ex As Exception
1392 Return "Err:" + ex.Message
1395 Case HttpStatusCode.OK
1396 Twitter.AccountState = ACCOUNT_STATE.Valid
1397 Case HttpStatusCode.Unauthorized
1398 Twitter.AccountState = ACCOUNT_STATE.Invalid
1399 Return "Check your Username/Password."
1400 Case HttpStatusCode.BadRequest
1401 Return "Err:API Limits?"
1403 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1406 If gType = WORKERTYPE.Timeline Then
1407 Return CreatePostsFromJson(content, gType, Nothing, read, count, Me.minHomeTimeline)
1409 Return CreatePostsFromJson(content, gType, Nothing, read, count, Me.minMentions)
1413 Public Function GetUserTimelineApi(ByVal read As Boolean,
1414 ByVal count As Integer,
1415 ByVal userName As String,
1416 ByVal tab As TabClass) As String
1418 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1420 If _endingFlag Then Return ""
1422 Dim res As HttpStatusCode
1423 Dim content As String = ""
1425 If count = 0 Then count = 20
1427 If String.IsNullOrEmpty(userName) Then
1428 Dim target As PostClass = tab.RelationTargetPost
1429 If target Is Nothing Then Return ""
1430 res = twCon.UserTimeline(target.Uid, "", count, 0, 0, content)
1432 res = twCon.UserTimeline(0, userName, count, 0, 0, content)
1434 Catch ex As Exception
1435 Return "Err:" + ex.Message
1438 Case HttpStatusCode.OK
1439 Twitter.AccountState = ACCOUNT_STATE.Valid
1440 Case HttpStatusCode.Unauthorized
1441 Twitter.AccountState = ACCOUNT_STATE.Invalid
1442 Return "Check your Username/Password."
1443 Case HttpStatusCode.BadRequest
1444 Return "Err:API Limits?"
1446 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1449 Dim items As List(Of TwitterDataModel.Status)
1451 items = CreateDataFromJson(Of List(Of TwitterDataModel.Status))(content)
1452 Catch ex As SerializationException
1453 TraceOut(ex.Message + Environment.NewLine + content)
1454 Return "Json Parse Error(DataContractJsonSerializer)"
1455 Catch ex As Exception
1457 Return "Invalid Json!"
1460 For Each status As TwitterDataModel.Status In items
1461 Dim item As PostClass = CreatePostsFromStatusData(status)
1462 If item Is Nothing Then Continue For
1464 If item.IsMe AndAlso Not read AndAlso _readOwnPost Then item.IsRead = True
1465 If tab IsNot Nothing Then item.RelTabName = tab.TabName
1466 '非同期アイコン取得&StatusDictionaryに追加
1467 TabInformations.GetInstance.AddPost(item)
1473 Private Function CreatePostsFromStatusData(ByVal status As TwitterDataModel.Status) As PostClass
1474 Dim post As New PostClass
1477 If status.RetweetedStatus IsNot Nothing Then
1478 Dim retweeted As TwitterDataModel.RetweetedStatus = status.RetweetedStatus
1480 post.PDate = DateTimeParse(retweeted.CreatedAt)
1483 post.RetweetedId = retweeted.Id
1485 post.Data = retweeted.Text
1486 'Source取得(htmlの場合は、中身を取り出し)
1487 post.Source = retweeted.Source
1489 Long.TryParse(retweeted.InReplyToStatusId, post.InReplyToId)
1490 post.InReplyToUser = retweeted.InReplyToScreenName
1491 post.IsFav = TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.RetweetedId)
1494 Dim user As TwitterDataModel.User = retweeted.User
1497 post.Name = user.ScreenName
1498 post.Nickname = user.Name
1499 post.ImageUrl = user.ProfileImageUrl
1500 post.IsProtect = user.Protected
1501 If post.IsMe Then _UserIdNo = post.Uid.ToString()
1504 post.RetweetedBy = status.User.ScreenName
1506 post.PDate = DateTimeParse(status.CreatedAt)
1508 post.Data = status.Text
1509 'Source取得(htmlの場合は、中身を取り出し)
1510 post.Source = status.Source
1511 Long.TryParse(status.InReplyToStatusId, post.InReplyToId)
1512 post.InReplyToUser = status.InReplyToScreenName
1514 post.IsFav = status.Favorited
1517 Dim user As TwitterDataModel.User = status.User
1520 post.Name = user.ScreenName
1521 post.Nickname = user.Name
1522 post.ImageUrl = user.ProfileImageUrl
1523 post.IsProtect = user.Protected
1524 post.IsMe = post.Name.ToLower.Equals(_uid)
1525 If post.IsMe Then _UserIdNo = post.Uid.ToString
1528 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
1529 post.Data = HttpUtility.HtmlDecode(post.Data)
1530 post.Data = post.Data.Replace("<3", "♡")
1534 post.IsReply = post.ReplyToList.Contains(_uid)
1535 post.IsExcludeReply = False
1540 If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.Uid)
1547 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
1548 Dim items As List(Of TwitterDataModel.Status)
1550 items = CreateDataFromJson(Of List(Of TwitterDataModel.Status))(content)
1551 Catch ex As SerializationException
1552 TraceOut(ex.Message + Environment.NewLine + content)
1553 Return "Json Parse Error(DataContractJsonSerializer)"
1554 Catch ex As Exception
1556 Return "Invalid Json!"
1559 For Each status As TwitterDataModel.Status In items
1560 Dim post As PostClass = Nothing
1562 post = CreatePostsFromStatusData(status)
1564 If minimumId > post.Id Then minimumId = post.Id
1567 If tab Is Nothing Then
1568 If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
1570 If TabInformations.GetInstance.ContainsKey(post.Id, tab.TabName) Then Continue For
1575 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
1577 If tab IsNot Nothing Then post.RelTabName = tab.TabName
1578 '非同期アイコン取得&StatusDictionaryに追加
1579 TabInformations.GetInstance.AddPost(post)
1585 Public Overloads Function GetListStatus(ByVal read As Boolean, _
1586 ByVal tab As TabClass, _
1587 ByVal more As Boolean, _
1588 ByVal startup As Boolean) As String
1590 If _endingFlag Then Return ""
1592 Dim res As HttpStatusCode
1593 Dim content As String = ""
1594 Dim page As Integer = 0
1595 Dim count As Integer = Setting.Instance.CountApi
1596 If Setting.Instance.UseAdditionalCount Then
1597 If more AndAlso Setting.Instance.MoreCountApi <> 0 Then
1598 count = Setting.Instance.MoreCountApi
1599 ElseIf startup AndAlso Setting.Instance.FirstCountApi <> 0 Then
1600 count = Setting.Instance.FirstCountApi
1605 res = twCon.GetListsStatuses(tab.ListInfo.UserId.ToString, tab.ListInfo.Id.ToString, count, tab.OldestId, 0, content)
1607 res = twCon.GetListsStatuses(tab.ListInfo.UserId.ToString, tab.ListInfo.Id.ToString, count, 0, 0, content)
1609 Catch ex As Exception
1610 Return "Err:" + ex.Message
1613 Case HttpStatusCode.OK
1614 Twitter.AccountState = ACCOUNT_STATE.Valid
1615 Case HttpStatusCode.Unauthorized
1616 Twitter.AccountState = ACCOUNT_STATE.Invalid
1617 Return "Check your Username/Password."
1618 Case HttpStatusCode.BadRequest
1619 Return "Err:API Limits?"
1621 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1624 Return CreatePostsFromXml(content, WORKERTYPE.List, tab, read, count, tab.OldestId)
1627 Public Function GetRelatedResultsApi(ByVal read As Boolean, _
1628 ByVal tab As TabClass) As String
1630 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
1632 If _endingFlag Then Return ""
1634 Dim res As HttpStatusCode
1635 Dim content As String = ""
1637 res = twCon.GetRelatedResults(tab.RelationTargetPost.Id, content)
1638 Catch ex As Exception
1639 Return "Err:" + ex.Message
1642 Case HttpStatusCode.OK
1643 Twitter.AccountState = ACCOUNT_STATE.Valid
1644 Case HttpStatusCode.Unauthorized
1645 Twitter.AccountState = ACCOUNT_STATE.Invalid
1646 Return "Check your Username/Password."
1647 Case HttpStatusCode.BadRequest
1648 Return "Err:API Limits?"
1650 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
1653 Dim targetItem As PostClass = tab.RelationTargetPost
1654 If targetItem Is Nothing Then
1657 targetItem = targetItem.Copy()
1659 targetItem.RelTabName = tab.TabName
1660 TabInformations.GetInstance.AddPost(targetItem)
1662 Dim replyToItem As PostClass = Nothing
1663 Dim replyToUserName As String = targetItem.InReplyToUser
1664 If targetItem.InReplyToId > 0 AndAlso TabInformations.GetInstance.Item(targetItem.InReplyToId) IsNot Nothing Then
1665 replyToItem = TabInformations.GetInstance.Item(targetItem.InReplyToId).Copy
1666 replyToItem.RelTabName = tab.TabName
1669 Dim items As List(Of TwitterDataModel.RelatedResult)
1671 items = CreateDataFromJson(Of List(Of TwitterDataModel.RelatedResult))(content)
1672 Catch ex As SerializationException
1673 TraceOut(ex.Message + Environment.NewLine + content)
1674 Return "Json Parse Error(DataContractJsonSerializer)"
1675 Catch ex As Exception
1677 Return "Invalid Json!"
1680 For Each relatedData As TwitterDataModel.RelatedResult In items
1681 For Each result As TwitterDataModel.RelatedTweet In relatedData.Results
1682 Dim item As PostClass = CreatePostsFromStatusData(result.Status)
1683 If item Is Nothing Then Continue For
1684 If targetItem.InReplyToId = item.Id Then replyToItem = Nothing
1686 If item.IsMe AndAlso Not read AndAlso _readOwnPost Then item.IsRead = True
1687 If tab IsNot Nothing Then item.RelTabName = tab.TabName
1688 '非同期アイコン取得&StatusDictionaryに追加
1689 TabInformations.GetInstance.AddPost(item)
1693 '発言者・返信先ユーザーの直近10発言取得
1694 'Dim rslt As String = Me.GetUserTimelineApi(read, 10, "", tab)
1695 'If Not String.IsNullOrEmpty(rslt) Then Return rslt
1696 'If Not String.IsNullOrEmpty(replyToUserName) Then
1697 ' rslt = Me.GetUserTimelineApi(read, 10, replyToUserName, tab)
1703 Private Function CreatePostsFromXml(ByVal content As String, ByVal gType As WORKERTYPE, ByVal tab As TabClass, ByVal read As Boolean, ByVal count As Integer, ByRef minimumId As Long) As String
1704 Dim xdoc As New XmlDocument
1706 xdoc.LoadXml(content)
1707 Catch ex As Exception
1709 'MessageBox.Show("不正なXMLです。(TL-LoadXml)")
1710 Return "Invalid XML!"
1713 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("./status")
1714 Dim xentry As XmlElement = CType(xentryNode, XmlElement)
1715 Dim post As New PostClass
1717 post.Id = Long.Parse(xentry.Item("id").InnerText)
1718 If minimumId > post.Id Then minimumId = post.Id
1721 If tab Is Nothing Then
1722 If TabInformations.GetInstance.ContainsKey(post.Id) Then Continue For
1724 If TabInformations.GetInstance.ContainsKey(post.Id, tab.TabName) Then Continue For
1728 Dim xRnode As XmlNode = xentry.SelectSingleNode("./retweeted_status")
1729 If xRnode IsNot Nothing Then
1730 Dim xRentry As XmlElement = CType(xRnode, XmlElement)
1731 post.PDate = DateTime.ParseExact(xRentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
1733 post.RetweetedId = Long.Parse(xRentry.Item("id").InnerText)
1735 post.Data = xRentry.Item("text").InnerText
1736 'Source取得(htmlの場合は、中身を取り出し)
1737 post.Source = xRentry.Item("source").InnerText
1739 Long.TryParse(xRentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
1740 post.InReplyToUser = xRentry.Item("in_reply_to_screen_name").InnerText
1741 post.IsFav = TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.RetweetedId)
1742 'post.IsFav = Boolean.Parse(xentry.Item("favorited").InnerText)
1745 Dim xRUentry As XmlElement = CType(xRentry.SelectSingleNode("./user"), XmlElement)
1746 post.Uid = Long.Parse(xRUentry.Item("id").InnerText)
1747 post.Name = xRUentry.Item("screen_name").InnerText
1748 post.Nickname = xRUentry.Item("name").InnerText
1749 post.ImageUrl = xRUentry.Item("profile_image_url").InnerText
1750 post.IsProtect = Boolean.Parse(xRUentry.Item("protected").InnerText)
1751 post.IsMe = post.Name.ToLower.Equals(_uid)
1752 If post.IsMe Then _UserIdNo = post.Uid.ToString()
1755 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
1756 post.RetweetedBy = xUentry.Item("screen_name").InnerText
1758 post.PDate = DateTime.ParseExact(xentry.Item("created_at").InnerText, "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
1760 post.Data = xentry.Item("text").InnerText
1761 'Source取得(htmlの場合は、中身を取り出し)
1762 post.Source = xentry.Item("source").InnerText
1763 Long.TryParse(xentry.Item("in_reply_to_status_id").InnerText, post.InReplyToId)
1764 post.InReplyToUser = xentry.Item("in_reply_to_screen_name").InnerText
1765 'in_reply_to_user_idを使うか?
1766 post.IsFav = Boolean.Parse(xentry.Item("favorited").InnerText)
1769 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./user"), XmlElement)
1770 post.Uid = Long.Parse(xUentry.Item("id").InnerText)
1771 post.Name = xUentry.Item("screen_name").InnerText
1772 post.Nickname = xUentry.Item("name").InnerText
1773 post.ImageUrl = xUentry.Item("profile_image_url").InnerText
1774 post.IsProtect = Boolean.Parse(xUentry.Item("protected").InnerText)
1775 post.IsMe = post.Name.ToLower.Equals(_uid)
1776 If post.IsMe Then _UserIdNo = post.Uid.ToString()
1779 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
1780 post.Data = HttpUtility.HtmlDecode(post.Data)
1781 post.Data = post.Data.Replace("<3", "♡")
1786 If gType = WORKERTYPE.Timeline OrElse tab IsNot Nothing Then
1787 post.IsReply = post.ReplyToList.Contains(_uid)
1791 post.IsExcludeReply = False
1796 If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.Uid)
1798 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
1801 If tab IsNot Nothing Then post.RelTabName = tab.TabName
1802 Catch ex As Exception
1804 'MessageBox.Show("不正なXMLです。(TL-Parse)")
1808 TabInformations.GetInstance.AddPost(post)
1815 Public Function GetSearch(ByVal read As Boolean, _
1816 ByVal tab As TabClass, _
1817 ByVal more As Boolean) As String
1819 If _endingFlag Then Return ""
1821 Dim res As HttpStatusCode
1822 Dim content As String = ""
1823 Dim page As Integer = 0
1824 Dim sinceId As Long = 0
1825 Dim count As Integer = 100
1826 If Setting.Instance.UseAdditionalCount AndAlso
1827 Setting.Instance.SearchCountApi <> 0 Then
1828 count = Setting.Instance.SearchCountApi
1831 page = tab.GetSearchPage(count)
1833 sinceId = tab.SinceId
1837 ' TODO:一時的に40>100件に 件数変更UI作成の必要あり
1838 res = twCon.Search(tab.SearchWords, tab.SearchLang, count, page, sinceId, content)
1839 Catch ex As Exception
1840 Return "Err:" + ex.Message
1843 Case HttpStatusCode.BadRequest
1844 Return "Invalid query"
1845 Case HttpStatusCode.NotFound
1846 Return "Invalid query"
1847 Case HttpStatusCode.PaymentRequired 'API Documentには420と書いてあるが、該当コードがないので402にしてある
1848 Return "Search API Limit?"
1849 Case HttpStatusCode.OK
1851 Return "Err:" + res.ToString + "(" + GetCurrentMethod.Name + ")"
1854 If Not TabInformations.GetInstance.ContainsTab(tab) Then Return ""
1856 Dim xdoc As New XmlDocument
1858 xdoc.LoadXml(content)
1859 Catch ex As Exception
1861 Return "Invalid ATOM!"
1863 Dim nsmgr As New XmlNamespaceManager(xdoc.NameTable)
1864 nsmgr.AddNamespace("search", "http://www.w3.org/2005/Atom")
1865 nsmgr.AddNamespace("twitter", "http://api.twitter.com/")
1866 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/search:feed/search:entry", nsmgr)
1867 Dim xentry As XmlElement = CType(xentryNode, XmlElement)
1868 Dim post As New PostClass
1870 post.Id = Long.Parse(xentry.Item("id").InnerText.Split(":"c)(2))
1871 If TabInformations.GetInstance.ContainsKey(post.Id, tab.TabName) Then Continue For
1872 post.PDate = DateTime.Parse(xentry.Item("published").InnerText)
1874 post.Data = xentry.Item("title").InnerText
1875 'Source取得(htmlの場合は、中身を取り出し)
1876 post.Source = xentry.Item("twitter:source").InnerText
1877 post.InReplyToId = 0
1878 post.InReplyToUser = ""
1882 Dim xUentry As XmlElement = CType(xentry.SelectSingleNode("./search:author", nsmgr), XmlElement)
1884 post.Name = xUentry.Item("name").InnerText.Split(" "c)(0).Trim
1885 post.Nickname = xUentry.Item("name").InnerText.Substring(post.Name.Length).Trim
1886 If post.Nickname.Length > 2 Then
1887 post.Nickname = post.Nickname.Substring(1, post.Nickname.Length - 2)
1889 post.Nickname = post.Name
1891 post.ImageUrl = CType(xentry.SelectSingleNode("./search:link[@type='image/png']", nsmgr), XmlElement).GetAttribute("href")
1892 post.IsProtect = False
1893 post.IsMe = post.Name.ToLower.Equals(_uid)
1896 post.OriginalData = CreateHtmlAnchor(HttpUtility.HtmlEncode(post.Data), post.ReplyToList)
1897 post.Data = HttpUtility.HtmlDecode(post.Data)
1902 post.IsReply = post.ReplyToList.Contains(_uid)
1903 post.IsExcludeReply = False
1906 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
1908 post.RelTabName = tab.TabName
1909 If Not more AndAlso post.Id > tab.SinceId Then tab.SinceId = post.Id
1910 Catch ex As Exception
1915 'Me._dIcon.Add(post.ImageUrl, Nothing)
1916 TabInformations.GetInstance.AddPost(post)
1921 '' 遡るための情報max_idやnext_pageの情報を保持する
1924 Dim xNode As XmlNode = xdoc.DocumentElement.SelectSingleNode("/search:feed/twitter:warning", nsmgr)
1926 If xNode IsNot Nothing Then
1927 Return "Warn:" + xNode.InnerText + "(" + GetCurrentMethod.Name + ")"
1934 Private Function CreateDirectMessagesFromJson(ByVal content As String, ByVal gType As WORKERTYPE, ByVal read As Boolean) As String
1935 Dim item As List(Of TwitterDataModel.Directmessage)
1937 If gType = WORKERTYPE.UserStream Then
1938 Dim itm As List(Of TwitterDataModel.DirectmessageEvent) = CreateDataFromJson(Of List(Of TwitterDataModel.DirectmessageEvent))(content)
1939 item = New List(Of TwitterDataModel.Directmessage)
1940 For Each dat As TwitterDataModel.DirectmessageEvent In itm
1941 item.Add(dat.Directmessage)
1944 item = CreateDataFromJson(Of List(Of TwitterDataModel.Directmessage))(content)
1946 Catch ex As SerializationException
1947 TraceOut(ex.Message + Environment.NewLine + content)
1948 Return "Json Parse Error(DataContractJsonSerializer)"
1949 Catch ex As Exception
1951 Return "Invalid Json!"
1954 For Each message As TwitterDataModel.Directmessage In item
1955 Dim post As New PostClass
1957 post.Id = message.Id
1958 If gType <> WORKERTYPE.UserStream Then
1959 If gType = WORKERTYPE.DirectMessegeRcv Then
1960 If minDirectmessage > post.Id Then minDirectmessage = post.Id
1962 If minDirectmessageSent > post.Id Then minDirectmessageSent = post.Id
1968 If TabInformations.GetInstance.GetTabByType(TabUsageType.DirectMessage).Contains(post.Id) Then Continue For
1972 post.PDate = DateTimeParse(message.CreatedAt)
1974 post.Data = message.Text
1976 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
1977 post.Data = HttpUtility.HtmlDecode(post.Data)
1978 post.Data = post.Data.Replace("<3", "♡")
1982 Dim user As TwitterDataModel.User
1983 If gType = WORKERTYPE.UserStream Then
1984 If twCon.AuthenticatedUsername.Equals(message.Recipient.ScreenName, StringComparison.CurrentCultureIgnoreCase) Then
1985 user = message.Sender
1989 user = message.Recipient
1994 If gType = WORKERTYPE.DirectMessegeRcv Then
1995 user = message.Sender
1999 user = message.Recipient
2006 post.Name = user.ScreenName
2007 post.Nickname = user.Name
2008 post.ImageUrl = user.ProfileImageUrl
2009 post.IsProtect = user.protected
2010 Catch ex As Exception
2012 MessageBox.Show("Parse Error(CreateDirectMessagesFromJson)")
2017 If post.IsMe AndAlso Not read AndAlso _readOwnPost Then post.IsRead = True
2018 post.IsReply = False
2019 post.IsExcludeReply = False
2022 TabInformations.GetInstance.AddPost(post)
2029 Public Function GetDirectMessageApi(ByVal read As Boolean, _
2030 ByVal gType As WORKERTYPE, _
2031 ByVal more As Boolean) As String
2032 If _endingFlag Then Return ""
2034 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2036 Dim res As HttpStatusCode
2037 Dim content As String = ""
2040 If gType = WORKERTYPE.DirectMessegeRcv Then
2042 res = twCon.DirectMessages(20, minDirectmessage, 0, content)
2044 res = twCon.DirectMessages(20, 0, 0, content)
2048 res = twCon.DirectMessagesSent(20, minDirectmessageSent, 0, content)
2050 res = twCon.DirectMessagesSent(20, 0, 0, content)
2053 Catch ex As Exception
2054 Return "Err:" + ex.Message
2058 Case HttpStatusCode.OK
2059 Twitter.AccountState = ACCOUNT_STATE.Valid
2060 Case HttpStatusCode.Unauthorized
2061 Twitter.AccountState = ACCOUNT_STATE.Invalid
2062 Return "Check your Username/Password."
2063 Case HttpStatusCode.BadRequest
2064 Return "Err:API Limits?"
2066 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2069 Return CreateDirectMessagesFromJson(content, gType, read)
2072 Public Function GetFavoritesApi(ByVal read As Boolean, _
2073 ByVal gType As WORKERTYPE) As String
2075 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2077 If _endingFlag Then Return ""
2079 Dim res As HttpStatusCode
2080 Dim content As String = ""
2081 Dim count As Integer = Setting.Instance.CountApi
2082 If Setting.Instance.UseAdditionalCount AndAlso
2083 Setting.Instance.FavoritesCountApi <> 0 Then
2084 count = Setting.Instance.FavoritesCountApi
2087 res = twCon.Favorites(count, content)
2088 Catch ex As Exception
2089 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2093 Case HttpStatusCode.OK
2094 Twitter.AccountState = ACCOUNT_STATE.Valid
2095 Case HttpStatusCode.Unauthorized
2096 Twitter.AccountState = ACCOUNT_STATE.Invalid
2097 Return "Check your Username/Password."
2098 Case HttpStatusCode.BadRequest
2099 Return "Err:API Limits?"
2101 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2104 Dim serializer As New DataContractJsonSerializer(GetType(List(Of TwitterDataModel.Status)))
2105 Dim item As List(Of TwitterDataModel.Status)
2108 item = CreateDataFromJson(Of List(Of TwitterDataModel.Status))(content)
2109 Catch ex As SerializationException
2110 TraceOut(ex.Message + Environment.NewLine + content)
2111 Return "Json Parse Error(DataContractJsonSerializer)"
2112 Catch ex As Exception
2114 Return "Invalid Json!"
2117 For Each status As TwitterDataModel.Status In item
2118 Dim post As New PostClass
2123 If TabInformations.GetInstance.GetTabByType(TabUsageType.Favorites).Contains(post.Id) Then Continue For
2126 If status.RetweetedStatus IsNot Nothing Then
2127 Dim retweeted As TwitterDataModel.RetweetedStatus = status.RetweetedStatus
2128 post.PDate = DateTimeParse(retweeted.CreatedAt)
2131 post.RetweetedId = post.Id
2133 post.Data = retweeted.text
2134 'Source取得(htmlの場合は、中身を取り出し)
2135 post.Source = retweeted.source
2137 Long.TryParse(retweeted.InReplyToStatusId, post.InReplyToId)
2138 post.InReplyToUser = retweeted.InReplyToScreenName
2139 post.IsFav = retweeted.favorited
2142 Dim user As TwitterDataModel.User = retweeted.User
2144 post.Name = user.ScreenName
2145 post.Nickname = user.Name
2146 post.ImageUrl = user.ProfileImageUrl
2147 post.IsProtect = user.Protected
2148 post.IsMe = post.Name.ToLower.Equals(_uid)
2149 If post.IsMe Then _UserIdNo = post.Uid.ToString()
2152 post.RetweetedBy = status.User.ScreenName
2154 post.PDate = DateTimeParse(status.CreatedAt)
2157 post.Data = status.Text
2158 'Source取得(htmlの場合は、中身を取り出し)
2159 post.Source = status.Source
2160 Long.TryParse(status.InReplyToStatusId, post.InReplyToId)
2161 post.InReplyToUser = status.InReplyToScreenName
2163 post.IsFav = status.Favorited
2166 Dim user As TwitterDataModel.User = status.User
2168 post.Name = user.ScreenName
2169 post.Nickname = user.Name
2170 post.ImageUrl = user.ProfileImageUrl
2171 post.IsProtect = user.Protected
2172 post.IsMe = post.Name.ToLower.Equals(_uid)
2173 If post.IsMe Then _UserIdNo = post.Uid.ToString
2176 post.OriginalData = CreateHtmlAnchor(post.Data, post.ReplyToList)
2177 post.Data = HttpUtility.HtmlDecode(post.Data)
2178 post.Data = post.Data.Replace("<3", "♡")
2183 post.IsReply = post.ReplyToList.Contains(_uid)
2184 post.IsExcludeReply = False
2189 If followerId.Count > 0 Then post.IsOwl = Not followerId.Contains(post.Uid)
2193 Catch ex As Exception
2198 TabInformations.GetInstance.AddPost(post)
2205 Public Function GetFollowersApi() As String
2206 If _endingFlag Then Return ""
2207 Dim cursor As Long = -1
2208 Dim tmpFollower As New List(Of Long)(followerId)
2212 Dim ret As String = FollowerApi(cursor)
2213 If Not String.IsNullOrEmpty(ret) Then
2215 followerId.AddRange(tmpFollower)
2216 _GetFollowerResult = False
2219 Loop While cursor > 0
2221 TabInformations.GetInstance.RefreshOwl(followerId)
2223 _GetFollowerResult = True
2227 Public ReadOnly Property GetFollowersSuccess() As Boolean
2229 Return _GetFollowerResult
2233 Private Function FollowerApi(ByRef cursor As Long) As String
2234 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2236 Dim res As HttpStatusCode
2237 Dim content As String = ""
2239 res = twCon.FollowerIds(cursor, content)
2240 Catch ex As Exception
2241 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2245 Case HttpStatusCode.OK
2246 Twitter.AccountState = ACCOUNT_STATE.Valid
2247 Case HttpStatusCode.Unauthorized
2248 Twitter.AccountState = ACCOUNT_STATE.Invalid
2249 Return "Check your Username/Password."
2250 Case HttpStatusCode.BadRequest
2251 Return "Err:API Limits?"
2253 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2256 Dim xdoc As New XmlDocument
2258 xdoc.LoadXml(content)
2259 Catch ex As Exception
2261 Return "Invalid XML!"
2265 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/id_list/ids/id")
2266 followerId.Add(Long.Parse(xentryNode.InnerText))
2268 cursor = Long.Parse(xdoc.DocumentElement.SelectSingleNode("/id_list/next_cursor").InnerText)
2269 Catch ex As Exception
2271 Return "Invalid XML!"
2278 Public Function GetListsApi() As String
2279 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2281 Dim res As HttpStatusCode
2282 Dim content As String = ""
2283 Dim cursor As Long = -1
2285 Dim lists As New List(Of ListElement)
2288 res = twCon.GetLists(Me.Username, cursor, content)
2289 Catch ex As Exception
2290 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2294 Case HttpStatusCode.OK
2295 Twitter.AccountState = ACCOUNT_STATE.Valid
2296 Case HttpStatusCode.Unauthorized
2297 Twitter.AccountState = ACCOUNT_STATE.Invalid
2298 Return "Check your Username/Password."
2299 Case HttpStatusCode.BadRequest
2300 Return "Err:API Limits?"
2302 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2305 Dim xdoc As New XmlDocument
2307 xdoc.LoadXml(content)
2308 Catch ex As Exception
2310 Return "Invalid XML!"
2314 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/lists_list/lists/list")
2315 lists.Add(New ListElement(xentryNode, Me))
2317 cursor = Long.Parse(xdoc.DocumentElement.SelectSingleNode("/lists_list/next_cursor").InnerText)
2318 Catch ex As Exception
2320 Return "Invalid XML!"
2322 Loop While cursor <> 0
2328 res = twCon.GetListsSubscriptions(Me.Username, cursor, content)
2329 Catch ex As Exception
2330 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2334 Case HttpStatusCode.OK
2335 Twitter.AccountState = ACCOUNT_STATE.Valid
2336 Case HttpStatusCode.Unauthorized
2337 Twitter.AccountState = ACCOUNT_STATE.Invalid
2338 Return "Check your Username/Password."
2339 Case HttpStatusCode.BadRequest
2340 Return "Err:API Limits?"
2342 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2345 Dim xdoc As New XmlDocument
2347 xdoc.LoadXml(content)
2348 Catch ex As Exception
2350 Return "Invalid XML!"
2354 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/lists_list/lists/list")
2355 lists.Add(New ListElement(xentryNode, Me))
2357 cursor = Long.Parse(xdoc.DocumentElement.SelectSingleNode("/lists_list/next_cursor").InnerText)
2358 Catch ex As Exception
2360 Return "Invalid XML!"
2362 Loop While cursor <> 0
2364 TabInformations.GetInstance.SubscribableLists = lists
2368 Public Function DeleteList(ByVal list_id As String) As String
2369 Dim res As HttpStatusCode
2370 Dim content As String = ""
2373 res = twCon.DeleteListID(Me.Username, list_id, content)
2374 Catch ex As Exception
2375 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2379 Case HttpStatusCode.OK
2380 Twitter.AccountState = ACCOUNT_STATE.Valid
2381 Case HttpStatusCode.Unauthorized
2382 Twitter.AccountState = ACCOUNT_STATE.Invalid
2383 Return "Check your Username/Password."
2384 Case HttpStatusCode.BadRequest
2385 Return "Err:API Limits?"
2387 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2393 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
2394 Dim res As HttpStatusCode
2395 Dim content As String = ""
2396 Dim modeString As String = "public"
2398 modeString = "private"
2402 res = twCon.PostListID(Me.Username, list_id, new_name, modeString, description, content)
2403 Catch ex As Exception
2404 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2408 Case HttpStatusCode.OK
2409 Twitter.AccountState = ACCOUNT_STATE.Valid
2410 Case HttpStatusCode.Unauthorized
2411 Twitter.AccountState = ACCOUNT_STATE.Invalid
2412 Return "Check your Username/Password."
2413 Case HttpStatusCode.BadRequest
2414 Return "Err:API Limits?"
2416 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2419 Dim xdoc As New XmlDocument
2421 xdoc.LoadXml(content)
2422 Dim newList As New ListElement(xdoc.DocumentElement, Me)
2423 list.Description = newList.Description
2424 list.Id = newList.Id
2425 list.IsPublic = newList.IsPublic
2426 list.MemberCount = newList.MemberCount
2427 list.Name = newList.Name
2428 list.SubscriberCount = newList.SubscriberCount
2429 list.Slug = newList.Slug
2430 list.Nickname = newList.Nickname
2431 list.Username = newList.Username
2432 list.UserId = newList.UserId
2433 Catch ex As Exception
2435 Return "Invalid XML!"
2441 Public Function GetListMembers(ByVal list_id As String, ByVal lists As List(Of UserInfo), ByRef cursor As Long) As String
2442 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2444 Dim res As HttpStatusCode
2445 Dim content As String = ""
2446 'Dim cursor As Long = -1
2450 res = twCon.GetListMembers(Me.Username, list_id, cursor, content)
2451 Catch ex As Exception
2452 Return "Err:" + ex.Message
2456 Case HttpStatusCode.OK
2457 Twitter.AccountState = ACCOUNT_STATE.Valid
2458 Case HttpStatusCode.Unauthorized
2459 Twitter.AccountState = ACCOUNT_STATE.Invalid
2460 Return "Check your Username/Password."
2461 Case HttpStatusCode.BadRequest
2462 Return "Err:API Limits?"
2464 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2467 Dim xdoc As New XmlDocument
2469 xdoc.LoadXml(content)
2470 Catch ex As Exception
2472 Return "Invalid XML!"
2476 For Each xentryNode As XmlNode In xdoc.DocumentElement.SelectNodes("/users_list/users/user")
2477 lists.Add(New UserInfo(xentryNode))
2479 cursor = Long.Parse(xdoc.DocumentElement.SelectSingleNode("/users_list/next_cursor").InnerText)
2480 Catch ex As Exception
2482 Return "Invalid XML!"
2484 'Loop While cursor <> 0
2489 Public Function CreateListApi(ByVal listName As String, ByVal isPrivate As Boolean, ByVal description As String) As String
2490 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2492 Dim res As HttpStatusCode
2493 Dim content As String = ""
2496 res = twCon.PostLists(Me.Username, listName, isPrivate, description, content)
2497 Catch ex As Exception
2498 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2502 Case HttpStatusCode.OK
2503 Twitter.AccountState = ACCOUNT_STATE.Valid
2504 Case HttpStatusCode.Unauthorized
2505 Twitter.AccountState = ACCOUNT_STATE.Invalid
2506 Return "Check your Username/Password."
2507 Case HttpStatusCode.BadRequest
2508 Return "Err:API Limits?"
2510 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2513 Dim xdoc As New XmlDocument
2515 xdoc.LoadXml(content)
2517 TabInformations.GetInstance().SubscribableLists.Add(New ListElement(xdoc.DocumentElement, Me))
2518 Catch ex As Exception
2520 Return "Invalid XML!"
2526 Public Function ContainsUserAtList(ByVal list_name As String, ByVal user As String, ByRef value As Boolean) As String
2529 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return ""
2531 Dim res As HttpStatusCode
2532 Dim content As String = ""
2535 res = Me.twCon.GetListMembersID(Me.Username, list_name, user, content)
2536 Catch ex As Exception
2537 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2541 Case HttpStatusCode.OK
2542 Twitter.AccountState = ACCOUNT_STATE.Valid
2543 Case HttpStatusCode.Unauthorized
2544 Twitter.AccountState = ACCOUNT_STATE.Invalid
2545 Return "Check your Username/Password."
2546 Case HttpStatusCode.BadRequest
2547 Return "Err:API Limits?"
2548 Case HttpStatusCode.NotFound
2552 Return "Err:" + res.ToString() + "(" + GetCurrentMethod.Name + ")"
2555 Dim xdoc As New XmlDocument
2557 xdoc.LoadXml(content)
2558 value = xdoc.DocumentElement.Name = "user"
2559 Catch ex As Exception
2561 Return "Invalid XML!"
2567 Public Function AddUserToList(ByVal list_name As String, ByVal user As String) As String
2568 Dim content As String = ""
2569 Dim res As HttpStatusCode
2572 res = twCon.PostListMembers(Me.Username, list_name, user, content)
2573 Catch ex As Exception
2574 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2580 Public Function RemoveUserToList(ByVal list_name As String, ByVal user As String) As String
2581 Dim content As String = ""
2582 Dim res As HttpStatusCode
2585 res = twCon.DeleteListMembers(Me.Username, list_name, user, content)
2586 Catch ex As Exception
2587 Return "Err:" + ex.Message + "(" + GetCurrentMethod.Name + ")"
2594 Public Property fromIndex As Integer
2595 Public Property toIndex As Integer
2596 Public Sub New(ByVal fromIndex As Integer, ByVal toIndex As Integer)
2597 Me.fromIndex = fromIndex
2598 Me.toIndex = toIndex
2601 Public Function CreateHtmlAnchor(ByVal Text As String, ByVal AtList As List(Of String)) As String
2602 Dim retStr As String = Text.Replace(">", "<<<<<tweenだいなり>>>>>").Replace("<", "<<<<<tweenしょうなり>>>>>")
2604 'Const rgUrl As String = "(?<before>(?:[^\""':!=]|^|\:))" + _
2605 ' "(?<url>(?<protocol>https?://|www\.)" + _
2606 ' "(?<domain>(?:[\.-]|[^\p{P}\s])+\.[a-z]{2,}(?::[0-9]+)?)" + _
2607 ' "(?<path>/[a-z0-9!*'();:&=+$/%#\[\]\-_.,~@^]*[a-z0-9)=#/]?)?" + _
2608 ' "(?<query>\?[a-z0-9!*'();:&=+$/%#\[\]\-_.,~]*[a-z0-9_&=#])?)"
2609 Const url_valid_general_path_chars As String = "[a-z0-9!*';:=+$/%#\[\]\-_,~]"
2610 Const url_valid_url_path_ending_chars As String = "[a-z0-9=#/]"
2611 Const pth As String = "(?<path>/(?:(?:\(" + url_valid_general_path_chars + "+\))" +
2612 "|@" + url_valid_general_path_chars + "+/" +
2613 "|[.,]?" + url_valid_general_path_chars +
2615 url_valid_url_path_ending_chars + "?)?"
2616 Const qry As String = "(?<query>\?[a-z0-9!*'();:&=+$/%#\[\]\-_.,~]*[a-z0-9_&=#])?"
2617 Const rgUrl As String = "(?<before>(?:[^\""':!=]|^|\:))" +
2618 "(?<url>(?<protocol>https?://|www\.)" +
2619 "(?<domain>(?:[\.-]|[^\p{P}\s])+\.[a-z]{2,}(?::[0-9]+)?)" +
2624 retStr = Regex.Replace(retStr,
2626 New MatchEvaluator(Function(mu As Match)
2627 Dim sb As New StringBuilder(mu.Result("${before}<a href="""))
2628 If mu.Result("${protocol}").StartsWith("w", StringComparison.OrdinalIgnoreCase) Then
2629 sb.Append("http://")
2631 sb.Append(mu.Result("${url}"">")).Append(mu.Result("${url}")).Append("</a>")
2634 RegexOptions.IgnoreCase)
2637 retStr = Regex.Replace(retStr,
2638 "(^|[^a-zA-Z0-9_/])([@@]+)([a-zA-Z0-9_]{1,20}/[a-zA-Z][a-zA-Z0-9\p{IsLatin-1Supplement}\-]{0,79})",
2639 "$1$2<a href=""/$3"">$3</a>")
2641 Dim m As Match = Regex.Match(retStr, "(^|[^a-zA-Z0-9_])[@@]([a-zA-Z0-9_]{1,20})")
2643 If Not AtList.Contains(m.Result("$2").ToLower) Then AtList.Add(m.Result("$2").ToLower)
2647 retStr = Regex.Replace(retStr,
2648 "(^|[^a-zA-Z0-9_/])([@@])([a-zA-Z0-9_]{1,20})",
2649 "$1$2<a href=""/$3"">$3</a>")
2652 Dim anchorRange As New List(Of range)
2653 For i As Integer = 0 To retStr.Length - 1
2654 Dim index As Integer = retStr.IndexOf("<a ", i)
2655 If index > -1 AndAlso index < retStr.Length Then
2657 Dim toIndex As Integer = retStr.IndexOf("</a>", index)
2658 If toIndex > -1 Then
2659 anchorRange.Add(New range(index, toIndex + 3))
2664 retStr = Regex.Replace(retStr,
2665 "(^|[^a-zA-Z0-9/&])([##])([0-9a-zA-Z_]*[a-zA-Z_]+[a-zA-Z0-9_\xc0-\xd6\xd8-\xf6\xf8-\xff]*)",
2666 New MatchEvaluator(Function(mh As Match)
2667 For Each rng As range In anchorRange
2668 If mh.Index >= rng.fromIndex AndAlso
2669 mh.Index <= rng.toIndex Then Return mh.Result("$0")
2671 If IsNumeric(mh.Result("$3")) Then Return mh.Result("$0")
2673 _hashList.Add("#" + mh.Result("$3"))
2675 Return mh.Result("$1") + "<a href=""" & _protocol & "twitter.com/search?q=%23" + mh.Result("$3") + """>" + mh.Result("$2$3") + "</a>"
2677 RegexOptions.IgnoreCase)
2679 'Dim mhs As MatchCollection = Regex.Matches(retStr, "(^|[^a-zA-Z0-9/&])[##]([0-9a-zA-Z_]*[a-zA-Z_]+[a-zA-Z_\xc0-\xd6\xd8-\xf6\xf8-\xff]*)")
2680 'For Each mt As Match In mhs
2681 ' If Not IsNumeric(mt.Result("$2")) Then
2682 ' 'retStr = retStr.Replace(mt.Result("$1") + mt.Result("$2"), "<a href=""" + _protocol + "twitter.com/search?q=%23" + mt.Result("$2") + """>#" + mt.Result("$2") + "</a>")
2684 ' _hashList.Add("#" + mt.Result("$2"))
2688 'retStr = Regex.Replace(retStr, "(^|[^a-zA-Z0-9/&])([##])([0-9a-zA-Z_]*[a-zA-Z_]+[a-zA-Z0-9_\xc0-\xd6\xd8-\xf6\xf8-\xff]*)", "$1<a href=""" & _protocol & "twitter.com/search?q=%23$3"">$2$3</a>")
2690 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>")
2692 retStr = retStr.Replace("<<<<<tweenだいなり>>>>>", ">").Replace("<<<<<tweenしょうなり>>>>>", "<")
2694 retStr = AdjustHtml(ShortUrl.Resolve(PreProcessUrl(retStr))) 'IDN置換、短縮Uri解決、@リンクを相対→絶対にしてtarget属性付与
2699 Private Sub CreateSource(ByRef post As PostClass)
2700 If post.Source.StartsWith("<") Then
2701 If Not post.Source.Contains("</a>") Then
2702 post.Source += "</a>"
2704 Dim mS As Match = Regex.Match(post.Source, ">(?<source>.+)<")
2706 post.SourceHtml = String.Copy(ShortUrl.Resolve(PreProcessUrl(post.Source)))
2707 post.Source = HttpUtility.HtmlDecode(mS.Result("${source}"))
2710 post.SourceHtml = ""
2713 If post.Source = "web" Then
2714 post.SourceHtml = My.Resources.WebSourceString
2715 ElseIf post.Source = "Keitai Mail" Then
2716 post.SourceHtml = My.Resources.KeitaiMailSourceString
2718 post.SourceHtml = String.Copy(post.Source)
2723 Public Function GetInfoApi(ByVal info As ApiInfo) As Boolean
2724 If Twitter.AccountState <> ACCOUNT_STATE.Valid Then Return True
2726 If _endingFlag Then Return True
2728 Dim res As HttpStatusCode
2729 Dim content As String = ""
2731 res = twCon.RateLimitStatus(content)
2732 Catch ex As Exception
2733 TwitterApiInfo.Initialize()
2737 If res <> HttpStatusCode.OK Then Return False
2739 Dim xdoc As New XmlDocument
2741 xdoc.LoadXml(content)
2742 Dim arg As New ApiInformationChangedEventArgs
2744 arg.ApiInfo.MaxCount = Integer.Parse(xdoc.SelectSingleNode("/hash/hourly-limit").InnerText)
2745 arg.ApiInfo.RemainCount = Integer.Parse(xdoc.SelectSingleNode("/hash/remaining-hits").InnerText)
2746 arg.ApiInfo.ResetTime = DateTime.Parse(xdoc.SelectSingleNode("/hash/reset-time").InnerText)
2747 arg.ApiInfo.ResetTimeInSeconds = Integer.Parse(xdoc.SelectSingleNode("/hash/reset-time-in-seconds").InnerText)
2748 If info IsNot Nothing Then
2749 arg.ApiInfo.UsingCount = info.UsingCount
2751 info.MaxCount = arg.ApiInfo.MaxCount
2752 info.RemainCount = arg.ApiInfo.RemainCount
2753 info.ResetTime = arg.ApiInfo.ResetTime
2754 info.ResetTimeInSeconds = arg.ApiInfo.ResetTimeInSeconds
2757 RaiseEvent ApiInformationChanged(Me, arg)
2758 TwitterApiInfo.WriteBackEventArgs(arg)
2760 Catch ex As Exception
2761 TwitterApiInfo.Initialize()
2766 Public Function GetHashList() As String()
2767 Dim hashArray As String()
2769 hashArray = _hashList.ToArray
2775 Public ReadOnly Property AccessToken() As String
2777 Return twCon.AccessToken
2781 Public ReadOnly Property AccessTokenSecret() As String
2783 Return twCon.AccessTokenSecret
2787 Public Property UserIdNo As String
2789 Public Event ApiInformationChanged(ByVal sender As Object, ByVal e As ApiInformationChangedEventArgs)
2791 Private Sub Twitter_ApiInformationChanged(ByVal sender As Object, ByVal e As ApiInformationChangedEventArgs) Handles Me.ApiInformationChanged
2794 #Region "UserStream"
2795 Public Property TrackWord As String = ""
2796 Public Property AllAtReply As Boolean = False
2798 Public Event NewPostFromStream()
2799 Public Event UserStreamStarted()
2800 Public Event UserStreamStopped()
2801 Public Event UserStreamGetFriendsList()
2802 Public Event PostDeleted(ByVal id As Long, ByRef post As PostClass)
2803 Public Event UserStreamEventReceived(ByVal eventType As FormattedEvent)
2804 Private WithEvents userStream As TwitterUserstream
2806 Public Class FormattedEvent
2807 Public Property CreatedAt As DateTime
2808 Public Property [Event] As String
2809 Public Property Username As String
2810 Public Property Target As String
2814 Public Property StoredEvent As New List(Of FormattedEvent)
2816 Private EventNameTable() As String = {
2820 "list_member_added",
2821 "list_member_removed",
2825 Private Sub userStream_StatusArrived(ByVal line As String) Handles userStream.StatusArrived
2826 If String.IsNullOrEmpty(line) Then Exit Sub
2828 Dim isDm As Boolean = False
2830 Using jsonReader As XmlDictionaryReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(line), XmlDictionaryReaderQuotas.Max)
2831 Dim xElm As XElement = XElement.Load(jsonReader)
2832 If xElm.Element("friends") IsNot Nothing Then
2833 Debug.Print("friends")
2835 ElseIf xElm.Element("delete") IsNot Nothing Then
2836 Debug.Print("delete")
2837 Dim post As PostClass = Nothing
2839 If xElm.Element("delete").Element("direct_message") IsNot Nothing Then
2840 id = CLng(xElm.Element("delete").Element("direct_message").Element("id").Value)
2841 RaiseEvent PostDeleted(id, post)
2843 id = CLng(xElm.Element("delete").Element("status").Element("id").Value)
2844 RaiseEvent PostDeleted(id, post)
2846 CreateDeleteEvent(DateTime.Now, id, post)
2848 ElseIf xElm.Element("limit") IsNot Nothing Then
2851 ElseIf xElm.Element("event") IsNot Nothing Then
2852 Debug.Print("event: " + xElm.Element("event").Value)
2853 CreateEventFromJson(line)
2855 ElseIf xElm.Element("direct_message") IsNot Nothing Then
2856 Debug.Print("direct_message")
2861 Dim res As New StringBuilder
2868 CreateDirectMessagesFromJson(res.ToString, WORKERTYPE.UserStream, False)
2870 CreatePostsFromJson(res.ToString, WORKERTYPE.Timeline, Nothing, False, Nothing, Nothing)
2873 RaiseEvent NewPostFromStream()
2876 Private Sub CreateDeleteEvent(ByVal createdat As DateTime, ByVal id As Int64, ByVal post As PostClass)
2877 Dim evt As New FormattedEvent
2878 evt.CreatedAt = createdat
2879 If post Is Nothing Then
2880 Dim tmp As PostClass = (From p In _deletemessages Where p.Id = id).FirstOrDefault
2881 If tmp IsNot Nothing Then
2883 _deletemessages.Remove(post)
2886 If post Is Nothing Then
2887 'evt.Event = "DELETE(UNKNOWN)"
2888 'evt.Username = "--UNKNOWN--"
2889 'evt.Target = "--UNKNOWN--"
2890 '保持していない発言に対しての削除イベントは無視
2894 evt.Event = "DELETE(DM)"
2896 evt.Event = "DELETE(Post)"
2898 evt.Username = post.Name
2899 evt.Target = If(post.Data.Length > 5, post.Data.Substring(0, 5) + "...", post.Data) + " [" + post.PDate.ToString + "]"
2901 Me.StoredEvent.Insert(0, evt)
2902 RaiseEvent UserStreamEventReceived(evt)
2905 Private Sub CreateEventFromJson(ByVal content As String)
2906 Dim eventData As TwitterDataModel.EventData = Nothing
2908 eventData = CreateDataFromJson(Of TwitterDataModel.EventData)(content)
2909 Catch ex As SerializationException
2910 TraceOut(ex, "Event Serialize Exception!" + Environment.NewLine + content)
2911 Catch ex As Exception
2912 TraceOut(ex, "Event Exception!" + Environment.NewLine + content)
2915 Dim evt As New FormattedEvent
2916 evt.CreatedAt = DateTimeParse(eventData.CreatedAt)
2917 evt.Event = eventData.Event
2918 evt.Username = eventData.Source.ScreenName
2919 Select Case eventData.Event
2921 If eventData.Target.ScreenName.ToLower.Equals(_uid) Then
2922 If Not Me.followerId.Contains(eventData.Source.Id) Then Me.followerId.Add(eventData.Source.Id)
2924 Exit Sub 'Block後のUndoをすると、SourceとTargetが逆転したfollowイベントが帰ってくるため。
2927 Case "favorite", "unfavorite"
2928 evt.Target = eventData.TargetObject.Text
2929 Case "list_member_added", "list_member_removed"
2930 evt.Target = eventData.TargetObject.Name
2936 TraceOut("Unknown Event:" + evt.Event + Environment.NewLine + content)
2938 Me.StoredEvent.Insert(0, evt)
2939 RaiseEvent UserStreamEventReceived(evt)
2942 Private Function CreateDataFromJson(Of T)(ByVal content As String) As T
2944 Using stream As New MemoryStream()
2945 Dim buf As Byte() = Encoding.Unicode.GetBytes(content)
2946 stream.Write(Encoding.Unicode.GetBytes(content), offset:=0, count:=buf.Length)
2947 stream.Seek(offset:=0, loc:=SeekOrigin.Begin)
2948 data = DirectCast((New DataContractJsonSerializer(GetType(T))).ReadObject(stream), T)
2953 Private Sub userStream_Started() Handles userStream.Started
2954 RaiseEvent UserStreamStarted()
2957 Private Sub userStream_Stopped() Handles userStream.Stopped
2958 RaiseEvent UserStreamStopped()
2961 Public ReadOnly Property UserStreamEnabled As Boolean
2963 Return If(userStream Is Nothing, False, userStream.Enabled)
2967 Public Sub StartUserStream()
2968 If userStream IsNot Nothing Then
2971 userStream = New TwitterUserstream(twCon)
2972 userStream.Start(Me.AllAtReply, Me.TrackWord)
2975 Public Sub StopUserStream()
2976 If userStream IsNot Nothing Then userStream.Dispose()
2977 userStream = Nothing
2978 If Not _endingFlag Then RaiseEvent UserStreamStopped()
2981 Public Sub ReconnectUserStream()
2982 If userStream IsNot Nothing Then
2983 Me.StartUserStream()
2987 Private Class TwitterUserstream
2988 Implements IDisposable
2990 Public Event StatusArrived(ByVal status As String)
2991 Public Event Stopped()
2992 Public Event Started()
2993 Private twCon As HttpTwitter
2995 Private _streamThread As Thread
2996 Private _streamActive As Boolean
2998 Private _allAtreplies As Boolean = False
2999 Private _trackwords As String = ""
3001 Public Sub New(ByVal twitterConnection As HttpTwitter)
3002 twCon = DirectCast(twitterConnection.Clone(), HttpTwitter)
3005 Public Sub Start(ByVal allAtReplies As Boolean, ByVal trackwords As String)
3006 Me.AllAtReplies = allAtReplies
3007 Me.TrackWords = trackwords
3008 _streamActive = True
3009 If _streamThread IsNot Nothing AndAlso _streamThread.IsAlive Then Exit Sub
3010 _streamThread = New Thread(AddressOf UserStreamLoop)
3011 _streamThread.Name = "UserStreamReceiver"
3012 _streamThread.IsBackground = True
3013 _streamThread.Start()
3016 Public ReadOnly Property Enabled() As Boolean
3018 Return _streamActive
3022 Public Property AllAtReplies As Boolean
3024 Return _allAtreplies
3026 Set(ByVal value As Boolean)
3027 _allAtreplies = value
3031 Public Property TrackWords As String
3035 Set(ByVal value As String)
3040 Private Sub UserStreamLoop()
3041 Dim st As Stream = Nothing
3042 Dim sr As StreamReader = Nothing
3045 If Not NetworkInterface.GetIsNetworkAvailable Then
3046 Thread.Sleep(30 * 1000)
3050 RaiseEvent Started()
3052 twCon.UserStream(st, _allAtreplies, _trackwords, My.Application.Info.ProductName + " v" + fileVersion)
3053 sr = New StreamReader(st)
3055 Do While _streamActive AndAlso Not sr.EndOfStream
3056 RaiseEvent StatusArrived(sr.ReadLine())
3060 If sr.EndOfStream Then
3061 RaiseEvent Stopped()
3062 'TraceOut("Stop:EndOfStream")
3063 Thread.Sleep(10 * 1000)
3067 Catch ex As WebException
3068 If Not Me._streamActive Then
3070 ElseIf ex.Status = WebExceptionStatus.Timeout Then
3071 RaiseEvent Stopped()
3072 TraceOut("Stop:Timeout")
3073 Thread.Sleep(10 * 1000)
3074 ElseIf CType(ex.Response, HttpWebResponse).StatusCode = 420 Then
3075 TraceOut("Stop:Connection Limit")
3078 RaiseEvent Stopped()
3079 TraceOut("Stop:WebException " & ex.Status.ToString)
3080 Thread.Sleep(10 * 1000)
3082 Catch ex As ThreadAbortException
3084 Catch ex As IOException
3085 If Not Me._streamActive Then
3088 RaiseEvent Stopped()
3089 TraceOut("Stop:IOException with Active." + Environment.NewLine + ex.Message)
3090 Thread.Sleep(10 * 1000)
3092 Catch ex As ArgumentException
3093 'System.ArgumentException: ストリームを読み取れませんでした。
3094 'サーバー側もしくは通信経路上で切断された場合?タイムアウト頻発後発生
3095 RaiseEvent Stopped()
3096 TraceOut(ex, "Stop:ArgumentException")
3097 Thread.Sleep(10 * 1000)
3098 Catch ex As Exception
3099 TraceOut("Stop:Exception." + Environment.NewLine + ex.Message)
3102 If sr IsNot Nothing Then
3103 twCon.RequestAbort()
3104 sr.BaseStream.Close()
3109 If _streamActive Then RaiseEvent Stopped()
3110 TraceOut("Stop:EndLoop")
3113 #Region "IDisposable Support"
3114 Private disposedValue As Boolean ' 重複する呼び出しを検出するには
3117 Protected Overridable Sub Dispose(ByVal disposing As Boolean)
3118 If Not Me.disposedValue Then
3120 ' TODO: マネージ状態を破棄します (マネージ オブジェクト)。
3121 _streamActive = False
3122 If _streamThread IsNot Nothing AndAlso _streamThread.IsAlive Then
3123 _streamThread.Abort()
3124 _streamThread.Join(1000)
3128 ' TODO: アンマネージ リソース (アンマネージ オブジェクト) を解放し、下の Finalize() をオーバーライドします。
3129 ' TODO: 大きなフィールドを null に設定します。
3131 Me.disposedValue = True
3134 ' TODO: 上の Dispose(ByVal disposing As Boolean) にアンマネージ リソースを解放するコードがある場合にのみ、Finalize() をオーバーライドします。
3135 'Protected Overrides Sub Finalize()
3136 ' ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
3141 ' このコードは、破棄可能なパターンを正しく実装できるように Visual Basic によって追加されました。
3142 Public Sub Dispose() Implements IDisposable.Dispose
3143 ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
3145 GC.SuppressFinalize(Me)
3152 #Region "IDisposable Support"
3153 Private disposedValue As Boolean ' 重複する呼び出しを検出するには
3156 Protected Overridable Sub Dispose(ByVal disposing As Boolean)
3157 If Not Me.disposedValue Then
3159 ' TODO: マネージ状態を破棄します (マネージ オブジェクト)。
3163 ' TODO: アンマネージ リソース (アンマネージ オブジェクト) を解放し、下の Finalize() をオーバーライドします。
3164 ' TODO: 大きなフィールドを null に設定します。
3166 Me.disposedValue = True
3169 ' TODO: 上の Dispose(ByVal disposing As Boolean) にアンマネージ リソースを解放するコードがある場合にのみ、Finalize() をオーバーライドします。
3170 'Protected Overrides Sub Finalize()
3171 ' ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
3176 ' このコードは、破棄可能なパターンを正しく実装できるように Visual Basic によって追加されました。
3177 Public Sub Dispose() Implements IDisposable.Dispose
3178 ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(ByVal disposing As Boolean) に記述します。
3180 GC.SuppressFinalize(Me)