Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(alerts): add promo alert support #5424

Merged
merged 8 commits into from Aug 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion locales/cs/ui/properties.json
Expand Up @@ -3,5 +3,9 @@
"command": "Příkaz",
"price": "Cena (body)",
"priceBits": "Cena (bity)",
"thisvalue": "Tato hodnota"
"thisvalue": "Tato hodnota",
"promo": {
"shoutoutMessage": "Shoutout message",
"enableShoutoutMessage": "Send shoutout messge in chat"
}
}
2 changes: 1 addition & 1 deletion locales/cs/ui/registry/alerts.json
Expand Up @@ -113,7 +113,7 @@
"messageTemplate": {
"name": "Šablona zprávy",
"placeholder": "Zadejte svou šablonu zprávy",
"help": "Dostupné proměnné: {name}, {amount} (bits, subs, tips, subgifts, sub community gifts, command redeems), {recipient} (subgifts, command redeems), {monthsName} (subs, subgifts), {currency} (tips)"
"help": "Available variables: {name}, {amount} (cheers, subs, tips, subgifts, sub community gifts, command redeems), {recipient} (subgifts, command redeems), {monthsName} (subs, subgifts), {currency} (tips), {game} (promo). If | is added (see promo) then it will show those values in sequence."
},
"ttsTemplate": {
"name": "TTS šablona",
Expand Down
6 changes: 5 additions & 1 deletion locales/en/ui/properties.json
Expand Up @@ -3,5 +3,9 @@
"command": "Command",
"price": "Price (points)",
"priceBits": "Price (bits)",
"thisvalue": "This value"
"thisvalue": "This value",
"promo": {
"shoutoutMessage": "Shoutout message",
"enableShoutoutMessage": "Send shoutout message in chat"
}
}
3 changes: 2 additions & 1 deletion locales/en/ui/registry/alerts.json
Expand Up @@ -55,6 +55,7 @@
"hosts": "Hosts",
"raids": "Raids",
"cmdredeems": "Custom",
"promo": "Promo",
"rewardredeems": "Reward Redeems"
},
"title": {
Expand Down Expand Up @@ -113,7 +114,7 @@
"messageTemplate": {
"name": "Message template",
"placeholder": "Set your message template",
"help": "Available variables: {name}, {amount} (cheers, subs, tips, subgifts, sub community gifts, command redeems), {recipient} (subgifts, command redeems), {monthsName} (subs, subgifts), {currency} (tips)"
"help": "Available variables: {name}, {amount} (cheers, subs, tips, subgifts, sub community gifts, command redeems), {recipient} (subgifts, command redeems), {monthsName} (subs, subgifts), {currency} (tips), {game} (promo). If | is added (see promo) then it will show those values in sequence."
},
"ttsTemplate": {
"name": "TTS template",
Expand Down
24 changes: 12 additions & 12 deletions package.json
Expand Up @@ -11,10 +11,10 @@
"author": "Michal Orlik <sogehige@gmail.com>",
"license": "MIT",
"dependencies": {
"@sogebot/ui-admin": "^58.0.0",
"@sogebot/ui-admin": "^59.0.2",
"@sogebot/ui-helpers": "^3.1.0",
"@sogebot/ui-oauth": "~3.1.1",
"@sogebot/ui-overlay": "^30.0.0",
"@sogebot/ui-overlay": "^31.0.0",
"@sogebot/ui-public": "^3.0.2",
"@twurple/api": "^5.2.2",
"@twurple/auth": "^5.2.2",
Expand All @@ -39,7 +39,7 @@
"emoji-regex": "10.1.0",
"express": "^4.18.1",
"express-graphql": "^0.12.0",
"express-rate-limit": "6.5.1",
"express-rate-limit": "6.5.2",
"figlet": "1.5.2",
"file-type": "^17.1.6",
"get-changelog-lib": "^3.0.0",
Expand All @@ -51,15 +51,15 @@
"jsonwebtoken": "8.5.1",
"localtunnel": "^2.0.2",
"lodash": "4.17.21",
"mathjs": "11.0.1",
"mathjs": "11.1.0",
"mkdir": "0.0.2",
"multer": "^1.4.4",
"mysql2": "2.3.3",
"node-fetch": "^2.6.6",
"npm-check-updates": "^16.0.5",
"obs-websocket-js": "5.0.1",
"patch-package": "6.4.7",
"pg": "8.7.3",
"pg": "8.8.0",
"proxy-deep": "3.1.1",
"reflect-metadata": "0.1.13",
"request": "2.88.2",
Expand All @@ -72,7 +72,7 @@
"source-map-support": "0.5.21",
"spotify-web-api-node": "5.0.2",
"strip-ansi": "6.0.0",
"terser": "^5.14.2",
"terser": "^5.15.0",
"tiny-typed-emitter": "2.1.0",
"tlds": "1.231.0",
"trigram-similarity": "^1.0.7",
Expand Down Expand Up @@ -111,36 +111,36 @@
"@types/cors": "2.8.12",
"@types/eslint": "8.4.6",
"@types/express-rate-limit": "5.1.3",
"@types/figlet": "1.5.4",
"@types/figlet": "1.5.5",
"@types/glob": "7.2.0",
"@types/gsap": "1.20.2",
"@types/jquery": "3.5.14",
"@types/jsonwebtoken": "8.5.8",
"@types/jsonwebtoken": "8.5.9",
"@types/localtunnel": "^2.0.1",
"@types/lodash": "4.14.184",
"@types/mathjs": "9.4.1",
"@types/minimist": "1.2.2",
"@types/mocha": "9.1.1",
"@types/module-alias": "2.0.1",
"@types/multer": "^1.4.7",
"@types/node": "18.7.11",
"@types/node": "18.7.13",
"@types/page": "1.11.5",
"@types/pg": "8.6.5",
"@types/prismjs": "1.26.0",
"@types/qs": "6.9.7",
"@types/request": "2.48.8",
"@types/shortid": "0.0.29",
"@types/sinon": "10.0.13",
"@types/source-map-support": "0.5.4",
"@types/source-map-support": "0.5.6",
"@types/spotify-web-api-node": "5.0.7",
"@types/swagger-ui-express": "^4.1.3",
"@types/url-join": "4.0.1",
"@types/uuid": "8.3.4",
"@types/ws": "8.5.3",
"@types/xregexp": "4.3.0",
"@types/yargs": "17.0.11",
"@typescript-eslint/eslint-plugin": "5.34.0",
"@typescript-eslint/parser": "5.34.0",
"@typescript-eslint/eslint-plugin": "5.35.1",
"@typescript-eslint/parser": "5.35.1",
"axios-mock-adapter": "1.21.2",
"bestzip": "2.2.1",
"deepmerge": "4.2.2",
Expand Down
26 changes: 26 additions & 0 deletions src/database/entity/alert.ts
Expand Up @@ -9,6 +9,7 @@ export interface EmitData {
amount: number;
tier: null | 'Prime' | '1' | '2' | '3';
recipient?: string;
game?: string;
service?: string;
rewardId?: string;
currency: string;
Expand Down Expand Up @@ -163,6 +164,7 @@ export interface AlertInterface {
}[];
};
customProfanityList: string;
promo: AlertResubInterface[];
follows: CommonSettingsInterface[];
subs: CommonSettingsInterface[];
subgifts: CommonSettingsInterface[];
Expand Down Expand Up @@ -284,6 +286,12 @@ export const Alert = new EntitySchema<Readonly<Required<AlertInterface>>>({
parry: { type: 'simple-json' },
},
relations: {
promo: {
type: 'one-to-many',
target: 'alert_promo',
inverseSide: 'alert',
cascade: true,
},
follows: {
type: 'one-to-many',
target: 'alert_follow',
Expand Down Expand Up @@ -353,6 +361,24 @@ export const Alert = new EntitySchema<Readonly<Required<AlertInterface>>>({
},
});

export const AlertPromo = new EntitySchema<Readonly<Required<AlertResubInterface>>>({
name: 'alert_promo',
columns: {
...CommonSettingsSchema,
message: { type: 'simple-json' },
},
relations: {
alert: {
type: 'many-to-one',
target: 'alert',
inverseSide: 'promo',
joinColumn: { name: 'alertId' },
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
},
},
});

export const AlertFollow = new EntitySchema<Readonly<Required<CommonSettingsInterface>>>({
name: 'alert_follow',
columns: { ...CommonSettingsSchema },
Expand Down
@@ -0,0 +1,16 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class addAlertPromoTable1661348421630 implements MigrationInterface {
name = 'addAlertPromoTable1661348421630';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE \`alert_promo\` (\`id\` varchar(36) NOT NULL, \`alertId\` varchar(255) NULL, \`enabled\` tinyint NOT NULL, \`title\` varchar(255) NOT NULL, \`variantAmount\` int NOT NULL, \`messageTemplate\` varchar(255) NOT NULL, \`ttsTemplate\` varchar(255) NOT NULL DEFAULT '', \`layout\` varchar(255) NOT NULL, \`animationIn\` varchar(255) NOT NULL, \`animationInDuration\` int NOT NULL DEFAULT '2000', \`animationOut\` varchar(255) NOT NULL, \`animationOutDuration\` int NOT NULL DEFAULT '2000', \`animationText\` varchar(255) NOT NULL, \`animationTextOptions\` text NOT NULL, \`imageId\` varchar(255) NULL, \`imageOptions\` text NOT NULL, \`filter\` text NULL, \`soundId\` varchar(255) NULL, \`soundVolume\` int NOT NULL, \`alertDurationInMs\` int NOT NULL, \`alertTextDelayInMs\` int NOT NULL, \`enableAdvancedMode\` tinyint NOT NULL, \`advancedMode\` text NOT NULL, \`tts\` text NOT NULL, \`font\` text NULL, \`message\` text NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
await queryRunner.query(`ALTER TABLE \`alert_promo\` ADD CONSTRAINT \`FK_4e34eee32f20813d614feb05847\` FOREIGN KEY (\`alertId\`) REFERENCES \`alert\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE \`alert_promo\` DROP FOREIGN KEY \`FK_4e34eee32f20813d614feb05847\``);
await queryRunner.query(`DROP TABLE \`alert_promo\``);
}

}
@@ -0,0 +1,16 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class addAlertPromoTable1661348421630 implements MigrationInterface {
name = 'addAlertPromoTable1661348421630';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "alert_promo" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "alertId" uuid, "enabled" boolean NOT NULL, "title" character varying NOT NULL, "variantAmount" integer NOT NULL, "messageTemplate" character varying NOT NULL, "ttsTemplate" character varying NOT NULL DEFAULT '', "layout" character varying NOT NULL, "animationIn" character varying NOT NULL, "animationInDuration" integer NOT NULL DEFAULT '2000', "animationOut" character varying NOT NULL, "animationOutDuration" integer NOT NULL DEFAULT '2000', "animationText" character varying NOT NULL, "animationTextOptions" text NOT NULL, "imageId" character varying, "imageOptions" text NOT NULL, "filter" text, "soundId" character varying, "soundVolume" integer NOT NULL, "alertDurationInMs" integer NOT NULL, "alertTextDelayInMs" integer NOT NULL, "enableAdvancedMode" boolean NOT NULL, "advancedMode" text NOT NULL, "tts" text NOT NULL, "font" text, "message" text NOT NULL, CONSTRAINT "PK_32662dd686a472162eb4eee7914" PRIMARY KEY ("id"))`);
await queryRunner.query(`ALTER TABLE "alert_promo" ADD CONSTRAINT "FK_4e34eee32f20813d614feb05847" FOREIGN KEY ("alertId") REFERENCES "alert"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "alert_promo" DROP CONSTRAINT "FK_4e34eee32f20813d614feb05847"`);
await queryRunner.query(`DROP TABLE "alert_promo"`);
}

}
@@ -0,0 +1,22 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class addAlertPromoTable1661348421630 implements MigrationInterface {
name = 'addAlertPromoTable1661348421630';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "alert_promo" ("id" varchar PRIMARY KEY NOT NULL, "alertId" varchar, "enabled" boolean NOT NULL, "title" varchar NOT NULL, "variantAmount" integer NOT NULL, "messageTemplate" varchar NOT NULL, "ttsTemplate" varchar NOT NULL DEFAULT (''), "layout" varchar NOT NULL, "animationIn" varchar NOT NULL, "animationInDuration" integer NOT NULL DEFAULT (2000), "animationOut" varchar NOT NULL, "animationOutDuration" integer NOT NULL DEFAULT (2000), "animationText" varchar NOT NULL, "animationTextOptions" text NOT NULL, "imageId" varchar, "imageOptions" text NOT NULL, "filter" text, "soundId" varchar, "soundVolume" integer NOT NULL, "alertDurationInMs" integer NOT NULL, "alertTextDelayInMs" integer NOT NULL, "enableAdvancedMode" boolean NOT NULL, "advancedMode" text NOT NULL, "tts" text NOT NULL, "font" text, "message" text NOT NULL)`);
await queryRunner.query(`CREATE TABLE "temporary_alert_promo" ("id" varchar PRIMARY KEY NOT NULL, "alertId" varchar, "enabled" boolean NOT NULL, "title" varchar NOT NULL, "variantAmount" integer NOT NULL, "messageTemplate" varchar NOT NULL, "ttsTemplate" varchar NOT NULL DEFAULT (''), "layout" varchar NOT NULL, "animationIn" varchar NOT NULL, "animationInDuration" integer NOT NULL DEFAULT (2000), "animationOut" varchar NOT NULL, "animationOutDuration" integer NOT NULL DEFAULT (2000), "animationText" varchar NOT NULL, "animationTextOptions" text NOT NULL, "imageId" varchar, "imageOptions" text NOT NULL, "filter" text, "soundId" varchar, "soundVolume" integer NOT NULL, "alertDurationInMs" integer NOT NULL, "alertTextDelayInMs" integer NOT NULL, "enableAdvancedMode" boolean NOT NULL, "advancedMode" text NOT NULL, "tts" text NOT NULL, "font" text, "message" text NOT NULL, CONSTRAINT "FK_4e34eee32f20813d614feb05847" FOREIGN KEY ("alertId") REFERENCES "alert" ("id") ON DELETE CASCADE ON UPDATE CASCADE)`);
await queryRunner.query(`INSERT INTO "temporary_alert_promo"("id", "alertId", "enabled", "title", "variantAmount", "messageTemplate", "ttsTemplate", "layout", "animationIn", "animationInDuration", "animationOut", "animationOutDuration", "animationText", "animationTextOptions", "imageId", "imageOptions", "filter", "soundId", "soundVolume", "alertDurationInMs", "alertTextDelayInMs", "enableAdvancedMode", "advancedMode", "tts", "font", "message") SELECT "id", "alertId", "enabled", "title", "variantAmount", "messageTemplate", "ttsTemplate", "layout", "animationIn", "animationInDuration", "animationOut", "animationOutDuration", "animationText", "animationTextOptions", "imageId", "imageOptions", "filter", "soundId", "soundVolume", "alertDurationInMs", "alertTextDelayInMs", "enableAdvancedMode", "advancedMode", "tts", "font", "message" FROM "alert_promo"`);
await queryRunner.query(`DROP TABLE "alert_promo"`);
await queryRunner.query(`ALTER TABLE "temporary_alert_promo" RENAME TO "alert_promo"`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "alert_promo" RENAME TO "temporary_alert_promo"`);
await queryRunner.query(`CREATE TABLE "alert_promo" ("id" varchar PRIMARY KEY NOT NULL, "alertId" varchar, "enabled" boolean NOT NULL, "title" varchar NOT NULL, "variantAmount" integer NOT NULL, "messageTemplate" varchar NOT NULL, "ttsTemplate" varchar NOT NULL DEFAULT (''), "layout" varchar NOT NULL, "animationIn" varchar NOT NULL, "animationInDuration" integer NOT NULL DEFAULT (2000), "animationOut" varchar NOT NULL, "animationOutDuration" integer NOT NULL DEFAULT (2000), "animationText" varchar NOT NULL, "animationTextOptions" text NOT NULL, "imageId" varchar, "imageOptions" text NOT NULL, "filter" text, "soundId" varchar, "soundVolume" integer NOT NULL, "alertDurationInMs" integer NOT NULL, "alertTextDelayInMs" integer NOT NULL, "enableAdvancedMode" boolean NOT NULL, "advancedMode" text NOT NULL, "tts" text NOT NULL, "font" text, "message" text NOT NULL)`);
await queryRunner.query(`INSERT INTO "alert_promo"("id", "alertId", "enabled", "title", "variantAmount", "messageTemplate", "ttsTemplate", "layout", "animationIn", "animationInDuration", "animationOut", "animationOutDuration", "animationText", "animationTextOptions", "imageId", "imageOptions", "filter", "soundId", "soundVolume", "alertDurationInMs", "alertTextDelayInMs", "enableAdvancedMode", "advancedMode", "tts", "font", "message") SELECT "id", "alertId", "enabled", "title", "variantAmount", "messageTemplate", "ttsTemplate", "layout", "animationIn", "animationInDuration", "animationOut", "animationOutDuration", "animationText", "animationTextOptions", "imageId", "imageOptions", "filter", "soundId", "soundVolume", "alertDurationInMs", "alertTextDelayInMs", "enableAdvancedMode", "advancedMode", "tts", "font", "message" FROM "temporary_alert_promo"`);
await queryRunner.query(`DROP TABLE "temporary_alert_promo"`);
await queryRunner.query(`DROP TABLE "alert_promo"`);
}

}
4 changes: 2 additions & 2 deletions src/filters/stream.ts
Expand Up @@ -36,7 +36,7 @@ const stream: ResponseFilter = {
throw new Error();
}

const getChannelInfo = await clientBot.channels.getChannelInfo(getUserByName.id);
const getChannelInfo = await clientBot.channels.getChannelInfoById(getUserByName.id);
if (!getChannelInfo) {
throw new Error();
}
Expand All @@ -62,7 +62,7 @@ const stream: ResponseFilter = {
throw new Error();
}

const getChannelInfo = await clientBot.channels.getChannelInfo(getUserByName.id);
const getChannelInfo = await clientBot.channels.getChannelInfoById(getUserByName.id);
if (!getChannelInfo) {
throw new Error();
}
Expand Down
2 changes: 1 addition & 1 deletion src/general.ts
Expand Up @@ -101,7 +101,7 @@ class General extends Core {
try {
const commands: Command[] = [];

for (const type of ['overlays', 'integrations', 'core', 'systems', 'games', 'services']) {
for (const type of ['overlays', 'integrations', 'core', 'systems', 'games', 'services', 'registries']) {
for (const system of list(type)) {
for (const cmd of system._commands) {
const name = typeof cmd === 'string' ? cmd : cmd.name;
Expand Down
7 changes: 6 additions & 1 deletion src/graphql/resolvers/alertResolver.ts
Expand Up @@ -11,7 +11,7 @@ import { v4 } from 'uuid';

import { AlertObject } from '../schema/alert/AlertObject';

const relations = ['rewardredeems', 'cmdredeems', 'cheers', 'follows', 'hosts', 'raids', 'resubs', 'subcommunitygifts', 'subgifts', 'subs', 'tips'];
const relations = ['promo', 'rewardredeems', 'cmdredeems', 'cheers', 'follows', 'hosts', 'raids', 'resubs', 'subcommunitygifts', 'subgifts', 'subs', 'tips'];

@Resolver()
export class alertResolver {
Expand Down Expand Up @@ -118,6 +118,11 @@ export class alertResolver {
...o, id: v4(), imageId: o.imageId, soundId: o.soundId,
};
}),
promo: item.promo.map((o) => {
return {
...o, id: v4(), imageId: o.imageId, soundId: o.soundId,
};
}),
};
return getRepository(Alert).save(clonedItem);
}
Expand Down
2 changes: 2 additions & 0 deletions src/graphql/schema/alert/AlertObject.ts
Expand Up @@ -35,6 +35,8 @@ export class AlertObject implements AlertInterface {
font: CustomizationFontObject<'left' | 'center' | 'right', string, string>;
@Field()
customProfanityList: string;
@Field(type => [AlertResubObject])
promo: AlertResubObject[];
@Field(type => [CommonSettingsObject])
follows: CommonSettingsObject[];
@Field(type => [CommonSettingsObject])
Expand Down
6 changes: 3 additions & 3 deletions src/helpers/commons/prepare.ts
Expand Up @@ -5,12 +5,12 @@ import { showWithAt } from '../tmi/showWithAt';
* Prepares strings with replacement attributes
* @param translate Translation key
* @param attr Attributes to replace { 'replaceKey': 'value' }
* @param isTranslation consider if translation key to be translate key or pure message
* @param isTranslationKey consider if translation key to be translate key or pure message
*/
export function prepare(toTranslate: string, attr?: {[x: string]: any }, isTranslation = true): string {
export function prepare(toTranslate: string, attr?: {[x: string]: any }, isTranslationKey = true): string {
attr = attr || {};
let msg = (() => {
if (isTranslation) {
if (isTranslationKey) {
return translate(toTranslate);
} else {
return toTranslate;
Expand Down