Giter Club home page Giter Club logo

lainonlife's People

Contributors

barrucadu avatar dependabot[bot] avatar fuerbringer avatar pussinboot avatar typicalfence avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

lainonlife's Issues

Add a fallback stream

It's unlikely, but MPD can go wrong. Adding a fallback stream to the /mpd-*.{mp3,ogg} mountpoints would at least prevent the radio from going totally dead until I fix things.

Ideally, the source of this stream should not be another MPD instance. Just something simple that can loop a single audio track.

The 404 music would work fine.

This is a server configuration change and so implementing it would kick everyone off the stream.

Set Referrer-Policy header

https://scotthelme.co.uk/a-new-security-header-referrer-policy/

This is especially useful when #32 is implemented, which may well leak CSRF tokens into GET parameters (and so the default referrer for any external links.)

strict-origin-when-cross-origin seems like a good default. This sends the full URL when going to the same origin, the origin when going to another origin, and nothing when downgrading from https to http:

Source Destination Referrer
https://lainon.life/foo/ https://lainon.life/bar/ https://lainon.life/foo/
https://lainon.life/foo/ https://example.com/ https://lainon.life/
https://lainon.life/foo/ http://lainon.life/bar/ NULL
https://lainon.life/foo/ http://example.com/ NULL

This is a server configuration change and so implementing it would kick everyone off the stream.

Vapourwave channel?

Currently got a few Vapourwave albums on everything, worth having a dedicated channel?

Improve very inefficient use of MPD clients

backend.py opens a new MPD client every time a playlist is requested, which is every 15 seconds per listener. This is very inefficient: it should open the clients when it starts, and re-open them if they drop for any reason, returning the current error if reconnection fails.

Not so great:

Jun 07 02:03:23 lainonlife mpd[27198]: client: [118420] closed
Jun 07 02:03:23 lainonlife mpd[22299]: client: [111921] closed
Jun 07 02:03:23 lainonlife mpd[27198]: client: [118419] closed
Jun 07 02:03:23 lainonlife mpd[25580]: client: [536400] closed
Jun 07 02:03:23 lainonlife mpd[25580]: client: [536399] closed
Jun 07 02:03:23 lainonlife mpd[25580]: client: [536398] closed
Jun 07 02:03:23 lainonlife mpd[22299]: client: [111920] closed
Jun 07 02:03:23 lainonlife mpd[27198]: client: [118418] closed
Jun 07 02:03:23 lainonlife mpd[25580]: client: [536397] closed
Jun 07 02:03:23 lainonlife mpd[25580]: client: [536396] closed
...
Jun 07 02:02:44 lainonlife mpd[22299]: client: [111919] closed
Jun 07 02:02:44 lainonlife mpd[25580]: client: [536395] closed
Jun 07 02:02:44 lainonlife mpd[27198]: client: [118417] closed
Jun 07 02:02:44 lainonlife mpd[25580]: client: [536394] closed
Jun 07 02:02:44 lainonlife mpd[22299]: client: [111918] closed
Jun 07 02:02:44 lainonlife mpd[27198]: client: [118416] closed
Jun 07 02:02:44 lainonlife mpd[25580]: client: [536393] closed
Jun 07 02:02:44 lainonlife mpd[25580]: client: [536392] closed
Jun 07 02:02:44 lainonlife mpd[22299]: client: [111917] closed
Jun 07 02:02:44 lainonlife mpd[25580]: client: [536391] closed

Display donate page inside modal window

I think it would make more sense to have the donate page display inside a modal window instead of having it as a separate .html page. So basically like https://lainon.life/#schedule. Also the stream wouldn't be interrupted that way. The donate.html page could be kept for external linking purposes.

New track/album request form

There's a feedback thread on /music/, but something directly on the site would be nice as well. Maybe this would work best as a generic comment form, with suggested topics (eg "music you want").

