public void GetUserTimelineQuery_ReturnsExpectedQuery()
        {
            // Arrange
            var queryGenerator = CreateTimelineQueryGenerator();

            var parameters = new GetUserTimelineParameters("linvi")
            {
                IncludeEntities           = true,
                TrimUser                  = true,
                IncludeContributorDetails = true,
                IncludeRetweets           = true,
                ExcludeReplies            = true,
                MaxId    = 42,
                SinceId  = 43,
                PageSize = 44,
                CustomQueryParameters = { new Tuple <string, string>("hello", "world") }
            };

            // Act
            var result = queryGenerator.GetUserTimelineQuery(parameters, ComputedTweetMode.Extended);

            // Assert
            Assert.Equal(result, $"https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=linvi&count=44&since_id=43&max_id=42" +
                         $"&include_entities=true&trim_user=true&tweet_mode=extended&exclude_replies=true&include_rts=true&hello=world");
        }
예제 #2
0
        private async Task <IEnumerable <ITweet> > RetrieveTweets(string username, DateTime earliest, DateTime latest)
        {
            var tweets = new List <ITweet>();
            IEnumerable <ITweet> fetched;

            var timelineParams = new GetUserTimelineParameters(username)
            {
                IncludeEntities = true,
                IncludeRetweets = true,
                PageSize        = 200
            };

            var finish = false;

            do
            {
                fetched = await client.Timelines.GetUserTimelineAsync(timelineParams);

                Log("Fetched page with: " + fetched.Count() + " tweets.");

                var fetchedInRange = fetched.Where(t => t.CreatedAt >= earliest && t.CreatedAt < latest);
                Log("➡ Found " + fetchedInRange.Count() + " tweets in range.");
                tweets.AddRange(fetchedInRange);

                if (fetched.Count() > 0)
                {
                    timelineParams.MaxId = fetched.Min(t => t.Id) - 1; Log("➡ New max id: " + timelineParams.MaxId);
                }

                finish = fetched.Count() == 0 || fetched.All(t => t.CreatedAt < earliest) || tweets.Count() >= API_LIMIT_MAX_TWEETS;
            } while (!finish);

            return(tweets);
        }
예제 #3
0
        public ITwitterPageIterator <ITwitterResult <ITweetDTO[]>, long?> GetUserTimelineIterator(IGetUserTimelineParameters parameters, ITwitterRequest request)
        {
            return(_pageCursorIteratorFactories.Create(parameters, cursor =>
            {
                var cursoredParameters = new GetUserTimelineParameters(parameters)
                {
                    MaxId = cursor
                };

                return _timelineQueryExecutor.GetUserTimeline(cursoredParameters, new TwitterRequest(request));
            }));
        }
예제 #4
0
        public async Task <IEnumerable <Update> > GetUpdatesAsync(string userId)
        {
            var parameters = new GetUserTimelineParameters(userId)
            {
                PageSize  = 10,
                TweetMode = TweetMode.Extended
            };

            ITweet[] tweets = await _twitterClient.Timelines.GetUserTimelineAsync(parameters);

            return(tweets
                   .Select(ToUpdate(userId)));
        }
예제 #5
0
        public void GetUserTimelineIterator_ReturnsFromPageCursorIteratorFactories()
        {
            // arrange
            var parameters = new GetUserTimelineParameters("linvi")
            {
                PageSize = 2
            };
            var request        = A.Fake <ITwitterRequest>();
            var expectedResult = A.Fake <ITwitterPageIterator <ITwitterResult <ITweetDTO[]>, long?> >();

            A.CallTo(() => _fakePageCursorIteratorFactories.Create(parameters, It.IsAny <Func <long?, Task <ITwitterResult <ITweetDTO[]> > > >()))
            .Returns(expectedResult);

            var controller = CreateTimelineController();
            var iterator   = controller.GetUserTimelineIterator(parameters, request);

            // assert
            Assert.Equal(iterator, expectedResult);
        }
