from django.conf import settings

from rest_framework.decorators import api_view

from common.helpers import PrettyJsonResponse as JsonResponse

from .models import Lock, Course, Depts, ModuleA, ModuleB

from .app_helpers import get_student_timetable, get_custom_timetable

from common.decorators import uclapi_protected_endpoint

_SETID = settings.ROOMBOOKINGS_SETID


@api_view(["GET"])
@uclapi_protected_endpoint(personal_data=True, required_scopes=['timetable'])
def get_personal_timetable(request, *args, **kwargs):
    token = kwargs['token']
    user = token.user
    try:
        date_filter = request.GET["date_filter"]
        timetable = get_student_timetable(user.employee_id, date_filter)
    except KeyError:
        timetable = get_student_timetable(user.employee_id)

    response = {
        "ok": True,
        "timetable": timetable
    }
    return JsonResponse(response, rate_limiting_data=kwargs)


@api_view(["GET"])
@uclapi_protected_endpoint()
def get_modules_timetable(request, *args, **kwargs):
    module_ids = request.GET.get("modules")
    if module_ids is None:
        return JsonResponse({
            "ok": False,
            "error": "No module IDs provided."
        }, rate_limiting_data=kwargs)

    try:
        modules = module_ids.split(',')
    except ValueError:
        return JsonResponse({
            "ok": False,
            "error": "Invalid module IDs provided."
        }, rate_limiting_data=kwargs)

    try:
        date_filter = request.GET["date_filter"]
        custom_timetable = get_custom_timetable(modules, date_filter)
    except KeyError:
        custom_timetable = get_custom_timetable(modules)

    if custom_timetable:
        response_json = {
            "ok": True,
            "timetable": custom_timetable
        }
        return JsonResponse(response_json, rate_limiting_data=kwargs)
    else:
        response_json = {
            "ok": False,
            "error": "One or more invalid Module IDs supplied."
        }
        response = JsonResponse(response_json, rate_limiting_data=kwargs)
        response.status_code = 400
        return response


@api_view(["GET"])
@uclapi_protected_endpoint()
def get_departments(request, *args, **kwargs):
    """
    Returns all departments at UCL
    """
    depts = {"ok": True, "departments": []}
    for dept in Depts.objects.all():
        depts["departments"].append({
            "department_id": dept.deptid,
            "name": dept.name
        }, rate_limiting_data=kwargs)
    return JsonResponse(depts, rate_limiting_data=kwargs)


@api_view(["GET"])
@uclapi_protected_endpoint()
def get_department_courses(request, *args, **kwargs):
    """
    Returns all the courses in UCL with relevant ID
    """
    try:
        department_id = request.GET["department"]
    except KeyError:
        response = JsonResponse({
            "ok": False,
            "error": "Supply a Department ID using the department parameter."
        }, rate_limiting_data=kwargs)
        response.status_code = 400
        return response

    courses = {"ok": True, "courses": []}
    for course in Course.objects.filter(owner=department_id, setid=_SETID):
        courses["courses"].append({
            "course_name": course.name,
            "course_id": course.courseid,
            "years": course.numyears
        })
    return JsonResponse(courses, rate_limiting_data=kwargs)


@api_view(["GET"])
@uclapi_protected_endpoint()
def get_department_modules(request, *args, **kwargs):
    """
    Returns all modules taught by a particular department.
    """
    try:
        department_id = request.GET["department"]
    except KeyError:
        response = JsonResponse({
            "ok": False,
            "error": "Supply a Department ID using the department parameter."
        }, rate_limiting_data=kwargs)
        response.status_code = 400
        return response

    modules = {"ok": True, "modules": []}
    lock = Lock.objects.all()[0]
    m = ModuleA if lock.a else ModuleB
    for module in m.objects.filter(owner=department_id, setid=_SETID):
        modules["modules"].append({
            "module_id": module.moduleid,
            "name": module.name,
            "module_code": module.linkcode,
            "class_size": module.csize
        })

    return JsonResponse(modules, rate_limiting_data=kwargs)

backend/uclapi/timetable/views.py
from django.conf import settings

from rest_framework.decorators import api_view

from common.helpers import PrettyJsonResponse as JsonResponse

from .models import Lock, Course, Depts, ModuleA, ModuleB

from .app_helpers import get_student_timetable, get_custom_timetable

from common.decorators import uclapi_protected_endpoint

_SETID = settings.ROOMBOOKINGS_SETID


