예제 #1
0
 public StatusNotification(TwitterStatus status, bool isAdded)
 {
     Debug.Assert(status != null, "status could not be null.");
     this.Status = status;
     this.StatusId = status.Id;
     this.IsAdded = isAdded;
 }
예제 #2
0
 public static bool IsMuted(TwitterStatus status)
 {
     return !AccountsStore.AccountIds.Contains(status.User.Id) &&
            (Setting.Muteds.Evaluator(status) || status.RetweetedOriginal != null &&
             Setting.ApplyMuteToRetweetOriginals.Value &&
             Setting.Muteds.Evaluator(status.RetweetedOriginal));
 }
예제 #3
0
 private bool CheckVisibleTimeline(TwitterStatus status, IEnumerable<AccountRelationData> datas)
 {
     if (status.StatusType == StatusType.DirectMessage)
         return false;
     return datas.Any(ad =>
         status.User.Id == ad.AccountId ||
         ad.IsFollowing(status.User.Id) ||
         FilterSystemUtil.InReplyToUsers(status).Contains(ad.AccountId));
 }
예제 #4
0
 public static IObservable<TwitterStatus> MergeStore(TwitterStatus status)
 {
     return StatusStore.Get(status.Id)
                       .ConcatIfEmpty(() =>
                       {
                           StatusStore.Store(status);
                           return Observable.Return(status);
                       });
 }
예제 #5
0
 /// <summary>
 /// Store a tweet.
 /// </summary>
 /// <param name="status">storing status</param>
 /// <param name="publish">flag of publish status for other listening children</param>
 public static void Store(TwitterStatus status, bool publish = true)
 {
     if (_isInShutdown) return;
     if (publish)
     {
         _statusPublisher.OnNext(new StatusNotification(status, true));
     }
     Task.Run(() => _store.Store(status));
     UserStore.Store(status.User);
 }
예제 #6
0
 public static IObservable<TwitterStatus> NotifyAndMergeStore(TwitterStatus status)
 {
     return StatusStore.Get(status.Id)
                       .ConcatIfEmpty(() =>
                       {
                           StatusStore.Store(status);
                           NotificationModel.NotifyNewArrival(status);
                           return Observable.Return(status);
                       });
 }
