示例#1
0
        private async void TraceBackConversations(long origin)
        {
            try
            {
                _isPreparing = true;
                var queue = new Queue <long>();
                var list  = new List <long>();
                queue.Enqueue(await this.FindHeadAsync(origin));
                while (queue.Count > 0)
                {
                    var cid = queue.Dequeue();
                    list.Add(cid);
                    var ids = await StatusProxy.FindFromInReplyToAsync(cid);

                    ids.ForEach(queue.Enqueue);
                }
                lock (_statuses)
                {
                    list.ForEach(_statuses.Add);
                }
            }
            finally
            {
                _isPreparing = false;
                this.RaiseInvalidateRequired();
            }
        }
示例#2
0
 protected override IObservable <TwitterStatus> Fetch(long?maxId, int?count)
 {
     if (_option == SearchOption.Web)
     {
         var acc = Setting.Accounts.GetRandomOne();
         if (acc == null)
         {
             return(Observable.Empty <TwitterStatus>());
         }
         System.Diagnostics.Debug.WriteLine("SEARCHPANE SEARCH QUERY: " + _query);
         var param = new SearchParameter(_query, maxId: maxId, count: count,
                                         lang: String.IsNullOrWhiteSpace(Setting.SearchLanguage.Value)
                 ? null
                 : Setting.SearchLanguage.Value,
                                         locale: String.IsNullOrWhiteSpace(Setting.SearchLocale.Value)
                 ? null
                 : Setting.SearchLocale.Value);
         return(acc.CreateAccessor()
                .SearchAsync(param, CancellationToken.None)
                .ToObservable()
                .SelectMany(s => s.Result)
                .Do(StatusInbox.Enqueue));
     }
     return(StatusProxy.FetchStatuses(_filterFunc, _filterSql, maxId, count)
            .ToObservable()
            .SelectMany(s => s)
            .Merge(_filterQuery != null
                           ? _filterQuery.ReceiveSources(maxId)
                           : Observable.Empty <TwitterStatus>()));
 }
示例#3
0
        private static void StatusDeleted(long statusId)
        {
            // registered as removed status
            _removes[statusId] = DateTime.Now;
            Task.Run(async() =>
            {
                // find removed statuses
                var removeds = await StatusProxy.RemoveStatusAsync(statusId).ConfigureAwait(false);

                // notify removed ids
                foreach (var removed in removeds)
                {
                    _removes[removed] = DateTime.Now;
                    StatusBroadcaster.Enqueue(new StatusNotification(removed));
                }

                // check cleanup cycle
                var stamp = DateTime.Now;
                if (stamp - _cleanupPeriod > _threshold)
                {
                    // update period stamp
                    _cleanupPeriod = stamp;

                    // remove expireds
                    _removes.Where(t => (stamp - t.Value) > _threshold)
                    .ForEach(t =>
                    {
                        // remove expired
                        DateTime value;
                        _removes.TryRemove(t.Key, out value);
                    });
                }
            });
        }
示例#4
0
        public async void RemoveRetweetedUser(long userId)
        {
            if (Status.RetweetedStatus != null)
            {
                var status = await Get(Status.RetweetedStatus).ConfigureAwait(false);

                status.RemoveRetweetedUser(userId);
            }
            else
            {
                TwitterUser remove;
                lock (_retweetedsLock)
                {
                    if (_retweetedUsersDic.TryGetValue(userId, out remove))
                    {
                        _retweetedUsersDic.Remove(userId);
                        Status.RetweetedUsers = Status.RetweetedUsers.Guard().Except(new[] { userId }).ToArray();
                    }
                }
                if (remove != null)
                {
                    _retweetedUsers.Remove(remove);
                    // update persistent info
#pragma warning disable 4014
                    StatusProxy.RemoveRetweeter(Status.Id, userId);
                    StatusBroadcaster.Republish(this);
#pragma warning restore 4014
                }
            }
        }
示例#5
0
        public async void AddRetweetedUser(TwitterUser user)
        {
            if (this.Status.RetweetedOriginal != null)
            {
                var status = await Get(this.Status.RetweetedOriginal);

                status.AddRetweetedUser(user);
            }
            else
            {
                var added = false;
                lock (this._retweetedsLock)
                {
                    if (!this._retweetedUsersDic.ContainsKey(user.Id))
                    {
                        this._retweetedUsersDic.Add(user.Id, user);
                        this.Status.RetweetedUsers = this.Status.RetweetedUsers.Guard()
                                                     .Append(user.Id)
                                                     .Distinct()
                                                     .ToArray();
                        added = true;
                    }
                }
                if (added)
                {
                    this._retweetedUsers.Add(user);
#pragma warning disable 4014
                    StatusProxy.AddRetweeter(this.Status.Id, user.Id);
                    StatusBroadcaster.Republish(this);
#pragma warning restore 4014
                }
            }
        }
