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