Macで再生中の最強のバンドの曲をTwitterに投稿する

# はじめに
普段はPMとか組み込みとかをやっていますが、あまりにもバンドへの衝動が抑えきれなかったので作りました。
swiftとかも初めてですが、あまりにもswift5で動かない文献が多く苦しかったので記事を書きました。
# 作ったもの
最強のバンドへの衝動を解き放ちます
使い方はここを参照しましょう
https://github.com/thrillingdream/saikyo-band
Macで再生中のアーティストの曲の情報を取得して、Twitter上にUploadします。

こんな感じ

>やっぱり最強のバンドは＋[artist名]＋なんだよなあ＋[iThunes URL]
<img width="837" alt="screenshot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680402/021e5548-8381-027d-3224-0dba106c5462.png">


## 動作確認環境
macOS Catalina 10.15.6
swift 5.2.4

# 処理の流れ&使ったもの
Swift Console appです。（UI使ってない）
1. アーティスト名を取得(Apple script)
2. 楽曲のURLを取得(iThunesAPI)
3. 文字の整形
4. ツイートする(NSWorkspace)

ハマった点など書いていきます。

##アーティスト名の取得(Apple script)
[iTunesで聴いている曲をSlackに通知するアプリをswiftで書いた](https://qiita.com/ayasuda/items/3773858e5e93ba94da48)
再生中の楽曲を取るのはこちらがとてもしっかり書かれています。
（ここにたどり着いたということは参照した人も多いのでは）
しかし、現在の環境(swift5, Catalina)ではうまく動作しないようです。

### AppleScriptでの楽曲情報の取得
逆に記事中では
>この中を調べても、やっぱり Apple Music の情報は取れなさそうだ とわかります。

とありましたが、現在は取れるようです。やったね。

```swift:getMusicInfo.swift
    class func getMusicInfoName()-> (String){
        let appleScript = "tell application \"Music\"\n"
            + "set trackName to name of current track\n"
            + "return trackName\n"
            + "end tell"

            var error: NSDictionary?
            let scriptObject = NSAppleScript(source: appleScript)
            if let output: NSAppleEventDescriptor = scriptObject?.executeAndReturnError(&error){
                return (output.stringValue ?? "まだないお")
            }
                
            return("[存在しないトラックを追い求めて行け]")

        }
```
これで大丈夫。

記事の中で通知センターを使う方法が取られていたけど、これはダメっぽい。
引っかかった点は
>"com.apple.iTunes.playerInfo" のオブザーバを登録することで Apple Music の音楽も曲情報が取得できます

これは今、"com.apple.**Music**.playerInfo"になっているっぽい。
ただし、自分でこのIdで発行したら情報が取れたのですが、AppleMusicからは通知が飛んでないようでした。
Gitでブランチ切ってるので検討したい方はぜひ。
私は断念しました。

##楽曲のURLを取得(iThunesAPI)
iOS用の物が多くMacOS向けのの文献は少なかった印象があります。

```swift:getMusicInfo.swift
import Cocoa
```

```swift:getMusicInfo.swift
let artist = getMusicInfoArtist()
let name = getMusicInfoName()
let searchWord = artist + " " + name
let urlString:String = "http://itunes.apple.com/search?term=\(searchWord)&country=JP&lang=ja_jp&media=music&entity=song&limit=30"
let encodeUrlString: String = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let url = URL(string: encodeUrlString)!
```
検索のロジックはこんなかんじ。
ithunesAPIのURLに検索のワードを入れてあげてください。
あと、URLはエンコードしてあげましょう。

```swift:getMusicInfo.swift
        var trackUrl = ""

        let task = URLSession.shared.dataTask(with: url) {(data:Data?, response:URLResponse?, error:Error?) in

            if let error = error {
                trackUrl = "client error: \(error.localizedDescription)"
                return
            }

            guard let data = data, let response = response as? HTTPURLResponse else {
                trackUrl = "no data or no response"
                return
            }

            if response.statusCode == 200 {
                let items = try! JSONSerialization.jsonObject(with: data) as! Dictionary<String, Any>
                let result = items["results"] as! NSArray //JSONから結果の部分を取り出す。JSONの中を見るとわかる。
                let trackUrlNSArray = result.value(forKey: "trackViewUrl")as! NSArray //楽曲のURL情報
                let trackUrlArray = trackUrlNSArray as NSArray as? [String] ?? [""]
                
                //iTunesの検索ロジックで出た結果の一番最初の要素を取り出す（たまにミスる）
                trackUrl = trackUrlArray.first ?? ""
            } else {
                trackUrl = "server error: \(response.statusCode)"
            }

        }
        task.resume()
        
        //Console appなのでsleepを入れないとThreadが処理を終わる前に抜けてしまう
        sleep(1)

        return(trackUrl)
    }
```

JSONの部分は割と雑に作りました。
ご指摘点あればぜひ。

##文字の整形

```swift:getMusicInfo.swift
class EditText{
    
    class func editTextToSaikyo(band_name: String, url: String)-> String{
        
        return ("やっぱり最強のバンドは" + band_name + "なんだよなあ\n" + url)
    }
    
}
```
好きな雛形に変えても構いません。
bloodthirsty butchersはいいぞ。

##ツイートする(NSWorkspace)

```swift:getMusicInfo.swift
import Cocoa

class TweetService{
    
    class func start(text: String){
  
        let encodedText = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
        if let encodedText = encodedText,
            let url = URL(string: "https://twitter.com/intent/tweet?text=\(encodedText)") {
            
            if NSWorkspace.shared.open(url) {
                print("最強のバンド")
            }
        }
    }
}
```
Mac OSなのでNSWorkspace使ってます。
iOSだとUIAppricationっていうのを使うみたいですね。

# 制約及び今後のUpdateなど
1. URLの検索はなかなかにアホです。聞いているの曲ではない可能性があります。直したい。
2. ハッシュタグをつけて最強のバンドランキングとかができれば...

#最後に
やっぱり最強のバンドはeastern youthなんだよなあ
[eastern youthの「心ノ底ニ灯火トモセ」](https://music.apple.com/jp/album/%E3%83%89%E3%83%83%E3%82%B3%E3%82%A4%E7%94%9F%E3%82%AD%E3%83%86%E3%83%AB%E8%A1%97%E3%83%8E%E4%B8%AD/434927497?i=434927628 )

## 参考にしたサイト
ストリーミングされている曲情報の取り方
https://qiita.com/ayasuda/items/3773858e5e93ba94da48
Twitterへの連携のやつ
https://qiita.com/kumamotone/items/c1fe3dd5718d29cc94d0
swiftでAppleScriptを使うやつ
https://qiita.com/Eiryyy/items/4925e7d420519814176a
JSON系
https://qiita.com/satoshi-iwaki/items/708fac8f24ec26068455
URLの使い方
https://qiita.com/shiz/items/09523baf7d1cd37f6dee
iThunes APIの使い方
https://qiita.com/kenchan1837/items/a9e1de18c7eab75c4145