2021-04-14 12:56:41 +00:00
using System ;
2020-02-01 12:03:02 +00:00
using System.Threading.Tasks ;
2020-12-20 10:52:35 +00:00
using System.Net ;
using System.Net.Http ;
using System.Web ;
2021-04-14 12:56:41 +00:00
using System.Linq ;
2020-02-01 12:03:02 +00:00
2020-10-19 08:50:51 +00:00
using Dapper ;
2020-12-25 11:56:46 +00:00
using Myriad.Builders ;
2020-12-20 10:52:35 +00:00
using Newtonsoft.Json.Linq ;
2020-02-01 12:03:02 +00:00
using PluralKit.Core ;
2020-02-12 14:16:19 +00:00
namespace PluralKit.Bot
2020-02-01 12:03:02 +00:00
{
public class Member
{
2020-08-29 11:46:27 +00:00
private readonly IDatabase _db ;
private readonly ModelRepository _repo ;
private readonly EmbedService _embeds ;
2020-12-20 10:52:35 +00:00
private readonly HttpClient _client ;
2020-02-01 13:40:57 +00:00
2020-12-20 10:52:35 +00:00
public Member ( EmbedService embeds , IDatabase db , ModelRepository repo , HttpClient client )
2020-02-01 12:03:02 +00:00
{
_embeds = embeds ;
2020-06-13 17:42:04 +00:00
_db = db ;
2020-08-29 11:46:27 +00:00
_repo = repo ;
2020-12-20 10:52:35 +00:00
_client = client ;
2020-02-01 12:03:02 +00:00
}
public async Task NewMember ( Context ctx ) {
if ( ctx . System = = null ) throw Errors . NoSystemError ;
var memberName = ctx . RemainderOrNull ( ) ? ? throw new PKSyntaxError ( "You must pass a member name." ) ;
// Hard name length cap
if ( memberName . Length > Limits . MaxMemberNameLength ) throw Errors . MemberNameTooLongError ( memberName . Length ) ;
// Warn if there's already a member by this name
2020-08-29 11:46:27 +00:00
var existingMember = await _db . Execute ( c = > _repo . GetMemberByName ( c , ctx . System . Id , memberName ) ) ;
2020-02-01 12:03:02 +00:00
if ( existingMember ! = null ) {
2020-07-21 00:10:26 +00:00
var msg = $"{Emojis.Warn} You already have a member in your system with the name \" { existingMember . NameFor ( ctx ) } \ " (with ID `{existingMember.Hid}`). Do you want to create another member with the same name?" ;
2021-07-02 10:40:40 +00:00
if ( ! await ctx . PromptYesNo ( msg , "Create" ) ) throw new PKError ( "Member creation cancelled." ) ;
2020-02-01 12:03:02 +00:00
}
2020-06-29 12:54:11 +00:00
await using var conn = await _db . Obtain ( ) ;
2020-02-01 12:03:02 +00:00
// Enforce per-system member limit
2020-08-29 11:46:27 +00:00
var memberCount = await _repo . GetSystemMemberCount ( conn , ctx . System . Id ) ;
2020-10-09 10:18:29 +00:00
var memberLimit = ctx . System . MemberLimitOverride ? ? Limits . MaxMemberCount ;
if ( memberCount > = memberLimit )
throw Errors . MemberLimitReachedError ( memberLimit ) ;
2020-02-01 12:03:02 +00:00
// Create the member
2020-08-29 11:46:27 +00:00
var member = await _repo . CreateMember ( conn , ctx . System . Id , memberName ) ;
2020-02-01 12:03:02 +00:00
memberCount + + ;
2021-04-14 12:56:41 +00:00
// Try to match an image attached to the message
var avatarArg = ctx . Message . Attachments . FirstOrDefault ( ) ;
Exception imageMatchError = null ;
if ( avatarArg ! = null )
{
try {
await AvatarUtils . VerifyAvatarOrThrow ( avatarArg . Url ) ;
await _db . Execute ( conn = > _repo . UpdateMember ( conn , member . Id , new MemberPatch { AvatarUrl = avatarArg . Url } ) ) ;
} catch ( Exception e ) {
imageMatchError = e ;
}
}
2020-02-01 12:03:02 +00:00
// Send confirmation and space hint
2020-10-04 07:44:21 +00:00
await ctx . Reply ( $"{Emojis.Success} Member \" { memberName } \ " (`{member.Hid}`) registered! Check out the getting started page for how to get a member up and running: https://pluralkit.me/start#create-a-member" ) ;
2020-10-19 08:50:51 +00:00
if ( await _db . Execute ( conn = > conn . QuerySingleAsync < bool > ( "select has_private_members(@System)" ,
new { System = ctx . System . Id } ) ) ) //if has private members
2020-10-19 09:05:54 +00:00
await ctx . Reply ( $"{Emojis.Warn} This member is currently **public**. To change this, use `pk;member {member.Hid} private`." ) ;
2021-04-14 12:56:41 +00:00
if ( avatarArg ! = null )
if ( imageMatchError = = null )
await ctx . Reply ( $"{Emojis.Success} Member avatar set to attached image.\n{Emojis.Warn} If you delete the message containing the attachment, the avatar will stop working." ) ;
else
await ctx . Reply ( $"{Emojis.Error} Couldn't set avatar: {imageMatchError.Message}" ) ;
2020-02-01 12:03:02 +00:00
if ( memberName . Contains ( " " ) )
await ctx . Reply ( $"{Emojis.Note} Note that this member's name contains spaces. You will need to surround it with \" double quotes \ " when using commands referring to it, or just use the member's 5-character ID (which is `{member.Hid}`)." ) ;
2020-10-09 14:23:31 +00:00
if ( memberCount > = memberLimit )
await ctx . Reply ( $"{Emojis.Warn} You have reached the per-system member limit ({memberLimit}). You will be unable to create additional members until existing members are deleted." ) ;
else if ( memberCount > = Limits . MaxMembersWarnThreshold ( memberLimit ) )
await ctx . Reply ( $"{Emojis.Warn} You are approaching the per-system member limit ({memberCount} / {memberLimit} members). Please review your member list for unused or duplicate members." ) ;
2020-02-01 12:03:02 +00:00
}
public async Task ViewMember ( Context ctx , PKMember target )
{
2020-08-29 11:46:27 +00:00
var system = await _db . Execute ( c = > _repo . GetSystem ( c , target . System ) ) ;
2021-01-31 15:16:52 +00:00
await ctx . Reply ( embed : await _embeds . CreateMemberEmbed ( system , target , ctx . Guild , ctx . LookupContextFor ( system ) ) ) ;
2020-02-01 12:03:02 +00:00
}
2020-12-20 10:52:35 +00:00
public async Task Soulscream ( Context ctx , PKMember target )
{
// this is for a meme, please don't take this code seriously. :)
var name = target . NameFor ( ctx . LookupContextFor ( target ) ) ;
var encoded = HttpUtility . UrlEncode ( name ) ;
var resp = await _client . GetAsync ( $"https://onomancer.sibr.dev/api/generateStats2?name={encoded}" ) ;
if ( resp . StatusCode ! = HttpStatusCode . OK )
// lol
return ;
var data = JObject . Parse ( await resp . Content . ReadAsStringAsync ( ) ) ;
var scream = data [ "soulscream" ] ! . Value < string > ( ) ;
2020-12-25 11:56:46 +00:00
var eb = new EmbedBuilder ( )
2021-01-15 10:29:43 +00:00
. Color ( DiscordUtils . Red )
2020-12-25 11:56:46 +00:00
. Title ( name )
. Url ( $"https://onomancer.sibr.dev/reflect?name={encoded}" )
. Description ( $"*{scream}*" ) ;
2020-12-20 10:52:35 +00:00
await ctx . Reply ( embed : eb . Build ( ) ) ;
}
2020-02-01 12:03:02 +00:00
}
2020-10-19 09:05:54 +00:00
}