feat: 🎉 Everything works
Some checks failed
ci / docker (push) Has been cancelled

This commit is contained in:
Louis Gallet 2024-06-19 23:40:27 +02:00
commit 0e10bf6476
Signed by: lgallet
GPG Key ID: 84D3DF1528A84511
17 changed files with 567 additions and 0 deletions

1
.dockerignore Normal file
View File

@ -0,0 +1 @@
.env

34
.github/workflows/build-publish.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: ci
on:
push:
branches:
- 'main'
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: gitea.louisgallet.fr
username: lgallet
password: ${{ secrets.GITEA_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: gitea.louisgallet.fr/lgallet/makethisplaylist:latest

269
.gitignore vendored Normal file
View File

@ -0,0 +1,269 @@
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### macOS template
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

8
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,10 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<Languages>
<language minSize="63" name="Python" />
</Languages>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.12 (playlistCreator)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (playlistCreator)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/playlistCreator.iml" filepath="$PROJECT_DIR$/.idea/playlistCreator.iml" />
</modules>
</component>
</project>

10
.idea/playlistCreator.iml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

16
Dockerfile Normal file
View File

@ -0,0 +1,16 @@
FROM python:3.11-alpine
LABEL authors="louisgallet"
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 3000
ENTRYPOINT ["python", "main.py"]

28
main.py Normal file
View File

@ -0,0 +1,28 @@
from flask import Flask, request, render_template
from flask_bootstrap import Bootstrap5
from spotifySearch import searchSpotify
app = Flask(__name__)
bootstrap = Bootstrap5(app)
@app.route('/', methods=['GET', 'POST'])
def form_example():
# handle the POST request
if request.method == 'POST':
search = request.form.get('search')
result = searchSpotify(search)
return render_template("found.html", query=search, trackName=result[0], trackArtist=result[1], trackAlbum=result[2], trackPreview=result[3], trackImage=result[4], trackID=result[5],)
# otherwise handle the GET request
return render_template("index.html")
@app.route('/test')
def test():
return render_template("test.html")
if __name__ == '__main__':
# run app in debug mode on port 5000
app.run(debug=True, port="3000", host="0.0.0.0")

64
requirements.txt Normal file
View File

@ -0,0 +1,64 @@
appnope==0.1.4
asttokens==2.4.1
attrs==23.2.0
backcall==0.2.0
beautifulsoup4==4.12.3
bleach==6.1.0
blinker==1.8.2
Bootstrap-Flask==2.4.0
certifi==2024.6.2
charset-normalizer==3.3.2
click==8.1.7
decorator==5.1.1
defusedxml==0.7.1
docopt==0.6.2
executing==2.0.1
fastjsonschema==2.20.0
Flask==3.0.3
idna==3.7
ipython==8.12.3
itsdangerous==2.2.0
jedi==0.19.1
Jinja2==3.1.4
jsonschema==4.22.0
jsonschema-specifications==2023.12.1
jupyter_client==8.6.2
jupyter_core==5.7.2
jupyterlab_pygments==0.3.0
MarkupSafe==2.1.5
matplotlib-inline==0.1.7
mistune==3.0.2
nbclient==0.10.0
nbconvert==7.16.4
nbformat==5.10.4
packaging==24.1
pandocfilters==1.5.1
parso==0.8.4
pexpect==4.9.0
pickleshare==0.7.5
pipreqs==0.5.0
platformdirs==4.2.2
prompt_toolkit==3.0.47
ptyprocess==0.7.0
pure-eval==0.2.2
Pygments==2.18.0
python-dateutil==2.9.0.post0
python-dotenv==1.0.1
pyzmq==26.0.3
redis==5.0.6
referencing==0.35.1
requests==2.32.3
rpds-py==0.18.1
six==1.16.0
soupsieve==2.5
spotipy==2.24.0
stack-data==0.6.3
tinycss2==1.3.0
tornado==6.4.1
traitlets==5.14.3
urllib3==2.2.2
wcwidth==0.2.13
webencodings==0.5.1
Werkzeug==3.0.3
WTForms==3.1.2
yarg==0.1.9

17
spotifySearch.py Normal file
View File

@ -0,0 +1,17 @@
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
import os
from dotenv import load_dotenv
load_dotenv()
def searchSpotify(spotifySearch, limit=1):
sp = spotipy.Spotify(auth_manager=SpotifyClientCredentials(client_id=os.getenv("client_id"), client_secret=os.getenv("client_secret")))
results = sp.search(q=spotifySearch, limit=limit)
trackName = results['tracks']['items'][0]['name']
trackArtist = results['tracks']['items'][0]['artists'][0]['name']
trackAlbum = results['tracks']['items'][0]['album']['name']
trackPreview = results['tracks']['items'][0]['preview_url']
trackImage = results['tracks']['items'][0]['album']['images'][0]['url']
trackID = results['tracks']['items'][0]['uri']
return (trackName, trackArtist, trackAlbum, trackPreview, trackImage, trackID)

37
templates/found.html Normal file
View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Results</title>
{{ bootstrap.load_css() }}
</head>
<body>
<div class="container text-center">
<form method="POST">
<div class="form-group">
<div class="form-inline text-center">
<label>Enter here the music that you want:</label>
<input type="text" name="search" class="form-control" />
</div>
</div>
<div class="text-center">
<input type="submit" value="Submit" class="btn btn-primary">
</div>
</form>
<div class="alert alert-primary" role="alert">
Here's the music I found. If it doesn't match, try the query again in more detail.
</div>
<div class="card" style="width: 21rem;">
<img class="card-img-top" src="{{trackImage}}" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">{{trackName}}</h5>
<p class="card-text">{{trackArtist}} - {{trackAlbum}}</p>
<audio controls><source src="{{trackPreview}}"></audio>
<a href="https://n8n.louisgallet.fr/webhook/61f08b8c-5bca-4091-a934-da66d9ae09e7/61f08b8c-5bca-4091-a934-da66d9ae09e7/{{trackID}}" class="btn btn-primary">Add to the playlist</a>
</div>
</div>
</div>
</body>
</html>

26
templates/index.html Normal file
View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Fête de la musique</title>
{{ bootstrap.load_css() }}
</head>
<body>
<div class="container">
<form method="POST">
<div class="form-group">
<div class="form-inline text-center">
<label>Enter here the music that you want:</label>
<input type="text" name="search" class="form-control" />
</div>
</div>
<div class="text-center">
<input type="submit" value="Submit" class="btn btn-primary">
</div>
</form>
</div>
</body>
</html>

20
templates/test.html Normal file
View File

@ -0,0 +1,20 @@
<!doctype html>
<html lang="en">
<head>
{% block head %}
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
{% block styles %}
<!-- Bootstrap CSS -->
{{ bootstrap.load_css() }}
{% endblock %}
<title>Your page title</title>
{% endblock %}
</head>
<body>
<button type="button" class="btn btn-primary">Primary</button>
</body>
</html>