initial commit
This commit is contained in:
117
.gitignore
vendored
Normal file
117
.gitignore
vendored
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
credentials.json
|
||||||
|
token.json
|
||||||
|
timetableurl
|
||||||
|
|
||||||
|
# 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
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# 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/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# 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/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
.vscode
|
||||||
16
Pipfile
Normal file
16
Pipfile
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[[source]]
|
||||||
|
name = "pypi"
|
||||||
|
verify_ssl = true
|
||||||
|
url = "https://pypi.org/simple"
|
||||||
|
|
||||||
|
[packages]
|
||||||
|
google-api-python-client = "*"
|
||||||
|
"oauth2client" = "*"
|
||||||
|
requests = "*"
|
||||||
|
"bs4" = "*"
|
||||||
|
pyjsparser = "*"
|
||||||
|
|
||||||
|
[dev-packages]
|
||||||
|
|
||||||
|
[requires]
|
||||||
|
python_version = "3.5"
|
||||||
159
Pipfile.lock
generated
Normal file
159
Pipfile.lock
generated
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
{
|
||||||
|
"_meta": {
|
||||||
|
"hash": {
|
||||||
|
"sha256": "4f51c5cdd18415e19bcc08f7b94be7674d2ed4295d49a0668d611e3e0e284e3d"
|
||||||
|
},
|
||||||
|
"pipfile-spec": 6,
|
||||||
|
"requires": {
|
||||||
|
"python_version": "3.5"
|
||||||
|
},
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"name": "pypi",
|
||||||
|
"url": "https://pypi.org/simple",
|
||||||
|
"verify_ssl": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"beautifulsoup4": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:194ec62a25438adcb3fdb06378b26559eda1ea8a747367d34c33cef9c7f48d57",
|
||||||
|
"sha256:90f8e61121d6ae58362ce3bed8cd997efb00c914eae0ff3d363c32f9a9822d10",
|
||||||
|
"sha256:f0abd31228055d698bb392a826528ea08ebb9959e6bea17c606fd9c9009db938"
|
||||||
|
],
|
||||||
|
"version": "==4.6.3"
|
||||||
|
},
|
||||||
|
"bs4": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==0.0.1"
|
||||||
|
},
|
||||||
|
"cachetools": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:90f1d559512fc073483fe573ef5ceb39bf6ad3d39edc98dc55178a2b2b176fa3",
|
||||||
|
"sha256:d1c398969c478d336f767ba02040fa22617333293fb0b8968e79b16028dfee35"
|
||||||
|
],
|
||||||
|
"version": "==2.1.0"
|
||||||
|
},
|
||||||
|
"certifi": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:376690d6f16d32f9d1fe8932551d80b23e9d393a8578c5633a2ed39a64861638",
|
||||||
|
"sha256:456048c7e371c089d0a77a5212fb37a2c2dce1e24146e3b7e0261736aaeaa22a"
|
||||||
|
],
|
||||||
|
"version": "==2018.8.24"
|
||||||
|
},
|
||||||
|
"chardet": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
||||||
|
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
||||||
|
],
|
||||||
|
"version": "==3.0.4"
|
||||||
|
},
|
||||||
|
"google-api-python-client": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:5d5cb02c6f3112c68eed51b74891a49c0e35263380672d662f8bfe85b8114d7c",
|
||||||
|
"sha256:7cc47cf80b25ecd7f3d917ea247bb6c62587514e40604ae29c47c0e4ebd1174b"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==1.7.4"
|
||||||
|
},
|
||||||
|
"google-auth": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:9ca363facbf2622d9ba828017536ccca2e0f58bd15e659b52f312172f8815530",
|
||||||
|
"sha256:a4cf9e803f2176b5de442763bd339b313d3f1ed3002e3e1eb6eec1d7c9bbc9b4"
|
||||||
|
],
|
||||||
|
"version": "==1.5.1"
|
||||||
|
},
|
||||||
|
"google-auth-httplib2": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:098fade613c25b4527b2c08fa42d11f3c2037dda8995d86de0745228e965d445",
|
||||||
|
"sha256:f1c437842155680cf9918df9bc51c1182fda41feef88c34004bd1978c8157e08"
|
||||||
|
],
|
||||||
|
"version": "==0.0.3"
|
||||||
|
},
|
||||||
|
"httplib2": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:e71daed9a0e6373642db61166fa70beecc9bf04383477f84671348c02a04cbdf"
|
||||||
|
],
|
||||||
|
"version": "==0.11.3"
|
||||||
|
},
|
||||||
|
"idna": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e",
|
||||||
|
"sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16"
|
||||||
|
],
|
||||||
|
"version": "==2.7"
|
||||||
|
},
|
||||||
|
"oauth2client": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:bd3062c06f8b10c6ef7a890b22c2740e5f87d61b6e1f4b1c90d069cdfc9dadb5",
|
||||||
|
"sha256:cf061f52f75e91d489bf5c276498f8af2655fe331b454f10022441513cf445a6"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==4.1.2"
|
||||||
|
},
|
||||||
|
"pyasn1": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:b9d3abc5031e61927c82d4d96c1cec1e55676c1a991623cfed28faea73cdd7ca",
|
||||||
|
"sha256:f58f2a3d12fd754aa123e9fa74fb7345333000a035f3921dbdaa08597aa53137"
|
||||||
|
],
|
||||||
|
"version": "==0.4.4"
|
||||||
|
},
|
||||||
|
"pyasn1-modules": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:a0cf3e1842e7c60fde97cb22d275eb6f9524f5c5250489e292529de841417547",
|
||||||
|
"sha256:a38a8811ea784c0136abfdba73963876328f66172db21a05a82f9515909bfb4e"
|
||||||
|
],
|
||||||
|
"version": "==0.2.2"
|
||||||
|
},
|
||||||
|
"pyjsparser": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:e4a659df3db42a2ff9fbc961eb6d4076a0b945e1aadfc20d48f913ad5dca011d"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==2.5.2"
|
||||||
|
},
|
||||||
|
"requests": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1",
|
||||||
|
"sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==2.19.1"
|
||||||
|
},
|
||||||
|
"rsa": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:25df4e10c263fb88b5ace923dd84bf9aa7f5019687b5e55382ffcdb8bede9db5",
|
||||||
|
"sha256:43f682fea81c452c98d09fc316aae12de6d30c4b5c84226642cf8f8fd1c93abd"
|
||||||
|
],
|
||||||
|
"version": "==3.4.2"
|
||||||
|
},
|
||||||
|
"six": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
|
||||||
|
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
|
||||||
|
],
|
||||||
|
"version": "==1.11.0"
|
||||||
|
},
|
||||||
|
"uritemplate": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:01c69f4fe8ed503b2951bef85d996a9d22434d2431584b5b107b2981ff416fbd",
|
||||||
|
"sha256:1b9c467a940ce9fb9f50df819e8ddd14696f89b9a8cc87ac77952ba416e0a8fd",
|
||||||
|
"sha256:c02643cebe23fc8adb5e6becffe201185bf06c40bda5c0b4028a93f1527d011d"
|
||||||
|
],
|
||||||
|
"version": "==3.0.0"
|
||||||
|
},
|
||||||
|
"urllib3": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf",
|
||||||
|
"sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5"
|
||||||
|
],
|
||||||
|
"markers": "python_version != '3.0.*' and python_version < '4' and python_version != '3.3.*' and python_version >= '2.6' and python_version != '3.2.*' and python_version != '3.1.*'",
|
||||||
|
"version": "==1.23"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"develop": {}
|
||||||
|
}
|
||||||
88
main.py
Normal file
88
main.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import requests
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from datetime import datetime
|
||||||
|
from googleapiclient.discovery import build
|
||||||
|
from httplib2 import Http
|
||||||
|
from oauth2client import file, client, tools
|
||||||
|
|
||||||
|
URL = open("timetableurl").read().strip()
|
||||||
|
|
||||||
|
def parse_events(page_data):
|
||||||
|
soup = BeautifulSoup(page_data, features="html.parser")
|
||||||
|
|
||||||
|
source = ""
|
||||||
|
for script in soup.head.findAll("script", {"type": "text/javascript"}):
|
||||||
|
if not script.has_attr("src"):
|
||||||
|
source = script.text
|
||||||
|
break
|
||||||
|
|
||||||
|
events_data = source.split("events:")[1].split("]")[0] +"]"
|
||||||
|
|
||||||
|
# Replace date objects with tuples, easier to parse
|
||||||
|
events_data = events_data.replace("new Date", "")
|
||||||
|
|
||||||
|
cleaned_data = ""
|
||||||
|
|
||||||
|
# Remove comments, properties to keys
|
||||||
|
for line in events_data.split("\n"):
|
||||||
|
comment_pos = line.find("//")
|
||||||
|
if comment_pos != -1:
|
||||||
|
line = line[:comment_pos]
|
||||||
|
|
||||||
|
|
||||||
|
if ":" in line:
|
||||||
|
line_values = line.split(":")
|
||||||
|
line = "'" + line_values[0] + "': " + line_values[1]
|
||||||
|
|
||||||
|
cleaned_data += line + "\n"
|
||||||
|
|
||||||
|
parsed_data = eval(cleaned_data)
|
||||||
|
|
||||||
|
for event in parsed_data:
|
||||||
|
if "start" in event:
|
||||||
|
event["start"] = list(event["start"])
|
||||||
|
event["start"][1] += 1
|
||||||
|
event["start"] = datetime(*event["start"])
|
||||||
|
|
||||||
|
if "end" in event:
|
||||||
|
event["end"] = list(event["end"])
|
||||||
|
event["end"][1] += 1
|
||||||
|
event["end"] = datetime(*event["end"])
|
||||||
|
|
||||||
|
return parsed_data
|
||||||
|
|
||||||
|
# If modifying these scopes, delete the file token.json.
|
||||||
|
SCOPES = 'https://www.googleapis.com/auth/calendar.readonly'
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Shows basic usage of the Google Calendar API.
|
||||||
|
Prints the start and name of the next 10 events on the user's calendar.
|
||||||
|
"""
|
||||||
|
store = file.Storage('token.json')
|
||||||
|
creds = store.get()
|
||||||
|
if not creds or creds.invalid:
|
||||||
|
flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
|
||||||
|
creds = tools.run_flow(flow, store)
|
||||||
|
service = build('calendar', 'v3', http=creds.authorize(Http()))
|
||||||
|
|
||||||
|
# Call the Calendar API
|
||||||
|
now = datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
|
||||||
|
print('Getting the upcoming 10 events')
|
||||||
|
events_result = service.events().list(calendarId='primary', timeMin=now,
|
||||||
|
maxResults=10, singleEvents=True,
|
||||||
|
orderBy='startTime').execute()
|
||||||
|
events = events_result.get('items', [])
|
||||||
|
|
||||||
|
if not events:
|
||||||
|
print('No upcoming events found.')
|
||||||
|
for event in events:
|
||||||
|
start = event['start'].get('dateTime', event['start'].get('date'))
|
||||||
|
print(start, event['summary'])
|
||||||
|
|
||||||
|
new_event = parse_events(requests.get(URL).text)[0]
|
||||||
|
new_event["title"] += " - " + new_event["lecturer"]
|
||||||
|
new_event["description"] = new_event[""]
|
||||||
|
print(new_event)
|
||||||
|
service.events().insert(body=new_event).execute()
|
||||||
|
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user