boosts v1
This commit is contained in:
parent
1a288f4d2d
commit
d0e4a09d3d
8 changed files with 103 additions and 10 deletions
|
@ -18,7 +18,7 @@ namespace BirdsiteLive.Domain
|
||||||
{
|
{
|
||||||
Task<Actor> GetUser(string objectId);
|
Task<Actor> GetUser(string objectId);
|
||||||
Task<HttpStatusCode> PostDataAsync<T>(T data, string targetHost, string actorUrl, string inbox = null);
|
Task<HttpStatusCode> PostDataAsync<T>(T data, string targetHost, string actorUrl, string inbox = null);
|
||||||
Task PostNewNoteActivity(Note note, string username, string noteId, string targetHost,
|
Task PostNewActivity(Note note, string username, string activityType, string noteId, string targetHost,
|
||||||
string targetInbox);
|
string targetInbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ namespace BirdsiteLive.Domain
|
||||||
return actor;
|
return actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task PostNewNoteActivity(Note note, string username, string noteId, string targetHost, string targetInbox)
|
public async Task PostNewActivity(Note note, string username, string activityType, string noteId, string targetHost, string targetInbox)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -71,7 +71,7 @@ namespace BirdsiteLive.Domain
|
||||||
{
|
{
|
||||||
context = "https://www.w3.org/ns/activitystreams",
|
context = "https://www.w3.org/ns/activitystreams",
|
||||||
id = $"{noteUri}/activity",
|
id = $"{noteUri}/activity",
|
||||||
type = "Create",
|
type = activityType,
|
||||||
actor = actor,
|
actor = actor,
|
||||||
published = nowString,
|
published = nowString,
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ namespace BirdsiteLive.Domain
|
||||||
if (!string.IsNullOrWhiteSpace(inbox))
|
if (!string.IsNullOrWhiteSpace(inbox))
|
||||||
usedInbox = inbox;
|
usedInbox = inbox;
|
||||||
|
|
||||||
var json = JsonConvert.SerializeObject(data);
|
var json = JsonConvert.SerializeObject(data, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||||
|
|
||||||
var date = DateTime.UtcNow.ToUniversalTime();
|
var date = DateTime.UtcNow.ToUniversalTime();
|
||||||
var httpDate = date.ToString("r");
|
var httpDate = date.ToString("r");
|
||||||
|
|
|
@ -42,6 +42,11 @@ namespace BirdsiteLive.Domain
|
||||||
{
|
{
|
||||||
var actorUrl = UrlFactory.GetActorUrl(_instanceSettings.Domain, username);
|
var actorUrl = UrlFactory.GetActorUrl(_instanceSettings.Domain, username);
|
||||||
var noteUrl = UrlFactory.GetNoteUrl(_instanceSettings.Domain, username, tweet.Id.ToString());
|
var noteUrl = UrlFactory.GetNoteUrl(_instanceSettings.Domain, username, tweet.Id.ToString());
|
||||||
|
if (tweet.IsRetweet)
|
||||||
|
{
|
||||||
|
actorUrl = UrlFactory.GetActorUrl(_instanceSettings.Domain, tweet.OriginalAuthor.Name);
|
||||||
|
noteUrl = UrlFactory.GetNoteUrl(_instanceSettings.Domain, tweet.OriginalAuthor.Name, tweet.Id.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
var to = $"{actorUrl}/followers";
|
var to = $"{actorUrl}/followers";
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks
|
||||||
_settings.PublishReplies)
|
_settings.PublishReplies)
|
||||||
{
|
{
|
||||||
var note = _statusService.GetStatus(user.Acct, tweet);
|
var note = _statusService.GetStatus(user.Acct, tweet);
|
||||||
await _activityPubService.PostNewNoteActivity(note, user.Acct, tweet.Id.ToString(), follower.Host, inbox);
|
await _activityPubService.PostNewActivity(note, user.Acct, "Create", tweet.Id.ToString(), follower.Host, inbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ArgumentException e)
|
catch (ArgumentException e)
|
||||||
|
|
|
@ -56,12 +56,17 @@ namespace BirdsiteLive.Pipeline.Processors.SubTasks
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!tweet.IsReply ||
|
if (tweet.IsRetweet)
|
||||||
|
{
|
||||||
|
var note = _statusService.GetStatus(user.Acct, tweet);
|
||||||
|
await _activityPubService.PostNewActivity(note, user.Acct, "Announce", tweet.Id.ToString(), host, inbox);
|
||||||
|
}
|
||||||
|
else if (!tweet.IsReply ||
|
||||||
tweet.IsReply && tweet.IsThread ||
|
tweet.IsReply && tweet.IsThread ||
|
||||||
_settings.PublishReplies)
|
_settings.PublishReplies)
|
||||||
{
|
{
|
||||||
var note = _statusService.GetStatus(user.Acct, tweet);
|
var note = _statusService.GetStatus(user.Acct, tweet);
|
||||||
await _activityPubService.PostNewNoteActivity(note, user.Acct, tweet.Id.ToString(), host, inbox);
|
await _activityPubService.PostNewActivity(note, user.Acct, "Create", tweet.Id.ToString(), host, inbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ArgumentException e)
|
catch (ArgumentException e)
|
||||||
|
|
|
@ -36,6 +36,16 @@ namespace BirdsiteLive.Twitter
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public TwitterUser GetUser(long id)
|
||||||
|
{
|
||||||
|
if (!_userCache.TryGetValue(id, out TwitterUser user))
|
||||||
|
{
|
||||||
|
user = _twitterService.GetUser(id);
|
||||||
|
if(user != null) _userCache.Set(id, user, _cacheEntryOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
public TwitterUser GetUser(string username)
|
public TwitterUser GetUser(string username)
|
||||||
{
|
{
|
||||||
if (!_userCache.TryGetValue(username, out TwitterUser user))
|
if (!_userCache.TryGetValue(username, out TwitterUser user))
|
||||||
|
|
|
@ -15,6 +15,6 @@ namespace BirdsiteLive.Twitter.Models
|
||||||
public bool IsThread { get; set; }
|
public bool IsThread { get; set; }
|
||||||
public bool IsRetweet { get; set; }
|
public bool IsRetweet { get; set; }
|
||||||
public string RetweetUrl { get; set; }
|
public string RetweetUrl { get; set; }
|
||||||
public string OriginalAuthor { get; set; }
|
public TwitterUser OriginalAuthor { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -110,7 +110,7 @@ namespace BirdsiteLive.Twitter
|
||||||
return tweets.RootElement.GetProperty("data").EnumerateArray().Select<JsonElement, ExtractedTweet>(Extract).ToArray();
|
return tweets.RootElement.GetProperty("data").EnumerateArray().Select<JsonElement, ExtractedTweet>(Extract).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExtractedTweet Extract(JsonElement tweet)
|
private ExtractedTweet Extract(JsonElement tweet)
|
||||||
{
|
{
|
||||||
bool IsRetweet = false;
|
bool IsRetweet = false;
|
||||||
bool IsReply = false;
|
bool IsReply = false;
|
||||||
|
@ -129,9 +129,11 @@ namespace BirdsiteLive.Twitter
|
||||||
if (first.GetProperty("type").GetString() == "retweeted")
|
if (first.GetProperty("type").GetString() == "retweeted")
|
||||||
{
|
{
|
||||||
IsRetweet = true;
|
IsRetweet = true;
|
||||||
|
var originalAuthor = _twitterUserService.GetUser(Int64.Parse(tweet.GetProperty("author_id").GetString()));
|
||||||
var statusId = Int64.Parse(first.GetProperty("id").GetString());
|
var statusId = Int64.Parse(first.GetProperty("id").GetString());
|
||||||
var extracted = GetTweet(statusId);
|
var extracted = GetTweet(statusId);
|
||||||
extracted.IsRetweet = true;
|
extracted.IsRetweet = true;
|
||||||
|
extracted.OriginalAuthor = originalAuthor;
|
||||||
return extracted;
|
return extracted;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -158,7 +160,8 @@ namespace BirdsiteLive.Twitter
|
||||||
IsReply = IsReply,
|
IsReply = IsReply,
|
||||||
IsThread = false,
|
IsThread = false,
|
||||||
IsRetweet = IsRetweet,
|
IsRetweet = IsRetweet,
|
||||||
RetweetUrl = "https://t.co/123"
|
RetweetUrl = "https://t.co/123",
|
||||||
|
OriginalAuthor = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
return extractedTweet;
|
return extractedTweet;
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace BirdsiteLive.Twitter
|
||||||
public interface ITwitterUserService
|
public interface ITwitterUserService
|
||||||
{
|
{
|
||||||
TwitterUser GetUser(string username);
|
TwitterUser GetUser(string username);
|
||||||
|
TwitterUser GetUser(long id);
|
||||||
bool IsUserApiRateLimited();
|
bool IsUserApiRateLimited();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +34,10 @@ namespace BirdsiteLive.Twitter
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public TwitterUser GetUser(long id)
|
||||||
|
{
|
||||||
|
return GetUserAsync(id).Result;
|
||||||
|
}
|
||||||
public TwitterUser GetUser(string username)
|
public TwitterUser GetUser(string username)
|
||||||
{
|
{
|
||||||
return GetUserAsync(username).Result;
|
return GetUserAsync(username).Result;
|
||||||
|
@ -108,6 +113,71 @@ namespace BirdsiteLive.Twitter
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<TwitterUser> GetUserAsync(long id)
|
||||||
|
{
|
||||||
|
//Check if API is saturated
|
||||||
|
if (IsUserApiRateLimited()) throw new RateLimitExceededException();
|
||||||
|
|
||||||
|
//Proceed to account retrieval
|
||||||
|
await _twitterAuthenticationInitializer.EnsureAuthenticationIsInitialized();
|
||||||
|
|
||||||
|
JsonDocument res;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var request = new HttpRequestMessage(new HttpMethod("GET"), "https://api.twitter.com/2/users/"+ id + "?user.fields=name,username,protected,profile_image_url,url,description"))
|
||||||
|
{
|
||||||
|
request.Headers.TryAddWithoutValidation("Authorization", "Bearer " + _twitterAuthenticationInitializer.Token);
|
||||||
|
|
||||||
|
var httpResponse = await _httpClient.SendAsync(request);
|
||||||
|
httpResponse.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var c = await httpResponse.Content.ReadAsStringAsync();
|
||||||
|
res = JsonDocument.Parse(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (HttpRequestException e)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
//if (e.TwitterExceptionInfos.Any(x => x.Message.ToLowerInvariant().Contains("User has been suspended".ToLowerInvariant())))
|
||||||
|
//{
|
||||||
|
// throw new UserHasBeenSuspendedException();
|
||||||
|
//}
|
||||||
|
//else if (e.TwitterExceptionInfos.Any(x => x.Message.ToLowerInvariant().Contains("User not found".ToLowerInvariant())))
|
||||||
|
//{
|
||||||
|
// throw new UserNotFoundException();
|
||||||
|
//}
|
||||||
|
//else if (e.TwitterExceptionInfos.Any(x => x.Message.ToLowerInvariant().Contains("Rate limit exceeded".ToLowerInvariant())))
|
||||||
|
//{
|
||||||
|
// throw new RateLimitExceededException();
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// throw;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, "Error retrieving user id {id}", id);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_statisticsHandler.CalledUserApi();
|
||||||
|
}
|
||||||
|
return new TwitterUser
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
Acct = res.RootElement.GetProperty("data").GetProperty("username").GetString(),
|
||||||
|
Name = res.RootElement.GetProperty("data").GetProperty("name").GetString(),
|
||||||
|
Description = res.RootElement.GetProperty("data").GetProperty("description").GetString(),
|
||||||
|
Url = res.RootElement.GetProperty("data").GetProperty("url").GetString(),
|
||||||
|
ProfileImageUrl = res.RootElement.GetProperty("data").GetProperty("profile_image_url").GetString(),
|
||||||
|
ProfileBackgroundImageUrl = res.RootElement.GetProperty("data").GetProperty("profile_image_url").GetString(), //for now
|
||||||
|
ProfileBannerURL = res.RootElement.GetProperty("data").GetProperty("profile_image_url").GetString(), //for now
|
||||||
|
Protected = res.RootElement.GetProperty("data").GetProperty("protected").GetBoolean(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsUserApiRateLimited()
|
public bool IsUserApiRateLimited()
|
||||||
{
|
{
|
||||||
// Retrieve limit from tooling
|
// Retrieve limit from tooling
|
||||||
|
|
Loading…
Add table
Reference in a new issue