Beispiel #1
0
// CheckAPIKey performs a test API call with the API key
// provided in the configuration file to determine if the
// service should be enabled.
func (yt *YouTube) CheckAPIKey() error {
	var (
		response *http.Response
		v        *jason.Object
		err      error
	)

	if viper.GetString("api_keys.youtube") == "" {
		return errors.New("No YouTube API key has been provided")
	}
	url := "https://www.googleapis.com/youtube/v3/videos?part=snippet&id=KQY9zrjPBjo&key=%s"
	response, err = http.Get(fmt.Sprintf(url, viper.GetString("api_keys.youtube")))
	defer response.Body.Close()
	if err != nil {
		return err
	}

	if v, err = jason.NewObjectFromReader(response.Body); err != nil {
		return err
	}

	if v, err = v.GetObject("error"); err == nil {
		message, _ := v.GetString("message")
		code, _ := v.GetInt64("code")
		errArray, _ := v.GetObjectArray("errors")
		reason, _ := errArray[0].GetString("reason")

		return fmt.Errorf("%d: %s (reason: %s)", code, message, reason)
	}
	return nil
}
Beispiel #2
0
func PrintLsFromJSON(json *jason.Object, version int, long bool, blobs bool, item string) {

	var thisVersion int

	blobArray, _ := json.GetObjectArray("Blobs")
	versionArray, _ := json.GetObjectArray("Versions")

	// if version set to zero, use lastest, else use the one given

	if version == 0 {
		thisVersion = len(versionArray)
	} else {
		thisVersion = version
	}

	// Find the version in the JSON, and its subtending slot map

	versionElement := versionArray[thisVersion-1]
	slotMap, _ := versionElement.GetObject("Slots")

	// sort the Slot Keys (filenames) in an array

	keyMap := []string{}

	for key, _ := range slotMap.Map() {
		keyMap = append(keyMap, key)

	}

	sort.Strings(keyMap)

	// Print the slots in the sorted order

	if long {
		fmt.Println("Blob       Size Date                 Creator File")
		fmt.Println("-------------------------------------------------------------------------------------")
	}

	for i := range keyMap {

		if long {
			blobID, _ := slotMap.GetInt64(keyMap[i])
			itemSize, _ := blobArray[blobID-1].GetInt64("Size")
			saveDate, _ := blobArray[blobID-1].GetString("SaveDate")
			creator, _ := blobArray[blobID-1].GetString("Creator")

			fmt.Printf("%03d %12d %s %-8s ", blobID, itemSize, strings.Split(strings.Replace(saveDate, "T", " ", 1), ".")[0], creator)
		}

		fmt.Printf("%s/", item)

		if version != 0 {
			fmt.Printf("@%d/", thisVersion)
		}

		fmt.Printf("%s ", keyMap[i])
		fmt.Printf("\n")
	}
}
Beispiel #3
0
// Return device make/model from json imageinfo object.
func extractCamera(imageinfo *jason.Object) (string, string) {
	metadata, err := imageinfo.GetObjectArray("commonmetadata")
	if err != nil {
		// metadata is null in some cases
		return "", ""
	} else {
		return findCamera(metadata)
	}
}
Beispiel #4
0
func PrintListFromJSON(json *jason.Object) {

	versionArray, _ := json.GetObjectArray("Versions")

	for _, version := range versionArray {
		versionID, _ := version.GetInt64("ID")
		saveDate, _ := version.GetString("SaveDate")
		creator, _ := version.GetString("Creator")
		note, _ := version.GetString("Note")

		if note == "" {
			note = "\"\""
		}

		fmt.Printf("@%02d %s %s %s\n", versionID, strings.Split(strings.Replace(saveDate, "T", " ", 1), ".")[0], creator, note)
	}
}
Beispiel #5
0
func (yt *YouTube) getTrack(id string, submitter *gumble.User, offset time.Duration) (bot.Track, error) {
	var (
		resp *http.Response
		err  error
		v    *jason.Object
	)

	videoURL := "https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id=%s&key=%s"
	resp, err = http.Get(fmt.Sprintf(videoURL, id, viper.GetString("api_keys.youtube")))
	defer resp.Body.Close()
	if err != nil {
		return bot.Track{}, err
	}

	v, err = jason.NewObjectFromReader(resp.Body)
	if err != nil {
		return bot.Track{}, err
	}
	items, _ := v.GetObjectArray("items")
	if len(items) == 0 {
		return bot.Track{}, errors.New("This YouTube video is private")
	}
	item := items[0]
	title, _ := item.GetString("snippet", "title")
	thumbnail, _ := item.GetString("snippet", "thumbnails", "high", "url")
	author, _ := item.GetString("snippet", "channelTitle")
	durationString, _ := item.GetString("contentDetails", "duration")
	durationConverted, _ := duration.FromString(durationString)
	duration := durationConverted.ToDuration()

	return bot.Track{
		ID:             id,
		URL:            "https://youtube.com/watch?v=" + id,
		Title:          title,
		Author:         author,
		Submitter:      submitter.Name,
		Service:        yt.ReadableName,
		Filename:       id + ".track",
		ThumbnailURL:   thumbnail,
		Duration:       duration,
		PlaybackOffset: offset,
		Playlist:       nil,
	}, nil
}
Beispiel #6
0
func MakeStubFromJSON(json *jason.Object, item string, pathPrefix string) {

	versionArray, _ := json.GetObjectArray("Versions")

	thisVersion := len(versionArray)

	// Find the version in the JSON, and its subtending slot map

	versionElement := versionArray[thisVersion-1]
	slotMap, _ := versionElement.GetObject("Slots")

	for key, _ := range slotMap.Map() {
		targetFile := path.Join(pathPrefix, key)

		// create target directory, return on error

		targetDir, _ := path.Split(targetFile)

		err := os.MkdirAll(targetDir, 0755)

		if err != nil {
			fmt.Printf("Error: could not create directory %s\n%s\n", err.Error())
			return
		}

		filePtr, err := os.Create(targetFile)

		if err != nil {
			fmt.Printf("Error: could not file directory %s\n%s\n", err.Error())
			return
		}

		err = filePtr.Close()

		if err != nil {
			fmt.Printf("Error: could not close file %s\n%s\n", err.Error())
			return
		}

		fmt.Println(targetFile)
	}

}
Beispiel #7
0
func (f *FileList) BuildListFromJSON(json *jason.Object) {

	blobArray, _ := json.GetObjectArray("Blobs")
	versionArray, _ := json.GetObjectArray("Versions")

	// build lovely mapping of md5 to blobs
	for _, blob := range blobArray {
		md5Sum, _ := blob.GetString("MD5")
		DecodedMD5, _ := base64.StdEncoding.DecodeString(md5Sum)
		blobID, _ := blob.GetInt64("ID")
		f.Blobs[hex.EncodeToString(DecodedMD5)] = blobID
	}

	for _, version := range versionArray {
		versionID, _ := version.GetInt64("ID")
		slotMap, _ := version.GetObject("Slots")

		for key, _ := range slotMap.Map() {

			blobID, _ := slotMap.GetInt64(key)
			md5Sum, _ := blobArray[blobID-1].GetString("MD5")
			DecodedMD5, _ := base64.StdEncoding.DecodeString(md5Sum)

			innerMap, ok := f.Files[key]

			if !ok {
				innerMap = make(map[int64][]byte)
				f.Files[key] = innerMap
			}

			f.Files[key][blobID] = DecodedMD5

			// maps files in latest version to their blobs
			if versionID == int64(len(versionArray)) {
				f.Blobs[key] = blobID
			}
		}
	}
}
Beispiel #8
0
// GetTracks uses the passed URL to find and return
// tracks associated with the URL. An error is returned
// if any error occurs during the API call.
func (sc *SoundCloud) GetTracks(url string, submitter *gumble.User) ([]interfaces.Track, error) {
	var (
		apiURL string
		err    error
		resp   *http.Response
		v      *jason.Object
		track  bot.Track
		tracks []interfaces.Track
	)

	urlSplit := strings.Split(url, "#t=")

	apiURL = "http://api.soundcloud.com/resolve?url=%s&client_id=%s"

	if sc.isPlaylist(url) {
		// Submitter has added a playlist!
		resp, err = http.Get(fmt.Sprintf(apiURL, urlSplit[0], viper.GetString("api_keys.soundcloud")))
		defer resp.Body.Close()
		if err != nil {
			return nil, err
		}

		v, err = jason.NewObjectFromReader(resp.Body)
		if err != nil {
			return nil, err
		}

		title, _ := v.GetString("title")
		permalink, _ := v.GetString("permalink_url")
		playlist := &bot.Playlist{
			ID:        permalink,
			Title:     title,
			Submitter: submitter.Name,
			Service:   sc.ReadableName,
		}

		var scTracks []*jason.Object
		scTracks, err = v.GetObjectArray("tracks")
		if err != nil {
			return nil, err
		}

		dummyOffset, _ := time.ParseDuration("0s")
		for _, t := range scTracks {
			track, err = sc.getTrack(t, dummyOffset, submitter)
			if err != nil {
				// Skip this track.
				continue
			}
			track.Playlist = playlist
			tracks = append(tracks, track)
		}

		if len(tracks) == 0 {
			return nil, errors.New("Invalid playlist. No tracks were added")
		}
		return tracks, nil
	}

	// Submitter has added a track!

	offset := 0
	// Calculate track offset if needed
	if len(urlSplit) == 2 {
		timeSplit := strings.Split(urlSplit[1], ":")
		multiplier := 1
		for i := len(timeSplit) - 1; i >= 0; i-- {
			time, _ := strconv.Atoi(timeSplit[i])
			offset += time * multiplier
			multiplier *= 60
		}
	}
	playbackOffset, _ := time.ParseDuration(fmt.Sprintf("%ds", offset))

	resp, err = http.Get(fmt.Sprintf(apiURL, urlSplit[0], viper.GetString("api_keys.soundcloud")))
	defer resp.Body.Close()
	if err != nil {
		return nil, err
	}

	v, err = jason.NewObjectFromReader(resp.Body)
	if err != nil {
		return nil, err
	}
	track, err = sc.getTrack(v, playbackOffset, submitter)
	if err != nil {
		return nil, err
	}

	tracks = append(tracks, track)
	return tracks, nil
}
Beispiel #9
0
// GetTracks uses the passed URL to find and return
// tracks associated with the URL. An error is returned
// if any error occurs during the API call.
func (yt *YouTube) GetTracks(url string, submitter *gumble.User) ([]interfaces.Track, error) {
	var (
		playlistURL      string
		playlistItemsURL string
		id               string
		err              error
		resp             *http.Response
		v                *jason.Object
		track            bot.Track
		tracks           []interfaces.Track
	)

	playlistURL = "https://www.googleapis.com/youtube/v3/playlists?part=snippet&id=%s&key=%s"
	playlistItemsURL = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet,contentDetails&playlistId=%s&maxResults=%d&key=%s&pageToken=%s"
	id, err = yt.getID(url)
	if err != nil {
		return nil, err
	}

	if yt.isPlaylist(url) {
		resp, err = http.Get(fmt.Sprintf(playlistURL, id, viper.GetString("api_keys.youtube")))
		defer resp.Body.Close()
		if err != nil {
			return nil, err
		}

		v, err = jason.NewObjectFromReader(resp.Body)
		if err != nil {
			return nil, err
		}

		items, _ := v.GetObjectArray("items")
		item := items[0]

		title, _ := item.GetString("snippet", "title")

		playlist := &bot.Playlist{
			ID:        id,
			Title:     title,
			Submitter: submitter.Name,
			Service:   yt.ReadableName,
		}

		maxItems := math.MaxInt32
		if viper.GetInt("queue.max_tracks_per_playlist") > 0 {
			maxItems = viper.GetInt("queue.max_tracks_per_playlist")
		}

		pageToken := ""
		for len(tracks) < maxItems {
			curResp, curErr := http.Get(fmt.Sprintf(playlistItemsURL, id, maxItems, viper.GetString("api_keys.youtube"), pageToken))
			defer curResp.Body.Close()
			if curErr != nil {
				// An error occurred, simply skip this track.
				continue
			}

			v, err = jason.NewObjectFromReader(curResp.Body)
			if err != nil {
				// An error occurred, simply skip this track.
				continue
			}

			curTracks, _ := v.GetObjectArray("items")
			for _, track := range curTracks {
				videoID, _ := track.GetString("snippet", "resourceId", "videoId")

				// Unfortunately we have to execute another API call for each video as the YouTube API does not
				// return video durations from the playlistItems endpoint...
				newTrack, _ := yt.getTrack(videoID, submitter)
				newTrack.Playlist = playlist
				tracks = append(tracks, newTrack)

				if len(tracks) >= maxItems {
					break
				}
			}
		}

		if len(tracks) == 0 {
			return nil, errors.New("Invalid playlist. No tracks were added")
		}
		return tracks, nil
	}

	track, err = yt.getTrack(id, submitter)
	if err != nil {
		return nil, err
	}
	tracks = append(tracks, track)
	return tracks, nil
}