---
# System prepended metadata

title: 架構圖
tags: [Jukebox]

---

架構圖
===
###### tags: `Jukebox`
[toc]

# Spotify 使用 Fire base

```graphviz
digraph {
node[shape=Mrecord]
rankdir=LR

// subgraph cluster_WebPlayer {
// label="網頁"
    subgraph cluster_user {
    label="user"

    beforeLogin [label="<f1>未登入 |輸入 host 帳號進入 room |查看 host 歌單"];

    userPlayer [label="登入自己的帳號 |<search>搜尋歌 |<list>查看自己的歌單 |網頁播放器"]
    user2host [label="編輯 room 歌單(點/插歌)| 投票決定喀歌"]
    

    userToken [label="自己的 token"]
    }

    subgraph cluster_host {
    label="host"

    hostCreate [label="登入 host, 建立 room"]
    player [label="SDK網頁播放器"]
    message [label="廣播"]


    }
// }

subgraph cluster_firebase {
label="Fire base"

userSystem [label="會員系統"]
room [label="<data>room data |<list>歌單"]
hostToken [label="host token"]
}

subgraph cluster_spotify {
label="spotify"
server [label="Spotify server"];
oauth2 [label="Spotify Oauth2"];
}


message -> Speaker
player -> Speaker
hostCreate -> oauth2 -> room:data -> hostToken

beforeLogin -> room
room -> beforeLogin

userPlayer -> oauth2 -> userToken -> server -> userPlayer

user2host -> hostToken -> server -> player
}
```
好難畫Q_Q總之就是用 firebase 做啦
---
---

## 前端頁面: 

功能:
1. 顯示播放清單(host)
2. 顯示播放清單(user)
3. 網頁播放器(user)
4. 會員登入系統
5. 點歌系統(host)
6. 廣播系統
7. 投票喀歌系統

## story

- 初次造訪網頁先輸入 host 的帳號(room)，找到存在於 Fire base 的 room / 在 fire base 建立 room。
- 取得 room 的資料，顯示目前 room 裡面有的歌單，
- 登入自己的 spotify account 搜尋歌，也可以先透過網頁播放器用自己的帳號先播歌，選擇是否要語音廣播，排序進去 fire base。
- 需要是登入的狀態才可以參與咖歌投票事件
- **歌曲的播放實際上是透過 fire base 讓網頁帳號是登入 host 的手機撥放音樂，原本要在後端做的"音樂與語音的切換"都由 host 的網頁處理**
- user 必須要有 spotify 帳號才可以搜尋音樂

## 待討論

1. 不使用讓 user 使用 host 的 token:
    - 讓 user 可以使用自己的帳號事先播放音樂
    

## Fire base:

1. 儲存 room data
    - host account
    - host token
    - track list
3. 即時發送 room 歌單, 語音文字
4. 會員資料

---

# spotify 單一帳號固定在後端

```graphviz
digraph {
node[shape=Mrecord]
// rankdir=LR

// subgraph cluster_WebPlayer {}

server [label="Spotify server" shape=box];

back [label="
    {<f1> 儲存歌單 |<f2> 自訂會員系統 |插入 Ms.Google 語音}
    |backend
"];


font [label="
    {<f2>查看現在的歌單 |<s1>編輯 backend 歌單(點/插歌) |<s2>投票決定喀歌} |<f1>搜尋介面
    |fontend
"];

phone [label="{phone |與 backend 登入同帳號 |SDK網頁播放器}"]

back -> phone [label="Spotify connect"];
phone -> speaker;

server -> back;
back -> server [label="發出下一首歌API"];

back -> font:s1;
font:s1 -> back;

server -> font:f1 [label="用從 back end 取得的 token 來查詢歌"];
font:f1 -> server;
}
```

## story

- 前端: 顯示播放清單+播放器介面+會員登入系統+點歌廣播系統+投票喀歌系統
    - 登入會員系統前，可以先經由 spotify oauth 登入自己的 spotify account，使用 WEB API 查詢歌或者先在自己的電腦撥放確定這是想要點的歌，再透過網頁傳要點的歌給後端 server。WEB API 目前查看結果也必須要有 token，有誤請告知。如果不需要則可以不需要登入自己的 spotify account 就可以查詢
    - 登入會員系統後，才可以操作後端 server 內的播放清單、投票機制

- 後端: 接收編輯清單+會員資料+投票喀歌系統+發送撥放歌曲 API
    - 會員系統可以
        - 從個人 spotify 獲取基本資料 (但是點歌部分只是傳送 spotify_url 給後端，後端接收到是哪一首歌後加進去暫存的歌單)
            - 訪客式登入或者簡單註冊暱稱當作帳號登入，主要目的只是紀錄是誰點了歌、投票時需要有的依據
    - 必須在前端點歌時接收廣播 message，在當前撥放的歌結束後發暫停撥放API，然後先插入 message 廣播，再送出撥放歌曲的 api
    - 必須發送即時播放清單的更動
    
