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(); } }
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>())); }
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); }); } }); }
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 } } }
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 } } }
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(); } }
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 } } }
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); }
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); } }
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 } } }
private static async Task UpdateTweetCount() { try { _estimatedGrossTweetCount = (int)(await StatusProxy.GetCountAsync()); } catch (SQLiteException) { } }
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)); }
private static async Task UpdateTweetCount() { try { var dbcount = (int)(await StatusProxy.GetCountAsync().ConfigureAwait(false)); _estimatedGrossTweetCount = dbcount + _queuedStatusesCount; } catch (SqliteCrudException) { } catch (SQLiteException) { } }
private async Task <long> FindHeadAsync(long id) { var irt = await StatusProxy.GetInReplyToAsync(id); if (irt == null) { return(id); } return(await this.FindHeadAsync(irt.Value)); }
public StatusProxy(string appid,string value) : this() { AppId = appid; Value = value; _original=new StatusProxy() { AppId = appid, Value = value }; }
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); }
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)); }); }
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); } }
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); }
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); }
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()); }
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); })); }
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); }
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>())); }
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); }
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); }); }
/// <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)); }