🎉」 init: working shitty script

This commit is contained in:
adjoly
2025-06-10 12:02:50 +02:00
commit 564df78a87
6 changed files with 355 additions and 0 deletions

1
.envrc Normal file
View File

@ -0,0 +1 @@
use flake

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.direnv
.env

156
24h.ics Normal file
View 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
View 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
View 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
View 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()