You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.6 KiB
122 lines
3.6 KiB
import Control.Monad (unless)
|
|
import System.Info (os)
|
|
import System.Process (system, rawSystem)
|
|
import System.Exit (ExitCode(..))
|
|
import System.Directory (doesFileExist)
|
|
import Network.Google.OAuth2 (formUrl, exchangeCode, refreshTokens,
|
|
OAuth2Client(..), OAuth2Tokens(..))
|
|
import Network.Google (makeRequest, doRequest)
|
|
import Network.HTTP.Conduit (simpleHttp)
|
|
import Data.Aeson
|
|
import qualified Data.ByteString.Lazy.Char8 as BL
|
|
import qualified Data.Text as T
|
|
import qualified Data.Map as M
|
|
|
|
data URL = URL { jurl :: T.Text }
|
|
deriving (Show, Eq)
|
|
|
|
data VideoID = VideoID { videoID :: T.Text }
|
|
deriving (Show, Eq)
|
|
|
|
data Thumbnail = Thumbnail { thumbnail :: URL }
|
|
deriving (Show, Eq)
|
|
|
|
data JSearchResult = JSearchResult {
|
|
jvideoID :: VideoID,
|
|
snippet :: Snippet
|
|
}
|
|
deriving (Show, Eq)
|
|
|
|
data Snippet = Snippet {
|
|
jtitle :: T.Text,
|
|
jdescription :: T.Text,
|
|
jthumbnails :: Thumbnail
|
|
}
|
|
deriving (Show, Eq)
|
|
|
|
data JItems = JItems [JSearchResult]
|
|
deriving (Show)
|
|
|
|
data SearchResult = SearchResult {
|
|
title :: T.Text,
|
|
description :: T.Text,
|
|
url :: T.Text,
|
|
thumb :: T.Text
|
|
}
|
|
deriving (Show, Eq)
|
|
|
|
instance FromJSON URL where
|
|
parseJSON (Object v) = URL <$> v .: "url"
|
|
|
|
instance FromJSON Thumbnail where
|
|
parseJSON (Object v) = Thumbnail <$> v .: "default"
|
|
|
|
instance FromJSON VideoID where
|
|
parseJSON (Object v) = VideoID <$>
|
|
v .: "videoId"
|
|
|
|
instance FromJSON Snippet where
|
|
parseJSON (Object v) = Snippet <$>
|
|
v .: "title" <*>
|
|
v .: "description" <*>
|
|
v .: "thumbnails"
|
|
|
|
instance FromJSON JSearchResult where
|
|
parseJSON (Object v) = JSearchResult <$>
|
|
(v .: "id") <*>
|
|
(v .: "snippet")
|
|
|
|
instance FromJSON JItems where
|
|
parseJSON (Object v) = JItems <$> v .: "items"
|
|
|
|
makeURL :: T.Text -> T.Text
|
|
makeURL vid = "https://youtube.com/watch?v=" `T.append` vid
|
|
|
|
getItems :: BL.ByteString -> [SearchResult]
|
|
getItems str =
|
|
let parsed = decode str :: Maybe JItems
|
|
in maybe [] getResults parsed
|
|
where
|
|
getResults (JItems xs) = map getResult xs
|
|
getResult x = SearchResult (jtitle . snippet $ x)
|
|
(jdescription . snippet $ x)
|
|
(makeURL . videoID . jvideoID $ x)
|
|
(jurl . thumbnail . jthumbnails . snippet $ x)
|
|
|
|
cid = "571126085022-7ash7a48cdao0tesqe66ghtime34cfvo.apps.googleusercontent.com"
|
|
secret = "FjgeOtSZoJgU87FbuwJf2vwj"
|
|
file = "./tokens.txt"
|
|
baseURI = "https://www.googleapis.com/youtube/v3/"
|
|
|
|
searchRequest :: String -> String -> String
|
|
searchRequest keyword accessTok =
|
|
baseURI ++
|
|
"search?part=snippet&q=" ++
|
|
keyword ++
|
|
"&type=video&access_token=" ++
|
|
accessTok
|
|
|
|
|
|
|
|
main = do
|
|
let client = OAuth2Client { clientId = cid, clientSecret = secret }
|
|
permissionUrl = formUrl client ["https://www.googleapis.com/auth/youtube"]
|
|
b <- doesFileExist file
|
|
unless b $ do
|
|
putStrLn $ "Load this URL: " ++ show permissionUrl
|
|
putStrLn "Please paste the verification code: "
|
|
authcode <- getLine
|
|
tokens <- exchangeCode client authcode
|
|
putStrLn $ "Received access token: " ++ show (accessToken tokens)
|
|
tokens2 <- refreshTokens client tokens
|
|
putStrLn $ "As a test, refreshed token: " ++ show (accessToken tokens2)
|
|
writeFile file (show tokens2)
|
|
accessTok <- fmap (accessToken . read) (readFile file)
|
|
findTracks accessTok "Foo+Fighters"
|
|
|
|
findTracks accessTok term = do
|
|
response <- simpleHttp $ searchRequest term accessTok
|
|
return $ getItems response
|
|
|
|
search :: String -> [T.Text]
|
|
search term = undefined
|
|
|