Untitled

mail@pastecode.io avatarunknown
typescript
2 months ago
6.7 kB
12
Indexable
Never
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
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: any,
  source: any,
  callbackWhenLoaded: Function,
) {
  const 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: { data: any }) => {
        const data = res.data;
        data.tracks.data.forEach(
          (
            item: { title: any; preview: any; link: any; id: any },
            i: string | number,
          ) => {
            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: any) => {
        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: {
          data: { session: { client_id: any }; placement: { id: any } };
        }) => {
          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: { data: any }) => {
              const data = res.data;
              data.audio_files.forEach(
                (item: { id: any }, i: string | number) => {
                  const 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: { data: { play: { audio_file: any } } }) => {
                      const 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: any) => {
                      console.error(error);
                    });
                },
              );
            })
            .then(() => {
              this.data = {
                tracks: this.tracks,
              };
              this.loaded = true;
              this.getSound(0);
              this.callbackWhenLoaded(true);
            })
            .catch((error: any) => {
              console.error(error);
            });
        },
      )
      .catch((error: any) => {
        console.error(error);
      });
  }

  getSound(index = 0) {
    let sound;
    index = typeof index === "number" ? index : this.index;
    const 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: number | undefined) {
    const sound = this.getSound(index);
    sound.play();
  }

  skip(direction: string) {
    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: number | undefined) {
    if (this.tracks[this.index] && this.tracks[this.index].howl) {
      this.tracks[this.index].howl.stop();
    }
    this.play(index);
  }
}