commit
58dea7c7f6
3 changed files with 288 additions and 0 deletions
@ -0,0 +1,123 @@ |
|||||
|
ntnoe_credentials |
||||
|
|
||||
|
|
||||
|
# Created by https://www.gitignore.io/api/vim,python |
||||
|
|
||||
|
### Python ### |
||||
|
# Byte-compiled / optimized / DLL files |
||||
|
__pycache__/ |
||||
|
*.py[cod] |
||||
|
*$py.class |
||||
|
|
||||
|
# C extensions |
||||
|
*.so |
||||
|
|
||||
|
# Distribution / packaging |
||||
|
.Python |
||||
|
build/ |
||||
|
develop-eggs/ |
||||
|
dist/ |
||||
|
downloads/ |
||||
|
eggs/ |
||||
|
.eggs/ |
||||
|
lib/ |
||||
|
lib64/ |
||||
|
parts/ |
||||
|
sdist/ |
||||
|
var/ |
||||
|
wheels/ |
||||
|
*.egg-info/ |
||||
|
.installed.cfg |
||||
|
*.egg |
||||
|
|
||||
|
# PyInstaller |
||||
|
# Usually these files are written by a python script from a template |
||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it. |
||||
|
*.manifest |
||||
|
*.spec |
||||
|
|
||||
|
# Installer logs |
||||
|
pip-log.txt |
||||
|
pip-delete-this-directory.txt |
||||
|
|
||||
|
# Unit test / coverage reports |
||||
|
htmlcov/ |
||||
|
.tox/ |
||||
|
.coverage |
||||
|
.coverage.* |
||||
|
.cache |
||||
|
nosetests.xml |
||||
|
coverage.xml |
||||
|
*.cover |
||||
|
.hypothesis/ |
||||
|
|
||||
|
# Translations |
||||
|
*.mo |
||||
|
*.pot |
||||
|
|
||||
|
# Django stuff: |
||||
|
*.log |
||||
|
local_settings.py |
||||
|
|
||||
|
# Flask stuff: |
||||
|
instance/ |
||||
|
.webassets-cache |
||||
|
|
||||
|
# Scrapy stuff: |
||||
|
.scrapy |
||||
|
|
||||
|
# Sphinx documentation |
||||
|
docs/_build/ |
||||
|
|
||||
|
# PyBuilder |
||||
|
target/ |
||||
|
|
||||
|
# Jupyter Notebook |
||||
|
.ipynb_checkpoints |
||||
|
|
||||
|
# pyenv |
||||
|
.python-version |
||||
|
|
||||
|
# celery beat schedule file |
||||
|
celerybeat-schedule |
||||
|
|
||||
|
# SageMath parsed files |
||||
|
*.sage.py |
||||
|
|
||||
|
# Environments |
||||
|
.env |
||||
|
.venv |
||||
|
env/ |
||||
|
venv/ |
||||
|
ENV/ |
||||
|
env.bak/ |
||||
|
venv.bak/ |
||||
|
|
||||
|
# Spyder project settings |
||||
|
.spyderproject |
||||
|
.spyproject |
||||
|
|
||||
|
# Rope project settings |
||||
|
.ropeproject |
||||
|
|
||||
|
# mkdocs documentation |
||||
|
/site |
||||
|
|
||||
|
# mypy |
||||
|
.mypy_cache/ |
||||
|
|
||||
|
### Vim ### |
||||
|
# swap |
||||
|
[._]*.s[a-v][a-z] |
||||
|
[._]*.sw[a-p] |
||||
|
[._]s[a-v][a-z] |
||||
|
[._]sw[a-p] |
||||
|
# session |
||||
|
Session.vim |
||||
|
# temporary |
||||
|
.netrwhist |
||||
|
*~ |
||||
|
# auto-generated tag files |
||||
|
tags |
||||
|
|
||||
|
# End of https://www.gitignore.io/api/vim,python |
||||
@ -0,0 +1,163 @@ |
|||||
|
import datetime |
||||
|
import httplib2 |
||||
|
import urllib |
||||
|
import os |
||||
|
|
||||
|
from apiclient import discovery |
||||
|
from oauth2client import client |
||||
|
from oauth2client import tools |
||||
|
from oauth2client.file import Storage |
||||
|
|
||||
|
import icalendar |
||||
|
|
||||
|
|
||||
|
TIMEDELTA_SYNCHRO = datetime.timedelta(days=4) # Number of days to look for |
||||
|
# for synchronization |
||||
|
with open('ntnoe_credentials') as f: |
||||
|
NTNOE_ID,NTNOE_PASS,_ = f.read().split('\n') |
||||
|
|
||||
|
|
||||
|
SCOPES = 'https://www.googleapis.com/auth/calendar' |
||||
|
CLIENT_SECRET_FILE = 'client_secret.json' |
||||
|
APPLICATION_NAME = 'Google Calendar API Python Quickstart' |
||||
|
|
||||
|
|
||||
|
class Event: |
||||
|
# ColorId corresponding to course code |
||||
|
EVENT_COLOR = { |
||||
|
'9' : '9', # Amphi |
||||
|
'11' : '10', # TL |
||||
|
'10' : '6', # TD |
||||
|
'13' : '5', # Autre |
||||
|
'12' : '3', # Exam |
||||
|
|
||||
|
} |
||||
|
|
||||
|
def __init__(self, e): |
||||
|
""" Initialize an event from a `icalendar.cal.Event`.""" |
||||
|
self.summary = e.decoded('SUMMARY').decode('utf-8') |
||||
|
self.start = e.decoded('DTSTART') |
||||
|
self.end = e.decoded('DTEND') |
||||
|
self.location = e.decoded('LOCATION').decode('utf-8') |
||||
|
self.colorid = self.EVENT_COLOR.get(e.decoded('DESCRIPTION').decode('utf-8'), '1') |
||||
|
|
||||
|
def __str__(self): |
||||
|
return str(self.as_google()) |
||||
|
|
||||
|
def as_google(self): |
||||
|
return { |
||||
|
'summary' : self.summary, |
||||
|
'location' : self.location, |
||||
|
'start' : { |
||||
|
'dateTime' : self.start.isoformat(), |
||||
|
'timeZone' : 'Europe/Paris', |
||||
|
}, |
||||
|
'end' : { |
||||
|
'dateTime' : self.end.isoformat(), |
||||
|
'timeZone' : 'Europe/Paris', |
||||
|
}, |
||||
|
'colorId' : self.colorid, |
||||
|
'reminders': { |
||||
|
'useDefault': False, |
||||
|
'overrides': [], |
||||
|
}, |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
def get_credentials(): |
||||
|
"""Gets valid user credentials from storage. |
||||
|
|
||||
|
If nothing has been stored, or if the stored credentials are invalid, |
||||
|
the OAuth2 flow is completed to obtain the new credentials. |
||||
|
|
||||
|
Returns: |
||||
|
Credentials, the obtained credential. |
||||
|
""" |
||||
|
home_dir = os.path.expanduser('~') |
||||
|
credential_dir = os.path.join(home_dir, '.credentials') |
||||
|
if not os.path.exists(credential_dir): |
||||
|
os.makedirs(credential_dir) |
||||
|
credential_path = os.path.join(credential_dir, 'ntnoe.json') |
||||
|
|
||||
|
store = Storage(credential_path) |
||||
|
credentials = store.get() |
||||
|
if not credentials or credentials.invalid: |
||||
|
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES) |
||||
|
flow.user_agent = APPLICATION_NAME |
||||
|
print('Storing credentials to ' + credential_path) |
||||
|
credentials = tools.run_flow(flow, store) |
||||
|
|
||||
|
return credentials |
||||
|
|
||||
|
|
||||
|
def get_ntnoe(): |
||||
|
url = "http://ntnoe.metz.supelec.fr/ical/EdTcustom/Eleves/edt_{}.ics" |
||||
|
url = url.format(NTNOE_ID) |
||||
|
|
||||
|
h = httplib2.Http() |
||||
|
h.add_credentials(NTNOE_ID,NTNOE_PASS) |
||||
|
data = {'envoyer':'Utf8_All','submit':'G%E9n%E9rer'} |
||||
|
|
||||
|
h.request( |
||||
|
"https://ntnoe.metz.supelec.fr/ical/index.php", |
||||
|
body=urllib.parse.urlencode(data), |
||||
|
method='POST', |
||||
|
) |
||||
|
# resp,content = h.request( |
||||
|
# "https://ntnoe.metz.supelec.fr/ical/EdTcustom/Eleves/edt_{id}.ics".format(id=NTNOE_ID), |
||||
|
# ) |
||||
|
# print(resp,content) |
||||
|
# TODO : download from ntnoe |
||||
|
|
||||
|
|
||||
|
|
||||
|
def main(): |
||||
|
"""Get the events on NTNOE the puts them on Google Calendar. |
||||
|
|
||||
|
""" |
||||
|
get_ntnoe() |
||||
|
credentials = get_credentials() |
||||
|
http = credentials.authorize(httplib2.Http()) |
||||
|
service = discovery.build('calendar', 'v3', http=http) |
||||
|
|
||||
|
with open("edt_" + NTNOE_ID + ".ics") as f: |
||||
|
c = icalendar.Calendar.from_ical(f.read()) |
||||
|
|
||||
|
now = datetime.datetime.now() |
||||
|
then = now + TIMEDELTA_SYNCHRO |
||||
|
response = service.events().list( |
||||
|
calendarId='primary', |
||||
|
timeMin=now.isoformat()+'Z', |
||||
|
timeMax=then.isoformat()+'Z', |
||||
|
).execute() |
||||
|
|
||||
|
existing_events = set() |
||||
|
for e in response['items']: |
||||
|
if 'summary' in e.keys(): |
||||
|
existing_events.add(e['summary']) |
||||
|
for e in c.walk('VEVENT'): |
||||
|
event = Event(e) |
||||
|
t = ( |
||||
|
event.summary, |
||||
|
event.start.isoformat(), |
||||
|
event.end.isoformat(), |
||||
|
event.location |
||||
|
) |
||||
|
if now >= event.end or event.start >= then: |
||||
|
continue |
||||
|
|
||||
|
if existing_events.intersection({event.summary}): |
||||
|
continue |
||||
|
else: |
||||
|
print(event.summary) |
||||
|
|
||||
|
event = service.events().insert( |
||||
|
calendarId='primary', |
||||
|
body=event.as_google() |
||||
|
).execute() |
||||
|
print("Added event : {}".format(event.get('htmlLink'))) |
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
main() |
||||
|
|
||||
@ -0,0 +1,2 @@ |
|||||
|
nom_pre |
||||
|
ThisIsASecretPassword |
||||
Loading…
Reference in new issue