"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/index.ts
var src_exports = {};
__export(src_exports, {
  YtDlpPlugin: () => YtDlpPlugin,
  download: () => download,
  json: () => json
});
module.exports = __toCommonJS(src_exports);

// src/wrapper.ts
var import_dargs = __toESM(require("dargs"));
var import_promises = __toESM(require("fs/promises"));
var import_node_child_process = require("child_process");
var import_undici = require("undici");

// src/env.ts
var import_path = __toESM(require("path"));
var e = /* @__PURE__ */ __name((key) => process.env[key], "e");
var YTDLP_DISABLE_DOWNLOAD = !!e("YTDLP_DISABLE_DOWNLOAD");
var YTDLP_URL = e("YTDLP_URL");
var YTDLP_IS_WINDOWS = e("YTDLP_IS_WINDOWS") || process.platform === "win32";
var YTDLP_DIR = e("YTDLP_DIR") || import_path.default.join(__dirname, "..", "bin");
var YTDLP_FILENAME = e("YTDLP_FILENAME") || `yt-dlp${YTDLP_IS_WINDOWS ? ".exe" : ""}`;
var YTDLP_PATH = import_path.default.join(YTDLP_DIR, YTDLP_FILENAME);

// src/wrapper.ts
var makeRequest = /* @__PURE__ */ __name(async (url) => {
  const response = await (0, import_undici.request)(url, { headers: { "user-agent": "distube" } });
  if (!response.statusCode) throw new Error(`Cannot make requests to '${url}'`);
  if (response.statusCode.toString().startsWith("3")) {
    if (!response.headers.location || Array.isArray(response.headers.location)) {
      throw new Error(`Cannot redirect to '${url}'`);
    }
    for await (const _chunk of response.body) {
    }
    return makeRequest(response.headers.location);
  }
  if (response.statusCode.toString().startsWith("2")) return response;
  throw new Error(`${url}
Status code ${response.statusCode.toString()}`);
}, "makeRequest");
var args = /* @__PURE__ */ __name((url, flags = {}) => [url].concat((0, import_dargs.default)(flags, { useEquals: false })).filter(Boolean), "args");
var json = /* @__PURE__ */ __name((url, flags, options) => {
  const process2 = (0, import_node_child_process.spawn)(YTDLP_PATH, args(url, flags), options);
  return new Promise((resolve, reject) => {
    let output = "";
    process2.stdout?.on("data", (chunk) => {
      output += chunk;
    });
    process2.stderr?.on("data", (chunk) => {
      output += chunk;
    });
    process2.on("close", (code) => {
      if (code === 0) resolve(JSON.parse(output));
      else reject(new Error(output));
    });
    process2.on("error", reject);
  });
}, "json");
var binContentTypes = ["binary/octet-stream", "application/octet-stream", "application/x-binary"];
var getBinary = /* @__PURE__ */ __name(async (url) => {
  let version = "N/A";
  if (!url) {
    const defaultFilename = `yt-dlp${YTDLP_IS_WINDOWS ? ".exe" : ""}`;
    const defaultUrl = `https://github.com/yt-dlp/yt-dlp/releases/latest/download/${defaultFilename}`;
    try {
      const response2 = await makeRequest("https://api.github.com/repos/yt-dlp/yt-dlp/releases?per_page=1");
      const [{ assets, tag_name }] = await response2.body.json();
      const { browser_download_url } = assets.find(
        ({ name }) => name === `yt-dlp${YTDLP_IS_WINDOWS ? ".exe" : ""}`
      );
      version = typeof tag_name === "string" ? tag_name : "latest";
      url = typeof browser_download_url === "string" ? browser_download_url : defaultUrl;
    } catch {
      version = "latest";
      url = defaultUrl;
    }
  }
  const response = await makeRequest(url);
  const contentType = response.headers["content-type"]?.toString();
  if (binContentTypes.includes(contentType ?? "")) return { buffer: await response.body.arrayBuffer(), version };
  throw new Error(`Unsupported content type: ${contentType}`);
}, "getBinary");
var download = /* @__PURE__ */ __name(() => Promise.all([getBinary(YTDLP_URL), import_promises.default.mkdir(YTDLP_DIR, { recursive: true }).catch(() => void 0)]).then(
  ([{ buffer, version }]) => {
    import_promises.default.writeFile(YTDLP_PATH, Buffer.from(buffer), { mode: 493 });
    return version;
  }
), "download");

