Giter Club home page Giter Club logo

cyf-stay-tuned-radio's Introduction

Contributors Forks Stargazers Issues LinkedIn


Stay Tuned Radio

An awesome a music-sharing platform, designed to foster community engagement and discovery.
Explore the docs »

View Demo · Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Built With
  3. Contact
  4. Getting Started
  5. Usage
  6. Roadmap
  7. Contributing
  8. License
  9. Acknowledgments

About The Project

Product Name Screen Shot

We like to share our music and we like to stream coding music while we work. But we don’t have our own radio station to share and discover music that resonates with the community.

Introducing our app, a music-sharing platform integrated with Spotify, designed to foster community engagement and discovery. Each day, a selection of songs from our extensive database is randomly curated and added to a Spotify playlist, accessible via a widget embedded within our app. Users can return daily to explore fresh tracks recommended by fellow community members.

While our app is publicly available, exclusive access to certain features, such as song submissions, is reserved for community members. Authentication is seamlessly facilitated through Slack, leveraging the Sign in with Slack feature. Team members are authenticated based on their membership within the designated Slack workspace. Upon authentication, users gain access to the song submission feature, where they can contribute to expanding our music database by providing song details and URL.

(back to top)

Contact

Project Link: https://github.com/m4ndycheung/cyf-stay-tuned-radio

(back to top)

Built With

  • React
  • Bootstrap
  • Postgres
  • Node

Other technology used

Slack API

The Slack API enables secure authentication, verifying users' team membership before granting access to additional features.

Spotify API

The Spotify API facilitates seamless integration, allowing our app to dynamically generate and update playlists based on community submissions.

JWT

We employ JSON Web Tokens (JWT) to facilitate secure transmission of user data between frontend and backend components. Following industry best practices, JWTs are issued upon user authentication, enabling subsequent requests without exposing sensitive tokens

(back to top)

Getting Started

To get a local copy up and running follow these not-so-simple steps.

Prerequisites

  • npm
npm install npm@latest -g
  • Install ngrok
  • Create a Slack app
  • Create a Spotify app
  • Create a Postgresql database

Installation

  1. Clone the repo
git clone https://github.com/m4ndycheung/cyf-stay-tuned-radio.git
  1. Install NPM packages and dependencies for both client and server
npm install

Setup Environment Variables

  1. Create .env variable file in client directory
VITE_SERVER_URL=http://localhost:3001
VITE_FRONTEND_URL=http://localhost:5173
VITE_SLACK_WORKSPACE_NAME=
  • VITE_SLACK_WORKSPACE_NAME is a string variable which is displayed in the header
  1. Create .env variable file in server directory
# spotify credentials
SPOTIFY_CLIENT_ID=
SPOTIFY_CLIENT_SECRET=
SPOTIFY_REDIRECT_URI=http://localhost:3001/callback
SPOTIFY_PLAYLIST_ID=

# slack credentials
SLACK_CLIENT_ID=
SLACK_CLIENT_SECRET=
SLACK_REDIRECT_URI=**ngrok_url**/slack/oauth_redirect
SLACK_ADMIN_USER_ID=
SLACK_WORKSPACE_NAME=

# database credentials
DB_USER=
DB_PASSWORD=
DB_HOST=
DB_PORT=
DB_NAME=

# jwt variables
JWT_SECRET=

# addresses
SERVER_URL=http://localhost:3001
FRONTEND_URL=http://localhost:5173

Spotify

SPOTIFY_CLIENT_ID and SPOTIFY_CLIENT_SECRET

