///<summary>Revokeの回数を数えると同時に次回のツイート取得の延期を行う</summary> void MarkRevoked(UserStreamer Streamer) { var UserId = Streamer.Token.UserId; if (!RevokeRetryUserID.TryGetValue(UserId, out var status)) { status = 0; } switch (status) { //再試行毎に待ち時間を適当に延ばす case 0: //不規則なUnauthorized対策として再試行まで時間をおく //15分待てば大丈夫っぽいけどダメなときはダメ RevokeRetryUserID[UserId] = 1; Streamer.PostponeConnect(1200); break; case 1: RevokeRetryUserID[UserId] = 2; Streamer.PostponeConnect(); break; case 2: //つまり3(以上)になったらTokenを消す RevokeRetryUserID[UserId] = 3; break; default: //そんなバナナ UnmarkRevoked(Streamer); break; } }
///<summary>UserStreamerを生成して追加する</summary> bool Add(UserStreamer.UserStreamerSetting setting) { if (setting.Token == null) { return(false); } if (Streamers.ContainsKey(setting.Token.UserId)) { //Console.WriteLine("{0} {1}: Already running.", DateTime.Now, t.UserId); return(false); } else { //Console.WriteLine("{0} {1}: Assigned.", DateTime.Now, t.UserId); UserStreamer s = new UserStreamer(setting); return(Streamers.TryAdd(setting.Token.UserId, s)); } }
/// <summary> /// 指定したアカウントのツイート, フォロー等を取得する /// 新規ログイン向け /// 常に最大数のツイートを取得する /// </summary> /// <param name="user_id"></param> /// <returns></returns> public async Task OneAccount(long user_id) { var timeOut = Task.Run(async() => { await Task.Delay(60000).ConfigureAwait(false); Environment.Exit(1); }); var t = await db.SelectUserStreamerSetting(user_id).ConfigureAwait(false); if (!t.HasValue) { return; } //無条件でAPIの最大数のツイートを取得するためにToken以外は捨てる var s = new UserStreamer(new UserStreamer.UserStreamerSetting() { Token = t.Value.Token }); var friend = s.RestFriend(); var block = s.RestBlock(); var tweet = s.RestMyTweetMax(); var cred = s.VerifyCredentials(); var timeline = s.RestTimeline(); await Task.WhenAll(friend, block, tweet, cred, timeline).ConfigureAwait(false); Console.WriteLine("{0}: API access completed.", user_id); //ツイート等の取得を行ったことをDBに保存する var savesetting = s.Setting; savesetting.rest_my_tweet = false; var settingTask = db.StoreUserStreamerSetting(savesetting); var crawlInfoTask = s.LastReceivedTweetId != 0 ? db.StoreCrawlInfo_Timeline(s.Token.UserId, s.LastMessageTime.ToUnixTimeSeconds()) : Task.CompletedTask; await Task.WhenAll(settingTask, crawlInfoTask, UserStreamerStatic.Complete()).ConfigureAwait(false); Console.WriteLine("{0}: Profile stored\t{1}, {2}", user_id, friend.Result, block.Result); Counter.PrintReset(); }
/// <summary> /// サインインした全アカウントのツイート, フォロー等を取得する /// 常に最大数のツイートを取得する /// </summary> /// <returns></returns> public async Task <int> Proceed(bool getTweet = false) { var tokens = (await db.SelectUserStreamerSetting(DBHandler.SelectTokenMode.All).ConfigureAwait(false)).ToArray(); if (tokens.Length > 0) { Console.WriteLine("App: {0} Accounts to REST", tokens.Length); } var RestProcess = new ActionBlock <Tokens>(async(t) => { //無条件でAPIの最大数のツイートを取得するためにToken以外は捨てる var s = new UserStreamer(new UserStreamer.UserStreamerSetting() { Token = t }); await s.RestFriend().ConfigureAwait(false); await s.RestBlock().ConfigureAwait(false); if (getTweet) { await s.RestMyTweet().ConfigureAwait(false); } await s.VerifyCredentials().ConfigureAwait(false); }, new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = config.crawl.RestTweetThreads, BoundedCapacity = config.crawl.RestTweetThreads << 1 }); var sw = Stopwatch.StartNew(); foreach (var t in tokens) { await RestProcess.SendAsync(t.Token).ConfigureAwait(false); while (true) { if (sw.ElapsedMilliseconds > 60000) { Counter.PrintReset(); GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; //これは毎回必要らしい GC.Collect(); sw.Restart(); } //ツイートが詰まってたら休む if (UserStreamerStatic.NeedConnectPostpone()) { await Task.Delay(1000).ConfigureAwait(false); } else { break; } } } RestProcess.Complete(); await RestProcess.Completion.ConfigureAwait(false); await UserStreamerStatic.Complete().ConfigureAwait(false); Counter.PrintReset(); return(tokens.Length); }
///<summary>ツイート取得等に成功したTokenをRevoke再試行対象から外す</summary> bool UnmarkRevoked(UserStreamer Streamer) { return(RevokeRetryUserID.TryRemove(Streamer.Token.UserId, out _)); }