Steps:

  1. Implement a pretty form as an HTML page.
  2. Implement the backend functionality. The upload_voice function should be helpful.
  3. Link from the radio page.

Websockets instead of AJAX

Currently there's a buttload of AJAX requests. Every client is frequently talking to (1) Icecast, for the number of listeners and channel description; and (2) backend.py, for the current playlist.

All of this data is something which changes relatively infrequently, so it would be nice to use something push-based rather than pull-based.

Steps:

  1. Look into Python websocket server libraries
    • How would this work with Python's poor concurrency?
    • How would this work with Flask? If it doesn't, another backend service would be needed.
      • This would require restarting nginx, kicking everyone off the current stream again...
    • Maybe it would be better to rewrite the backend in (eg) Haskell, which I know how to do this in, and which has (a) good concurrency and (b) good libraries.
  2. Reimplement the playlist client AJAX with websockets.
  3. Talk to Icecast in the backend, and replace that client AJAX with websockets too.
    • Is there something other than pull-based HTTP which can be done here for the Icecast communication?

Require javascript?

Currently index.html works for both javascript and non-javascript users, although the non-javascript behaviour is greatly degraded.

This leads to significant complication in the code, however. It also means that it's hard to implement features like (eg) the requests form being a modal window with a javascript submission, rather than a separate page with a regular POST submission. It would be nice to keep everything on one page, to avoid navigating away from the audio stream.

A <noscript> tag could be used to point people to the raw streams at /radio/.

Metric script weirdness last night

From the systemd journal:

Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:10:35Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:10:05Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:09:34Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:09:04Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:08:33Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:08:03Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:07:32Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:07:01Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:06:31Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:06:00Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:05:30Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:04:59Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:04:29Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:03:58Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:03:27Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:02:57Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:02:26Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:01:56Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:01:25Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:00:55Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-07T00:00:24Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:59:53Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:59:23Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:58:52Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:58:22Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:57:51Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:57:21Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:56:50Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:56:19Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:55:49Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:55:18Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:54:48Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:54:17Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:53:47Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:53:16Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:52:45Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:52:15Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:51:44Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:51:14Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:50:43Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:50:12Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:49:42Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:49:11Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:48:41Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:48:10Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:47:40Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:47:09Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:46:38Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:46:08Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:45:37Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:45:07Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:44:36Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:44:06Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:43:35Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:43:04Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:42:34Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:42:03Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:41:33Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:41:02Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:40:31Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:40:01Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:39:30Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:39:00Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:38:29Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:37:59Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:37:28Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:36:58Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:36:27Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:35:56Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:35:26Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:34:55Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:34:25Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:33:54Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:33:24Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:32:53Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:32:22Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:31:52Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:31:21Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:30:51Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:30:20Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:29:50Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:29:19Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:28:48Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:28:18Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:27:47Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:27:17Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:26:46Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:26:16Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:25:45Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:25:14Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:24:44Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:24:13Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:23:43Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:23:12Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:22:42Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:22:11Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:21:40Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:21:10Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:20:39Z
Jun 07 02:04:36 lainonlife python3[22806]: Sending report for 2017-06-06T23:20:09Z
Jun 07 02:04:36 lainonlife systemd-journald[460]: Suppressed 105 messages from /system.slice/metrics.service

That shouldn't happen.

Refresh playlist at end of song

The playlist only updates every 15 seconds, so the user will be up to 15s into the next song when the current one ends. Not terribly great UX.

http-backend service was hanging for some reason

I was having difficulty loading the site and noticed that there had been no journalctl entries for two hours. Attempting to load the playlist from another machine hung:

--2017-10-14 14:03:51--  https://lainon.life/playlist/cyberia.json
Resolving lainon.life (lainon.life)... 2001:41d0:1:5394::1, 91.121.0.148
Connecting to lainon.life (lainon.life)|2001:41d0:1:5394::1|:443... connected.
HTTP request sent, awaiting response... ^C

I did not try to load the playlist locally, so I don't know if this was an nginx or a http-backend issue.

Restarting the service fixed it. Here's the journal showing the latest requests received before the restart and the restart itself:

