Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 11 additions & 19 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
module.exports = {
env: {
es6: true,
node: true,
jest: true
},
extends: [
'standard'
'standard-with-typescript',
'prettier',
'prettier/@typescript-eslint'
],
globals: {
Atomics: 'readonly',
SharedArrayBuffer: 'readonly'
plugins: ['prettier'],
rules: {
'prettier/prettier': 'error'
},
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module'
project: './tsconfig.json'
},
plugins: [
'@typescript-eslint'
],
rules: {
// See: https://github.com/typescript-eslint/typescript-eslint/pull/688
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': 'warn'
settings: {
react: {
version: 'detect'
}
}
}
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
dist
.track.json
data/
6 changes: 6 additions & 0 deletions .prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
trailingComma: 'none',
semi: false,
singleQuote: true,
arrowParens: 'avoid'
}
12 changes: 11 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,21 @@ RUN npm install --production

FROM node:12-alpine
WORKDIR /app

# Ensure timezone data is available
RUN apk --no-cache update && \
apk --no-cache add tzdata
RUN rm -rf /var/cache/apk/*

# Copy build app and dependencies
COPY --from=builder /app/dist ./dist
COPY --from=dependencies /app/node_modules ./node_modules
COPY ./package* ./
COPY ./package.json ./

# Setup config path
ENV DATA_DIR="/data"
RUN mkdir -p $DATA_DIR
RUN chown -R node:node $DATA_DIR

USER node
CMD ["npm", "run", "start:prod"]
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<p align="center">
<img src="./header.png" alt="slack-fm" />
<br />
<a href="https://travis-ci.org/JackCuthbert/slack-fm">
<img src="https://api.travis-ci.org/JackCuthbert/slack-fm.svg?branch=master" alt="Travis CI" />
</a>
<a href="https://hub.docker.com/repository/docker/jckcthbrt/slack-fm">
<img src="https://img.shields.io/docker/pulls/jckcthbrt/slack-fm" alt="Docker Pulls" />
</a>
<br />
<a href="https://www.producthunt.com/posts/slack-fm?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-slack-fm" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=173963&theme=dark" alt="slack-fm - Self-hosted service to sync Last.fm with your Slack status | Product Hunt Embed" style="width: 250px; height: 54px;" width="250px" height="54px" />
</a>
</p>

## Introduction

**Slack-fm** is a tiny self-hosted service that automatically updates your Slack
status from your Last.fm profile. It updates your Slack status when all the
following conditions are met:

* the user is not set to "away"
* a custom status hasn't been set
* something is now playing on Last.fm
* the time is between 9am and 5pm (configurable)
* it's not a weekend (configurable)

To clear the status it will search Last.fm for the now playing tracks duration
and use that as the status expiration time. If there is no duration information
it defaults to a 10 minute expiration (configurable).

It looks like this:

![Slack Preview](./slack-preview.png)

## Setup

[Read SETUP.md](./SETUP.md)

## Contributing

This should be relatively simple to set up and run, all that's required is Node
v12 and some environment variables.

1. Fork this repository and clone your version
1. Install dependencies with `npm install`
1. Run the tests with `npm test`
1. Copy the sample config file with `cp data/config.sample.yml data/config.yml` and edit it
1. Start the app locally with `npm start`
1. Commit and push your changes then submit a PR back to this repository
105 changes: 105 additions & 0 deletions SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Setup slack-fm

Since Slack has now removed the ability to create new Legacy Tokens you'll need
to create a Slack App and find your member ID to enable slack-fm functionality.

## 1. Create the Slack App Token

1. Navigate to <https://api.slack.com/apps>
1. Click "Create New App", give it a name like "slack-fm", and choose your
Workspace.
1. Click "Add features and functionality"
1. Select "Permissions" and scroll down to "Scopes"
1. Add 2x "User Token Scopes"
* `users.profile:write`
* `users:read`
1. Copy the token at the top of this page

### Note on token permissions

The above instructions create a _Workspace_ token which has full access to
your... Workspace. For example, if you provide someone else's member ID in your
config file slack-fm will update their status.

Please exercise reasonable discretion when configuring slack-fm for your member
ID only. We wouldn't want anyone getting confused or upset about their status
changing to the great music you're listening to would we 😅

If your team has multiple people that would like to run slack-fm then each
person must configure and run their own instance of it (you can use the same
Workspace token/app). Multiple Last.fm account support may exist in the future
if there's enough demand for it.

## 2. Get your Slack member ID

1. Go to Slack
1. Click your profile image in the top right and select "View Profile"
1. Click the "More" button and select "Copy member ID"

## 3. Create a Last.fm app

1. [Create an API account here](https://www.last.fm/api/account/create)
2. Copy the API key and shared secret

## 4. Create the config file

Copy the below snippet (or the sample in [`config.sample.yml`](./data/config.sample.yml))
and create a file called `config.yml` somewhere replacing the properties with
what you created above.

> All the options here are required, the sample below contains some sensible
defaults for the app.

```yml
# config.yml
app:
emoji: ':headphones:'
separator: '·'
update_interval: 1
update_weekends: false
update_hour_start: 8
update_hour_end: 18

lastfm:
username: 'your_lastfm_username'
api_key: '00000000000000000000000000000000'
shared_secret: '00000000000000000000000000000000'

slack:
- user_id: 'U00000000'
token: 'xoxp-XXX-XXX-XXX-XXX'
- user_id: 'U00000000'
token: 'xoxp-XXX-XXX-XXX-XXX'
```

This file will be used in the next step.

## 5. Hosting

I designed this to be easily self hosted on either your local machine or on a
server somewhere with Docker. Slack-fm is automatically built and versioned on
[Docker Hub](https://hub.docker.com/repository/docker/jckcthbrt/slack-fm/tags)
based on GitHub activity.

Define a `docker-compose.yml` file with the following content being careful to
replace the `volumes` property with the correct `config.yml` path.

```yml
# docker-compose.yml
version: '3.7'

services:
slack_fm:
image: jckcthbrt/slack-fm:latest
container_name: slack_fm
restart: unless-stopped
environment:
TZ: '<YOUR_TIMEZONE>'
volumes:
- '</LOCAL/PATH/TO/config.yml>:/data/config.yml'
```

```bash
docker-compose up
```

Empty file added data/.gitkeep
Empty file.
16 changes: 16 additions & 0 deletions data/config.sample.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
app:
emoji: ':headphones:'
separator: '·'
update_interval: 1
update_weekends: false
update_hour_start: 8
update_hour_end: 18

lastfm:
username: ''
api_key: ''
shared_secret: ''

slack:
- user_id: ''
token: ''
Loading