Skip to content

Commit

Permalink
landing page + gunicorn
Browse files Browse the repository at this point in the history
  • Loading branch information
sagarreddypatil committed Jan 24, 2025
1 parent 577c0d1 commit ca88c95
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ WORKDIR /app
RUN uv sync --frozen

EXPOSE 5000
CMD ["uv", "run", "flask", "run", "--host=0.0.0.0"]
CMD ["uv", "run", "gunicorn", "app:app", "--bind", "0.0.0.0:5000"]
48 changes: 27 additions & 21 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,58 +1,64 @@
from main import do_the_thing
from flask import Flask, request, send_file
from flask import Flask, request, send_file, render_template, make_response
import json
import base64
from typing import Callable, Dict, Any
from typing import Dict, Any
from io import BytesIO

app = Flask(__name__)

@app.route('/gradescope.ics')

@app.route("/")
def index():
response = make_response(render_template("index.html"))
response.headers["Cache-Control"] = "public, max-age=3600"

return response


@app.route("/gradescope.ics")
def gradescope_calendar():
try:
# Get the base64 encoded query parameter
encoded_data = request.args.get('data')
encoded_data = request.args.get("data")
if not encoded_data:
return 'Missing data parameter', 400
return "Missing data parameter", 400

# Decode base64 to JSON string
try:
json_str = base64.b64decode(encoded_data).decode('utf-8')
json_str = base64.b64decode(encoded_data).decode("utf-8")
except Exception as e:
return f'Invalid base64 encoding: {str(e)}', 400
return f"Invalid base64 encoding: {str(e)}", 400

# Parse JSON
try:
data: Dict[str, Any] = json.loads(json_str)
except json.JSONDecodeError as e:
return f'Invalid JSON: {str(e)}', 400
return f"Invalid JSON: {str(e)}", 400

# Validate required fields
required_fields = ['email', 'pwd', 'sem']
required_fields = ["email", "pwd", "sem"]
for field in required_fields:
if field not in data:
return f'Missing required field: {field}', 400
return f"Missing required field: {field}", 400

# Call do_the_thing with the parameters
file_data = do_the_thing(
email=data['email'],
pwd=data['pwd'],
sem=data['sem']
)
file_data = do_the_thing(email=data["email"], pwd=data["pwd"], sem=data["sem"])

file_str = "".join(file_data)
file_io = BytesIO(file_str.encode('utf-8'))
file_io = BytesIO(file_str.encode("utf-8"))

# Send the file
return send_file(
file_io,
mimetype='text/calendar',
mimetype="text/calendar",
as_attachment=True,
download_name='gradescope.ics'
download_name="gradescope.ics",
)

except Exception as e:
return f'Server error: {str(e)}', 500
return f"Server error: {str(e)}", 500


if __name__ == '__main__':
app.run(debug=True)
if __name__ == "__main__":
app.run(debug=True)
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ requires-python = ">=3.12"
dependencies = [
"beautifulsoup4>=4.12.3",
"flask>=3.1.0",
"gunicorn>=23.0.0",
"ics>=0.7.2",
"python-dotenv>=1.0.1",
"requests>=2.32.3",
Expand Down
80 changes: 80 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!DOCTYPE html>
<html>
<head>
<title>Gradescope iCalendar</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');

body {
font-family: 'Inter', sans-serif;
}

.container {
display: flex;
flex-direction: column;
align-items: center;
/* justify-content: center; */
height: 100vh;
}

input {
margin: 0.5rem;
padding: 0.5rem;
width: 300px;
}

h1 {
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="container">
<h1>Gradescope iCalendar</h1>
<input type="text" id="email" placeholder="Gradescope Email" />
<input type="password" id="pwd" placeholder="Gradescope Password" />
<input type="text" id="sem" placeholder="Semester (e.g. Spring 2025)" />

<div style="height: 1rem"></div>

<input type="text" id="url" placeholder="URL" readonly />
</div>

<script>
function updateURL() {
var email = document.getElementById("email").value;
var pwd = document.getElementById("pwd").value;
var sem = document.getElementById("sem").value;

if (email === "" || pwd === "" || sem === "") {
document.getElementById("url").value = "";
return;
}

const data = {
email: email,
pwd: pwd,
sem: sem,
};

const data_b64 = btoa(JSON.stringify(data));

let url = window.location.href;
url = url.substring(0, url.lastIndexOf("/"));
url += "/gradescope.ics?data=" + data_b64;
document.getElementById("url").value = url;
}

document.getElementById("email").oninput = updateURL;
document.getElementById("pwd").oninput = updateURL;
document.getElementById("sem").oninput = updateURL;

updateURL();

document.getElementById("url").onclick = function () {
this.select();
document.execCommand("copy");
};
</script>
</body>
</html>
23 changes: 23 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ca88c95

Please sign in to comment.