Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spotify plugin #138

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ build*
*.qmlc
*.jsc
.DS_Store
.idea
8 changes: 8 additions & 0 deletions spotify/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.16)
find_package(Albert REQUIRED)

project(spotify VERSION 1.0.0)

file(GLOB_RECURSE SOURCES "src/*")

albert_plugin(QT Widgets)
60 changes: 60 additions & 0 deletions spotify/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Spotify extension

The Spotify extension for Albert launcher allows you to search
tracks on Spotify and play them immediately or add them to the
queue. It also allows you to choose the Spotify client, where
to play the track.

The extension uses the Spotify Web API.

For the proper
functionality of extension, **Spotify premium is required**.

![Spotify extension](https://i.imgur.com/CoE2C5i.png)

## Web API connection

### 1. Get your Client ID and Client Secret

Visit: https://developer.spotify.com/dashboard/applications and log
in with your Spotify account.

Click on the button **Create an app**
and fill the form. You can use for example name "Albert" and
description "Spotify extension for Albert launcher".

Once you
click on **Create**, your new application window will appear. You
can copy your **Client ID** and show **Client Secret**.
Both are 32-character strings.

Click on **Edit settings** and add new **Redirect URI**. It doesn't
have to exist. In this example, I will use: `https://nonexistent-uri.net/`

### 2. Get `code` parameter

Open your browser and visit: https://accounts.spotify.com/cs/authorize?response_type=code&client_id=[[client_id]]&scope=user-modify-playback-state%20user-read-playback-state&redirect_uri=https://nonexistent-uri.net/

You have to replace `[[client_id]]` with your actual **Client ID**.

When you press enter, you will get redirected to
`https://nonexistent-uri.net/` with `code` in URL parameters.
Copy that string and note it down for the next usage.

### 3. Get your Refresh Token

I will use `curl` for this last step. Replace or export all variables and run this command:

```
curl -d client_id=$CLIENT_ID -d client_secret=$CLIENT_SECRET -d grant_type=authorization_code -d code=$CODE -d redirect_uri=https://nonexistent-uri.net/ https://accounts.spotify.com/api/token
```

Use your Client ID, Client Secret and `code` from the previous step.

It will send POST request and return JSON in the answer.
You can finally get your **Refresh Token**.

<hr>

The whole process is also similarly described
[here](https://benwiz.com/blog/create-spotify-refresh-token/).
7 changes: 7 additions & 0 deletions spotify/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"authors": ["@BlueManCZ"],
"description": "Control your Spotify player",
"license": "MIT",
"name": "Spotify",
"url": "https://github.com/albertlauncher/plugins/tree/main/spotify"
}
227 changes: 227 additions & 0 deletions spotify/src/configwidget.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigWidget</class>
<widget class="QWidget" name="ConfigWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>448</width>
<height>325</height>
</rect>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Web API connection&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="label_client_id">
<property name="text">
<string>Client ID:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_client_secret">
<property name="text">
<string>Client Secret:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_refresh_token">
<property name="text">
<string>Refresh Token:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="lineEdit_refresh_token"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEdit_client_id"/>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineEdit_client_secret"/>
</item>
<item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pushButton_test_connection">
<property name="text">
<string>Test connection</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;User preferences&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Number of results:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QSpinBox" name="spinBox_number_of_results">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>10</number>
</property>
<property name="value">
<number>5</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Spotify executable:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineEdit_spotify_executable">
<property name="text">
<string/>
</property>
<property name="placeholderText">
<string>spotify</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkBox_explicit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_client_secret_2">
<property name="text">
<string>Allow explicit content:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Cache directory:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="lineEdit_cache_directory">
<property name="placeholderText">
<string>Using system temporary directory</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<tabstops>
<tabstop>lineEdit_client_id</tabstop>
<tabstop>lineEdit_client_secret</tabstop>
<tabstop>lineEdit_refresh_token</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
Loading