示例#6
0
 protected override IObservable <TwitterStatus> Fetch(long?maxId, int?count)
 {
     return(StatusProxy.FetchStatuses(this._filterFunc, this._filterSql, maxId, count)
            .Merge(_filterQuery != null
                           ? _filterQuery.ReceiveSources(maxId)
                           : Observable.Empty <TwitterStatus>()));
 }
        private async void TraceBackConversations(long origin)
        {
            try
            {
                _isPreparing = true;
                var queue = new Queue <long>();
                var list  = new List <long>();
                queue.Enqueue(await FindHeadAsync(origin).ConfigureAwait(false));
                while (queue.Count > 0)
                {
                    var cid = queue.Dequeue();
                    list.Add(cid);
                    var ids = await StatusProxy.FindFromInReplyToAsync(cid).ConfigureAwait(false);

                    ids.ForEach(queue.Enqueue);
                }
                lock (_statuses)
                {
                    list.ForEach(_statuses.Add);
                }
            }
            finally
            {
                _isPreparing = false;
                System.Diagnostics.Debug.WriteLine("#INVALIDATION: Conversation Loaded");
                RaiseInvalidateRequired();
            }
        }
示例#8
0
        public async void RemoveRetweetedUser(long userId)
        {
            if (this.Status.RetweetedOriginal != null)
            {
                var status = await Get(this.Status.RetweetedOriginal);

                status.RemoveRetweetedUser(userId);
            }
            else
            {
                TwitterUser remove;
                lock (this._retweetedsLock)
                {
                    if (this._retweetedUsersDic.TryGetValue(userId, out remove))
                    {
                        this._retweetedUsersDic.Remove(userId);
                        this.Status.RetweetedUsers = this.Status.RetweetedUsers.Except(new[] { userId }).ToArray();
                    }
                }
                if (remove != null)
                {
                    this._retweetedUsers.Remove(remove);
                    // update persistent info
#pragma warning disable 4014
                    StatusProxy.RemoveRetweeter(this.Status.Id, userId);
                    StatusBroadcaster.Republish(this);
#pragma warning restore 4014
                }
            }
        }
示例#9
0
        private static async Task <bool> StatusReceived([CanBeNull] TwitterStatus status)
        {
            if (status == null)
            {
                throw new ArgumentNullException(nameof(status));
            }
            try
            {
                if (await CheckAlreadyExisted(status.Id).ConfigureAwait(false))
                {
                    // already received
                    return(false);
                }
                StatusProxy.StoreStatus(status);
                return(true);
            }
            catch (SqliteCrudException)
            {
            }
            catch (SQLiteException)
            {
            }

            // when throw exception from database: retry.

            // enqueue for retry
            Enqueue(status);

            // and return "already received" sign
            return(false);
        }
        internal static void NotifyRetweetRetweeted(TwitterUser source, TwitterUser target, TwitterStatus status)
        {
            if (MuteBlockManager.IsBlocked(source) || MuteBlockManager.IsOfficialMuted(source))
            {
                return;
            }
            if (!Setting.NotifyBackfilledTweets.Value && status.CreatedAt < App.StartupDateTime)
            {
                // backfilled tweets
                return;
            }
            var original = status.RetweetedStatus;

            if (original == null)
            {
                return;
            }
            Task.Run(() => UserProxy.StoreUser(source));
            Task.Run(() => StatusModel.UpdateStatusInfo(
                         original.Id,
                         model => model.AddRetweetedUser(source), _ =>
            {
                StatusProxy.AddRetweeter(original.Id, source.Id);
                StatusBroadcaster.Republish(original);
            }));
            Head.NotifyRetweetRetweeted(source, target, status);
        }
        internal static void NotifyRetweetFavorited(TwitterUser source, TwitterUser target, TwitterStatus status)
        {
            if (MuteBlockManager.IsBlocked(source) || MuteBlockManager.IsOfficialMuted(source))
            {
                return;
            }
            if (!NotificationLatch.CheckSetPositive(NotificationLatchTarget.Favorite, source.Id, status.Id))
            {
                return;
            }
            var original = status.RetweetedStatus;

            if (original == null)
            {
                return;
            }
            Task.Run(() => UserProxy.StoreUser(source));
            Task.Run(() => StatusModel.UpdateStatusInfo(
                         original.Id,
                         model => model.AddFavoritedUser(source), _ =>
            {
                StatusProxy.AddFavoritor(original.Id, source.Id);
                StatusBroadcaster.Republish(original);
            }));
            Head.NotifyRetweetFavorited(source, target, status);
        }
