2020-08-29 11:46:27 +00:00
using System.Collections.Generic ;
using System.Linq ;
using System.Threading.Tasks ;
using Dapper ;
namespace PluralKit.Core
{
public partial class ModelRepository
{
public async Task AddMessage ( IPKConnection conn , PKMessage msg ) {
// "on conflict do nothing" in the (pretty rare) case of duplicate events coming in from Discord, which would lead to a DB error before
await conn . ExecuteAsync ( "insert into messages(mid, guild, channel, member, sender, original_mid) values(@Mid, @Guild, @Channel, @Member, @Sender, @OriginalMid) on conflict do nothing" , msg ) ;
_logger . Debug ( "Stored message {@StoredMessage} in channel {Channel}" , msg , msg . Channel ) ;
}
public async Task < FullMessage > GetMessage ( IPKConnection conn , ulong id )
{
FullMessage Mapper ( PKMessage msg , PKMember member , PKSystem system ) = >
new FullMessage { Message = msg , System = system , Member = member } ;
var result = await conn . QueryAsync < PKMessage , PKMember , PKSystem , FullMessage > (
"select messages.*, members.*, systems.* from messages, members, systems where (mid = @Id or original_mid = @Id) and messages.member = members.id and systems.id = members.system" ,
Mapper , new { Id = id } ) ;
return result . FirstOrDefault ( ) ;
}
public async Task DeleteMessage ( IPKConnection conn , ulong id )
{
var rowCount = await conn . ExecuteAsync ( "delete from messages where mid = @Id" , new { Id = id } ) ;
if ( rowCount > 0 )
_logger . Information ( "Deleted message {MessageId} from database" , id ) ;
}
public async Task DeleteMessagesBulk ( IPKConnection conn , IReadOnlyCollection < ulong > ids )
{
// Npgsql doesn't support ulongs in general - we hacked around it for plain ulongs but tbh not worth it for collections of ulong
// Hence we map them to single longs, which *are* supported (this is ok since they're Technically (tm) stored as signed longs in the db anyway)
var rowCount = await conn . ExecuteAsync ( "delete from messages where mid = any(@Ids)" ,
new { Ids = ids . Select ( id = > ( long ) id ) . ToArray ( ) } ) ;
if ( rowCount > 0 )
_logger . Information ( "Bulk deleted messages ({FoundCount} found) from database: {MessageIds}" , rowCount ,
ids ) ;
}
2021-05-03 10:33:30 +00:00
public async Task < PKMessage ? > GetLastMessage ( IPKConnection conn , ulong guildId , ulong channelId , ulong accountId )
{
// Want to index scan on the (guild, sender, mid) index so need the additional constraint
return await conn . QuerySingleOrDefaultAsync < PKMessage > (
"select * from messages where guild = @Guild and channel = @Channel and sender = @Sender order by mid desc limit 1" , new
{
Guild = guildId ,
Channel = channelId ,
Sender = accountId
} ) ;
}
2020-08-29 11:46:27 +00:00
}
public class PKMessage
{
public ulong Mid { get ; set ; }
public ulong? Guild { get ; set ; } // null value means "no data" (ie. from before this field being added)
public ulong Channel { get ; set ; }
public MemberId Member { get ; set ; }
public ulong Sender { get ; set ; }
public ulong? OriginalMid { get ; set ; }
}
public class FullMessage
{
public PKMessage Message ;
public PKMember Member ;
public PKSystem System ;
}
}