-
Mahmoud Aglan authored
Campaigns saved as 'scheduled' were never looked at again: nothing in either app processed them. CampaignService::processDue() sends every due campaign into the game's bell (notifications with title_ar/body_ar, as the game's notifications.php reads them) and records recipients, claiming each one with a conditional scheduled -> sending update so overlapping runs never send twice. It runs from GET/POST /api/cron/notifications (X-Service-Key, or X-Cron-Secret / ?secret= when CRON_SECRET is set, the same credentials as the game's api/cron.php) for a scheduler, and as a fallback at most once a minute after any staff page load. Scheduling now stores the typed Cairo time as UTC (the raw datetime-local value was saved as UTC, 2-3 hours late) and refuses past times; filters are stored as jsonb, not a JSON string; cancelling only cancels a campaign that has not started; send-now shares the same delivery code. Co-Authored-By:Claude Opus 5.5 <noreply@anthropic.com>
52d5591d