@merkl/api 0.10.313 → 0.10.315
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/backgroundJobs/index.js +4 -0
 - package/dist/src/modules/v4/dungeonKeeper/dungeonKeeper.controller.d.ts +34 -0
 - package/dist/src/modules/v4/dungeonKeeper/dungeonKeeper.controller.js +8 -0
 - package/dist/src/modules/v4/dungeonKeeper/dungeonKeeper.model.d.ts +0 -0
 - package/dist/src/modules/v4/dungeonKeeper/dungeonKeeper.model.js +1 -0
 - package/dist/src/modules/v4/dungeonKeeper/dungeonKeeper.repository.d.ts +5 -0
 - package/dist/src/modules/v4/dungeonKeeper/dungeonKeeper.repository.js +72 -0
 - package/dist/src/modules/v4/dungeonKeeper/dungeonKeeper.service.d.ts +3 -0
 - package/dist/src/modules/v4/dungeonKeeper/dungeonKeeper.service.js +15 -0
 - package/dist/src/modules/v4/dungeonKeeper/index.d.ts +2 -0
 - package/dist/src/modules/v4/dungeonKeeper/index.js +2 -0
 - package/dist/src/modules/v4/status/status.model.js +5 -3
 - package/dist/tsconfig.package.tsbuildinfo +1 -1
 - package/package.json +1 -1
 
| 
         @@ -1,4 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            import { redisClient } from "../cache/redis";
         
     | 
| 
      
 2 
     | 
    
         
            +
            import { DungeonKeeperController } from "../modules/v4/dungeonKeeper";
         
     | 
| 
       2 
3 
     | 
    
         
             
            import { log } from "../utils/logger";
         
     | 
| 
       3 
4 
     | 
    
         
             
            import { engineDbClient } from "../utils/prisma";
         
     | 
| 
       4 
5 
     | 
    
         
             
            import { swagger } from "@elysiajs/swagger";
         
     | 
| 
         @@ -20,6 +21,9 @@ new Elysia() 
     | 
|
| 
       20 
21 
     | 
    
         
             
                .use(priceUpdater) // /v3/updatePrices
         
     | 
| 
       21 
22 
     | 
    
         
             
                .use(healthCheck) // /v3/health
         
     | 
| 
       22 
23 
     | 
    
         
             
                .use(sync) // GET /jobs/api/sync-with-engine
         
     | 
| 
      
 24 
     | 
    
         
            +
                .group("/v4", app => {
         
     | 
| 
      
 25 
     | 
    
         
            +
                return app.use(DungeonKeeperController);
         
     | 
| 
      
 26 
     | 
    
         
            +
            })
         
     | 
| 
       23 
