in dotnet/space-translate/SpaceTranslate/WebHook/SpaceTranslateWebHookHandler.HandleMenuAction.cs [13:146]
public override async Task<AppUserActionExecutionResult> HandleMenuActionAsync(MenuActionPayload payload)
{
using var loggerScopeForClientId = _logger.BeginScope("ClientId={ClientId}", payload.ClientId);
var organization = await _db.Organizations.FirstOrDefaultAsync(it => it.ClientId == payload.ClientId);
if (organization == null)
{
_logger.LogWarning("The organization does not exist");
return AppUserActionExecutionResult.Failure("The organization does not exist.");
}
using var loggerScopeForUserId = _logger.BeginScope("UserId={UserId}", payload.UserId);
if (payload.Context is not ChannelMessageMenuActionContext actionContext)
{
_logger.LogWarning("Unknown payload context type. ContextType={ContextType}", payload.Context?.GetType());
return AppUserActionExecutionResult.Failure("The payload could not be processed.");
}
if (actionContext.ChannelIdentifier is not ChannelIdentifier.ChannelIdentifierId channelIdentifierId)
{
_logger.LogWarning("Unknown channel identifier type. ChannelIdentifierType={ChannelIdentifierType}", actionContext.ChannelIdentifier.GetType().Name);
return AppUserActionExecutionResult.Failure("The payload could not be processed.");
}
var user = await _db.Users
.Include(m => m.Organization)
.FirstOrDefaultAsync(it => it.OrganizationId == organization.Id && it.UserId == payload.UserId);
if (user == null)
{
_logger.LogWarning("User-specific permissions required (no cached credential)");
return PermissionsRequired(null, channelIdentifierId);
}
var organizationConnection = organization.CreateConnection();
var userConnection = user.CreateConnection();
if (userConnection == null)
{
_logger.LogWarning("User-specific permissions required (no cached credential)");
return PermissionsRequired(user.Scope, null);
}
var organizationChatClient = new ChatClient(organizationConnection);
var userChatClient = new ChatClient(userConnection);
ChannelItemRecord? originalMessage = null;
M2ChannelRecord? originalMessageChannelInfo = null;
try
{
originalMessage = await userChatClient.Messages.GetMessageAsync(
actionContext.MessageIdentifier,
actionContext.ChannelIdentifier,
_ => _
.WithAllFieldsWildcard());
// Try accessing text, if it is not accessible we need additional permissions
var _ = originalMessage.Text;
originalMessageChannelInfo = await userChatClient.Channels.GetChannelAsync(actionContext.ChannelIdentifier);
}
catch (PermissionDeniedException)
{
_logger.LogWarning("User-specific permissions required (permission denied)");
return PermissionsRequired(user.Scope, channelIdentifierId);
}
catch (RefreshTokenRevokedException)
{
_logger.LogWarning("User-specific permissions required (refresh token revoked)");
return PermissionsRequired(user.Scope, channelIdentifierId);
}
catch (PropertyNotRequestedException)
{
_logger.LogWarning("User-specific permissions required (property not accessible)");
return PermissionsRequired(user.Scope, channelIdentifierId);
}
if (userConnection.AuthenticationTokens?.RefreshToken != null &&
userConnection.AuthenticationTokens.RefreshToken != user.RefreshToken)
{
user.RefreshToken = userConnection.AuthenticationTokens.RefreshToken;
await _db.SaveChangesAsync();
}
var cacheKey = organization.Id + "__" +
actionContext.ChannelIdentifier + "__" +
actionContext.MessageIdentifier + "__" +
originalMessage.Text.ToMd5();
var cachedTranslation = await _cache.GetOrCreateAsync(cacheKey, async entry =>
{
if (string.IsNullOrWhiteSpace(originalMessage.Text)) return "(empty)";
_logger.LogInformation("Requesting translation from DeepL...");
var translatedText = await _translator.TranslateTextAsync(
text: originalMessage.Text,
sourceLanguageCode: null,
targetLanguageCode: "en-US",
options: null);
_logger.LogInformation("Received translation from DeepL. DetectedSourceLanguageCode={DetectedSourceLanguageCode}", translatedText.DetectedSourceLanguageCode);
return translatedText.Text;
});
if (cachedTranslation != null)
{
var channelInfoName = "original message";
if (originalMessageChannelInfo.Contact.Ext is M2SharedChannelContent channelContent)
{
channelInfoName = $"original message in #{channelContent.Name}";
}
await organizationChatClient.Messages.SendMessageAsync(
recipient: MessageRecipient.Member(ProfileIdentifier.Id(payload.UserId)),
content: ChatMessage.Block(new List<MessageSectionElement>
{
MessageSectionElement.MessageSection(new List<MessageBlockElement>
{
MessageBlockElement.MessageText(
$"Translation of [{channelInfoName}]({organization.ServerUrl}/im/translated/?message={actionContext.MessageIdentifier.ToString()!.Replace("id:", "").Replace("externalId:", "")}&channel={actionContext.ChannelIdentifier.ToString()!.Replace("id:", "")}): "),
MessageBlockElement.MessageDivider(),
MessageBlockElement.MessageText(cachedTranslation)
})
}));
}
else
{
_logger.LogWarning("Could not translate message");
return AppUserActionExecutionResult.Failure("Could not translate message.");
}
return await base.HandleMenuActionAsync(payload);
}