Code Monkey home page Code Monkey logo

soundforest's Introduction

Soundforest

A quick and dirty proof of concept for an application that can export soundtracks of TV shows and movies to playlists on Spotify.

Why?

Functional Reason

I was watching a TV show with great music in it and wanted to compile a playlist of it. It had quite a lot of episodes, it was a bit tedious to do it all manually, so I thought it would be cool to do it in a more automated way.

Technical Reason

I wanted to have a look at some of the concepts / technologies below and thought making a proof of concept for an app would be good way going a bit deeper below the surface, beyond "Hello World" type tutorials.

  • Vertical Slice
  • Blazor
  • Tailwind
  • Azure Functions
  • Azure CosmosDB
  • MediatR
  • OneOf

Demo

image

Architecture

image

Takeaways

Vertical Slice

This approach is definitely interesting, probably more so on projects with tight deadlines and lots of people involved. There is quite some overhead to it, partly because of it being acceptable to have some duplication, which feels a bit unnatural. It does make you think a bit more on how to structure a project and how to name things.

Blazor

I dabbled with SvelteKit before and found Blazor to be quite similar. If you are already a dotnet back-end developer, this framework is probably the easiest to transition into some front-end work.

Tailwind

Last time I touched CSS, was in college and it was not a great experience. Tailwind, makes a lot of things very easy and you can assemble something that look a bit more unique than e.g. bootstrap based applications.

Azure Functions

I've used Azure Functions before, I think they're great and it's a cheap way to build API's for proof of concepts like this. I used a Cosmos DB trigger to listen to "status" updates on the "exports" container. This would then trigger a different action, depending on the status. In hindsight, I probably wouldn't take this approach again, as there is the possibility of updates not being read when e.g. the trigger is down for a little while. Something like Azure Service Bus, would probably be a better fit.

Azure Cosmos DB

Cosmos DB is a cool concept and a convenient tool in Azure's offering. I might use it again, for large scale use, I would have to run some cost and performance analysis before picking it.

MediatR

MediatR is a convenient tool, especially to get things done for a proof of concept and still keep everything structured enough to be able to maintain it. This is the first time I've used Behaviors, it's a pretty neat feature, but I did have some issues with open generic types with them, which were not so clear to figure out.

OneOf

In my spare time, I like to play around with typescript and one of the things I love a lot about it, is discriminated unions. The OneOf library offers with feature for C# and it's great. I can't wait for Microsoft to offer it as a feature in one of the upcoming C# versions.

What's Next?

There's lots of refactoring that could be done here, but I consider this project closed. I have a few 100s of hours of songs to listen to now :). Working on this project, I did uncover some interesting topics I want to look into next, so I'll focus on that instead.

Disclaimer

This project is for my personal development / learning purposes and is in no way intended for commercial use. There are no affiliations or endorsements between this repository and the resources or tools it makes use of.

soundforest's People

Contributors

brecht-vde avatar

Watchers

 avatar

soundforest's Issues

General UI Refactoring

  • Refactor component & page layouts (what's truly reusable and what isn't)
  • Make app mobile friendly
  • Revise messaging events & framework
  • Add state management
  • Make proper api integration client

API Exports

Description

A user should be able to a list of exports they've requested

Technical Requirements

Prerequisites

  • AZ Table Storage is provisioned
  • AZ Service Bus is provisioned
  • Spotify API is properly linked via M2M auth

API Tech

  • Azure Functions (HTTP trigger)
  • Azure Functions (Service Bus trigger)

API Specification

Endpoint
/api/exports

Response Codes

  • 200: return results
  • 404: no results found
  • 401: authorization header missing or invalid
  • 500: any unexpected server side error

Response format

{
	"total": 3,
	"results": [
		...,
		{
			"identifier": "tt1234567",
			"title": "Some cool movie",
                        "url": "http://spotify.com/someplaylist",
                        "status": "completed|pending|inprogress|failed",
                        "reason": "Any error or status message"
		},
		...
	]
}

Example
/api/exports

Acceptance Criteria

Service Exports

Description

When a user requests an export via the API endpoint a job should be scheduled through a message queue.
A service should pick up this job from the queue and asynchronously prepare the playlist.

Technical Requirements

  • AZ Service Bus is provisioned
  • AZ Table Storage is provisioned
  • Spotify API is setup and linked for M2M auth

Acceptance Requirements

  • A playlist job can be executed
  • Happy flow from pending to completed status

General Refactoring

  • Move messages to constants class or resource
  • Add unit tests for DI for pipeline behaviors
  • Refactor serialization (setting default export settings)
  • Change status from string to enum

Implement PlaylistExists endpoint

Currently UI project uses a NotFound record to indicate a playlist was not found.
Instead of calling the playlistdetails endpoint and parsing the status code, there should just be a playlistexists endpoint with a valid response structure to indicate if a record exists.

Containerization

Description

Projects should be containerized, to more easily run specific parts or orchestrate the whole thing on a local environment

Acceptance Criteria

Each project can be built as a container or ran via e.g. docker compose

UX Exports

Description

  • A user should be able to see for which titles they requested a playlist
  • A user should be able to see the status of the export job

