no hypr folder + waybar cclock, nx_gcal_event
This commit is contained in:
@@ -50,42 +50,6 @@ in
|
||||
pkgs-unstable.hyprlock
|
||||
pkgs-unstable.hypridle
|
||||
|
||||
(pkgs.writeShellScriptBin "waybar_mode" ''
|
||||
#!/bin/bash
|
||||
|
||||
# Function to print help message
|
||||
print_help() {
|
||||
echo "Usage: waybar_mode {set <string>|unset}"
|
||||
}
|
||||
if [ $# -lt 1 ]; then
|
||||
print_help; exit 1;
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
set)
|
||||
# Check if there is a second argument for the 'set' operation
|
||||
if [ $# -eq 2 ]; then
|
||||
echo "$2" > /tmp/waybar-mode
|
||||
pkill -RTMIN+8 waybar
|
||||
else
|
||||
echo "Error: 'set' operation requires exactly one string argument."
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
unset)
|
||||
echo "" > /tmp/waybar-mode
|
||||
pkill -RTMIN+8 waybar
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unknown command '$1'"
|
||||
print_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
'')
|
||||
];
|
||||
|
||||
wayland.windowManager.hyprland = {
|
||||
222
home-modules/nx-gcal-event.nix
Normal file
222
home-modules/nx-gcal-event.nix
Normal file
@@ -0,0 +1,222 @@
|
||||
{ config, pkgs, secrets, ... }:
|
||||
let in
|
||||
{
|
||||
home = {
|
||||
file."${config.xdg.dataHome}/nx-gcal-event-credentials.json".text = ''
|
||||
{
|
||||
"installed": {
|
||||
"client_id": "${secrets.nx-gcal-event.client-client-id}",
|
||||
"project_id": "my-own-cal",
|
||||
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
||||
"token_uri": "https://oauth2.googleapis.com/token",
|
||||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
||||
"client_secret": "${secrets.nx-gcal-event.client-secret}",
|
||||
"redirect_uris": [
|
||||
"http://localhost"
|
||||
]
|
||||
}
|
||||
}
|
||||
'';
|
||||
|
||||
packages = with pkgs; [
|
||||
# TODO: make into real package, currently dependencies are in home.nix
|
||||
# (pkgs.python311.withPackages (python-pkgs: [
|
||||
# python-pkgs.google
|
||||
# ]))
|
||||
(writeScriptBin "nx_gcal_event" ''
|
||||
#!${pkgs.python3}/bin/python3
|
||||
import datetime
|
||||
import os
|
||||
import pickle
|
||||
import sys
|
||||
|
||||
from google.auth.transport.requests import Request
|
||||
from google.oauth2.credentials import Credentials
|
||||
from google_auth_oauthlib.flow import InstalledAppFlow
|
||||
from googleapiclient.discovery import build
|
||||
from googleapiclient.errors import HttpError
|
||||
from html import escape
|
||||
|
||||
|
||||
|
||||
CREDENTIALS_PATH = f"{os.environ['XDG_DATA_HOME']}/nx-gcal-event-credentials.json"
|
||||
TOKEN_PATH = f"{os.environ['XDG_CACHE_HOME']}/nx-gcal-event-token.json"
|
||||
PICKLE_PATH = "/tmp/nx-gcal-event.pickle"
|
||||
|
||||
|
||||
def sec_to_nice_string(seconds: int):
|
||||
(hours, rsec) = divmod(seconds, 3600)
|
||||
minutes = rsec // 60
|
||||
sep = " "
|
||||
if hours == 0:
|
||||
s_hours = f""
|
||||
sep = ""
|
||||
elif hours == 1: s_hours = f"{hours} hour"
|
||||
else: s_hours = f"{hours} hours"
|
||||
if minutes == 0:
|
||||
s_minutes = f""
|
||||
sep = ""
|
||||
elif minutes == 1: s_minutes = f"{minutes} minute"
|
||||
else: s_minutes = f"{minutes} minutes"
|
||||
if hours + minutes == 0:
|
||||
s_minutes = "~ No time"
|
||||
os.remove(PICKLE_PATH)
|
||||
|
||||
return f"{s_hours}{sep}{s_minutes}"
|
||||
|
||||
def get_event_from_api():
|
||||
creds = None
|
||||
SCOPES = ["https://www.googleapis.com/auth/calendar.readonly"]
|
||||
|
||||
if os.path.exists(TOKEN_PATH):
|
||||
creds = Credentials.from_authorized_user_file(TOKEN_PATH, SCOPES)
|
||||
|
||||
if not creds or not creds.valid:
|
||||
if creds and creds.expired and creds.refresh_token:
|
||||
creds.refresh(Request())
|
||||
else:
|
||||
flow = InstalledAppFlow.from_client_secrets_file(CREDENTIALS_PATH, SCOPES)
|
||||
creds = flow.run_local_server(port=0)
|
||||
# Save the credentials for the next run
|
||||
with open(TOKEN_PATH, "w") as token:
|
||||
token.write(creds.to_json())
|
||||
|
||||
try:
|
||||
service = build("calendar", "v3", credentials=creds)
|
||||
now = datetime.datetime.utcnow().isoformat() + "Z" # 'Z' indicates UTC time
|
||||
in_24_h = (datetime.datetime.utcnow() + datetime.timedelta(days=1)).isoformat() + "Z"
|
||||
calendar_list = service.calendarList().list().execute()
|
||||
calendars = calendar_list.get("items", [])
|
||||
|
||||
# List events from all calendars
|
||||
all_events = []
|
||||
for calendar in calendars:
|
||||
calendar_id = calendar["id"]
|
||||
events_result = service.events().list(
|
||||
calendarId=calendar_id,
|
||||
timeMin=now,
|
||||
timeMax=in_24_h,
|
||||
singleEvents=True,
|
||||
orderBy="startTime",
|
||||
).execute()
|
||||
events = events_result.get("items", [])
|
||||
|
||||
all_events.extend(events)
|
||||
|
||||
# Filter out all-day events
|
||||
all_events = [event for event in all_events if "dateTime" in event["start"]]
|
||||
|
||||
# Find the earliest event
|
||||
earliest_event = None
|
||||
for event in all_events:
|
||||
event_start = event["start"]["dateTime"]
|
||||
if not earliest_event or event_start < earliest_event["start"]["dateTime"]:
|
||||
earliest_event = event
|
||||
|
||||
# Now earliest_event contains the event that starts earliest
|
||||
return earliest_event
|
||||
|
||||
except HttpError as error:
|
||||
print("An error occurred: %s" % error)
|
||||
exit(1)
|
||||
|
||||
def dump_dict_to_file(event, now):
|
||||
if not event:
|
||||
event = {}
|
||||
event['nxWriteTime'] = now
|
||||
with open(PICKLE_PATH, 'wb') as f:
|
||||
pickle.dump(event, f)
|
||||
|
||||
def load_dict_from_file(now):
|
||||
with open(PICKLE_PATH, 'rb') as f:
|
||||
event = pickle.load(f)
|
||||
# recheck all 15 minutes
|
||||
if (now - event['nxWriteTime']).seconds > 900:
|
||||
event = get_event_from_api()
|
||||
os.remove(PICKLE_PATH)
|
||||
return event
|
||||
|
||||
def lookup():
|
||||
# set now (timezone CEST)
|
||||
now = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=2)))
|
||||
|
||||
no_event_string = "~ Zen ~"
|
||||
|
||||
if os.path.exists(PICKLE_PATH):
|
||||
event = load_dict_from_file(now)
|
||||
else:
|
||||
event = get_event_from_api()
|
||||
if not event:
|
||||
print(no_event_string)
|
||||
dump_dict_to_file(event, now)
|
||||
exit(0)
|
||||
dump_dict_to_file(event, now)
|
||||
|
||||
try: # when the saved even was empty (there was no event)
|
||||
end = datetime.datetime.strptime(event["end"]["dateTime"], "%Y-%m-%dT%H:%M:%S%z")
|
||||
start = datetime.datetime.strptime(event["start"]["dateTime"], "%Y-%m-%dT%H:%M:%S%z")
|
||||
except:
|
||||
if (now - event['nxWriteTime']).seconds > 900:
|
||||
event = get_event_from_api()
|
||||
os.remove(PICKLE_PATH)
|
||||
else:
|
||||
print(no_event_string)
|
||||
exit(0)
|
||||
|
||||
# set mode, remaining
|
||||
if start.day != now.day: # event start tomorrow
|
||||
print(no_event_string)
|
||||
exit(0)
|
||||
elif (start - now).days < 0: # today, started alredy
|
||||
remaining = end - now
|
||||
mode = " remaining in "
|
||||
else: # today, not started yet
|
||||
remaining = start - now
|
||||
mode = " until the start of "
|
||||
|
||||
name = escape(event['summary'])
|
||||
|
||||
print(f" {sec_to_nice_string(remaining.seconds)}{mode}\'{name}\'")
|
||||
exit(0)
|
||||
|
||||
def print_help():
|
||||
print("Usage: nx_gcal_event [lookup|force-lookup|reauthenicate|help]")
|
||||
|
||||
def forece_lookup():
|
||||
try:
|
||||
os.remove(PICKLE_PATH)
|
||||
os.system('notify-send --app-name="nx_gcal_event" "Saved event deleted!"')
|
||||
except:
|
||||
os.system('notify-send --app-name="nx_gcal_event" "No saved event found!"')
|
||||
finally:
|
||||
lookup()
|
||||
|
||||
def reauthenicate():
|
||||
os.remove(PICKLE_PATH)
|
||||
os.remove(TOKEN_PATH)
|
||||
os.system('notify-send --app-name="nx_gcal_event" "Deleted Token"')
|
||||
lookup()
|
||||
|
||||
def print_help():
|
||||
print("Usage: nx_gcal_event [lookup|force-lookup|reauthenicate|help]")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
print("Incorrect number of arguments.")
|
||||
print_help()
|
||||
else:
|
||||
arg = sys.argv[1]
|
||||
if arg == "lookup":
|
||||
lookup()
|
||||
elif arg == "force-lookup":
|
||||
forece_lookup()
|
||||
elif arg == "reauthenticate":
|
||||
reauthenicate()
|
||||
elif arg == "help":
|
||||
print_help()
|
||||
else:
|
||||
print_help()
|
||||
'')
|
||||
];
|
||||
};
|
||||
}
|
||||
18
home-modules/python.nix
Normal file
18
home-modules/python.nix
Normal file
@@ -0,0 +1,18 @@
|
||||
{ config, pkgs, ... }:
|
||||
let
|
||||
python-with-packages = pkgs.python3.withPackages (pp: with pp; [
|
||||
ipython
|
||||
pipdeptree
|
||||
requests
|
||||
google google-api-python-client google-auth-httplib2 google-auth-oauthlib
|
||||
]);
|
||||
in
|
||||
{
|
||||
home.packages = [
|
||||
python-with-packages
|
||||
];
|
||||
|
||||
home.sessionVariables = {
|
||||
PYTHONPATH = "${python-with-packages}/${python-with-packages.sitePackages}";
|
||||
};
|
||||
}
|
||||
@@ -2,8 +2,56 @@
|
||||
let
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./nx-gcal-event.nix
|
||||
];
|
||||
|
||||
home.packages = with pkgs; [
|
||||
waybar
|
||||
|
||||
(pkgs.writeShellScriptBin "waybar_mode" ''
|
||||
#!/usr/bin/env bash
|
||||
print_help() {
|
||||
echo "Usage: waybar_mode {set <string>|unset}"
|
||||
}
|
||||
if [ $# -lt 1 ]; then
|
||||
print_help; exit 1;
|
||||
fi
|
||||
case "$1" in
|
||||
set)
|
||||
# Check if there is a second argument for the 'set' operation
|
||||
if [ $# -eq 2 ]; then
|
||||
echo "$2" > /tmp/waybar-mode
|
||||
pkill -RTMIN+8 waybar
|
||||
else
|
||||
echo "Error: 'set' operation requires exactly one string argument."
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
unset)
|
||||
echo "" > /tmp/waybar-mode
|
||||
pkill -RTMIN+8 waybar
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unknown command '$1'"
|
||||
print_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
'')
|
||||
(pkgs.writeShellScriptBin "cclock" ''
|
||||
#!/bin/bash
|
||||
#ord=$(date +"%e" | awk '{printf("%d%s\n", $1, substr("thstndrd", ($1%100-20)%10*2+1, 2))}')
|
||||
ord=$(date +"%e" | awk '{printf("%d%s\n", $1, ($1==11||$1==12||$1==13)?"th":((($1%10)==1)?"st":((($1%10)==2)?"nd":((($1%10)==3)?"rd":"th"))))}')
|
||||
if [ $# -eq 0 ]; then
|
||||
echo " $(date +'%A the')" "$ord" "of" "$(date +'%B')" " " "$(date +'%R')"
|
||||
elif [ "$1" = "--no-icons" ]; then
|
||||
echo "$(date +'%A the')" "$ord" "of" "$(date +'%B')" "$(date +'%R')"
|
||||
fi
|
||||
'')
|
||||
|
||||
];
|
||||
|
||||
programs.waybar = {
|
||||
@@ -48,11 +96,11 @@ in
|
||||
separate-outputs = true;
|
||||
};
|
||||
"custom/cclock" = {
|
||||
exec = "/home/nx2/scripts/cclock.sh";
|
||||
exec = "cclock";
|
||||
restart-interval = 60;
|
||||
};
|
||||
"custom/ctimeremaining" = {
|
||||
exec = "python /home/nx2/scripts/NxGCalEvent/get-remaining-time.py";
|
||||
exec = "nx_gcal_event lookup";
|
||||
restart-interval = 60;
|
||||
};
|
||||
"custom/mode" = {
|
||||
Reference in New Issue
Block a user