Skip to content

Commit 0e50453

Browse files
josiasalexandrejosiasal
authored andcommitted
Add initial support for Twitter V2 Timelines
1 parent 0207234 commit 0e50453

File tree

16 files changed

+443
-1
lines changed

16 files changed

+443
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using Tweetinvi.Core.Iterators;
4+
using Tweetinvi.Core.Controllers.V2;
5+
using Tweetinvi.Core.Web;
6+
using Tweetinvi.Models;
7+
using Tweetinvi.Models.V2;
8+
using Tweetinvi.Parameters.V2;
9+
10+
namespace Tweetinvi.Controllers.Timeline
11+
{
12+
public class TimelinesV2Controller : ITimelinesV2Controller
13+
{
14+
private readonly ITimelinesV2QueryExecutor _queryExecutor;
15+
16+
public TimelinesV2Controller(ITimelinesV2QueryExecutor queryExecutor)
17+
{
18+
_queryExecutor = queryExecutor;
19+
}
20+
21+
private ITwitterPageIterator<ITwitterResult<TimelinesV2Response>, string> GetIterator(
22+
Func<IGetTimelinesV2Parameters, ITwitterRequest, Task<ITwitterResult<TimelinesV2Response>>> Method,
23+
IGetTimelinesV2Parameters parameters,
24+
ITwitterRequest request)
25+
{
26+
Func<string, Task<ITwitterResult<TimelinesV2Response>>> getNext = nextToken =>
27+
{
28+
var cursoredParameters = new GetTimelinesV2Parameters(parameters)
29+
{
30+
PaginationToken = nextToken
31+
};
32+
33+
return Method(cursoredParameters, request);
34+
};
35+
36+
var twitterCursorResult = new TwitterPageIterator<ITwitterResult<TimelinesV2Response>, string>(
37+
parameters.PaginationToken,
38+
getNext,
39+
page =>
40+
{
41+
if (page.Model.Tweets.Length == 0)
42+
{
43+
return null;
44+
}
45+
46+
return page.Model.Meta.NextToken;
47+
},
48+
page =>
49+
{
50+
if (page.Model.Tweets.Length == 0)
51+
{
52+
return true;
53+
}
54+
55+
return page.Model.Meta.NextToken == null;
56+
});
57+
58+
return twitterCursorResult;
59+
}
60+
61+
public ITwitterPageIterator<ITwitterResult<TimelinesV2Response>, string> GetUserTweetsTimelineIterator(IGetTimelinesV2Parameters parameters, ITwitterRequest request)
62+
{
63+
return GetIterator(_queryExecutor.GetUserTweetsTimelineAsync, parameters, request);
64+
}
65+
66+
public ITwitterPageIterator<ITwitterResult<TimelinesV2Response>, string> GetUserMentionedTimelineIterator(IGetTimelinesV2Parameters parameters, ITwitterRequest request)
67+
{
68+
return GetIterator(_queryExecutor.GetUserMentionedTimelineAsync, parameters, request);
69+
}
70+
}
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System.Threading.Tasks;
2+
using Tweetinvi.Core.QueryGenerators.V2;
3+
using Tweetinvi.Core.Web;
4+
using Tweetinvi.Models;
5+
using Tweetinvi.Models.V2;
6+
using Tweetinvi.Parameters.V2;
7+
8+
namespace Tweetinvi.Controllers.Timeline
9+
{
10+
public interface ITimelinesV2QueryExecutor
11+
{
12+
Task<ITwitterResult<TimelinesV2Response>> GetUserTweetsTimelineAsync(IGetTimelinesV2Parameters parameters, ITwitterRequest request);
13+
Task<ITwitterResult<TimelinesV2Response>> GetUserMentionedTimelineAsync(IGetTimelinesV2Parameters parameters, ITwitterRequest request);
14+
}
15+
16+
public class TimelinesV2QueryExecutor : ITimelinesV2QueryExecutor
17+
{
18+
private readonly JsonContentFactory _jsonContentFactory;
19+
private readonly ITimelinesV2QueryGenerator _timelinesQueryGenerator;
20+
private readonly ITwitterAccessor _twitterAccessor;
21+
22+
public TimelinesV2QueryExecutor(
23+
JsonContentFactory jsonContentFactory,
24+
ITimelinesV2QueryGenerator timelinesQueryGenerator,
25+
ITwitterAccessor twitterAccessor)
26+
{
27+
_jsonContentFactory = jsonContentFactory;
28+
_timelinesQueryGenerator = timelinesQueryGenerator;
29+
_twitterAccessor = twitterAccessor;
30+
}
31+
32+
public Task<ITwitterResult<TimelinesV2Response>> GetUserTweetsTimelineAsync(IGetTimelinesV2Parameters parameters, ITwitterRequest request)
33+
{
34+
request.Query.Url = _timelinesQueryGenerator.GetTimelineQuery(parameters);
35+
request.Query.HttpMethod = HttpMethod.GET;
36+
return _twitterAccessor.ExecuteRequestAsync<TimelinesV2Response>(request);
37+
}
38+
public Task<ITwitterResult<TimelinesV2Response>> GetUserMentionedTimelineAsync(IGetTimelinesV2Parameters parameters, ITwitterRequest request)
39+
{
40+
request.Query.Url = _timelinesQueryGenerator.GetMentionTimelineQuery(parameters);
41+
return _twitterAccessor.ExecuteRequestAsync<TimelinesV2Response>(request);
42+
}
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using System.Text;
2+
using Tweetinvi.Controllers.Properties;
3+
using Tweetinvi.Core.Extensions;
4+
using Tweetinvi.Core.QueryGenerators.V2;
5+
using Tweetinvi.Parameters.V2;
6+
7+
namespace Tweetinvi.Controllers.Timeline
8+
{
9+
public class TimelinesV2QueryGenerator : ITimelinesV2QueryGenerator
10+
{
11+
private readonly ITweetsV2QueryGenerator _tweetsV2QueryGenerator;
12+
13+
public TimelinesV2QueryGenerator(ITweetsV2QueryGenerator tweetsV2QueryGenerator)
14+
{
15+
_tweetsV2QueryGenerator = tweetsV2QueryGenerator;
16+
}
17+
18+
public string GetTimelineQuery(IGetTimelinesV2Parameters parameters)
19+
{
20+
var query = new StringBuilder($"{Resources.UserV2_Get}/{parameters.UserId}/tweets");
21+
AddTimelineFieldsParameters(parameters, query);
22+
query.AddFormattedParameterToQuery(parameters.FormattedCustomQueryParameters);
23+
return query.ToString();
24+
}
25+
26+
public string GetMentionTimelineQuery(IGetTimelinesV2Parameters parameters)
27+
{
28+
var query = new StringBuilder($"{Resources.UserV2_Get}/{parameters.UserId}/mentions");
29+
AddTimelineFieldsParameters(parameters, query);
30+
query.AddFormattedParameterToQuery(parameters.FormattedCustomQueryParameters);
31+
return query.ToString();
32+
}
33+
34+
public void AddTimelineFieldsParameters(IGetTimelinesV2Parameters parameters, StringBuilder query)
35+
{
36+
_tweetsV2QueryGenerator.AddTweetFieldsParameters(parameters, query);
37+
38+
// specific timeline parameters
39+
query.AddParameterToQuery("exclude", parameters.Exclude);
40+
query.AddParameterToQuery("max_results", parameters.MaxResults);
41+
query.AddParameterToQuery("pagination_token", parameters.PaginationToken);
42+
query.AddParameterToQuery("since_id", parameters.SinceId);
43+
query.AddParameterToQuery("start_time", parameters.StartTime?.ToString("yyy-MM-ddThh:mm:ssZ"));
44+
query.AddParameterToQuery("end_time", parameters.EndTime?.ToString("yyy-MM-ddThh:mm:ssZ"));
45+
query.AddParameterToQuery("until_id", parameters.UntilId);
46+
}
47+
}
48+
}

src/Tweetinvi.Controllers/TweetinviControllersModule.cs

+3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ private void InitializeControllers(ITweetinviContainer container)
5252
container.RegisterType<ISearchV2Controller, SearchV2Controller>(RegistrationLifetime.InstancePerApplication);
5353
container.RegisterType<ITweetsV2Controller, TweetsV2Controller>(RegistrationLifetime.InstancePerApplication);
5454
container.RegisterType<IUsersV2Controller, UsersV2Controller>(RegistrationLifetime.InstancePerApplication);
55+
container.RegisterType<ITimelinesV2Controller, TimelinesV2Controller>(RegistrationLifetime.InstancePerApplication);
5556

5657
container.RegisterType<IStreamsV2Controller, StreamsV2Controller>(RegistrationLifetime.InstancePerApplication);
5758
}
@@ -77,6 +78,7 @@ private void InitializeQueryExecutors(ITweetinviContainer container)
7778
container.RegisterType<ISearchV2QueryExecutor, SearchV2QueryExecutor>();
7879
container.RegisterType<ITweetsV2QueryExecutor, TweetsV2QueryExecutor>();
7980
container.RegisterType<IUsersV2QueryExecutor, UsersV2QueryExecutor>();
81+
container.RegisterType<ITimelinesV2QueryExecutor, TimelinesV2QueryExecutor>();
8082

8183
container.RegisterType<IStreamsV2QueryExecutor, StreamsV2QueryExecutor>(RegistrationLifetime.InstancePerApplication);
8284
}
@@ -107,6 +109,7 @@ private void InitializeQueryGenerators(ITweetinviContainer container)
107109
container.RegisterType<ISearchV2QueryGenerator, SearchV2QueryGenerator>(RegistrationLifetime.InstancePerApplication);
108110
container.RegisterType<ITweetsV2QueryGenerator, TweetsV2QueryGenerator>(RegistrationLifetime.InstancePerApplication);
109111
container.RegisterType<IUsersV2QueryGenerator, UsersV2QueryGenerator>(RegistrationLifetime.InstancePerApplication);
112+
container.RegisterType<ITimelinesV2QueryGenerator, TimelinesV2QueryGenerator>(RegistrationLifetime.InstancePerApplication);
110113

111114
container.RegisterType<IStreamsV2QueryGenerator, StreamsV2QueryGenerator>(RegistrationLifetime.InstancePerApplication);
112115
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using Tweetinvi.Core.Iterators;
2+
using Tweetinvi.Core.Web;
3+
using Tweetinvi.Models;
4+
using Tweetinvi.Models.V2;
5+
using Tweetinvi.Parameters.V2;
6+
7+
namespace Tweetinvi.Core.Controllers.V2
8+
{
9+
public interface ITimelinesV2Controller
10+
{
11+
ITwitterPageIterator<ITwitterResult<TimelinesV2Response>, string> GetUserTweetsTimelineIterator(IGetTimelinesV2Parameters parameters, ITwitterRequest request);
12+
ITwitterPageIterator<ITwitterResult<TimelinesV2Response>, string> GetUserMentionedTimelineIterator(IGetTimelinesV2Parameters parameters, ITwitterRequest request);
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System.Text;
2+
using Tweetinvi.Parameters.V2;
3+
4+
namespace Tweetinvi.Core.QueryGenerators.V2
5+
{
6+
public interface ITimelinesV2QueryGenerator
7+
{
8+
string GetTimelineQuery(IGetTimelinesV2Parameters parameters);
9+
string GetMentionTimelineQuery(IGetTimelinesV2Parameters parameters);
10+
void AddTimelineFieldsParameters(IGetTimelinesV2Parameters parameters, StringBuilder query);
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Tweetinvi.Iterators;
2+
using Tweetinvi.Models.V2;
3+
using Tweetinvi.Parameters.V2;
4+
5+
namespace Tweetinvi.Client.V2
6+
{
7+
public interface ITimelinesV2Client
8+
{
9+
/// <summary>
10+
/// Returns Tweets composed by a single user, specified by the requested user ID. By default,
11+
/// the most recent ten Tweets are returned per request. Using pagination, the most recent
12+
/// 3,200 Tweets can be retrieved.
13+
/// <para>Read more : https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets </para>
14+
/// </summary>
15+
/// <returns>The Timeline</returns>
16+
ITwitterRequestIterator<TimelinesV2Response, string> GetUserTweetsTimelineIterator(IGetTimelinesV2Parameters parameters);
17+
18+
/// <summary>
19+
/// Returns Tweets mentioning a single user specified by the requested user ID. By default,
20+
/// the most recent ten Tweets are returned per request. Using pagination, up to the most
21+
/// recent 800 Tweets can be retrieved.
22+
/// <para>Read more : https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-mentions </para>
23+
/// </summary>
24+
ITwitterRequestIterator<TimelinesV2Response, string> GetUserMentionedTimelineIterator(IGetTimelinesV2Parameters parameters);
25+
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Tweetinvi.Core.Iterators;
2+
using Tweetinvi.Core.Web;
3+
using Tweetinvi.Models.V2;
4+
using Tweetinvi.Parameters.V2;
5+
6+
namespace Tweetinvi.Client.Requesters.V2
7+
{
8+
public interface ITimelinesV2Requester
9+
{
10+
/// <summary>
11+
/// Returns Tweets composed by a single user, specified by the requested user ID. By default,
12+
/// the most recent ten Tweets are returned per request. Using pagination, the most recent
13+
/// 3,200 Tweets can be retrieved.
14+
/// <para>Read more : https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets </para>
15+
/// </summary>
16+
/// <returns>The Timeline</returns>
17+
ITwitterPageIterator<ITwitterResult<TimelinesV2Response>, string> GetUserTweetsTimelineIterator(IGetTimelinesV2Parameters parameters);
18+
19+
/// <summary>
20+
/// Returns Tweets mentioning a single user specified by the requested user ID. By default,
21+
/// the most recent ten Tweets are returned per request. Using pagination, up to the most
22+
/// recent 800 Tweets can be retrieved.
23+
/// <para>Read more : https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-mentions </para>
24+
/// </summary>
25+
ITwitterPageIterator<ITwitterResult<TimelinesV2Response>, string> GetUserMentionedTimelineIterator(IGetTimelinesV2Parameters parameters);
26+
}
27+
}

src/Tweetinvi.Core/Public/ITwitterClient.cs

-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ public interface ITwitterClient
129129
/// </summary>
130130
IParametersValidator ParametersValidator { get; }
131131

132-
133132
/// <summary>
134133
/// Creates skeleton request representing a request from the client
135134
/// </summary>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Newtonsoft.Json;
2+
3+
namespace Tweetinvi.Models.V2
4+
{
5+
public class TimelinesV2Response
6+
{
7+
/// <summary>
8+
/// Tweets returned by the request
9+
/// </summary>
10+
[JsonProperty("data")] public TweetV2[] Tweets { get; set; } = new TweetV2[0];
11+
12+
/// <summary>
13+
/// Contains all the requested expansions
14+
/// </summary>
15+
[JsonProperty("includes")] public TweetIncludesV2 Includes { get; set; }
16+
17+
/// <summary>
18+
/// All errors that prevented Twitter to send some data,
19+
/// but which did not prevent the request to be resolved.
20+
/// </summary>
21+
[JsonProperty("errors")] public ErrorV2[] Errors { get; set; }
22+
23+
/// <summary>
24+
/// This object contains information about the Timeline Tweets
25+
/// returned in the current request and pagination details.
26+
/// </summary>
27+
[JsonProperty("meta")] public TimelineMetaV2 Meta { get; set; }
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using Newtonsoft.Json;
3+
4+
namespace Tweetinvi.Models.V2
5+
{
6+
/// <summary>
7+
/// A Tweet
8+
/// <para>Read more here : https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets</para>
9+
/// </summary>
10+
public class TimelineMetaV2
11+
{
12+
/// <summary>
13+
/// The Tweet ID of the oldest Tweet returned in the response.
14+
/// </summary>
15+
[JsonProperty("oldest_id")] public string OldestId { get; set; }
16+
17+
/// <summary>
18+
/// The Tweet ID of the most recent Tweet returned in the response.
19+
/// </summary>
20+
[JsonProperty("newest_id")] public string NewestId { get; set; }
21+
22+
/// <summary>
23+
/// The number of Tweet results returned in the response.
24+
/// </summary>
25+
[JsonProperty("count")] public int Count { get; set; }
26+
27+
/// <summary>
28+
/// A value that encodes the next 'page' of results that can be requested,
29+
/// via the pagination_token request parameter.
30+
/// </summary>
31+
[JsonProperty("next_token")] public string NextToken { get; set; }
32+
33+
/// <summary>
34+
/// A value that encodes the previous 'page' of results that can be requested,
35+
/// via the pagination_token request parameter.
36+
/// </summary>
37+
[JsonProperty("previous_token")] public string PreviousToken { get; set; }
38+
39+
}
40+
}

0 commit comments

Comments
 (0)