<commit_before>import mongoose from 'mongoose';
import Promise from 'bluebird';
import debug from 'debug';

import { createCommand } from '../sockets';
import { GenericError } from '../errors';
import { fetchMedia } from './search';

const ObjectId = mongoose.Types.ObjectId;
const log = debug('uwave:api:v1:playlists');

const addMedia = function addMedia(sourceType, sourceID, keys, Media) {
  return fetchMedia(sourceType, sourceID, keys)
  .then(media => {
    return new Media(media).save();
  });
};

const toPlaylistResponse = function toPlaylistResponse(model) {
  return {
    '_id': model.id,
    'name': model.name,
    'author': model.author,
    'created': model.created,
    'description': model.description,
    'shared': model.shared,
    'nsfw': model.nsfw,
    'size': model.media.length
  };
};

export const getPlaylists = function getPlaylists(page, limit, id, mongo) {
  const Playlist = mongo.model('Playlist');

  const _page = (isNaN(page) ? 0 : page);
  const _limit = (isNaN(limit) ? 50 : Math.min(limit, 50));

  return Playlist.find({'author': id})
  .setOptions({ 'limit': _limit, 'skip': _limit * _page })
  .exec()
  .then(playlists => {
    const _playlists = [];

    for (let i = playlists.length - 1; i >= 0; i--) {
      _playlists.push(toPlaylistResponse(playlists[i]));
    }

    return _playlists;
  });
};

export const createPlaylist = function createPlaylist(data, mediaArray, mongo) {
  const PlaylistItem = mongo.model('PlaylistItem');
  const Playlist = mongo.model('Playlist');

  const playlist = new Playlist(data);

  return playlist.validate()
  .then(() => {
    let pending = mediaArray.length;
    const cb = (err, media) => {
      if (err) {
        playlist.remove();
        throw err;
      }

      pending--;
      playlist.media.push(media.id);
      if (!pending) return playlist.save();
    };

    if (!pending) return playlist.save();

    for (let i = 0, l = mediaArray.length; i < l; i++) {
      new PlaylistItem(mediaArray[i]).save();
    }
  });
};

export const getPlaylist = function getPlaylist(page, limit, id, playlistID, populate, mongo) {
  const Playlist = mongo.model('Playlist');
  const _page = (isNaN(page) ? 0 : page);
  const _limit = (isNaN(limit) ? 100 : Math.min(limit, 100));
  const _slice = { 'media' : { '$slice': [_limit * _page, _limit ] } };

  return Playlist.findOne({ '_id': playlistID, 'author': id })
  .then(playlist => {
    if (!playlist) throw new GenericError(404, 'playlist not found or private');

    if (populate) {
      return playlist.populate('media').execPopulate()
      .then(_playlist => {
        return Playlist.populate(_playlist, { 'path': 'media.media', 'model': 'Media' });
      });
    } else {
      return toPlaylistResponse(playlist);
    }
  });
};

export const deletePlaylist = function deletePlaylist(id, playlistID, uwave) {
  const Playlist = uwave.mongo.model('Playlist');
  let _active = null;

  return uwave.redis.get(`playlist:${id}`)
  .then(active => {
    _active = active;
    return Playlist.findOne(ObjectId(playlistID));
  })<commit_msg>playlists: paginate playlist media results, fixes #54<commit_after>import mongoose from 'mongoose';
import Promise from 'bluebird';
import debug from 'debug';

import { createCommand } from '../sockets';
import { GenericError } from '../errors';
import { fetchMedia } from './search';

const ObjectId = mongoose.Types.ObjectId;
const log = debug('uwave:api:v1:playlists');

const addMedia = function addMedia(sourceType, sourceID, keys, Media) {
  return fetchMedia(sourceType, sourceID, keys)
  .then(media => {
    return new Media(media).save();
  });
};

const toPlaylistResponse = function toPlaylistResponse(model) {
  return {
    '_id': model.id,
    'name': model.name,
    'author': model.author,
    'created': model.created,
    'description': model.description,
    'shared': model.shared,
    'nsfw': model.nsfw,
    'size': model.media.length
  };
};

export const getPlaylists = function getPlaylists(page, limit, id, mongo) {
  const Playlist = mongo.model('Playlist');

  const _page = (isNaN(page) ? 0 : page);
  const _limit = (isNaN(limit) ? 50 : Math.min(limit, 50));

  return Playlist.find({'author': id})
  .setOptions({ 'limit': _limit, 'skip': _limit * _page })
  .exec()
  .then(playlists => {
    const _playlists = [];

    for (let i = playlists.length - 1; i >= 0; i--) {
      _playlists.push(toPlaylistResponse(playlists[i]));
    }

    return _playlists;
  });
};

export const createPlaylist = function createPlaylist(data, mediaArray, mongo) {
  const PlaylistItem = mongo.model('PlaylistItem');
  const Playlist = mongo.model('Playlist');

  const playlist = new Playlist(data);

  return playlist.validate()
  .then(() => {
    let pending = mediaArray.length;
    const cb = (err, media) => {
      if (err) {
        playlist.remove();
        throw err;
      }

      pending--;
      playlist.media.push(media.id);
      if (!pending) return playlist.save();
    };

    if (!pending) return playlist.save();

    for (let i = 0, l = mediaArray.length; i < l; i++) {
      new PlaylistItem(mediaArray[i]).save();
    }
  });
};

export const getPlaylist = function getPlaylist(page, limit, id, playlistID, populate, mongo) {
  const Playlist = mongo.model('Playlist');
  const _page = (isNaN(page) ? 0 : page);
  const _limit = (isNaN(limit) ? 100 : Math.min(limit, 100));

  return Playlist.findOne(
    { '_id': playlistID, 'author': id },
    { 'media' : { '$slice': [_limit * _page, _limit ] } }
  )
  .then(playlist => {
    if (!playlist) throw new GenericError(404, 'playlist not found or private');

    if (populate) {
      return playlist.populate('media').execPopulate()
      .then(_playlist => {
        return Playlist.populate(_playlist, { 'path': 'media.media', 'model': 'Media' });
      });
    } else {
      return toPlaylistResponse(playlist);
    }
  });
};

export const deletePlaylist = function deletePlaylist(id, playlistID, uwave) {
  const Playlist = uwave.mongo.model('Playlist');
  let _active = null;

  return uwave.redis.get(`playlist:${id}`)
  .then(active => {
    _active = active;
    return Playlist.findOne(ObjectId(playlistID));
  })
{'fraction_non_alphanumeric': 0.158632919555054, 'fraction_numerical': 0.006448492664839594, 'mean_word_length': 3.508720930232558, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1978870', 'n_tokens_mistral': 2079, 'n_tokens_neox': 2026, 'n_words': 498}