@api_view(["GET"])
@uclapi_protected_endpoint(personal_data=True, required_scopes=['timetable'])
def get_personal_timetable(request, *args, **kwargs):
    token = kwargs['token']
    user = token.user
    try:
        date_filter = request.GET["date_filter"]
        timetable = get_student_timetable(user.employee_id, date_filter)
    except KeyError:
        timetable = get_student_timetable(user.employee_id)

    response = {
        "ok": True,
        "timetable": timetable
    }
    return JsonResponse(response, rate_limiting_data=kwargs)


@api_view(["GET"])
@uclapi_protected_endpoint()
def get_modules_timetable(request, *args, **kwargs):
    module_ids = request.GET.get("modules")
    if module_ids is None:
        return JsonResponse({
            "ok": False,
            "error": "No module IDs provided."
        }, rate_limiting_data=kwargs)

    try:
        modules = module_ids.split(',')
    except ValueError:
        return JsonResponse({
            "ok": False,
            "error": "Invalid module IDs provided."
        }, rate_limiting_data=kwargs)

    try:
        date_filter = request.GET["date_filter"]
        custom_timetable = get_custom_timetable(modules, date_filter)
    except KeyError:
        custom_timetable = get_custom_timetable(modules)

    if custom_timetable:
        response_json = {
            "ok": True,
            "timetable": custom_timetable
        }
        return JsonResponse(response_json, rate_limiting_data=kwargs)
    else:
        response_json = {
            "ok": False,
            "error": "One or more invalid Module IDs supplied."
        }
        response = JsonResponse(response_json, rate_limiting_data=kwargs)
        response.status_code = 400
        return response


@api_view(["GET"])
@uclapi_protected_endpoint()
def get_departments(request, *args, **kwargs):
    """
    Returns all departments at UCL
    """
    depts = {"ok": True, "departments": []}
    for dept in Depts.objects.all():
        depts["departments"].append({
            "department_id": dept.deptid,
            "name": dept.name
        })
    return JsonResponse(depts, rate_limiting_data=kwargs)


@api_view(["GET"])
@uclapi_protected_endpoint()
def get_department_courses(request, *args, **kwargs):
    """
    Returns all the courses in UCL with relevant ID
    """
    try:
        department_id = request.GET["department"]
    except KeyError:
        response = JsonResponse({
            "ok": False,
            "error": "Supply a Department ID using the department parameter."
        }, rate_limiting_data=kwargs)
        response.status_code = 400
        return response

    courses = {"ok": True, "courses": []}
    for course in Course.objects.filter(owner=department_id, setid=_SETID):
        courses["courses"].append({
            "course_name": course.name,
            "course_id": course.courseid,
            "years": course.numyears
        })
    return JsonResponse(courses, rate_limiting_data=kwargs)


@api_view(["GET"])
@uclapi_protected_endpoint()
def get_department_modules(request, *args, **kwargs):
    """
    Returns all modules taught by a particular department.
    """
    try:
        department_id = request.GET["department"]
    except KeyError:
        response = JsonResponse({
            "ok": False,
            "error": "Supply a Department ID using the department parameter."
        }, rate_limiting_data=kwargs)
        response.status_code = 400
        return response

    modules = {"ok": True, "modules": []}
    lock = Lock.objects.all()[0]
    m = ModuleA if lock.a else ModuleB
    for module in m.objects.filter(owner=department_id, setid=_SETID):
        modules["modules"].append({
            "module_id": module.moduleid,
            "name": module.name,
            "module_code": module.linkcode,
            "class_size": module.csize
        })

    return JsonResponse(modules, rate_limiting_data=kwargs)

backend/uclapi/timetable/views.py
diff --git a/backend/uclapi/timetable/views.py b/backend/uclapi/timetable/views.py
index 521ee4b5d..5b4812e83 100644
--- a/backend/uclapi/timetable/views.py
+++ b/backend/uclapi/timetable/views.py
@@ -82,7 +82,7 @@ def get_departments(request, *args, **kwargs):
         depts["departments"].append({
             "department_id": dept.deptid,
             "name": dept.name
-        }, rate_limiting_data=kwargs)
+        })
     return JsonResponse(depts, rate_limiting_data=kwargs)
 
 

timetable/data/departments endpoint returns 500 error
The timetable/data/departments endpoint is currently returning a 500 error on any request.

I know it's not a documented endpoint, but it would be nice if it worked :)

It looks to me like the problem is line 85 below - `rate_limiting_data` is being passed as an argument to `append`. 

https://github.com/uclapi/uclapi/blob/cfd6753ae3d979bbe53573dad68babc2de19e04d/backend/uclapi/timetable/views.py#L82-L85

Removing that and replacing with this:
```python
depts["departments"].append({ 
"department_id": dept.deptid, 
"name": dept.name}) 
```
should fix it, though I don't have the whole API setup installed, so I can't be sure.
