Esempio n. 1
0
 public UserLinkData(AccountInfo info, UserSelectorViewModel parent, bool isLink)
 {
     this.parent = parent;
     this.info = info;
     this._profileImageProvider = new ProfileImageProvider(info);
     this._IsLink = isLink;
 }
Esempio n. 2
0
 /// <summary>
 /// 指定アカウントの依存情報を受信します。
 /// </summary>
 public static void ReceiveInidividualInfo(AccountInfo info)
 {
     // アカウント情報の受信
     SafeExec(() => UserStorage.Register(info.GetUserByScreenName(info.ScreenName)));
     // フォロー/フォロワー/ブロックの受信
     SafeExec(() => info.GetFriendIds(screenName: info.ScreenName).ForEach(i => info.RegisterFollowing(i)));
     SafeExec(() => info.GetFollowerIds(screenName: info.ScreenName).ForEach(i => info.RegisterFollower(i)));
     SafeExec(() => info.GetBlockingIds().ForEach(i => info.RegisterBlocking(i)));
 }
 public static AccountScheduler GetScheduler(AccountInfo info)
 {
     if (info == null)
         throw new ArgumentNullException("info");
     AccountScheduler sched;
     if (schedulers.TryGetValue(info, out sched))
         return sched;
     else
         return null;
 }
Esempio n. 4
0
 public TweetWorker(InputBlockViewModel parent, AccountInfo info, string body, long inReplyToId, string attachedImage, string[] tag)
 {
     this.parent = parent;
     this.TweetSummary = info.ScreenName + ": " + body;
     this.accountInfo = info;
     this.body = body;
     this.inReplyToId = inReplyToId;
     this.attachImagePath = attachedImage;
     this.tags = tag;
 }
Esempio n. 5
0
 public AccountScheduler(AccountInfo info)
 {
     this._accountInfo = info;
     this.AddSchedule(new HomeReceiveTask(info));
     this.AddSchedule(new MentionReceiveTask(info));
     this.AddSchedule(new DirectMessageReceiveTask(info));
     this.AddSchedule(new SentDirectMessageReceiveTask(info));
     this.AddSchedule(new FavoritesReceiveTask(info));
     this.AddSchedule(new MyTweetsTask(info));
     ThreadHelper.Halt += this.StopSchedule;
 }
Esempio n. 6
0
 public static bool DeleteAccount(AccountInfo info)
 {
     if (info != null && accounts.Contains(info))
     {
         accounts.Remove(info);
         OnAccountsChanged(EventArgs.Empty);
         return true;
     }
     else
     {
         return false;
     }
 }
Esempio n. 7
0
 public TweetWorker(InputBlockViewModel parent, AccountInfo info, string body, long inReplyToId, string attachedImage, string[] tag)
 {
     isImageAttached = false;
     isBodyStandby = false;
     if (info == null)
         throw new ArgumentNullException("info");
     this.parent = parent;
     this.TweetSummary = info.ScreenName + ": " + body;
     this.accountInfo = info;
     this.body = body;
     this.inReplyToId = inReplyToId;
     this.attachImagePath = attachedImage;
     this.tags = tag;
 }
Esempio n. 8
0
        /// <summary>
        /// 接続を開始します。<para />
        /// すでに接続が存在する場合は、すでに存在している接続を破棄します。
        /// </summary>
        public static bool RefreshConnection(AccountInfo info)
        {
            if (info == null)
                throw new ArgumentNullException("info", "AccountInfo is not set.");

            System.Diagnostics.Debug.WriteLine("Refresh connection: " + info.ToString());

            UserStreamsConnection ncon;
            lock (info)
            {
                UserStreamsConnection prevCon;
                // 旧接続の破棄
                if (connections.TryGetValue(info, out prevCon))
                {
                    connections.Remove(info);
                    if (prevCon != null)
                        prevCon.Dispose();
                }

                // User Streams接続しない設定になっている
                if (!info.AccountProperty.UseUserStreams)
                    return false;

                ncon = new UserStreamsConnection(info);
                if (!connections.TryAdd(info, ncon))
                    throw new InvalidOperationException("Connection refresh violation.");
            }

            var queries = lookupDictionary.Where(v => v.Value == info).Select(v => v.Key).ToArray();
            try
            {
                ncon.Connect(queries);
                return true;
            }
            catch (Exception e)
            {
                connections[info] = null;
                ncon.Dispose();
                ExceptionStorage.Register(e, ExceptionCategory.TwitterError,
                    "User Streams接続に失敗しました。", () =>
                        {
                            if (connections.ContainsKey(info) && connections[info] == null)
                                RefreshConnection(info);
                        });
                return false;
            }
        }