Oct 14 14:04:11 lainonlife bash[20651]:  * Running on http://127.0.0.1:8002/ (Press CTRL+C to quit)
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: MarkupSafe>=0.23 in ./__venv__/lib/python3.5/site-packages (from Jinja2>=2.4->Flask>=0.12.0->-r requirements.txt (line 2))                                                                          
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: python-dateutil>=2.6.0 in ./__venv__/lib/python3.5/site-packages (from influxdb->-r requirements.txt (line 8))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: idna<2.6,>=2.5 in ./__venv__/lib/python3.5/site-packages (from requests->-r requirements.txt (line 7))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: urllib3<1.22,>=1.21.1 in ./__venv__/lib/python3.5/site-packages (from requests->-r requirements.txt (line 7))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: chardet<3.1.0,>=3.0.2 in ./__venv__/lib/python3.5/site-packages (from requests->-r requirements.txt (line 7))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: certifi>=2017.4.17 in ./__venv__/lib/python3.5/site-packages (from requests->-r requirements.txt (line 7))                                                                                          
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: pytz in ./__venv__/lib/python3.5/site-packages (from apscheduler->-r requirements.txt (line 6))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: setuptools>=0.7 in ./__venv__/lib/python3.5/site-packages (from apscheduler->-r requirements.txt (line 6))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: tzlocal>=1.2 in ./__venv__/lib/python3.5/site-packages (from apscheduler->-r requirements.txt (line 6))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: six>=1.4.0 in ./__venv__/lib/python3.5/site-packages (from apscheduler->-r requirements.txt (line 6))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: Jinja2>=2.4 in ./__venv__/lib/python3.5/site-packages (from Flask>=0.12.0->-r requirements.txt (line 2))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: itsdangerous>=0.21 in ./__venv__/lib/python3.5/site-packages (from Flask>=0.12.0->-r requirements.txt (line 2))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: Werkzeug>=0.7 in ./__venv__/lib/python3.5/site-packages (from Flask>=0.12.0->-r requirements.txt (line 2))                                                                                          
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: click>=2.0 in ./__venv__/lib/python3.5/site-packages (from Flask>=0.12.0->-r requirements.txt (line 2))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: influxdb in ./__venv__/lib/python3.5/site-packages (from -r requirements.txt (line 8))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: requests in ./__venv__/lib/python3.5/site-packages (from -r requirements.txt (line 7))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: apscheduler in ./__venv__/lib/python3.5/site-packages (from -r requirements.txt (line 6))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: tinydb in ./__venv__/lib/python3.5/site-packages (from -r requirements.txt (line 5))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: flask-login in ./__venv__/lib/python3.5/site-packages (from -r requirements.txt (line 4))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: python-mpd2>=0.5.5 in ./__venv__/lib/python3.5/site-packages (from -r requirements.txt (line 3))                                                                                                    
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: Flask>=0.12.0 in ./__venv__/lib/python3.5/site-packages (from -r requirements.txt (line 2))
Oct 14 14:04:10 lainonlife bash[20651]: Requirement already satisfied: docopt>=0.6.2 in ./__venv__/lib/python3.5/site-packages (from -r requirements.txt (line 1))
Oct 14 14:04:10 lainonlife bash[20651]: The directory '/var/empty/.cache/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -
Oct 14 14:04:10 lainonlife bash[20651]: The directory '/var/empty/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want s
Oct 14 14:04:07 lainonlife systemd[1]: Started HTTP backend service.
Oct 14 14:04:07 lainonlife systemd[1]: Stopped HTTP backend service.
Oct 14 14:04:07 lainonlife systemd[1]: Stopping HTTP backend service...                                                                                                                                                                                                    
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -                                                                                                                                                   
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -                                                                                                                                                   
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
Oct 14 12:01:22 lainonlife bash[20093]: 127.0.0.1 - - [14/Oct/2017 12:01:22] "GET /playlist/cyberia.json HTTP/1.0" 200 -
...