示例#12
0
        private static async Task <bool> StatusReceived([NotNull] TwitterStatus status)
        {
            if (status == null)
            {
                throw new ArgumentNullException("status");
            }
            try
            {
                if (await CheckAlreadyExisted(status.Id))
                {
                    // already received
                    return(false);
                }
                StatusProxy.StoreStatus(status);
                return(true);
            }
            catch (SQLiteException sqex)
            {
                System.Diagnostics.Debug.WriteLine("Requeue: " + status);

                // enqueue for retry
                Enqueue(status);

                // and return "already received" sign
                return(false);
            }
        }
示例#13
0
        public async void AddFavoritedUser(TwitterUser user)
        {
            if (Status.RetweetedStatus != null)
            {
                var status = await Get(Status.RetweetedStatus).ConfigureAwait(false);

                status.AddFavoritedUser(user);
            }
            else
            {
                var added = false;
                lock (_favoritedsLock)
                {
                    if (!_favoritedUsersDic.ContainsKey(user.Id))
                    {
                        _favoritedUsersDic.Add(user.Id, user);
                        Status.FavoritedUsers = Status.FavoritedUsers
                                                .Guard()
                                                .Append(user.Id)
                                                .Distinct()
                                                .ToArray();
                        added = true;
                    }
                }
                if (added)
                {
                    _favoritedUsers.Add(user);
#pragma warning disable 4014
                    StatusProxy.AddFavoritor(Status.Id, user.Id);
                    StatusBroadcaster.Republish(this);
#pragma warning restore 4014
                }
            }
        }
示例#14
0
 private static async Task UpdateTweetCount()
 {
     try
     {
         _estimatedGrossTweetCount = (int)(await StatusProxy.GetCountAsync());
     }
     catch (SQLiteException) { }
 }
示例#15
0
 private static async Task UpdateTweetCount()
 {
     try
     {
         _estimatedGrossTweetCount = (int)(await StatusProxy.GetCountAsync()) + _queuedStatusesCount;
     }
     catch (SqliteCrudException) { }
     catch (SQLiteException) { }
 }
        private async Task <long> FindHeadAsync(long id)
        {
            var irt = await StatusProxy.GetInReplyToAsync(id).ConfigureAwait(false);

            if (irt == null)
            {
                return(id);
            }
            return(await FindHeadAsync(irt.Value).ConfigureAwait(false));
        }
示例#17
0
 private static async Task UpdateTweetCount()
 {
     try
     {
         var dbcount = (int)(await StatusProxy.GetCountAsync().ConfigureAwait(false));
         _estimatedGrossTweetCount = dbcount + _queuedStatusesCount;
     }
     catch (SqliteCrudException) { }
     catch (SQLiteException) { }
 }
示例#18
0
        private async Task <long> FindHeadAsync(long id)
        {
            var irt = await StatusProxy.GetInReplyToAsync(id);

            if (irt == null)
            {
                return(id);
            }
            return(await this.FindHeadAsync(irt.Value));
        }
示例#19
0
        public StatusProxy(string appid,string value)
            : this()
        {
            AppId = appid;
            Value = value;

            _original=new StatusProxy()
                          {
                              AppId = appid,
                              Value = value
                          };
        }
示例#20
0
 internal static void NotifyDeleted(long statusId, TwitterStatus deleted)
 {
     if (deleted != null && deleted.RetweetedOriginal != null)
     {
         Task.Run(() => StatusModel.UpdateStatusInfo(
                      deleted.RetweetedOriginal.Id,
                      model => model.RemoveRetweetedUser(deleted.User.Id),
                      _ => StatusProxy.RemoveRetweeter(deleted.RetweetedOriginal.Id,
                                                       deleted.User.Id)));
     }
     Head.NotifyDeleted(statusId, deleted);
 }