Esempio n. 9
0
 public AccountViewModel(AccountInfo info)
 {
     this.Info = info;
     this._profileImageProvider = new Common.ProfileImageProvider(info);
     Task.Factory.StartNew(() => UpdatePostChunk());
     ViewModelHelper.BindNotification(info.ConnectionStateChangedEvent, this,
         (o, e) => RaisePropertyChanged(() => ConnectState));
     ViewModelHelper.BindNotification(TimeTickCall, this, (o, e) =>
     {
         Task.Factory.StartNew(() => UpdatePostChunk());
     });
     ViewModelHelper.BindNotification(PostOffice.OnUnderControlChangedEvent, this, (o, e) =>
     {
         RaisePropertyChanged(() => IsAccountUnderControlled);
         RaisePropertyChanged(() => AccountControlReleaseTime);
     });
 }
Esempio n. 10
0
 public AccountScheduler(AccountInfo info)
 {
     this._accountInfo = info;
     this.AddSchedule(new HomeReceiveTask(info));
     this.AddSchedule(new MentionReceiveTask(info));
     this.AddSchedule(new DirectMessageReceiveTask(info));
     this.AddSchedule(new SentDirectMessageReceiveTask(info));
     this.AddSchedule(new FavoritesReceiveTask(info));
     this.AddSchedule(new MyTweetsTask(info));
     Task.Factory.StartNew(() =>
         {
             try
             {
                 // テストを飛ばす
                 ApiHelper.ExecApi(() => info.Test());
             }
             catch { }
         });
     ThreadHelper.Halt += () => this.StopSchedule();
 }
Esempio n. 11
0
 /// <summary>
 /// 接続を開始します。<para />
 /// すでに接続が存在する場合は、すでに存在している接続を破棄します。
 /// </summary>
 public static bool RefreshConnection(AccountInfo info)
 {
     if (info == null)
         throw new ArgumentNullException("info", "AccountInfo is not set.");
     var ncon = new UserStreamsConnection(info);
     if (connections.ContainsKey(info))
     {
         var pcon = connections[info];
         // 以前の接続がある
         connections[info] = ncon;
         if (pcon != null)
             pcon.Dispose();
     }
     else
     {
         connections.AddOrUpdate(info, ncon);
     }
     var queries = lookupDictionary.Where(v => v.Value == info).Select(v => v.Key).ToArray();
     try
     {
         ncon.Connect(queries);
         return true;
     }
     catch (Exception e)
     {
         connections[info] = null;
         ncon.Dispose();
         ExceptionStorage.Register(e, ExceptionCategory.TwitterError,
             "User Streams接続に失敗しました。", () =>
                 {
                     if (connections.ContainsKey(info) && connections[info] == null)
                         RefreshConnection(info);
                 });
         return false;
     }
 }
Esempio n. 12
0
 private static void RemoveRetweetCore(AccountInfo d, TweetViewModel status)
 {
     // リツイートステータスの特定
     var rts = TweetStorage.GetAll(vm =>
         vm.Status.User.ScreenName == d.ScreenName && vm.Status is TwitterStatus &&
         ((TwitterStatus)vm.Status).RetweetedOriginal != null &&
         ((TwitterStatus)vm.Status).RetweetedOriginal.Id == status.Status.Id).FirstOrDefault();
     if (rts == null || ApiHelper.ExecApi(() => d.DestroyStatus(rts.Status.Id) == null))
         throw new ApplicationException();
 }
Esempio n. 13
0
 private static void RemoveDMSink(AccountInfo info, long tweetId)
 {
     var tweet = ApiHelper.ExecApi(() => info.DestroyDirectMessage(tweetId.ToString()));
     if (tweet != null)
     {
         if (tweet.Id != tweetId)
         {
             NotifyStorage.Notify("削除には成功しましたが、ダイレクトメッセージIDが一致しません。(" + tweetId.ToString() + " -> " + tweet.Id.ToString() + ")");
         }
         else
         {
             TweetStorage.Remove(tweetId);
             NotifyStorage.Notify("削除しました:" + tweet.ToString());
         }
     }
     else
     {
         NotifyStorage.Notify("ダイレクトメッセージを削除できませんでした(@" + info.ScreenName + ")");
     }
 }
