Untitled

mail@pastecode.io avatar
unknown
typescript
a year ago
5.5 kB
1
Indexable
Never
import getConfig from 'next/config';

import axios from 'axios';
import jsonpAdapter from 'axios-jsonp';
import { Howl } from 'howler';

import { addActiveSound, removeActiveSound } from '../../redux/slices/audioController';

const { publicRuntimeConfig } = getConfig();

type SourceType = {
  name: string;
  id: string | null;
};

type TrackType = {
  name: string;
  src: string;
  link: string;
  id: string;
  howl: Howl;
};

export function getPlayer(albumId, source, callbackWhenLoaded) {
  let player = new Player(
    {
      name: source,
      id: albumId,
    },
    callbackWhenLoaded
  );
  return player;
}

class Player {
  src: SourceType;
  callbackWhenLoaded: Function;
  tracks: TrackType[];
  index: number;
  url: string;
  loaded: boolean;
  playing: boolean;
  data: Object;
  constructor(src: SourceType, callbackWhenLoaded: Function) {
    this.src = {
      name: src.name,
      id: src.id,
    };

    this.callbackWhenLoaded = callbackWhenLoaded;
    this.tracks = [];
    this.index = 0;
    this.url = null;
    this.loaded = false;
    this.playing = false;
    this.data = null;
    this.init();
  }

  init() {
    if (this.src.name == 'Deezer') {
      this.runDeezer();
    } else if (this.src.name == 'FeedFm') {
      this.runFeedFm();
    }
  }

  runDeezer() {
    this.url = `https://api.deezer.com/album/${this.src.id}?output=jsonp`;
    axios
      .get(this.url, { adapter: jsonpAdapter })
      .then((res) => {
        let data = res.data;
        data.tracks.data.forEach((item, i) => {
          this.tracks[i] = {
            name: item.title,
            src: item.preview,
            link: item.link,
            id: item.id,
            howl: null,
          };
        });
      })
      .then(() => {
        this.data = {
          tracks: this.tracks,
        };
        this.loaded = true;
        this.getSound(0);
        this.callbackWhenLoaded(true);
      })
      .catch((error) => {
        console.error(error);
      });
  }

  runFeedFm() {
    const token = publicRuntimeConfig.FEEDFM_CLIENT_TOKEN;
    const secret = publicRuntimeConfig.FEEDFM_CLIENT_SECRET;
    const encodedBase64Token = Buffer.from(`${token}:${secret}`).toString('base64');
    const authorization = `Basic ${encodedBase64Token}`;

    const getSessionUrl = `https://feed.fm/api/v2/session`;

    axios
      .post(getSessionUrl, {}, { headers: { Authorization: authorization } })
      .then((res) => {
        const clientId = res.data.session.client_id;
        const placementId = res.data.placement.id;
        const getSessionUrl = `https://feed.fm/api/v2/station/13586077/audio_file`;

        axios
          .get(getSessionUrl, {
            headers: { Authorization: authorization },
            params: { client_id: clientId },
          })
          .then((res) => {
            let data = res.data;
            data.audio_files.forEach((item, i) => {
              let getAudioFileUrl = `https://feed.fm/api/v2/play`;
              axios
                .post(
                  getAudioFileUrl,
                  {},
                  {
                    headers: { Authorization: authorization },
                    params: { client_id: clientId, placement_id: placementId, audio_file_id: item.id },
                  }
                )
                .then((res) => {
                  let data = res.data.play.audio_file;
                  this.tracks[i] = {
                    name: data.track.title,
                    src: data.url,
                    link: data.url,
                    id: data.track.id,
                    howl: null,
                  };
                })
                .catch((error) => {
                  console.error(error);
                });
            });
          })
          .then(() => {
            this.data = {
              tracks: this.tracks,
            };
            this.loaded = true;
            this.getSound(0);
            this.callbackWhenLoaded(true);
          })
          .catch((error) => {
            console.error(error);
          });
      })
      .catch((error) => {
        console.error(error);
      });
  }

  getSound(index = 0) {
    let sound;
    index = typeof index === 'number' ? index : this.index;
    let data = this.tracks[index];
    if (data) {
      if (data.howl) {
        sound = data.howl;
      } else {
        sound = data.howl = new Howl({
          src: data.src,
          html5: true,
        });
        sound.on('play', addActiveSound(this.tracks[index].name, sound, 2));
        sound.on('end', () => {
          removeActiveSound(this.tracks[index].name)();
          this.skip('next');
        });
      }
      this.index = index;
      return sound;
    }
  }

  play(index) {
    let sound = this.getSound(index);
    sound.play();
  }

  skip(direction) {
    let index = 0;
    if (direction === 'prev') {
      index = this.index - 1;
      if (index < 0) {
        index = this.tracks.length - 1;
      }
    } else {
      index = this.index + 1;
      if (index >= this.tracks.length) {
        index = 0;
      }
    }

    this.skipTo(index);
  }

  skipTo(index) {
    if (this.tracks[this.index] && this.tracks[this.index].howl) {
      this.tracks[this.index].howl.stop();
    }
    this.play(index);
  }
}