示例#21
0
        public void ReportAsSpam()
        {
            var msg = new TaskDialogMessage(new TaskDialogOptions
            {
                Title                   = "ユーザーをスパムとして報告",
                MainIcon                = VistaTaskDialogIcon.Warning,
                MainInstruction         = "ユーザー " + this.Status.User.ScreenName + " をスパム報告しますか?",
                Content                 = "全てのアカウントからブロックし、代表のアカウントからスパム報告します。",
                CustomButtons           = new[] { "スパム報告", "キャンセル" },
                AllowDialogCancellation = true,
            });
            var response = this.Parent.Messenger.GetResponse(msg);

            if (response.Response.CustomButtonResult != 0)
            {
                return;
            }
            // report as a spam
            var accounts = Setting.Accounts.Collection.ToArray();
            var reporter = accounts.FirstOrDefault();

            if (reporter == null)
            {
                return;
            }
            var rreq = new UpdateRelationRequest(this.User.User, RelationKind.Block);

            accounts.ToObservable()
            .SelectMany(a =>
                        RequestQueue.Enqueue(a, rreq)
                        .Do(r => BackstageModel.RegisterEvent(
                                new BlockedEvent(a.GetPserudoUser(), this.User.User))))
            .Merge(
                RequestQueue.Enqueue(reporter,
                                     new UpdateRelationRequest(this.User.User, RelationKind.ReportAsSpam))
                .Do(r =>
                    BackstageModel.RegisterEvent(
                        new BlockedEvent(reporter.GetPserudoUser(), this.User.User))))
            .Subscribe(
                _ => { },
                ex => BackstageModel.RegisterEvent(new InternalErrorEvent(ex.Message)), () =>
            {
                var tid    = this.Status.User.Id;
                var tidstr = tid.ToString(CultureInfo.InvariantCulture);
                StatusProxy.FetchStatuses(
                    s => s.User.Id == tid ||
                    (s.RetweetedOriginal != null && s.RetweetedOriginal.User.Id == tid),
                    "UserId = " + tidstr + " OR BaseUserId = " + tidstr)
                .Subscribe(s => StatusInbox.EnqueueRemoval(s.Id));
            });
        }
示例#22
0
 private static void SetupAccount(TwitterAccount info)
 {
     lock (_dictLock)
     {
         if (_dictionary.ContainsKey(info.Id))
         {
             return;
         }
         _dictionary.Add(info.Id, new LinkedList <TwitterStatus>());
         StatusProxy.FetchStatuses(
             s => s.User.Id == info.Id,
             "UserId = " + info.Id.ToString(CultureInfo.InvariantCulture),
             count: Setting.PostLimitPerWindow.Value)
         .Subscribe(PostDetected);
     }
 }
示例#23
0
 internal static void NotifyRetweeted(TwitterUser source, TwitterStatus status)
 {
     if (MuteBlockManager.IsBlocked(source))
     {
         return;
     }
     Task.Run(() => UserProxy.StoreUser(source));
     Task.Run(() => StatusModel.UpdateStatusInfo(
                  status.Id,
                  model => model.AddRetweetedUser(source), _ =>
     {
         StatusProxy.AddRetweeter(status.Id, source.Id);
         StatusBroadcaster.Republish(status);
     }));
     Head.NotifyRetweeted(source, status);
 }
示例#24
0
        public static async Task <TwitterStatus> GetTweetAsync(long id)
        {
            var status = await StatusProxy.GetStatusAsync(id).ConfigureAwait(false);

            if (status == null)
            {
                var acc = Setting.Accounts.GetRandomOne();
                if (acc == null)
                {
                    return(null);
                }
                status = await acc.ShowTweetAsync(id).ConfigureAwait(false);

                StatusInbox.Enqueue(status);
            }
            return(status);
        }
示例#25
0
        public static async Task <StatusModel> Get(TwitterStatus status)
        {
            return(GetIfCacheIsAlive(status.Id) ?? await _loader.StartNew(async() =>
            {
                if (status.GenerateFromJson)
                {
                    status = await StatusProxy.SyncStatusActivityAsync(status);
                }
                var rto = status.RetweetedOriginal == null
                              ? null
                              : await Get(status.RetweetedOriginal);
                var lockerobj = _generateLock.GetOrAdd(status.Id, new object());
                try
                {
                    lock (lockerobj)
                    {
                        StatusModel model;
                        WeakReference <StatusModel> wr;
                        _staticCache.TryGetValue(status.Id, out wr);
                        if (wr != null && wr.TryGetTarget(out model))
                        {
                            return model;
                        }

                        // cache is dead/not cached yet
                        model = new StatusModel(status, rto);
                        wr = new WeakReference <StatusModel>(model);
                        _staticCache[status.Id] = wr;
                        return model;
                    }
                }
                finally
                {
                    _generateLock.TryRemove(status.Id, out lockerobj);
                    // ReSharper disable InvertIf
#pragma warning disable 4014
                    if (Interlocked.Increment(ref _cleanupCount) == CleanupInterval)
                    {
                        Interlocked.Exchange(ref _cleanupCount, 0);
                        Task.Run((Action)CollectGarbages);
                    }
#pragma warning restore 4014
                    // ReSharper restore InvertIf
                }
            }).Unwrap());
        }