예제 #7
0
        public static async Task<StatusModel> Get(TwitterStatus status)
        {
            status = await StatusStore.Get(status.Id)
                                      .DefaultIfEmpty(status)
                                      .FirstAsync();
            var rto = status.RetweetedOriginal == null
                          ? null
                          : await Get(status.RetweetedOriginal);
            var lockerobj = _generateLock.GetOrAdd(status.Id, new object());
            try
            {
                lock (lockerobj)
                {
                    StatusModel model;
                    WeakReference wr;
                    lock (_staticCacheLock)
                    {
                        _staticCache.TryGetValue(status.Id, out wr);
                    }
                    if (wr != null)
                    {
                        model = (StatusModel)wr.Target;
                        if (model != null)
                        {
                            return model;
                        }
                    }

                    // cache is dead/not cached yet
                    model = new StatusModel(status, rto);
                    wr = new WeakReference(model);
                    lock (_staticCacheLock)
                    {
                        _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
            }
        }
예제 #8
0
        private static void PostDetected(TwitterStatus status)
        {
            // check timestamp
            if (status.CreatedAt < DateTime.Now - TimeSpan.FromSeconds(Setting.PostWindowTimeSec.Value))
            {
                return;
            }

            // lookup chunk
            LinkedList<TwitterStatus> statuses;
            lock (_dictLock)
            {
                if (!_dictionary.TryGetValue(status.User.Id, out statuses))
                {
                    return;
                }
            }

            lock (statuses)
            {
                // find insert position
                var afterThis =
                    statuses.First == null
                        ? null
                        : EnumerableEx.Generate(statuses.First, n => n.Next != null, n => n.Next, n => n)
                                      .TakeWhile(n => n.Value.Id >= status.Id)
                                      .LastOrDefault();
                if (afterThis == null)
                {
                    statuses.AddFirst(status);
                }
                else if (afterThis.Value.Id == status.Id)
                {
                    return;
                }
                else
                {
                    statuses.AddAfter(afterThis, status);
                }
                LinkedListNode<TwitterStatus> last;
                var stamp = DateTime.Now - TimeSpan.FromSeconds(Setting.PostWindowTimeSec.Value);
                while ((last = statuses.Last) != null)
                {
                    if (last.Value.CreatedAt >= stamp)
                    {
                        break;
                    }
                    // timeout
                    statuses.RemoveLast();
                }
            }
        }
예제 #9
0
 private bool CheckConversation(TwitterStatus status)
 {
     lock (_statuses)
     {
         if (_statuses.Contains(status.Id))
         {
             return true;
         }
         if (status.InReplyToStatusId == null) return false;
         if (_statuses.Contains(status.InReplyToStatusId.Value))
         {
             _statuses.Add(status.Id);
             return true;
         }
     }
     return false;
 }
예제 #10
0
 private StatusModel(TwitterStatus status)
 {
     Status = status;
     ImageResolver.Resolve(status.GetEntityAidedText(true))
                  .Aggregate(new List<Tuple<Uri, Uri>>(), (l, i) =>
                  {
                      l.Add(i);
                      return l;
                  })
                  .Finally(() =>
                  {
                      var subj = Interlocked.Exchange(ref _imagesSubject, null);
                      subj.OnCompleted();
                      subj.Dispose();
                  })
                  .Subscribe(l => Images = l);
 }
예제 #11
0
 public static IEnumerable<long> InReplyToUsers(TwitterStatus status)
 {
     if (status.Entities == null)
         return Enumerable.Empty<long>();
     return status.Entities
                  .Where(e => e.EntityType == EntityType.UserMentions)
                  .Select(e =>
                  {
                      try
                      {
                          return long.Parse(e.OriginalText);
                      }
                      catch
                      {
                          return 0;
                      }
                  }).Where(_ => _ != 0);
 }
예제 #12
0
        // ReSharper restore TooWideLocalVariableScope
        // ReSharper restore FunctionNeverReturns

        private static bool ValidateStatus(TwitterStatus status)
        {
            if (_cacheInvalid)
            {
                var nbs = new AVLTree<long>();
                AccountRelationDataStore.AccountRelations
                                        .SelectMany(a => a.Blockings)
                                        .ForEach(nbs.Add);
                _blockings = nbs;
                _cacheInvalid = false;
            }
            if (_predicateInvalid)
            {
                _muteEval = Setting.Muteds.Evaluator;
                _predicateInvalid = false;
            }
            if (_blockings.Contains(status.User.Id)) return false;
            if (_muteEval(status)) return false;

            return status.RetweetedOriginal == null || ValidateStatus(status.RetweetedOriginal);
        }
        private static void PostDetected(TwitterStatus status)
        {
            // check timestamp
            if (status.CreatedAt < DateTime.Now - TimeSpan.FromSeconds(Setting.PostWindowTimeSec.Value))
                return;

            // lookup chunk
            LinkedList<TwitterStatus> statuses;
            lock (_dictLock)
            {
                if (!_dictionary.TryGetValue(status.User.Id, out statuses)) return;
            }

            lock (statuses)
            {
                // find insert position
                var afterThis = statuses.FirstOrDefault(t => t.Id <= status.Id);
                // check duplication
                if (afterThis.Id == status.Id) return;
            }
        }
예제 #14
0
        private async void AddStatus(TwitterStatus status)
        {
            bool add;
            lock (_sicLocker)
            {
                add = _statusIdCache.AddDistinct(status.Id);
            }
            if (!add) return;
            // estimate point
            var model = await StatusModel.Get(status);
            var stamp = model.Status.CreatedAt;
            if (!this._isSuppressTimelineTrimming)
            {
                StatusModel lastModel;
                if (this.Statuses.TryIndexOf(TimelineChunkCount, out lastModel) &&
                    lastModel != null &&
                    lastModel.Status.CreatedAt > stamp)
                {
                    lock (this._sicLocker)
                    {
                        this._statusIdCache.Remove(model.Status.Id);
                    }
                    return;
                }
            }
            this._statuses.Insert(
                i => i.TakeWhile(s => s.Status.CreatedAt > stamp).Count(),
                model);
            if (this._statusIdCache.Count > TimelineChunkCount + TimelineChunkCountBounce &&
                Interlocked.Exchange(ref this._trimCount, 1) == 0)
            {
#pragma warning disable 4014
                Task.Run(() => this.TrimTimeline());
#pragma warning restore 4014
            }
            var handler = this.NewStatusArrival;
            if (handler != null)
                handler(status);
        }
예제 #15
0
 public static void NotifyFavorited(TwitterUser source, TwitterStatus target)
 {
     Action<TwitterStatusEvent> handler = OnFavorited;
     if (handler != null)
         handler(new TwitterStatusEvent(source, target));
 }
예제 #16
0
 public PostResult(AuthenticateInfo info, TwitterStatus status)
 {
     AuthInfo = info;
     IsSucceeded = true;
     Status = status;
 }
예제 #17
0
 public TwitterEventBase(TwitterUser source, TwitterStatus target)
     : this(source, target.User)
 {
     this._targetStatus = target;
 }
예제 #18
0
 private static IEnumerable<Inline> GenerateInlines(DependencyObject obj, TwitterStatus status)
 {
     if (status.RetweetedOriginal != null)
         status = status.RetweetedOriginal; // change target
     var escaped = XmlParser.EscapeEntity(status.Text);
     TwitterEntity prevEntity = null;
     foreach (var entity in status.Entities.Guard().OrderBy(e => e.StartIndex))
     {
         int pidx = 0;
         if (prevEntity != null)
             pidx = prevEntity.EndIndex;
         if (pidx < entity.StartIndex)
         {
             // output raw
             yield return GenerateText(XmlParser.ResolveEntity(escaped.Substring(pidx, entity.StartIndex - pidx)));
         }
         switch (entity.EntityType)
         {
             case EntityType.Hashtags:
                 yield return GenerateHashtagLink(obj, XmlParser.ResolveEntity(entity.DisplayText));
                 break;
             case EntityType.Media:
             case EntityType.Urls:
                 yield return GenerateLink(obj, entity.DisplayText, XmlParser.ResolveEntity(entity.OriginalText));
                 break;
             case EntityType.UserMentions:
                 yield return GenerateUserLink(obj, entity.DisplayText, XmlParser.ResolveEntity(entity.DisplayText));
                 break;
         }
         prevEntity = entity;
     }
     if (prevEntity == null)
     {
         yield return GenerateText(status.Text);
     }
     else if (prevEntity.EndIndex < status.Text.Length)
     {
         yield return GenerateText(
             XmlParser.ResolveEntity(escaped.Substring(prevEntity.EndIndex, status.Text.Length - prevEntity.EndIndex)));
     }
 }
예제 #19
0
 public static void SetTwitterStatus(DependencyObject obj, TwitterStatus value)
 {
     obj.SetValue(TwitterStatusProperty, value);
 }
예제 #20
0
 private StatusViewModel GenerateStatusViewModel(TwitterStatus status)
 {
     return new StatusViewModel(this, status, Model.BindingAccountIds);
 }
예제 #21
0
 public RetweetedEvent(TwitterUser source, TwitterStatus target)
     : base(source, target)
 {
 }
예제 #22
0
 public static void UpdateStatusInfo(TwitterStatus status,
                                     Action<StatusModel> ifCacheIsAlive,
                                     Action<TwitterStatus> ifCacheIsDead)
 {
     WeakReference wr;
     lock (_staticCacheLock)
     {
         _staticCache.TryGetValue(status.Id, out wr);
     }
     if (wr != null)
     {
         var target = (StatusModel)wr.Target;
         if (wr.IsAlive)
         {
             ifCacheIsAlive(target);
             StatusStore.Store(target.Status);
             return;
         }
     }
     StatusStore.Get(status.Id)
                .DefaultIfEmpty(status)
                .Subscribe(s =>
                {
                    ifCacheIsDead(s);
                    StatusStore.Store(s);
                });
 }
예제 #23
0
 private StatusModel(TwitterStatus status, StatusModel retweetedOriginal)
     : this(status)
 {
     this.RetweetedOriginal = retweetedOriginal;
 }
예제 #24
0
 public TwitterStatusEvent(TwitterUser source, TwitterStatus target)
 {
     Source = source;
     Target = target;
 }
예제 #25
0
 public TrophyScceededEvent(TwitterStatus status)
 {
     Status = status;
 }
예제 #26
0
 public static void NotifyDeleted(TwitterStatus deleted)
 {
     Action<TwitterStatus> handler = OnDeleted;
     if (handler != null)
         handler(deleted);
 }
예제 #27
0
 public FavoritedEvent(TwitterUser source, TwitterStatus target)
     : base(source, target)
 {
 }
예제 #28
0
 public static void NotifyReceived(TwitterStatus status)
 {
     Action<TwitterStatus> handler = OnReceived;
     if (handler != null)
         handler(status);
 }
예제 #29
0
 public TrophyFailedEvent(TwitterStatus status, string response)
 {
     Status = status;
     Response = response;
 }
예제 #30
0
 public static void NotifyRetweeted(TwitterUser source, TwitterStatus status)
 {
     Action<TwitterStatusEvent> handler = OnRetweeted;
     if (handler != null)
         handler(new TwitterStatusEvent(source, status));
 }