can now see completed tasks
This commit is contained in:
parent
1112cd83bf
commit
0cdfa8eefc
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,6 +1,8 @@
|
|||||||
.env
|
.env
|
||||||
/__pycache__
|
/__pycache__
|
||||||
/calendar
|
/secret
|
||||||
/dvenv
|
/dvenv
|
||||||
copies.txt
|
copies.txt
|
||||||
|
.gitignore
|
||||||
|
user_location.db
|
||||||
|
|
||||||
|
|||||||
80
task_bot.py
80
task_bot.py
@ -2,7 +2,7 @@ import os
|
|||||||
import discord
|
import discord
|
||||||
import datetime
|
import datetime
|
||||||
import pytz
|
import pytz
|
||||||
import google_auth_oauthlib.flow
|
from google_auth_oauthlib.flow import InstalledAppFlow
|
||||||
from weather import OpenWeatherMapAPIClient
|
from weather import OpenWeatherMapAPIClient
|
||||||
from googleapiclient.discovery import build
|
from googleapiclient.discovery import build
|
||||||
from google.oauth2.credentials import Credentials
|
from google.oauth2.credentials import Credentials
|
||||||
@ -15,9 +15,9 @@ load_dotenv()
|
|||||||
DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")
|
DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")
|
||||||
WEATHER_TOKEN = os.getenv("WEATHER_TOKEN")
|
WEATHER_TOKEN = os.getenv("WEATHER_TOKEN")
|
||||||
|
|
||||||
CREDENTIALS_FILE = './calendar/credentials.json'
|
CREDENTIALS_FILE = './secret/credentials.json'
|
||||||
TOKEN_FILE = './calendar/token.json'
|
TOKEN_FILE = './secret/token.json'
|
||||||
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly', 'https://www.googleapis.com/auth/tasks.readonly']
|
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly', 'https://www.googleapis.com/auth/tasks.readonly', 'https://www.googleapis.com/auth/tasks']
|
||||||
|
|
||||||
weather_client = OpenWeatherMapAPIClient(WEATHER_TOKEN, "MyDiscordWeatherBot")
|
weather_client = OpenWeatherMapAPIClient(WEATHER_TOKEN, "MyDiscordWeatherBot")
|
||||||
intents = discord.Intents(messages=True, guilds=True)
|
intents = discord.Intents(messages=True, guilds=True)
|
||||||
@ -32,8 +32,9 @@ def build_calendar_service():
|
|||||||
return build('calendar', 'v3', credentials=creds)
|
return build('calendar', 'v3', credentials=creds)
|
||||||
|
|
||||||
def build_tasks_service():
|
def build_tasks_service():
|
||||||
creds = creds = Credentials.from_authorized_user_file(TOKEN_FILE, SCOPES)
|
creds = Credentials.from_authorized_user_file(TOKEN_FILE, SCOPES)
|
||||||
return build('tasks', 'v1', credentials=creds)
|
service = build('tasks', 'v1', credentials=creds)
|
||||||
|
return service, creds
|
||||||
|
|
||||||
def parse_google_time(s: str) -> datetime.datetime:
|
def parse_google_time(s: str) -> datetime.datetime:
|
||||||
dt = datetime.datetime.fromisoformat(s)
|
dt = datetime.datetime.fromisoformat(s)
|
||||||
@ -47,23 +48,6 @@ def parse_google_time(s: str) -> datetime.datetime:
|
|||||||
return dt.replace(tzinfo=datetime.timezone.utc)
|
return dt.replace(tzinfo=datetime.timezone.utc)
|
||||||
return dt
|
return dt
|
||||||
|
|
||||||
def is_due_today(due_iso: str, tz: pytz.timezone = TZ) -> bool:
|
|
||||||
if not due_iso:
|
|
||||||
return False
|
|
||||||
try:
|
|
||||||
dt = datetime.datetime.fromisoformat(due_iso.replace("Z", "+00:00"))
|
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
return dt.astimezone(tz).date() == datetime.datetime.now(tz).date()
|
|
||||||
|
|
||||||
def due_time_str(due_iso: str, tz: pytz.timezone = TZ) -> str:
|
|
||||||
if not due_iso:
|
|
||||||
return ""
|
|
||||||
try:
|
|
||||||
dt = datetime.datetime.fromisoformat(due_iso.replace("Z", "+00:00")).astimezone(tz)
|
|
||||||
return dt.strftime("%H:%M")
|
|
||||||
except Exception:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
#Calendar authentification
|
#Calendar authentification
|
||||||
async def authenticate():
|
async def authenticate():
|
||||||
@ -72,43 +56,59 @@ async def authenticate():
|
|||||||
return
|
return
|
||||||
|
|
||||||
print("No token found: running interactive OAuth flow(will open browser).")
|
print("No token found: running interactive OAuth flow(will open browser).")
|
||||||
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(CREDENTIALS_FILE, SCOPES)
|
flow = InstalledAppFlow.from_client_secrets_file(CREDENTIALS_FILE, SCOPES)
|
||||||
credentials = flow.run_local_server(port=0)
|
credentials = flow.run_local_server(port=0)
|
||||||
|
|
||||||
with open(TOKEN_FILE, 'w') as f:
|
with open(TOKEN_FILE, 'w') as f:
|
||||||
f.write(credentials.to_json())
|
f.write(credentials.to_json())
|
||||||
print(f"Saved credentials to {TOKEN_FILE} for instant access")
|
print(f"Saved credentials to {TOKEN_FILE} for instant access")
|
||||||
|
|
||||||
|
|
||||||
@bot.tree.command(name="daily_tasks", description="Check today's saved tasks")
|
@bot.tree.command(name="daily_tasks", description="Check today's saved tasks")
|
||||||
async def today(interaction: discord.Interaction):
|
async def today(interaction: discord.Interaction):
|
||||||
await interaction.response.defer(thinking=True)
|
await interaction.response.defer(thinking=True)
|
||||||
try:
|
try:
|
||||||
service = build_tasks_service()
|
service, creds = build_tasks_service()
|
||||||
tl_res = service.tasklists().list(maxResults=100).execute()
|
tl_res = service.tasklists().list(maxResults=100).execute()
|
||||||
lists = tl_res.get("items", [])
|
lists = tl_res.get("items", []) or []
|
||||||
|
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
title="Today's tasks",
|
title="Today's tasks",
|
||||||
color=0x2ecc71,
|
color=0x2ecc71,
|
||||||
timestamp=datetime.datetime.now(tz=TZ)
|
timestamp=datetime.datetime.now(tz=TZ)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
added = 0
|
||||||
for tl in lists:
|
for tl in lists:
|
||||||
tl_id = tl["id"]
|
tl_id = tl.get("id")
|
||||||
tl_title = tl.get("title", "Untitled")
|
tl_title = tl.get("title") or "<untitled>"
|
||||||
tasks_res = service.tasks().list(tasklist=tl_id, showCompleted=True, maxResults=200).execute()
|
|
||||||
items = tasks_res.get("items", [])
|
tasks_res = service.tasks().list(tasklist=tl_id, showCompleted=True, showHidden=True, maxResults=250).execute() or {}
|
||||||
if not items:
|
items = tasks_res.get("items", []) or []
|
||||||
continue
|
|
||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
for t in items:
|
for t in items:
|
||||||
|
if not isinstance(t, dict):
|
||||||
|
continue
|
||||||
|
|
||||||
status = "✅" if t.get("status") == "completed" else "🔲"
|
status = "✅" if t.get("status") == "completed" else "🔲"
|
||||||
title = t.get("title", "(no title)")
|
title = t.get("title") or "(no title)"
|
||||||
lines.append(f"{status} {title}")
|
completed_ts = t.get("completed")
|
||||||
|
|
||||||
|
if completed_ts:
|
||||||
|
completed_short = completed_ts.replace("T", "").split(".")[0]
|
||||||
|
lines.append(f"{status} {title} - completed {completed_short}")
|
||||||
|
else:
|
||||||
|
lines.append(f"{status} {title}")
|
||||||
|
|
||||||
|
if not lines:
|
||||||
|
continue
|
||||||
|
|
||||||
value = "\n".join(lines)[:1024]
|
value = "\n".join(lines)[:1024]
|
||||||
embed.add_field(name=tl_title, value=value, inline=False)
|
embed.add_field(name=tl_title, value=value, inline=False)
|
||||||
|
added += 1
|
||||||
|
|
||||||
if not embed.fields:
|
if added == 0:
|
||||||
embed.description = "No tasks due today."
|
embed.description = "No tasks due today."
|
||||||
|
|
||||||
await interaction.followup.send(embed=embed)
|
await interaction.followup.send(embed=embed)
|
||||||
@ -157,10 +157,7 @@ async def events(interaction: discord.Interaction):
|
|||||||
|
|
||||||
|
|
||||||
if not events:
|
if not events:
|
||||||
embed = discord.Embed(
|
embed.description = "No tasks due today"
|
||||||
title="No events this week!",
|
|
||||||
description="Go outside maybe"
|
|
||||||
)
|
|
||||||
await interaction.followup.send(embed=embed)
|
await interaction.followup.send(embed=embed)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
@ -242,6 +239,7 @@ async def on_ready():
|
|||||||
print("Registered Commands:")
|
print("Registered Commands:")
|
||||||
for command in commands:
|
for command in commands:
|
||||||
print(f"- {command.name}")
|
print(f"- {command.name}")
|
||||||
|
print("- !set_location")
|
||||||
print("your bot is online and ready to serve !")
|
print("your bot is online and ready to serve !")
|
||||||
|
|
||||||
bot.run(DISCORD_TOKEN)
|
bot.run(DISCORD_TOKEN)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user