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