2023-04-07 10:27:40 +00:00
[![License: MIT ](https://img.shields.io/badge/License-LGPL-blue.svg )](https://opensource.org/license/lgpl-3-0/)
[![Release ](https://shields.io/badge/dynamic/json.svg?label=release&url=https://phlaym.net/git/api/v1/repos/phlaym/moshing-mammut/releases&query=$[0].tag_name )](https://phlaym.net/phlaym/moshing-mammut/releases)
2023-04-02 11:19:42 +00:00
# Moshing Mammut
2023-03-19 16:00:49 +00:00
2023-04-02 11:19:42 +00:00
The fine folks on the [metalhead.club Mastodon Server ](https://metalhead.club ) occasionally share like to share
what they're currently listening to.
Having a quick overview over what is being posted can be a great way to discover new music!
2023-03-19 16:00:49 +00:00
2023-04-02 11:19:42 +00:00
# Technical Notes
2023-03-19 16:00:49 +00:00
2023-04-02 11:19:42 +00:00
This is fairly simple from a technical point of view! metalhead.club's local timeline is being watched using the
Mastodon Streaming API over a Websocket. Every time a new post arrives, it is checked if it contains any music by
2023-04-24 17:38:13 +00:00
checking included hashtags and URLs. A list of tags can be found in [the configuration ](.env.EXAMPLE ).
Additionally, links are vetted if they are music by checking if https://song.link finds info on them.
2023-03-19 16:00:49 +00:00
2023-04-02 11:19:42 +00:00
If a post passes this check it is saved to a SQLite database.
2023-03-19 16:00:49 +00:00
2023-04-02 11:19:42 +00:00
The UI is built using [SvelteKit ](https://kit.svelte.dev ). The initial page is rendered on the server, and works even
without Javascript. If Javascript is enabled, new posts are fetched every 10 seconds, but there are plans to switch
to Websockets instead. See #10 .
2023-03-19 16:00:49 +00:00
2023-04-02 11:19:42 +00:00
# The ~~Mastodon~~ Elephant in the Room
2023-03-19 16:00:49 +00:00
2023-04-02 11:19:42 +00:00
> So, are you just going to save other peoples posts into your own database?
2023-03-19 16:00:49 +00:00
2023-04-02 11:19:42 +00:00
I'm afraid so, and I'm not particularly happy about this. I've thought about how to do it without and it doesn't look
good.
2023-03-19 16:00:49 +00:00
2023-04-02 11:19:42 +00:00
My initial plan was to search for posts and work with the search results, however
Mastodon doesn't offer full text search, so this would be limited to work with hashtags.
I can see that there are plenty of posts using only descriptions and links without a corresponding hashtag that would
be missed. This isn't a great solution.
2023-03-19 16:00:49 +00:00
2023-04-02 11:19:42 +00:00
Another idea was to store only URLs of posts and resolve the content and account information live.
2023-04-11 14:02:54 +00:00
This would be better, but I'm _still_ storing post information while also slowing the app down and introduce more code
2023-04-02 11:19:42 +00:00
complexity. I'm willing to make this change if people prefer this though.
2023-03-19 16:00:49 +00:00
2023-04-02 11:19:42 +00:00
Additionally, I ended up adding a few things which turned out to be not needed:
The `tags` table (tags are included in the post's content and I don't do anything separately with tags) and
2023-04-12 18:47:23 +00:00
~~`accounts.username`~~ (s being used for #18 ) ~~and `accounts.avatar_static`~~ (has been removed). I will keep these in until the initial wave of feedback arrives, and
2023-04-02 11:19:42 +00:00
remove it if no new features required them.
2023-03-19 16:00:49 +00:00
2023-04-02 11:19:42 +00:00
I'll gladly accept any help in coming up with a good solution which doesn't need to store anything at all!
2023-03-19 16:00:49 +00:00
2023-04-02 13:26:19 +00:00
# Set Up
This might not be the ideal setup to run this, but here's how I am doing it. Instructions are for running on a Debian
or Debian derivative, using Apache as HTTP Proxy. Other setups are possible, but not covered here.
By default, NVM is used to install NodeJS, but you can install it any way you want.
2023-04-04 10:32:04 +00:00
This is based on [SvelteKit's instructions ](https://kit.svelte.dev/docs/adapter-node#deploying ) and [How To Deploy Node.js Applications Using Systemd and Nginx ](https://www.digitalocean.com/community/tutorials/how-to-deploy-node-js-applications-using-systemd-and-nginx )
2023-04-02 13:26:19 +00:00
#### On your server
2023-04-04 10:32:04 +00:00
Install Apache2 if not already installed.
2023-04-02 13:26:19 +00:00
2023-04-04 10:32:04 +00:00
Copy `apache2.conf.EXAMPLE` and `moshing-mammut.service.EXAMPLE` to your server.
Set up a user for the app: `useradd -mrU moshing-mammut`
Switch to your newly created user: `su moshing-mammut`
Set up NVM:
```
$ cd
$ curl https://raw.github.com/creationix/nvm/master/install.sh | sh
$ source ~/.nvm/nvm.sh
$ nvm install --lts
```
Create a directory for the app. This will be called `$APP_DIR` from now on. I use `/home/moshing-mammut/app` .
Enter `$APP_DIR` .
Place `package-lock.json` and `start.sh.EXAMPLE` in this directory.
Run `npm ci --omit dev` to install the dependencies.
Rename `start.sh.EXAMPLE` to `start.sh` and set the path to your NVM.
If you do not have NVM installed, simply remove the line and make sure your node executable can be found either by
specifying the full path or by adding it to your $PATH.
Exit out of your `moshing-mammut` user shell.
2023-04-02 13:26:19 +00:00
Copy `apache2.conf.EXAMPLE` to `/etc/apache2/sites-available/moshingmammut.conf` and replace `ServerName` with your
Domain. If you do not need or want SSL support, remove the whole `<IfModule mod_ssl.c>` block.
If you do, add the path to your SSLCertificateFile and SSLCertificateKeyFile.
Copy `moshing-mammut.service.EXAMPLE` to `/etc/systemd/system/moshing-mammut.service`
2023-04-04 10:32:04 +00:00
and set your `User` , `Group` , `ExecStart` and `WorkingDirectory` accordingly.
2023-04-02 13:26:19 +00:00
#### On your development machine
2023-04-24 17:38:13 +00:00
Copy `.env.EXAMPLE` to `.env` and add your `YOUTUBE_API_KEY` and `ODESLI_API_KEY` .
2023-04-02 13:26:19 +00:00
To obtain one follow [YouTube's guide ](https://developers.google.com/youtube/registering_an_application ) to create an
2023-04-11 16:39:02 +00:00
_API key_.
2023-06-20 06:20:30 +00:00
If `YOUTUBE_API_KEY` is unset, no playlist will be updated. Also, _all_ YouTube links will be treated as music videos,
because the API is the only way to check if a YouTube link leads to music or something else.
2023-04-24 17:38:13 +00:00
If `ODESLI_API_KEY` is unset, your rate limit to the song.link API will be lower.
2023-04-02 13:26:19 +00:00
Run `npm run build` and copy the output folder, usually `build` to `$APP_DIR` on your server.
#### On your server again
Now, you are ready to start everything up.
Enable the site in Apache2 by running `a2ensite moshingmammut.conf` .
Create and start the system service by running `sudo systemctl enable moshing-mammut.service`
and then `service moshing-mammut start` .
Verify that everything is okay with `service moshing-mammut status` .
The app should now be reachable on http://localhost:3000 or whatever you configured your domain to be!
2023-04-07 14:47:37 +00:00
# Icons
Favicon is a combination of [speaker-line by remix icon ](https://remixicon.com/icon/speaker-line )
and [the official Mastodon icon ](https://joinmastodon.org/en/branding ).
It has been mushed together by me, saved as SVG file in [icon.svg ](./icon.svg )
and turned into a slew of icons by [https://realfavicongenerator.net/ ](https://realfavicongenerator.net/ ):
```sh
npm install -g cli-real-favicon
real-favicon generate faviconDescription.json faviconData.json static
```
Other icons:
- [error-warning-fill by remix icon ](https://remixicon.com/icon/error-warning-fill )
- [git-branch-fill by remix icon ](https://remixicon.com/icon/git-branch-fill )
- [rss-fill by remix icon ](https://remixicon.com/icon/rss-line )