2019-06-20 21:15:57 +02:00
using System.Threading.Tasks ;
2020-02-12 15:16:19 +01:00
2020-12-25 13:19:35 +01:00
using Myriad.Extensions ;
2020-12-25 12:56:46 +01:00
using Myriad.Rest.Exceptions ;
2020-12-25 13:19:35 +01:00
using Myriad.Rest.Types.Requests ;
using Myriad.Types ;
2019-10-05 07:41:00 +02:00
2020-02-12 15:16:19 +01:00
using PluralKit.Core ;
2019-06-20 21:15:57 +02:00
2020-02-12 15:16:19 +01:00
namespace PluralKit.Bot
2019-06-20 21:15:57 +02:00
{
2020-02-01 13:03:02 +01:00
public class Token
2019-06-20 21:15:57 +02:00
{
2020-06-29 14:39:19 +02:00
private readonly IDatabase _db ;
2020-08-29 13:46:27 +02:00
private readonly ModelRepository _repo ;
public Token ( IDatabase db , ModelRepository repo )
2019-10-05 07:41:00 +02:00
{
2020-06-29 14:39:19 +02:00
_db = db ;
2020-08-29 13:46:27 +02:00
_repo = repo ;
2019-10-05 07:41:00 +02:00
}
public async Task GetToken ( Context ctx )
2019-06-20 21:15:57 +02:00
{
2019-10-05 07:41:00 +02:00
ctx . CheckSystem ( ) ;
2020-08-26 00:17:05 +02:00
2019-06-20 21:15:57 +02:00
// Get or make a token
2019-10-05 07:41:00 +02:00
var token = ctx . System . Token ? ? await MakeAndSetNewToken ( ctx . System ) ;
2021-08-27 11:03:47 -04:00
2020-08-26 00:17:05 +02:00
try
2019-06-20 21:15:57 +02:00
{
2020-08-26 00:17:05 +02:00
// DM the user a security disclaimer, and then the token in a separate message (for easy copying on mobile)
2021-01-31 16:16:52 +01:00
var dm = await ctx . Cache . GetOrCreateDmChannel ( ctx . Rest , ctx . Author . Id ) ;
await ctx . Rest . CreateMessage ( dm . Id , new MessageRequest
2020-12-25 13:19:35 +01:00
{
Content = $"{Emojis.Warn} Please note that this grants access to modify (and delete!) all your system data, so keep it safe and secure. If it leaks or you need a new one, you can invalidate this one with `pk;token refresh`.\n\nYour token is below:"
} ) ;
2021-08-27 11:03:47 -04:00
await ctx . Rest . CreateMessage ( dm . Id , new MessageRequest { Content = token } ) ;
2019-06-20 21:15:57 +02:00
2020-08-26 00:17:05 +02:00
// If we're not already in a DM, reply with a reminder to check
2021-01-31 16:16:52 +01:00
if ( ctx . Channel . Type ! = Channel . ChannelType . Dm )
2020-12-25 13:19:35 +01:00
await ctx . Reply ( $"{Emojis.Success} Check your DMs!" ) ;
2020-08-26 00:17:05 +02:00
}
2021-03-18 11:38:28 +01:00
catch ( ForbiddenException )
2020-08-26 00:17:05 +02:00
{
// Can't check for permission errors beforehand, so have to handle here :/
2021-01-31 16:16:52 +01:00
if ( ctx . Channel . Type ! = Channel . ChannelType . Dm )
2020-12-25 13:19:35 +01:00
await ctx . Reply ( $"{Emojis.Error} Could not send token in DMs. Are your DMs closed?" ) ;
2020-08-26 00:17:05 +02:00
}
2019-06-20 21:15:57 +02:00
}
2019-10-05 07:41:00 +02:00
private async Task < string > MakeAndSetNewToken ( PKSystem system )
2019-06-20 21:15:57 +02:00
{
2021-09-29 21:51:38 -04:00
system = await _repo . UpdateSystem ( system . Id , new ( ) { Token = StringUtils . GenerateToken ( ) } ) ;
2019-10-05 07:41:00 +02:00
return system . Token ;
2019-06-20 21:15:57 +02:00
}
2021-08-27 11:03:47 -04:00
2019-10-05 07:41:00 +02:00
public async Task RefreshToken ( Context ctx )
2019-06-20 21:15:57 +02:00
{
2019-10-05 07:41:00 +02:00
ctx . CheckSystem ( ) ;
2021-08-27 11:03:47 -04:00
2019-10-05 07:41:00 +02:00
if ( ctx . System . Token = = null )
2019-06-20 21:15:57 +02:00
{
// If we don't have a token, call the other method instead
// This does pretty much the same thing, except words the messages more appropriately for that :)
2019-10-05 07:41:00 +02:00
await GetToken ( ctx ) ;
2019-06-20 21:15:57 +02:00
return ;
}
2020-08-26 00:17:05 +02:00
2021-08-27 11:03:47 -04:00
try
{
2020-08-26 00:17:05 +02:00
// DM the user an invalidation disclaimer, and then the token in a separate message (for easy copying on mobile)
2021-01-31 16:16:52 +01:00
var dm = await ctx . Cache . GetOrCreateDmChannel ( ctx . Rest , ctx . Author . Id ) ;
await ctx . Rest . CreateMessage ( dm . Id , new MessageRequest
2020-12-25 13:19:35 +01:00
{
Content = $"{Emojis.Warn} Your previous API token has been invalidated. You will need to change it anywhere it's currently used.\n\nYour token is below:"
} ) ;
2021-08-27 11:03:47 -04:00
2020-08-26 00:17:05 +02:00
// Make the new token after sending the first DM; this ensures if we can't DM, we also don't end up
// breaking their existing token as a side effect :)
var token = await MakeAndSetNewToken ( ctx . System ) ;
2021-01-31 16:16:52 +01:00
await ctx . Rest . CreateMessage ( dm . Id , new MessageRequest { Content = token } ) ;
2021-08-27 11:03:47 -04:00
2020-08-26 00:17:05 +02:00
// If we're not already in a DM, reply with a reminder to check
2021-01-31 16:16:52 +01:00
if ( ctx . Channel . Type ! = Channel . ChannelType . Dm )
2020-12-25 13:19:35 +01:00
await ctx . Reply ( $"{Emojis.Success} Check your DMs!" ) ;
2020-08-26 00:17:05 +02:00
}
2021-03-18 11:38:28 +01:00
catch ( ForbiddenException )
2019-06-20 21:15:57 +02:00
{
2020-08-26 00:17:05 +02:00
// Can't check for permission errors beforehand, so have to handle here :/
2021-01-31 16:16:52 +01:00
if ( ctx . Channel . Type ! = Channel . ChannelType . Dm )
2020-12-25 13:19:35 +01:00
await ctx . Reply ( $"{Emojis.Error} Could not send token in DMs. Are your DMs closed?" ) ;
2019-06-20 21:15:57 +02:00
}
}
}
}