As there should be a request to the playlist every 15 seconds, at least, it's very suspicious that there were apparently no requests for two hours. This means that something was going wrong processing all requests: either nginx failing to deliver them (and just hanging internally for some reason) or http-backend failing to process them.

Make the site responsive

I think it would be nice if the site would be responsive.

This is not that important, I guess, most people won't use it on a smartphone.
Nevertheless I think it would be a "nice to have"-feature.

I tend to use the site on the go, on mine, so I would be happy about it. ^^

Lolicore channel?

Got this request:

album: Dancefloor Degrader
url: http://lolicore.ml/DanceCorps/[DCRPS010]%20Goreshit%20-%20Dancefloor%20Degrader/
notes: I think there already is a bit of breakcore/lolicore, but I am not really sure tbh.
I am also not really sure if it is fitting, but I thought I suggest it anyway.

It's a classic lolicore album.

Maybe a breakcore/lolicore channel would be something but I think there aren't enough listeners.
artist: Goreshit

Maybe worth having a lolicore channel?

Add a stop button

Currently the pause button, when resumed, causes the player to continue where it left off. It's now behind the stream. Better behaviour would be to just resume from wherever the stream is up to.

Incorrect Peak Listeners Count

Something's (potentially) up on icecast's end, stepped through check_status in radio.js and it's working as it should but the listener_peak from status-json.xsl doesn't match what the graph dashboard says.

from lainon life

vs

from graph page

Custom player widget

The browser widget really doesn't fit in. Just a simple play button, progress bar, and time, of the appropriate colours (eg http://r-a-d.io/).

Notes:

  1. The current radio page works even if you have javascript, it just has no interactive features and tells you to turn on javascript. That graceful degradation should be kept.
    • It even works if you have CSS disabled, but then it looks bad as well.
  2. The check_playlist function gets the duration and progress of the current track. These can be used to correct the progress bar, with constant-rate advancement happening otherwise.

Different passwords for MPD and livestreamers

Currently the same password is used for the /$channel.$ext and /mpd-$channel.$ext streams (although it is a per-channel password). This means a DJ could stream to the MPD mountpoint. It would be better to have different passwords, to prevent this.

This is a server configuration change and so implementing it would kick everyone off the stream.

Vote to skip?

The current playlist is planned hours in advance. I do think that occasionally playing a complete album is nicer than purely global shuffle, but it does mean we can't really have a request form like r/a/dio. The next best thing is a link to vote to skip an upcoming track.

Steps:

  1. Add an AJAX-powered button to send a "skip track" request to the backend.
  2. Keep track of number of listeners of the channel.
    • Maybe it should only be listeners who are listening via lainon.life, rather than lainchan.org or other sites. Those other people won't be voting.
    • The number of listeners on lainon.life can be measured by logging unique IPs over a short time.
  3. Keep track of number of skip votes.
  4. Remove the track from the playlist when the skip votes reach a certain proportion of the listeners.

Absolute include paths

Is there a reason why the backend scripts file-list.sh and backend.py are reading files from an absolute path (/srv/http)?

I'm not much of a Python programmer, but I could imagine this causing issues when deploying the application on different kinds of operating systems. Debian for example uses /var/www/html as webserver root.

So basically I'm suggesting using relative paths. That way the web application should be able to run from any directory.

Script support for livestreaming

Fortunately, Icecast makes livestreaming very simple. There's just a little work that needs to be done for it to be seamless.

  1. Some sort of schedule on the website. r/a/dio (click "Schedule") just has a box appear with javascript. We can use something like that too, with an appropriate non-javascript fallback.

  2. The playlist_for function in backend.py needs to be aware that the playlist may not come from MPD:

    • For the current track: perhaps a file at a designated location would work; even better would be extracting metadata from the stream from Icecast, if possible, with some fallback.
    • The "Last Played" and "Queue" can just be blank.
    • The duration of the current track can be unspecified, with radio.js and player.js displaying that nicely somehow.
  3. A script to start a stream:

    • Pause MPD
    • Turn off the Icecast outputs
    • Do whatever needs to be done for playlist_for in backend.py to know there is a stream
  4. A script to stop a stream:

    • Unpause MPD
    • Turn on the Icecast outputs
    • Undo whatever was done to backend.py

