Пример #1
0
        public TwitterBot(TwitterSettings settings, PokeTradeHub <PK8> hub)
        {
            Hub      = hub;
            Settings = settings;

            client = new TwitterClient(Settings.ConsumerKey, Settings.ConsumerSecret, Settings.AccessToken, Settings.AccessTokenSecret);

            client.Events.OnTwitterException += HandleTwitterException;

            try
            {
                var taskAuthenticate = Task.Run(async() => await client.Users.GetAuthenticatedUserAsync());
                TwitterUser = taskAuthenticate.Result;
                LogUtil.LogText($"Successfully authenticated as: @{TwitterUser.ScreenName}");

                MentionParams = new GetMentionsTimelineParameters {
                    PageSize = Settings.MentionCount
                };
                var taskGetInitialMentions = Task.Run(async() => await client.Timelines.GetMentionsTimelineAsync(MentionParams));
                localMentions = new TwitterMentions(taskGetInitialMentions.Result);
                Task.Run(() => CheckMentionsForTradesAsync(localMentions, CancellationToken.None));
            }
            catch (Exception e)
            {
                LogUtil.LogError($"Unable to authenticate with error: {e.Message}", nameof(TwitterBot));
            }
        }
Пример #2
0
        public async Task <ITweet[]> FetchMentionsAsync(IEnumerable <long> inFlight)
        {
            try
            {
                var parameters    = new GetMentionsTimelineParameters();
                var latestMention = await _repository.GetLatestMention();

                if (latestMention != null)
                {
                    Log.Information("Latest mention {Mention} on {Date}", latestMention.TweetId, latestMention.Timestamp);
                    parameters.SinceId = latestMention.TweetId;
                }
                var mentions = await _client.Timelines.GetMentionsTimelineAsync(parameters);

                var alreadyReplied = await _repository.FindByTweetId(mentions.Select(it => it.Id));

                var repliedIds = alreadyReplied.Select(it => it.TweetId);
                return(mentions
                       .Where(it => !repliedIds.Contains(it.Id))
                       .Where(it => !inFlight.Contains(it.Id))
                       .ToArray());
            }
            catch (Exception e)
            {
                Log.Error(e, "Failed to fetch tweets");
                return(Array.Empty <ITweet>());
            }
        }
Пример #3
0
        public ITwitterPageIterator <ITwitterResult <ITweetDTO[]>, long?> GetMentionsTimelineIterator(IGetMentionsTimelineParameters parameters, ITwitterRequest request)
        {
            return(_pageCursorIteratorFactories.Create(parameters, cursor =>
            {
                var cursoredParameters = new GetMentionsTimelineParameters(parameters)
                {
                    MaxId = cursor
                };

                return _timelineQueryExecutor.GetMentionsTimeline(cursoredParameters, new TwitterRequest(request));
            }));
        }
Пример #4
0
        public void GetMentionsTimelineIterator_ReturnsFromPageCursorIteratorFactories()
        {
            // arrange
            var parameters = new GetMentionsTimelineParameters {
                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.GetMentionsTimelineIterator(parameters, request);

            // assert
            Assert.Equal(iterator, expectedResult);
        }
Пример #5
0
        public async Task GetMentionsTimelineQuery_ReturnsTweetsAsync()
        {
            // Arrange
            var queryExecutor = CreateTimelineQueryExecutor();
            var expectedQuery = TestHelper.GenerateString();

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

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

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

            // Assert
            Assert.Equal(result, expectedResult);
            Assert.Equal(request.Query.Url, expectedQuery);
            Assert.Equal(HttpMethod.GET, request.Query.HttpMethod);
        }
        public void GetMentionsTimelineQuery_ReturnsExpectedQuery()
        {
            // Arrange
            var queryGenerator = CreateTimelineQueryGenerator();

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

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

            // Assert
            Assert.Equal(result, $"https://api.twitter.com/1.1/statuses/mentions_timeline.json?count=44&since_id=43&max_id=42" +
                         $"&include_entities=true&trim_user=true&tweet_mode=extended&hello=world");
        }
Пример #7
0
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        Logger.LogInformation("TwitterBotMentionHostedService started");

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                long lastTweetId = await _twitterMentionLogService.GetLastTweetId();

                var getMentionParameters = new GetMentionsTimelineParameters();

                if (lastTweetId == 0)
                {
                    getMentionParameters.PageSize = TwitterBotSettings.TimelineFirstLoadPageSize;
                }
                else
                {
                    getMentionParameters.SinceId = lastTweetId;
                }

                var mentions = await TwitterClient.Timelines.GetMentionsTimelineAsync(getMentionParameters);

                var myUser = await TwitterClient.Users.GetUserAsync(TwitterBotSettings.BotUsername);

                foreach (var mention in mentions.Where(x => x.Text.Contains($"@{TwitterBotSettings.BotUsername}") && (x.InReplyToStatusId.HasValue || x.QuotedStatusId.HasValue)))
                {
                    // Avoid correcting replies to my own tweets
                    if (mention.InReplyToUserId == myUser.Id)
                    {
                        continue;
                    }

                    var tweet = await GetTweetFromMention(mention);

                    if (tweet == null)
                    {
                        continue;
                    }

                    var tweetText = StringUtils.RemoveHashtags(StringUtils.RemoveMentions(StringUtils.RemoveEmojis(tweet.Text)));

                    var correctionsResult = await _grammarService.GetCorrections(tweetText);

                    if (!correctionsResult.HasCorrections)
                    {
                        await PublishReplyTweet($"@{mention.CreatedBy.ScreenName} I don't see anything wrong here.", mention.Id);

                        continue;
                    }

                    var messageBuilder = new StringBuilder();

                    messageBuilder.Append($"@{mention.CreatedBy.ScreenName}");

                    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: {mention.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 : $"@{mention.CreatedBy.ScreenName} {reply}";

                            await PublishReplyTweet(correctionStringSplitted, mention.Id);

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

                        continue;
                    }

                    await PublishReplyTweet(correctionString, mention.Id);

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

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

                    // Save last Tweet Id
                    await _twitterMentionLogService.LogTweet(lastTweet.Id, default);
                }

                var followersTask = TwitterClient.Users.GetFollowersAsync(TwitterBotSettings.BotUsername);
                var friendIdsTask = TwitterClient.Users.GetFriendIdsAsync(TwitterBotSettings.BotUsername);

                await FollowBackUsers(await followersTask, await friendIdsTask);
                await PublishScheduledTweets();
                await LikeRepliesToBot(mentions);
            }
            // TODO: Move all this to some "CatchExceptionService"
            catch (TwitterException ex) when(ex.TwitterDescription.Contains("Try again later") || ex.TwitterDescription.Contains("Timeout limit"))
            {
                Logger.LogWarning(ex, ex.TwitterDescription);
            }
            catch (SqlException ex) when(ex.Message.Contains("SHUTDOWN"))
            {
                Logger.LogWarning(ex, "Sql Server shutdown in progress");
            }
            catch (Exception ex)
            {
                var message = ex is TwitterException tEx ? tEx.TwitterDescription : ex.Message;

                var innerExceptions = ex.GetInnerExceptions();

                if (innerExceptions.Any(x => x.GetType() == typeof(SocketException) && x.Message.Contains("Connection reset by peer")))
                {
                    // The server has reset the connection.
                    Logger.LogWarning(ex, "Socket reseted.");
                }
                else
                {
                    Logger.LogError(ex, message);

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

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