TuneSnap using Flutter SDK for iOS - Linode + DEV Hackathon
Tags: linodehackathon, flutter, ios
Published: 2023-02-19 11:20:56

## What I built

I created an iOS app using Flutter, Linode services - Linode, Object Storage, MySQL database, Spotify API, and Python. 

The main goal of the app is to take a picture of a user in their current mood, and then recommend some songs to help them calm, relax or even get some new cool songs for their playlist.

I've personally felt that, when I sometimes feel sad, or get angry, music is the best therapist and this was the main reason why I could relate to this project and make the best out of it.


### Category Submission:

Integration Innovators

### App Link

https://github.com/ameysunu/linode_flutter

* Clone the project, and install all the dependencies for Flutter by running `flutter pub get`.

* Once done, create a `secrets.dart` file within the folder `controllers` and add in all the needed API keys, which can be retrieved from Linode, and Linode MySQL Databse.

### Screenshots

*Linode Emotion Analysis output* 


![emotion analysis sample output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hbx43m9aqi4olvv5l99o.png)


![emotion analyser](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kns4fo0sqmadtwf0yi35.png)


*Linode Spotify API token retrieval*

![retrieve spotify api](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0n1zugkhyvaomh1oi39i.png)

*Generate token and add to .env file*


![Token generation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/puyhjaiu0sd0to8lymd1.png)

*Linode Object Storage Bucket*

![Object Storage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d03634dcw9hwo9uo88tw.png)

*Linode Server*

![Linode Server](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9gdpkpy7aps15fk586c2.png)

*Linode MySQL Server*

![Linode MySQL Server](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cba1y1v0c5floxizihrg.png)


![MySQL Workbench](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ic8n0gjp4x9f3vls7iib.png)

*Flutter App Screenshots*


![Home Screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iv83z156x2e3xlaktovo.png)


![Analyser](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9spfdyhmdign82xp6vmr.png)


![Mood](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mvoxnn39bty7m36e7c21.png)


![Loader](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zmpi1dpad5dudtbetp08.png)


![Songs and mood](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tos7jk93711s1vdrgngk.png)


![Saved SQL usermood](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qdedmoi76u5uwgvegl53.png)


![Saved SQL songdata](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sun18ipap7jh9aszl71f.png)


Here's a video showing some preview of how the app works:

https://youtu.be/R7fBcWT9vE4


### Description

The project aims to provide users with a list of songs depending on the user's current mood to give them something to relax or even get a lot of new songs depending on your mood. 

All the user needs to do is simply log in, take a photo or upload one if their device doesn't support a camera hardware and then voila, they simply wait for their song list and it can even be saved within the app, for listening to later.

### Link to Source Code

{% github ameysunu/linode_flutter %}

### Permissive License

MIT License 2023

## Background
I've personally felt that music helps people a lot, especially if their mood is a little down. And I thought why not use this opportunity to give users a chance to get to know about some new songs, listen to them, and even save them to the app so that users can always access to those.


### How I built it
I built this with Flutter SDK for iOS, using Firebase Authentication and of course, Linode services. 

How? -> I used three of Linode Services: 

* Linode - I created a Linode, and developed a Python program using machine learning libraries such as `fer` which is made using `keras` and `tensorflow` for facial recognition. I then used `flask` to make an API for POST request to upload images from the mobile device using `nginx`. The images were being saved on Linode, and to improve this, I created another Python program using `flask` which first uploads the image to Linode Object Storage and then progresses that to our emotion analyzer python code.

* Linode Object Storage - The images used for facial recognition are stored on Linode Object Storage to avoid image cluttering on the Linode server and makes it very easy for computation and execution.

* Linode Database MySQL - Using Flutter and Dart code, the data is saved to a Linode MySQL database. I've been quite rough with SQL, hence I needed a lot of brushing up to use different tables and perform a ton of CRUD operation.

It was my first time using Linode, and it was really easy to integrate all of Linode services to make this project work bit faster and on time, of course my favorite part is that it's very easy to use FaaS within Linode, and there was no downtime at all.

### Additional Resources/Info

It was a lot of fun to develop and create this project, but there are a few things I'd like to mention. 

It was my first time doing a machine learning project, so I had to go through a lot of documentation, and stackoverflow while making this project. I even had my fears since not all computers supported tensorflow modules for GPU operations, but that was not at all the case with Linode. I had decided to use `ngrok` so that I could do `POST` and `GET` request to get response from the Linode server, and hence that turned out be not the best solution at all, two reasons why:

1. `ngrok` free version only allows to expose one localhost url and port to the public. I had two of them -> One was the uploader to Linode Object Storage, and the other was the emotion analyzer.

2. There was a timeout and everytime, I load the server and expose the url to public, it changes. Hence, it was hard for me to continuously put the URL everytime in my Flutter code and reload the application.

Hence, using `nginx` , `gunicorn3` and `flask`, I could make `POST` and `GET` requests to the Linode's IP address directly, hence making it easy for me (as a developer) to focus on my Flutter code rather than having to spend hours to start `ngrok` everytime and then use a different URL. 

After getting this sorted, an another issue was Spotify's API token. Spotify's API would expire after 3600 seconds or 1 hour. Hence, replacing the Spotify API everytime I work on the app was not an ideal solution. 

So I came up with a solution. I created an `.env` file on my Linode server to store my Spotify token, and then wrote a Python script that would generate a Spotify token based of on my Spotify Client and Secret ID every 45 minutes, and then replace that with the token on `.env` file. The app could fetch token on the `.env` file using a simple `GET` to the Linode server.

There was also a python program that runs every 1 hour to delete all the images from the Linode Object Storage, of course for privacy reasons.

Long story short, these were just a few tiny challenges I faced, and it was really easy for me to focus on coming up with  solutions rather than worrying about my downtime, server restrictions, or SQL Database as it was all backed up by Linode.