Esempio n. 14
0
 public MyTweetsTask(AccountInfo info)
 {
     this._accountInfo = info;
 }
Esempio n. 15
0
 /// <summary>
 /// アカウントを登録します。
 /// </summary>
 /// <param name="accountInfo">登録するアカウント情報</param>
 public static void RegisterAccount(AccountInfo accountInfo)
 {
     if (accountInfo == null)
         throw new ArgumentNullException("accountInfo");
     accounts.Add(accountInfo);
     OnAccountsChanged(EventArgs.Empty);
     // アカウント情報のキャッシュ
     // Task.Factory.StartNew(() => accountInfo.UserViewModel);
 }
Esempio n. 16
0
        private static void UpdateTweetSink(AccountInfo info, string text, long? inReplyToId = null)
        {
            var status = info.UpdateStatus(text, inReplyToId);
            if (status == null || status.Id == 0)
                throw new WebException("Timeout or failure sending tweet.", WebExceptionStatus.Timeout);

            TweetStorage.Register(status);
            NotifyStorage.Notify("ツイートしました:@" + info.ScreenName + ": " + text);
        }
Esempio n. 17
0
 private static void UnfavTweetCore(AccountInfo d, TweetViewModel status)
 {
     if (ApiHelper.ExecApi(() => d.DestroyFavorites(status.Status.Id)) == null)
         throw new ApplicationException();
 }
Esempio n. 18
0
 private static void RemoveTweetSink(AccountInfo info, long tweetId)
 {
     var tweet = ApiHelper.ExecApi(() => info.DestroyStatus(tweetId));
     if (tweet != null)
     {
         if (tweet.Id != tweetId)
         {
             NotifyStorage.Notify("削除には成功しましたが、ツイートIDが一致しません。(" + tweetId.ToString() + " -> " + tweet.Id.ToString() + ")");
         }
         else
         {
             if (tweet.InReplyToStatusId != 0)
             {
                 var s = TweetStorage.Get(tweet.InReplyToStatusId);
                 if (s != null)
                     s.RemoveInReplyToThis(tweetId);
             }
             TweetStorage.Remove(tweetId);
             NotifyStorage.Notify("削除しました:" + tweet.ToString());
         }
     }
     else
     {
         NotifyStorage.Notify("ツイートを削除できませんでした(@" + info.ScreenName + ")");
     }
 }
Esempio n. 19
0
 private static void RetweetCore(AccountInfo d, TweetViewModel status)
 {
     if (ApiHelper.ExecApi(() => d.Retweet(status.Status.Id)) == null)
         throw new ApplicationException();
 }
Esempio n. 20
0
 public static void RemoveTweet(AccountInfo info, long tweetId)
 {
     var result = Task.Factory.StartNew(() =>
                 removeInjection.Execute(new Tuple<AccountInfo, long>(info, tweetId)));
     var ex = result.Exception;
     if (ex != null)
     {
         NotifyStorage.Notify("ツイートを削除できませんでした(@" + info.ScreenName + ")");
         ExceptionStorage.Register(ex, ExceptionCategory.TwitterError, "ツイート削除時にエラーが発生しました");
     }
 }
Esempio n. 21
0
        private static void UpdateDirectMessageSink(AccountInfo info, string target, string body)
        {
            var status = info.SendDirectMessage(target, body);
            if (status == null || status.Id == 0)
                throw new WebException("Timeout or failure sending tweet.", WebExceptionStatus.Timeout);

            TweetStorage.Register(status);
            NotifyStorage.Notify("DMを送信しました: @" + info.ScreenName + " -> @" + target + ": " + body);
        }