// src/index.ts
var import_distube = require("distube");
var isPlaylist = /* @__PURE__ */ __name((i) => Array.isArray(i.entries), "isPlaylist");
var YtDlpPlugin = class extends import_distube.PlayableExtractorPlugin {
  static {
    __name(this, "YtDlpPlugin");
  }
  constructor({ update } = {}) {
    super();
    if (update ?? true) download().catch(() => void 0);
  }
  init(distube) {
    super.init(distube);
    if (this.distube.plugins[this.distube.plugins.length - 1] !== this) {
      console.warn(
        `[${this.constructor.name}] This plugin is not the last plugin in distube. This is not recommended.`
      );
    }
  }
  validate() {
    return true;
  }
  async resolve(url, options) {
    const info = await json(url, {
      dumpSingleJson: true,
      noWarnings: true,
      noCallHome: true,
      preferFreeFormats: true,
      skipDownload: true,
      simulate: true
    }).catch((e2) => {
      throw new import_distube.DisTubeError("YTDLP_ERROR", `${e2.stderr || e2}`);
    });
    if (isPlaylist(info)) {
      if (info.entries.length === 0) throw new import_distube.DisTubeError("YTDLP_ERROR", "The playlist is empty");
      return new import_distube.Playlist(
        {
          source: info.extractor,
          songs: info.entries.map((i) => new YtDlpSong(this, i, options)),
          id: info.id.toString(),
          name: info.title,
          url: info.webpage_url,
          thumbnail: info.thumbnails?.[0]?.url
        },
        options
      );
    }
    return new YtDlpSong(this, info, options);
  }
  async getStreamURL(song) {
    if (!song.url) {
      throw new import_distube.DisTubeError("YTDLP_PLUGIN_INVALID_SONG", "Cannot get stream url from invalid song.");
    }
    const info = await json(song.url, {
      dumpSingleJson: true,
      noWarnings: true,
      noCallHome: true,
      preferFreeFormats: true,
      skipDownload: true,
      simulate: true,
      format: "ba/ba*"
    }).catch((e2) => {
      throw new import_distube.DisTubeError("YTDLP_ERROR", `${e2.stderr || e2}`);
    });
    if (isPlaylist(info)) throw new import_distube.DisTubeError("YTDLP_ERROR", "Cannot get stream URL of a entire playlist");
    return info.url;
  }
  getRelatedSongs() {
    return [];
  }
};
var YtDlpSong = class extends import_distube.Song {
  static {
    __name(this, "YtDlpSong");
  }
  constructor(plugin, info, options = {}) {
    super(
      {
        plugin,
        source: info.extractor,
        playFromSource: true,
        id: info.id,
        name: info.title || info.fulltitle,
        url: info.webpage_url || info.original_url,
        isLive: info.is_live,
        thumbnail: info.thumbnail || info.thumbnails?.[0]?.url,
        duration: info.is_live ? 0 : info.duration,
        uploader: {
          name: info.uploader,
          url: info.uploader_url
        },
        views: info.view_count,
        likes: info.like_count,
        dislikes: info.dislike_count,
        reposts: info.repost_count,
        ageRestricted: Boolean(info.age_limit) && info.age_limit >= 18
      },
      options
    );
  }
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  YtDlpPlugin,
  download,
  json
});
//# sourceMappingURL=index.js.map