- Documentation - underway using mkdocs
- Initial setup
- env file
- docker build process + describing
./compose.sh
+overrides.yml
- Add streaming instructions page for users
- AutoDJ weighting concept
- Harbor architecture and concepts
- AutoDJ
- Finish Zoom broadcasting
- needs a second pass, and a better show length picker that limits users time based on google calendar
- time remaining of current Zoom Show
- Indicator about why the zoom form doesn't show for calendar based auth
- deal with invalid meeting popup
- Code cleanup
- Clean up Dockerfiles stripping dev stuff
- Go over
TODO
s andXXX
s in codebase - Pin versions in all Dockerfiles
- Pin Python packages (using Poetry), remove dev dependencies
- Pin nginx module versions
- Unit tests for at least the Django app - skeleton done
- major second pass, fix broken tests, aim for high coverage (or 100%)
- Mature
strip_blank
implementation - Convert some Django views to class-based
-
api
package -
webui
package
-
- Player for local icecast on status page
- Make track log a more generic playout log, with asset playing on metadata one particular type.
- Convert logging to redis list + blocking list pop (so web server doesn't have to be up to log)
- Kick off DJs outside of calendar times (with a grace period)
- Add make active/disable quick actions for playlists and stopsets
- Add scheduled time inline to broadcasts asset creation
- Hide skip track button for lower precedence sources
- Copy change: rename "precedence" -> "priority"
- BUG: Edit profile seems to have re-enabled harbor access type
- Thoroughly test new ffprobe + ffmpeg flows for audio assets + task
- Harbor: use an add_timeout poll to check for
status_json()
changes rather than hooksupdate_status[_ref]()
hooks throughout the code. - GCal shows stored as
ManyToManyField
- add show name to JSON, useful for Zoom or Liquidsoap metadata am I sure I want this??? 👅
- Tasks to purge failed broadcasts/assets + unstuck processing ones, clean sftpgo files
- Re-try broadcasts for which underlying assets which aren't
READY
every 2 seconds. Fix asset's inline broadcasts. - Remove
sse
service and use nginx module nchan - Add sftp service using sftpgo
- Deal with WinSCP's
.filepart
situation - Add ability to use SSH authorized keys.
- Deal with WinSCP's
- Rename uploads with valid contents but wrong extension (ie file that's an mp3 but named wav)
- User emails
- Users can update their email address in their profile (
EMAIL_ENABLED
+ verification only) - We don't really need a postfix container. Just configure Django to send email directly.
- Create user flow that sends user an email (and possibly they fill out their details)
- Consistent "From: " emails
- Add account username to set password emails
- Users can update their email address in their profile (
- rtmp streaming using nginx-rtmp
- huey logs seem to print twice / django logging seems overly verbose (maybe just in gunicorn?)
- use multirun for nginx (nginx + certbot), and icecast (icecast + notify) containers
- investigate whether asset models should use
clean()
orfull_clean()
? (Does it only matter with unique indexes?) - "There were errors on this page" message for forms with errors at top of page. Possible mixin
that adds a message when
form_invalid(...)
-
Don't organize assets by folder prefixes that say where they came from likeupload/
,external/
, etc instead organize by<artist-normalized-and-non-empty>/<album-normalized-and-non-empty>/
- Kind of difficult to do, since we don't have a model with metadata yet at time of
upload_to=
function
- Kind of difficult to do, since we don't have a model with metadata yet at time of
- Remove bulk upload ui now that sftp works
- On status page, move server uptime with some less pertinent details like version, etc below the source list
- first name, last name => single field (dj name or display name)
- SFTP audio asset playlists based on first folder instead of a user preference
- way to convert asset types, potentially using https://github.com/ninemoreminutes/django-admin-object-actions
- After asset.file.save(..., save=False) is called file is created, whether we create the asset or not
django-unused-media
good candidate, but may interfere with constance's file fields
- Admin css for input type=file busted
- Protect assets via nginx's
internal;
flag - Skips to playout log
- Rename playout log
- Don't use JSON field for show times so we get each show individually for status page and get show names
- Update user iteration hack in webui/views.py:StatusView.get_upcoming_status_data()
- Verify sftp playlist uploads aren't broken when playlists are disabled
- Configure pre-recorded broadcasts to come with lower priority than live sources
- Test stream
- Empty playlist counted as enabled with
weight = 1.0
, via feature flag - Harbor + upstream watchdog task
- Email + text notifications on CRITICAL logger?
- Make sure TZ is working properly on shouting fire server
- Remove the "Note: You are 3 hours ahead of server time." helper
- Show banner for users who are Zoom broadcasting to go to Zoom page
- Clean up many to many relation verbose names
Gcalshow-user relationship: GCalShow_users object (2465)
- Archiving of shows
- Different upstream output types (HLS, RTMP using ffmpeg like iHeartRadio used?)
- Show live info about zoom on status page, similar to
dj_harbor_source
+live_user
in status JSON - S3 as a storage source using django-storages
- Compression and normalization on a per-DJ basis. (Add a liquidsoap
switch()
to change between compressed or not). Hard part is what are the rules for triggering this? - Move liquidsoap harbor source editing into webui, but we could still only link it from admin.
Remove
@admin.site.register_view()
, associated code, and simplify admin links. Rename "Miscellaneous Configuration" to "Additional Modules". Rethink how admin nav links are generated. - Radio buttons for ban times
- Stock error pages for nginx, in particular if app doesn't boot
- Record shows on the calendar, or just record everything
- S3 storage will come in handy at that point
- public API
- Get fancy with stopsets, create a telnet requests queue for them specifically so they get
scheduled on time. Could use something similar for autodj requests. Would be a track sensitive fallback:
1. stopsets via
requests.queue()
, these happen on a timer in liquidsoap or from huey 2. autodj requests viarequests.queue()
happen the web UI (do we need some way to cap them?) 3. regular autodj viarequest.dynamic.list()
- Ban DJs dynamically on the ban page (not just live ones) using select2
- Skip button appears when it shouldn't
- Downloaded assets
- Some workflow for dynamically allowing unlimited time
- Upload progress meter
- Queue for AutoDJ's "up next"
- Show password feature for hidden fields
- Use same harbor.liq script for test as live
- Stop using Django admin, instead roll everything on our own.
- user preference for harbor auth = always to be kicked off at the end of their show anyway
- Twilio integration that forwards calls to live DJs + works with voicemail/text/dial to listen