user twitter service to retrieve timelines

This commit is contained in:
Nicolas Constant 2021-01-18 02:07:09 -05:00
parent 05fa5dfb59
commit 639ad3ae14
No known key found for this signature in database
GPG key ID: 1E9F677FB01A5688
9 changed files with 90 additions and 68 deletions

View file

@ -14,13 +14,13 @@ namespace BirdsiteLive.Pipeline.Processors
{ {
public class RetrieveTweetsProcessor : IRetrieveTweetsProcessor public class RetrieveTweetsProcessor : IRetrieveTweetsProcessor
{ {
private readonly ITwitterService _twitterService; private readonly ITwitterTweetsService _twitterTweetsService;
private readonly ITwitterUserDal _twitterUserDal; private readonly ITwitterUserDal _twitterUserDal;
#region Ctor #region Ctor
public RetrieveTweetsProcessor(ITwitterService twitterService, ITwitterUserDal twitterUserDal) public RetrieveTweetsProcessor(ITwitterTweetsService twitterTweetsService, ITwitterUserDal twitterUserDal)
{ {
_twitterService = twitterService; _twitterTweetsService = twitterTweetsService;
_twitterUserDal = twitterUserDal; _twitterUserDal = twitterUserDal;
} }
#endregion #endregion
@ -56,9 +56,9 @@ namespace BirdsiteLive.Pipeline.Processors
{ {
ExtractedTweet[] tweets; ExtractedTweet[] tweets;
if (user.LastTweetPostedId == -1) if (user.LastTweetPostedId == -1)
tweets = _twitterService.GetTimeline(user.Acct, 1); tweets = _twitterTweetsService.GetTimeline(user.Acct, 1);
else else
tweets = _twitterService.GetTimeline(user.Acct, 200, user.LastTweetSynchronizedForAllFollowersId); tweets = _twitterTweetsService.GetTimeline(user.Acct, 200, user.LastTweetSynchronizedForAllFollowersId);
return tweets; return tweets;
} }

View file

@ -4,9 +4,9 @@ using Microsoft.Extensions.Caching.Memory;
namespace BirdsiteLive.Twitter namespace BirdsiteLive.Twitter
{ {
public class CachedTwitterService : ITwitterService public class CachedTwitterUserService : ITwitterUserService
{ {
private readonly ITwitterService _twitterService; private readonly ITwitterUserService _twitterService;
private MemoryCache _userCache = new MemoryCache(new MemoryCacheOptions() private MemoryCache _userCache = new MemoryCache(new MemoryCacheOptions()
{ {
@ -22,7 +22,7 @@ namespace BirdsiteLive.Twitter
.SetAbsoluteExpiration(TimeSpan.FromDays(30)); .SetAbsoluteExpiration(TimeSpan.FromDays(30));
#region Ctor #region Ctor
public CachedTwitterService(ITwitterService twitterService) public CachedTwitterUserService(ITwitterUserService twitterService)
{ {
_twitterService = twitterService; _twitterService = twitterService;
} }
@ -38,15 +38,5 @@ namespace BirdsiteLive.Twitter
return user; return user;
} }
public ExtractedTweet GetTweet(long statusId)
{
return _twitterService.GetTweet(statusId);
}
public ExtractedTweet[] GetTimeline(string username, int nberTweets, long fromTweetId = -1)
{
return _twitterService.GetTimeline(username, nberTweets, fromTweetId);
}
} }
} }

View file

@ -2,6 +2,7 @@
{ {
public class TwitterUser public class TwitterUser
{ {
public long Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string Description { get; set; } public string Description { get; set; }
public string Url { get; set; } public string Url { get; set; }

View file

@ -1,65 +1,39 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using BirdsiteLive.Common.Settings; using BirdsiteLive.Common.Settings;
using BirdsiteLive.Statistics.Domain; using BirdsiteLive.Statistics.Domain;
using BirdsiteLive.Twitter.Extractors; using BirdsiteLive.Twitter.Extractors;
using BirdsiteLive.Twitter.Models; using BirdsiteLive.Twitter.Models;
using Tweetinvi; using Tweetinvi;
using Tweetinvi.Models; using Tweetinvi.Models;
using Tweetinvi.Models.Entities;
using Tweetinvi.Parameters; using Tweetinvi.Parameters;
namespace BirdsiteLive.Twitter namespace BirdsiteLive.Twitter
{ {
public interface ITwitterService public interface ITwitterTweetsService
{ {
TwitterUser GetUser(string username);
ExtractedTweet GetTweet(long statusId); ExtractedTweet GetTweet(long statusId);
ExtractedTweet[] GetTimeline(string username, int nberTweets, long fromTweetId = -1); ExtractedTweet[] GetTimeline(string username, int nberTweets, long fromTweetId = -1);
} }
public class TwitterService : ITwitterService public class TwitterTweetsService : ITwitterTweetsService
{ {
private readonly TwitterSettings _settings; private readonly TwitterSettings _settings;
private readonly ITweetExtractor _tweetExtractor; private readonly ITweetExtractor _tweetExtractor;
private readonly ITwitterStatisticsHandler _statisticsHandler; private readonly ITwitterStatisticsHandler _statisticsHandler;
private readonly ITwitterUserService _twitterUserService;
#region Ctor #region Ctor
public TwitterService(TwitterSettings settings, ITweetExtractor tweetExtractor, ITwitterStatisticsHandler statisticsHandler) public TwitterTweetsService(TwitterSettings settings, ITweetExtractor tweetExtractor, ITwitterStatisticsHandler statisticsHandler, ITwitterUserService twitterUserService)
{ {
_settings = settings; _settings = settings;
_tweetExtractor = tweetExtractor; _tweetExtractor = tweetExtractor;
_statisticsHandler = statisticsHandler; _statisticsHandler = statisticsHandler;
_twitterUserService = twitterUserService;
Auth.SetApplicationOnlyCredentials(_settings.ConsumerKey, _settings.ConsumerSecret, true); Auth.SetApplicationOnlyCredentials(_settings.ConsumerKey, _settings.ConsumerSecret, true);
} }
#endregion #endregion
public TwitterUser GetUser(string username)
{
var user = User.GetUserFromScreenName(username);
_statisticsHandler.CalledUserApi();
if (user == null) return null;
// Expand URLs
var description = user.Description;
foreach (var descriptionUrl in user.Entities?.Description?.Urls?.OrderByDescending(x => x.URL.Length))
description = description.Replace(descriptionUrl.URL, descriptionUrl.ExpandedURL);
return new TwitterUser
{
Acct = username,
Name = user.Name,
Description = description,
Url = $"https://twitter.com/{username}",
ProfileImageUrl = user.ProfileImageUrlFullSize,
ProfileBackgroundImageUrl = user.ProfileBackgroundImageUrlHttps,
ProfileBannerURL = user.ProfileBannerURL
};
}
public ExtractedTweet GetTweet(long statusId) public ExtractedTweet GetTweet(long statusId)
{ {
TweetinviConfig.CurrentThreadSettings.TweetMode = TweetMode.Extended; TweetinviConfig.CurrentThreadSettings.TweetMode = TweetMode.Extended;
@ -72,9 +46,9 @@ namespace BirdsiteLive.Twitter
public ExtractedTweet[] GetTimeline(string username, int nberTweets, long fromTweetId = -1) public ExtractedTweet[] GetTimeline(string username, int nberTweets, long fromTweetId = -1)
{ {
TweetinviConfig.CurrentThreadSettings.TweetMode = TweetMode.Extended; TweetinviConfig.CurrentThreadSettings.TweetMode = TweetMode.Extended;
var user = _twitterUserService.GetUser(username);
var user = User.GetUserFromScreenName(username);
_statisticsHandler.CalledUserApi();
var tweets = new List<ITweet>(); var tweets = new List<ITweet>();
if (fromTweetId == -1) if (fromTweetId == -1)
{ {
@ -97,4 +71,4 @@ namespace BirdsiteLive.Twitter
return tweets.Select(_tweetExtractor.Extract).ToArray(); return tweets.Select(_tweetExtractor.Extract).ToArray();
} }
} }
} }

View file

@ -0,0 +1,55 @@
using System.Linq;
using BirdsiteLive.Common.Settings;
using BirdsiteLive.Statistics.Domain;
using BirdsiteLive.Twitter.Extractors;
using BirdsiteLive.Twitter.Models;
using Tweetinvi;
namespace BirdsiteLive.Twitter
{
public interface ITwitterUserService
{
TwitterUser GetUser(string username);
}
public class TwitterUserService : ITwitterUserService
{
private readonly TwitterSettings _settings;
private readonly ITweetExtractor _tweetExtractor;
private readonly ITwitterStatisticsHandler _statisticsHandler;
#region Ctor
public TwitterUserService(TwitterSettings settings, ITweetExtractor tweetExtractor, ITwitterStatisticsHandler statisticsHandler)
{
_settings = settings;
_tweetExtractor = tweetExtractor;
_statisticsHandler = statisticsHandler;
Auth.SetApplicationOnlyCredentials(_settings.ConsumerKey, _settings.ConsumerSecret, true);
}
#endregion
public TwitterUser GetUser(string username)
{
var user = User.GetUserFromScreenName(username);
_statisticsHandler.CalledUserApi();
if (user == null) return null;
// Expand URLs
var description = user.Description;
foreach (var descriptionUrl in user.Entities?.Description?.Urls?.OrderByDescending(x => x.URL.Length))
description = description.Replace(descriptionUrl.URL, descriptionUrl.ExpandedURL);
return new TwitterUser
{
Id = user.Id,
Acct = username,
Name = user.Name,
Description = description,
Url = $"https://twitter.com/{username}",
ProfileImageUrl = user.ProfileImageUrlFullSize,
ProfileBackgroundImageUrl = user.ProfileBackgroundImageUrlHttps,
ProfileBannerURL = user.ProfileBannerURL
};
}
}
}

View file

@ -21,18 +21,20 @@ namespace BirdsiteLive.Controllers
{ {
public class UsersController : Controller public class UsersController : Controller
{ {
private readonly ITwitterService _twitterService; private readonly ITwitterUserService _twitterUserService;
private readonly ITwitterTweetsService _twitterTweetService;
private readonly IUserService _userService; private readonly IUserService _userService;
private readonly IStatusService _statusService; private readonly IStatusService _statusService;
private readonly InstanceSettings _instanceSettings; private readonly InstanceSettings _instanceSettings;
#region Ctor #region Ctor
public UsersController(ITwitterService twitterService, IUserService userService, IStatusService statusService, InstanceSettings instanceSettings) public UsersController(ITwitterUserService twitterUserService, IUserService userService, IStatusService statusService, InstanceSettings instanceSettings, ITwitterTweetsService twitterTweetService)
{ {
_twitterService = twitterService; _twitterUserService = twitterUserService;
_userService = userService; _userService = userService;
_statusService = statusService; _statusService = statusService;
_instanceSettings = instanceSettings; _instanceSettings = instanceSettings;
_twitterTweetService = twitterTweetService;
} }
#endregion #endregion
@ -53,7 +55,7 @@ namespace BirdsiteLive.Controllers
public IActionResult Index(string id) public IActionResult Index(string id)
{ {
id = id.Trim(new[] { ' ', '@' }).ToLowerInvariant(); id = id.Trim(new[] { ' ', '@' }).ToLowerInvariant();
var user = _twitterService.GetUser(id); var user = _twitterUserService.GetUser(id);
var acceptHeaders = Request.Headers["Accept"]; var acceptHeaders = Request.Headers["Accept"];
if (acceptHeaders.Any()) if (acceptHeaders.Any())
@ -96,7 +98,7 @@ namespace BirdsiteLive.Controllers
if (!long.TryParse(statusId, out var parsedStatusId)) if (!long.TryParse(statusId, out var parsedStatusId))
return NotFound(); return NotFound();
var tweet = _twitterService.GetTweet(parsedStatusId); var tweet = _twitterTweetService.GetTweet(parsedStatusId);
if (tweet == null) if (tweet == null)
return NotFound(); return NotFound();

View file

@ -16,14 +16,14 @@ namespace BirdsiteLive.Controllers
[ApiController] [ApiController]
public class WellKnownController : ControllerBase public class WellKnownController : ControllerBase
{ {
private readonly ITwitterService _twitterService; private readonly ITwitterUserService _twitterUserService;
private readonly ITwitterUserDal _twitterUserDal; private readonly ITwitterUserDal _twitterUserDal;
private readonly InstanceSettings _settings; private readonly InstanceSettings _settings;
#region Ctor #region Ctor
public WellKnownController(InstanceSettings settings, ITwitterService twitterService, ITwitterUserDal twitterUserDal) public WellKnownController(InstanceSettings settings, ITwitterUserService twitterUserService, ITwitterUserDal twitterUserDal)
{ {
_twitterService = twitterService; _twitterUserService = twitterUserService;
_twitterUserDal = twitterUserDal; _twitterUserDal = twitterUserDal;
_settings = settings; _settings = settings;
} }
@ -163,7 +163,7 @@ namespace BirdsiteLive.Controllers
if (!string.IsNullOrWhiteSpace(domain) && domain != _settings.Domain) if (!string.IsNullOrWhiteSpace(domain) && domain != _settings.Domain)
return NotFound(); return NotFound();
var user = _twitterService.GetUser(name); var user = _twitterUserService.GetUser(name);
if (user == null) if (user == null)
return NotFound(); return NotFound();

View file

@ -84,8 +84,8 @@ namespace BirdsiteLive
throw new NotImplementedException($"{dbSettings.Type} is not supported"); throw new NotImplementedException($"{dbSettings.Type} is not supported");
} }
services.For<ITwitterService>().DecorateAllWith<CachedTwitterService>(); services.For<ITwitterUserService>().DecorateAllWith<CachedTwitterUserService>();
services.For<ITwitterService>().Use<TwitterService>().Singleton(); services.For<ITwitterUserService>().Use<TwitterUserService>().Singleton();
services.Scan(_ => services.Scan(_ =>
{ {

View file

@ -40,7 +40,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
#endregion #endregion
#region Mocks #region Mocks
var twitterServiceMock = new Mock<ITwitterService>(MockBehavior.Strict); var twitterServiceMock = new Mock<ITwitterTweetsService>(MockBehavior.Strict);
twitterServiceMock twitterServiceMock
.Setup(x => x.GetTimeline( .Setup(x => x.GetTimeline(
It.Is<string>(y => y == user1.Acct), It.Is<string>(y => y == user1.Acct),
@ -105,7 +105,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
#endregion #endregion
#region Mocks #region Mocks
var twitterServiceMock = new Mock<ITwitterService>(MockBehavior.Strict); var twitterServiceMock = new Mock<ITwitterTweetsService>(MockBehavior.Strict);
twitterServiceMock twitterServiceMock
.Setup(x => x.GetTimeline( .Setup(x => x.GetTimeline(
It.Is<string>(y => y == user1.Acct), It.Is<string>(y => y == user1.Acct),
@ -165,7 +165,7 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
#endregion #endregion
#region Mocks #region Mocks
var twitterServiceMock = new Mock<ITwitterService>(MockBehavior.Strict); var twitterServiceMock = new Mock<ITwitterTweetsService>(MockBehavior.Strict);
twitterServiceMock twitterServiceMock
.Setup(x => x.GetTimeline( .Setup(x => x.GetTimeline(
It.Is<string>(y => y == user1.Acct), It.Is<string>(y => y == user1.Acct),