diff --git a/src/database/stats.service.ts b/src/database/stats.service.ts index fa6dde7..09e3d98 100644 --- a/src/database/stats.service.ts +++ b/src/database/stats.service.ts @@ -70,6 +70,51 @@ export class StatsService { return rows.length ? +rows[0].count : 0 } + public async getNewUsers (daysPeriod = 0): Promise { + const currentTime = moment() + const dateStart = moment() + .tz('America/Los_Angeles') + .set({ hour: 0, minute: 0, second: 0 }) + .subtract(daysPeriod, 'days') + .unix() + + const dateEnd = currentTime.unix() + + const query = logRepository + .createQueryBuilder('logs') + .select('distinct("FirstInsertTime")') + .from(subQuery => + subQuery + .select('"tgUserId", MIN("createdAt") AS "FirstInsertTime"') + .from(BotLog, 'logs') + .groupBy('"tgUserId"'), 'first_inserts') + if (daysPeriod > 0) { + query.where(`"FirstInsertTime" BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`) + } + const result = await query.execute() + // console.log(dateStart, dateEnd, result.length) + return result.length + } + + // Doesn't check last 7 days. + public async getOnetimeUsers (): Promise { + const bufferDays = 7 + const bufferDate = moment() + .tz('America/Los_Angeles') + .set({ hour: 0, minute: 0, second: 0 }) + .subtract(bufferDays, 'days') + .unix() + + const query = await logRepository + .createQueryBuilder('logs') + .select('count("tgUserId") AS row_count, "tgUserId", MAX("createdAt") AS max_created') + .where(`"createdAt" < TO_TIMESTAMP(${bufferDate})`) + .groupBy('"tgUserId"') + .getRawMany() + const result = query.filter(row => row.row_count === '1') + return result.length + } + public async getTotalMessages (daysPeriod = 0, onlySupportedCommands = false): Promise { const currentTime = moment() const dateStart = moment() @@ -83,8 +128,9 @@ export class StatsService { const query = logRepository .createQueryBuilder('logs') .select('count(*)') - .where(`logs.createdAt BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`) - + if (daysPeriod > 0) { + query.where(`logs.createdAt BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`) + } if (onlySupportedCommands) { query.andWhere('logs.isSupportedCommand=true') } @@ -113,6 +159,23 @@ export class StatsService { return rows } + public async getRevenueFromLog (daysPeriod = 7): Promise { + const currentTime = moment() + const dateStart = moment() + .tz('America/Los_Angeles') + .set({ hour: 0, minute: 0, second: 0 }) + .subtract(daysPeriod, 'days') + .unix() + + const dateEnd = currentTime.unix() + const result = await logRepository.createQueryBuilder('logs') + .select('SUM(CAST(logs.amountCredits AS NUMERIC)) AS revenue') + .where('logs.isSupportedCommand=true') + .andWhere(`logs.createdAt BETWEEN TO_TIMESTAMP(${dateStart}) and TO_TIMESTAMP(${dateEnd})`) + .execute() + return result[0].revenue + } + public async addCommandStat ({ tgUserId, rawMessage, command }: { tgUserId: number, rawMessage: string, command: string }): Promise { const stat = new StatBotCommand() diff --git a/src/modules/schedule/index.ts b/src/modules/schedule/index.ts index 0b50bdd..1ed95d7 100644 --- a/src/modules/schedule/index.ts +++ b/src/modules/schedule/index.ts @@ -92,8 +92,12 @@ export class BotSchedule { swapTradingVolume, balance, + uniqueUsersCount, + totalMessage, + weeklyUsers, - dailyMessages + newUsers, + weeklyRevenue ] = await Promise.all([ getDailyMetrics(MetricsDailyType.totalFee, 7), getDailyMetrics(MetricsDailyType.walletsCount, 7), @@ -104,8 +108,12 @@ export class BotSchedule { getTradingVolume(7), getAddressBalance(this.holderAddress), + statsService.getUniqueUsersCount(), + statsService.getTotalMessages(0, true), + statsService.getActiveUsers(7), - statsService.getTotalMessages(1, true) + statsService.getNewUsers(7), + getBotFee(this.holderAddress, 7) // statsService.getRevenue(100) ]) const networkFeesSum = networkFeesWeekly.reduce((sum, item) => sum + +item.value, 0) @@ -123,13 +131,19 @@ export class BotSchedule { 'Total assets, monthly stakes, weekly swaps: ' + `*$${abbreviateNumber(bridgeTVL)}*, ${abbreviateNumber(totalStakeONE)}, $${abbreviateNumber(swapTradingVolumeSum)}` + const oneBotWeeklyMetrics = + 'Bot weekly earns, active users, new users: ' + + `*${abbreviateNumber(+weeklyRevenue)}* ONE` + + `, ${lessThan100(abbreviateNumber(weeklyUsers))}` + + `, ${lessThan100(abbreviateNumber(newUsers))}` + const oneBotMetrics = - 'Bot total earns, weekly users, daily messages: ' + + 'Bot total earns, users, messages: ' + `*${abbreviateNumber(balance / Math.pow(10, 18))}* ONE` + - `, ${lessThan100(abbreviateNumber(weeklyUsers))}` + - `, ${lessThan100(abbreviateNumber(dailyMessages))}` + `, ${lessThan100(abbreviateNumber(uniqueUsersCount))}` + + `, ${lessThan100(abbreviateNumber(totalMessage))}` - return `${networkUsage}\n${assetsUpdate}\n${oneBotMetrics}` + return `${networkUsage}\n${assetsUpdate}\n${oneBotWeeklyMetrics}\n${oneBotMetrics}` } public async generateReportEngagementByCommand (days: number): Promise { @@ -163,7 +177,10 @@ export class BotSchedule { weeklyUsers, totalMessages, totalSupportedMessages, - engagementByCommand + engagementByCommand, + onetimeUsers, + newUsers, + totalUsers ] = await Promise.all([ this.getBotFeeReport(this.holderAddress), getBotFee(this.holderAddress, 7), @@ -173,7 +190,10 @@ export class BotSchedule { statsService.getActiveUsers(7), statsService.getTotalMessages(7), statsService.getTotalMessages(7, true), - this.generateReportEngagementByCommand(7) + this.generateReportEngagementByCommand(7), + statsService.getOnetimeUsers(), + statsService.getNewUsers(7), + statsService.getUniqueUsersCount() ]) const report = `\nBot fees: *${botFeesReport}*` + @@ -182,8 +202,11 @@ export class BotSchedule { `\nTotal fees users pay in ONE: *${abbreviateNumber(totalOne)}*` + `\nTotal fees users pay in free credits: *${abbreviateNumber(totalCredits)}*` + `\nWeekly active users: *${abbreviateNumber(weeklyUsers)}*` + + `\nWeekly new users: *${abbreviateNumber(newUsers)}*` + `\nWeekly user engagement (any commands): *${abbreviateNumber(totalMessages)}*` + `\nWeekly user engagement (commands supported by bot): *${abbreviateNumber(totalSupportedMessages)}*` + + `\nTotal users: *${totalUsers}*` + + `\nOne-time users: *${onetimeUsers}*` + `\n\n${engagementByCommand}` return report }