예제 #6
0
        public async Task GetUserTimelineQuery_ReturnsTweetsAsync()
        {
            // Arrange
            var queryExecutor = CreateTimelineQueryExecutor();
            var expectedQuery = TestHelper.GenerateString();

            var parameters     = new GetUserTimelineParameters("linvi");
            var request        = A.Fake <ITwitterRequest>();
            var expectedResult = A.Fake <ITwitterResult <ITweetDTO[]> >();

            A.CallTo(() => _fakeTimelineQueryGenerator.GetUserTimelineQuery(parameters, It.IsAny <TweetMode?>())).Returns(expectedQuery);
            A.CallTo(() => _fakeTwitterAccessor.ExecuteRequestAsync <ITweetDTO[]>(request)).Returns(expectedResult);

            // Act
            var result = await queryExecutor.GetUserTimelineAsync(parameters, request);

            // Assert
            Assert.Equal(result, expectedResult);
            Assert.Equal(request.Query.Url, expectedQuery);
            Assert.Equal(HttpMethod.GET, request.Query.HttpMethod);
        }
예제 #7
0
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    var lastTweetIdTask = _twitterLogService.GetLastTweetId();

                    var user = await _twitterClient.Users.GetUserAsync(_twitterBotSettings.BotUsername);

                    long sinceTweetId = await lastTweetIdTask;

                    var tweets = new List <ITweet>();

                    await foreach (var followerId in GetFollowersIds(user))
                    {
                        var getTimeLineParameters = new GetUserTimelineParameters(followerId);

                        if (sinceTweetId == 0)
                        {
                            getTimeLineParameters.PageSize = _twitterBotSettings.TimelineFirstLoadPageSize;
                        }
                        else
                        {
                            getTimeLineParameters.SinceId = sinceTweetId;
                        }

                        var timeLine = await _twitterClient.Timelines.GetUserTimelineAsync(getTimeLineParameters);

                        if (timeLine.Length == 0)
                        {
                            continue;
                        }

                        // Avoid Retweets.
                        tweets.AddRange(timeLine.Where(v => !v.Text.StartsWith("RT")));
                    }

                    foreach (var tweet in tweets)
                    {
                        var tweetText = StringUtils.RemoveHashtags(StringUtils.RemoveMentions(tweet.Text));

                        var correctionsResult = await _grammarService.GetCorrections(tweetText);

                        if (correctionsResult.HasCorrections)
                        {
                            var messageBuilder = new StringBuilder();

                            var mentionedUsers = tweet.UserMentions.Select(v => v.ToString()).Join(" "); // Other users mentioned in the tweet
                            messageBuilder.Append($"@{tweet.CreatedBy.ScreenName} {mentionedUsers}");

                            foreach (var correction in correctionsResult.Corrections)
                            {
                                // Only suggest the first possible replacement for now
                                messageBuilder.AppendLine($"*{correction.PossibleReplacements.First()} [{correction.Message}]");
                            }

                            var correctionString = messageBuilder.ToString();

                            _logger.LogInformation($"Sending reply to: {tweet.CreatedBy.ScreenName}");
                            var publishTweetParameters = new PublishTweetParameters(correctionString)
                            {
                                InReplyToTweetId = tweet.Id,
                            };
                            var replyTweet = await _twitterClient.Tweets.PublishTweetAsync(publishTweetParameters);

                            if (replyTweet != null)
                            {
                                _logger.LogInformation("Reply sent successfuly");
                                await _twitterLogService.LogReply(tweet.Id, replyTweet.Id);
                            }

                            await Task.Delay(_twitterBotSettings.PublishTweetDelayMilliseconds);
                        }
                    }

                    if (tweets.Any())
                    {
                        var lastTweet = tweets.OrderByDescending(v => v.Id).First();

                        // Save last Tweet Id
                        await _twitterLogService.LogTweet(lastTweet.Id);
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, ex.Message);
                }

                await Task.Delay(_twitterBotSettings.HostedServiceIntervalMilliseconds);
            }
        }
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    var lastTweetIdTask = TwitterLogService.GetLastTweetId();

                    var followers = await TwitterClient.Users.GetFollowersAsync(TwitterBotSettings.BotUsername);

                    var friendIds = await TwitterClient.Users.GetFriendIdsAsync(TwitterBotSettings.BotUsername);

                    long sinceTweetId = await lastTweetIdTask;

                    var tweets = new List <ITweet>();

                    foreach (var follower in followers)
                    {
                        if (follower.Protected && !friendIds.Contains(follower.Id))
                        {
                            continue;
                        }

                        var getTimeLineParameters = new GetUserTimelineParameters(follower);

                        if (sinceTweetId == 0)
                        {
                            getTimeLineParameters.PageSize = TwitterBotSettings.TimelineFirstLoadPageSize;
                        }
                        else
                        {
                            getTimeLineParameters.SinceId = sinceTweetId;
                        }

                        var timeLine = await TwitterClient.Timelines.GetUserTimelineAsync(getTimeLineParameters);

                        if (timeLine.Length == 0)
                        {
                            continue;
                        }

                        // Avoid Retweets.
                        tweets.AddRange(timeLine.Where(v => !v.Text.StartsWith("RT")));
                    }

                    foreach (var tweet in tweets)
                    {
                        var tweetText = StringUtils.RemoveHashtags(StringUtils.RemoveMentions(StringUtils.RemoveEmojis(tweet.Text)));

                        var correctionsResult = await _grammarService.GetCorrections(tweetText);

                        if (!correctionsResult.HasCorrections)
                        {
                            continue;
                        }

                        var messageBuilder = new StringBuilder();

                        var mentionedUsers = tweet.UserMentions.Select(v => v.ToString()).Join(" "); // Other users mentioned in the tweet
                        messageBuilder.Append($"@{tweet.CreatedBy.ScreenName} {mentionedUsers} ");

                        foreach (var correction in correctionsResult.Corrections)
                        {
                            // Only suggest the first possible replacement
                            messageBuilder.AppendLine($"*{correction.PossibleReplacements.First()} [{correction.Message}]");
                        }

                        var correctionString = messageBuilder.ToString();

                        Logger.LogInformation($"Sending reply to: {tweet.CreatedBy.ScreenName}");

                        if (correctionString.Length >= Defaults.TwitterTextMaxLength)
                        {
                            var replyTweets = correctionString.SplitInParts(Defaults.TwitterTextMaxLength);

                            foreach (var(reply, index) in replyTweets.WithIndex())
                            {
                                var correctionStringSplitted = index == 0 ? reply : $"@{tweet.CreatedBy.ScreenName} {mentionedUsers} {reply}";

                                await PublishReplyTweet(correctionStringSplitted, tweet.Id);

                                await Task.Delay(TwitterBotSettings.PublishTweetDelayMilliseconds, stoppingToken);
                            }

                            continue;
                        }

                        await PublishReplyTweet(correctionString, tweet.Id);

                        await Task.Delay(TwitterBotSettings.PublishTweetDelayMilliseconds, stoppingToken);
                    }

                    if (tweets.Any())
                    {
                        var lastTweet = tweets.OrderByDescending(v => v.Id).First();

                        // Save last Tweet Id
                        await TwitterLogService.LogTweet(lastTweet.Id);
                    }

                    await FollowBackUsers(followers, friendIds);
                    await PublishScheduledTweets();
                    await LikeRepliesToBot(tweets);
                }
                catch (Exception ex)
                {
                    var message = ex is TwitterException tEx ? tEx.TwitterDescription : ex.Message;

                    Logger.LogError(ex, message);

                    // fire and forget
                    _ = _githubService.CreateBugIssue($"Application Exception: {message}", ex, GithubIssueLabels.Twitter);
                }

                await Task.Delay(TwitterBotSettings.HostedServiceIntervalMilliseconds);
            }
        }