mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Add Facebook based login.
This commit is contained in:
parent
4d712efb48
commit
4b4bc2f4e1
12 changed files with 383 additions and 42 deletions
|
@ -13,6 +13,7 @@ addons:
|
||||||
script:
|
script:
|
||||||
- cargo build
|
- cargo build
|
||||||
- cargo build --features with-tremor
|
- cargo build --features with-tremor
|
||||||
|
- cargo build --features facebook
|
||||||
# Building without syntex only works on nightly
|
# Building without syntex only works on nightly
|
||||||
- if [[ $(rustc --version) == *"nightly"* ]]; then
|
- if [[ $(rustc --version) == *"nightly"* ]]; then
|
||||||
cargo build --no-default-features;
|
cargo build --no-default-features;
|
||||||
|
|
130
Cargo.lock
generated
130
Cargo.lock
generated
|
@ -4,6 +4,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit-set 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bit-set 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"clippy 0.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"dns-sd 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dns-sd 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"eventual 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"eventual 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -12,6 +13,7 @@ dependencies = [
|
||||||
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"librespot-protocol 0.1.0",
|
"librespot-protocol 0.1.0",
|
||||||
"num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"openssl 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"portaudio 0.2.0 (git+https://github.com/mvdnes/portaudio-rs)",
|
"portaudio 0.2.0 (git+https://github.com/mvdnes/portaudio-rs)",
|
||||||
"protobuf 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"protobuf 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"protobuf_macros 0.3.0 (git+https://github.com/plietar/rust-protobuf-macros)",
|
"protobuf_macros 0.3.0 (git+https://github.com/plietar/rust-protobuf-macros)",
|
||||||
|
@ -90,11 +92,24 @@ name = "chunked_transfer"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clippy"
|
||||||
|
version = "0.0.53"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"regex-syntax 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cookie"
|
name = "cookie"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"openssl 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -180,6 +195,14 @@ name = "gcc"
|
||||||
version = "0.3.25"
|
version = "0.3.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gdi32-sys"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getopts"
|
name = "getopts"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
|
@ -209,6 +232,7 @@ dependencies = [
|
||||||
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"openssl 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -235,7 +259,7 @@ name = "kernel32-sys"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -267,6 +291,14 @@ dependencies = [
|
||||||
"protobuf_build 0.1.1 (git+https://github.com/plietar/rust-protobuf-build.git)",
|
"protobuf_build 0.1.1 (git+https://github.com/plietar/rust-protobuf-build.git)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libressl-pnacl-sys"
|
||||||
|
version = "2.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"pnacl-build-helper 1.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
|
@ -289,6 +321,11 @@ dependencies = [
|
||||||
"serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "1.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num"
|
name = "num"
|
||||||
version = "0.1.31"
|
version = "0.1.31"
|
||||||
|
@ -316,11 +353,54 @@ dependencies = [
|
||||||
"pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"openssl-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"openssl-sys-extras 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-sys"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"gdi32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libressl-pnacl-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"user32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-sys-extras"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"openssl-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.8"
|
version = "0.3.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pnacl-build-helper"
|
||||||
|
version = "1.4.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"tempdir 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "portaudio"
|
name = "portaudio"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -392,6 +472,11 @@ dependencies = [
|
||||||
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rpassword"
|
name = "rpassword"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
@ -400,7 +485,7 @@ dependencies = [
|
||||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -433,6 +518,14 @@ name = "semver"
|
||||||
version = "0.1.20"
|
version = "0.1.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"nom 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "0.6.15"
|
version = "0.6.15"
|
||||||
|
@ -499,6 +592,14 @@ dependencies = [
|
||||||
"unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempdir"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
|
@ -507,7 +608,7 @@ dependencies = [
|
||||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -516,7 +617,7 @@ version = "0.2.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -534,7 +635,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -550,6 +651,14 @@ dependencies = [
|
||||||
"url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.1.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "traitobject"
|
name = "traitobject"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
@ -627,6 +736,15 @@ dependencies = [
|
||||||
"uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "user32-sys"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "0.1.18"
|
version = "0.1.18"
|
||||||
|
@ -681,7 +799,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.2.5"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -44,6 +44,8 @@ protobuf_macros = { git = "https://github.com/plietar/rust-protobuf-macros" }
|
||||||
shannon = { git = "https://github.com/plietar/rust-shannon" }
|
shannon = { git = "https://github.com/plietar/rust-shannon" }
|
||||||
tremor = { git = "https://github.com/plietar/rust-tremor", optional = true }
|
tremor = { git = "https://github.com/plietar/rust-tremor", optional = true }
|
||||||
|
|
||||||
|
openssl = { version = "0.7", optional = true }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
vergen = "~0.1.0"
|
vergen = "~0.1.0"
|
||||||
syntex = { version = "*", optional = true }
|
syntex = { version = "*", optional = true }
|
||||||
|
@ -54,5 +56,6 @@ json_macros = { git = "https://github.com/plietar/json_macros" }
|
||||||
discovery = ["dns-sd"]
|
discovery = ["dns-sd"]
|
||||||
with-syntex = ["syntex", "protobuf_macros/with-syntex", "json_macros/with-syntex"]
|
with-syntex = ["syntex", "protobuf_macros/with-syntex", "json_macros/with-syntex"]
|
||||||
with-tremor = ["tremor"]
|
with-tremor = ["tremor"]
|
||||||
|
facebook = ["hyper/ssl", "openssl"]
|
||||||
static-appkey = []
|
static-appkey = []
|
||||||
default = ["with-syntex"]
|
default = ["with-syntex"]
|
||||||
|
|
16
README.md
16
README.md
|
@ -47,6 +47,16 @@ cargo build --release --features discovery
|
||||||
|
|
||||||
When running *librespot* simply omit the `--username` argument.
|
When running *librespot* simply omit the `--username` argument.
|
||||||
|
|
||||||
|
## Facebook Accounts
|
||||||
|
*librespot* can be built with Facebook authentication support. OpenSSL is required for this.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cargo build --release --features facebook
|
||||||
|
target/release/librespot --appkey APPKEY --cache CACHEDIR --name DEVICENAME --facebook
|
||||||
|
```
|
||||||
|
|
||||||
|
This will print a link to the console, which must be visited on the same computer *librespot* is running on.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
When developing *librespot*, it is preferable to use Rust nightly, and build it using the following :
|
When developing *librespot*, it is preferable to use Rust nightly, and build it using the following :
|
||||||
```shell
|
```shell
|
||||||
|
@ -55,12 +65,6 @@ cargo build --no-default-features
|
||||||
|
|
||||||
This produces better compilation error messages than with the default configuration.
|
This produces better compilation error messages than with the default configuration.
|
||||||
|
|
||||||
## Facebook Accounts
|
|
||||||
If you connect using a facebook account, librespot will not show up among the
|
|
||||||
devices in the Spotify app. What you need to do is apply for a
|
|
||||||
[device password](http://www.spotify.com/account/set-device-password/) and
|
|
||||||
use that to sign in instead.
|
|
||||||
|
|
||||||
## Disclaimer
|
## Disclaimer
|
||||||
Using this code to connect to Spotify's API is probably forbidden by them, and
|
Using this code to connect to Spotify's API is probably forbidden by them, and
|
||||||
might result in you application key getting banned. Use at you own risk
|
might result in you application key getting banned. Use at you own risk
|
||||||
|
|
|
@ -11,13 +11,12 @@ pub struct APResolveData {
|
||||||
|
|
||||||
pub fn apresolve() -> Result<Vec<String>, ()> {
|
pub fn apresolve() -> Result<Vec<String>, ()> {
|
||||||
let client = hyper::client::Client::new();
|
let client = hyper::client::Client::new();
|
||||||
let mut res = String::new();
|
|
||||||
|
|
||||||
client.get(APRESOLVE_ENDPOINT)
|
let mut response = client.get(APRESOLVE_ENDPOINT).send().unwrap();
|
||||||
.send().unwrap()
|
let mut data = String::new();
|
||||||
.read_to_string(&mut res).unwrap();
|
response.read_to_string(&mut data).unwrap();
|
||||||
|
|
||||||
let data : APResolveData = json::decode(&res).unwrap();
|
let data : APResolveData = json::decode(&data).unwrap();
|
||||||
|
|
||||||
Ok(data.ap_list)
|
Ok(data.ap_list)
|
||||||
}
|
}
|
||||||
|
|
35
src/data/spotilocal.cert
Normal file
35
src/data/spotilocal.cert
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIGGzCCBQOgAwIBAgIQCMsbyFVsBNk7vWlJ7YFryjANBgkqhkiG9w0BAQsFADBN
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E
|
||||||
|
aWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTQxMTI4MDAwMDAwWhcN
|
||||||
|
MTcxMjA2MTIwMDAwWjBlMQswCQYDVQQGEwJTRTESMBAGA1UECBMJU3RvY2tob2xt
|
||||||
|
MRIwEAYDVQQHEwlTdG9ja2hvbG0xEzARBgNVBAoTClNwb3RpZnkgQUIxGTAXBgNV
|
||||||
|
BAMMECouc3BvdGlsb2NhbC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
|
||||||
|
AoICAQDwccCju1/MY/lVM+2j0Hiu/M4u8jbR5ctk11U3i3ugYF4xwyqzbh8ziQq6
|
||||||
|
9atIDg33OTEGGD1m2LkOursIRng6UUth1wqdRlRylHG2p4JYW22WEa730hnysSDn
|
||||||
|
AHLfFawfHh40BPwLY7UD/0c0J8dUTu7Xx3fNHcJATQAHO7KlhTj+t+axUvFj+AxK
|
||||||
|
0YyGZKmyS4GATtdDuI7uFp188iDI3zZgSI7A4svoDUvn3yGA2G7sgOG1va8aYVRW
|
||||||
|
ftD5f2minppMy3UKt8XVGM+CuFMbQbLaTnQCW6t3fj/luscX4mlBC7pWj+swfoC2
|
||||||
|
q5LvV3vErA8q6jPKDZElps8KRqeLvqkSheKI9Zh7+foijkAkC1kJGbJiX7BnFhM1
|
||||||
|
EKKS6xda4tbewDVBseguO5b37Xqvh3vexSC42q/lxGbo7Md2LlgkORoeGYw7wzDH
|
||||||
|
OoVvYmgktmwEccNu6BtjT0ql9OW3/+PPxxBXL/85crFWrMieNBf3eLeiT5ncv/mR
|
||||||
|
JD+EB4QTTiUvZokEbG8/haGNrJVxDImBIqc4B9dUdikNkwr+cFgjdJezM8FBy7vd
|
||||||
|
5suQHfeLYeqkc+pN097jw6qWdIA2ZPr/96IhIb1Pg0rIC+NqFte5+DB3QKCgUZJR
|
||||||
|
1SUyT1BuNgU65kaM3rTx71UwQ46DMvWwL6BHja8ujPhjh/UiJwIDAQABo4IB3TCC
|
||||||
|
AdkwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0OBBYEFFGI
|
||||||
|
qQzKfuxgQuJad85y1CRs++4ZMCsGA1UdEQQkMCKCECouc3BvdGlsb2NhbC5jb22C
|
||||||
|
DnNwb3RpbG9jYWwuY29tMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEF
|
||||||
|
BQcDAQYIKwYBBQUHAwIwawYDVR0fBGQwYjAvoC2gK4YpaHR0cDovL2NybDMuZGln
|
||||||
|
aWNlcnQuY29tL3NzY2Etc2hhMi1nMy5jcmwwL6AtoCuGKWh0dHA6Ly9jcmw0LmRp
|
||||||
|
Z2ljZXJ0LmNvbS9zc2NhLXNoYTItZzMuY3JsMEIGA1UdIAQ7MDkwNwYJYIZIAYb9
|
||||||
|
bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMw
|
||||||
|
fAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
|
||||||
|
dC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E
|
||||||
|
aWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkq
|
||||||
|
hkiG9w0BAQsFAAOCAQEAr4W8l4mhi1nZUIeRFUyaeFSuKF3wwmMTprkE8y1gZyj2
|
||||||
|
9dReUR/3SsiWsiZhfoZVNDAuDx+poue3YnSq1oNBZvbff2mOZQmVFbMTCiDrfY0e
|
||||||
|
5qCZDNNqoo8d93BHGmAtJq2mnhBLnGTX6s3uiQHrcqs8iSzgXfSn7T6og9GA5vCt
|
||||||
|
qlNykfuVtbMdfVdgI3u2i4TZ/5xmJyRLvzhM4AtdwwHecbJc57/LN3Buif+Al6py
|
||||||
|
l54mNPfvtisl0O7Otz1Tj3aqTDLG8BrLbMRccbgRmfNwAd4bW9jtL0NnKcFDbKeY
|
||||||
|
d3Docj7OIYK7IjWfb4LKts3jUq1ZM1o/eGyp/B4G+w==
|
||||||
|
-----END CERTIFICATE-----
|
51
src/data/spotilocal.key
Normal file
51
src/data/spotilocal.key
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
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
|
||||||
|
-----END RSA PRIVATE KEY-----
|
112
src/facebook.rs
Normal file
112
src/facebook.rs
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
use hyper;
|
||||||
|
use hyper::net::Openssl;
|
||||||
|
use hyper::server::Request;
|
||||||
|
use hyper::server::Response;
|
||||||
|
use hyper::uri::RequestUri;
|
||||||
|
use hyper::header::AccessControlAllowOrigin;
|
||||||
|
use openssl::ssl::{SslContext, SslMethod, SSL_VERIFY_NONE};
|
||||||
|
use openssl::ssl::error::SslError;
|
||||||
|
use openssl::crypto::pkey::PKey;
|
||||||
|
use openssl::x509::X509;
|
||||||
|
use rand::{self, Rng};
|
||||||
|
use rustc_serialize::json;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::io::{Cursor, Read};
|
||||||
|
use std::sync::{mpsc, Arc, Mutex};
|
||||||
|
use url;
|
||||||
|
|
||||||
|
use protocol::authentication::AuthenticationType;
|
||||||
|
use authentication::Credentials;
|
||||||
|
|
||||||
|
static SPOTILOCAL_CERT : &'static [u8] = include_bytes!("data/spotilocal.cert");
|
||||||
|
static SPOTILOCAL_KEY : &'static [u8] = include_bytes!("data/spotilocal.key");
|
||||||
|
|
||||||
|
fn spotilocal_ssl_context() -> Result<Openssl, SslError> {
|
||||||
|
let cert = try!(X509::from_pem(&mut Cursor::new(SPOTILOCAL_CERT)));
|
||||||
|
let key = try!(PKey::private_key_from_pem(&mut Cursor::new(SPOTILOCAL_KEY)));
|
||||||
|
|
||||||
|
let mut ctx = try!(SslContext::new(SslMethod::Sslv23));
|
||||||
|
try!(ctx.set_cipher_list("DEFAULT"));
|
||||||
|
try!(ctx.set_private_key(&key));
|
||||||
|
try!(ctx.set_certificate(&cert));
|
||||||
|
ctx.set_verify(SSL_VERIFY_NONE, None);
|
||||||
|
Ok(Openssl { context: Arc::new(ctx) })
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ServerHandler {
|
||||||
|
token_tx: Mutex<mpsc::Sender<String>>,
|
||||||
|
csrf: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ServerHandler {
|
||||||
|
fn handle_login(&self, params: &BTreeMap<String, String>) -> hyper::status::StatusCode {
|
||||||
|
let token = params.get("access_token").unwrap();
|
||||||
|
let csrf = params.get("csrf").unwrap();
|
||||||
|
|
||||||
|
if *csrf == self.csrf {
|
||||||
|
self.token_tx.lock().unwrap().send(token.to_owned()).unwrap();
|
||||||
|
hyper::status::StatusCode::Ok
|
||||||
|
} else {
|
||||||
|
hyper::status::StatusCode::Forbidden
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl hyper::server::Handler for ServerHandler {
|
||||||
|
fn handle<'a, 'k>(&'a self, request: Request<'a, 'k>, mut response: Response<'a, hyper::net::Fresh>) {
|
||||||
|
response.headers_mut().set(AccessControlAllowOrigin::Value("https://login.spotify.com".to_owned()));
|
||||||
|
*response.status_mut() = if let RequestUri::AbsolutePath(path) = request.uri {
|
||||||
|
let (path, query, _) = url::parse_path(&path).unwrap();
|
||||||
|
let params = query.map_or(vec![], |q| url::form_urlencoded::parse(q.as_bytes()))
|
||||||
|
.into_iter().collect::<BTreeMap<_,_>>();
|
||||||
|
|
||||||
|
if request.method == hyper::method::Method::Get && path == vec!["login", "facebook_login_sso.json"] {
|
||||||
|
self.handle_login(¶ms)
|
||||||
|
} else {
|
||||||
|
hyper::status::StatusCode::NotFound
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hyper::status::StatusCode::NotFound
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn facebook_get_me_id(token: &str) -> Result<String, ()> {
|
||||||
|
let url = format!("https://graph.facebook.com/me?fields=id&access_token={}", token);
|
||||||
|
|
||||||
|
let client = hyper::Client::new();
|
||||||
|
let mut response = client.get(&url).send().unwrap();
|
||||||
|
let mut body = String::new();
|
||||||
|
response.read_to_string(&mut body).unwrap();
|
||||||
|
|
||||||
|
let mut result : BTreeMap<String, String> = json::decode(&body).unwrap();
|
||||||
|
Ok(result.remove("id").unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn facebook_login() -> Result<Credentials, ()> {
|
||||||
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
|
let csrf = rand::thread_rng().gen_ascii_chars().take(32).collect::<String>();
|
||||||
|
let handler = ServerHandler {
|
||||||
|
token_tx: Mutex::new(tx),
|
||||||
|
csrf: csrf.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
let ssl = spotilocal_ssl_context().unwrap();
|
||||||
|
let mut server = hyper::Server::https("127.0.0.1:8001", ssl).unwrap().handle(handler).unwrap();
|
||||||
|
|
||||||
|
println!("Logging in using Facebook, please visit https://login.spotify.com/login-facebook-sso/?csrf={}&port={} in your browser.",
|
||||||
|
csrf, 8001);
|
||||||
|
|
||||||
|
//a2c27234068bbe05d22c1b930b3bc2f5
|
||||||
|
let token = rx.recv().unwrap();
|
||||||
|
let user_id = facebook_get_me_id(&token).unwrap();
|
||||||
|
let cred = Credentials {
|
||||||
|
username: user_id,
|
||||||
|
auth_type: AuthenticationType::AUTHENTICATION_FACEBOOK_TOKEN,
|
||||||
|
auth_data: token.as_bytes().to_owned(),
|
||||||
|
};
|
||||||
|
|
||||||
|
server.close().unwrap();
|
||||||
|
Ok(cred)
|
||||||
|
}
|
|
@ -18,4 +18,7 @@ pub mod stream;
|
||||||
pub mod apresolve;
|
pub mod apresolve;
|
||||||
mod zeroconf;
|
mod zeroconf;
|
||||||
|
|
||||||
|
#[cfg(feature = "facebook")]
|
||||||
|
pub mod facebook;
|
||||||
|
|
||||||
pub use album_cover::get_album_cover;
|
pub use album_cover::get_album_cover;
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#![cfg_attr(not(feature = "with-syntex"), plugin(protobuf_macros))]
|
#![cfg_attr(not(feature = "with-syntex"), plugin(protobuf_macros))]
|
||||||
#![cfg_attr(not(feature = "with-syntex"), plugin(json_macros))]
|
#![cfg_attr(not(feature = "with-syntex"), plugin(json_macros))]
|
||||||
|
|
||||||
|
#![cfg_attr(feature="clippy", feature(plugin))]
|
||||||
|
#![cfg_attr(feature="clippy", plugin(clippy))]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|
||||||
|
@ -31,6 +34,9 @@ extern crate tremor as vorbis;
|
||||||
#[cfg(feature = "dns-sd")]
|
#[cfg(feature = "dns-sd")]
|
||||||
extern crate dns_sd;
|
extern crate dns_sd;
|
||||||
|
|
||||||
|
#[cfg(feature = "openssl")]
|
||||||
|
extern crate openssl;
|
||||||
|
|
||||||
extern crate librespot_protocol as protocol;
|
extern crate librespot_protocol as protocol;
|
||||||
|
|
||||||
#[cfg(feature = "with-syntex")]
|
#[cfg(feature = "with-syntex")]
|
||||||
|
|
43
src/main.rs
43
src/main.rs
|
@ -17,6 +17,13 @@ use librespot::session::{Bitrate, Config, Session};
|
||||||
use librespot::spirc::SpircManager;
|
use librespot::spirc::SpircManager;
|
||||||
use librespot::util::version::version_string;
|
use librespot::util::version::version_string;
|
||||||
|
|
||||||
|
#[cfg(feature = "facebook")]
|
||||||
|
use librespot::facebook::facebook_login;
|
||||||
|
#[cfg(not(feature = "facebook"))]
|
||||||
|
fn facebook_login() -> Result<Credentials, ()> {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
static PASSWORD_ENV_NAME: &'static str = "SPOTIFY_PASSWORD";
|
static PASSWORD_ENV_NAME: &'static str = "SPOTIFY_PASSWORD";
|
||||||
|
|
||||||
fn usage(program: &str, opts: &getopts::Options) -> String {
|
fn usage(program: &str, opts: &getopts::Options) -> String {
|
||||||
|
@ -46,6 +53,10 @@ fn main() {
|
||||||
opts.optopt("a", "appkey", "Path to a spotify appkey", "APPKEY");
|
opts.optopt("a", "appkey", "Path to a spotify appkey", "APPKEY");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if cfg!(feature = "facebook") {
|
||||||
|
opts.optflag("", "facebook", "Login with a Facebook account");
|
||||||
|
}
|
||||||
|
|
||||||
let matches = match opts.parse(&args[1..]) {
|
let matches = match opts.parse(&args[1..]) {
|
||||||
Ok(m) => m,
|
Ok(m) => m,
|
||||||
Err(f) => {
|
Err(f) => {
|
||||||
|
@ -68,19 +79,6 @@ fn main() {
|
||||||
let cache_location = matches.opt_str("c").map(PathBuf::from);
|
let cache_location = matches.opt_str("c").map(PathBuf::from);
|
||||||
let name = matches.opt_str("n").unwrap();
|
let name = matches.opt_str("n").unwrap();
|
||||||
|
|
||||||
let credentials = username.map(|u| {
|
|
||||||
let password = matches.opt_str("p")
|
|
||||||
.or_else(|| std::env::var(PASSWORD_ENV_NAME).ok())
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
print!("Password: ");
|
|
||||||
stdout().flush().unwrap();
|
|
||||||
read_password().unwrap()
|
|
||||||
});
|
|
||||||
|
|
||||||
(u, password)
|
|
||||||
});
|
|
||||||
std::env::remove_var(PASSWORD_ENV_NAME);
|
|
||||||
|
|
||||||
let bitrate = match matches.opt_str("b").as_ref().map(String::as_ref) {
|
let bitrate = match matches.opt_str("b").as_ref().map(String::as_ref) {
|
||||||
None => Bitrate::Bitrate160, // default value
|
None => Bitrate::Bitrate160, // default value
|
||||||
|
|
||||||
|
@ -102,8 +100,23 @@ fn main() {
|
||||||
|
|
||||||
let credentials_path = cache_location.map(|c| c.join("credentials.json"));
|
let credentials_path = cache_location.map(|c| c.join("credentials.json"));
|
||||||
|
|
||||||
let credentials = credentials.map(|(username, password)| {
|
let credentials = username.map(|username| {
|
||||||
|
let password = matches.opt_str("p")
|
||||||
|
.or_else(|| std::env::var(PASSWORD_ENV_NAME).ok())
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
print!("Password: ");
|
||||||
|
stdout().flush().unwrap();
|
||||||
|
read_password().unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
Credentials::with_password(username, password)
|
Credentials::with_password(username, password)
|
||||||
|
}).or_else(|| {
|
||||||
|
if cfg!(feature = "facebook") && matches.opt_present("facebook") {
|
||||||
|
Some(facebook_login().unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}).or_else(|| {
|
}).or_else(|| {
|
||||||
credentials_path.as_ref()
|
credentials_path.as_ref()
|
||||||
.and_then(|p| File::open(p).ok())
|
.and_then(|p| File::open(p).ok())
|
||||||
|
@ -115,6 +128,8 @@ fn main() {
|
||||||
discovery.run()
|
discovery.run()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
std::env::remove_var(PASSWORD_ENV_NAME);
|
||||||
|
|
||||||
let reusable_credentials = session.login(credentials).unwrap();
|
let reusable_credentials = session.login(credentials).unwrap();
|
||||||
if let Some(path) = credentials_path {
|
if let Some(path) = credentials_path {
|
||||||
reusable_credentials.save_to_file(path);
|
reusable_credentials.save_to_file(path);
|
||||||
|
|
|
@ -36,13 +36,7 @@ macro_rules! eprint(
|
||||||
);
|
);
|
||||||
|
|
||||||
pub fn rand_vec<G: Rng, R: Rand>(rng: &mut G, size: usize) -> Vec<R> {
|
pub fn rand_vec<G: Rng, R: Rand>(rng: &mut G, size: usize) -> Vec<R> {
|
||||||
let mut vec = Vec::with_capacity(size);
|
rng.gen_iter().take(size).collect()
|
||||||
|
|
||||||
for _ in 0..size {
|
|
||||||
vec.push(R::rand(rng));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue