private string GetRelatedResultsApi(bool read, PostClass post, TabClass tab, List<PostClass> relatedPosts) { if (AccountState != AccountState.Valid) { return string.Empty; } if (MyCommon.IsEnding) { return string.Empty; } HttpStatusCode res; string content = string.Empty; try { res = _twitterConnection.GetRelatedResults(post.OriginalStatusId, ref content); } catch (Exception ex) { return "Err:" + ex.Message; } switch (res) { case HttpStatusCode.OK: AccountState = AccountState.Valid; break; case HttpStatusCode.Unauthorized: AccountState = AccountState.Invalid; return R.Unauthorized; case HttpStatusCode.BadRequest: return "Err:API Limits?"; default: return string.Format("Err:{0}({1})", res, MethodBase.GetCurrentMethod().Name); } List<RelatedResult> items; try { items = D.CreateDataFromJson<List<RelatedResult>>(content); } catch (SerializationException ex) { MyCommon.TraceOut(ex.Message + Environment.NewLine + content); return "Json Parse Error(DataContractJsonSerializer)"; } catch (Exception ex) { MyCommon.TraceOut(ex, MethodBase.GetCurrentMethod().Name + " " + content); return "Invalid Json!"; } PostClass targetItem = post; // if (targetItem == null){return string.Empty;} targetItem = targetItem.Copy(); targetItem.RelTabName = tab.TabName; TabInformations.Instance.AddPost(targetItem); PostClass replyToItem = null; if (targetItem.InReplyToStatusId > 0 && TabInformations.Instance.Item(targetItem.InReplyToStatusId) != null) { replyToItem = TabInformations.Instance.Item(targetItem.InReplyToStatusId).Copy(); replyToItem.IsRead = read || replyToItem.IsMe && ReadOwnPost; replyToItem.RelTabName = tab.TabName; } var replyAdded = false; foreach (var relatedData in items) { foreach (var result in relatedData.Results) { var item = CreatePostsFromStatusData(result.Status); if (item == null) { continue; } if (targetItem.InReplyToStatusId == item.StatusId) { replyToItem = null; replyAdded = true; } item.IsRead = read || item.IsMe && ReadOwnPost; // if (tab != null) { item.RelTabName = tab.TabName; } // 非同期アイコン取得&StatusDictionaryに追加 relatedPosts.Add(item); } } if (replyToItem != null) { relatedPosts.Add(replyToItem); } else if (targetItem.InReplyToStatusId > 0 && !replyAdded) { PostClass p = null; var rslt = GetStatusApi(read, targetItem.InReplyToStatusId, ref p); if (string.IsNullOrEmpty(rslt)) { p.IsRead = read; p.RelTabName = tab.TabName; relatedPosts.Add(p); } return rslt; } // MRTとかに対応のためツイート内にあるツイートを指すURLを取り込む var ma = Regex.Matches(tab.RelationTargetPost.Text, "title=\"https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)(/status(es)?/(?<StatusId>[0-9]+))\""); foreach (Match m in ma) { long statusId; if (!long.TryParse(m.Groups["StatusId"].Value, out statusId)) continue; PostClass p = null; var p2 = TabInformations.Instance.Item(statusId); if (p2 == null) { GetStatusApi(read, statusId, ref p); } else { p = p2.Copy(); } if (p != null) { p.IsRead = read; p.RelTabName = tab.TabName; relatedPosts.Add(p); } } return string.Empty; }
public string GetUserTimelineApi(bool read, int count, string userName, TabClass tab, bool more) { if (AccountState != AccountState.Valid) { return string.Empty; } if (MyCommon.IsEnding) { return string.Empty; } HttpStatusCode res; string content = string.Empty; if (count == 0) { count = 20; } try { if (string.IsNullOrEmpty(userName)) { string target = tab.User; if (string.IsNullOrEmpty(target)) { return string.Empty; } userName = target; res = _twitterConnection.UserTimeline(0, target, count, 0, 0, ref content); } else { res = _twitterConnection.UserTimeline(0, userName, count, more ? tab.OldestId : 0, 0, ref content); } } catch (Exception ex) { return "Err:" + ex.Message; } switch (res) { case HttpStatusCode.OK: AccountState = AccountState.Valid; break; case HttpStatusCode.Unauthorized: AccountState = AccountState.Valid; return string.Format("Err:@{0}'s Tweets are protected.", userName); case HttpStatusCode.BadRequest: return "Err:API Limits?"; default: return string.Format("Err:{0}({1})", res, MethodBase.GetCurrentMethod().Name); } List<Status> items; try { items = D.CreateDataFromJson<List<Status>>(content); } catch (SerializationException ex) { MyCommon.TraceOut(ex.Message + Environment.NewLine + content); return "Json Parse Error(DataContractJsonSerializer)"; } catch (Exception ex) { MyCommon.TraceOut(ex, MethodBase.GetCurrentMethod().Name + " " + content); return "Invalid Json!"; } foreach (var status in items) { PostClass item = CreatePostsFromStatusData(status); if (item == null) { continue; } if (item.StatusId < tab.OldestId) { tab.OldestId = item.StatusId; } item.IsRead = read || (item.IsMe && ReadOwnPost); // if (tab != null) { item.RelTabName = tab.TabName; } // 非同期アイコン取得&StatusDictionaryに追加 TabInformations.Instance.AddPost(item); } return string.Empty; }
// TODO: clean arguments private string CreatePostsFromJson(string content, WorkerType workerType, TabClass tab, bool read, int count, ref long minimumId) { List<Status> items; try { items = D.CreateDataFromJson<List<Status>>(content); } catch (SerializationException ex) { MyCommon.TraceOut(ex.Message + Environment.NewLine + content); return "Json Parse Error(DataContractJsonSerializer)"; } catch (Exception ex) { MyCommon.TraceOut(ex, MethodBase.GetCurrentMethod().Name + " " + content); return "Invalid Json!"; } foreach (var status in items) { PostClass post = CreatePostsFromStatusData(status); if (post == null) { continue; } if (minimumId > post.StatusId) { minimumId = post.StatusId; } // 二重取得回避 lock (_lockObj) { if (tab == null) { if (TabInformations.Instance.ContainsKey(post.StatusId)) { continue; } } else { if (TabInformations.Instance.ContainsKey(post.StatusId, tab.TabName)) { continue; } } } // RT禁止ユーザーによるもの if (post.IsRetweeted && _noRetweetIds.Contains(post.RetweetedByUserId)) { continue; } post.IsRead = read || post.IsMe && ReadOwnPost; if (tab != null) { post.RelTabName = tab.TabName; } // 非同期アイコン取得&StatusDictionaryに追加 TabInformations.Instance.AddPost(post); } return string.Empty; }
public string GetSearch(bool read, TabClass tab, bool more) { if (MyCommon.IsEnding) { return string.Empty; } var count = Configs.Instance.UseAdditionalCount && Configs.Instance.SearchCountApi != 0 ? Configs.Instance.SearchCountApi : Configs.Instance.CountApi; HttpStatusCode res; var content = string.Empty; try { res = _twitterConnection.Search(tab.SearchWords, tab.SearchLang, count, tab.SinceId, ref content); } catch (Exception ex) { return "Err:" + ex.Message; } switch (res) { case HttpStatusCode.BadRequest: return "Invalid query"; case HttpStatusCode.NotFound: return "Invalid query"; case HttpStatusCode.PaymentRequired: // API Documentには420と書いてあるが、該当コードがないので402にしてある return "Search API Limit?"; case HttpStatusCode.OK: break; default: return string.Format("Err:{0}({1})", res, MethodBase.GetCurrentMethod().Name); } if (!TabInformations.Instance.ContainsTab(tab)) { return string.Empty; } SearchResult sres; try { sres = D.CreateDataFromJson<SearchResult>(content); } catch (Exception ex) { MyCommon.TraceOut(ex, MethodBase.GetCurrentMethod().Name + " " + content); return "Invalid JSON!"; } foreach (var item in sres.Statuses.Select(CreatePostsFromStatusData).Where(item => item != null)) { if (item.StatusId < tab.OldestId) { tab.OldestId = item.StatusId; } item.IsRead = read || (item.IsMe && ReadOwnPost); // if (tab != null) { item.RelTabName = tab.TabName; } // 非同期アイコン取得&StatusDictionaryに追加 TabInformations.Instance.AddPost(item); } // TODO: use more sres.SearchMetadata tab.SinceId = sres.SearchMetadata.MaxId; return string.Empty; }
public string GetStatusApi(bool read, long id, TabClass tab) { PostClass post = null; string r = GetStatusApi(read, id, ref post); if (string.IsNullOrEmpty(r)) { if (tab != null) { post.RelTabName = tab.TabName; } // 非同期アイコン取得&StatusDictionaryに追加 TabInformations.Instance.AddPost(post); } return r; }
public string GetRelatedResult(bool read, TabClass tab) { string rslt; var relPosts = new List<PostClass>(); if (tab.RelationTargetPost.TextFromApi.Contains("@") && tab.RelationTargetPost.InReplyToStatusId == 0) { // 検索結果対応 var p = TabInformations.Instance.Item(tab.RelationTargetPost.StatusId); if (p != null && p.InReplyToStatusId > 0) { tab.RelationTargetPost = p; } else { rslt = GetStatusApi(read, tab.RelationTargetPost.StatusId, ref p); if (!string.IsNullOrEmpty(rslt)) { return rslt; } tab.RelationTargetPost = p; } } relPosts.Add(tab.RelationTargetPost.Copy()); var tmpPost = relPosts[0]; do { rslt = GetRelatedResultsApi(read, tmpPost, tab, relPosts); if (!string.IsNullOrEmpty(rslt)) { break; } tmpPost = CheckReplyToPost(relPosts); } while (tmpPost != null); relPosts.ForEach(p => TabInformations.Instance.AddPost(p)); return rslt; }
public string GetListStatus(bool read, TabClass tab, bool more, bool startup) { if (MyCommon.IsEnding) { return string.Empty; } HttpStatusCode res; string content = string.Empty; int count; if (Configs.Instance.UseAdditionalCount) { count = Configs.Instance.ListCountApi; if (count == 0) { if (more && Configs.Instance.MoreCountApi != 0) { count = Configs.Instance.MoreCountApi; } else if (startup && Configs.Instance.FirstCountApi != 0) { count = Configs.Instance.FirstCountApi; } else { count = Configs.Instance.CountApi; } } } else { count = Configs.Instance.CountApi; } try { long oldest = more ? tab.OldestId : 0L; res = _twitterConnection.GetListsStatuses(tab.ListInfo.UserId, tab.ListInfo.Id, count, oldest, 0, Configs.Instance.IsListStatusesIncludeRts, ref content); } catch (Exception ex) { return "Err:" + ex.Message; } switch (res) { case HttpStatusCode.OK: AccountState = AccountState.Valid; break; case HttpStatusCode.Unauthorized: AccountState = AccountState.Invalid; return R.Unauthorized; case HttpStatusCode.BadRequest: return "Err:API Limits?"; default: return string.Format("Err:{0}({1})", res, MethodBase.GetCurrentMethod().Name); } var t = tab.OldestId; var ret = CreatePostsFromJson(content, WorkerType.List, tab, read, count, ref t); tab.OldestId = t; return ret; }
public bool ContainsTab(TabClass ts) { return Tabs.ContainsValue(ts); }
private void SetNextUnreadId(long currentId, TabClass tab) { // CurrentID:今既読にしたID(OldestIDの可能性あり) // 最古未読が設定されていて、既読の場合(1発言以上存在) try { // 次の未読探索 var posts = tab.IsInnerStorageTabType ? tab.Posts : _statuses; if (tab.OldestUnreadId > -1 && posts.ContainsKey(tab.OldestUnreadId) && posts[tab.OldestUnreadId].IsRead && _sorter.Mode == IdComparerClass.ComparerMode.Id) { if (tab.UnreadCount == 0) { // 未読数0→最古未読なし tab.OldestUnreadId = -1; } else if (tab.OldestUnreadId == currentId && currentId > -1) { // 最古IDを既読にしたタイミング→次のIDから続けて探索 int idx = tab.IndexOf(currentId); if (idx > -1) { // 続きから探索 FindUnreadId(idx, tab); } else { // 頭から探索 FindUnreadId(-1, tab); } } else { // 頭から探索 FindUnreadId(-1, tab); } } else { // 頭から探索 FindUnreadId(-1, tab); } } catch (KeyNotFoundException) { // 頭から探索 FindUnreadId(-1, tab); } }
private void FindUnreadId(int startIdx, TabClass tab) { if (tab.AllCount == 0) { tab.OldestUnreadId = -1; tab.UnreadCount = 0; return; } int toIdx; int stp; tab.OldestUnreadId = -1; if (_sorter.Order == SortOrder.Ascending) { if (startIdx == -1) { startIdx = 0; } else { if (startIdx > tab.AllCount - 1) { startIdx = tab.AllCount - 1; // 念のため } } toIdx = tab.AllCount - 1; if (toIdx < 0) { toIdx = 0; // 念のため } stp = 1; } else { if (startIdx == -1) { startIdx = tab.AllCount - 1; } if (startIdx < 0) { startIdx = 0; } // 念のため toIdx = 0; stp = -1; } var posts = tab.IsInnerStorageTabType ? tab.Posts : _statuses; for (int i = startIdx; i <= toIdx; i += stp) { long id = tab.GetId(i); if (id > -1 && !posts[id].IsRead) { tab.OldestUnreadId = id; break; } } }