//------------------------------------------------------------------------------- /// <summary> /// 発言がフィルタを通るかどうか判別します。 /// </summary> /// <param name="twitdata">発言</param> /// <param name="filter">フィルター</param> /// <param name="friends_ids">フォローしている人のID</param> /// <returns></returns> /// <remarks>通ると判断したらすぐにtrueを返していくようにする</remarks> public static bool ThroughFilter(TwitData twitdata, StatusFilterInfo filter, Func<long,bool> checkIncludeFriendFunc) { Debug.Assert(twitdata != null && filter != null && checkIncludeFriendFunc != null); // ユーザー抽出 switch (filter.User_FilterType) { case StatusFilterUserType.All: break; case StatusFilterUserType.Following: if (!checkIncludeFriendFunc(twitdata.UserID)) { return true; } break; case StatusFilterUserType.Unfollowing: if (checkIncludeFriendFunc(twitdata.UserID)) { return true; } break; case StatusFilterUserType.UserList: // 通る:パターンが存在,そのいずれかに当てはまっていない if (filter.User_Patterns != null && filter.User_Patterns.Any(pattern => !Regex.IsMatch(twitdata.UserScreenName, pattern))) { return true; } break; default: Debug.Assert(false, "不正なフィルタ"); return false; } if (filter.Status_FilterType != StatusFilterStatusType.All) { // 発言パターン抽出 if ((filter.Status_FilterType & StatusFilterStatusType.NormalTweet) != StatusFilterStatusType.NormalTweet && twitdata.TwitType == TwitType.Normal && twitdata.Mention_UserID < 0) { return true; } else if ((filter.Status_FilterType & StatusFilterStatusType.ReplyTweet) != StatusFilterStatusType.ReplyTweet && twitdata.TwitType == TwitType.Normal && twitdata.Mention_UserID >= 0) { return true; } else if ((filter.Status_FilterType & StatusFilterStatusType.Retweet) != StatusFilterStatusType.Retweet && TwitData.IsRT(twitdata)) { return true; } } // Text抽出 if (filter.Status_Text_Patterns != null && filter.Status_Text_Patterns.Any(pattern => !Regex.IsMatch(twitdata.MainTwitData.Text, pattern))) { return true; } // Client抽出 if (filter.Status_Client_Patterns != null && filter.Status_Client_Patterns.Any(pattern => !Regex.IsMatch(twitdata.MainTwitData.Source, pattern))) { return true; } return false; }
//------------------------------------------------------------------------------- // private TwitData ConvertToTwitDataUserStream(XElement el) { try { XElement RTel = el.Element("retweeted_status"); bool notRT = (RTel == null); var data = new TwitData() { TwitType = (notRT) ? TwitType.Normal : TwitType.Retweet, DMScreenName = "", StatusID = long.Parse(el.Element("id").Value), Time = StringToDateTime(el.Element("created_at").Value), Favorited = bool.Parse(el.Element("favorited").Value), Mention_StatusID = TryParseLong(el.Element("in_reply_to_status_id").Value), Mention_UserID = TryParseLong(el.Element("in_reply_to_user_id").Value), Mention_ScreenName = el.Element("in_reply_to_screen_name").Value, Text = ConvertSpecialChar(el.Element("text").Value), Source = CutSourceString(el.Element("source").Value), UserID = long.Parse(el.Element("user").Element("id").Value), UserName = el.Element("user").Element("name").Value, IconURL = el.Element("user").Element("profile_image_url").Value, UserScreenName = el.Element("user").Element("screen_name").Value, UserProtected = bool.Parse(el.Element("user").Element("protected").Value), RTTwitData = (notRT) ? null : new TwitData() { TwitType = StarlitTwit.TwitType.Normal, DMScreenName = "", StatusID = long.Parse(RTel.Element("id").Value), Time = StringToDateTime(RTel.Element("created_at").Value), Favorited = bool.Parse(RTel.Element("favorited").Value), Mention_StatusID = TryParseLong(RTel.Element("in_reply_to_status_id").Value), Mention_UserID = TryParseLong(RTel.Element("in_reply_to_user_id").Value), Mention_ScreenName = RTel.Element("in_reply_to_screen_name").Value, Text = ConvertSpecialChar(RTel.Element("text").Value), Source = CutSourceString(RTel.Element("source").Value), UserID = long.Parse(RTel.Element("user").Element("id").Value), UserName = RTel.Element("user").Element("name").Value, IconURL = RTel.Element("user").Element("profile_image_url").Value, UserScreenName = RTel.Element("user").Element("screen_name").Value, UserProtected = bool.Parse(RTel.Element("user").Element("protected").Value) }, }; XElement mainel = (notRT) ? el : RTel; if (mainel.Element("entities") != null) { IEnumerable<URLData> urldata = ConvertToURLData(mainel.Element("entities"), true); foreach (var u in urldata) { data.MainTwitData.Text = data.MainTwitData.Text.Replace(u.shorten_url, u.expand_url); } data.UrlData = urldata.ToArray(); } data.Entities = GetEntitiesByRegex(data.MainTwitData.Text).ToArray(); if (!notRT) { data.RTTwitData.Entities = GetEntitiesByRegex(data.RTTwitData.Text).ToArray(); } return data; } catch (NullReferenceException ex) { Log.DebugLog(ex); Log.DebugLog(el.ToString()); throw new TwitterAPIException(1001, "予期しないXmlです。"); } }
//------------------------------------------------------------------------------- // private IEnumerable<TwitData> ConvertToTwitDataSearch(XElement el) { try { Func<XElement, TwitData> makeTwitData = xel => { TwitData data = new TwitData() { TwitType = StarlitTwit.TwitType.Search, DMScreenName = "", StatusID = long.Parse(xel.Element("id").Value), Time = StringToDateTime(xel.Element("created_at").Value), Favorited = false, Mention_StatusID = -1, Mention_UserID = -1, // TryParseLong(xel.Element("to_user_id").Value), Text = ConvertSpecialChar(xel.Element("text").Value), Source = CutSourceString(ConvertSpecialChar(xel.Element("source").Value)), UserID = long.Parse(xel.Element("from_user_id").Value), UserName = "", IconURL = xel.Element("profile_image_url").Value, UserScreenName = xel.Element("from_user").Value, UserProtected = false, RTTwitData = null }; if (xel.Element("entities") != null) { IEnumerable<URLData> urldata = ConvertToURLData(xel.Element("entities"), true); foreach (var u in urldata) { data.MainTwitData.Text = data.MainTwitData.Text.Replace(u.shorten_url, u.expand_url); } data.UrlData = urldata.ToArray(); } data.Entities = GetEntitiesByRegex(data.Text).ToArray(); return data; }; return from stat in el.Element("statuses").Elements("item") select makeTwitData(stat); } catch (NullReferenceException ex) { Log.DebugLog(ex); throw new TwitterAPIException(1001, "予期しないXmlです。"); } }
//------------------------------------------------------------------------------- /// <summary> /// <para>XElementからTwitDataに変換します。</para> /// <para>DirectMessageデータ用です。</para> /// </summary> /// <param name="el"></param> /// <returns></returns> private TwitData ConvertToTwitDataDM(XElement el) { try { var data = new TwitData() { TwitType = StarlitTwit.TwitType.DirectMessage, DMScreenName = el.Element("recipient_screen_name").Value, StatusID = long.Parse(el.Element("id").Value), Time = StringToDateTime(el.Element("created_at").Value), Favorited = false, Mention_StatusID = -1, Mention_UserID = -1, Text = ConvertSpecialChar(el.Element("text").Value), Source = "", UserID = long.Parse(el.Element("sender").Element("id").Value), UserName = el.Element("sender").Element("name").Value, IconURL = el.Element("sender").Element("profile_image_url").Value, UserScreenName = el.Element("sender_screen_name").Value, UserProtected = bool.Parse(el.Element("sender").Element("protected").Value), RTTwitData = null }; data.Entities = GetEntitiesByRegex(data.Text).ToArray(); return data; } catch (NullReferenceException ex) { Log.DebugLog(ex); Log.DebugLog(el.ToString()); throw new TwitterAPIException(1001, "予期しないXmlです。"); } }
//------------------------------------------------------------------------------- /// <summary> /// 発言がフィルタを通るかどうか判別します。 /// </summary> /// <param name="twitdata">発言</param> /// <param name="filters">フィルター配列</param> /// <param name="friends_ids">フォローしている人のID</param> /// <returns></returns> public static bool ThroughFilters(TwitData twitdata, IEnumerable<StatusFilterInfo> filters, Func<long, bool> checkIncludeFriendFunc) { Debug.Assert(twitdata != null && checkIncludeFriendFunc != null); if (filters == null) { return true; } return filters.Where(sfi => sfi.Enabled) .All(sfi => ThroughFilter(twitdata, sfi, checkIncludeFriendFunc)); }
//------------------------------------------------------------------------------- /// <summary> /// より新しいツイートを取得します。 /// </summary> /// <param name="uctldisp">更新を行うUctlDispTwit</param> /// <returns>取得に成功したか</returns> private bool GetMoreRecentTweets(UctlDispTwit uctldisp, long since_id) { IEnumerable<TwitData> d; try { if (uctldisp == uctlDispHome) { d = Twitter.statuses_home_timeline(count: SettingsData.RenewGetNum_Home, since_id: since_id); if (_friendIDSet != null) { d = d.Where(twitdata => StatusFilter.ThroughFilters(twitdata, SettingsData.Filters, CheckIncludeFriendIDs)); } } else if (uctldisp == uctlDispReply) { d = Twitter.statuses_mentions_timeline(count: SettingsData.RenewGetNum_Reply, since_id: since_id); } else if (uctldisp == uctlDispHistory) { d = Twitter.statuses_user_timeline(count: SettingsData.RenewGetNum_History, since_id: since_id, include_rts: true); } else if (uctldisp == uctlDispDirect) { d = Twitter.direct_messages(count: SettingsData.RenewGetNum_Direct, since_id: since_id) .Concat(Twitter.direct_messages_sent(count: SettingsData.RenewGetNum_Direct, since_id: since_id)) .OrderByDescending(twdata => twdata.StatusID); } else { TabData tabdata; lock (SettingsData.TabDataDic) { tabdata = SettingsData.TabDataDic[(string)uctldisp.Tag]; } switch (tabdata.SearchType) { case TabSearchType.Keyword: var ret = Twitter.search_tweets(q: tabdata.SearchWord, count: tabdata.RenewGetNum, since_id: since_id); d = ret.Item1; break; case TabSearchType.User: d = Twitter.statuses_user_timeline(screen_name: tabdata.SearchWord, count: tabdata.RenewGetNum, since_id: since_id, include_rts: true); break; case TabSearchType.List: d = Twitter.lists_statuses(slug: tabdata.SearchWord, owner_screen_name: tabdata.ListOwner, count: tabdata.RenewGetNum, since_id: since_id, include_rts: true); break; default: Debug.Assert(false, "異常な検索タイプ"); d = new TwitData[0]; break; } } } catch (TwitterAPIException ex) { tssLabel.SetText(Twitter.MakeTwitterAPIExceptionStr(ex), ERROR_STATUSBAR_DISP_TIMES); SYSTEMSOUND.Play(); return false; } this.Invoke((Action)(() => { uctldisp.AddData(d, true); /* tsslRestAPI.Text = string.Format(REST_API_FORMAT, Twitter.API_Rest, Twitter.API_Max); */ })); return true; }
//------------------------------------------------------------------------------- /// <summary> /// 最新のツイートを取得します。 /// </summary> /// <param name="uctldisp">更新を行うUctlDispTwit</param> /// <returns>取得に成功したか</returns> private bool GetMostRecentTweets(UctlDispTwit uctldisp) { IEnumerable<TwitData> d; bool isFirst = (uctldisp.MaxTweetID == -1); try { //if (uctldisp == uctlDispPublic) { // d = _twitter.statuses_public_timeline(); //} //else if (uctldisp == uctlDispHome) { int iCount = (isFirst) ? SettingsData.FirstGetNum_Home : SettingsData.RenewGetNum_Home; d = Twitter.statuses_home_timeline(count: iCount); if (_friendIDSet != null) { d = d.Where(twitdata => StatusFilter.ThroughFilters(twitdata, SettingsData.Filters, CheckIncludeFriendIDs)); } } else if (uctldisp == uctlDispReply) { int iCount = (isFirst) ? SettingsData.FirstGetNum_Reply : SettingsData.RenewGetNum_Reply; d = Twitter.statuses_mentions_timeline(count: iCount); } else if (uctldisp == uctlDispHistory) { int iCount = (isFirst) ? SettingsData.FirstGetNum_History : SettingsData.RenewGetNum_History; d = Twitter.statuses_user_timeline(count: iCount, include_rts: true); } else if (uctldisp == uctlDispDirect) { int iCount = (isFirst) ? SettingsData.FirstGetNum_Direct : SettingsData.RenewGetNum_Direct; d = Twitter.direct_messages(count: iCount) .Concat(Twitter.direct_messages_sent(count: iCount)) .OrderByDescending(twdata => twdata.StatusID); } else { TabData tabdata; lock (SettingsData.TabDataDic) { tabdata = SettingsData.TabDataDic[(string)uctldisp.Tag]; } int iCount = (isFirst) ? tabdata.FirstGetNum : tabdata.RenewGetNum; switch (tabdata.SearchType) { case TabSearchType.Keyword: var ret = Twitter.search_tweets(q: tabdata.SearchWord, count: iCount); d = ret.Item1; break; case TabSearchType.User: d = Twitter.statuses_user_timeline(screen_name: tabdata.SearchWord, count: iCount, include_rts: true); break; case TabSearchType.List: d = Twitter.lists_statuses(slug: tabdata.SearchWord, owner_screen_name: tabdata.ListOwner, count: iCount, include_rts: true); break; default: Debug.Assert(false, "異常な検索タイプ"); d = new TwitData[0]; break; } } } catch (TwitterAPIException ex) { tssLabel.SetText(Twitter.MakeTwitterAPIExceptionStr(ex), ERROR_STATUSBAR_DISP_TIMES); SYSTEMSOUND.Play(); return false; } this.Invoke((Action)(() => { string baloontext = uctldisp.AddData(d); /* tsslRestAPI.Text = string.Format(REST_API_FORMAT, Twitter.API_Rest, Twitter.API_Max); */ // バルーン設定 if (!isFirst) { if (uctldisp == uctlDispReply && SettingsData.DisplayReplyBaloon) { PopupTasktrayReply(baloontext); } else if (uctldisp == uctlDispDirect && SettingsData.DisplayDMBaloon) { PopupTasktrayDM(baloontext); } } })); return true; }
//------------------------------------------------------------------------------- // private void GetTweets() { bool disableAppend = false; try { try { this.Invoke((Action)(() => { tsslabel.Text = "発言取得中..."; btnAppend.Enabled = false; })); IEnumerable<TwitData> d = null; string changedStatusText = null; switch (FormType) { case EFormType.UserStatus: d = FrmMain.Twitter.statuses_user_timeline(screen_name: UserScreenName, max_id: _last_status_id - 1, count: GET_NUM, include_rts: true); if (d.Count() > 0) { _last_status_id = d.Min(td => td.StatusID); } else { disableAppend = true; } break; case EFormType.Conversation: disableAppend = true; changedStatusText = "全ての会話を取得完了しました。"; while (_last_status_id >= 0) { TwitData data; if (!Utilization.GetTwitDataFromID(_last_status_id, out data)) { changedStatusText = "取得できなかった発言があります。"; disableAppend = false; break; } this.Invoke((Action)(() => uctlDispTwit.AddData(data.AsEnumerable(), true))); _last_status_id = data.Mention_StatusID; } d = new TwitData[0]; break; case EFormType.MyRetweet: // TODO 消去 //d = FrmMain.Twitter.statuses_retweeted_by_me(max_id: _last_status_id - 1, count: GET_NUM); //if (d.Count() > 0) { _last_status_id = d.Min(td => td.StatusID); } //else { disableAppend = true; } break; case EFormType.FollowersRetweet: // TODO 消去 //d = FrmMain.Twitter.statuses_retweeted_to_me(max_id: _last_status_id - 1, count: GET_NUM); //if (d.Count() > 0) { _last_status_id = d.Min(td => td.StatusID); } //else { disableAppend = true; } break; case EFormType.FollowersRetweetToMe: d = FrmMain.Twitter.statuses_retweets_of_me(max_id: _last_status_id - 1, count: GET_NUM); if (d.Count() > 0) { _last_status_id = d.Min(td => td.StatusID); } else { disableAppend = true; } break; case EFormType.ListStatuses: d = FrmMain.Twitter.lists_statuses(slug: ListID, owner_screen_name: UserScreenName, max_id: _last_status_id - 1, count: GET_NUM, include_rts: true); if (d.Count() > 0) { _last_status_id = d.Min(td => td.StatusID); } else { disableAppend = true; } break; case EFormType.MyFavorite: d = FrmMain.Twitter.favorites_list(max_id: _last_status_id); if (d.Count() > 0) { _last_status_id = d.Min(td => td.StatusID); } disableAppend = (d.Count() == 0); break; case EFormType.UserFavorite: d = FrmMain.Twitter.favorites_list(max_id: _last_status_id); if (d.Count() > 0) { _last_status_id = d.Min(td => td.StatusID); } disableAppend = (d.Count() == 0); break; default: Debug.Assert(false); // ここには来ない return; } this.Invoke((Action)(() => { uctlDispTwit.AddData(d); tsslabel.Text = (changedStatusText == null) ? "取得完了しました。" : changedStatusText; btnAppend.Enabled = !disableAppend; })); } catch (TwitterAPIException) { this.Invoke((Action)(() => { tsslabel.Text = "取得に失敗しました。"; btnAppend.Enabled = !disableAppend; })); } } catch (InvalidOperationException) { } }