2021-08-27 15:03:47 +00:00
|
|
|
#nullable enable
|
2021-11-30 02:35:21 +00:00
|
|
|
using Dapper;
|
|
|
|
|
2021-09-30 01:51:38 +00:00
|
|
|
using SqlKata;
|
2020-08-29 11:46:27 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
namespace PluralKit.Core;
|
|
|
|
|
|
|
|
public partial class ModelRepository
|
2020-08-29 11:46:27 +00:00
|
|
|
{
|
2021-11-27 02:10:56 +00:00
|
|
|
public Task<PKSystem?> GetSystem(SystemId id)
|
2020-08-29 11:46:27 +00:00
|
|
|
{
|
2021-11-27 02:10:56 +00:00
|
|
|
var query = new Query("systems").Where("id", id);
|
|
|
|
return _db.QueryFirst<PKSystem?>(query);
|
|
|
|
}
|
2020-08-29 11:46:27 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
public Task<PKSystem?> GetSystemByGuid(Guid id)
|
|
|
|
{
|
|
|
|
var query = new Query("systems").Where("uuid", id);
|
|
|
|
return _db.QueryFirst<PKSystem?>(query);
|
|
|
|
}
|
2021-09-27 03:18:17 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
public Task<PKSystem?> GetSystemByAccount(ulong accountId)
|
|
|
|
{
|
|
|
|
var query = new Query("accounts")
|
|
|
|
.Select("systems.*")
|
|
|
|
.LeftJoin("systems", "systems.id", "accounts.system")
|
2022-01-22 07:47:47 +00:00
|
|
|
.Where("uid", accountId)
|
|
|
|
.WhereNotNull("system");
|
2021-11-27 02:10:56 +00:00
|
|
|
return _db.QueryFirst<PKSystem?>(query);
|
|
|
|
}
|
2020-08-29 11:46:27 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
public Task<PKSystem?> GetSystemByHid(string hid)
|
|
|
|
{
|
|
|
|
var query = new Query("systems").Where("hid", hid.ToLower());
|
|
|
|
return _db.QueryFirst<PKSystem?>(query);
|
|
|
|
}
|
2020-08-29 11:46:27 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
public Task<IEnumerable<ulong>> GetSystemAccounts(SystemId system)
|
|
|
|
{
|
|
|
|
var query = new Query("accounts").Select("uid").Where("system", system);
|
|
|
|
return _db.Query<ulong>(query);
|
|
|
|
}
|
2020-08-29 11:46:27 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
public IAsyncEnumerable<PKMember> GetSystemMembers(SystemId system)
|
|
|
|
{
|
|
|
|
var query = new Query("members").Where("system", system);
|
|
|
|
return _db.QueryStream<PKMember>(query);
|
|
|
|
}
|
2020-08-29 11:46:27 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
public IAsyncEnumerable<PKGroup> GetSystemGroups(SystemId system)
|
|
|
|
{
|
|
|
|
var query = new Query("groups").Where("system", system);
|
|
|
|
return _db.QueryStream<PKGroup>(query);
|
|
|
|
}
|
2021-09-22 01:42:41 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
public Task<int> GetSystemMemberCount(SystemId system, PrivacyLevel? privacyFilter = null)
|
|
|
|
{
|
|
|
|
var query = new Query("members").SelectRaw("count(*)").Where("system", system);
|
|
|
|
if (privacyFilter != null)
|
|
|
|
query.Where("member_visibility", (int)privacyFilter.Value);
|
2021-09-30 01:51:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
return _db.QueryFirst<int>(query);
|
|
|
|
}
|
2020-08-29 11:46:27 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
public Task<int> GetSystemGroupCount(SystemId system, PrivacyLevel? privacyFilter = null)
|
|
|
|
{
|
|
|
|
var query = new Query("groups").SelectRaw("count(*)").Where("system", system);
|
|
|
|
if (privacyFilter != null)
|
|
|
|
query.Where("visibility", (int)privacyFilter.Value);
|
2021-09-30 01:51:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
return _db.QueryFirst<int>(query);
|
|
|
|
}
|
2021-09-30 01:51:38 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
public async Task<PKSystem> CreateSystem(string? systemName = null, IPKConnection? conn = null)
|
|
|
|
{
|
|
|
|
var query = new Query("systems").AsInsert(new
|
2020-08-29 11:46:27 +00:00
|
|
|
{
|
2021-11-27 02:10:56 +00:00
|
|
|
hid = new UnsafeLiteral("find_free_system_hid()"),
|
|
|
|
name = systemName
|
|
|
|
});
|
|
|
|
var system = await _db.QueryFirst<PKSystem>(conn, query, "returning *");
|
|
|
|
_logger.Information("Created {SystemId}", system.Id);
|
|
|
|
|
2021-12-01 14:16:44 +00:00
|
|
|
var (q, pms) = ("insert into system_config (system) values (@system)", new { system = system.Id });
|
2021-11-30 22:04:42 +00:00
|
|
|
|
|
|
|
if (conn == null)
|
|
|
|
await _db.Execute(conn => conn.QueryAsync(q, pms));
|
|
|
|
else
|
|
|
|
await conn.QueryAsync(q, pms);
|
2021-11-30 02:35:21 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
// no dispatch call here - system was just created, we don't have a webhook URL
|
|
|
|
return system;
|
|
|
|
}
|
|
|
|
|
|
|
|
public async Task<PKSystem> UpdateSystem(SystemId id, SystemPatch patch, IPKConnection? conn = null)
|
|
|
|
{
|
|
|
|
_logger.Information("Updated {SystemId}: {@SystemPatch}", id, patch);
|
|
|
|
var query = patch.Apply(new Query("systems").Where("id", id));
|
|
|
|
var res = await _db.QueryFirst<PKSystem>(conn, query, "returning *");
|
|
|
|
|
|
|
|
_ = _dispatch.Dispatch(id, new UpdateDispatchData
|
2020-08-29 11:46:27 +00:00
|
|
|
{
|
2021-11-27 02:10:56 +00:00
|
|
|
Event = DispatchEvent.UPDATE_SYSTEM,
|
|
|
|
EventData = patch.ToJson(),
|
|
|
|
});
|
2021-11-19 16:37:50 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
return res;
|
|
|
|
}
|
2021-11-19 16:37:50 +00:00
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
public async Task AddAccount(SystemId system, ulong accountId, IPKConnection? conn = null)
|
|
|
|
{
|
|
|
|
// We have "on conflict do nothing" since linking an account when it's already linked to the same system is idempotent
|
|
|
|
// This is used in import/export, although the pk;link command checks for this case beforehand
|
2020-08-29 11:46:27 +00:00
|
|
|
|
2022-01-22 07:47:47 +00:00
|
|
|
// update 2022-01: the accounts table is now independent of systems
|
|
|
|
// we MUST check for the presence of a system before inserting, or it will move the new account to the current system
|
|
|
|
|
2021-11-27 02:10:56 +00:00
|
|
|
var query = new Query("accounts").AsInsert(new { system, uid = accountId });
|
2022-01-22 07:47:47 +00:00
|
|
|
await _db.ExecuteQuery(conn, query, "on conflict (uid) do update set system = @p0");
|
2021-11-27 02:10:56 +00:00
|
|
|
|
|
|
|
_logger.Information("Linked account {UserId} to {SystemId}", accountId, system);
|
|
|
|
|
|
|
|
_ = _dispatch.Dispatch(system, new UpdateDispatchData
|
2020-08-29 11:46:27 +00:00
|
|
|
{
|
2021-11-27 02:10:56 +00:00
|
|
|
Event = DispatchEvent.LINK_ACCOUNT,
|
|
|
|
EntityId = accountId.ToString(),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public async Task RemoveAccount(SystemId system, ulong accountId)
|
|
|
|
{
|
2022-01-22 07:47:47 +00:00
|
|
|
var query = new Query("accounts").AsUpdate(new
|
|
|
|
{
|
|
|
|
system = (ulong?)null
|
|
|
|
}).Where("uid", accountId).Where("system", system);
|
2021-11-27 02:10:56 +00:00
|
|
|
await _db.ExecuteQuery(query);
|
|
|
|
_logger.Information("Unlinked account {UserId} from {SystemId}", accountId, system);
|
|
|
|
_ = _dispatch.Dispatch(system, new UpdateDispatchData
|
2020-08-29 11:46:27 +00:00
|
|
|
{
|
2021-11-27 02:10:56 +00:00
|
|
|
Event = DispatchEvent.UNLINK_ACCOUNT,
|
|
|
|
EntityId = accountId.ToString(),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-03-24 01:32:18 +00:00
|
|
|
public async Task DeleteSystem(SystemId id)
|
2021-11-27 02:10:56 +00:00
|
|
|
{
|
2022-03-24 01:32:18 +00:00
|
|
|
await _db.Execute(c => c.QueryAsync("update systems set is_deleting = true where id = @id", new { id = id }));
|
2021-11-27 02:10:56 +00:00
|
|
|
var query = new Query("systems").AsDelete().Where("id", id);
|
2022-03-24 01:32:18 +00:00
|
|
|
await _db.ExecuteQuery(query);
|
2021-11-27 02:10:56 +00:00
|
|
|
_logger.Information("Deleted {SystemId}", id);
|
2020-08-29 11:46:27 +00:00
|
|
|
}
|
|
|
|
}
|