示例#26
0
 public static IObservable <TwitterStatus> GetTweet(long id)
 {
     return(StatusProxy.GetStatusAsync(id)
            .ToObservable()
            .Where(_ => _ != null)
            .ConcatIfEmpty(() =>
     {
         var acc = Setting.Accounts.GetRandomOne();
         if (acc == null)
         {
             return Observable.Empty <TwitterStatus>();
         }
         return acc.ShowTweetAsync(id)
         .ToObservable()
         .Do(StatusInbox.Enqueue);
     }));
 }
示例#27
0
        public static async Task <TwitterStatus> GetTweetAsync(long id)
        {
            var status = await StatusProxy.GetStatusAsync(id).ConfigureAwait(false);

            if (status == null)
            {
                var acc = Setting.Accounts.GetRandomOne();
                if (acc == null)
                {
                    return(null);
                }
                status = (await acc.CreateAccessor().ShowTweetAsync(id, CancellationToken.None)
                          .ConfigureAwait(false)).Result;
                StatusInbox.Enqueue(status);
            }
            return(status);
        }
示例#28
0
 protected override IObservable <TwitterStatus> Fetch(long?maxId, int?count)
 {
     if (_option == SearchOption.Web)
     {
         var acc = Setting.Accounts.GetRandomOne();
         if (acc == null)
         {
             return(Observable.Empty <TwitterStatus>());
         }
         return(acc.SearchAsync(this._query, maxId: maxId, count: count)
                .ToObservable()
                .Do(StatusInbox.Enqueue));
     }
     return(StatusProxy.FetchStatuses(this._filterFunc, this._filterSql, maxId, count)
            .Merge(this._filterQuery != null
                           ? this._filterQuery.ReceiveSources(maxId)
                           : Observable.Empty <TwitterStatus>()));
 }
示例#29
0
 internal static void NotifyUnfavorited(TwitterUser source, TwitterStatus status)
 {
     if (MuteBlockManager.IsBlocked(source))
     {
         return;
     }
     if (!NotificationLatch.CheckSetNegative(
             NotificationLatchTarget.Favorite, source.Id, status.Id))
     {
         return;
     }
     Task.Run(() => StatusModel.UpdateStatusInfo(
                  status.Id,
                  model => model.RemoveFavoritedUser(source.Id), _ =>
     {
         StatusProxy.RemoveFavoritor(status.Id, source.Id);
         StatusBroadcaster.Republish(status);
     }));
     Head.NotifyUnfavorited(source, status);
 }
示例#30
0
 private static void SetupAccount(TwitterAccount info)
 {
     lock (_dictLock)
     {
         if (_dictionary.ContainsKey(info.Id))
         {
             return;
         }
         _dictionary.Add(info.Id, new LinkedList <TwitterStatus>());
     }
     Task.Run(async() =>
     {
         var result = await StatusProxy.FetchStatuses(
             s => s.User.Id == info.Id,
             "UserId = " + info.Id.ToString(CultureInfo.InvariantCulture),
             count: Setting.PostLimitPerWindow.Value);
         result
         .OrderBy(c => c.CreatedAt)
         .ForEach(PostDetected);
     });
 }
示例#31
0
        /// <summary>
        /// Check received status is already existed or not.
        /// </summary>
        /// <param name="id">status id</param>
        /// <returns>if id is already existed, return true.</returns>
        private static async Task <bool> CheckAlreadyExisted(long id)
        {
            // check new status based on timestamps
            var stamp = GetTimestampFromSnowflakeId(id);

            if (_lastReceivedTimestamp == 0)
            {
                _lastReceivedTimestamp = stamp;
            }
            else if (stamp > _lastReceivedTimestamp)
            {
                _lastReceivedTimestamp = stamp;
                return(false); // new status
            }
            // check status based on model cache
            if (StatusModel.GetIfCacheIsAlive(id) != null)
            {
                return(true); // already existed
            }
            // check with database
            return(await StatusProxy.IsStatusExistsAsync(id).ConfigureAwait(false));
        }