In order to get these credentials, go to your Spotify app and copy them from settings section. (For more details, click here: https://developer.spotify.com/)

SPOTIFY_PLAYLIST_ID

Create a playlist on Spotify and paste the playlist id here

Slack

SLACK_CLIENT_ID and SLACK_CLIENT_SECRET

Go to your Slack App and copy them here. (For more details, click here: https://api.slack.com/authentication/sign-in-with-slack)

SLACK_ADMIN_USER_ID

To get this you need to login to your Slack workspace, click on the account you intend to make the admin. Click three dots and copy the member ID.

SLACK_WORKSPACE_NAME

You can find the workspace name in the slack url of your workspace. It is your workspace or organisation name followed by the slack.com domain (For more details, click here: https://slack.com/intl/en-gb/help/articles/221769328-Locate-your-Slack-URL-or-ID)

JWT

JWT_SECRET

This string variable is used to encode and decode/verify the JSON Web Tokens used in the backend server only allowing authorised users to access certain endpoints.

Setup Database

Note: A seed file is available in the server/data directory. This will create 2 tables:

tracks
refresh_tokens_table

The tracks table stores songs and information about the artists as well as the unique track id and the username of the user who submitted it.

tracks

It has 6 columns consisting of:

  • id: which is automatically generated when a new song is added
  • song_name: add the title of your chosen song
  • artist_name: add the name of the artist of your chosen song
  • cyf_slack_username (optional): add your slack username
  • song_genre (optional): add the gene of your chosen song
  • spotify_song_id: on Spotify, click on your chosen song, and from the browser copy the highlighted bit from the example below:
  https://open.spotify.com/track/5fHXbmrx8mfOT1wfSa1Nc8

refresh tokens

The refresh tokens table stores (you guessed it!) the refresh token provided by spotify which can then be exchanged for a new access token. It has 2 columns consisting of:

  • id: which is automatically generated when a refresh token is added
  • refresh_token: refresh token provided by Spotify.

Installation Complete (Well done!)

Told you they weren't simple. Well done on getting so far! It would be rude to stop now, follow the next few steps to get the project up and running 🚀

On First Time Run

start the project

Refer to Running the project locally

login as admin user

Under the maintenance section:

click Get Access and Refresh Token (This will populate the refresh tokens table in the database)

Running the project locally

To start:

  1. Go to Client folder and enter in terminal:
     npm run dev
  2. Go to Server folder and enter:
    npm start
  3. Start ngrok:
    ngrok http 3001
  4. Copy the forwarding URL from ngrok CLI, it’ll look something like this: https://2e73-94-119-32-12.ngrok-free.app
  5. Append /slack/oauth_redirect to this URL i.e. https://2e73-94-119-32-12.ngrok-free.app/slack/oauth_redirect
  6. Paste into env file SLACK_REDIRECT_URI
  7. Go to https://api.slack.com/ and go to Oauth and Permissions tab and paste into Redirect URLs.
  8. Go to http://localhost:3001 to access the backend.
  9. Go to http://localhost:5173 to access the frontend.

(back to top)

Usage

How to update the playlist There’s a button for this sitting on the front page

How to add songs to the database User needs to be logged in for the add songs form to be shown

(back to top)

Roadmap

  • Create a scheduled script to automate the playist update process
  • Display previous daily playlists
  • Display how many users added a specific track
  • View tracks added by a specific user

See the open issues for a full list of proposed features (and known issues).

(back to top)

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch
git checkout -b feature/AmazingFeature
  1. Commit your Changes
git commit -m 'Add some AmazingFeature'
  1. Push to the Branch
git push origin feature/AmazingFeature
  1. Open a Pull Request

(back to top)

License

Distributed under the MIT License. See LICENSE.txt for more information.

(back to top)

Acknowledgments

(back to top)

cyf-stay-tuned-radio's People

Contributors

mansangsin avatar m4ndycheung avatar munozirianni1988 avatar christina-mifsud avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

cyf-stay-tuned-radio's Issues

Get access and refresh tokens - BE - UserStory3a 🐘

  • Get refresh token from Spotify for the app via Authorization Fl.ow
  • Create a new component to hold the function for getting a refresh token.
  • Make a function inside that component that will return a refresh token.
  • Ensure the function is exported.

Dev Notes:

Create a Slack App

  • 27th January 2024: Christina created a Slack App that's not part of the CYF workspace
  • We need #46 and #48 to check if we can use this account instead of one that's part of the CYF workspace
  • Slack details in G Drive

Bug Fix: Deployed version of /update not working

Error: /opt/render/project/src/server/modules/deleteAllTracksFromSpotifyPlaylist.js:8
const tracksArray = playlistData.tracks.items
^
TypeError: Cannot read properties of undefined (reading 'items')
at deleteAllTracksFromSpotifyPlaylist (/opt/render/project/src/server/modules/deleteAllTracksFromSpotifyPlaylist.js:8:45)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Research into Spotify Authorization

What we think Spotify Authorization:

  • For our app to create playlists - We have a feeling we'll need to login to the Master Spotify Account i.e. get authorized
  • For us to show a playlist from the Master Account on our website - can we get away with just using Client Credentials?

To Do:

  • Confirm what Authorization we need for creating playlists and adding songs to that playlist
  • Confirm what Authorization is needed to get playlist from the Master Account and display it on our website

Dev Notes:

Get Slack profile data

  • Once user has logged in, and get an access token
  • Use that access token to get user profile data

Get a general overview of Authentication

To Do:
Look into Auth for CYF

  • Slack/CYF email
  • Passport JS
  • Github? - Maybe some volunteers won’t have Github i.e. the Caros? But all CYF trainees and mentors will

Dev Notes:

  • Read into Passport or some other library / plugin (tbc)
  • If you haven't logged in, you will see the playlist and a button "Login to add song"
  • When you login, you gain the power to add songs - you will see a form to add a song

Links:

[Don't merge] Get access token - BE - UserStory3b 🐑

  • Get access token for the app to communicate with the master Spotify account.
  • Create a new component to hold the function for getting an access token.
  • Make a function inside that component that will return an access token.
  • Ensure the function is exported.

Dev Notes:

  • A refresh token is used so the person logged in isn't continuously asked for an access token

Fix deployment

Notes:

  • We got an error, publish directory build does not exist

Give the frontend some TLC

  • Remove Vite and React bits
  • Add a header
  • Round the spotify player corners
  • Gussy up the form
  • Add a footer

Create Postgres DB - BE - UserStory2 🐑

To Dos:

  1. Create a db
  2. Create a table to hold the songs
  3. Columns: song id, song name, artist, slack username, genre
  4. Insert 10 songs into table

fOR Reviewer: Check DB on dbeaver, a second eye on the data we're storing is okay

Stretch Goal: Implement Spotify Search API - BE

  • Use refresh_token endpoint to get a new access token (when people search will they need to get a new access token every single time?)
  • Set up a GET request to spotify with search params
  • Access the crazy JSON response data that comes back
  • Grabbing the query params: Really if we're searching songs, we only need the "q" parameter, we can hard code the type and limit in the fetch URL
  • THought - every time someone types a search, it'll be sent to the backend /search endpoint - it's probably not good to keep requesting access tokens - how can we only run that code when it's needed?

Dev Notes:

Other work for another ticket:

  • show results on FE
  • get the query params from the user searching in the search bar

Create Slack MACI Master Account

If we don't have this by the Monday 29th January meeting, we will create the app using one of our personal accounts
We might get away with using a random Slack user account to create the app itself. Doesn't need to be part of CYF?

Get Refresh token - BE - UserStory3b

  • Get refresh token from Spotify for the app.
  • Create a new component to hold the function for getting a refresh token.
  • Make a function inside that component that will return a refresh token.
  • Ensure the function is exported.

Dev Notes:

  • A refresh token is used so the person logged in isn't continuously asked for an access token

Get refresh token from API and store it in db

  • get refresh token from API call
  • take refresh token and store it in db
  • refresh token has to be overwritten in db - otherwise we might get a bad one(?)

Dev Notes
Changed table name from refresh_tokens to refresh_tokens_table for clarity
Updated db refresh_token column from VARCHAR(100) to VARCHAR as the refresh_token is longer

Combine Refresh Token #42 with Delete Songs #25 and Add Songs #4 (Mob programme Monday 29th Jan)

To do as a mob programming exercise on Monday meeting.

To Do:

  • Create an endpoint to make the following happen (like a parent function):
  • Get refresh token from the database
  • Refresh token function to get an access token (#42)
  • Pass that access token as a parameter and call Delete Songs function (#25)
  • Pass that same access token as a parameter and call Add Songs function (#4)

Dev Notes:

Bug Fix: Slack state validation

Notes

  • Issue with the createIdentifier function and how validate function is accessed
  • Noticed the activeID object is empty in console.log, so the state can't be validated and will always return falsy i.e. error message "Invalid state parameter"
  • Tried exporting the createIdentifier function to its own module, learned that when you require it in different modules, a new instance of createIdentifier is created each time essentially resetting activeID
  • ChatGPT explanation: When you declare const activeID = {}; inside the createIdentifier function, activeID becomes a local variable, and its scope is limited to that specific invocation of the function. This means that every time you require the module and call createIdentifier, a new version of activeID is created because it's part of the function's local scope.
  • activeID is declared at the module level, shared across all instances of the module.
  • Modifications to activeID in one module are visible in other modules.

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.