27 
     | 
    
         
             
                .onError(ctx => {
         
     | 
| 
       24 
28 
     | 
    
         
             
                console.error(ctx.error.message);
         
     | 
| 
       25 
29 
     | 
    
         
             
                console.error(ctx.error.stack);
         
     | 
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import Elysia from "elysia";
         
     | 
| 
      
 2 
     | 
    
         
            +
            export declare const DungeonKeeperController: Elysia<"/dungeonkeeper", false, {
         
     | 
| 
      
 3 
     | 
    
         
            +
                decorator: {};
         
     | 
| 
      
 4 
     | 
    
         
            +
                store: {};
         
     | 
| 
      
 5 
     | 
    
         
            +
                derive: {};
         
     | 
| 
      
 6 
     | 
    
         
            +
                resolve: {};
         
     | 
| 
      
 7 
     | 
    
         
            +
            }, {
         
     | 
| 
      
 8 
     | 
    
         
            +
                type: {};
         
     | 
| 
      
 9 
     | 
    
         
            +
                error: {};
         
     | 
| 
      
 10 
     | 
    
         
            +
            }, {
         
     | 
| 
      
 11 
     | 
    
         
            +
                schema: {};
         
     | 
| 
      
 12 
     | 
    
         
            +
                macro: {};
         
     | 
| 
      
 13 
     | 
    
         
            +
                macroFn: {};
         
     | 
| 
      
 14 
     | 
    
         
            +
            }, {
         
     | 
| 
      
 15 
     | 
    
         
            +
                dungeonkeeper: {
         
     | 
| 
      
 16 
     | 
    
         
            +
                    get: {
         
     | 
| 
      
 17 
     | 
    
         
            +
                        body: unknown;
         
     | 
| 
      
 18 
     | 
    
         
            +
                        params: {};
         
     | 
| 
      
 19 
     | 
    
         
            +
                        query: unknown;
         
     | 
| 
      
 20 
     | 
    
         
            +
                        headers: unknown;
         
     | 
| 
      
 21 
     | 
    
         
            +
                        response: {
         
     | 
| 
      
 22 
     | 
    
         
            +
                            200: void;
         
     | 
| 
      
 23 
     | 
    
         
            +
                        };
         
     | 
| 
      
 24 
     | 
    
         
            +
                    };
         
     | 
| 
      
 25 
     | 
    
         
            +
                };
         
     | 
| 
      
 26 
     | 
    
         
            +
            }, {
         
     | 
| 
      
 27 
     | 
    
         
            +
                derive: {};
         
     | 
| 
      
 28 
     | 
    
         
            +
                resolve: {};
         
     | 
| 
      
 29 
     | 
    
         
            +
                schema: {};
         
     | 
| 
      
 30 
     | 
    
         
            +
            }, {
         
     | 
| 
      
 31 
     | 
    
         
            +
                derive: {};
         
     | 
| 
      
 32 
     | 
    
         
            +
                resolve: {};
         
     | 
| 
      
 33 
     | 
    
         
            +
                schema: {};
         
     | 
| 
      
 34 
     | 
    
         
            +
            }>;
         
     | 
| 
         @@ -0,0 +1,8 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import Elysia from "elysia";
         
     | 
| 
      
 2 
     | 
    
         
            +
            import { DungeonKeeperService } from ".";
         
     | 
| 
      
 3 
     | 
    
         
            +
            // ─── DungeonKeeper Controller ──────────────────────────────────────────────────
         
     | 
| 
      
 4 
     | 
    
         
            +
            export const DungeonKeeperController = new Elysia({ prefix: "/dungeonkeeper", detail: { hide: true } })
         
     | 
| 
      
 5 
     | 
    
         
            +
                // ─── Assign the daily DungeonKeeper ──────────────────────────────────────────
         
     | 
| 
      
 6 
     | 
    
         
            +
                .get("", async () => await DungeonKeeperService.create(), {
         
     | 
| 
      
 7 
     | 
    
         
            +
                detail: { hide: true },
         
     | 
| 
      
 8 
     | 
    
         
            +
            });
         
     | 
| 
         
            File without changes
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            "use strict";
         
     | 
| 
         @@ -0,0 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import type { PartialDatabaseObjectResponse } from "@notionhq/client/build/src/api-endpoints";
         
     | 
| 
      
 2 
     | 
    
         
            +
            export declare abstract class DungeonKeeperRepository {
         
     | 
| 
      
 3 
     | 
    
         
            +
                static fetchEntriesForDateWithTag(databaseId: string, date: string, tag: string): Promise<PartialDatabaseObjectResponse[]>;
         
     | 
| 
      
 4 
     | 
    
         
            +
                static assignRole(notionId: string): Promise<void>;
         
     | 
| 
      
 5 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -0,0 +1,72 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import { Client } from "@notionhq/client";
         
     | 
| 
      
 2 
     | 
    
         
            +
            import { Client as DiscordClient, GatewayIntentBits } from "discord.js";
         
     | 
| 
      
 3 
     | 
    
         
            +
            const notion = new Client({ auth: process.env.NOTION_TOKEN });
         
     | 
| 
      
 4 
     | 
    
         
            +
            const discord = new DiscordClient({ intents: [GatewayIntentBits.GuildMembers] });
         
     | 
| 
      
 5 
     | 
    
         
            +
            const NOTION_EMAIL_TO_DISCORD_ID = {
         
     | 
| 
      
 6 
     | 
    
         
            +
                picodes: "thepicodes",
         
     | 
| 
      
 7 
     | 
    
         
            +
                hugo: "ugolxt",
         
     | 
| 
      
 8 
     | 
    
         
            +
                alex: "wombomango",
         
     | 
| 
      
 9 
     | 
    
         
            +
                nileco: ".nileco",
         
     | 
| 
      
 10 
     | 
    
         
            +
                thibaudb: ".greedythib",
         
     | 
| 
      
 11 
     | 
    
         
            +
                gnervo: "gs8nrv",
         
     | 
| 
      
 12 
     | 
    
         
            +
                vincent: "vince_merkl",
         
     | 
| 
      
 13 
     | 
    
         
            +
                hicham: "lamicham_93854",
         
     | 
| 
      
 14 
     | 
    
         
            +
                pveyrat: "sogipec",
         
     | 
| 
      
 15 
     | 
    
         
            +
                baptiste: "baptistg",
         
     | 
| 
      
 16 
     | 
    
         
            +
                clement: "clmntngl",
         
     | 
| 
      
 17 
     | 
    
         
            +
            };
         
     | 
| 
      
 18 
     | 
    
         
            +
            export class DungeonKeeperRepository {
         
     | 
| 
      
 19 
     | 
    
         
            +
                static async fetchEntriesForDateWithTag(databaseId, date, tag) {
         
     | 
| 
      
 20 
     | 
    
         
            +
                    const response = await notion.databases.query({
         
     | 
| 
      
 21 
     | 
    
         
            +
                        database_id: databaseId,
         
     | 
| 
      
 22 
     | 
    
         
            +
                        filter: {
         
     | 
| 
      
 23 
     | 
    
         
            +
                            and: [
         
     | 
| 
      
 24 
     | 
    
         
            +
                                {
         
     | 
| 
      
 25 
     | 
    
         
            +
                                    property: "Date",
         
     | 
| 
      
 26 
     | 
    
         
            +
                                    date: {
         
     | 
| 
      
 27 
     | 
    
         
            +
                                        equals: date,
         
     | 
| 
      
 28 
     | 
    
         
            +
                                    },
         
     | 
| 
      
 29 
     | 
    
         
            +
                                },
         
     | 
| 
      
 30 
     | 
    
         
            +
                                {
         
     | 
| 
      
 31 
     | 
    
         
            +
                                    property: "Database",
         
     | 
| 
      
 32 
     | 
    
         
            +
                                    select: {
         
     | 
| 
      
 33 
     | 
    
         
            +
                                        equals: tag,
         
     | 
| 
      
 34 
     | 
    
         
            +
                                    },
         
     | 
| 
      
 35 
     | 
    
         
            +
                                },
         
     | 
| 
      
 36 
     | 
    
         
            +
                            ],
         
     | 
| 
      
 37 
     | 
    
         
            +
                        },
         
     | 
| 
      
 38 
     | 
    
         
            +
                    });
         
     | 
| 
      
 39 
     | 
    
         
            +
                    return response.results;
         
     | 
| 
      
 40 
     | 
    
         
            +
                }
         
     | 
| 
      
 41 
     | 
    
         
            +
                static async assignRole(notionId) {
         
     | 
| 
      
 42 
     | 
    
         
            +
                    const discordId = NOTION_EMAIL_TO_DISCORD_ID[notionId];
         
     | 
| 
      
 43 
     | 
    
         
            +
                    if (!discordId)
         
     | 
| 
      
 44 
     | 
    
         
            +
                        throw "Discord ID not found.";
         
     | 
| 
      
 45 
     | 
    
         
            +
                    await discord.login(process.env.DISCORD_TOKEN);
         
     | 
| 
      
 46 
     | 
    
         
            +
                    const guild = await discord.guilds.cache.get("862708408711643136");
         
     | 
| 
      
 47 
     | 
    
         
            +
                    if (!guild)
         
     | 
| 
      
 48 
     | 
    
         
            +
                        throw "Guild not found.";
         
     | 
| 
      
 49 
     | 
    
         
            +
                    const roles = await guild.roles.fetch();
         
     | 
| 
      
 50 
     | 
    
         
            +
                    const teamRole = roles.find(r => r.name === "Team");
         
     | 
| 
      
 51 
     | 
    
         
            +
                    const dkRole = roles.find(r => r.name === "Dungeon Keeper");
         
     | 
| 
      
 52 
     | 
    
         
            +
                    if (!teamRole || !dkRole)
         
     | 
| 
      
 53 
     | 
    
         
            +
                        throw "Roles not found.";
         
     | 
| 
      
 54 
     | 
    
         
            +
                    const users = await guild.members.fetch();
         
     | 
| 
      
 55 
     | 
    
         
            +
                    for (const [_id, dkUser] of users.filter(member => member.roles.cache.has(dkRole.id))) {
         
     | 
| 
      
 56 
     | 
    
         
            +
                        console.log(dkUser.user.tag);
         
     | 
| 
      
 57 
     | 
    
         
            +
                        await dkUser.roles.remove(dkRole);
         
     | 
| 
      
 58 
     | 
    
         
            +
                    }
         
     | 
| 
      
 59 
     | 
    
         
            +
                    const user = users
         
     | 
| 
      
 60 
     | 
    
         
            +
                        .filter(member => member.roles.cache.has(teamRole.id))
         
     | 
| 
      
 61 
     | 
    
         
            +
                        .find(member => member.user.tag === discordId);
         
     | 
| 
      
 62 
     | 
    
         
            +
                    if (!user)
         
     | 
| 
      
 63 
     | 
    
         
            +
                        throw "User not found";
         
     | 
| 
      
 64 
     | 
    
         
            +
                    await user.roles.add(dkRole);
         
     | 
| 
      
 65 
     | 
    
         
            +
                    const channel = await discord.channels.fetch("1328383110957633630");
         
     | 
| 
      
 66 
     | 
    
         
            +
                    if (!channel)
         
     | 
| 
      
 67 
     | 
    
         
            +
                        throw "Channel not found";
         
     | 
| 
      
 68 
     | 
    
         
            +
                    if (channel.isSendable()) {
         
     | 
| 
      
 69 
     | 
    
         
            +
                        await channel.send(`Lucky you <@${user.id}>! You're the <@&${dkRole.id}> today!`);
         
     | 
| 
      
 70 
     | 
    
         
            +
                    }
         
     | 
| 
      
 71 
     | 
    
         
            +
                }
         
     | 
| 
      
 72 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import moment from "moment";
         
     | 
| 
      
 2 
     | 
    
         
            +
            import { DungeonKeeperRepository } from "./dungeonKeeper.repository";
         
     | 
| 
      
 3 
     | 
    
         
            +
            export class DungeonKeeperService {
         
     | 
| 
      
 4 
     | 
    
         
            +
                static async create() {
         
     | 
| 
      
 5 
     | 
    
         
            +
                    const entries = await DungeonKeeperRepository.fetchEntriesForDateWithTag("8546f6a84641406bafb2358762281e81", moment().format("YYYY-MM-DD"), "Dungeon Keeper");
         
     | 
| 
      
 6 
     | 
    
         
            +
                    const user = entries?.[0];
         
     | 
| 
      
 7 
     | 
    
         
            +
                    if (!user) {
         
     | 
| 
      
 8 
     | 
    
         
            +
                        throw "No dk found for today";
         
     | 
| 
      
 9 
     | 
    
         
            +
                    }
         
     | 
| 
      
 10 
     | 
    
         
            +
                    const notionId = (user?.properties["Qui ?"]).people[0].person.email
         
     | 
| 
      
 11 
     | 
    
         
            +
                        .replace("@angle.money", "")
         
     | 
| 
      
 12 
     | 
    
         
            +
                        .replace("@merkl.xyz", "");
         
     | 
| 
      
 13 
     | 
    
         
            +
                    await DungeonKeeperRepository.assignRole(notionId);
         
     | 
| 
      
 14 
     | 
    
         
            +
                }
         
     | 
| 
      
 15 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -6,9 +6,11 @@ export const CampaignUniqueDto = t.Object({ 
     | 
|
| 
       6 
6 
     | 
    
         
             
                campaignId: t.String(),
         
     | 
| 
       7 
7 
     | 
    
         
             
            });
         
     | 
| 
       8 
8 
     | 
    
         
             
            export const DelayDto = t.Object({
         
     | 
| 
       9 
     | 
    
         
            -
                endTimestampLowerBound: t.Optional(t.Numeric( 
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
                 
     | 
| 
      
 9 
     | 
    
         
            +
                endTimestampLowerBound: t.Optional(t.Numeric({
         
     | 
| 
      
 10 
     | 
    
         
            +
                    description: "Lower bound of end timestamps - by default it'll take all campaigns where endTimestamp is more than now - 1 week",
         
     | 
| 
      
 11 
     | 
    
         
            +
                })),
         
     | 
| 
      
 12 
     | 
    
         
            +
                delayLowerBound: t.Optional(t.Numeric({ description: "To filter small delays (in seconds)" })),
         
     | 
| 
      
 13 
     | 
    
         
            +
                chainId: t.Optional(t.Numeric({ description: "To get delays for Campaigns on a given chain only" })),
         
     | 
| 
       12 
14 
     | 
    
         
             
            });
         
     | 
| 
       13 
15 
     | 
    
         
             
            export const CampaignStatusResourceDto = t.Object({
         
     | 
| 
       14 
16 
     | 
    
         
             
                campaignId: t.String(),
         
     |