The MPD and Icecast configs are not very exciting, but in case they are of use:

icecast.xml:

<!-- There is nothing exciting here.  I have set the hostname and passwords, that's it.  Everything else is default. -->
<icecast>
  <hostname>lainon.life</hostname>

  <authentication>
    <admin-user>admin</admin-user>
    <admin-password>password</admin-password>
  </authentication>

  <paths>
    <logdir>/var/log/icecast</logdir>
    <!-- These paths will depend on your distro -->
    <adminroot>/nix/store/d7gk1q4crva10l8785aa8fwm79r3j62l-icecast-2.4.1/share/icecast/admin</adminroot>
    <webroot>/nix/store/d7gk1q4crva10l8785aa8fwm79r3j62l-icecast-2.4.1/share/icecast/web</webroot>
    <alias source="/" dest="/status.xsl"/>
  </paths>

  <listen-socket>
    <port>8000</port>
    <bind-address>::</bind-address>
  </listen-socket>   

  <security>
    <chroot>0</chroot>
    <changeowner>
        <user>nobody</user>
        <group>nogroup</group>
    </changeowner>
  </security>

  <authentication>
  <source-password>password</source-password>
  <relay-password>password</relay-password>
</authentication>

</icecast>

mpd-cyberia.conf:

# These paths will depend on your system
music_directory     "/srv/radio/music/cyberia"
playlist_directory  "/srv/radio/data/cyberia/playlists"
db_file             "/srv/radio/data/cyberia/db"
state_file          "/srv/radio/data/cyberia/state"
sticker_file        "/srv/radio/data/cyberia/sticker.sql"
log_file            "syslog"
bind_to_address     "127.0.0.1"
port                "6601"

audio_output {
  name        "cyberia (ogg)"
  description "classic lainchan radio: electronic, chiptune, weeb"
  type        "shout"
  encoder     "vorbis"
  host        "localhost"
  port        "8000"
  mount       "/cyberia.ogg"
  user        "source"
  password    "password"
  quality     "3"
  format      "44100:16:2"
  always_on   "yes"
}

audio_output {
  name        "cyberia (mp3)"
  description "classic lainchan radio: electronic, chiptune, weeb"
  type        "shout"
  encoder     "lame"
  host        "localhost"
  port        "8000"
  mount       "/cyberia.mp3"
  user        "source"
  password    "password"
  quality     "3"
  format      "44100:16:2"
  always_on   "yes"
}


audio_output {
  type "null"
  name "null"
}

For dealing with the MPD outputs, see the python-mpd2 docs.

Deprecate /radio/ route (301 it to :8000)

To avoid an ugly http://lainon.life:8000 URL, the stream is currently proxied through nginx, which has two downsides:

  1. Any restart of nginx kicks people off the stream.
  2. This adds SSL overhead.

It would be best to get a second IP, point stream.lainon.life to that IP, and have Icecast listen on stream.lainon.life:80.

This is a server configuration change and so implementing it would kick everyone off the stream.

Set up a staging site

As evidenced by this morning, just checking configuration is syntactically valid and looks reasonable before deploying is a good way to cause downtime.

Fortunately, NixOS containers should make it trivial to run a staging site.

Prioritise new albums

Similar to #10 but different.

It would be nice to pick a new album, if there are any, when deciding which one to schedule.

There could simply be a list of which albums have been played, or maybe MPD's sticker mechanism could be used to store that info in its database.

Add a donate page

I got an email from someone wanting to donate for server costs.

This is quite possibly the first ever non-scam email I've got out of the blue offering me money.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.