3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-05-10 12:25:02 +00:00

feat: upgrade to TypeORM 0.3

This commit is contained in:
Dragory 2023-07-01 12:17:45 +00:00
parent 8cee4ec1e4
commit 761ff27771
No known key found for this signature in database
57 changed files with 412 additions and 325 deletions

View file

@ -1,8 +1,9 @@
import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { DBDateFormat } from "../utils";
import { ApiPermissionTypes } from "./ApiPermissionAssignments";
import { BaseRepository } from "./BaseRepository";
import { dataSource } from "./dataSource";
import { AllowedGuild } from "./entities/AllowedGuild";
export class AllowedGuilds extends BaseRepository {
@ -10,10 +11,10 @@ export class AllowedGuilds extends BaseRepository {
constructor() {
super();
this.allowedGuilds = getRepository(AllowedGuild);
this.allowedGuilds = dataSource.getRepository(AllowedGuild);
}
async isAllowed(guildId) {
async isAllowed(guildId: string) {
const count = await this.allowedGuilds.count({
where: {
id: guildId,
@ -22,11 +23,15 @@ export class AllowedGuilds extends BaseRepository {
return count !== 0;
}
find(guildId) {
return this.allowedGuilds.findOne(guildId);
find(guildId: string) {
return this.allowedGuilds.findOne({
where: {
id: guildId,
},
});
}
getForApiUser(userId) {
getForApiUser(userId: string) {
return this.allowedGuilds
.createQueryBuilder("allowed_guilds")
.innerJoin(

View file

@ -1,6 +1,7 @@
import { getRepository, Repository } from "typeorm/index";
import { AuditLogEventData, AuditLogEventType } from "./apiAuditLogTypes";
import { Repository } from "typeorm/index";
import { BaseRepository } from "./BaseRepository";
import { AuditLogEventData, AuditLogEventType } from "./apiAuditLogTypes";
import { dataSource } from "./dataSource";
import { ApiAuditLogEntry } from "./entities/ApiAuditLogEntry";
export class ApiAuditLog extends BaseRepository {
@ -8,7 +9,7 @@ export class ApiAuditLog extends BaseRepository {
constructor() {
super();
this.auditLog = getRepository(ApiAuditLogEntry);
this.auditLog = dataSource.getRepository(ApiAuditLogEntry);
}
addEntry<TEventType extends AuditLogEventType>(

View file

@ -1,10 +1,11 @@
import crypto from "crypto";
import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
// tslint:disable-next-line:no-submodule-imports
import uuidv4 from "uuid/v4";
import { DAYS, DBDateFormat } from "../utils";
import { BaseRepository } from "./BaseRepository";
import { dataSource } from "./dataSource";
import { ApiLogin } from "./entities/ApiLogin";
const LOGIN_EXPIRY_TIME = 1 * DAYS;
@ -14,7 +15,7 @@ export class ApiLogins extends BaseRepository {
constructor() {
super();
this.apiLogins = getRepository(ApiLogin);
this.apiLogins = dataSource.getRepository(ApiLogin);
}
async getUserIdByApiKey(apiKey: string): Promise<string | null> {

View file

@ -1,8 +1,9 @@
import { ApiPermissions } from "@shared/apiPermissions";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { ApiAuditLog } from "./ApiAuditLog";
import { AuditLogEventTypes } from "./apiAuditLogTypes";
import { BaseRepository } from "./BaseRepository";
import { AuditLogEventTypes } from "./apiAuditLogTypes";
import { dataSource } from "./dataSource";
import { ApiPermissionAssignment } from "./entities/ApiPermissionAssignment";
export enum ApiPermissionTypes {
@ -16,7 +17,7 @@ export class ApiPermissionAssignments extends BaseRepository {
constructor() {
super();
this.apiPermissions = getRepository(ApiPermissionAssignment);
this.apiPermissions = dataSource.getRepository(ApiPermissionAssignment);
this.auditLogs = new ApiAuditLog();
}

View file

@ -1,8 +1,8 @@
import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { DBDateFormat } from "../utils";
import { BaseRepository } from "./BaseRepository";
import { connection } from "./db";
import { dataSource } from "./dataSource";
import { ApiUserInfoData, ApiUserInfo as ApiUserInfoEntity } from "./entities/ApiUserInfo";
export class ApiUserInfo extends BaseRepository {
@ -10,7 +10,7 @@ export class ApiUserInfo extends BaseRepository {
constructor() {
super();
this.apiUserInfo = getRepository(ApiUserInfoEntity);
this.apiUserInfo = dataSource.getRepository(ApiUserInfoEntity);
}
get(id) {
@ -22,7 +22,7 @@ export class ApiUserInfo extends BaseRepository {
}
update(id, data: ApiUserInfoData) {
return connection.transaction(async (entityManager) => {
return dataSource.transaction(async (entityManager) => {
const repo = entityManager.getRepository(ApiUserInfoEntity);
const existingInfo = await repo.findOne({ where: { id } });

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseRepository } from "./BaseRepository";
import { dataSource } from "./dataSource";
import { ArchiveEntry } from "./entities/ArchiveEntry";
export class Archives extends BaseRepository {
@ -7,7 +8,7 @@ export class Archives extends BaseRepository {
constructor() {
super();
this.archives = getRepository(ArchiveEntry);
this.archives = dataSource.getRepository(ArchiveEntry);
}
public deleteExpiredArchives() {

View file

@ -40,7 +40,7 @@ export class BaseRepository<TEntity = unknown> {
return entity;
}
protected async processEntityFromDB<T extends TEntity | undefined>(entity: T): Promise<T> {
protected async processEntityFromDB<T extends TEntity | null>(entity: T): Promise<T> {
return this._processEntityFromDB(entity);
}

View file

@ -1,9 +1,9 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { isAPI } from "../globals";
import { HOURS, SECONDS } from "../utils";
import { BaseRepository } from "./BaseRepository";
import { cleanupConfigs } from "./cleanup/configs";
import { connection } from "./db";
import { dataSource } from "./dataSource";
import { Config } from "./entities/Config";
const CLEANUP_INTERVAL = 1 * HOURS;
@ -24,7 +24,7 @@ export class Configs extends BaseRepository {
constructor() {
super();
this.configs = getRepository(Config);
this.configs = dataSource.getRepository(Config);
}
getActiveByKey(key) {
@ -37,7 +37,7 @@ export class Configs extends BaseRepository {
}
async getHighestId(): Promise<number> {
const rows = await connection.query("SELECT MAX(id) AS highest_id FROM configs");
const rows = await dataSource.query("SELECT MAX(id) AS highest_id FROM configs");
return (rows.length && rows[0].highest_id) || 0;
}
@ -62,7 +62,7 @@ export class Configs extends BaseRepository {
}
async saveNewRevision(key, config, editedBy) {
return connection.transaction(async (entityManager) => {
return dataSource.transaction(async (entityManager) => {
const repo = entityManager.getRepository(Config);
// Mark all old revisions inactive
await repo.update({ key }, { is_active: false });

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { AntiraidLevel } from "./entities/AntiraidLevel";
export class GuildAntiraidLevels extends BaseGuildRepository {
@ -7,7 +8,7 @@ export class GuildAntiraidLevels extends BaseGuildRepository {
constructor(guildId: string) {
super(guildId);
this.antiraidLevels = getRepository(AntiraidLevel);
this.antiraidLevels = dataSource.getRepository(AntiraidLevel);
}
async get() {

View file

@ -1,12 +1,13 @@
import { Guild, Snowflake } from "discord.js";
import moment from "moment-timezone";
import { isDefaultSticker } from "src/utils/isDefaultSticker";
import { Repository, getRepository } from "typeorm";
import { Repository } from "typeorm";
import { TemplateSafeValueContainer, renderTemplate } from "../templateFormatter";
import { renderUsername, trimLines } from "../utils";
import { decrypt, encrypt } from "../utils/crypt";
import { channelToTemplateSafeChannel, guildToTemplateSafeGuild } from "../utils/templateSafeObjects";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { ArchiveEntry } from "./entities/ArchiveEntry";
import { SavedMessage } from "./entities/SavedMessage";
@ -23,7 +24,7 @@ export class GuildArchives extends BaseGuildRepository<ArchiveEntry> {
constructor(guildId) {
super(guildId);
this.archives = getRepository(ArchiveEntry);
this.archives = dataSource.getRepository(ArchiveEntry);
}
protected async _processEntityFromDB(entity: ArchiveEntry | undefined) {
@ -42,7 +43,7 @@ export class GuildArchives extends BaseGuildRepository<ArchiveEntry> {
return entity;
}
async find(id: string): Promise<ArchiveEntry | undefined> {
async find(id: string): Promise<ArchiveEntry | null> {
const result = await this.archives.findOne({
where: { id },
relations: this.getRelations(),

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { AutoReaction } from "./entities/AutoReaction";
export class GuildAutoReactions extends BaseGuildRepository {
@ -7,7 +8,7 @@ export class GuildAutoReactions extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.autoReactions = getRepository(AutoReaction);
this.autoReactions = dataSource.getRepository(AutoReaction);
}
async all(): Promise<AutoReaction[]> {
@ -18,7 +19,7 @@ export class GuildAutoReactions extends BaseGuildRepository {
});
}
async getForChannel(channelId: string): Promise<AutoReaction | undefined> {
async getForChannel(channelId: string): Promise<AutoReaction | null> {
return this.autoReactions.findOne({
where: {
guild_id: this.guildId,

View file

@ -12,15 +12,19 @@ export class GuildButtonRoles extends BaseGuildRepository {
async getForButtonId(buttonId: string) {
return this.buttonRoles.findOne({
guild_id: this.guildId,
button_id: buttonId,
where: {
guild_id: this.guildId,
button_id: buttonId,
},
});
}
async getAllForMessageId(messageId: string) {
return this.buttonRoles.find({
guild_id: this.guildId,
message_id: messageId,
where: {
guild_id: this.guildId,
message_id: messageId,
},
});
}
@ -40,8 +44,10 @@ export class GuildButtonRoles extends BaseGuildRepository {
async getForButtonGroup(buttonGroup: string) {
return this.buttonRoles.find({
guild_id: this.guildId,
button_group: buttonGroup,
where: {
guild_id: this.guildId,
button_group: buttonGroup,
},
});
}

View file

@ -1,9 +1,9 @@
import { getRepository, In, InsertResult, Repository } from "typeorm";
import { In, InsertResult, Repository } from "typeorm";
import { Queue } from "../Queue";
import { chunkArray } from "../utils";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { CaseTypes } from "./CaseTypes";
import { connection } from "./db";
import { dataSource } from "./dataSource";
import { Case } from "./entities/Case";
import { CaseNote } from "./entities/CaseNote";
@ -15,8 +15,8 @@ export class GuildCases extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.cases = getRepository(Case);
this.caseNotes = getRepository(CaseNote);
this.cases = dataSource.getRepository(Case);
this.caseNotes = dataSource.getRepository(CaseNote);
this.createQueue = new Queue();
}
@ -30,7 +30,7 @@ export class GuildCases extends BaseGuildRepository {
});
}
async find(id: number): Promise<Case | undefined> {
async find(id: number): Promise<Case | null> {
return this.cases.findOne({
relations: this.getRelations(),
where: {
@ -40,7 +40,7 @@ export class GuildCases extends BaseGuildRepository {
});
}
async findByCaseNumber(caseNumber: number): Promise<Case | undefined> {
async findByCaseNumber(caseNumber: number): Promise<Case | null> {
return this.cases.findOne({
relations: this.getRelations(),
where: {
@ -50,7 +50,7 @@ export class GuildCases extends BaseGuildRepository {
});
}
async findLatestByModId(modId: string): Promise<Case | undefined> {
async findLatestByModId(modId: string): Promise<Case | null> {
return this.cases.findOne({
relations: this.getRelations(),
where: {
@ -63,7 +63,7 @@ export class GuildCases extends BaseGuildRepository {
});
}
async findByAuditLogId(auditLogId: string): Promise<Case | undefined> {
async findByAuditLogId(auditLogId: string): Promise<Case | null> {
return this.cases.findOne({
relations: this.getRelations(),
where: {
@ -88,7 +88,7 @@ export class GuildCases extends BaseGuildRepository {
where: {
guild_id: this.guildId,
mod_id: modId,
is_hidden: 0,
is_hidden: false,
},
});
}
@ -99,7 +99,7 @@ export class GuildCases extends BaseGuildRepository {
where: {
guild_id: this.guildId,
mod_id: modId,
is_hidden: 0,
is_hidden: false,
},
skip,
take: count,
@ -181,7 +181,7 @@ export class GuildCases extends BaseGuildRepository {
}
async softDelete(id: number, deletedById: string, deletedByName: string, deletedByText: string) {
return connection.transaction(async (entityManager) => {
return dataSource.transaction(async (entityManager) => {
const cases = entityManager.getRepository(Case);
const caseNotes = entityManager.getRepository(CaseNote);

View file

@ -1,5 +1,6 @@
import { DeleteResult, getRepository, InsertResult, Repository } from "typeorm";
import { DeleteResult, InsertResult, Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { ContextMenuLink } from "./entities/ContextMenuLink";
export class GuildContextMenuLinks extends BaseGuildRepository {
@ -7,10 +8,10 @@ export class GuildContextMenuLinks extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.contextLinks = getRepository(ContextMenuLink);
this.contextLinks = dataSource.getRepository(ContextMenuLink);
}
async get(id: string): Promise<ContextMenuLink | undefined> {
async get(id: string): Promise<ContextMenuLink | null> {
return this.contextLinks.findOne({
where: {
guild_id: this.guildId,

View file

@ -1,11 +1,11 @@
import moment from "moment-timezone";
import { FindConditions, getRepository, In, IsNull, Not, Repository } from "typeorm";
import { FindOptionsWhere, In, IsNull, Not, Repository } from "typeorm";
import { Queue } from "../Queue";
import { DAYS, DBDateFormat, HOURS, MINUTES } from "../utils";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { connection } from "./db";
import { dataSource } from "./dataSource";
import { Counter } from "./entities/Counter";
import { CounterTrigger, isValidCounterComparisonOp, TriggerComparisonOp } from "./entities/CounterTrigger";
import { CounterTrigger, TriggerComparisonOp, isValidCounterComparisonOp } from "./entities/CounterTrigger";
import { CounterTriggerState } from "./entities/CounterTriggerState";
import { CounterValue } from "./entities/CounterValue";
@ -17,11 +17,11 @@ const MAX_COUNTER_VALUE = 2147483647; // 2^31-1, for MySQL INT
const decayQueue = new Queue();
async function deleteCountersMarkedToBeDeleted(): Promise<void> {
await getRepository(Counter).createQueryBuilder().where("delete_at <= NOW()").delete().execute();
await dataSource.getRepository(Counter).createQueryBuilder().where("delete_at <= NOW()").delete().execute();
}
async function deleteTriggersMarkedToBeDeleted(): Promise<void> {
await getRepository(CounterTrigger).createQueryBuilder().where("delete_at <= NOW()").delete().execute();
await dataSource.getRepository(CounterTrigger).createQueryBuilder().where("delete_at <= NOW()").delete().execute();
}
setInterval(deleteCountersMarkedToBeDeleted, 1 * HOURS);
@ -38,10 +38,10 @@ export class GuildCounters extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.counters = getRepository(Counter);
this.counterValues = getRepository(CounterValue);
this.counterTriggers = getRepository(CounterTrigger);
this.counterTriggerStates = getRepository(CounterTriggerState);
this.counters = dataSource.getRepository(Counter);
this.counterValues = dataSource.getRepository(CounterValue);
this.counterTriggers = dataSource.getRepository(CounterTrigger);
this.counterTriggerStates = dataSource.getRepository(CounterTriggerState);
}
async findOrCreateCounter(name: string, perChannel: boolean, perUser: boolean): Promise<Counter> {
@ -80,7 +80,7 @@ export class GuildCounters extends BaseGuildRepository {
}
async markUnusedCountersToBeDeleted(idsToKeep: number[]): Promise<void> {
const criteria: FindConditions<Counter> = {
const criteria: FindOptionsWhere<Counter> = {
guild_id: this.guildId,
delete_at: IsNull(),
};
@ -256,10 +256,12 @@ export class GuildCounters extends BaseGuildRepository {
throw new Error(`Invalid comparison value: ${reverseComparisonValue}`);
}
return connection.transaction(async (entityManager) => {
return dataSource.transaction(async (entityManager) => {
const existing = await entityManager.findOne(CounterTrigger, {
counter_id: counterId,
name: triggerName,
where: {
counter_id: counterId,
name: triggerName,
},
});
if (existing) {
@ -308,11 +310,13 @@ export class GuildCounters extends BaseGuildRepository {
channelId = channelId || "0";
userId = userId || "0";
return connection.transaction(async (entityManager) => {
return dataSource.transaction(async (entityManager) => {
const previouslyTriggered = await entityManager.findOne(CounterTriggerState, {
trigger_id: counterTrigger.id,
user_id: userId!,
channel_id: channelId!,
where: {
trigger_id: counterTrigger.id,
user_id: userId!,
channel_id: channelId!,
},
});
if (previouslyTriggered) {
@ -356,7 +360,7 @@ export class GuildCounters extends BaseGuildRepository {
async checkAllValuesForTrigger(
counterTrigger: CounterTrigger,
): Promise<Array<{ channelId: string; userId: string }>> {
return connection.transaction(async (entityManager) => {
return dataSource.transaction(async (entityManager) => {
const matchingValues = await entityManager
.createQueryBuilder(CounterValue, "cv")
.leftJoin(
@ -407,7 +411,7 @@ export class GuildCounters extends BaseGuildRepository {
channelId = channelId || "0";
userId = userId || "0";
return connection.transaction(async (entityManager) => {
return dataSource.transaction(async (entityManager) => {
const matchingValue = await entityManager
.createQueryBuilder(CounterValue, "cv")
.innerJoin(
@ -446,7 +450,7 @@ export class GuildCounters extends BaseGuildRepository {
async checkAllValuesForReverseTrigger(
counterTrigger: CounterTrigger,
): Promise<Array<{ channelId: string; userId: string }>> {
return connection.transaction(async (entityManager) => {
return dataSource.transaction(async (entityManager) => {
const matchingValues: Array<{
id: string;
triggerStateId: string;

View file

@ -1,8 +1,9 @@
import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { Blocker } from "../Blocker";
import { DBDateFormat, MINUTES } from "../utils";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { MemberCacheItem } from "./entities/MemberCacheItem";
const SAVE_PENDING_BLOCKER_KEY = "save-pending" as const;
@ -20,7 +21,7 @@ export class GuildMemberCache extends BaseGuildRepository {
constructor(guildId: string) {
super(guildId);
this.#memberCache = getRepository(MemberCacheItem);
this.#memberCache = dataSource.getRepository(MemberCacheItem);
this.#pendingUpdates = new Map();
this.#blocker = new Blocker();
}

View file

@ -1,6 +1,6 @@
import { getRepository, Repository } from "typeorm/index";
import { Repository } from "typeorm/index";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { connection } from "./db";
import { dataSource } from "./dataSource";
import { MemberTimezone } from "./entities/MemberTimezone";
export class GuildMemberTimezones extends BaseGuildRepository {
@ -8,22 +8,26 @@ export class GuildMemberTimezones extends BaseGuildRepository {
constructor(guildId: string) {
super(guildId);
this.memberTimezones = getRepository(MemberTimezone);
this.memberTimezones = dataSource.getRepository(MemberTimezone);
}
get(memberId: string) {
return this.memberTimezones.findOne({
guild_id: this.guildId,
member_id: memberId,
where: {
guild_id: this.guildId,
member_id: memberId,
},
});
}
async set(memberId, timezone: string) {
await connection.transaction(async (entityManager) => {
await dataSource.transaction(async (entityManager) => {
const repo = entityManager.getRepository(MemberTimezone);
const existingRow = await repo.findOne({
guild_id: this.guildId,
member_id: memberId,
where: {
guild_id: this.guildId,
member_id: memberId,
},
});
if (existingRow) {

View file

@ -1,9 +1,10 @@
import moment from "moment-timezone";
import { Brackets, getRepository, Repository } from "typeorm";
import { Brackets, Repository } from "typeorm";
import { DBDateFormat } from "../utils";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { Mute } from "./entities/Mute";
import { MuteTypes } from "./MuteTypes";
import { dataSource } from "./dataSource";
import { Mute } from "./entities/Mute";
export type AddMuteParams = {
userId: Mute["user_id"];
@ -19,7 +20,7 @@ export class GuildMutes extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.mutes = getRepository(Mute);
this.mutes = dataSource.getRepository(Mute);
}
async getExpiredMutes(): Promise<Mute[]> {
@ -31,7 +32,7 @@ export class GuildMutes extends BaseGuildRepository {
.getMany();
}
async findExistingMuteForUserId(userId: string): Promise<Mute | undefined> {
async findExistingMuteForUserId(userId: string): Promise<Mute | null> {
return this.mutes.findOne({
where: {
guild_id: this.guildId,

View file

@ -1,8 +1,9 @@
import { getRepository, In, Repository } from "typeorm";
import { In, Repository } from "typeorm";
import { isAPI } from "../globals";
import { MINUTES, SECONDS } from "../utils";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { cleanupNicknames } from "./cleanup/nicknames";
import { dataSource } from "./dataSource";
import { NicknameHistoryEntry } from "./entities/NicknameHistoryEntry";
const CLEANUP_INTERVAL = 5 * MINUTES;
@ -25,7 +26,7 @@ export class GuildNicknameHistory extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.nicknameHistory = getRepository(NicknameHistoryEntry);
this.nicknameHistory = dataSource.getRepository(NicknameHistoryEntry);
}
async getByUserId(userId): Promise<NicknameHistoryEntry[]> {
@ -40,7 +41,7 @@ export class GuildNicknameHistory extends BaseGuildRepository {
});
}
getLastEntry(userId): Promise<NicknameHistoryEntry | undefined> {
getLastEntry(userId): Promise<NicknameHistoryEntry | null> {
return this.nicknameHistory.findOne({
where: {
guild_id: this.guildId,

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { PersistedData } from "./entities/PersistedData";
export class GuildPersistedData extends BaseGuildRepository {
@ -7,7 +8,7 @@ export class GuildPersistedData extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.persistedData = getRepository(PersistedData);
this.persistedData = dataSource.getRepository(PersistedData);
}
async find(userId: string) {

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { PingableRole } from "./entities/PingableRole";
export class GuildPingableRoles extends BaseGuildRepository {
@ -7,7 +8,7 @@ export class GuildPingableRoles extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.pingableRoles = getRepository(PingableRole);
this.pingableRoles = dataSource.getRepository(PingableRole);
}
async all(): Promise<PingableRole[]> {
@ -27,7 +28,7 @@ export class GuildPingableRoles extends BaseGuildRepository {
});
}
async getByChannelAndRoleId(channelId: string, roleId: string): Promise<PingableRole | undefined> {
async getByChannelAndRoleId(channelId: string, roleId: string): Promise<PingableRole | null> {
return this.pingableRoles.findOne({
where: {
guild_id: this.guildId,

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { ReactionRole } from "./entities/ReactionRole";
export class GuildReactionRoles extends BaseGuildRepository {
@ -7,7 +8,7 @@ export class GuildReactionRoles extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.reactionRoles = getRepository(ReactionRole);
this.reactionRoles = dataSource.getRepository(ReactionRole);
}
async all(): Promise<ReactionRole[]> {
@ -30,7 +31,7 @@ export class GuildReactionRoles extends BaseGuildRepository {
});
}
async getByMessageAndEmoji(messageId: string, emoji: string): Promise<ReactionRole | undefined> {
async getByMessageAndEmoji(messageId: string, emoji: string): Promise<ReactionRole | null> {
return this.reactionRoles.findOne({
where: {
guild_id: this.guildId,

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { Reminder } from "./entities/Reminder";
export class GuildReminders extends BaseGuildRepository {
@ -7,7 +8,7 @@ export class GuildReminders extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.reminders = getRepository(Reminder);
this.reminders = dataSource.getRepository(Reminder);
}
async getDueReminders(): Promise<Reminder[]> {
@ -28,7 +29,9 @@ export class GuildReminders extends BaseGuildRepository {
}
find(id: number) {
return this.reminders.findOne({ id });
return this.reminders.findOne({
where: { id },
});
}
async delete(id) {

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { RoleButtonsItem } from "./entities/RoleButtonsItem";
export class GuildRoleButtons extends BaseGuildRepository {
@ -7,11 +8,15 @@ export class GuildRoleButtons extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.roleButtons = getRepository(RoleButtonsItem);
this.roleButtons = dataSource.getRepository(RoleButtonsItem);
}
getSavedRoleButtons(): Promise<RoleButtonsItem[]> {
return this.roleButtons.find({ guild_id: this.guildId });
return this.roleButtons.find({
where: {
guild_id: this.guildId,
},
});
}
async deleteRoleButtonItem(name: string): Promise<void> {

View file

@ -1,6 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { connection } from "./db";
import { dataSource } from "./dataSource";
import { RoleQueueItem } from "./entities/RoleQueueItem";
export class GuildRoleQueue extends BaseGuildRepository {
@ -8,11 +8,11 @@ export class GuildRoleQueue extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.roleQueue = getRepository(RoleQueueItem);
this.roleQueue = dataSource.getRepository(RoleQueueItem);
}
consumeNextRoleAssignments(count: number): Promise<RoleQueueItem[]> {
return connection.transaction(async (entityManager) => {
return dataSource.transaction(async (entityManager) => {
const repository = entityManager.getRepository(RoleQueueItem);
const nextAssignments = await repository

View file

@ -1,12 +1,13 @@
import { GuildChannel, Message } from "discord.js";
import moment from "moment-timezone";
import { Repository, getRepository } from "typeorm";
import { Repository } from "typeorm";
import { QueuedEventEmitter } from "../QueuedEventEmitter";
import { noop } from "../utils";
import { asyncMap } from "../utils/async";
import { decryptJson, encryptJson } from "../utils/cryptHelpers";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { buildEntity } from "./buildEntity";
import { dataSource } from "./dataSource";
import { ISavedMessageData, SavedMessage } from "./entities/SavedMessage";
export class GuildSavedMessages extends BaseGuildRepository<SavedMessage> {
@ -17,7 +18,7 @@ export class GuildSavedMessages extends BaseGuildRepository<SavedMessage> {
constructor(guildId) {
super(guildId);
this.messages = getRepository(SavedMessage);
this.messages = dataSource.getRepository(SavedMessage);
this.events = new QueuedEventEmitter();
this.toBePermanent = new Set();
@ -137,7 +138,7 @@ export class GuildSavedMessages extends BaseGuildRepository<SavedMessage> {
return entity;
}
async find(id: string, includeDeleted = false): Promise<SavedMessage | undefined> {
async find(id: string, includeDeleted = false): Promise<SavedMessage | null> {
let query = this.messages
.createQueryBuilder()
.where("guild_id = :guild_id", { guild_id: this.guildId })

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { ScheduledPost } from "./entities/ScheduledPost";
export class GuildScheduledPosts extends BaseGuildRepository {
@ -7,7 +8,7 @@ export class GuildScheduledPosts extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.scheduledPosts = getRepository(ScheduledPost);
this.scheduledPosts = dataSource.getRepository(ScheduledPost);
}
all(): Promise<ScheduledPost[]> {
@ -23,7 +24,11 @@ export class GuildScheduledPosts extends BaseGuildRepository {
}
find(id: number) {
return this.scheduledPosts.findOne({ id });
return this.scheduledPosts.findOne({
where: {
id,
},
});
}
async delete(id) {

View file

@ -1,6 +1,7 @@
import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { SlowmodeChannel } from "./entities/SlowmodeChannel";
import { SlowmodeUser } from "./entities/SlowmodeUser";
@ -10,11 +11,11 @@ export class GuildSlowmodes extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.slowmodeChannels = getRepository(SlowmodeChannel);
this.slowmodeUsers = getRepository(SlowmodeUser);
this.slowmodeChannels = dataSource.getRepository(SlowmodeChannel);
this.slowmodeUsers = dataSource.getRepository(SlowmodeUser);
}
async getChannelSlowmode(channelId): Promise<SlowmodeChannel | undefined> {
async getChannelSlowmode(channelId): Promise<SlowmodeChannel | null> {
return this.slowmodeChannels.findOne({
where: {
guild_id: this.guildId,
@ -51,11 +52,13 @@ export class GuildSlowmodes extends BaseGuildRepository {
});
}
async getChannelSlowmodeUser(channelId, userId): Promise<SlowmodeUser | undefined> {
async getChannelSlowmodeUser(channelId, userId): Promise<SlowmodeUser | null> {
return this.slowmodeUsers.findOne({
guild_id: this.guildId,
channel_id: channelId,
user_id: userId,
where: {
guild_id: this.guildId,
channel_id: channelId,
user_id: userId,
},
});
}

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { StarboardMessage } from "./entities/StarboardMessage";
export class GuildStarboardMessages extends BaseGuildRepository {
@ -7,7 +8,7 @@ export class GuildStarboardMessages extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.allStarboardMessages = getRepository(StarboardMessage);
this.allStarboardMessages = dataSource.getRepository(StarboardMessage);
}
async getStarboardMessagesForMessageId(messageId: string) {

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { StarboardReaction } from "./entities/StarboardReaction";
export class GuildStarboardReactions extends BaseGuildRepository {
@ -7,7 +8,7 @@ export class GuildStarboardReactions extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.allStarboardReactions = getRepository(StarboardReaction);
this.allStarboardReactions = dataSource.getRepository(StarboardReaction);
}
async getAllReactionsForMessageId(messageId: string) {

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { StatValue } from "./entities/StatValue";
export class GuildStats extends BaseGuildRepository {
@ -7,7 +8,7 @@ export class GuildStats extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.stats = getRepository(StatValue);
this.stats = dataSource.getRepository(StatValue);
}
async saveValue(source: string, key: string, value: number): Promise<void> {

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { Tag } from "./entities/Tag";
import { TagResponse } from "./entities/TagResponse";
@ -9,8 +10,8 @@ export class GuildTags extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.tags = getRepository(Tag);
this.tagResponses = getRepository(TagResponse);
this.tags = dataSource.getRepository(Tag);
this.tagResponses = dataSource.getRepository(TagResponse);
}
async all(): Promise<Tag[]> {
@ -21,7 +22,7 @@ export class GuildTags extends BaseGuildRepository {
});
}
async find(tag): Promise<Tag | undefined> {
async find(tag): Promise<Tag | null> {
return this.tags.findOne({
where: {
guild_id: this.guildId,
@ -61,7 +62,7 @@ export class GuildTags extends BaseGuildRepository {
});
}
async findResponseByCommandMessageId(messageId: string): Promise<TagResponse | undefined> {
async findResponseByCommandMessageId(messageId: string): Promise<TagResponse | null> {
return this.tagResponses.findOne({
where: {
guild_id: this.guildId,
@ -70,7 +71,7 @@ export class GuildTags extends BaseGuildRepository {
});
}
async findResponseByResponseMessageId(messageId: string): Promise<TagResponse | undefined> {
async findResponseByResponseMessageId(messageId: string): Promise<TagResponse | null> {
return this.tagResponses.findOne({
where: {
guild_id: this.guildId,

View file

@ -1,6 +1,7 @@
import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { Tempban } from "./entities/Tempban";
export class GuildTempbans extends BaseGuildRepository {
@ -8,7 +9,7 @@ export class GuildTempbans extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.tempbans = getRepository(Tempban);
this.tempbans = dataSource.getRepository(Tempban);
}
async getExpiredTempbans(): Promise<Tempban[]> {
@ -20,7 +21,7 @@ export class GuildTempbans extends BaseGuildRepository {
.getMany();
}
async findExistingTempbanForUserId(userId: string): Promise<Tempban | undefined> {
async findExistingTempbanForUserId(userId: string): Promise<Tempban | null> {
return this.tempbans.findOne({
where: {
guild_id: this.guildId,

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseGuildRepository } from "./BaseGuildRepository";
import { dataSource } from "./dataSource";
import { VCAlert } from "./entities/VCAlert";
export class GuildVCAlerts extends BaseGuildRepository {
@ -7,7 +8,7 @@ export class GuildVCAlerts extends BaseGuildRepository {
constructor(guildId) {
super(guildId);
this.allAlerts = getRepository(VCAlert);
this.allAlerts = dataSource.getRepository(VCAlert);
}
async getOutdatedAlerts(): Promise<VCAlert[]> {
@ -41,7 +42,9 @@ export class GuildVCAlerts extends BaseGuildRepository {
}
find(id: number) {
return this.allAlerts.findOne({ id });
return this.allAlerts.findOne({
where: { id },
});
}
async delete(id) {

View file

@ -1,7 +1,8 @@
import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { DAYS } from "../utils";
import { BaseRepository } from "./BaseRepository";
import { dataSource } from "./dataSource";
import { MemberCacheItem } from "./entities/MemberCacheItem";
const STALE_PERIOD = 90 * DAYS;
@ -11,7 +12,7 @@ export class MemberCache extends BaseRepository {
constructor() {
super();
this.#memberCache = getRepository(MemberCacheItem);
this.#memberCache = dataSource.getRepository(MemberCacheItem);
}
async deleteStaleData(): Promise<void> {

View file

@ -1,9 +1,10 @@
import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { DAYS, DBDateFormat } from "../utils";
import { BaseRepository } from "./BaseRepository";
import { Mute } from "./entities/Mute";
import { MuteTypes } from "./MuteTypes";
import { dataSource } from "./dataSource";
import { Mute } from "./entities/Mute";
const OLD_EXPIRED_MUTE_THRESHOLD = 7 * DAYS;
@ -16,10 +17,10 @@ export class Mutes extends BaseRepository {
constructor() {
super();
this.mutes = getRepository(Mute);
this.mutes = dataSource.getRepository(Mute);
}
findMute(guildId: string, userId: string): Promise<Mute | undefined> {
findMute(guildId: string, userId: string): Promise<Mute | null> {
return this.mutes.findOne({
where: {
guild_id: guildId,

View file

@ -1,8 +1,9 @@
import crypto from "crypto";
import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { env } from "../env";
import { DAYS, DBDateFormat, HOURS, MINUTES } from "../utils";
import { dataSource } from "./dataSource";
import { PhishermanCacheEntry } from "./entities/PhishermanCacheEntry";
import { PhishermanKeyCacheEntry } from "./entities/PhishermanKeyCacheEntry";
import { PhishermanDomainInfo, PhishermanUnknownDomain } from "./types/phisherman";
@ -39,7 +40,7 @@ const KEY_VALIDITY_LIFETIME = 24 * HOURS;
let cacheRepository: Repository<PhishermanCacheEntry> | null = null;
function getCacheRepository(): Repository<PhishermanCacheEntry> {
if (cacheRepository == null) {
cacheRepository = getRepository(PhishermanCacheEntry);
cacheRepository = dataSource.getRepository(PhishermanCacheEntry);
}
return cacheRepository;
}
@ -47,7 +48,7 @@ function getCacheRepository(): Repository<PhishermanCacheEntry> {
let keyCacheRepository: Repository<PhishermanKeyCacheEntry> | null = null;
function getKeyCacheRepository(): Repository<PhishermanKeyCacheEntry> {
if (keyCacheRepository == null) {
keyCacheRepository = getRepository(PhishermanKeyCacheEntry);
keyCacheRepository = dataSource.getRepository(PhishermanKeyCacheEntry);
}
return keyCacheRepository;
}
@ -153,7 +154,9 @@ export async function getPhishermanDomainInfo(domain: string): Promise<Phisherma
}
const dbCache = getCacheRepository();
const existingCachedEntry = await dbCache.findOne({ domain });
const existingCachedEntry = await dbCache.findOne({
where: { domain },
});
if (existingCachedEntry) {
return existingCachedEntry.data;
}
@ -196,7 +199,9 @@ export async function phishermanApiKeyIsValid(apiKey: string): Promise<boolean>
const keyCache = getKeyCacheRepository();
const hash = crypto.createHash("sha256").update(apiKey).digest("hex");
const entry = await keyCache.findOne({ hash });
const entry = await keyCache.findOne({
where: { hash },
});
if (entry) {
return entry.is_valid;
}

View file

@ -1,7 +1,8 @@
import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { DBDateFormat } from "../utils";
import { BaseRepository } from "./BaseRepository";
import { dataSource } from "./dataSource";
import { Reminder } from "./entities/Reminder";
export class Reminders extends BaseRepository {
@ -9,7 +10,7 @@ export class Reminders extends BaseRepository {
constructor() {
super();
this.reminders = getRepository(Reminder);
this.reminders = dataSource.getRepository(Reminder);
}
async getRemindersDueSoon(threshold: number): Promise<Reminder[]> {

View file

@ -1,7 +1,8 @@
import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { DBDateFormat } from "../utils";
import { BaseRepository } from "./BaseRepository";
import { dataSource } from "./dataSource";
import { ScheduledPost } from "./entities/ScheduledPost";
export class ScheduledPosts extends BaseRepository {
@ -9,7 +10,7 @@ export class ScheduledPosts extends BaseRepository {
constructor() {
super();
this.scheduledPosts = getRepository(ScheduledPost);
this.scheduledPosts = dataSource.getRepository(ScheduledPost);
}
getScheduledPostsDueSoon(threshold: number): Promise<ScheduledPost[]> {

View file

@ -1,5 +1,6 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { BaseRepository } from "./BaseRepository";
import { dataSource } from "./dataSource";
import { Supporter } from "./entities/Supporter";
export class Supporters extends BaseRepository {
@ -7,7 +8,7 @@ export class Supporters extends BaseRepository {
constructor() {
super();
this.supporters = getRepository(Supporter);
this.supporters = dataSource.getRepository(Supporter);
}
getAll() {

View file

@ -1,7 +1,8 @@
import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { DBDateFormat } from "../utils";
import { BaseRepository } from "./BaseRepository";
import { dataSource } from "./dataSource";
import { Tempban } from "./entities/Tempban";
export class Tempbans extends BaseRepository {
@ -9,7 +10,7 @@ export class Tempbans extends BaseRepository {
constructor() {
super();
this.tempbans = getRepository(Tempban);
this.tempbans = dataSource.getRepository(Tempban);
}
getSoonExpiringTempbans(threshold: number): Promise<Tempban[]> {

View file

@ -1,8 +1,9 @@
import { getRepository, In, Repository } from "typeorm";
import { In, Repository } from "typeorm";
import { isAPI } from "../globals";
import { MINUTES, SECONDS } from "../utils";
import { BaseRepository } from "./BaseRepository";
import { cleanupUsernames } from "./cleanup/usernames";
import { dataSource } from "./dataSource";
import { UsernameHistoryEntry } from "./entities/UsernameHistoryEntry";
const CLEANUP_INTERVAL = 5 * MINUTES;
@ -25,7 +26,7 @@ export class UsernameHistory extends BaseRepository {
constructor() {
super();
this.usernameHistory = getRepository(UsernameHistoryEntry);
this.usernameHistory = dataSource.getRepository(UsernameHistoryEntry);
}
async getByUserId(userId): Promise<UsernameHistoryEntry[]> {
@ -40,7 +41,7 @@ export class UsernameHistory extends BaseRepository {
});
}
getLastEntry(userId): Promise<UsernameHistoryEntry | undefined> {
getLastEntry(userId): Promise<UsernameHistoryEntry | null> {
return this.usernameHistory.findOne({
where: {
user_id: userId,

View file

@ -1,7 +1,8 @@
import moment from "moment-timezone";
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { DBDateFormat } from "../utils";
import { BaseRepository } from "./BaseRepository";
import { dataSource } from "./dataSource";
import { VCAlert } from "./entities/VCAlert";
export class VCAlerts extends BaseRepository {
@ -9,7 +10,7 @@ export class VCAlerts extends BaseRepository {
constructor() {
super();
this.allAlerts = getRepository(VCAlert);
this.allAlerts = dataSource.getRepository(VCAlert);
}
async getSoonExpiringAlerts(threshold: number): Promise<VCAlert[]> {

View file

@ -1,10 +1,11 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { decrypt, encrypt } from "../utils/crypt";
import { BaseRepository } from "./BaseRepository";
import { dataSource } from "./dataSource";
import { Webhook } from "./entities/Webhook";
export class Webhooks extends BaseRepository {
repository: Repository<Webhook> = getRepository(Webhook);
repository: Repository<Webhook> = dataSource.getRepository(Webhook);
protected async _processEntityFromDB(entity) {
entity.token = await decrypt(entity.token);

View file

@ -1,13 +1,13 @@
import moment from "moment-timezone";
import { getRepository, In } from "typeorm";
import { In } from "typeorm";
import { DBDateFormat } from "../../utils";
import { connection } from "../db";
import { dataSource } from "../dataSource";
import { Config } from "../entities/Config";
const CLEAN_PER_LOOP = 50;
export async function cleanupConfigs() {
const configRepository = getRepository(Config);
const configRepository = dataSource.getRepository(Config);
// FIXME: The query below doesn't work on MySQL 8.0. Pending an update.
return;
@ -18,7 +18,7 @@ export async function cleanupConfigs() {
// >1 month old: 1 config retained per month
const oneMonthCutoff = moment.utc().subtract(30, "days").format(DBDateFormat);
do {
rows = await connection.query(
rows = await dataSource.query(
`
WITH _configs
AS (
@ -56,7 +56,7 @@ export async function cleanupConfigs() {
// >2 weeks old: 1 config retained per day
const twoWeekCutoff = moment.utc().subtract(2, "weeks").format(DBDateFormat);
do {
rows = await connection.query(
rows = await dataSource.query(
`
WITH _configs
AS (

View file

@ -1,7 +1,7 @@
import moment from "moment-timezone";
import { getRepository, In } from "typeorm";
import { In } from "typeorm";
import { DAYS, DBDateFormat, MINUTES, SECONDS, sleep } from "../../utils";
import { connection } from "../db";
import { dataSource } from "../dataSource";
import { SavedMessage } from "../entities/SavedMessage";
/**
@ -16,7 +16,7 @@ const CLEAN_PER_LOOP = 100;
export async function cleanupMessages(): Promise<number> {
let cleaned = 0;
const messagesRepository = getRepository(SavedMessage);
const messagesRepository = dataSource.getRepository(SavedMessage);
const deletedAtThreshold = moment.utc().subtract(DELETED_MESSAGE_RETENTION_PERIOD, "ms").format(DBDateFormat);
const postedAtThreshold = moment.utc().subtract(RETENTION_PERIOD, "ms").format(DBDateFormat);
@ -27,7 +27,7 @@ export async function cleanupMessages(): Promise<number> {
// when a message was being inserted at the same time
let ids: string[];
do {
const deletedMessageRows = await connection.query(
const deletedMessageRows = await dataSource.query(
`
SELECT id
FROM messages
@ -40,7 +40,7 @@ export async function cleanupMessages(): Promise<number> {
[deletedAtThreshold],
);
const oldPostedRows = await connection.query(
const oldPostedRows = await dataSource.query(
`
SELECT id
FROM messages
@ -53,7 +53,7 @@ export async function cleanupMessages(): Promise<number> {
[postedAtThreshold],
);
const oldBotPostedRows = await connection.query(
const oldBotPostedRows = await dataSource.query(
`
SELECT id
FROM messages

View file

@ -1,7 +1,7 @@
import moment from "moment-timezone";
import { getRepository, In } from "typeorm";
import { In } from "typeorm";
import { DAYS, DBDateFormat } from "../../utils";
import { connection } from "../db";
import { dataSource } from "../dataSource";
import { NicknameHistoryEntry } from "../entities/NicknameHistoryEntry";
export const NICKNAME_RETENTION_PERIOD = 30 * DAYS;
@ -10,13 +10,13 @@ const CLEAN_PER_LOOP = 500;
export async function cleanupNicknames(): Promise<number> {
let cleaned = 0;
const nicknameHistoryRepository = getRepository(NicknameHistoryEntry);
const nicknameHistoryRepository = dataSource.getRepository(NicknameHistoryEntry);
const dateThreshold = moment.utc().subtract(NICKNAME_RETENTION_PERIOD, "ms").format(DBDateFormat);
// Clean old nicknames (NICKNAME_RETENTION_PERIOD)
let rows;
do {
rows = await connection.query(
rows = await dataSource.query(
`
SELECT id
FROM nickname_history

View file

@ -1,7 +1,7 @@
import moment from "moment-timezone";
import { getRepository, In } from "typeorm";
import { In } from "typeorm";
import { DAYS, DBDateFormat } from "../../utils";
import { connection } from "../db";
import { dataSource } from "../dataSource";
import { UsernameHistoryEntry } from "../entities/UsernameHistoryEntry";
export const USERNAME_RETENTION_PERIOD = 30 * DAYS;
@ -10,13 +10,13 @@ const CLEAN_PER_LOOP = 500;
export async function cleanupUsernames(): Promise<number> {
let cleaned = 0;
const usernameHistoryRepository = getRepository(UsernameHistoryEntry);
const usernameHistoryRepository = dataSource.getRepository(UsernameHistoryEntry);
const dateThreshold = moment.utc().subtract(USERNAME_RETENTION_PERIOD, "ms").format(DBDateFormat);
// Clean old usernames (USERNAME_RETENTION_PERIOD)
let rows;
do {
rows = await connection.query(
rows = await dataSource.query(
`
SELECT id
FROM username_history

View file

@ -0,0 +1,45 @@
import moment from "moment-timezone";
import path from "path";
import { DataSource } from "typeorm";
import { env } from "../env";
import { backendDir } from "../paths";
moment.tz.setDefault("UTC");
const entities = path.relative(process.cwd(), path.resolve(backendDir, "dist/backend/src/data/entities/*.js"));
const migrations = path.relative(process.cwd(), path.resolve(backendDir, "dist/backend/src/migrations/*.js"));
export const dataSource = new DataSource({
type: "mysql",
host: env.DB_HOST,
port: env.DB_PORT,
username: env.DB_USER,
password: env.DB_PASSWORD,
database: env.DB_DATABASE,
charset: "utf8mb4",
supportBigNumbers: true,
bigNumberStrings: true,
dateStrings: true,
synchronize: false,
connectTimeout: 2000,
logging: ["error", "warn"],
// Entities
entities: [entities],
// Pool options
extra: {
typeCast(field, next) {
if (field.type === "DATETIME") {
const val = field.string();
return val != null ? moment.utc(val).format("YYYY-MM-DD HH:mm:ss") : null;
}
return next();
},
},
// Migrations
migrations: [migrations],
});

View file

@ -1,33 +1,15 @@
import path from "path";
import { Connection, createConnection } from "typeorm";
import { SimpleError } from "../SimpleError";
import { backendDir } from "../paths";
import { QueryLogger } from "./queryLogger";
import { dataSource } from "./dataSource";
const ormconfigPath = path.join(backendDir, "ormconfig.js");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const connectionOptions = require(ormconfigPath);
let connectionPromise: Promise<Connection>;
export let connection: Connection;
let connectionPromise: Promise<void>;
export function connect() {
if (!connectionPromise) {
connectionPromise = createConnection({
...(connectionOptions as any),
logging: ["query", "error"],
logger: new QueryLogger(),
}).then((newConnection) => {
// Verify the DB timezone is set to UTC
return newConnection.query("SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP) AS tz").then((r) => {
if (r[0].tz !== "00:00:00") {
throw new SimpleError(`Database timezone must be UTC (detected ${r[0].tz})`);
}
connection = newConnection;
return newConnection;
});
connectionPromise = dataSource.initialize().then(async (initializedDataSource) => {
const tzResult = await initializedDataSource.query("SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP) AS tz");
if (tzResult[0].tz !== "00:00:00") {
throw new SimpleError(`Database timezone must be UTC (detected ${tzResult[0].tz})`);
}
});
}

View file

@ -1,14 +1,15 @@
import { getRepository, Repository } from "typeorm";
import { Repository } from "typeorm";
import { dataSource } from "./dataSource";
import { SavedMessage } from "./entities/SavedMessage";
let repository: Repository<SavedMessage>;
export async function getChannelIdFromMessageId(messageId: string): Promise<string | null> {
if (!repository) {
repository = getRepository(SavedMessage);
repository = dataSource.getRepository(SavedMessage);
}
const savedMessage = await repository.findOne(messageId);
const savedMessage = await repository.findOne({ where: { id: messageId } });
if (savedMessage) {
return savedMessage.channel_id;
}