「🎉」 init: working shitty script
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.direnv
|
||||||
|
|
||||||
|
.env
|
156
24h.ics
Normal file
156
24h.ics
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
BEGIN:VCALENDAR
|
||||||
|
PRODID:-//Proton AG//ProtonCalendar 1.0.0//EN
|
||||||
|
VERSION:2.0
|
||||||
|
CALSCALE:GREGORIAN
|
||||||
|
METHOD:PUBLISH
|
||||||
|
X-WR-CALNAME:24h du Mans
|
||||||
|
X-WR-CALDESC:
|
||||||
|
X-WR-TIMEZONE:Europe/Paris
|
||||||
|
REFRESH-INTERVAL;VALUE=DURATION:PT240M
|
||||||
|
X-PUBLISHED-TTL:PT240M
|
||||||
|
BEGIN:VTIMEZONE
|
||||||
|
TZID:Europe/Paris
|
||||||
|
LAST-MODIFIED:20250218T131521Z
|
||||||
|
X-LIC-LOCATION:Europe/Paris
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
TZNAME:CEST
|
||||||
|
TZOFFSETFROM:+0100
|
||||||
|
TZOFFSETTO:+0200
|
||||||
|
DTSTART:19700329T020000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:STANDARD
|
||||||
|
TZNAME:CET
|
||||||
|
TZOFFSETFROM:+0200
|
||||||
|
TZOFFSETTO:+0100
|
||||||
|
DTSTART:19701025T030000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
||||||
|
END:STANDARD
|
||||||
|
END:VTIMEZONE
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:sabre-vobject-244d1309-86d5-42d5-8db3-e6e61f4bb67c
|
||||||
|
DTSTAMP:20250609T141021Z
|
||||||
|
SUMMARY:24 Hours of Le Mans 2025 - Race
|
||||||
|
DTSTART;TZID=Europe/Paris:20250614T160000
|
||||||
|
DTEND;TZID=Europe/Paris:20250615T160000
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:sabre-vobject-460cb9f4-cd83-4249-805c-212be3043944
|
||||||
|
DTSTAMP:20250609T141021Z
|
||||||
|
SUMMARY:24 Hours of Le Mans 2025 - Qualifying - LMP2 & LMGT3
|
||||||
|
DTSTART;TZID=Europe/Paris:20250611T184500
|
||||||
|
DTEND;TZID=Europe/Paris:20250611T191500
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:sabre-vobject-c1f55045-3080-47aa-bf94-abf5d15a1ec0
|
||||||
|
DTSTAMP:20250609T141021Z
|
||||||
|
SUMMARY:24 Hours of Le Mans 2025 - Warm-up
|
||||||
|
DTSTART;TZID=Europe/Paris:20250614T120000
|
||||||
|
DTEND;TZID=Europe/Paris:20250614T121500
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:sabre-vobject-80f4f074-58c0-456f-ba1b-589c0c6da159
|
||||||
|
DTSTAMP:20250609T141021Z
|
||||||
|
SUMMARY:24 Hours of Le Mans 2025 - Free Practice 1
|
||||||
|
DTSTART;TZID=Europe/Paris:20250611T140000
|
||||||
|
DTEND;TZID=Europe/Paris:20250611T170000
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:sabre-vobject-428f7889-c774-481f-b75c-b7db74799381
|
||||||
|
DTSTAMP:20250609T141021Z
|
||||||
|
SUMMARY:24 Hours of Le Mans 2025 - Free Practice 4
|
||||||
|
DTSTART;TZID=Europe/Paris:20250612T230000
|
||||||
|
DTEND;TZID=Europe/Paris:20250613T000000
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:sabre-vobject-fe0d6ec8-5491-4fed-8db4-be1070b796fe
|
||||||
|
DTSTAMP:20250609T141021Z
|
||||||
|
SUMMARY:24 Hours of Le Mans 2025 - HYPERPOLE 2 - HYPERCAR
|
||||||
|
DTSTART;TZID=Europe/Paris:20250612T214000
|
||||||
|
DTEND;TZID=Europe/Paris:20250612T215500
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:sabre-vobject-78a2d420-cf27-4527-911e-f8ac04204f23
|
||||||
|
DTSTAMP:20250609T141021Z
|
||||||
|
SUMMARY:24 Hours of Le Mans 2025 - HYPERPOLE 1 - HYPERCAR
|
||||||
|
DTSTART;TZID=Europe/Paris:20250612T210500
|
||||||
|
DTEND;TZID=Europe/Paris:20250612T212500
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:sabre-vobject-9a9dbd76-adb3-42e3-992c-2d0ef04dc909
|
||||||
|
DTSTAMP:20250609T141021Z
|
||||||
|
SUMMARY:24 Hours of Le Mans 2025 - HYPERPOLE 2 - LMP2 & LMGT3
|
||||||
|
DTSTART;TZID=Europe/Paris:20250612T203500
|
||||||
|
DTEND;TZID=Europe/Paris:20250612T205000
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:sabre-vobject-f07a2dbe-8958-4e6d-948e-05c47cd71890
|
||||||
|
DTSTAMP:20250609T141022Z
|
||||||
|
SUMMARY:24 Hours of Le Mans 2025 - HYPERPOLE 1 - LMP2 & LMGT3
|
||||||
|
DTSTART;TZID=Europe/Paris:20250612T200000
|
||||||
|
DTEND;TZID=Europe/Paris:20250612T202000
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:sabre-vobject-a7ec4975-04b1-44c8-8065-743e3cf6e7cb
|
||||||
|
DTSTAMP:20250609T141022Z
|
||||||
|
SUMMARY:24 Hours of Le Mans 2025 - Free Practice 3
|
||||||
|
DTSTART;TZID=Europe/Paris:20250612T144500
|
||||||
|
DTEND;TZID=Europe/Paris:20250612T174500
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:sabre-vobject-fce906a9-4434-4adc-bcd6-0bb7669e0bb1
|
||||||
|
DTSTAMP:20250609T141022Z
|
||||||
|
SUMMARY:24 Hours of Le Mans 2025 - Free Practice 2
|
||||||
|
DTSTART;TZID=Europe/Paris:20250611T220000
|
||||||
|
DTEND;TZID=Europe/Paris:20250612T000000
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:sabre-vobject-8c32bb13-bb2e-4f29-9706-e4d03d8149d1
|
||||||
|
DTSTAMP:20250609T141022Z
|
||||||
|
SUMMARY:24 Hours of Le Mans 2025 - Qualifying - Hypercar
|
||||||
|
DTSTART;TZID=Europe/Paris:20250611T193000
|
||||||
|
DTEND;TZID=Europe/Paris:20250611T200000
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:AEf2LX8fa3lqe8dKTsDjPwmhvBip@proton.me
|
||||||
|
DTSTAMP:20250609T141022Z
|
||||||
|
SUMMARY:24 Hours of Le Mans 2025 - Eurosport 2
|
||||||
|
DTSTART;TZID=Europe/Paris:20250610T193000
|
||||||
|
DTEND;TZID=Europe/Paris:20250610T210000
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:x14Vl7X2L6pSQBH2mt1IRuy-Vjjx@proton.me
|
||||||
|
DTSTAMP:20250610T084743Z
|
||||||
|
SUMMARY:test
|
||||||
|
DTSTART;TZID=Europe/Paris:20250610T100000
|
||||||
|
DTEND;TZID=Europe/Paris:20250610T120000
|
||||||
|
SEQUENCE:0
|
||||||
|
STATUS:CONFIRMED
|
||||||
|
END:VEVENT
|
||||||
|
END:VCALENDAR
|
44
flake.lock
generated
Normal file
44
flake.lock
generated
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1749285348,
|
||||||
|
"narHash": "sha256-frdhQvPbmDYaScPFiCnfdh3B/Vh81Uuoo0w5TkWmmjU=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "3e3afe5174c561dee0df6f2c2b2236990146329f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pypresence": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1743073125,
|
||||||
|
"narHash": "sha256-DjwDmQMbI9tV40TTe1CthhphoysKSFICrRhqijJjIAE=",
|
||||||
|
"owner": "qwertyquerty",
|
||||||
|
"repo": "pypresence",
|
||||||
|
"rev": "4e882c36d0f800c016c15977243ac9a49177095a",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "qwertyquerty",
|
||||||
|
"repo": "pypresence",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"pypresence": "pypresence"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
58
flake.nix
Normal file
58
flake.nix
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
|
pypresence.url = "github:qwertyquerty/pypresence";
|
||||||
|
pypresence.flake = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs =
|
||||||
|
inputs@{ self, nixpkgs, ... }:
|
||||||
|
let
|
||||||
|
supportedSystems = [
|
||||||
|
"x86_64-linux"
|
||||||
|
"aarch64-linux"
|
||||||
|
"x86_64-darwin"
|
||||||
|
"aarch64-darwin"
|
||||||
|
];
|
||||||
|
forEachSupportedSystem =
|
||||||
|
f:
|
||||||
|
nixpkgs.lib.genAttrs supportedSystems (
|
||||||
|
system:
|
||||||
|
f {
|
||||||
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
packages = forEachSupportedSystem (
|
||||||
|
{ pkgs }:
|
||||||
|
{
|
||||||
|
default = pkgs.python313Packages.buildPythonPackage {
|
||||||
|
pname = "pypresence";
|
||||||
|
version = "4.4.0"; # Replace with the actual version or a placeholder
|
||||||
|
format = "setuptools";
|
||||||
|
src = inputs.pypresence;
|
||||||
|
doCheck = false; # tests require internet connection
|
||||||
|
pythonImportsCheck = [ "pypresence" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
devShells = forEachSupportedSystem (
|
||||||
|
{ pkgs }:
|
||||||
|
{
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
packages = with pkgs; [
|
||||||
|
nixd
|
||||||
|
nixfmt-rfc-style
|
||||||
|
python313
|
||||||
|
self.packages.${pkgs.system}.default
|
||||||
|
python313Packages.icalendar
|
||||||
|
python313Packages.pytz
|
||||||
|
python313Packages.python-dotenv
|
||||||
|
python313Packages.requests
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
93
rpc.py
Normal file
93
rpc.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
from pypresence import Presence, ActivityType
|
||||||
|
import os
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import icalendar
|
||||||
|
import pytz
|
||||||
|
import requests
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
import time
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# Initialize PyPresence with your application ID
|
||||||
|
client_id = os.getenv('DISCORD_APPLICATION_ID')
|
||||||
|
ics_url = os.getenv('ICS_URL')
|
||||||
|
|
||||||
|
if not client_id or not ics_url:
|
||||||
|
raise ValueError("issue in .env file")
|
||||||
|
|
||||||
|
RPC = Presence(client_id)
|
||||||
|
|
||||||
|
try:
|
||||||
|
RPC.connect()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed to connect to Discord: {e}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
def fetch_ics(url):
|
||||||
|
response = requests.get(url)
|
||||||
|
if response.status_code == 200:
|
||||||
|
return response.content
|
||||||
|
else:
|
||||||
|
raise Exception("Failed to fetch the .ics file")
|
||||||
|
|
||||||
|
def parse_ics(ics_content):
|
||||||
|
cal = icalendar.Calendar.from_ical(ics_content)
|
||||||
|
events = []
|
||||||
|
for component in cal.walk():
|
||||||
|
if component.name == 'VEVENT':
|
||||||
|
summary = component.get('summary')
|
||||||
|
dtstart = component.get('dtstart').dt
|
||||||
|
dtend = component.get('dtend').dt
|
||||||
|
|
||||||
|
# Convert datetime to timezone-aware if necessary
|
||||||
|
if isinstance(dtstart, datetime) and dtstart.tzinfo is None:
|
||||||
|
dtstart = pytz.utc.localize(dtstart)
|
||||||
|
if isinstance(dtend, datetime) and dtend.tzinfo is None:
|
||||||
|
dtend = pytz.utc.localize(dtend)
|
||||||
|
|
||||||
|
events.append({
|
||||||
|
'summary': str(summary),
|
||||||
|
'start': dtstart,
|
||||||
|
'end': dtend
|
||||||
|
})
|
||||||
|
return events
|
||||||
|
|
||||||
|
def update_presence(event):
|
||||||
|
now = datetime.now(timezone.utc)
|
||||||
|
if event['start'] <= now <= event['end']:
|
||||||
|
parts = event['summary'].split(' - ')
|
||||||
|
if len(parts) == 2:
|
||||||
|
state_part, details_part = parts
|
||||||
|
else:
|
||||||
|
state_part = event['summary']
|
||||||
|
details_part = 'Event'
|
||||||
|
|
||||||
|
RPC.update(
|
||||||
|
activity_type=ActivityType.WATCHING,
|
||||||
|
details=details_part,
|
||||||
|
state=state_part,
|
||||||
|
large_image="favicon", # Replace with your image key
|
||||||
|
large_text="Bangers incomming",
|
||||||
|
start=int(event['start'].timestamp()),
|
||||||
|
end=int(event['end'].timestamp())
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
RPC.clear()
|
||||||
|
|
||||||
|
print("Rich Presence is running. Press Ctrl+C to stop.")
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
ics_content = fetch_ics(ics_url)
|
||||||
|
events = parse_ics(ics_content)
|
||||||
|
for event in events:
|
||||||
|
update_presence(event)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
|
time.sleep(60) # Update every minute
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("Stopping Rich Presence...")
|
||||||
|
finally:
|
||||||
|
RPC.close()
|
Reference in New Issue
Block a user