160 lines
7.3 KiB
Python
160 lines
7.3 KiB
Python
# utils/scheduled.py
|
||
|
||
import random
|
||
import json
|
||
import os
|
||
import time
|
||
from datetime import datetime, timedelta
|
||
from apscheduler.triggers.date import DateTrigger
|
||
from discord import Status, ActivityType
|
||
|
||
import globals
|
||
from utils.llm import query_ollama
|
||
from utils.core import switch_model # If you moved switch_model into a separate utils file
|
||
from globals import scheduler
|
||
|
||
BEDTIME_TRACKING_FILE = "last_bedtime_targets.json"
|
||
|
||
async def send_monday_video():
|
||
await switch_model(globals.OLLAMA_MODEL)
|
||
|
||
# Generate a motivational message
|
||
prompt = "It's Miku Monday! Give me an energetic and heartfelt Miku Monday morning message to inspire someone for the week ahead."
|
||
response = await query_ollama(prompt, user_id="weekly-motivation")
|
||
|
||
video_url = "http://zip.koko210cloud.xyz/u/zEgU7Z.mp4"
|
||
|
||
target_channel_ids = [
|
||
761014220707332107,
|
||
1140377617237807266
|
||
]
|
||
|
||
for channel_id in target_channel_ids:
|
||
channel = globals.client.get_channel(channel_id)
|
||
if channel is None:
|
||
print(f"❌ Could not find channel with ID {channel_id}. Make sure the bot is in the server.")
|
||
return
|
||
|
||
try:
|
||
await channel.send(content=response)
|
||
# Send video link
|
||
await channel.send(f"[Happy Miku Monday!]({video_url})")
|
||
|
||
print(f"✅ Sent Monday video to channel ID {channel_id}")
|
||
except Exception as e:
|
||
print(f"⚠️ Failed to send video to channel ID {channel_id}: {e}")
|
||
|
||
def load_last_bedtime_targets():
|
||
if not os.path.exists(BEDTIME_TRACKING_FILE):
|
||
return {}
|
||
try:
|
||
with open(BEDTIME_TRACKING_FILE, "r") as f:
|
||
return json.load(f)
|
||
except Exception as e:
|
||
print(f"⚠️ Failed to load bedtime tracking file: {e}")
|
||
return {}
|
||
|
||
_last_bedtime_targets = load_last_bedtime_targets()
|
||
|
||
def save_last_bedtime_targets(data):
|
||
try:
|
||
with open(BEDTIME_TRACKING_FILE, "w") as f:
|
||
json.dump(data, f)
|
||
except Exception as e:
|
||
print(f"⚠️ Failed to save bedtime tracking file: {e}")
|
||
|
||
async def send_bedtime_reminder():
|
||
await switch_model(globals.OLLAMA_MODEL)
|
||
|
||
for channel_id in globals.BEDTIME_CHANNEL_IDS:
|
||
channel = globals.client.get_channel(channel_id)
|
||
if not channel:
|
||
print(f"⚠️ Channel ID {channel_id} not found.")
|
||
continue
|
||
|
||
guild = channel.guild
|
||
|
||
# Filter online members (excluding bots)
|
||
online_members = [
|
||
member for member in guild.members
|
||
if member.status in {Status.online, Status.idle, Status.dnd}
|
||
and not member.bot
|
||
]
|
||
|
||
specific_user_id = 214857593045254151 # target user ID
|
||
specific_user = guild.get_member(specific_user_id)
|
||
if specific_user and specific_user not in online_members:
|
||
online_members.append(specific_user)
|
||
|
||
if not online_members:
|
||
print(f"😴 No online members to ping in {guild.name}")
|
||
continue
|
||
|
||
# Avoid repeating the same person unless they're the only one
|
||
last_target_id = _last_bedtime_targets.get(str(guild.id))
|
||
eligible_members = [m for m in online_members if m.id != last_target_id]
|
||
|
||
if not eligible_members:
|
||
eligible_members = online_members # fallback if only one user
|
||
|
||
chosen_one = random.choice(online_members)
|
||
|
||
# 🎯 Status-aware phrasing
|
||
status_map = {
|
||
Status.online: "",
|
||
Status.idle: "Be sure to include the following information on their status too: Their profile status is currently idle. This implies they're not on their computer now, but are still awake.",
|
||
Status.dnd: "Be sure to include the following information on their status too: Their current profile status is 'Do Not Disturb.' This implies they are very absorbed in what they're doing. But it's still important for them to know when to stop for the day and get some sleep, right?",
|
||
Status.offline: "Be sure to include the following information on their status too: Their profile status is currently offline, but is it really? It's very likely they've just set it to invisible to avoid being seen that they're staying up so late!"
|
||
}
|
||
status_note = status_map.get(chosen_one.status, "")
|
||
|
||
# 🎮 Activity-aware phrasing
|
||
activity_note = ""
|
||
if chosen_one.activities:
|
||
for activity in chosen_one.activities:
|
||
if activity.type == ActivityType.playing:
|
||
activity_note = f"You should also include the following information on their current activity on their profile too: They are playing **{activity.name}** right now. It's getting late, though. Maybe it's time to pause, leave the rest of the game for tomorrow and rest..."
|
||
break
|
||
elif activity.type == ActivityType.streaming:
|
||
activity_note = f"You should also include the following information on their current activity on their profile too: They are steaming **{activity.name}** at this hour? They should know it's getting way too late for streams."
|
||
break
|
||
elif activity.type == ActivityType.watching:
|
||
activity_note = f"You should also include the following information on their current activity on their profile too: They are watching **{activity.name}** right now. That's cozy, but it's not good to binge so late."
|
||
break
|
||
elif activity.type == ActivityType.listening:
|
||
activity_note = f"You should also include the following information on their current activity on their profile too: They are listening to **{activity.name}** right now. Sounds like they're better off putting appropriate music to fall asleep to."
|
||
break
|
||
|
||
# Generate bedtime message
|
||
prompt = (
|
||
f"Write a sweet, funny, or encouraging bedtime message to remind someone it's getting late and they should sleep. "
|
||
f"Make it short and wholesome, as if Miku is genuinely worried about their well-being. Imply that it's not good staying up so late."
|
||
f"{status_note}"
|
||
f"{activity_note}"
|
||
f"Miku is currently feeling: {globals.CURRENT_MOOD}\nPlease word in a way that reflects this emotional tone."
|
||
)
|
||
bedtime_message = await query_ollama(prompt, user_id=f"bedtime-miku-{int(time.time())}")
|
||
|
||
try:
|
||
await channel.send(f"{chosen_one.mention}, {bedtime_message}")
|
||
print(f"🌙 Sent bedtime reminder to {chosen_one.display_name} in {guild.name}")
|
||
# Save for next run
|
||
_last_bedtime_targets[str(guild.id)] = chosen_one.id
|
||
save_last_bedtime_targets(_last_bedtime_targets)
|
||
except Exception as e:
|
||
print(f"⚠️ Failed to send bedtime reminder in {guild.name}: {e}")
|
||
|
||
def schedule_random_bedtime():
|
||
now = datetime.now()
|
||
target_time = now.replace(hour=20, minute=30, second=0, microsecond=0)
|
||
# If it's already past 23:30 today, schedule for tomorrow
|
||
if now > target_time:
|
||
target_time += timedelta(days=1)
|
||
|
||
# Add random offset (0–29 mins)
|
||
offset_minutes = random.randint(0, 29)
|
||
run_time = target_time + timedelta(minutes=offset_minutes)
|
||
|
||
scheduler.add_job(send_bedtime_reminder, trigger=DateTrigger(run_date=run_time))
|
||
print(f"⏰ Bedtime reminder scheduled for {run_time.strftime('%Y-%m-%d %H:%M:%S')}")
|