<commit_before>'use strict';

var EventEmitter = require('events').EventEmitter;
var async = require('async');
var util = require('util');
var fs = require('fs');
var request = require('request');
var buildUrl = require('./apiUrlBuilder');

// TODO add support for output folder
// TODO add support to skip already downloaded files
function Flickr(apiKey, parallelRequests) {
  var _this = this;

  _this.apiKey = apiKey;
  _this.parallelRequests = parallelRequests || 5;

  function parseResponse(error, response, body) {
    if (error || response.statusCode !== 200) {
      throw new Error('Unexpected error with getInfo request');
    }

    var data = JSON.parse(body);
    if (data.stat === 'fail') {
      throw new Error('Error with flickr API: ' + data.message);
    }

    return data;
  }

  function getSetInfo(setId, userId, cb) {
    var url = buildUrl(_this.apiKey, 'flickr.photosets.getPhotos', {
      photoset_id: setId,
      user_id: userId
    });

    request(url, function(error, response, body) {
      var data = parseResponse(error, response, body);

      // TODO manage multi-paged sets
      var info = {
        title: data.photoset.title,
        total: data.photoset.total,
        ownername: data.photoset.ownername,
        photos: data.photoset.photo
      };

      cb(info);
    });
  }

  function getPhotoSizes(photoId, cb) {
    var url = buildUrl(_this.apiKey, 'flickr.photos.getSizes', {
      photo_id: photoId
    });

    request(url, function(error, response, body) {
      var data = parseResponse(error, response, body);

      var sizes = {};

      for (var i = 0; i < data.sizes.size.length; i++) {
        sizes[data.sizes.size[i].label] = data.sizes.size[i];
      }

      cb(sizes);
    });
  }

  function downloadPhoto(url, path, cb) {
    // TODO use temp files until the download is complete
    request(url)
        .pipe(fs.createWriteStream(path))
        .on('close', cb);
  }

  // TODO avoid/reduce pyramid of doom (use promises?)
  _this.getSet = function(setId, userId, path, options) {
    getSetInfo(setId, userId, function(info) {
      _this.emit('setInfo', info);

      var tasks = info.photos.map(function(currentValue, index, array) {
        var photoId = currentValue.id;
        return function(cb) {
          getPhotoSizes(photoId, function(sizes) {
            _this.emit('photoSizes', photoId, sizes);

            var path = photoId + '.jpg';
            downloadPhoto(sizes.Original.source, path, function() {
              _this.emit('photoDownloaded', photoId, path);
              cb(null, path);<commit_msg>added temp file creation before the download is complete. Closes #8<commit_after>'use strict';

var EventEmitter = require('events').EventEmitter;
var async = require('async');
var util = require('util');
var fs = require('fs');
var request = require('request');
var buildUrl = require('./apiUrlBuilder');

// TODO add support for output folder
// TODO add support to skip already downloaded files
function Flickr(apiKey, parallelRequests) {
  var _this = this;

  _this.apiKey = apiKey;
  _this.parallelRequests = parallelRequests || 5;

  function parseResponse(error, response, body) {
    if (error || response.statusCode !== 200) {
      throw new Error('Unexpected error with getInfo request');
    }

    var data = JSON.parse(body);
    if (data.stat === 'fail') {
      throw new Error('Error with flickr API: ' + data.message);
    }

    return data;
  }

  function getSetInfo(setId, userId, cb) {
    var url = buildUrl(_this.apiKey, 'flickr.photosets.getPhotos', {
      photoset_id: setId,
      user_id: userId
    });

    request(url, function(error, response, body) {
      var data = parseResponse(error, response, body);

      // TODO manage multi-paged sets
      var info = {
        title: data.photoset.title,
        total: data.photoset.total,
        ownername: data.photoset.ownername,
        photos: data.photoset.photo
      };

      cb(info);
    });
  }

  function getPhotoSizes(photoId, cb) {
    var url = buildUrl(_this.apiKey, 'flickr.photos.getSizes', {
      photo_id: photoId
    });

    request(url, function(error, response, body) {
      var data = parseResponse(error, response, body);

      var sizes = {};

      for (var i = 0; i < data.sizes.size.length; i++) {
        sizes[data.sizes.size[i].label] = data.sizes.size[i];
      }

      cb(sizes);
    });
  }

  function downloadPhoto(url, path, cb) {
    var tempPath = path + '.download';
    request(url)
      .pipe(fs.createWriteStream(tempPath))
      .on('close', function() {
        fs.rename(tempPath, path, cb);
      });
  }

  // TODO avoid/reduce pyramid of doom (use promises?)
  _this.getSet = function(setId, userId, path, options) {
    getSetInfo(setId, userId, function(info) {
      _this.emit('setInfo', info);

      var tasks = info.photos.map(function(currentValue, index, array) {
        var photoId = currentValue.id;
        return function(cb) {
          getPhotoSizes(photoId, function(sizes) {
            _this.emit('photoSizes', photoId, sizes);

            var path = photoId + '.jpg';
            downloadPhoto(sizes.Original.source, path, function() {
              _this.emit('photoDownloaded', photoId, path);
              cb(null, path);
{'fraction_non_alphanumeric': 0.13290420295342673, 'fraction_numerical': 0.0020825444907232107, 'mean_word_length': 2.792534099066762, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 11, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3569899', 'n_tokens_mistral': 1655, 'n_tokens_neox': 1609, 'n_words': 411}