Esempio n. 22
0
        public static int UpdateTweet(AccountInfo info, string text, long? inReplyToId = null)
        {
            int retryCount = 0;
            do
            {
                try
                {
                    updateInjection.Execute(new Tuple<AccountInfo, string, long?>(info, text, inReplyToId));
                    break; // break roop on succeeded
                }
                catch (WebException wex)
                {
                    if (wex.Status == WebExceptionStatus.ProtocolError)
                    {
                        var hrw = wex.Response as HttpWebResponse;
                        if (hrw != null && hrw.StatusCode == HttpStatusCode.Forbidden)
                        {
                            // 規制?
                            using (var strm = hrw.GetResponseStream())
                            using (var json = JsonReaderWriterFactory.CreateJsonReader(strm,
                                System.Xml.XmlDictionaryReaderQuotas.Max))
                            {
                                var xdoc = XDocument.Load(json);
                                System.Diagnostics.Debug.WriteLine(xdoc);
                                var eel = xdoc.Root.Element("error");
                                if (eel != null)
                                {
                                    if (eel.Value.IndexOf("update limit", StringComparison.CurrentCultureIgnoreCase) >= 0)
                                    {
                                        // User is over daily status update limit.
                                        // POST規制
                                        AddUnderControlled(info);
                                        throw new TweetFailedException(TweetFailedException.TweetErrorKind.Controlled);
                                    }
                                    else if (eel.Value.IndexOf("duplicate", StringComparison.CurrentCultureIgnoreCase) >= 0)
                                    {
                                        // 同じツイートをしようとした
                                        if (retryCount == 0) // 複数回投稿している場合はサスペンドする
                                            throw new TweetFailedException(TweetFailedException.TweetErrorKind.Duplicated);
                                        else
                                            break; // 成功
                                    }
                                    else
                                    {
                                        // 何かよくわからない
                                        throw new TweetFailedException(TweetFailedException.TweetErrorKind.CommonFailed, eel.Value);
                                    }
                                }
                            }
                        }
                        // 何かよくわからない
                        throw new TweetFailedException(TweetFailedException.TweetErrorKind.CommonFailed, wex.Message);
                    }
                    else
                    {
                        if (!Setting.Instance.InputExperienceProperty.AutoRetryOnError)
                        {
                            if (wex.Status == WebExceptionStatus.Timeout)
                            {
                                // タイムアウト
                                throw new TweetFailedException(TweetFailedException.TweetErrorKind.Timeout, "ツイートに失敗しました(タイムアウトしました。Twitterが不調かも)", wex);
                            }
                            else
                            {
                                // 何かがおかしい
                                throw new TweetFailedException(TweetFailedException.TweetErrorKind.CommonFailed, "ツイートに失敗しました(" + (int)wex.Status + ")", wex);
                            }
                        }
                    }
                }
                catch (TweetAnnotationException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    throw new TweetFailedException(TweetFailedException.TweetErrorKind.CommonFailed, "ツイートに失敗しました(" + ex.Message + ")", ex);
                }
            } while (Setting.Instance.InputExperienceProperty.AutoRetryOnError && retryCount++ < Setting.Instance.InputExperienceProperty.AutoRetryMaxCount);

            var chunk = GetUnderControlChunk(info);
            if (chunk.Item2 > TwitterDefine.UnderControlWarningThreshold)
                throw new TweetAnnotationException(TweetAnnotationException.AnnotationKind.NearUnderControl);

            return chunk.Item2;
        }
Esempio n. 23
0
 public UnderControlEventArgs(AccountInfo info, bool added)
 {
     this.AccountInfo = info;
     this.Added = added;
 }
Esempio n. 24
0
 internal static void UpdateDirectMessage(AccountInfo accountInfo, string target, string body)
 {
     dmInjection.Execute(new Tuple<AccountInfo, string, string>(accountInfo, target, body));
 }
Esempio n. 25
0
 /// <summary>
 /// 既に存在するアカウント情報を更新します。
 /// </summary>
 /// <param name="prevId">旧アカウント情報</param>
 /// <param name="newinfo">新しいアカウント情報</param>
 public static void Update(string prevId, AccountInfo newinfo)
 {
     accounts.LockOperate(() =>
     {
         var prev = Get(prevId);
         if(prev == null)
             throw new ArgumentException("アカウント @" + prevId + " は存在しません。");
         var idx = accounts.IndexOf(prev);
         if (idx < 0) throw new ArgumentException("旧アカウント情報が見つかりません。");
         accounts[idx] = newinfo;
     });
     OnAccountsChanged(EventArgs.Empty);
 }