Search API Refactoring v2

  • Spotiwood.Integrations.Omdb project should just return raw response, without mapping yet
  • Dto's should be removed, okay to just map directly to domain classes (in infra project)
  • Used PagedCollection directly

API Search Detail

Description

A user should be able to fetch more details of a movie or series via its identifier.

Technical Requirements

Prerequisites

  • OMDb account must be setup
  • OMDb account api key must be protected
  • OMDb should only be used in the back end system

API Tech

  • Azure Functions (HTTP trigger)

API Specification

Endpoint
/api/search/{someid}

Response Codes

  • 200: query returned results
  • 400: invalid query parameters
  • 404: query did not return results
  • 401: authorization header missing or invalid
  • 500: any unexpected server side error

Response format

* = optional field

{
	"identifier": "tt1234567",
	"type": "movie|series",
	"title": "Some movie or series",
	"plot*": "Some movie or series plot",
	"poster*": "Image which belongs to a movie or series",
	"seasons*": 7,
	"year": 2010,
	"endYear*": 2020,
	"actors*": ["name1", "name2", "name3"],
	"genres*": ["name1", "name2", "name3"]
}

Example
/api/search/{identifier}

Acceptance Criteria

API Search & Detail Cache

Description

OMDb API is limited to 1000 requests per day, to decrease amount of calls, the requests to the search & details API should be cached.

Technical Requirements

  • Memory cache should be added

Acceptance Criteria

  • Search & details are cached in memory

Playlists API Refactoring

  • BaseClient Constructor guards need to be refactored using fixture or other
  • Duplicate mapping should be removed, map directly to domain classes instead (this mapping happens in infra project)
  • Add proper mappers
  • Properly namespace CosmosQueryBuilder etc.

UX Authentication

Description

A user must be able to login to the web application using their Spotify account.
A user must be able to logout of the web application

API JWT Authentication

Description

The API must be protected, so only authorized users can make requests. This should be done via a JWT token in the Authorization header of each request.

Technical Requirements

An Auth0 account must be setup, JWT tokens will be validated against the Auth0 instances.

Acceptance Criteria

When a user makes a request to the API they must:

  • Receive 401 Unauthorized in case the JWT token is invalid or missing
  • Receive a success code response in case the user provided a valid JWT token

Setup Nginx reverse proxy for API

Description

API project will consist of multiple Azure Functions projects, to mimic the "API Management" feature on Azure, we can use nginx to create a reverse proxy, so all azure functions are externally available through the same address, despite running on different addresses internally.

Acceptance Criteria

All API functions are available through a single address.

API Playlist Detail

Description

A user should be able to see a single exported playlist when a movie/series identifier is requested

Technical Requirements

Prerequisites

  • AZ Table Storage is setup

API Tech

  • Azure Functions (HTTP trigger)

API Specification

Endpoint
/api/playlists/{someid}

Method
GET

Response Codes

  • 200: query returned results
  • 400: invalid request data
  • 404: query did not return results
  • 401: authorization header missing or invalid
  • 500: any unexpected server side error

Response format

{
	"identifier": "tt1234567",
	"title": "Some cool movie",
	"playlistTitle": "Some playlist title",
	"playlistUri": "http://spotify.com/someplaylist"
}

Example
/api/playlists/tt1234567

Acceptance Criteria

UX Playlists

Description

A user should be able to see a list of all exported playlists that are available

Search API Refactoring v1

  • Spotiwood.Api.SearchDetails project should be merged with Spotiwood.Api.Search
  • Spotiwood.Api.SearchDetails.UnitTests project should be merged with Spotiwood.Api.Search.UnitTests

API Full Text Search

Description

A user should be able to search a movie or series via some key words and browse the results (if any).

Technical Requirements

Prerequisites

  • OMDb account must be setup
  • OMDb account api key must be protected
  • OMDb should only be used in the back end system

API Tech

  • Azure Functions (HTTP trigger)

API Specification

Endpoint
/api/search

Query parameters
q

Response Codes

  • 200: query returned results
  • 400: invalid query parameters
  • 404: query did not return results
  • 401: authorization header missing or invalid
  • 500: any unexpected server side error

Response format

{
	"total": 3,
	"results": [
		...,
		{
			"identifier": "tt1234567",
			"type": "movie|series",
			"title": "Some cool movie"
		},
		...
	]
}

Example
/api/search?q={keywords}

Acceptance Criteria

  • The API endpoint is available and complies with the API specification

UX Search

Description

A user must be able to navigate to a search page, in which they can enter search terms, see an overview of the results and being able to click through to the detail of a search result.

API List Playlists

Description

A user should be able to see a list of already exported playlists

Technical Requirements

Prerequisites

  • AZ Table Storage is setup

API Tech

  • Azure Functions (HTTP trigger)

API Specification

Endpoint
/api/playlists

Method
GET

Response Codes

  • 200: query returned results
  • 404: query did not return results
  • 401: authorization header missing or invalid
  • 500: any unexpected server side error

Response format

{
	"total": 3,
	"results": [
		...,
		{
			"identifier": "tt1234567",
			"title": "Some cool movie",
                        "playlistTitle": "Some playlist title",
                        "playlistUri": "http://spotify.com/someplaylist"
		},
		...
	]
}

Example
/api/playlists

Acceptance Criteria

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.