- 手機: 和使用者所見頁面基本上一樣，登入的是 host account，room host(房主) 的概念
    - 必須是瀏覽器的撥放器，這樣才可以結合 spotify web SDK 和 Google 語音，如果只是單純的 spotify 原生 app，就沒辦法插入 google 語音(是吧?)

---

# ~~單純使用 spotify connect~~

```graphviz

digraph {
node[shape=Mrecord]
// rankdir=LR

user [label="{user |可以使用電腦/手機操作原生 spotify app，連動群組 |自己的電腦/手機必須退出群組才可以撥自己要的音樂 |加入群組期間不小心誤觸手機/電腦的案件會直接影響到整個群組}"];

server [label="Spotify server" shape=box];

back [label="{back end 
|固定帳號維持登入狀態 
|回傳 spotify connent 邀請連結/條碼
|限時將以加入群組播放的 spotify account 踢出，\n因為同時間上限六個帳號
|在對應的歌上發暫停播放 API，並插入廣播給 phone 網頁播放器}"];

font [label="{font end | 渲染條碼 |  渲染目前播放+群組播放清單 | spotify web SDK player}"];

phone [label="{phone |與 backend 登入同帳號 |SDK 網頁播放器}"];


back -> font [label="傳送群組撥放邀請碼"];
font -> back [label="傳送歌單、\n對應廣播"]
font -> user [label="oauth 登入\n使用邀請碼\n加入群組"];
user -> font [label="新增歌單\n新增廣播"];
server -> phone
[label="->因為 connect 特性，\n user電腦/手機、font end SDK player 操作\n都會透過 spotify server 連帶操控手機"];
user -> server
[label="透過 spotify connet 功能\n操控 phone 的 spotify app"];
server -> user;
back -> server [label="登入\n"];
server -> back;
phone -> speaker;

}
```

## story

- spotify 群組播放會讓多個帳號登入後共享同一個播放清單、同時間播放同樣的歌，想像是多個帳號被 spotify server 視為同一個帳號、正在播放同一個清單同一首歌。
- 使用者加入群組後可以操控手機/電腦 spotify app 直接影響整個群組
- 因為釐清流程後立場轉變不推薦不再繼續說明XD好像更麻煩一點都不單純啊啊啊!!
- 最重要不推薦的原因: **使用者可以用自己的 app 操控共享歌單**
- 我的理解有誤或者想太多，那再繼續討論

---

# 單單使用 youtube

```graphviz
digraph {
node[shape=Mrecord]
// rankdir=LR

server [label="youtube server" shape=box];

font [label="{渲染播放清單 |渲染播放器+畫面 |點歌搜尋介面} | font end"];
phone [label="{phone |可能可以跟使用者的同個瀏覽器播放畫面?}"];


back [label="{<f1> 儲存歌單 |<f2> 自訂會員系統 |插入 Ms.Google 語音 |平衡音量} |backend"];


font -> server;
server -> font [label="直接搜尋找歌"];

font -> back
back -> font [label="確認點歌\n編輯歌單"]

phone -> server [label="跟 youtube server 要下首歌音訊"];
server -> phone;

back -> phone [label="下達接下來的歌單給網站"]
phone -> speaker

}

```

- 大概就這樣而已吧~?  感覺簡單多了
- 暫時撇除掉 youbute 可能也可以像 spotify connect 共同編輯歌單這件事情

---

# youtube + spotify

```graphviz
digraph {
node[shape=Mrecord]
// rankdir=LR

// subgraph cluster_WebPlayer {}

s_server [label="Spotify server" shape=box];
y_server [label="Youtube server" shape=box]

back [label="
    {<f1> 儲存歌單 |<f2> 自訂會員系統 |插入 Ms.Google 語音 |判別下一首是 youtube / spotify\n暫停另一方}
    |backend
"];


font [label="
    {<f2>查看現在的歌單 |<s1>編輯 backend 歌單(點/插歌) |<s2>投票決定喀歌} |<f1>搜尋介面
    |fontend
"];

phone [label="{phone |與 backend 登入同帳號 |SDK網頁播放器}"]


back -> phone [label="next youtube url"]
back -> phone [label="Spotify connect"];
phone -> y_server;
y_server -> phone;

phone -> speaker;

s_server -> back;
back -> s_server [label="發出下一首歌API"];

back -> font:s1;
font:s1 -> back;

s_server -> font:f1 [label="用 backend 取得的\ntoken 來查歌"];
font:f1 -> s_server;

y_server -> font:f1 [label="用 backend 取得的\ntoken 來查歌"];
font:f1 -> y_server;

{rank="same"; y_server s_server}

}
```

- 歌單由 backend 管理，順序可能夾雜 spotify / youtube 的歌，如果 下一首是 spotify、youtube 則暫停，反之亦然。
- 需要在網頁中實做出兩個 player 做切換。

# Line Bot

```graphviz
digraph {
node[shape=Mrecord]

spotify [label="Spotify server"];

client [label="{<1>Spotify client |line bot 處理字串變成 api 所需要的樣子 |<2>line bot }"]

spotify -> client
client -> spotify
user -> client:2 
client:2 -> user
// [label="{Line Bot |用 node 架的 server |spotify id, secret, token}"]


}
```