linvi/tweetinvi

TwitterException Code -1

Devtr0n opened this issue · 3 comments

What exactly does TwitterException Code -1 mean? It is not covered in the Wiki...

image

And for what it's worth...

   at Tweetinvi.Streams.StreamTask.<RunStreamAsync>d__25.MoveNext()
   at Tweetinvi.Streams.StreamTask.<StartAsync>d__24.MoveNext()
   at Tweetinvi.Streams.Helpers.StreamResultGenerator.<StartAsync>d__24.MoveNext()
   at Tweetinvi.Streams.Helpers.StreamResultGenerator.<StartAsync>d__23.MoveNext()
   at Tweetinvi.Streams.TweetStreamV2`1.<StartAsync>d__9.MoveNext()
   at API.Worker.TweetProcessor.<ProcessTweets>d__6.MoveNext() in C:\Workspace\TwitterAnalytics\Server\API\Worker\TweetProcessor.cs:line 55
   at API.Worker.TweetWorker.<ExecuteAsync>d__3.MoveNext() in C:\Workspace\TwitterAnalytics\Server\API\Worker\TweetWorker.cs:line 26

Ok, I figured out what makes Code - 1 occur. It happens for me when my TwitterClient has null credentials (secret key, bearer token, etc). When those are null, the stream obviously cannot iterate over any results, hence this "MoveNext" error. This was happening for me because I was trying to inject the TwitterClient into my integration test project. It was not picking up the configuration values from the other/WebAPI main project, so once I fixed that, it was all gravy.

It would be really nice if the "TwitterClient" was smart enough to tell me that the credentials are completely missing. Code -1 is not in the wiki or documentation anywhere here, so I had to turn into Sherlock Holmes.

In case anybody cares, here is the .NET 6 middleware I ended up using for my Integration test project. It uses two configuration files, one for local test project, and one from the main API project that stores my secret keys and token for Twitter Developer API.

using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Net.Http;
using Tweetinvi;
using Tweetinvi.Models;
using Xunit;

namespace API.IntegrationTests
{
    [CollectionDefinition("IntegrationTest")]
    public abstract class TestScenarioBase
    {
        // create a "client" for the "test" server
        protected readonly HttpClient Client = Server.CreateClient();

        // create a "test" server to run integration tests against
        protected static readonly WebApplicationFactory<Program> Server = CreateServer();

        private static WebApplicationFactory<Program> CreateServer()
        {
            // fetch configuration settings for base address uri with port number
            var integrationTestConfig = new ConfigurationBuilder().AddJsonFile($"appSettings.test.json", true, true).Build();
            var baseAddress = new Uri(integrationTestConfig["IntegrationTestServer:BaseAddress"]);

            // use the API configuration file in a different project
            var apiConfig = new ConfigurationBuilder()
                .SetBasePath(AppContext.BaseDirectory)
                .AddJsonFile("appsettings.json", false, true)
                .Build();

            // fetch the Twitter credentials from API project configuration
            var bearerToken = apiConfig["Twitter:BearerToken"];
            var consumerKey = apiConfig["Twitter:ConsumerKey"];
            var consumerSecret = apiConfig["Twitter:ConsumerSecret"];
            var userCredentials = new TwitterCredentials(consumerKey, consumerSecret, bearerToken);

            // create a test web application from factory based on the API entry point & middleware in a different project (API)
            var application = new WebApplicationFactory<Program>()
                .WithWebHostBuilder(builder =>
                {
                    // set the "test server" uri with port number
                    builder.UseTestServer(testServer =>
                    {
                        testServer.BaseAddress = baseAddress;
                    });

                    // define the middleware for test services
                    builder.ConfigureTestServices(x => x.AddSingleton(sp => { return new TwitterClient(userCredentials); }));
                });

            // instruct the client to use the uri with port number
            application.ClientOptions.BaseAddress = baseAddress;

            return application;
        }
    }
}

In case anybody cares, here is the .NET 6 middleware I ended up using for my Integration test project. It uses two configuration files, one for local test project, and one from the main API project that stores my secret keys and token for Twitter Developer API.

using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Net.Http;
using Tweetinvi;
using Tweetinvi.Models;
using Xunit;

namespace API.IntegrationTests
{
    [CollectionDefinition("IntegrationTest")]
    public abstract class TestScenarioBase
    {
        // create a "client" for the "test" server
        protected readonly HttpClient Client = Server.CreateClient();

        // create a "test" server to run integration tests against
        protected static readonly WebApplicationFactory<Program> Server = CreateServer();

        private static WebApplicationFactory<Program> CreateServer()
        {
            // fetch configuration settings for base address uri with port number
            var integrationTestConfig = new ConfigurationBuilder().AddJsonFile($"appSettings.test.json", true, true).Build();
            var baseAddress = new Uri(integrationTestConfig["IntegrationTestServer:BaseAddress"]);

            // use the API configuration file in a different project
            var apiConfig = new ConfigurationBuilder()
                .SetBasePath(AppContext.BaseDirectory)
                .AddJsonFile("appsettings.json", false, true)
                .Build();

            // fetch the Twitter credentials from API project configuration
            var bearerToken = apiConfig["Twitter:BearerToken"];
            var consumerKey = apiConfig["Twitter:ConsumerKey"];
            var consumerSecret = apiConfig["Twitter:ConsumerSecret"];
            var userCredentials = new TwitterCredentials(consumerKey, consumerSecret, bearerToken);

            // create a test web application from factory based on the API entry point & middleware in a different project (API)
            var application = new WebApplicationFactory<Program>()
                .WithWebHostBuilder(builder =>
                {
                    // set the "test server" uri with port number
                    builder.UseTestServer(testServer =>
                    {
                        testServer.BaseAddress = baseAddress;
                    });

                    // define the middleware for test services
                    builder.ConfigureTestServices(x => x.AddSingleton(sp => { return new TwitterClient(userCredentials); }));
                });

            // instruct the client to use the uri with port number
            application.ClientOptions.BaseAddress = baseAddress;

            return application;
        }
    }
}

With this I was able to figure out that my issue was that I wasn't passing in bearerToken. Thank you.