diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..5d522b4 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,27 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-dockerfile +{ + "name": "Existing Dockerfile", + "build": { + // Sets the run context to one level up instead of the .devcontainer folder. + "context": "..", + // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename. + "dockerfile": "../Dockerfile" + }, + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [8000], + "runArgs": ["--network=host"] + + // Uncomment the next line to run commands after the container is created. + // "postCreateCommand": "cat /etc/os-release", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "devcontainer" +} diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e1b48ba --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +__pycache__/ + + +# Django stuff +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +static + +# Environment +.env +.env* +.venv +venv/ diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml new file mode 100644 index 0000000..fa912b7 --- /dev/null +++ b/.github/workflows/deploy.yaml @@ -0,0 +1,117 @@ +name: Build and Deploy + +on: + push: + branches: + - main + release: + types: + - published + +permissions: + contents: read + packages: write + id-token: write + +jobs: + build-and-push: + runs-on: ubuntu-24.04-arm + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute image tags + id: image + env: + EVENT_NAME: ${{ github.event_name }} + RELEASE_TAG: ${{ github.event.release.tag_name }} + RELEASE_PRERELEASE: ${{ github.event.release.prerelease }} + REPOSITORY: ${{ github.repository }} + SHA: ${{ github.sha }} + run: | + set -euo pipefail + image="ghcr.io/${REPOSITORY,,}" + short_sha="${SHA::12}" + + tags="" + + if [[ "$EVENT_NAME" == "push" ]]; then + tags="${image}:nightly" + tags+=$'\n'"${image}:sha-${short_sha}" + elif [[ "$EVENT_NAME" == "release" ]]; then + tags="${image}:${RELEASE_TAG}" + if [[ "$RELEASE_PRERELEASE" != "true" ]]; then + tags+=$'\n'"${image}:latest" + fi + else + echo "Unsupported event: $EVENT_NAME" >&2 + exit 1 + fi + + { + echo "image=$image" + echo "tags<> "$GITHUB_OUTPUT" + + - name: Build and push image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile.aws + push: true + platforms: ${{ vars.DOCKER_PLATFORMS != '' && vars.DOCKER_PLATFORMS || 'linux/arm64' }} + tags: ${{ steps.image.outputs.tags }} + + deploy-dev: + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + needs: build-and-push + runs-on: ubuntu-latest + + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} + aws-region: ${{ vars.AWS_REGION }} + + - name: Trigger ECS deployment (dev) + run: | + aws ecs update-service \ + --cluster "${{ vars.ECS_DEV_CLUSTER }}" \ + --service "${{ vars.ECS_DEV_SERVICE }}" \ + --force-new-deployment + + deploy-prod: + if: github.event_name == 'release' && github.event.release.prerelease == false + needs: build-and-push + runs-on: ubuntu-latest + + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} + aws-region: ${{ vars.AWS_REGION }} + + - name: Trigger ECS deployment (prod) + run: | + aws ecs update-service \ + --cluster "${{ vars.ECS_PROD_CLUSTER }}" \ + --service "${{ vars.ECS_PROD_SERVICE }}" \ + --force-new-deployment diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 0000000..06bdb43 --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,25 @@ +name: Check Python Code Formatting + +on: + pull_request: + branches: + - main + +jobs: + format-check: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12.x" + + - name: Install Black + run: pip install black + + - name: Run Black + run: black . --check \ No newline at end of file diff --git a/.gitignore b/.gitignore index b1565d1..24dcd3c 100644 --- a/.gitignore +++ b/.gitignore @@ -151,7 +151,6 @@ typings/ ### VisualStudioCode template -.vscode/ .vscode/* !.vscode/settings.json !.vscode/tasks.json diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..b4736d5 --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +python 3.11.6 diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..e9f62bf --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python Debugger: Django", + "type": "debugpy", + "request": "launch", + "args": [ + "runserver" + ], + "django": true, + "autoStartBrowser": false, + "program": "${workspaceFolder}/manage.py" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..358e34a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter", + "editor.formatOnSave": true + }, + "editor.formatOnPaste": true, + "editor.formatOnSave": true +} \ No newline at end of file diff --git a/Dockerfile.aws b/Dockerfile.aws new file mode 100644 index 0000000..af6b772 --- /dev/null +++ b/Dockerfile.aws @@ -0,0 +1,35 @@ +FROM python:3.10-slim AS builder + +RUN mkdir /app + +WORKDIR /app + +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +COPY requirements.txt /app/ +COPY requirements/ /app/requirements/ +RUN pip install --no-cache-dir -r requirements.txt +RUN pip install --no-cache-dir -r /app/requirements/production.txt + +FROM python:3.10-slim + +RUN useradd -m -r appuser && \ + mkdir /app && \ + chown -R appuser /app + +COPY --from=builder /usr/local/lib/python3.10/site-packages/ /usr/local/lib/python3.10/site-packages/ +COPY --from=builder /usr/local/bin/ /usr/local/bin + +WORKDIR /app + +COPY --chown=appuser:appuser . . + +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +RUN chmod +x /app/entrypoint.prod.sh + +EXPOSE 8000 + +CMD ["/app/entrypoint.prod.sh"] diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..3351d8c --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: bash start.sh diff --git a/README.md b/README.md index 271327f..d81bf9c 100644 --- a/README.md +++ b/README.md @@ -82,21 +82,21 @@ Moved to [Live reloading and SASS compilation](http://cookiecutter-django.readth ### Email Server -In development, it is often nice to be able to see emails that are being sent from your application. If you choose to use [MailHog](https://github.com/mailhog/MailHog) when generating the project a local SMTP server with a web interface will be available. +In development, it is often nice to be able to see emails that are being sent from your application. If you choose to use [mailpit](https://github.com/axllent/mailpit) when generating the project a local SMTP server with a web interface will be available. -1. [Download the latest MailHog release](https://github.com/mailhog/MailHog/releases) for your OS. +1. [Download the latest mailpit release](https://github.com/axllent/mailpit/releases) for your OS. -2. Rename the build to `MailHog`. +2. Rename the build to `mailpit`. 3. Copy the file to the project root. 4. Make it executable: - $ chmod +x MailHog + $ chmod +x mailpit 5. Spin up another terminal window and start it there: - ./MailHog + ./mailpit 6. Check out to see how it goes. @@ -128,7 +128,7 @@ The following details how to deploy this application. # Renewing SSL Certs (requires creating DNS TXT Entries rn πŸ˜•) 1. maybe this is the command? - * `sudo certbot certonly --manual --server https://acme-v02.api.letsencrypt.org/directory --preferred-challenges dns-01 -d "*.musiccpr.org,musiccpr.org"` + * `sudo certbot certonly --manual --server https://acme-v02.api.letsencrypt.org/directory --preferred-challenges dns-01 -d "musiccpr.org,dev-api.musiccpr.org,dev.musiccpr.org,api.musiccpr.org"` # Deploying to Prod first time Prefer to have: 1. same ec2 instance as dev diff --git a/config/api_router.py b/config/api_router.py index 63fa6c3..67e7765 100644 --- a/config/api_router.py +++ b/config/api_router.py @@ -16,6 +16,7 @@ SubmissionViewSet, AttachmentViewSet, TeacherSubmissionViewSet, + ActivityProgressViewSet, ) from teleband.musics.api.views import PieceViewSet from teleband.instruments.api.views import InstrumentViewSet @@ -45,6 +46,7 @@ assignments_router = nested_cls(courses_router, "assignments", lookup="assignment") assignments_router.register("submissions", SubmissionViewSet) +assignments_router.register("activity-progress", ActivityProgressViewSet, basename="activity-progress") attachments_router = nested_cls(assignments_router, "submissions", lookup="submission") attachments_router.register("attachments", AttachmentViewSet) diff --git a/config/settings/base.py b/config/settings/base.py index 14fe04a..8cf4fdc 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -46,6 +46,8 @@ "default": env.db("DATABASE_URL", default="postgres:///teleband"), } DATABASES["default"]["ATOMIC_REQUESTS"] = True +DATABASES["default"]["OPTIONS"] = {"pool": True} + # https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-DEFAULT_AUTO_FIELD DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" @@ -90,6 +92,7 @@ "teleband.instruments", "teleband.musics", "teleband.submissions", + "teleband.dashboards", ] # https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS @@ -137,6 +140,7 @@ # ------------------------------------------------------------------------------ # https://docs.djangoproject.com/en/dev/ref/settings/#middleware MIDDLEWARE = [ + "teleband.utils.health_check.AlbHealthcheckMiddleware", "django.middleware.security.SecurityMiddleware", "corsheaders.middleware.CorsMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", diff --git a/config/settings/local.py b/config/settings/local.py index 297c550..6f37b8f 100644 --- a/config/settings/local.py +++ b/config/settings/local.py @@ -14,7 +14,16 @@ "default": env.db("DATABASE_URL", default="sqlite:///db.sqlite"), } # https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts -ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", default=["localhost", "0.0.0.0", "127.0.0.1"]) +ALLOWED_HOSTS = env.list( + "ALLOWED_HOSTS", + default=[ + "localhost", + "0.0.0.0", + "127.0.0.1", + "dev-api.musiccpr.org", + "api.musiccpr.org", + ], +) # CACHES # ------------------------------------------------------------------------------ diff --git a/config/settings/production.py b/config/settings/production.py index ccdac18..3ffe0c0 100644 --- a/config/settings/production.py +++ b/config/settings/production.py @@ -7,7 +7,10 @@ # https://docs.djangoproject.com/en/dev/ref/settings/#secret-key SECRET_KEY = env("DJANGO_SECRET_KEY") # https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts -ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["https://tele.band"]) +ALLOWED_HOSTS = env.list( + "DJANGO_ALLOWED_HOSTS", + default=["https://tele.band", "dev-api.musiccpr.org", "api.musiccpr.org"], +) # DATABASES # ------------------------------------------------------------------------------ @@ -20,18 +23,28 @@ # CACHES # ------------------------------------------------------------------------------ -CACHES = { - "default": { - "BACKEND": "django_redis.cache.RedisCache", - "LOCATION": env("REDIS_URL"), - "OPTIONS": { - "CLIENT_CLASS": "django_redis.client.DefaultClient", - # Mimicing memcache behavior. - # https://github.com/jazzband/django-redis#memcached-exceptions-behavior - "IGNORE_EXCEPTIONS": True, - }, +REDIS_URL = env("REDIS_URL", default="") + +if REDIS_URL: + CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": REDIS_URL, + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + # Mimicing memcache behavior. + # https://github.com/jazzband/django-redis#memcached-exceptions-behavior + "IGNORE_EXCEPTIONS": True, + }, + } + } +else: + CACHES = { + "default": { + "BACKEND": "django.core.cache.backends.locmem.LocMemCache", + "LOCATION": "", + } } -} # SECURITY # ------------------------------------------------------------------------------ @@ -69,6 +82,8 @@ # https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings AWS_STORAGE_BUCKET_NAME = env("DJANGO_AWS_STORAGE_BUCKET_NAME") # https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings +AWS_DEFAULT_ACL = None +# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings AWS_QUERYSTRING_AUTH = True # DO NOT change these unless you know what you're doing. _AWS_EXPIRY = 60 * 60 * 24 * 7 @@ -108,7 +123,7 @@ # ADMIN # ------------------------------------------------------------------------------ # Django Admin URL regex. -ADMIN_URL = env("DJANGO_ADMIN_URL") +ADMIN_URL = env("DJANGO_ADMIN_URL", default="admin/") # Anymail # ------------------------------------------------------------------------------ diff --git a/config/settings/railway.py b/config/settings/railway.py new file mode 100644 index 0000000..510c31e --- /dev/null +++ b/config/settings/railway.py @@ -0,0 +1,149 @@ +""" +Django settings for Railway deployment. + +Simplified production settings without AWS dependencies. +Uses whitenoise for static files and local filesystem for media. +""" + +from .base import * # noqa +from .base import env, ROOT_DIR +import os + +# GENERAL +# ------------------------------------------------------------------------------ +SECRET_KEY = env("DJANGO_SECRET_KEY") +DEBUG = env.bool("DJANGO_DEBUG", default=False) + +# Allow Railway's domain and custom domains +ALLOWED_HOSTS = env.list( + "DJANGO_ALLOWED_HOSTS", + default=["localhost", ".railway.app", ".up.railway.app"] +) + +# DATABASES +# ------------------------------------------------------------------------------ +# Railway provides DATABASE_URL automatically when you add Postgres +# Falls back to SQLite for simpler setups +if env("DATABASE_URL", default=None): + DATABASES = { + "default": env.db("DATABASE_URL"), + } + DATABASES["default"]["ATOMIC_REQUESTS"] = True + DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=60) +else: + DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": ROOT_DIR / "db.sqlite3", + } + } + +# CACHES +# ------------------------------------------------------------------------------ +# Use local memory cache instead of Redis for simplicity +CACHES = { + "default": { + "BACKEND": "django.core.cache.backends.locmem.LocMemCache", + "LOCATION": "unique-snowflake", + } +} + +# SECURITY +# ------------------------------------------------------------------------------ +SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") +SECURE_SSL_REDIRECT = env.bool("DJANGO_SECURE_SSL_REDIRECT", default=True) +SESSION_COOKIE_SECURE = True +CSRF_COOKIE_SECURE = True +SECURE_HSTS_SECONDS = 60 +SECURE_HSTS_INCLUDE_SUBDOMAINS = True +SECURE_HSTS_PRELOAD = True +SECURE_CONTENT_TYPE_NOSNIFF = True + +# STATIC FILES (whitenoise) +# ------------------------------------------------------------------------------ +INSTALLED_APPS = ["whitenoise.runserver_nostatic"] + INSTALLED_APPS # noqa F405 +MIDDLEWARE.insert(1, "whitenoise.middleware.WhiteNoiseMiddleware") # After SecurityMiddleware + +STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" +STATIC_URL = "/static/" +STATIC_ROOT = ROOT_DIR / "staticfiles" + +# MEDIA FILES (local filesystem) +# ------------------------------------------------------------------------------ +# Media files stored in Railway volume at /app/mediafiles +# Sample audio copied from git on first deploy, user recordings persist in volume +MEDIA_URL = "/media/" +MEDIA_ROOT = env("MEDIA_ROOT", default="/app/mediafiles") + +# EMAIL +# ------------------------------------------------------------------------------ +# Use console backend for development/testing (emails print to console) +EMAIL_BACKEND = env( + "DJANGO_EMAIL_BACKEND", + default="django.core.mail.backends.console.EmailBackend" +) +DEFAULT_FROM_EMAIL = env( + "DJANGO_DEFAULT_FROM_EMAIL", + default="MusicCPR " +) + +# ADMIN +# ------------------------------------------------------------------------------ +ADMIN_URL = env("DJANGO_ADMIN_URL", default="admin/") + +# LOGGING +# ------------------------------------------------------------------------------ +LOGGING = { + "version": 1, + "disable_existing_loggers": False, + "formatters": { + "verbose": { + "format": "%(levelname)s %(asctime)s %(name)s %(message)s" + } + }, + "handlers": { + "console": { + "level": "DEBUG", + "class": "logging.StreamHandler", + "formatter": "verbose", + }, + }, + "root": {"level": "INFO", "handlers": ["console"]}, + "loggers": { + "django": { + "handlers": ["console"], + "level": "WARNING", + "propagate": False, + }, + "django.request": { + "handlers": ["console"], + "level": "ERROR", + "propagate": False, + }, + }, +} + +# CORS +# ------------------------------------------------------------------------------ +# Allow Vercel frontend domains +CORS_ALLOWED_ORIGIN_REGEXES = env.list( + "CORS_ALLOWED_ORIGINS_REGEX", + default=[ + r"^https://.*\.vercel\.app$", + r"^https://.*\.railway\.app$", + r"^http://localhost:\d+$", + r"^http://127\.0\.0\.1:\d+$", + ] +) + +# Also allow specific origins if set +CORS_ALLOWED_ORIGINS = env.list( + "CORS_ALLOWED_ORIGINS", + default=[] +) + +# CSRF trusted origins (needed for admin) +CSRF_TRUSTED_ORIGINS = env.list( + "CSRF_TRUSTED_ORIGINS", + default=["https://*.railway.app", "https://*.vercel.app"] +) diff --git a/config/urls.py b/config/urls.py index 57abde6..7791b43 100644 --- a/config/urls.py +++ b/config/urls.py @@ -1,15 +1,51 @@ +import os from django.conf import settings from django.conf.urls.static import static from django.contrib import admin from django.contrib.staticfiles.urls import staticfiles_urlpatterns -from django.urls import include, path +from django.urls import include, path, re_path from django.views import defaults as default_views from django.views.generic import TemplateView +from django.views.static import serve +from django.http import JsonResponse from teleband.users.api.views import obtain_delete_auth_token from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView + +def debug_media(request): + """Diagnostic endpoint to check media files.""" + import subprocess + result = { + "MEDIA_ROOT": str(settings.MEDIA_ROOT), + "MEDIA_ROOT_exists": os.path.exists(settings.MEDIA_ROOT), + "cwd": os.getcwd(), + } + + # List files in MEDIA_ROOT + if os.path.exists(settings.MEDIA_ROOT): + try: + files = [] + for root, dirs, filenames in os.walk(settings.MEDIA_ROOT): + for f in filenames[:20]: # Limit to first 20 + files.append(os.path.join(root, f).replace(settings.MEDIA_ROOT, "")) + result["files"] = files + result["file_count"] = sum(len(f) for _, _, f in os.walk(settings.MEDIA_ROOT)) + except Exception as e: + result["error"] = str(e) + else: + result["files"] = [] + + # Also check teleband/media + teleband_media = os.path.join(os.getcwd(), "teleband", "media") + result["teleband_media_exists"] = os.path.exists(teleband_media) + if os.path.exists(teleband_media): + result["teleband_media_count"] = sum(len(f) for _, _, f in os.walk(teleband_media)) + + return JsonResponse(result) + urlpatterns = [ path("", TemplateView.as_view(template_name="pages/home.html"), name="home"), + path("debug-media/", debug_media, name="debug-media"), path( "about/", TemplateView.as_view(template_name="pages/about.html"), name="about" ), @@ -26,7 +62,17 @@ SpectacularSwaggerView.as_view(url_name="schema"), name="swagger-ui", ), -] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + path("dashboards/", include("teleband.dashboards.urls", namespace="dashboards")), +] + +# Serve media files - in production with S3 this is handled by S3, +# but for Railway/local deployments we serve from filesystem +# Note: static() only works with DEBUG=True, so we use serve() directly for non-S3 deployments +if not hasattr(settings, 'DEFAULT_FILE_STORAGE') or 'S3' not in getattr(settings, 'DEFAULT_FILE_STORAGE', ''): + urlpatterns += [ + re_path(r'^media/(?P.*)$', serve, {'document_root': settings.MEDIA_ROOT}), + ] + if settings.DEBUG: # Static file serving when using Gunicorn + Uvicorn for local web socket development urlpatterns += staticfiles_urlpatterns() diff --git a/docs/downloaded.txt b/docs/downloaded.txt new file mode 100644 index 0000000..5e6e06b --- /dev/null +++ b/docs/downloaded.txt @@ -0,0 +1,479 @@ +-rw-r--r--@ 1 tgm staff 1016448 May 23 2023 /Users/tgm/Downloads/student-recoding_On2htn8.mp3 +-rw-r--r-- 1 tgm staff 770688 Sep 12 2023 /Users/tgm/Downloads/student-recoding_tuYzlxf.mp3 +-rw-r--r--@ 1 tgm staff 109824 Sep 25 2023 /Users/tgm/Downloads/student-recoding_5j5cdp3.mp3 +-rw-r--r--@ 1 tgm staff 455040 Sep 28 2023 /Users/tgm/Downloads/student-recoding_fIV5m2w.mp3 +-rw-r--r--@ 1 tgm staff 984192 Apr 10 23:37 /Users/tgm/Downloads/student-recoding_jFZziwb.mp3 +-rw-r--r--@ 1 tgm staff 974208 Apr 10 23:38 /Users/tgm/Downloads/student-recoding_W4BegrY.mp3 +-rw-r--r-- 1 tgm staff 770688 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_GVrg4i0.mp3 +-rw-r--r-- 1 tgm staff 1184256 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_o2nOi8z.mp3 +-rw-r--r-- 1 tgm staff 971904 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_Kz3PK8b.mp3 +-rw-r--r-- 1 tgm staff 779520 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_Ct3HOAB.mp3 +-rw-r--r-- 1 tgm staff 901632 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_q9RoQUL.mp3 +-rw-r--r-- 1 tgm staff 1008768 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_nNQqAQa.mp3 +-rw-r--r-- 1 tgm staff 966528 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_zvUrV9s.mp3 +-rw-r--r-- 1 tgm staff 970752 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_dfsFDCe.mp3 +-rw-r--r-- 1 tgm staff 987648 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_cJGiiHg.mp3 +-rw-r--r-- 1 tgm staff 923520 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_2Ab7E6k.mp3 +-rw-r--r-- 1 tgm staff 1020288 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_Fz95M8L.mp3 +-rw-r--r-- 1 tgm staff 747264 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_vvA8WCn.mp3 +-rw-r--r-- 1 tgm staff 939264 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_hlbzOyn.mp3 +-rw-r--r-- 1 tgm staff 880512 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_mDXD055.mp3 +-rw-r--r-- 1 tgm staff 980736 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_q3OLTYX.mp3 +-rw-r--r-- 1 tgm staff 1040256 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_9yTfTDc.mp3 +-rw-r--r-- 1 tgm staff 890880 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_Vrff3AR.mp3 +-rw-r--r-- 1 tgm staff 903552 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_IvWwZvs.mp3 +-rw-r--r-- 1 tgm staff 639360 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_ECQbzdc.mp3 +-rw-r--r-- 1 tgm staff 633216 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_mgbTZQ5.mp3 +-rw-r--r-- 1 tgm staff 575232 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_o0w7I2i.mp3 +-rw-r--r-- 1 tgm staff 714624 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_9q41nUa.mp3 +-rw-r--r-- 1 tgm staff 596352 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_nigns91.mp3 +-rw-r--r-- 1 tgm staff 983040 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_YgXCjdw.mp3 +-rw-r--r-- 1 tgm staff 571776 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_NSmKGLZ.mp3 +-rw-r--r-- 1 tgm staff 888576 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_yuhY7RQ.mp3 +-rw-r--r-- 1 tgm staff 574080 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_WwrWR2Y.mp3 +-rw-r--r-- 1 tgm staff 621696 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_H89ZppX.mp3 +-rw-r--r-- 1 tgm staff 649728 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_7HSdu1W.mp3 +-rw-r--r-- 1 tgm staff 683904 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_MZq7QYX.mp3 +-rw-r--r-- 1 tgm staff 843648 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_bZ6aNDw.mp3 +-rw-r--r-- 1 tgm staff 574080 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_DS9IoTu.mp3 +-rw-r--r-- 1 tgm staff 803328 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_xIsxoWJ.mp3 +-rw-r--r-- 1 tgm staff 782976 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_PIf0F0r.mp3 +-rw-r--r-- 1 tgm staff 984960 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_LQGEL2k.mp3 +-rw-r--r-- 1 tgm staff 675840 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_4ffAmpC.mp3 +-rw-r--r-- 1 tgm staff 435456 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_ITtSUdT.mp3 +-rw-r--r-- 1 tgm staff 680448 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_kbRTQ47.mp3 +-rw-r--r-- 1 tgm staff 882048 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_lI7nTGV.mp3 +-rw-r--r-- 1 tgm staff 615552 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_lYMRvRv.mp3 +-rw-r--r-- 1 tgm staff 559488 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_jrERcL3.mp3 +-rw-r--r-- 1 tgm staff 833280 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_iN0VnCG.mp3 +-rw-r--r-- 1 tgm staff 476544 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_G3vcexh.mp3 +-rw-r--r-- 1 tgm staff 907008 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_YhaE8he.mp3 +-rw-r--r-- 1 tgm staff 662784 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_clPknnv.mp3 +-rw-r--r-- 1 tgm staff 538368 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_rOsNeQh.mp3 +-rw-r--r-- 1 tgm staff 599424 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_iuP2KFm.mp3 +-rw-r--r-- 1 tgm staff 930432 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_HnHWseg.mp3 +-rw-r--r-- 1 tgm staff 961920 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_7Hvqcr4.mp3 +-rw-r--r-- 1 tgm staff 539136 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_1U8tj1W.mp3 +-rw-r--r-- 1 tgm staff 710016 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_PFTRGdO.mp3 +-rw-r--r-- 1 tgm staff 999936 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_dMWpv4i.mp3 +-rw-r--r-- 1 tgm staff 561024 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_2JKULZF.mp3 +-rw-r--r-- 1 tgm staff 520704 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_9wxiZK2.mp3 +-rw-r--r-- 1 tgm staff 875136 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_zTEMI37.mp3 +-rw-r--r-- 1 tgm staff 741888 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_VDyqi0o.mp3 +-rw-r--r-- 1 tgm staff 892800 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_fcNTpJk.mp3 +-rw-r--r-- 1 tgm staff 835584 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_EyXlNlC.mp3 +-rw-r--r-- 1 tgm staff 694272 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_QnV0mmy.mp3 +-rw-r--r-- 1 tgm staff 904320 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_LF1RBsb.mp3 +-rw-r--r-- 1 tgm staff 879744 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_4jGriN2.mp3 +-rw-r--r-- 1 tgm staff 986496 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_J9u3lpz.mp3 +-rw-r--r-- 1 tgm staff 52608 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_mbj5oXd.mp3 +-rw-r--r-- 1 tgm staff 639360 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_RToNE09.mp3 +-rw-r--r-- 1 tgm staff 964992 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_NFUbi0Z.mp3 +-rw-r--r-- 1 tgm staff 991104 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_BGy4Yx4.mp3 +-rw-r--r-- 1 tgm staff 832128 Jun 25 21:00 /Users/tgm/Downloads/student-recoding_NY8A3aJ.mp3 +-rw-r--r-- 1 tgm staff 1010304 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_8kzmRlv.mp3 +-rw-r--r-- 1 tgm staff 839040 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_QuzFCTY.mp3 +-rw-r--r-- 1 tgm staff 925440 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_ZSpsdOv.mp3 +-rw-r--r-- 1 tgm staff 773376 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_f1XXQvN.mp3 +-rw-r--r-- 1 tgm staff 968448 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_zrdrZ9V.mp3 +-rw-r--r-- 1 tgm staff 776064 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_4LAceJ0.mp3 +-rw-r--r-- 1 tgm staff 933888 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_rq4Ed4z.mp3 +-rw-r--r-- 1 tgm staff 890112 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_4mAu4tA.mp3 +-rw-r--r-- 1 tgm staff 546048 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_4qyooKJ.mp3 +-rw-r--r-- 1 tgm staff 83712 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_x47Vo0c.mp3 +-rw-r--r-- 1 tgm staff 499584 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_5EXnBJa.mp3 +-rw-r--r-- 1 tgm staff 129024 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_g1e0I4P.mp3 +-rw-r--r-- 1 tgm staff 352896 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_1h9yKm3.mp3 +-rw-r--r-- 1 tgm staff 953472 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_lDZCgMV.mp3 +-rw-r--r-- 1 tgm staff 185472 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_5i22Rg9.mp3 +-rw-r--r-- 1 tgm staff 997248 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_meSaxcp.mp3 +-rw-r--r-- 1 tgm staff 868224 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_ntCi9FU.mp3 +-rw-r--r-- 1 tgm staff 245760 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_3KMfLfZ.mp3 +-rw-r--r-- 1 tgm staff 918144 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_AiwNiu3.mp3 +-rw-r--r-- 1 tgm staff 477696 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_q7D73kW.mp3 +-rw-r--r-- 1 tgm staff 547968 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_QPe39SB.mp3 +-rw-r--r-- 1 tgm staff 478464 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_b4kxgTz.mp3 +-rw-r--r-- 1 tgm staff 965067 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_7tqpFAJ.mp3 +-rw-r--r-- 1 tgm staff 547200 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_GbZ8U8d.mp3 +-rw-r--r-- 1 tgm staff 913240 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_GHcvPQK.mp3 +-rw-r--r-- 1 tgm staff 603264 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_aiPaPKV.mp3 +-rw-r--r-- 1 tgm staff 883200 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_ig1u2fA.mp3 +-rw-r--r-- 1 tgm staff 559488 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_ZQxYZDe.mp3 +-rw-r--r-- 1 tgm staff 551424 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_lrGZoAR.mp3 +-rw-r--r-- 1 tgm staff 953364 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_jlAq6D1.mp3 +-rw-r--r-- 1 tgm staff 628608 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_iNhpZVt.mp3 +-rw-r--r-- 1 tgm staff 467328 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_g8LwlBM.mp3 +-rw-r--r-- 1 tgm staff 534528 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_Wmd2cfq.mp3 +-rw-r--r-- 1 tgm staff 964992 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_lrOQ2cb.mp3 +-rw-r--r-- 1 tgm staff 915456 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_zS5A2yj.mp3 +-rw-r--r-- 1 tgm staff 880512 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_sIRntXr.mp3 +-rw-r--r--@ 1 tgm staff 992640 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_d5JHLY5.mp3 +-rw-r--r-- 1 tgm staff 529536 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_67Xa737.mp3 +-rw-r--r-- 1 tgm staff 765696 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_tfCCggl.mp3 +-rw-r--r-- 1 tgm staff 974208 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_sjsiRpv.mp3 +-rw-r--r-- 1 tgm staff 931584 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_1jNacmn.mp3 +-rw-r--r-- 1 tgm staff 319488 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_0N89hwo.mp3 +-rw-r--r-- 1 tgm staff 608256 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_8e2Ecvb.mp3 +-rw-r--r-- 1 tgm staff 903552 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_OP0sLVG.mp3 +-rw-r--r-- 1 tgm staff 1006848 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_gZzQ6Hs.mp3 +-rw-r--r-- 1 tgm staff 678528 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_VlUTCih.mp3 +-rw-r--r-- 1 tgm staff 16128 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_vT44ic0.mp3 +-rw-r--r-- 1 tgm staff 786816 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_Rbd6YyS.mp3 +-rw-r--r-- 1 tgm staff 1021824 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_eZA8pg7.mp3 +-rw-r--r-- 1 tgm staff 202752 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_2NI98S3.mp3 +-rw-r--r-- 1 tgm staff 10752 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_URmKReI.mp3 +-rw-r--r-- 1 tgm staff 943488 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_8LjMG2n.mp3 +-rw-r--r-- 1 tgm staff 923520 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_1XSu26R.mp3 +-rw-r--r-- 1 tgm staff 789888 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_63gLiPw.mp3 +-rw-r--r-- 1 tgm staff 1003520 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_W3WAeRd.mp3 +-rw-r--r-- 1 tgm staff 850560 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_0T2wAVK.mp3 +-rw-r--r-- 1 tgm staff 1028736 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_WTjZnuS.mp3 +-rw-r--r-- 1 tgm staff 963456 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_KiFfNUT.mp3 +-rw-r--r-- 1 tgm staff 1011456 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_5Q8ZqIi.mp3 +-rw-r--r-- 1 tgm staff 1013551 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_6bEB7Mf.mp3 +-rw-r--r-- 1 tgm staff 1060608 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_YRxJLfV.mp3 +-rw-r--r-- 1 tgm staff 970752 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_BI0ww0u.mp3 +-rw-r--r-- 1 tgm staff 1011072 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_qrPPh93.mp3 +-rw-r--r-- 1 tgm staff 1002266 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_UYX4DVU.mp3 +-rw-r--r-- 1 tgm staff 995712 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_kQvJDuY.mp3 +-rw-r--r-- 1 tgm staff 1002266 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_sfe8vib.mp3 +-rw-r--r-- 1 tgm staff 728832 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_0KJabag.mp3 +-rw-r--r-- 1 tgm staff 983040 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_DNdBQQp.mp3 +-rw-r--r-- 1 tgm staff 983040 Jun 25 21:01 /Users/tgm/Downloads/student-recoding_tUyX2ta.mp3 +-rw-r--r-- 1 tgm staff 976896 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_f0Jub5t.mp3 +-rw-r--r-- 1 tgm staff 989568 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_5pr3RA6.mp3 +-rw-r--r-- 1 tgm staff 989568 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_9NHAEWc.mp3 +-rw-r--r-- 1 tgm staff 1042176 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_SdfrFBS.mp3 +-rw-r--r-- 1 tgm staff 960384 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_O4RbmJI.mp3 +-rw-r--r-- 1 tgm staff 997248 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_LrBm0Le.mp3 +-rw-r--r-- 1 tgm staff 753024 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_1uddeZF.mp3 +-rw-r--r-- 1 tgm staff 993489 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_ZfUS5h3.mp3 +-rw-r--r-- 1 tgm staff 911232 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_h4H9CVP.mp3 +-rw-r--r-- 1 tgm staff 1019904 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_beMcrJm.mp3 +-rw-r--r-- 1 tgm staff 704256 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_py3eSsR.mp3 +-rw-r--r-- 1 tgm staff 904320 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_hEtE6bi.mp3 +-rw-r--r-- 1 tgm staff 827904 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_MvYBgPj.mp3 +-rw-r--r-- 1 tgm staff 749568 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_87cXcWN.mp3 +-rw-r--r-- 1 tgm staff 754176 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_HyctO2g.mp3 +-rw-r--r-- 1 tgm staff 765312 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_kJdlKP4.mp3 +-rw-r--r-- 1 tgm staff 995328 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_LOVxw2H.mp3 +-rw-r--r-- 1 tgm staff 770688 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_q2DFdyD.mp3 +-rw-r--r-- 1 tgm staff 30720 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_nu3JDUz.mp3 +-rw-r--r-- 1 tgm staff 849792 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_kSBWFA2.mp3 +-rw-r--r-- 1 tgm staff 745344 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_ogbDA8X.mp3 +-rw-r--r-- 1 tgm staff 662784 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_PMyVTBb.mp3 +-rw-r--r-- 1 tgm staff 1003392 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_OU3YKjF.mp3 +-rw-r--r-- 1 tgm staff 600192 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_2CIr77U.mp3 +-rw-r--r-- 1 tgm staff 1006080 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_PSmcvDq.mp3 +-rw-r--r-- 1 tgm staff 649344 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_yU3aIrS.mp3 +-rw-r--r-- 1 tgm staff 1046400 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_Ot2RQih.mp3 +-rw-r--r-- 1 tgm staff 615552 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_QYtNE1F.mp3 +-rw-r--r-- 1 tgm staff 995328 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_7ZNGYFl.mp3 +-rw-r--r-- 1 tgm staff 544128 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_70djkh9.mp3 +-rw-r--r-- 1 tgm staff 529536 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_Vb4OzZl.mp3 +-rw-r--r-- 1 tgm staff 46464 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_tBzNjg0.mp3 +-rw-r--r-- 1 tgm staff 640896 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_5khMkmS.mp3 +-rw-r--r-- 1 tgm staff 771840 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_7DXkGZd.mp3 +-rw-r--r-- 1 tgm staff 978816 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_PU7ZF1C.mp3 +-rw-r--r-- 1 tgm staff 967575 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_089bMXx.mp3 +-rw-r--r-- 1 tgm staff 974208 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_9HdrhrI.mp3 +-rw-r--r-- 1 tgm staff 937482 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_VCQLR9I.mp3 +-rw-r--r-- 1 tgm staff 870912 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_FhtEO84.mp3 +-rw-r--r-- 1 tgm staff 690048 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_Qa4iBlm.mp3 +-rw-r--r-- 1 tgm staff 632832 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_0f0EoY2.mp3 +-rw-r--r-- 1 tgm staff 552960 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_UGX8dST.mp3 +-rw-r--r-- 1 tgm staff 660096 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_AZtIYcr.mp3 +-rw-r--r-- 1 tgm staff 990336 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_1eF5f48.mp3 +-rw-r--r-- 1 tgm staff 847872 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_HJlkWxa.mp3 +-rw-r--r-- 1 tgm staff 920064 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_Hf3BfZ5.mp3 +-rw-r--r-- 1 tgm staff 940826 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_9MoMNws.mp3 +-rw-r--r-- 1 tgm staff 1008117 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_dGxDly0.mp3 +-rw-r--r--@ 1 tgm staff 974208 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_1qZvgDh.mp3 +-rw-r--r-- 1 tgm staff 990720 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_uZx0jHN.mp3 +-rw-r--r-- 1 tgm staff 704256 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_no8giT7.mp3 +-rw-r--r-- 1 tgm staff 972672 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_1mwNhV4.mp3 +-rw-r--r-- 1 tgm staff 799104 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_93ojXag.mp3 +-rw-r--r-- 1 tgm staff 208896 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_XVsPSSK.mp3 +-rw-r--r-- 1 tgm staff 236928 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_mGCKtdY.mp3 +-rw-r--r-- 1 tgm staff 113280 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_Cl7O9OW.mp3 +-rw-r--r-- 1 tgm staff 1047168 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_6UrbBQj.mp3 +-rw-r--r-- 1 tgm staff 938496 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_D5gOMVM.mp3 +-rw-r--r-- 1 tgm staff 1027200 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_26BIF0h.mp3 +-rw-r--r-- 1 tgm staff 857472 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_vvHVCCc.mp3 +-rw-r--r-- 1 tgm staff 836736 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_9DzHQg7.mp3 +-rw-r--r-- 1 tgm staff 730368 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_B2iBnaM.mp3 +-rw-r--r-- 1 tgm staff 1244544 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_wODPfYZ.mp3 +-rw-r--r-- 1 tgm staff 968411 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_EcM9Uop.mp3 +-rw-r--r-- 1 tgm staff 1002266 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_qoOW9WH.mp3 +-rw-r--r-- 1 tgm staff 5015 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_0ge6z6R.mp3 +-rw-r--r-- 1 tgm staff 980114 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_yo6iFy2.mp3 +-rw-r--r-- 1 tgm staff 974592 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_FjAk2G5.mp3 +-rw-r--r-- 1 tgm staff 185155 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_RET7Rxc.mp3 +-rw-r--r-- 1 tgm staff 910464 Jun 25 21:02 /Users/tgm/Downloads/student-recoding_o6iGiC4.mp3 +-rw-r--r-- 1 tgm staff 1021056 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_ILfJJ4m.mp3 +-rw-r--r-- 1 tgm staff 955008 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_vddxWGc.mp3 +-rw-r--r-- 1 tgm staff 212736 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_a2IeMXA.mp3 +-rw-r--r-- 1 tgm staff 212352 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_eBihmLt.mp3 +-rw-r--r-- 1 tgm staff 215424 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_gbZtKVD.mp3 +-rw-r--r-- 1 tgm staff 199296 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_lpA6LMK.mp3 +-rw-r--r-- 1 tgm staff 227712 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_tyfzWkN.mp3 +-rw-r--r-- 1 tgm staff 212352 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_SHB8iAi.mp3 +-rw-r--r-- 1 tgm staff 93312 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_FeCZmWf.mp3 +-rw-r--r-- 1 tgm staff 201984 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_X3T0nIk.mp3 +-rw-r--r-- 1 tgm staff 255744 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_fSIg5zA.mp3 +-rw-r--r-- 1 tgm staff 215040 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_K3IwJIk.mp3 +-rw-r--r-- 1 tgm staff 231168 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_EnRQkLP.mp3 +-rw-r--r-- 1 tgm staff 1002624 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_BydEMbJ.mp3 +-rw-r--r-- 1 tgm staff 981504 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_kWzKpBl.mp3 +-rw-r--r-- 1 tgm staff 755712 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_BfWB6mB.mp3 +-rw-r--r-- 1 tgm staff 1027968 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_TvfrNwR.mp3 +-rw-r--r-- 1 tgm staff 872280 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_t7GIZ0P.mp3 +-rw-r--r-- 1 tgm staff 974208 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_pPOh9Ex.mp3 +-rw-r--r-- 1 tgm staff 950439 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_vOkFlXA.mp3 +-rw-r--r-- 1 tgm staff 662465 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_vgCUo3Q.mp3 +-rw-r--r-- 1 tgm staff 1017216 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_KUfHpH1.mp3 +-rw-r--r-- 1 tgm staff 969984 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_R3dYU5S.mp3 +-rw-r--r-- 1 tgm staff 228864 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_n2gNygK.mp3 +-rw-r--r-- 1 tgm staff 234624 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_rfBsHnm.mp3 +-rw-r--r-- 1 tgm staff 210432 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_60Mu47C.mp3 +-rw-r--r-- 1 tgm staff 203904 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_VmtZZkJ.mp3 +-rw-r--r-- 1 tgm staff 210048 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_hKqoTQd.mp3 +-rw-r--r-- 1 tgm staff 196992 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_qFsfJOR.mp3 +-rw-r--r-- 1 tgm staff 982272 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_D8sCnit.mp3 +-rw-r--r-- 1 tgm staff 995712 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_AKnzpYs.mp3 +-rw-r--r-- 1 tgm staff 488832 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_V0dCD8e.mp3 +-rw-r--r-- 1 tgm staff 418176 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_KDv1e0K.mp3 +-rw-r--r-- 1 tgm staff 995712 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_gKU8U7J.mp3 +-rw-r--r-- 1 tgm staff 862080 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_RN5Rbkq.mp3 +-rw-r--r-- 1 tgm staff 616071 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_Tbgob2j.mp3 +-rw-r--r-- 1 tgm staff 855562 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_ytSQixG.mp3 +-rw-r--r--@ 1 tgm staff 1143168 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_quepY3W.mp3 +-rw-r--r-- 1 tgm staff 979584 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_IvPwVMD.mp3 +-rw-r--r-- 1 tgm staff 989184 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_HgibjIZ.mp3 +-rw-r--r-- 1 tgm staff 995712 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_w473wIU.mp3 +-rw-r--r-- 1 tgm staff 227328 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_q1Nlyvl.mp3 +-rw-r--r-- 1 tgm staff 188928 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_fhkF6jd.mp3 +-rw-r--r-- 1 tgm staff 234624 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_0RkWk5v.mp3 +-rw-r--r-- 1 tgm staff 206592 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_JeLdkFz.mp3 +-rw-r--r-- 1 tgm staff 225792 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_2NAHwb5.mp3 +-rw-r--r-- 1 tgm staff 218496 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_dW62Tq4.mp3 +-rw-r--r-- 1 tgm staff 206592 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_CpfPgOU.mp3 +-rw-r--r-- 1 tgm staff 226560 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_GQTJU9E.mp3 +-rw-r--r-- 1 tgm staff 202368 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_8GyNdYN.mp3 +-rw-r--r-- 1 tgm staff 971136 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_CwKKPUG.mp3 +-rw-r--r-- 1 tgm staff 523392 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_TNlt17J.mp3 +-rw-r--r-- 1 tgm staff 864768 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_UDuhGf8.mp3 +-rw-r--r-- 1 tgm staff 870912 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_iZgoguV.mp3 +-rw-r--r-- 1 tgm staff 820992 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_KsWuXTy.mp3 +-rw-r--r-- 1 tgm staff 703872 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_58oCfns.mp3 +-rw-r--r-- 1 tgm staff 941184 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_BDQ8Kcx.mp3 +-rw-r--r-- 1 tgm staff 798720 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_qAEO1y1.mp3 +-rw-r--r-- 1 tgm staff 937900 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_6BzLGGJ.mp3 +-rw-r--r-- 1 tgm staff 961920 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_zxCSpaY.mp3 +-rw-r--r-- 1 tgm staff 979200 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_0CA7NvJ.mp3 +-rw-r--r-- 1 tgm staff 984960 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_CTvAlSm.mp3 +-rw-r--r-- 1 tgm staff 793728 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_pwav2tH.mp3 +-rw-r--r-- 1 tgm staff 967680 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_RZNHqvm.mp3 +-rw-r--r-- 1 tgm staff 484992 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_QeUGb6D.mp3 +-rw-r--r-- 1 tgm staff 683904 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_EQeErn5.mp3 +-rw-r--r-- 1 tgm staff 225792 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_TjD1Yxz.mp3 +-rw-r--r-- 1 tgm staff 198528 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_nQ21lG0.mp3 +-rw-r--r-- 1 tgm staff 239616 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_Wrv5Jr8.mp3 +-rw-r--r-- 1 tgm staff 1032192 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_E0xjWEs.mp3 +-rw-r--r-- 1 tgm staff 1021824 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_kKNjwy0.mp3 +-rw-r--r-- 1 tgm staff 212736 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_U1qysrf.mp3 +-rw-r--r-- 1 tgm staff 965903 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_poZySOm.mp3 +-rw-r--r-- 1 tgm staff 641664 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_gZOIlCc.mp3 +-rw-r--r-- 1 tgm staff 968448 Jun 25 21:03 /Users/tgm/Downloads/student-recoding_a3sSOiz.mp3 +-rw-r--r-- 1 tgm staff 806016 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_YFyany6.mp3 +-rw-r--r-- 1 tgm staff 962977 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_a136s08.mp3 +-rw-r--r-- 1 tgm staff 719616 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_c4oJ2B3.mp3 +-rw-r--r-- 1 tgm staff 972672 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_xau7cin.mp3 +-rw-r--r-- 1 tgm staff 776064 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_DDXCiqT.mp3 +-rw-r--r-- 1 tgm staff 977280 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_m5xAmMq.mp3 +-rw-r--r-- 1 tgm staff 987219 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_pTPbmRL.mp3 +-rw-r--r-- 1 tgm staff 598656 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_HndNzR8.mp3 +-rw-r--r-- 1 tgm staff 217728 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_UELlRTs.mp3 +-rw-r--r-- 1 tgm staff 220416 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_dPcvDXB.mp3 +-rw-r--r-- 1 tgm staff 208128 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_WGeuOua.mp3 +-rw-r--r-- 1 tgm staff 249216 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_V1pgnC8.mp3 +-rw-r--r-- 1 tgm staff 166656 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_Ul6dqw7.mp3 +-rw-r--r-- 1 tgm staff 212352 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_fY94tC7.mp3 +-rw-r--r-- 1 tgm staff 991872 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_Q01D4yh.mp3 +-rw-r--r-- 1 tgm staff 1036032 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_irPOZAb.mp3 +-rw-r--r-- 1 tgm staff 1009536 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_ohSdfhB.mp3 +-rw-r--r-- 1 tgm staff 964608 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_53XSzDi.mp3 +-rw-r--r-- 1 tgm staff 978442 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_4mpSiKk.mp3 +-rw-r--r-- 1 tgm staff 952946 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_rWw0QlW.mp3 +-rw-r--r-- 1 tgm staff 985129 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_LajEAG5.mp3 +-rw-r--r-- 1 tgm staff 208128 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_s6nYuHz.mp3 +-rw-r--r-- 1 tgm staff 227712 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_Ce3cwlO.mp3 +-rw-r--r-- 1 tgm staff 208128 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_uK27rhX.mp3 +-rw-r--r-- 1 tgm staff 195840 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_aLNRyGD.mp3 +-rw-r--r-- 1 tgm staff 223872 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_ExCvq4C.mp3 +-rw-r--r-- 1 tgm staff 210048 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_788cRiU.mp3 +-rw-r--r-- 1 tgm staff 216960 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_Pg5xpdq.mp3 +-rw-r--r-- 1 tgm staff 207360 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_DlfAd5e.mp3 +-rw-r--r-- 1 tgm staff 210816 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_JKe3vDO.mp3 +-rw-r--r-- 1 tgm staff 202752 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_kaMWEpB.mp3 +-rw-r--r-- 1 tgm staff 214272 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_dzF09LG.mp3 +-rw-r--r-- 1 tgm staff 201216 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_vTmDKBR.mp3 +-rw-r--r-- 1 tgm staff 212352 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_KBn2btU.mp3 +-rw-r--r-- 1 tgm staff 228480 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_2ZeAu7A.mp3 +-rw-r--r-- 1 tgm staff 210048 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_9dtHrDQ.mp3 +-rw-r--r-- 1 tgm staff 218112 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_wMEVifG.mp3 +-rw-r--r-- 1 tgm staff 214272 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_2VSsaYn.mp3 +-rw-r--r-- 1 tgm staff 192384 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_NVz9VD3.mp3 +-rw-r--r-- 1 tgm staff 202752 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_dEydYZp.mp3 +-rw-r--r-- 1 tgm staff 216960 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_KTzx1tD.mp3 +-rw-r--r-- 1 tgm staff 249216 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_AQK3nA5.mp3 +-rw-r--r-- 1 tgm staff 205824 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_kCM4ESf.mp3 +-rw-r--r-- 1 tgm staff 212352 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_FrWCYMR.mp3 +-rw-r--r-- 1 tgm staff 217728 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_SWVBaS1.mp3 +-rw-r--r-- 1 tgm staff 209664 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_ICc8onS.mp3 +-rw-r--r-- 1 tgm staff 242688 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_MtdsLgE.mp3 +-rw-r--r-- 1 tgm staff 264192 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_3WhpjMh.mp3 +-rw-r--r-- 1 tgm staff 209280 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_1vXTCVP.mp3 +-rw-r--r-- 1 tgm staff 211968 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_SscRfN9.mp3 +-rw-r--r-- 1 tgm staff 205440 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_UXtlceZ.mp3 +-rw-r--r-- 1 tgm staff 217728 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_3dkMCbc.mp3 +-rw-r--r-- 1 tgm staff 231936 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_vBlq9OP.mp3 +-rw-r--r-- 1 tgm staff 205440 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_Q9mr3UD.mp3 +-rw-r--r-- 1 tgm staff 206976 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_uZJyd2q.mp3 +-rw-r--r-- 1 tgm staff 202752 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_EE1ZtlM.mp3 +-rw-r--r-- 1 tgm staff 203136 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_Uv3ZxNI.mp3 +-rw-r--r-- 1 tgm staff 197760 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_z8oOlF4.mp3 +-rw-r--r-- 1 tgm staff 228480 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_E3ySeFX.mp3 +-rw-r--r-- 1 tgm staff 206976 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_DvlgTbG.mp3 +-rw-r--r-- 1 tgm staff 200448 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_zwSfg84.mp3 +-rw-r--r-- 1 tgm staff 207360 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_uWHcE4s.mp3 +-rw-r--r-- 1 tgm staff 964992 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_Mac3gji.mp3 +-rw-r--r-- 1 tgm staff 905856 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_NfVrW2H.mp3 +-rw-r--r-- 1 tgm staff 983040 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_abPjq2w.mp3 +-rw-r--r-- 1 tgm staff 981504 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_q7bKQlL.mp3 +-rw-r--r-- 1 tgm staff 621312 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_H22pxxQ.mp3 +-rw-r--r-- 1 tgm staff 995712 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_Fh4Om6Z.mp3 +-rw-r--r-- 1 tgm staff 987648 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_9fLVFvx.mp3 +-rw-r--r-- 1 tgm staff 879744 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_01B0rat.mp3 +-rw-r--r-- 1 tgm staff 992640 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_Y9t3Q0I.mp3 +-rw-r--r-- 1 tgm staff 597888 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_3oJv5oR.mp3 +-rw-r--r-- 1 tgm staff 866688 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_PadYlYv.mp3 +-rw-r--r-- 1 tgm staff 592512 Jun 25 21:04 /Users/tgm/Downloads/student-recoding_JKQrrpi.mp3 +-rw-r--r-- 1 tgm staff 702336 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_X66j8cE.mp3 +-rw-r--r-- 1 tgm staff 814848 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_HFjBHLH.mp3 +-rw-r--r-- 1 tgm staff 844416 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_a3PlE3m.mp3 +-rw-r--r-- 1 tgm staff 930432 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_9W5vJk7.mp3 +-rw-r--r-- 1 tgm staff 481920 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_g9rkd86.mp3 +-rw-r--r-- 1 tgm staff 996480 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_coKprRH.mp3 +-rw-r--r-- 1 tgm staff 1000704 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_2hcZh0p.mp3 +-rw-r--r-- 1 tgm staff 953472 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_vM6NsKj.mp3 +-rw-r--r-- 1 tgm staff 900480 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_UDL9AFg.mp3 +-rw-r--r-- 1 tgm staff 1090944 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_bF5q5kq.mp3 +-rw-r--r-- 1 tgm staff 1012224 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_I9IBGuU.mp3 +-rw-r--r-- 1 tgm staff 1014144 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_KJEvQpG.mp3 +-rw-r--r-- 1 tgm staff 590208 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_f7Ttc29.mp3 +-rw-r--r-- 1 tgm staff 968064 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_8gqTpAF.mp3 +-rw-r--r-- 1 tgm staff 641664 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_yQwM60W.mp3 +-rw-r--r-- 1 tgm staff 995328 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_vzHp1Bx.mp3 +-rw-r--r-- 1 tgm staff 882432 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_a95LhlN.mp3 +-rw-r--r-- 1 tgm staff 946176 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_T0VwsI4.mp3 +-rw-r--r-- 1 tgm staff 969216 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_d0ICqx6.mp3 +-rw-r--r-- 1 tgm staff 1008000 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_lk6cTfz.mp3 +-rw-r--r-- 1 tgm staff 982272 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_hf57sqv.mp3 +-rw-r--r-- 1 tgm staff 971136 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_4EcTasa.mp3 +-rw-r--r-- 1 tgm staff 792960 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_Zx0ACbj.mp3 +-rw-r--r-- 1 tgm staff 1008768 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_pCZh1vJ.mp3 +-rw-r--r-- 1 tgm staff 676224 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_irE2bar.mp3 +-rw-r--r-- 1 tgm staff 530304 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_eEC6zuK.mp3 +-rw-r--r-- 1 tgm staff 943488 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_BqGrYAm.mp3 +-rw-r--r-- 1 tgm staff 1051776 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_rl3qmpt.mp3 +-rw-r--r-- 1 tgm staff 972672 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_Fz99q0Y.mp3 +-rw-r--r-- 1 tgm staff 1070208 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_V4HUZ1d.mp3 +-rw-r--r-- 1 tgm staff 898176 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_APgM42M.mp3 +-rw-r--r-- 1 tgm staff 1336704 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_minqdP2.mp3 +-rw-r--r-- 1 tgm staff 732288 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_HrwXi8F.mp3 +-rw-r--r-- 1 tgm staff 761088 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_l0kHWmg.mp3 +-rw-r--r-- 1 tgm staff 926976 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_713h2EN.mp3 +-rw-r--r-- 1 tgm staff 823296 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_Z7XDgRF.mp3 +-rw-r--r-- 1 tgm staff 909312 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_m7f5T9b.mp3 +-rw-r--r-- 1 tgm staff 746880 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_hT2kRT1.mp3 +-rw-r--r-- 1 tgm staff 761856 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_Wli0U2f.mp3 +-rw-r--r-- 1 tgm staff 702336 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_YoU6R2X.mp3 +-rw-r--r-- 1 tgm staff 726144 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_qk3pfZp.mp3 +-rw-r--r-- 1 tgm staff 774144 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_mUyuW71.mp3 +-rw-r--r-- 1 tgm staff 789888 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_QG8MDhH.mp3 +-rw-r--r-- 1 tgm staff 736512 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_xExjXsG.mp3 +-rw-r--r-- 1 tgm staff 883968 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_WOp1AXU.mp3 +-rw-r--r-- 1 tgm staff 778752 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_69mqarK.mp3 +-rw-r--r-- 1 tgm staff 803328 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_FhMbuFp.mp3 +-rw-r--r-- 1 tgm staff 735744 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_5oSc6sP.mp3 +-rw-r--r-- 1 tgm staff 677760 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_woM3EKE.mp3 +-rw-r--r-- 1 tgm staff 955776 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_Q68FwdB.mp3 +-rw-r--r-- 1 tgm staff 1011456 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_clckAJz.mp3 +-rw-r--r-- 1 tgm staff 971136 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_mxZdfvS.mp3 +-rw-r--r-- 1 tgm staff 933120 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_61INJdi.mp3 +-rw-r--r-- 1 tgm staff 1054464 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_Uhb4n5W.mp3 +-rw-r--r-- 1 tgm staff 964608 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_azisqUR.mp3 +-rw-r--r-- 1 tgm staff 994560 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_H9nxQIj.mp3 +-rw-r--r-- 1 tgm staff 786816 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_qe7TXo1.mp3 +-rw-r--r-- 1 tgm staff 126720 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_B8hy0OV.mp3 +-rw-r--r-- 1 tgm staff 1096320 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_c5Wz4fi.mp3 +-rw-r--r-- 1 tgm staff 937344 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_TyY0KJy.mp3 +-rw-r--r-- 1 tgm staff 956928 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_HEJXMxi.mp3 +-rw-r--r-- 1 tgm staff 842880 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_aMyPS6p.mp3 +-rw-r--r-- 1 tgm staff 990336 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_rB4iZmo.mp3 +-rw-r--r-- 1 tgm staff 1014144 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_w8Vnm6O.mp3 +-rw-r--r-- 1 tgm staff 970752 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_bUOWBCr.mp3 +-rw-r--r-- 1 tgm staff 995712 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_1SV9Gyl.mp3 +-rw-r--r-- 1 tgm staff 980736 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_wgItPfW.mp3 +-rw-r--r-- 1 tgm staff 1039488 Jun 25 21:05 /Users/tgm/Downloads/student-recoding_AX2qlrP.mp3 +-rw-r--r-- 1 tgm staff 942720 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_i5LN44D.mp3 +-rw-r--r-- 1 tgm staff 994560 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_STa1TfL.mp3 +-rw-r--r-- 1 tgm staff 666240 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_S3N3XX2.mp3 +-rw-r--r-- 1 tgm staff 999936 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_zPt3VCd.mp3 +-rw-r--r-- 1 tgm staff 968448 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_VP8O7L2.mp3 +-rw-r--r-- 1 tgm staff 964608 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_y5aHCM0.mp3 +-rw-r--r-- 1 tgm staff 981504 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_6ZFNyWP.mp3 +-rw-r--r-- 1 tgm staff 977280 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_fin2jOc.mp3 +-rw-r--r-- 1 tgm staff 1022592 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_bDw1Ieu.mp3 +-rw-r--r-- 1 tgm staff 979584 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_NGfHyE0.mp3 +-rw-r--r-- 1 tgm staff 880512 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_MWMonCB.mp3 +-rw-r--r-- 1 tgm staff 1012992 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_fUodLW1.mp3 +-rw-r--r-- 1 tgm staff 759552 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_FIvY7ek.mp3 +-rw-r--r-- 1 tgm staff 786432 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_QTy0XK6.mp3 +-rw-r--r-- 1 tgm staff 757632 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_CsKRC3d.mp3 +-rw-r--r-- 1 tgm staff 716544 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_zBn16gb.mp3 +-rw-r--r-- 1 tgm staff 786816 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_aKUZzgV.mp3 +-rw-r--r-- 1 tgm staff 723456 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_Nn0E4GM.mp3 +-rw-r--r-- 1 tgm staff 912000 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_RgXw8V3.mp3 +-rw-r--r-- 1 tgm staff 256512 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_3JX9zVR.mp3 +-rw-r--r-- 1 tgm staff 207744 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_85OhYrk.mp3 +-rw-r--r-- 1 tgm staff 206592 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_wW5Tlr4.mp3 +-rw-r--r-- 1 tgm staff 198528 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_RKdCxIR.mp3 +-rw-r--r-- 1 tgm staff 261888 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_KRaa5RI.mp3 +-rw-r--r-- 1 tgm staff 199296 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_BwxcGFA.mp3 +-rw-r--r-- 1 tgm staff 197760 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_Yv77pkT.mp3 +-rw-r--r-- 1 tgm staff 241152 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_EMZtbyE.mp3 +-rw-r--r-- 1 tgm staff 210432 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_MKTEWDr.mp3 +-rw-r--r-- 1 tgm staff 203136 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_vJM5vvd.mp3 +-rw-r--r-- 1 tgm staff 206592 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_Jj7EXMZ.mp3 +-rw-r--r-- 1 tgm staff 134400 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_anmRal0.mp3 +-rw-r--r-- 1 tgm staff 201216 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_xP9St0V.mp3 +-rw-r--r-- 1 tgm staff 210816 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_kY7Z2IW.mp3 +-rw-r--r-- 1 tgm staff 211584 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_oD05qjx.mp3 +-rw-r--r-- 1 tgm staff 203904 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_FPKqu8f.mp3 +-rw-r--r-- 1 tgm staff 215424 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_44rgV3m.mp3 +-rw-r--r-- 1 tgm staff 200448 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_V4FXfTr.mp3 +-rw-r--r-- 1 tgm staff 205440 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_wUy1BL6.mp3 +-rw-r--r-- 1 tgm staff 1004928 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_jgPyGhd.mp3 +-rw-r--r-- 1 tgm staff 991104 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_erzzTdH.mp3 +-rw-r--r-- 1 tgm staff 980736 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_Uez7rCa.mp3 +-rw-r--r-- 1 tgm staff 1023744 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_KCDidv9.mp3 +-rw-r--r-- 1 tgm staff 1052544 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_eDjVvuf.mp3 +-rw-r--r-- 1 tgm staff 1036800 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_9ZqYXE4.mp3 +-rw-r--r-- 1 tgm staff 999936 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_ZXNZAmu.mp3 +-rw-r--r-- 1 tgm staff 1006080 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_4sZfsww.mp3 +-rw-r--r-- 1 tgm staff 972672 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_ay0Bp4x.mp3 +-rw-r--r-- 1 tgm staff 951693 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_Mlc8XFL.mp3 +-rw-r--r-- 1 tgm staff 1004160 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_67loKRY.mp3 +-rw-r--r-- 1 tgm staff 993024 Jun 25 21:06 /Users/tgm/Downloads/student-recoding_HS7nK7l.mp3 diff --git a/docs/get_recordings-from-s3.sh b/docs/get_recordings-from-s3.sh new file mode 100755 index 0000000..bc2ec83 --- /dev/null +++ b/docs/get_recordings-from-s3.sh @@ -0,0 +1,474 @@ +#!/usr/bin/env bash +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_GVrg4i0.mp3 ~/Downloads/student-recoding_GVrg4i0.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_o2nOi8z.mp3 ~/Downloads/student-recoding_o2nOi8z.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Kz3PK8b.mp3 ~/Downloads/student-recoding_Kz3PK8b.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Ct3HOAB.mp3 ~/Downloads/student-recoding_Ct3HOAB.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_q9RoQUL.mp3 ~/Downloads/student-recoding_q9RoQUL.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_nNQqAQa.mp3 ~/Downloads/student-recoding_nNQqAQa.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_zvUrV9s.mp3 ~/Downloads/student-recoding_zvUrV9s.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_dfsFDCe.mp3 ~/Downloads/student-recoding_dfsFDCe.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_cJGiiHg.mp3 ~/Downloads/student-recoding_cJGiiHg.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_2Ab7E6k.mp3 ~/Downloads/student-recoding_2Ab7E6k.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Fz95M8L.mp3 ~/Downloads/student-recoding_Fz95M8L.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_vvA8WCn.mp3 ~/Downloads/student-recoding_vvA8WCn.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_hlbzOyn.mp3 ~/Downloads/student-recoding_hlbzOyn.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_mDXD055.mp3 ~/Downloads/student-recoding_mDXD055.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_q3OLTYX.mp3 ~/Downloads/student-recoding_q3OLTYX.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_9yTfTDc.mp3 ~/Downloads/student-recoding_9yTfTDc.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Vrff3AR.mp3 ~/Downloads/student-recoding_Vrff3AR.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_IvWwZvs.mp3 ~/Downloads/student-recoding_IvWwZvs.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ECQbzdc.mp3 ~/Downloads/student-recoding_ECQbzdc.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_mgbTZQ5.mp3 ~/Downloads/student-recoding_mgbTZQ5.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_o0w7I2i.mp3 ~/Downloads/student-recoding_o0w7I2i.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_9q41nUa.mp3 ~/Downloads/student-recoding_9q41nUa.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_nigns91.mp3 ~/Downloads/student-recoding_nigns91.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_YgXCjdw.mp3 ~/Downloads/student-recoding_YgXCjdw.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_NSmKGLZ.mp3 ~/Downloads/student-recoding_NSmKGLZ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_yuhY7RQ.mp3 ~/Downloads/student-recoding_yuhY7RQ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_WwrWR2Y.mp3 ~/Downloads/student-recoding_WwrWR2Y.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_H89ZppX.mp3 ~/Downloads/student-recoding_H89ZppX.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_7HSdu1W.mp3 ~/Downloads/student-recoding_7HSdu1W.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_MZq7QYX.mp3 ~/Downloads/student-recoding_MZq7QYX.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_bZ6aNDw.mp3 ~/Downloads/student-recoding_bZ6aNDw.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_DS9IoTu.mp3 ~/Downloads/student-recoding_DS9IoTu.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_xIsxoWJ.mp3 ~/Downloads/student-recoding_xIsxoWJ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_PIf0F0r.mp3 ~/Downloads/student-recoding_PIf0F0r.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_LQGEL2k.mp3 ~/Downloads/student-recoding_LQGEL2k.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_4ffAmpC.mp3 ~/Downloads/student-recoding_4ffAmpC.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ITtSUdT.mp3 ~/Downloads/student-recoding_ITtSUdT.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_kbRTQ47.mp3 ~/Downloads/student-recoding_kbRTQ47.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_lI7nTGV.mp3 ~/Downloads/student-recoding_lI7nTGV.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_lYMRvRv.mp3 ~/Downloads/student-recoding_lYMRvRv.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_jrERcL3.mp3 ~/Downloads/student-recoding_jrERcL3.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_iN0VnCG.mp3 ~/Downloads/student-recoding_iN0VnCG.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_G3vcexh.mp3 ~/Downloads/student-recoding_G3vcexh.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_YhaE8he.mp3 ~/Downloads/student-recoding_YhaE8he.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_clPknnv.mp3 ~/Downloads/student-recoding_clPknnv.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_rOsNeQh.mp3 ~/Downloads/student-recoding_rOsNeQh.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_iuP2KFm.mp3 ~/Downloads/student-recoding_iuP2KFm.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_HnHWseg.mp3 ~/Downloads/student-recoding_HnHWseg.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_7Hvqcr4.mp3 ~/Downloads/student-recoding_7Hvqcr4.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_1U8tj1W.mp3 ~/Downloads/student-recoding_1U8tj1W.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_PFTRGdO.mp3 ~/Downloads/student-recoding_PFTRGdO.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_dMWpv4i.mp3 ~/Downloads/student-recoding_dMWpv4i.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_2JKULZF.mp3 ~/Downloads/student-recoding_2JKULZF.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_9wxiZK2.mp3 ~/Downloads/student-recoding_9wxiZK2.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_zTEMI37.mp3 ~/Downloads/student-recoding_zTEMI37.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_VDyqi0o.mp3 ~/Downloads/student-recoding_VDyqi0o.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_fcNTpJk.mp3 ~/Downloads/student-recoding_fcNTpJk.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_EyXlNlC.mp3 ~/Downloads/student-recoding_EyXlNlC.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_QnV0mmy.mp3 ~/Downloads/student-recoding_QnV0mmy.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_LF1RBsb.mp3 ~/Downloads/student-recoding_LF1RBsb.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_4jGriN2.mp3 ~/Downloads/student-recoding_4jGriN2.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_J9u3lpz.mp3 ~/Downloads/student-recoding_J9u3lpz.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_mbj5oXd.mp3 ~/Downloads/student-recoding_mbj5oXd.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_RToNE09.mp3 ~/Downloads/student-recoding_RToNE09.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_NFUbi0Z.mp3 ~/Downloads/student-recoding_NFUbi0Z.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_BGy4Yx4.mp3 ~/Downloads/student-recoding_BGy4Yx4.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_NY8A3aJ.mp3 ~/Downloads/student-recoding_NY8A3aJ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_8kzmRlv.mp3 ~/Downloads/student-recoding_8kzmRlv.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_QuzFCTY.mp3 ~/Downloads/student-recoding_QuzFCTY.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ZSpsdOv.mp3 ~/Downloads/student-recoding_ZSpsdOv.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_f1XXQvN.mp3 ~/Downloads/student-recoding_f1XXQvN.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_zrdrZ9V.mp3 ~/Downloads/student-recoding_zrdrZ9V.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_4LAceJ0.mp3 ~/Downloads/student-recoding_4LAceJ0.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_rq4Ed4z.mp3 ~/Downloads/student-recoding_rq4Ed4z.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_4mAu4tA.mp3 ~/Downloads/student-recoding_4mAu4tA.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_4qyooKJ.mp3 ~/Downloads/student-recoding_4qyooKJ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_x47Vo0c.mp3 ~/Downloads/student-recoding_x47Vo0c.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_5EXnBJa.mp3 ~/Downloads/student-recoding_5EXnBJa.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_g1e0I4P.mp3 ~/Downloads/student-recoding_g1e0I4P.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_1h9yKm3.mp3 ~/Downloads/student-recoding_1h9yKm3.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_lDZCgMV.mp3 ~/Downloads/student-recoding_lDZCgMV.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_5i22Rg9.mp3 ~/Downloads/student-recoding_5i22Rg9.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_meSaxcp.mp3 ~/Downloads/student-recoding_meSaxcp.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ntCi9FU.mp3 ~/Downloads/student-recoding_ntCi9FU.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_3KMfLfZ.mp3 ~/Downloads/student-recoding_3KMfLfZ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_AiwNiu3.mp3 ~/Downloads/student-recoding_AiwNiu3.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_q7D73kW.mp3 ~/Downloads/student-recoding_q7D73kW.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_QPe39SB.mp3 ~/Downloads/student-recoding_QPe39SB.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_b4kxgTz.mp3 ~/Downloads/student-recoding_b4kxgTz.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_7tqpFAJ.mp3 ~/Downloads/student-recoding_7tqpFAJ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_GbZ8U8d.mp3 ~/Downloads/student-recoding_GbZ8U8d.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_GHcvPQK.mp3 ~/Downloads/student-recoding_GHcvPQK.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_aiPaPKV.mp3 ~/Downloads/student-recoding_aiPaPKV.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ig1u2fA.mp3 ~/Downloads/student-recoding_ig1u2fA.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ZQxYZDe.mp3 ~/Downloads/student-recoding_ZQxYZDe.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_lrGZoAR.mp3 ~/Downloads/student-recoding_lrGZoAR.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_jlAq6D1.mp3 ~/Downloads/student-recoding_jlAq6D1.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_iNhpZVt.mp3 ~/Downloads/student-recoding_iNhpZVt.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_g8LwlBM.mp3 ~/Downloads/student-recoding_g8LwlBM.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Wmd2cfq.mp3 ~/Downloads/student-recoding_Wmd2cfq.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_lrOQ2cb.mp3 ~/Downloads/student-recoding_lrOQ2cb.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_zS5A2yj.mp3 ~/Downloads/student-recoding_zS5A2yj.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_sIRntXr.mp3 ~/Downloads/student-recoding_sIRntXr.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_d5JHLY5.mp3 ~/Downloads/student-recoding_d5JHLY5.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_67Xa737.mp3 ~/Downloads/student-recoding_67Xa737.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_tfCCggl.mp3 ~/Downloads/student-recoding_tfCCggl.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_sjsiRpv.mp3 ~/Downloads/student-recoding_sjsiRpv.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_1jNacmn.mp3 ~/Downloads/student-recoding_1jNacmn.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_0N89hwo.mp3 ~/Downloads/student-recoding_0N89hwo.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_8e2Ecvb.mp3 ~/Downloads/student-recoding_8e2Ecvb.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_OP0sLVG.mp3 ~/Downloads/student-recoding_OP0sLVG.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_gZzQ6Hs.mp3 ~/Downloads/student-recoding_gZzQ6Hs.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_VlUTCih.mp3 ~/Downloads/student-recoding_VlUTCih.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_vT44ic0.mp3 ~/Downloads/student-recoding_vT44ic0.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Rbd6YyS.mp3 ~/Downloads/student-recoding_Rbd6YyS.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_eZA8pg7.mp3 ~/Downloads/student-recoding_eZA8pg7.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_2NI98S3.mp3 ~/Downloads/student-recoding_2NI98S3.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_URmKReI.mp3 ~/Downloads/student-recoding_URmKReI.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_8LjMG2n.mp3 ~/Downloads/student-recoding_8LjMG2n.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_1XSu26R.mp3 ~/Downloads/student-recoding_1XSu26R.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_63gLiPw.mp3 ~/Downloads/student-recoding_63gLiPw.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_W3WAeRd.mp3 ~/Downloads/student-recoding_W3WAeRd.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_0T2wAVK.mp3 ~/Downloads/student-recoding_0T2wAVK.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_WTjZnuS.mp3 ~/Downloads/student-recoding_WTjZnuS.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_KiFfNUT.mp3 ~/Downloads/student-recoding_KiFfNUT.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_5Q8ZqIi.mp3 ~/Downloads/student-recoding_5Q8ZqIi.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_6bEB7Mf.mp3 ~/Downloads/student-recoding_6bEB7Mf.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_YRxJLfV.mp3 ~/Downloads/student-recoding_YRxJLfV.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_BI0ww0u.mp3 ~/Downloads/student-recoding_BI0ww0u.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_qrPPh93.mp3 ~/Downloads/student-recoding_qrPPh93.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_UYX4DVU.mp3 ~/Downloads/student-recoding_UYX4DVU.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_kQvJDuY.mp3 ~/Downloads/student-recoding_kQvJDuY.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_sfe8vib.mp3 ~/Downloads/student-recoding_sfe8vib.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_0KJabag.mp3 ~/Downloads/student-recoding_0KJabag.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_DNdBQQp.mp3 ~/Downloads/student-recoding_DNdBQQp.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_tUyX2ta.mp3 ~/Downloads/student-recoding_tUyX2ta.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_f0Jub5t.mp3 ~/Downloads/student-recoding_f0Jub5t.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_5pr3RA6.mp3 ~/Downloads/student-recoding_5pr3RA6.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_9NHAEWc.mp3 ~/Downloads/student-recoding_9NHAEWc.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_SdfrFBS.mp3 ~/Downloads/student-recoding_SdfrFBS.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_O4RbmJI.mp3 ~/Downloads/student-recoding_O4RbmJI.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_LrBm0Le.mp3 ~/Downloads/student-recoding_LrBm0Le.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_1uddeZF.mp3 ~/Downloads/student-recoding_1uddeZF.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ZfUS5h3.mp3 ~/Downloads/student-recoding_ZfUS5h3.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_h4H9CVP.mp3 ~/Downloads/student-recoding_h4H9CVP.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_beMcrJm.mp3 ~/Downloads/student-recoding_beMcrJm.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_py3eSsR.mp3 ~/Downloads/student-recoding_py3eSsR.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_hEtE6bi.mp3 ~/Downloads/student-recoding_hEtE6bi.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_MvYBgPj.mp3 ~/Downloads/student-recoding_MvYBgPj.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_87cXcWN.mp3 ~/Downloads/student-recoding_87cXcWN.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_HyctO2g.mp3 ~/Downloads/student-recoding_HyctO2g.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_kJdlKP4.mp3 ~/Downloads/student-recoding_kJdlKP4.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_LOVxw2H.mp3 ~/Downloads/student-recoding_LOVxw2H.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_q2DFdyD.mp3 ~/Downloads/student-recoding_q2DFdyD.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_nu3JDUz.mp3 ~/Downloads/student-recoding_nu3JDUz.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_kSBWFA2.mp3 ~/Downloads/student-recoding_kSBWFA2.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ogbDA8X.mp3 ~/Downloads/student-recoding_ogbDA8X.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_PMyVTBb.mp3 ~/Downloads/student-recoding_PMyVTBb.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_OU3YKjF.mp3 ~/Downloads/student-recoding_OU3YKjF.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_2CIr77U.mp3 ~/Downloads/student-recoding_2CIr77U.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_PSmcvDq.mp3 ~/Downloads/student-recoding_PSmcvDq.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_yU3aIrS.mp3 ~/Downloads/student-recoding_yU3aIrS.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Ot2RQih.mp3 ~/Downloads/student-recoding_Ot2RQih.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_QYtNE1F.mp3 ~/Downloads/student-recoding_QYtNE1F.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_7ZNGYFl.mp3 ~/Downloads/student-recoding_7ZNGYFl.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_70djkh9.mp3 ~/Downloads/student-recoding_70djkh9.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Vb4OzZl.mp3 ~/Downloads/student-recoding_Vb4OzZl.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_tBzNjg0.mp3 ~/Downloads/student-recoding_tBzNjg0.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_5khMkmS.mp3 ~/Downloads/student-recoding_5khMkmS.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_7DXkGZd.mp3 ~/Downloads/student-recoding_7DXkGZd.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_PU7ZF1C.mp3 ~/Downloads/student-recoding_PU7ZF1C.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_089bMXx.mp3 ~/Downloads/student-recoding_089bMXx.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_9HdrhrI.mp3 ~/Downloads/student-recoding_9HdrhrI.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_VCQLR9I.mp3 ~/Downloads/student-recoding_VCQLR9I.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_FhtEO84.mp3 ~/Downloads/student-recoding_FhtEO84.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Qa4iBlm.mp3 ~/Downloads/student-recoding_Qa4iBlm.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_0f0EoY2.mp3 ~/Downloads/student-recoding_0f0EoY2.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_UGX8dST.mp3 ~/Downloads/student-recoding_UGX8dST.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_AZtIYcr.mp3 ~/Downloads/student-recoding_AZtIYcr.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_1eF5f48.mp3 ~/Downloads/student-recoding_1eF5f48.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_HJlkWxa.mp3 ~/Downloads/student-recoding_HJlkWxa.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Hf3BfZ5.mp3 ~/Downloads/student-recoding_Hf3BfZ5.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_9MoMNws.mp3 ~/Downloads/student-recoding_9MoMNws.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_dGxDly0.mp3 ~/Downloads/student-recoding_dGxDly0.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_1qZvgDh.mp3 ~/Downloads/student-recoding_1qZvgDh.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_uZx0jHN.mp3 ~/Downloads/student-recoding_uZx0jHN.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_no8giT7.mp3 ~/Downloads/student-recoding_no8giT7.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_1mwNhV4.mp3 ~/Downloads/student-recoding_1mwNhV4.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_93ojXag.mp3 ~/Downloads/student-recoding_93ojXag.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_XVsPSSK.mp3 ~/Downloads/student-recoding_XVsPSSK.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_mGCKtdY.mp3 ~/Downloads/student-recoding_mGCKtdY.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Cl7O9OW.mp3 ~/Downloads/student-recoding_Cl7O9OW.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_6UrbBQj.mp3 ~/Downloads/student-recoding_6UrbBQj.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_D5gOMVM.mp3 ~/Downloads/student-recoding_D5gOMVM.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_26BIF0h.mp3 ~/Downloads/student-recoding_26BIF0h.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_vvHVCCc.mp3 ~/Downloads/student-recoding_vvHVCCc.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_9DzHQg7.mp3 ~/Downloads/student-recoding_9DzHQg7.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_B2iBnaM.mp3 ~/Downloads/student-recoding_B2iBnaM.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_wODPfYZ.mp3 ~/Downloads/student-recoding_wODPfYZ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_EcM9Uop.mp3 ~/Downloads/student-recoding_EcM9Uop.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_qoOW9WH.mp3 ~/Downloads/student-recoding_qoOW9WH.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_0ge6z6R.mp3 ~/Downloads/student-recoding_0ge6z6R.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_yo6iFy2.mp3 ~/Downloads/student-recoding_yo6iFy2.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_FjAk2G5.mp3 ~/Downloads/student-recoding_FjAk2G5.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_RET7Rxc.mp3 ~/Downloads/student-recoding_RET7Rxc.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_o6iGiC4.mp3 ~/Downloads/student-recoding_o6iGiC4.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ILfJJ4m.mp3 ~/Downloads/student-recoding_ILfJJ4m.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_vddxWGc.mp3 ~/Downloads/student-recoding_vddxWGc.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_a2IeMXA.mp3 ~/Downloads/student-recoding_a2IeMXA.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_eBihmLt.mp3 ~/Downloads/student-recoding_eBihmLt.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_gbZtKVD.mp3 ~/Downloads/student-recoding_gbZtKVD.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_lpA6LMK.mp3 ~/Downloads/student-recoding_lpA6LMK.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_tyfzWkN.mp3 ~/Downloads/student-recoding_tyfzWkN.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_SHB8iAi.mp3 ~/Downloads/student-recoding_SHB8iAi.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_FeCZmWf.mp3 ~/Downloads/student-recoding_FeCZmWf.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_X3T0nIk.mp3 ~/Downloads/student-recoding_X3T0nIk.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_fSIg5zA.mp3 ~/Downloads/student-recoding_fSIg5zA.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_K3IwJIk.mp3 ~/Downloads/student-recoding_K3IwJIk.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_EnRQkLP.mp3 ~/Downloads/student-recoding_EnRQkLP.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_BydEMbJ.mp3 ~/Downloads/student-recoding_BydEMbJ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_kWzKpBl.mp3 ~/Downloads/student-recoding_kWzKpBl.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_BfWB6mB.mp3 ~/Downloads/student-recoding_BfWB6mB.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_TvfrNwR.mp3 ~/Downloads/student-recoding_TvfrNwR.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_t7GIZ0P.mp3 ~/Downloads/student-recoding_t7GIZ0P.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_pPOh9Ex.mp3 ~/Downloads/student-recoding_pPOh9Ex.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_vOkFlXA.mp3 ~/Downloads/student-recoding_vOkFlXA.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_vgCUo3Q.mp3 ~/Downloads/student-recoding_vgCUo3Q.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_KUfHpH1.mp3 ~/Downloads/student-recoding_KUfHpH1.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_R3dYU5S.mp3 ~/Downloads/student-recoding_R3dYU5S.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_n2gNygK.mp3 ~/Downloads/student-recoding_n2gNygK.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_rfBsHnm.mp3 ~/Downloads/student-recoding_rfBsHnm.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_60Mu47C.mp3 ~/Downloads/student-recoding_60Mu47C.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_VmtZZkJ.mp3 ~/Downloads/student-recoding_VmtZZkJ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_hKqoTQd.mp3 ~/Downloads/student-recoding_hKqoTQd.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_qFsfJOR.mp3 ~/Downloads/student-recoding_qFsfJOR.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_D8sCnit.mp3 ~/Downloads/student-recoding_D8sCnit.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_AKnzpYs.mp3 ~/Downloads/student-recoding_AKnzpYs.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_V0dCD8e.mp3 ~/Downloads/student-recoding_V0dCD8e.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_KDv1e0K.mp3 ~/Downloads/student-recoding_KDv1e0K.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_gKU8U7J.mp3 ~/Downloads/student-recoding_gKU8U7J.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_RN5Rbkq.mp3 ~/Downloads/student-recoding_RN5Rbkq.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Tbgob2j.mp3 ~/Downloads/student-recoding_Tbgob2j.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ytSQixG.mp3 ~/Downloads/student-recoding_ytSQixG.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_quepY3W.mp3 ~/Downloads/student-recoding_quepY3W.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_IvPwVMD.mp3 ~/Downloads/student-recoding_IvPwVMD.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_HgibjIZ.mp3 ~/Downloads/student-recoding_HgibjIZ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_w473wIU.mp3 ~/Downloads/student-recoding_w473wIU.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_q1Nlyvl.mp3 ~/Downloads/student-recoding_q1Nlyvl.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_fhkF6jd.mp3 ~/Downloads/student-recoding_fhkF6jd.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_0RkWk5v.mp3 ~/Downloads/student-recoding_0RkWk5v.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_JeLdkFz.mp3 ~/Downloads/student-recoding_JeLdkFz.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_2NAHwb5.mp3 ~/Downloads/student-recoding_2NAHwb5.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_dW62Tq4.mp3 ~/Downloads/student-recoding_dW62Tq4.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_CpfPgOU.mp3 ~/Downloads/student-recoding_CpfPgOU.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_GQTJU9E.mp3 ~/Downloads/student-recoding_GQTJU9E.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_8GyNdYN.mp3 ~/Downloads/student-recoding_8GyNdYN.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_CwKKPUG.mp3 ~/Downloads/student-recoding_CwKKPUG.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_TNlt17J.mp3 ~/Downloads/student-recoding_TNlt17J.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_UDuhGf8.mp3 ~/Downloads/student-recoding_UDuhGf8.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_iZgoguV.mp3 ~/Downloads/student-recoding_iZgoguV.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_KsWuXTy.mp3 ~/Downloads/student-recoding_KsWuXTy.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_58oCfns.mp3 ~/Downloads/student-recoding_58oCfns.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_BDQ8Kcx.mp3 ~/Downloads/student-recoding_BDQ8Kcx.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_qAEO1y1.mp3 ~/Downloads/student-recoding_qAEO1y1.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_6BzLGGJ.mp3 ~/Downloads/student-recoding_6BzLGGJ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_zxCSpaY.mp3 ~/Downloads/student-recoding_zxCSpaY.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_0CA7NvJ.mp3 ~/Downloads/student-recoding_0CA7NvJ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_CTvAlSm.mp3 ~/Downloads/student-recoding_CTvAlSm.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_pwav2tH.mp3 ~/Downloads/student-recoding_pwav2tH.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_RZNHqvm.mp3 ~/Downloads/student-recoding_RZNHqvm.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_QeUGb6D.mp3 ~/Downloads/student-recoding_QeUGb6D.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_EQeErn5.mp3 ~/Downloads/student-recoding_EQeErn5.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_TjD1Yxz.mp3 ~/Downloads/student-recoding_TjD1Yxz.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_nQ21lG0.mp3 ~/Downloads/student-recoding_nQ21lG0.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Wrv5Jr8.mp3 ~/Downloads/student-recoding_Wrv5Jr8.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_E0xjWEs.mp3 ~/Downloads/student-recoding_E0xjWEs.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_kKNjwy0.mp3 ~/Downloads/student-recoding_kKNjwy0.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_U1qysrf.mp3 ~/Downloads/student-recoding_U1qysrf.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_poZySOm.mp3 ~/Downloads/student-recoding_poZySOm.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_gZOIlCc.mp3 ~/Downloads/student-recoding_gZOIlCc.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_a3sSOiz.mp3 ~/Downloads/student-recoding_a3sSOiz.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_YFyany6.mp3 ~/Downloads/student-recoding_YFyany6.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_a136s08.mp3 ~/Downloads/student-recoding_a136s08.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_c4oJ2B3.mp3 ~/Downloads/student-recoding_c4oJ2B3.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_xau7cin.mp3 ~/Downloads/student-recoding_xau7cin.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_DDXCiqT.mp3 ~/Downloads/student-recoding_DDXCiqT.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_m5xAmMq.mp3 ~/Downloads/student-recoding_m5xAmMq.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_pTPbmRL.mp3 ~/Downloads/student-recoding_pTPbmRL.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_HndNzR8.mp3 ~/Downloads/student-recoding_HndNzR8.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_UELlRTs.mp3 ~/Downloads/student-recoding_UELlRTs.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_dPcvDXB.mp3 ~/Downloads/student-recoding_dPcvDXB.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_WGeuOua.mp3 ~/Downloads/student-recoding_WGeuOua.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_V1pgnC8.mp3 ~/Downloads/student-recoding_V1pgnC8.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Ul6dqw7.mp3 ~/Downloads/student-recoding_Ul6dqw7.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_fY94tC7.mp3 ~/Downloads/student-recoding_fY94tC7.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Q01D4yh.mp3 ~/Downloads/student-recoding_Q01D4yh.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_irPOZAb.mp3 ~/Downloads/student-recoding_irPOZAb.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ohSdfhB.mp3 ~/Downloads/student-recoding_ohSdfhB.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_53XSzDi.mp3 ~/Downloads/student-recoding_53XSzDi.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_4mpSiKk.mp3 ~/Downloads/student-recoding_4mpSiKk.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_rWw0QlW.mp3 ~/Downloads/student-recoding_rWw0QlW.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_LajEAG5.mp3 ~/Downloads/student-recoding_LajEAG5.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_s6nYuHz.mp3 ~/Downloads/student-recoding_s6nYuHz.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Ce3cwlO.mp3 ~/Downloads/student-recoding_Ce3cwlO.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_uK27rhX.mp3 ~/Downloads/student-recoding_uK27rhX.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_aLNRyGD.mp3 ~/Downloads/student-recoding_aLNRyGD.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ExCvq4C.mp3 ~/Downloads/student-recoding_ExCvq4C.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_788cRiU.mp3 ~/Downloads/student-recoding_788cRiU.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Pg5xpdq.mp3 ~/Downloads/student-recoding_Pg5xpdq.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_DlfAd5e.mp3 ~/Downloads/student-recoding_DlfAd5e.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_JKe3vDO.mp3 ~/Downloads/student-recoding_JKe3vDO.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_kaMWEpB.mp3 ~/Downloads/student-recoding_kaMWEpB.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_dzF09LG.mp3 ~/Downloads/student-recoding_dzF09LG.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_vTmDKBR.mp3 ~/Downloads/student-recoding_vTmDKBR.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_KBn2btU.mp3 ~/Downloads/student-recoding_KBn2btU.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_2ZeAu7A.mp3 ~/Downloads/student-recoding_2ZeAu7A.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_9dtHrDQ.mp3 ~/Downloads/student-recoding_9dtHrDQ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_wMEVifG.mp3 ~/Downloads/student-recoding_wMEVifG.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_2VSsaYn.mp3 ~/Downloads/student-recoding_2VSsaYn.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_NVz9VD3.mp3 ~/Downloads/student-recoding_NVz9VD3.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_dEydYZp.mp3 ~/Downloads/student-recoding_dEydYZp.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_KTzx1tD.mp3 ~/Downloads/student-recoding_KTzx1tD.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_AQK3nA5.mp3 ~/Downloads/student-recoding_AQK3nA5.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_kCM4ESf.mp3 ~/Downloads/student-recoding_kCM4ESf.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_FrWCYMR.mp3 ~/Downloads/student-recoding_FrWCYMR.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_SWVBaS1.mp3 ~/Downloads/student-recoding_SWVBaS1.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ICc8onS.mp3 ~/Downloads/student-recoding_ICc8onS.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_MtdsLgE.mp3 ~/Downloads/student-recoding_MtdsLgE.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_3WhpjMh.mp3 ~/Downloads/student-recoding_3WhpjMh.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_1vXTCVP.mp3 ~/Downloads/student-recoding_1vXTCVP.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_SscRfN9.mp3 ~/Downloads/student-recoding_SscRfN9.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_UXtlceZ.mp3 ~/Downloads/student-recoding_UXtlceZ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_3dkMCbc.mp3 ~/Downloads/student-recoding_3dkMCbc.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_vBlq9OP.mp3 ~/Downloads/student-recoding_vBlq9OP.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Q9mr3UD.mp3 ~/Downloads/student-recoding_Q9mr3UD.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_uZJyd2q.mp3 ~/Downloads/student-recoding_uZJyd2q.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_EE1ZtlM.mp3 ~/Downloads/student-recoding_EE1ZtlM.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Uv3ZxNI.mp3 ~/Downloads/student-recoding_Uv3ZxNI.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_z8oOlF4.mp3 ~/Downloads/student-recoding_z8oOlF4.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_E3ySeFX.mp3 ~/Downloads/student-recoding_E3ySeFX.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_DvlgTbG.mp3 ~/Downloads/student-recoding_DvlgTbG.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_zwSfg84.mp3 ~/Downloads/student-recoding_zwSfg84.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_uWHcE4s.mp3 ~/Downloads/student-recoding_uWHcE4s.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Mac3gji.mp3 ~/Downloads/student-recoding_Mac3gji.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_NfVrW2H.mp3 ~/Downloads/student-recoding_NfVrW2H.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_abPjq2w.mp3 ~/Downloads/student-recoding_abPjq2w.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_q7bKQlL.mp3 ~/Downloads/student-recoding_q7bKQlL.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_H22pxxQ.mp3 ~/Downloads/student-recoding_H22pxxQ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Fh4Om6Z.mp3 ~/Downloads/student-recoding_Fh4Om6Z.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_9fLVFvx.mp3 ~/Downloads/student-recoding_9fLVFvx.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_01B0rat.mp3 ~/Downloads/student-recoding_01B0rat.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Y9t3Q0I.mp3 ~/Downloads/student-recoding_Y9t3Q0I.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_3oJv5oR.mp3 ~/Downloads/student-recoding_3oJv5oR.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_PadYlYv.mp3 ~/Downloads/student-recoding_PadYlYv.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_JKQrrpi.mp3 ~/Downloads/student-recoding_JKQrrpi.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_X66j8cE.mp3 ~/Downloads/student-recoding_X66j8cE.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_HFjBHLH.mp3 ~/Downloads/student-recoding_HFjBHLH.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_a3PlE3m.mp3 ~/Downloads/student-recoding_a3PlE3m.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_9W5vJk7.mp3 ~/Downloads/student-recoding_9W5vJk7.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_g9rkd86.mp3 ~/Downloads/student-recoding_g9rkd86.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_coKprRH.mp3 ~/Downloads/student-recoding_coKprRH.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_2hcZh0p.mp3 ~/Downloads/student-recoding_2hcZh0p.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_vM6NsKj.mp3 ~/Downloads/student-recoding_vM6NsKj.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_UDL9AFg.mp3 ~/Downloads/student-recoding_UDL9AFg.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_bF5q5kq.mp3 ~/Downloads/student-recoding_bF5q5kq.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_I9IBGuU.mp3 ~/Downloads/student-recoding_I9IBGuU.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_KJEvQpG.mp3 ~/Downloads/student-recoding_KJEvQpG.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_f7Ttc29.mp3 ~/Downloads/student-recoding_f7Ttc29.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_8gqTpAF.mp3 ~/Downloads/student-recoding_8gqTpAF.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_yQwM60W.mp3 ~/Downloads/student-recoding_yQwM60W.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_vzHp1Bx.mp3 ~/Downloads/student-recoding_vzHp1Bx.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_a95LhlN.mp3 ~/Downloads/student-recoding_a95LhlN.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_T0VwsI4.mp3 ~/Downloads/student-recoding_T0VwsI4.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_d0ICqx6.mp3 ~/Downloads/student-recoding_d0ICqx6.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_lk6cTfz.mp3 ~/Downloads/student-recoding_lk6cTfz.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_hf57sqv.mp3 ~/Downloads/student-recoding_hf57sqv.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_4EcTasa.mp3 ~/Downloads/student-recoding_4EcTasa.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Zx0ACbj.mp3 ~/Downloads/student-recoding_Zx0ACbj.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_pCZh1vJ.mp3 ~/Downloads/student-recoding_pCZh1vJ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_irE2bar.mp3 ~/Downloads/student-recoding_irE2bar.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_eEC6zuK.mp3 ~/Downloads/student-recoding_eEC6zuK.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_BqGrYAm.mp3 ~/Downloads/student-recoding_BqGrYAm.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_rl3qmpt.mp3 ~/Downloads/student-recoding_rl3qmpt.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Fz99q0Y.mp3 ~/Downloads/student-recoding_Fz99q0Y.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_V4HUZ1d.mp3 ~/Downloads/student-recoding_V4HUZ1d.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_APgM42M.mp3 ~/Downloads/student-recoding_APgM42M.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_minqdP2.mp3 ~/Downloads/student-recoding_minqdP2.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_HrwXi8F.mp3 ~/Downloads/student-recoding_HrwXi8F.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_l0kHWmg.mp3 ~/Downloads/student-recoding_l0kHWmg.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_713h2EN.mp3 ~/Downloads/student-recoding_713h2EN.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Z7XDgRF.mp3 ~/Downloads/student-recoding_Z7XDgRF.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_m7f5T9b.mp3 ~/Downloads/student-recoding_m7f5T9b.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_hT2kRT1.mp3 ~/Downloads/student-recoding_hT2kRT1.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Wli0U2f.mp3 ~/Downloads/student-recoding_Wli0U2f.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_YoU6R2X.mp3 ~/Downloads/student-recoding_YoU6R2X.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_qk3pfZp.mp3 ~/Downloads/student-recoding_qk3pfZp.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_mUyuW71.mp3 ~/Downloads/student-recoding_mUyuW71.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_QG8MDhH.mp3 ~/Downloads/student-recoding_QG8MDhH.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_xExjXsG.mp3 ~/Downloads/student-recoding_xExjXsG.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_WOp1AXU.mp3 ~/Downloads/student-recoding_WOp1AXU.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_69mqarK.mp3 ~/Downloads/student-recoding_69mqarK.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_FhMbuFp.mp3 ~/Downloads/student-recoding_FhMbuFp.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_5oSc6sP.mp3 ~/Downloads/student-recoding_5oSc6sP.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_woM3EKE.mp3 ~/Downloads/student-recoding_woM3EKE.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Q68FwdB.mp3 ~/Downloads/student-recoding_Q68FwdB.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_clckAJz.mp3 ~/Downloads/student-recoding_clckAJz.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_mxZdfvS.mp3 ~/Downloads/student-recoding_mxZdfvS.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_61INJdi.mp3 ~/Downloads/student-recoding_61INJdi.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Uhb4n5W.mp3 ~/Downloads/student-recoding_Uhb4n5W.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_azisqUR.mp3 ~/Downloads/student-recoding_azisqUR.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_H9nxQIj.mp3 ~/Downloads/student-recoding_H9nxQIj.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_qe7TXo1.mp3 ~/Downloads/student-recoding_qe7TXo1.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_B8hy0OV.mp3 ~/Downloads/student-recoding_B8hy0OV.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_c5Wz4fi.mp3 ~/Downloads/student-recoding_c5Wz4fi.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_TyY0KJy.mp3 ~/Downloads/student-recoding_TyY0KJy.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_HEJXMxi.mp3 ~/Downloads/student-recoding_HEJXMxi.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_aMyPS6p.mp3 ~/Downloads/student-recoding_aMyPS6p.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_rB4iZmo.mp3 ~/Downloads/student-recoding_rB4iZmo.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_w8Vnm6O.mp3 ~/Downloads/student-recoding_w8Vnm6O.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_bUOWBCr.mp3 ~/Downloads/student-recoding_bUOWBCr.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_1SV9Gyl.mp3 ~/Downloads/student-recoding_1SV9Gyl.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_wgItPfW.mp3 ~/Downloads/student-recoding_wgItPfW.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_AX2qlrP.mp3 ~/Downloads/student-recoding_AX2qlrP.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_i5LN44D.mp3 ~/Downloads/student-recoding_i5LN44D.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_STa1TfL.mp3 ~/Downloads/student-recoding_STa1TfL.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_S3N3XX2.mp3 ~/Downloads/student-recoding_S3N3XX2.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_zPt3VCd.mp3 ~/Downloads/student-recoding_zPt3VCd.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_VP8O7L2.mp3 ~/Downloads/student-recoding_VP8O7L2.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_y5aHCM0.mp3 ~/Downloads/student-recoding_y5aHCM0.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_6ZFNyWP.mp3 ~/Downloads/student-recoding_6ZFNyWP.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_fin2jOc.mp3 ~/Downloads/student-recoding_fin2jOc.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_bDw1Ieu.mp3 ~/Downloads/student-recoding_bDw1Ieu.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_NGfHyE0.mp3 ~/Downloads/student-recoding_NGfHyE0.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_MWMonCB.mp3 ~/Downloads/student-recoding_MWMonCB.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_fUodLW1.mp3 ~/Downloads/student-recoding_fUodLW1.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_FIvY7ek.mp3 ~/Downloads/student-recoding_FIvY7ek.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_QTy0XK6.mp3 ~/Downloads/student-recoding_QTy0XK6.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_CsKRC3d.mp3 ~/Downloads/student-recoding_CsKRC3d.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_zBn16gb.mp3 ~/Downloads/student-recoding_zBn16gb.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_aKUZzgV.mp3 ~/Downloads/student-recoding_aKUZzgV.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Nn0E4GM.mp3 ~/Downloads/student-recoding_Nn0E4GM.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_RgXw8V3.mp3 ~/Downloads/student-recoding_RgXw8V3.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_3JX9zVR.mp3 ~/Downloads/student-recoding_3JX9zVR.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_85OhYrk.mp3 ~/Downloads/student-recoding_85OhYrk.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_wW5Tlr4.mp3 ~/Downloads/student-recoding_wW5Tlr4.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_RKdCxIR.mp3 ~/Downloads/student-recoding_RKdCxIR.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_KRaa5RI.mp3 ~/Downloads/student-recoding_KRaa5RI.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_BwxcGFA.mp3 ~/Downloads/student-recoding_BwxcGFA.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Yv77pkT.mp3 ~/Downloads/student-recoding_Yv77pkT.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_EMZtbyE.mp3 ~/Downloads/student-recoding_EMZtbyE.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_MKTEWDr.mp3 ~/Downloads/student-recoding_MKTEWDr.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_vJM5vvd.mp3 ~/Downloads/student-recoding_vJM5vvd.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Jj7EXMZ.mp3 ~/Downloads/student-recoding_Jj7EXMZ.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_anmRal0.mp3 ~/Downloads/student-recoding_anmRal0.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_xP9St0V.mp3 ~/Downloads/student-recoding_xP9St0V.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_kY7Z2IW.mp3 ~/Downloads/student-recoding_kY7Z2IW.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_oD05qjx.mp3 ~/Downloads/student-recoding_oD05qjx.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_FPKqu8f.mp3 ~/Downloads/student-recoding_FPKqu8f.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_44rgV3m.mp3 ~/Downloads/student-recoding_44rgV3m.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_V4FXfTr.mp3 ~/Downloads/student-recoding_V4FXfTr.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_wUy1BL6.mp3 ~/Downloads/student-recoding_wUy1BL6.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_jgPyGhd.mp3 ~/Downloads/student-recoding_jgPyGhd.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_erzzTdH.mp3 ~/Downloads/student-recoding_erzzTdH.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Uez7rCa.mp3 ~/Downloads/student-recoding_Uez7rCa.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_KCDidv9.mp3 ~/Downloads/student-recoding_KCDidv9.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_eDjVvuf.mp3 ~/Downloads/student-recoding_eDjVvuf.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_9ZqYXE4.mp3 ~/Downloads/student-recoding_9ZqYXE4.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ZXNZAmu.mp3 ~/Downloads/student-recoding_ZXNZAmu.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_4sZfsww.mp3 ~/Downloads/student-recoding_4sZfsww.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_ay0Bp4x.mp3 ~/Downloads/student-recoding_ay0Bp4x.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_Mlc8XFL.mp3 ~/Downloads/student-recoding_Mlc8XFL.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_67loKRY.mp3 ~/Downloads/student-recoding_67loKRY.mp3 --no-cli-pager +aws --profile cprprod s3api get-object --bucket "api-musiccpr-prod" --key media/student-recoding_HS7nK7l.mp3 ~/Downloads/student-recoding_HS7nK7l.mp3 --no-cli-pager \ No newline at end of file diff --git a/docs/railway-deployment.md b/docs/railway-deployment.md new file mode 100644 index 0000000..56ee8e2 --- /dev/null +++ b/docs/railway-deployment.md @@ -0,0 +1,83 @@ +# Railway + Vercel Deployment + +## Backend (Railway) + +### Setup + +1. Create project in Railway, connect GitHub repo +2. Add PostgreSQL: **+ New** β†’ **Database** β†’ **PostgreSQL** +3. Add Volume: **+ New** β†’ **Volume** β†’ mount at `/app/mediafiles` +4. Set environment variables (see below) +5. Enable public networking: **Settings** β†’ **Networking** β†’ **Public Networking** + +### Environment Variables + +| Variable | Value | +|----------|-------| +| `DJANGO_SECRET_KEY` | `python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"` | +| `MEDIA_ROOT` | `/app/mediafiles` | +| `CORS_ALLOWED_ORIGINS` | `https://your-frontend.vercel.app` | +| `CSRF_TRUSTED_ORIGINS` | `https://your-frontend.vercel.app,https://*.railway.app` | + +Auto-set by Railway: `DATABASE_URL` + +### Key Files + +- `config/settings/railway.py` - Railway-specific settings (whitenoise, local cache, no AWS) +- `requirements/railway.txt` - Dependencies without AWS packages +- `start.sh` - Startup script (seeds media to volume, runs migrations, starts gunicorn) +- `nixpacks.toml` - Points to `start.sh` +- `Procfile` - Fallback start command + +### Debug Endpoint + +`/debug-media/` - Shows MEDIA_ROOT contents and file counts + +--- + +## Frontend (Vercel) + +### Setup + +1. Import GitHub repo in Vercel +2. Framework: **Next.js** (auto-detected) +3. Set environment variables (see below) +4. Deploy + +### Environment Variables + +| Variable | Value | +|----------|-------| +| `NEXT_PUBLIC_BACKEND_HOST` | `https://your-backend.up.railway.app` | +| `NEXTAUTH_URL` | `https://your-frontend.vercel.app` | +| `SECRET` | Any random string | + +### Custom Domain + +1. Vercel: **Settings** β†’ **Domains** β†’ Add `your.domain.com` +2. DNS: Add CNAME record `your` β†’ `cname.vercel-dns.com` +3. Update `NEXTAUTH_URL` to match + +--- + +## Architecture + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Vercel │────▢│ Railway β”‚ +β”‚ (Next.js) β”‚ β”‚ (Django) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β–Ό β–Ό β–Ό + PostgreSQL Volume Whitenoise + (database) (media) (static) +``` + +| Component | Solution | +|-----------|----------| +| Static files | Whitenoise (served from container) | +| Media files | Railway Volume at `/app/mediafiles` | +| Database | Railway PostgreSQL | +| Cache | Local memory | +| Email | Console backend (logs) | diff --git a/entrypoint.prod.sh b/entrypoint.prod.sh new file mode 100644 index 0000000..79f1f58 --- /dev/null +++ b/entrypoint.prod.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +export DJANGO_READ_DOT_ENV_FILE=True +export DJANGO_SETTINGS_MODULE=config.settings.production + +python manage.py collectstatic --noinput +python manage.py migrate --noinput +python -m gunicorn config.asgi:application \ + --bind 0.0.0.0:8000 \ + --workers 4 \ + -k uvicorn.workers.UvicornWorker diff --git a/nixpacks.toml b/nixpacks.toml new file mode 100644 index 0000000..cb6090f --- /dev/null +++ b/nixpacks.toml @@ -0,0 +1,3 @@ +# Use shell script for start command +[start] +cmd = "bash start.sh" diff --git a/railway.json b/railway.json new file mode 100644 index 0000000..7644270 --- /dev/null +++ b/railway.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://railway.app/railway.schema.json", + "build": { + "builder": "NIXPACKS" + }, + "deploy": { + "restartPolicyType": "ON_FAILURE", + "restartPolicyMaxRetries": 10 + } +} diff --git a/requirements/local.txt b/requirements/local.txt index 797b21b..3fa4903 100644 --- a/requirements/local.txt +++ b/requirements/local.txt @@ -2,7 +2,7 @@ Werkzeug==3.0.3 # https://github.com/pallets/werkzeug ipdb==0.13.13 # https://github.com/gotcha/ipdb -psycopg2-binary==2.9.9 # https://github.com/psycopg/psycopg2 +psycopg[binary]>=3.0.0 # https://github.com/psycopg/psycopg watchgod==0.8.2 # https://github.com/samuelcolvin/watchgod # Testing diff --git a/requirements/production.txt b/requirements/production.txt index 1c04c47..7c6cfd5 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -4,7 +4,7 @@ wheel==0.43.0 # https://idk gunicorn==22.0.0 # https://github.com/benoitc/gunicorn -psycopg2-binary==2.9.9 # https://github.com/psycopg/psycopg2 +psycopg[binary]>=3.0.0 # https://github.com/psycopg/psycopg Collectfast==2.2.0 # https://github.com/antonagestam/collectfast boto3==1.34.145 diff --git a/requirements/railway.txt b/requirements/railway.txt new file mode 100644 index 0000000..9a4f455 --- /dev/null +++ b/requirements/railway.txt @@ -0,0 +1,19 @@ +# Railway deployment requirements +# Simplified production without AWS dependencies + +-r base.txt + +# Web server +gunicorn==22.0.0 + +# Database (Railway provides Postgres, or use SQLite) +psycopg2-binary==2.9.9 + +# Static files +whitenoise==6.7.0 + +# Note: The following are NOT included (vs production.txt): +# - boto3 (S3) +# - django-storages (S3) +# - django-anymail (SES email) +# - Collectfast (S3 optimization) diff --git a/runtime.txt b/runtime.txt new file mode 100644 index 0000000..431fc7e --- /dev/null +++ b/runtime.txt @@ -0,0 +1 @@ +python-3.11.4 diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..6d91516 --- /dev/null +++ b/start.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -e + +echo "=== Starting deployment ===" + +# Copy media files to volume if source exists and volume is empty +# (Only needed on first deploy or if volume is recreated) +if [ -d "teleband/media" ] && [ ! -f "/app/mediafiles/.seeded" ]; then + echo "=== Seeding media files to volume ===" + mkdir -p /app/mediafiles + cp -rv teleband/media/* /app/mediafiles/ || echo "Copy failed" + touch /app/mediafiles/.seeded + echo "=== Media files seeded ===" +fi + +echo "=== Running migrations ===" +python manage.py migrate --noinput + +echo "=== Collecting static files ===" +python manage.py collectstatic --noinput + +echo "=== Starting gunicorn ===" +exec gunicorn config.wsgi:application --bind 0.0.0.0:$PORT diff --git a/teleband/courses/admin.py b/teleband/courses/admin.py index 6434faf..6aa4d68 100644 --- a/teleband/courses/admin.py +++ b/teleband/courses/admin.py @@ -24,3 +24,4 @@ class EnrollmentAdmin(VersionAdmin): list_display = ("id", "user", "course", "instrument", "role") list_filter = ("course", "instrument", "role") search_fields = ("user__username", "course__name") + save_as = True diff --git a/teleband/dashboards/__init__.py b/teleband/dashboards/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/teleband/dashboards/admin.py b/teleband/dashboards/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/teleband/dashboards/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/teleband/dashboards/apps.py b/teleband/dashboards/apps.py new file mode 100644 index 0000000..de542fc --- /dev/null +++ b/teleband/dashboards/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class DashboardConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "teleband.dashboards" diff --git a/teleband/dashboards/migrations/__init__.py b/teleband/dashboards/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/teleband/dashboards/models.py b/teleband/dashboards/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/teleband/dashboards/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/teleband/dashboards/tests.py b/teleband/dashboards/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/teleband/dashboards/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/teleband/dashboards/urls.py b/teleband/dashboards/urls.py new file mode 100644 index 0000000..ab67004 --- /dev/null +++ b/teleband/dashboards/urls.py @@ -0,0 +1,10 @@ +from django.urls import path + +from teleband.dashboards.views import AssignmentListView, CourseListView, csv_view + +app_name = "dashboards" +urlpatterns = [ + path("", AssignmentListView.as_view(), name="assignment_list"), + path("courses/", CourseListView.as_view(), name="course_list"), + path("export/csv/", csv_view, name="export_csv"), +] diff --git a/teleband/dashboards/views.py b/teleband/dashboards/views.py new file mode 100644 index 0000000..c9d62c9 --- /dev/null +++ b/teleband/dashboards/views.py @@ -0,0 +1,165 @@ +from typing import Any +from django.db.models.query import QuerySet +from django.shortcuts import render + +from django.views import generic + +from teleband.assignments.models import Assignment +from teleband.courses.models import Course +from django.contrib.auth.mixins import UserPassesTestMixin + +import csv +from django.http import HttpResponse + + +class AssignmentListView(UserPassesTestMixin, generic.ListView): + model = Assignment + + def get_queryset(self) -> QuerySet[Any]: + results = Assignment.objects.prefetch_related( + "piece", + "piece_plan", + "enrollment", + "enrollment__user", + "enrollment__course", + "enrollment__instrument", + "enrollment__course__owner", + "instrument", + "submissions__attachments", + "submissions__grade", + "submissions__self_grade", + "activity", + ).all() + return results + + # queryset = Course.objects.prefetch_related( + # "enrollment_set__assignment_set__submissions__attachments" + # ).all() + + def test_func(self): + return self.request.user.is_superuser + + +class CourseListView(UserPassesTestMixin, generic.ListView): + model = Course + + def test_func(self): + return self.request.user.is_superuser + + +def csv_view(request): + """Function which generates a CSV file for download""" + # select related returns a queryset that will follow foreign-key relationships. This + # is a performance booster which results in a single more complex query but won't require + # database queries + assignments = Assignment.objects.select_related( + "piece", + "piece_plan", + "enrollment", + "enrollment__user", + "enrollment__course", + "enrollment__instrument", + "enrollment__course__owner", + "instrument", + "activity", + ).all() + + # Create the HttpResponse object with the appropriate CSV header + response = HttpResponse( + content_type="text/csv", + headers={"Content-Disposition": 'attachment; filename="assignment.csv"'}, + ) + + writer = csv.writer(response) + writer.writerow( + [ + "ID", + "Course ID", + "Course Name", + "Piece ID", + "Piece Name", + "Piece Plan ID", + "Piece Plan Name", + "Student ID", + "Student Instrument ID", + "Student Instrument Name", + "Assignment Activity ID", + "Assignment Activity", + "Assignment Instrument ID", + "Assignment Instrument Name", + "Submissions ID", + "Submissions Content", + "Submissions submitted", + "Submissions grade", + "Submissions Self Grade", + "Submission Attatchnment ID", + "Submission Attachment File", + "Submission Attachment Submitted", + ] + ) + for assn in assignments: + if len(assn.submissions.all()) == 0: + + writer.writerow( + [ + assn.id, + assn.enrollment.course.id, + assn.enrollment.course.name, + assn.piece.id, + assn.piece.name, + assn.piece_plan.id, + assn.piece_plan, + assn.enrollment.user.id, + assn.enrollment.instrument.id, + assn.enrollment.instrument.name, + assn.activity.id, + assn.activity, + assn.instrument.id, + assn.instrument.name, + "N/A", + "N/A", + "N/A", + "N/A", + "N/A", + "N/A", + "N/A", + "N/A", + ] + ) + else: + for sub in assn.submissions.all(): + for att in sub.attachments.all(): + csv_val = [ + assn.id, + assn.enrollment.course.id, + assn.enrollment.course.name, + assn.piece.id, + assn.piece.name, + assn.piece_plan.id, + assn.piece_plan, + assn.enrollment.user.id, + assn.enrollment.instrument.id, + assn.enrollment.instrument.name, + assn.activity.id, + assn.activity, + assn.instrument.id, + assn.instrument.name, + sub.id, + ] + if assn.activity.category == "Create": + csv_val.append("Create, see below") + else: + csv_val.append(sub.content) + csv_val.extend( + [ + sub.submitted, + sub.grade, + sub.self_grade, + att.id, + att.file, + att.submitted, + ] + ) + + writer.writerow(csv_val) + return response diff --git a/teleband/musics/admin.py b/teleband/musics/admin.py index a10e8f3..310c1ab 100644 --- a/teleband/musics/admin.py +++ b/teleband/musics/admin.py @@ -1,7 +1,15 @@ from django.contrib import admin from reversion.admin import VersionAdmin -from .models import EnsembleType, Composer, Piece, PartType, Part, PartTransposition +from .models import ( + EnsembleType, + Composer, + PartInstrumentSample, + Piece, + PartType, + Part, + PartTransposition, +) @admin.register(EnsembleType) @@ -49,3 +57,9 @@ class PartAdmin(VersionAdmin): class PartTranspositionAdmin(VersionAdmin): list_display = ("id", "part", "transposition", "flatio") list_filter = ("part", "transposition") + + +@admin.register(PartInstrumentSample) +class PartInstrumentSampleAdmin(VersionAdmin): + list_display = ("id", "part", "instrument", "sample_audio") + list_filter = ("part", "instrument") diff --git a/teleband/musics/api/serializers.py b/teleband/musics/api/serializers.py index ea39d8e..e899fdb 100644 --- a/teleband/musics/api/serializers.py +++ b/teleband/musics/api/serializers.py @@ -1,8 +1,14 @@ from rest_framework import serializers -from teleband.musics.models import Piece, Part, PartTransposition, Composer, PartType - -from teleband.musics.models import PartTransposition, EnsembleType +from teleband.musics.models import ( + Piece, + Part, + PartTransposition, + Composer, + PartType, + PartInstrumentSample, + EnsembleType, +) from teleband.instruments.models import Transposition from teleband.utils.serializers import GenericNameSerializer @@ -45,9 +51,16 @@ class Meta: fields = ["part", "transposition", "flatio"] +class PartInstrumentSampleSerializer(serializers.ModelSerializer): + class Meta: + model = PartInstrumentSample + fields = ["id", "part", "instrument", "sample_audio"] + + class PartSerializer(serializers.ModelSerializer): piece = PieceSerializer() transpositions = PartTranspositionSimpleSerializer(many=True) + instrument_samples = PartInstrumentSampleSerializer(many=True) class Meta: model = Part @@ -57,6 +70,7 @@ class Meta: "transpositions", "sample_audio", "chord_scale_pattern", + "instrument_samples", ] diff --git a/teleband/musics/migrations/0028_partinstrumentsample.py b/teleband/musics/migrations/0028_partinstrumentsample.py new file mode 100644 index 0000000..809b949 --- /dev/null +++ b/teleband/musics/migrations/0028_partinstrumentsample.py @@ -0,0 +1,53 @@ +# Generated by Django 5.0.6 on 2024-10-27 02:47 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("instruments", "0004_instrument_midi_program_number"), + ( + "musics", + "0027_correct_accompaniment_2040_and_deep_river_color_pattern_20240317_1712", + ), + ] + + operations = [ + migrations.CreateModel( + name="PartInstrumentSample", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("sample_audio", models.FileField(upload_to="instrument_samples/")), + ( + "instrument", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="instruments.instrument", + ), + ), + ( + "part", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="instrument_samples", + to="musics.part", + ), + ), + ], + options={ + "verbose_name": "Part Instrument Sample", + "verbose_name_plural": "Part Instrument Samples", + "unique_together": {("part", "instrument")}, + }, + ), + ] diff --git a/teleband/musics/models.py b/teleband/musics/models.py index cd6effa..7cf24db 100644 --- a/teleband/musics/models.py +++ b/teleband/musics/models.py @@ -93,3 +93,19 @@ class Meta: def __str__(self): return f"{self.part.piece}: {self.part} [{self.transposition}]" + + +class PartInstrumentSample(models.Model): + part = models.ForeignKey( + Part, related_name="instrument_samples", on_delete=models.PROTECT + ) + instrument = models.ForeignKey("instruments.Instrument", on_delete=models.PROTECT) + sample_audio = models.FileField(upload_to="instrument_samples/") + + class Meta: + unique_together = ["part", "instrument"] + verbose_name = "Part Instrument Sample" + verbose_name_plural = "Part Instrument Samples" + + def __str__(self): + return f"{self.part} - {self.instrument} Sample" diff --git a/teleband/static/css/project.css b/teleband/static/css/project.css index f1d543d..e1e68a8 100644 --- a/teleband/static/css/project.css +++ b/teleband/static/css/project.css @@ -11,3 +11,22 @@ background-color: #f2dede; border-color: #eed3d7; } + +/* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col#usage_notes */ +.dashboard colgroup { + border-inline-start: 2px solid black; +} + +.dashboard td, +.dashboard th { + border-inline-end: 1px dashed black; +} + +.dashboard thead, +.dashboard tbody { + border-block-end: 2px solid black; +} + +.dashboard tr { + border-block-end: 1px dashed black; +} diff --git a/teleband/static/sass/project.scss b/teleband/static/sass/project.scss index 3c8f261..ff86f55 100644 --- a/teleband/static/sass/project.scss +++ b/teleband/static/sass/project.scss @@ -4,6 +4,12 @@ // project specific CSS goes here + +.dashboard col td { + background-color: red; + /* border-inline-start: ; */ +} + //////////////////////////////// //Variables// //////////////////////////////// diff --git a/teleband/submissions/admin.py b/teleband/submissions/admin.py index 228c2b9..22d5ba0 100644 --- a/teleband/submissions/admin.py +++ b/teleband/submissions/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin from reversion.admin import VersionAdmin -from .models import Submission, SubmissionAttachment, Grade +from .models import Submission, SubmissionAttachment, Grade, ActivityProgress @admin.register(Submission) @@ -36,3 +36,27 @@ class GradeAdmin(VersionAdmin): ) # list_filter = ("student_submission", "own_submission", "grader") list_filter = ("grader",) + + +@admin.register(ActivityProgress) +class ActivityProgressAdmin(VersionAdmin): + list_display = ( + "id", + "assignment", + "current_step", + "participant_email", + "created_at", + "updated_at", + ) + list_filter = ("current_step", "created_at") + search_fields = ("participant_email", "assignment__id") + readonly_fields = ( + "activity_logs", + "step_completions", + "question_responses", + "audio_edit_history", + "audio_metadata", + "created_at", + "updated_at", + ) + raw_id_fields = ("assignment",) diff --git a/teleband/submissions/api/serializers.py b/teleband/submissions/api/serializers.py index c619676..c5822e8 100644 --- a/teleband/submissions/api/serializers.py +++ b/teleband/submissions/api/serializers.py @@ -1,6 +1,6 @@ from rest_framework import serializers -from teleband.submissions.models import Grade, Submission, SubmissionAttachment +from teleband.submissions.models import Grade, Submission, SubmissionAttachment, ActivityProgress # from teleband.assignments.api.serializers import AssignmentSerializer @@ -44,3 +44,23 @@ class Meta: "student_submission", "own_submission", ] + + +class ActivityProgressSerializer(serializers.ModelSerializer): + class Meta: + model = ActivityProgress + fields = [ + "id", + "assignment", + "current_step", + "step_completions", + "activity_logs", + "question_responses", + "participant_email", + "current_audio_url", + "audio_edit_history", + "audio_metadata", + "created_at", + "updated_at", + ] + read_only_fields = ["created_at", "updated_at"] diff --git a/teleband/submissions/api/views.py b/teleband/submissions/api/views.py index efea569..14b3718 100644 --- a/teleband/submissions/api/views.py +++ b/teleband/submissions/api/views.py @@ -1,21 +1,24 @@ from django.contrib.auth import get_user_model +from django.db import transaction +from django.db.models import OuterRef, Subquery from rest_framework import status from rest_framework.decorators import action from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, CreateModelMixin from rest_framework.response import Response from rest_framework.viewsets import GenericViewSet, ModelViewSet from teleband.submissions.api.teacher_serializers import TeacherSubmissionSerializer -from django.db.models import OuterRef, Subquery from .serializers import ( GradeSerializer, SubmissionSerializer, AttachmentSerializer, + ActivityProgressSerializer, ) from teleband.courses.models import Course -from teleband.submissions.models import Grade, Submission, SubmissionAttachment +from teleband.submissions.models import Grade, Submission, SubmissionAttachment, ActivityProgress from teleband.assignments.models import Assignment +from datetime import datetime class SubmissionViewSet( @@ -109,3 +112,198 @@ def get_queryset(self, *args, **kwargs): "course_slug_slug" ] ) + + +class ActivityProgressViewSet(GenericViewSet): + serializer_class = ActivityProgressSerializer + queryset = ActivityProgress.objects.all() + + def get_object(self): + """Get or create progress for the current assignment.""" + assignment_id = self.kwargs.get("assignment_id") + progress, created = ActivityProgress.objects.get_or_create( + assignment_id=assignment_id + ) + return progress + + def list(self, request, *args, **kwargs): + """Get progress for current assignment (uses list URL since no pk needed).""" + instance = self.get_object() + serializer = self.get_serializer(instance) + return Response(serializer.data) + + @action(detail=False, methods=["post"]) + def log_event(self, request, **kwargs): + """Log an operation event to the activity progress.""" + assignment_id = kwargs.get("assignment_id") + + try: + # Use transaction with row-level locking to prevent race conditions + with transaction.atomic(): + progress, created = ActivityProgress.objects.select_for_update().get_or_create( + assignment_id=assignment_id + ) + + # Extract event data from request + operation = request.data.get("operation") + step = request.data.get("step", progress.current_step) + data = request.data.get("data", {}) + email = request.data.get("email") + + # DEBUG: Log what we received + print(f"πŸ” Backend log_event received:") + print(f" operation: {operation}") + print(f" step: {step}") + print(f" BEFORE step_completions: {progress.step_completions}") + + # Store email if provided and not already set + if email and not progress.participant_email: + progress.participant_email = email + + # Add timestamped event to logs + event = { + "timestamp": datetime.now().isoformat(), + "step": step, + "operation": operation, + "data": data + } + progress.activity_logs.append(event) + + # Track operation completion + step_key = str(step) + if step_key not in progress.step_completions: + progress.step_completions[step_key] = [] + if operation not in progress.step_completions[step_key]: + progress.step_completions[step_key].append(operation) + print(f" βœ… Added {operation} to step {step_key}") + else: + print(f" ⏭️ Skipped {operation} (already exists)") + + print(f" AFTER step_completions: {progress.step_completions}") + + progress.save() + + # Serialize AFTER transaction completes + serializer = self.serializer_class(progress) + return Response(serializer.data, status=status.HTTP_200_OK) + + except Exception as e: + return Response( + {"error": str(e)}, + status=status.HTTP_400_BAD_REQUEST + ) + + @action(detail=False, methods=["post"]) + def submit_step(self, request, **kwargs): + """Submit current step and advance to next.""" + assignment_id = kwargs.get("assignment_id") + submitted_step = request.data.get("step") + + try: + with transaction.atomic(): + progress, created = ActivityProgress.objects.select_for_update().get_or_create( + assignment_id=assignment_id + ) + + # If a step was submitted, use it as the step being completed + # This ensures the user's actual position is used, not stale DB state + if submitted_step is not None: + submitted_step = int(submitted_step) + # Allow setting the step if it's valid (1-4) + if 1 <= submitted_step <= 4: + print(f"πŸ“ Submitted step: {submitted_step}, stored step was: {progress.current_step}") + # Set current_step to the submitted step (trust the frontend) + progress.current_step = submitted_step + + # Save any question responses + responses = request.data.get("question_responses", {}) + progress.question_responses.update(responses) + + # Advance to next step (max 4) + if progress.current_step < 4: + old_step = progress.current_step + progress.current_step += 1 + print(f"βœ… Advancing from step {old_step} to step {progress.current_step}") + + progress.save() + + # Refresh from database to ensure fresh data + progress.refresh_from_db() + serializer = self.serializer_class(progress) + return Response(serializer.data, status=status.HTTP_200_OK) + + except ActivityProgress.DoesNotExist: + return Response( + {"error": "Activity progress not found"}, + status=status.HTTP_404_NOT_FOUND + ) + except (ValueError, TypeError) as e: + return Response( + {"error": f"Invalid step value: {e}"}, + status=status.HTTP_400_BAD_REQUEST + ) + + @action(detail=False, methods=["post"]) + def save_response(self, request, **kwargs): + """Save a question response without advancing step.""" + assignment_id = kwargs.get("assignment_id") + + try: + progress, created = ActivityProgress.objects.get_or_create( + assignment_id=assignment_id + ) + + question_id = request.data.get("question_id") + response_text = request.data.get("response") + + if question_id and response_text is not None: + progress.question_responses[question_id] = response_text + progress.save() + + serializer = self.serializer_class(progress) + return Response(serializer.data, status=status.HTTP_200_OK) + + except Exception as e: + return Response( + {"error": str(e)}, + status=status.HTTP_400_BAD_REQUEST + ) + + @action(detail=False, methods=["post"]) + def save_audio_state(self, request, **kwargs): + """Save current audio state for persistence across activities.""" + assignment_id = kwargs.get("assignment_id") + + try: + with transaction.atomic(): + progress, created = ActivityProgress.objects.select_for_update().get_or_create( + assignment_id=assignment_id + ) + + # Extract audio state from request + audio_url = request.data.get("audio_url") + edit_history = request.data.get("edit_history") + metadata = request.data.get("metadata") + + # Update audio state fields + if audio_url is not None: + progress.current_audio_url = audio_url + if edit_history is not None: + progress.audio_edit_history = edit_history + if metadata is not None: + progress.audio_metadata = metadata + + progress.save() + + print(f"πŸ’Ύ Saved audio state for assignment {assignment_id}") + print(f" audio_url: {progress.current_audio_url[:50] if progress.current_audio_url else None}...") + print(f" edit_history length: {len(progress.audio_edit_history)}") + + serializer = self.serializer_class(progress) + return Response(serializer.data, status=status.HTTP_200_OK) + + except Exception as e: + return Response( + {"error": str(e)}, + status=status.HTTP_400_BAD_REQUEST + ) diff --git a/teleband/submissions/migrations/0010_activity_progress.py b/teleband/submissions/migrations/0010_activity_progress.py new file mode 100644 index 0000000..39db432 --- /dev/null +++ b/teleband/submissions/migrations/0010_activity_progress.py @@ -0,0 +1,65 @@ +# Generated by Django 5.0.6 on 2025-10-17 16:49 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("assignments", "0036_assignment_unique_assignment_20240320_1310"), + ("submissions", "0009_submission_index"), + ] + + operations = [ + migrations.CreateModel( + name="ActivityProgress", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("current_step", models.PositiveIntegerField(default=1)), + ( + "step_completions", + models.JSONField( + default=dict, + help_text="Tracks completed operations per step: {step: [operation_type, ...]}", + ), + ), + ( + "activity_logs", + models.JSONField( + default=list, + help_text="Array of timestamped events: [{timestamp, step, operation, data}, ...]", + ), + ), + ( + "question_responses", + models.JSONField( + default=dict, + help_text="Student responses to embedded questions: {question_id: response, ...}", + ), + ), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ( + "assignment", + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + related_name="activity_progress", + to="assignments.assignment", + ), + ), + ], + options={ + "verbose_name": "Activity Progress", + "verbose_name_plural": "Activity Progress", + }, + ), + ] diff --git a/teleband/submissions/migrations/0011_add_participant_email.py b/teleband/submissions/migrations/0011_add_participant_email.py new file mode 100644 index 0000000..69b261b --- /dev/null +++ b/teleband/submissions/migrations/0011_add_participant_email.py @@ -0,0 +1,22 @@ +# Generated manually on 2025-10-17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("submissions", "0010_activity_progress"), + ] + + operations = [ + migrations.AddField( + model_name="activityprogress", + name="participant_email", + field=models.EmailField( + blank=True, + null=True, + help_text="Email from Qualtrics for survey matching" + ), + ), + ] diff --git a/teleband/submissions/migrations/0012_activityprogress_audio_edit_history_and_more.py b/teleband/submissions/migrations/0012_activityprogress_audio_edit_history_and_more.py new file mode 100644 index 0000000..e677e57 --- /dev/null +++ b/teleband/submissions/migrations/0012_activityprogress_audio_edit_history_and_more.py @@ -0,0 +1,36 @@ +# Generated by Django 5.0.6 on 2025-10-17 21:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("submissions", "0011_add_participant_email"), + ] + + operations = [ + migrations.AddField( + model_name="activityprogress", + name="audio_edit_history", + field=models.JSONField( + default=list, + help_text="Array of edit history states for undo/redo: [{url, effectName, metadata}, ...]", + ), + ), + migrations.AddField( + model_name="activityprogress", + name="audio_metadata", + field=models.JSONField( + default=dict, + help_text="Additional audio metadata: {duration, sampleRate, numberOfChannels, ...}", + ), + ), + migrations.AddField( + model_name="activityprogress", + name="current_audio_url", + field=models.TextField( + blank=True, help_text="Current audio blob URL or file path", null=True + ), + ), + ] diff --git a/teleband/submissions/models.py b/teleband/submissions/models.py index fb67d07..5971ae3 100644 --- a/teleband/submissions/models.py +++ b/teleband/submissions/models.py @@ -57,3 +57,54 @@ class Meta: def __str__(self): return f"{self.submission.id}: {self.file}" + + +class ActivityProgress(models.Model): + """Tracks student progress through DAW study activities.""" + + assignment = models.OneToOneField( + Assignment, on_delete=models.CASCADE, related_name="activity_progress" + ) + current_step = models.PositiveIntegerField(default=1) # 1-4 for Activities 1-4 + step_completions = models.JSONField( + default=dict, + help_text="Tracks completed operations per step: {step: [operation_type, ...]}" + ) + activity_logs = models.JSONField( + default=list, + help_text="Array of timestamped events: [{timestamp, step, operation, data}, ...]" + ) + question_responses = models.JSONField( + default=dict, + help_text="Student responses to embedded questions: {question_id: response, ...}" + ) + participant_email = models.EmailField( + blank=True, + null=True, + help_text="Email from Qualtrics for survey matching" + ) + + # Audio state persistence for cross-activity editing + current_audio_url = models.TextField( + blank=True, + null=True, + help_text="Current audio blob URL or file path" + ) + audio_edit_history = models.JSONField( + default=list, + help_text="Array of edit history states for undo/redo: [{url, effectName, metadata}, ...]" + ) + audio_metadata = models.JSONField( + default=dict, + help_text="Additional audio metadata: {duration, sampleRate, numberOfChannels, ...}" + ) + + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + class Meta: + verbose_name = "Activity Progress" + verbose_name_plural = "Activity Progress" + + def __str__(self): + return f"Assignment {self.assignment.id} - Step {self.current_step}" diff --git a/teleband/templates/assignments/assignment_list.html b/teleband/templates/assignments/assignment_list.html new file mode 100644 index 0000000..d98f2c3 --- /dev/null +++ b/teleband/templates/assignments/assignment_list.html @@ -0,0 +1,183 @@ +{% extends "base.html" %} + +{% block content %} + + +Download CSV +{% comment %} https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col#usage_notes {% endcomment %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% for assn in assignment_list %} + + {% if assn.submissions.all|length == 0 %} + + + + + + + + + + + + + + + + + + {% else %} + {% for sub in assn.submissions.all %} + {% for att in sub.attachments.all %} + + + + + + + + + + + + + + + + + {% if assn.activity.category == 'Create' %} + + {% else %} + + {% endif %} + + + + + + + + {% if assn.activity.category == 'Create' %} + + + + {% endif %} + {% endfor %} + {% endfor %} + {% endif %} + + {% endfor %} +
IDCoursePieceStudentAssignmentSubmissionsSubmission Attachment
assnididnameidnameplan idplan nameidinstrument idinstrument nameact idactivityinstrument idinstrument nameidcontentsubmittedgradeself gradeidfilesubmitted
{{ assn.id }}{{ assn.enrollment.course.id }}{{ assn.enrollment.course.name }}{{ assn.piece.id }}{{ assn.piece.name }}{{ assn.piece_plan.id }}{{ assn.piece_plan }}{{ assn.enrollment.user.id }}{{ assn.enrollment.instrument.id }}{{ assn.enrollment.instrument.name }}{{ assn.activity.id }}{{ assn.activity }}{{ assn.instrument.id }}{{ assn.instrument.name }}N/A
{{ assn.id }}{{ assn.enrollment.course.id }}{{ assn.enrollment.course.name }}{{ assn.piece.id }}{{ assn.piece.name }}{{ assn.piece_plan.id }}{{ assn.piece_plan }}{{ assn.enrollment.user.id }}{{ assn.enrollment.instrument.id }}{{ assn.enrollment.instrument.name }}{{ assn.activity.id }}{{ assn.activity }}{{ assn.instrument.id }}{{ assn.instrument.name }}{{ sub.id }} + Create, see below + {{ sub.content }}{{ sub.submitted }}{{ sub.grade }}{{ sub.self_grade }}{{ att.id }}{{ att.file }}{{ att.submitted }}
+
+
+
+
+ +
+{% endblock content %} + +{% block custom_javascript %} + + +{% endblock custom_javascript %} \ No newline at end of file diff --git a/teleband/templates/base.html b/teleband/templates/base.html index a7f0bff..48823e8 100644 --- a/teleband/templates/base.html +++ b/teleband/templates/base.html @@ -112,5 +112,8 @@ {% endcomment %} {% endblock inline_javascript %} + + {% block custom_javascript %} + {% endblock custom_javascript %} diff --git a/teleband/templates/courses/course_list.html b/teleband/templates/courses/course_list.html new file mode 100644 index 0000000..096682c --- /dev/null +++ b/teleband/templates/courses/course_list.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} + +{% block content %} +{% for course in course_list %} +{{course.name}} +{% endfor %} +{% endblock content %} \ No newline at end of file diff --git a/teleband/users/api/views.py b/teleband/users/api/views.py index 988cdc0..f47be9f 100644 --- a/teleband/users/api/views.py +++ b/teleband/users/api/views.py @@ -6,6 +6,7 @@ from django.contrib.auth.models import Group from django.core.exceptions import ValidationError from django.core.validators import validate_email +from django.utils.timezone import now from rest_framework import permissions from rest_framework import status @@ -124,5 +125,19 @@ def delete(self, request, *args, **kwargs): except Token.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) + # with thanks to https://chatgpt.com/share/66ee4879-8d84-800f-b18c-7d63efbb2c43 + def post(self, request, *args, **kwargs): + # Call the original implementation to get the authenticated user and token + response = super().post(request, *args, **kwargs) + token = Token.objects.get(key=response.data["token"]) + user = token.user + + # Update last_login and save the user instance + user.last_login = now() + user.save() + + # Return the response with the token and any additional data + return response + obtain_delete_auth_token = ObtainDeleteAuthToken.as_view() diff --git a/teleband/utils/health_check.py b/teleband/utils/health_check.py new file mode 100644 index 0000000..006eb3f --- /dev/null +++ b/teleband/utils/health_check.py @@ -0,0 +1,11 @@ +from django.http import HttpResponse + +class AlbHealthcheckMiddleware: + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + # Bypass host validation path for ALB health checks + if request.path == "/healthz": + return HttpResponse("ok", status=200) + return self.get_response(request) \ No newline at end of file diff --git a/teleband/utils/storages.py b/teleband/utils/storages.py index bc9e506..75ece3b 100644 --- a/teleband/utils/storages.py +++ b/teleband/utils/storages.py @@ -3,9 +3,10 @@ class StaticRootS3Boto3Storage(S3Boto3Storage): location = "static" - default_acl = "public-read" + default_acl = None class MediaRootS3Boto3Storage(S3Boto3Storage): location = "media" + default_acl = None file_overwrite = False