collector->collect(); } catch (ApiErrorException $exception) { $this->error("Stripe API error: {$exception->getMessage()}"); return self::FAILURE; } $yesterdayStart = Carbon::now(self::TIMEZONE)->subDay()->startOfDay(); $todayStart = Carbon::now(self::TIMEZONE)->startOfDay(); $newUsers = User::query() ->whereBetween('created_at', [$yesterdayStart->copy()->utc(), $todayStart->copy()->utc()]) ->count(); $totalUsers = User::query() ->where('created_at', '<', $todayStart->copy()->utc()) ->count(); $embed = $this->buildEmbed($stats, $newUsers, $totalUsers, $yesterdayStart); if ($this->option('no-discord')) { $this->printEmbeds([$embed]); $this->info('Skipped Discord (--no-discord).'); return self::SUCCESS; } $this->discord->send('', [$embed]); $this->info('Daily stats report sent to Discord.'); return self::SUCCESS; } /** * @param array{active: array, trialing: array} $stats * @return array */ private function buildEmbed(array $stats, int $newUsers, int $totalUsers, Carbon $day): array { $fields = [ [ 'name' => '👥 Users', 'value' => "New yesterday: **{$newUsers}**\nTotal: **{$totalUsers}**", 'inline' => false, ], ]; $currencies = array_unique(array_merge(array_keys($stats['active']), array_keys($stats['trialing']))); sort($currencies); foreach ($currencies as $currency) { $active = $stats['active'][$currency] ?? ['count' => 0, 'mrr' => 0.0]; $trialing = $stats['trialing'][$currency] ?? ['count' => 0, 'mrr' => 0.0]; $currentMrr = $active['mrr']; $projectedMrr = $active['mrr'] + $trialing['mrr']; $fields[] = [ 'name' => '💳 '.strtoupper($currency), 'value' => implode("\n", [ "Active: **{$active['count']}** ({$this->money($currentMrr, $currency)} MRR)", "Trialing: **{$trialing['count']}** ({$this->money($trialing['mrr'], $currency)} MRR)", "Current MRR/ARR: **{$this->money($currentMrr, $currency)}** / **{$this->money($currentMrr * 12, $currency)}**", "Projected MRR/ARR: **{$this->money($projectedMrr, $currency)}** / **{$this->money($projectedMrr * 12, $currency)}**", ]), 'inline' => false, ]; } if ($currencies === []) { $fields[] = [ 'name' => '💳 Subscriptions', 'value' => 'No active or trialing subscriptions.', 'inline' => false, ]; } return [ 'title' => '📊 Daily Stats — '.$day->format('D, d M Y'), 'color' => 0x5865F2, 'fields' => $fields, ]; } /** * MRR figures are held in major units (e.g. euros), so convert to cents for * the shared formatter. */ private function money(float $amount, string $currency): string { return Money::format((int) round($amount * 100), $currency); } }