Esempio n. 26
0
        private static void AddUnderControlled(AccountInfo info)
        {
            if (underControls.ContainsKey(info))
            {
                NotifyStorage.Notify("[規制管理: @" + info.ScreenName + " は規制されています。解除予想時刻: " + underControls[info].ToString("HH:mm:ss"));
                return;
            }

            var timestamp = DateTime.Now.Subtract(TwitterDefine.UnderControlTimespan);

            // APIを利用してツイートを遡り受信
            var notify = NotifyStorage.NotifyManually("[規制管理: @" + info.ScreenName + " の直近のツイートを受信しています...]");

            try
            {
                ApiHelper.ExecApi(() => info.GetUserTimeline(count: 150, includeRts: true))
                    .Guard()
                    .ForEach(i => TweetStorage.Register(i));

                notify.Message = "[規制管理:規制開始時刻を割り出しています...]";

                // 127tweet/3hours
                var originate = TweetStorage.GetAll(
                    t => t.Status.User.ScreenName == info.ScreenName && DateTime.Now.Subtract(t.CreatedAt) < TwitterDefine.UnderControlTimespan)
                    .OrderByDescending((t) => t.Status.CreatedAt)
                    .Skip(TwitterDefine.UnderControlCount - 1)
                    .FirstOrDefault();

                if (originate == null)
                {
                    originate = TweetStorage.GetAll(
                        t => t.Status.User.ScreenName == info.ScreenName && DateTime.Now.Subtract(t.CreatedAt) < TwitterDefine.UnderControlTimespan)
                        .OrderByDescending((t) => t.Status.CreatedAt)
                        .LastOrDefault();
                }

                if (originate == null)
                {
                    NotifyStorage.Notify("[規制管理: @" + info.ScreenName + " はPOST規制されていますが、解除時刻を予想できません。しばらく置いて試してみてください。]");
                }
                else
                {
                    var release = (originate.Status.CreatedAt + TwitterDefine.UnderControlTimespan);
                    NotifyStorage.Notify("[規制管理: @" + info.ScreenName +
                        " はPOST規制されています。解除予想時刻は " + release.ToString("HH:mm:ss") + " です。]");
                    underControls.AddOrUpdate(info, release);
                    OnOnUnderControlChanged(new UnderControlEventArgs(info, true));
                }
            }
            finally
            {
                notify.Dispose();
            }
        }
Esempio n. 27
0
 public ProfileImageProvider(AccountInfo relatedInfo)
 {
     this._info = relatedInfo;
 }
Esempio n. 28
0
 private static AccountInfo CheckFallback(AccountInfo d)
 {
     if (d == null)
         throw new ArgumentNullException("d");
     AccountInfo origin = d;
     while (
         Setting.Instance.InputExperienceProperty.OfficialRetweetFallback &&
         IsAccountUnderControlled(d) &&
         !String.IsNullOrEmpty(d.AccountProperty.FallbackAccount))
     {
         var fallback = AccountStorage.Get(d.AccountProperty.FallbackAccount);
         if (fallback == null || fallback == origin)
             break;
         d = fallback;
     }
     return d;
 }
 private void StealCore(AccountInfo info)
 {
     var ibvm = this.Parent.Parent.Parent.Parent.InputBlockViewModel;
     ibvm.AddUpdateWorker(
         new InputBlock.TweetWorker(ibvm, info, this.Tweet.TweetText,
             ((TwitterStatus)this.Tweet.Status).InReplyToStatusId, null, null));
 }
Esempio n. 30
0
 private static void FavTweetCore(AccountInfo d, TweetViewModel status)
 {
     /*
     if (ApiHelper.ExecApi(() => d.CreateFavorites(status.Status.Id)) == null)
         throw new ApplicationException();
     */
     for (int i = 0; i < 3; i++)
     {
         try
         {
             if (d.CreateFavorites(status.Status.Id) != null)
                 break;
         }
         catch (WebException wex)
         {
             var hwr = wex.Response as HttpWebResponse;
             if (wex.Status == WebExceptionStatus.ProtocolError &&
                 hwr != null && hwr.StatusCode == HttpStatusCode.Forbidden)
             {
                 // あとIt's great that ... ならふぁぼ規制
                 using (var read = new StreamReader( hwr.GetResponseStream()))
                 {
                     var desc = read.ReadToEnd();
                     if (desc.Contains("It's great that you like so many updates, but we only allow so many updates to be marked as a favorite per day."))
                     {
                         throw new FavoriteSuspendedException();
                     }
                 }
             }
             else if (wex.Status == WebExceptionStatus.Timeout)
             {
                 continue;
             }
             else
             {
                 break;
             }
         }
     }
 }