<commit_before>import { LogManager } from "aurelia-framework"
import Album from '../models/album'
import Photo from '../models/photo'
import config from '../../config/app.config'

export default class Flickr {
  constructor() {
    this.log = LogManager.getLogger(`Saeris.io/${this.constructor.name}`)
    this.endpoint = config.flickr.endpoint
    this.key = config.flickr.key
    this.user = config.flickr.user
  }

  async request(method, options, endpoint = this.endpoint, key = this.key ) {
    this.log.debug(`Fetching request using: '${method}' with key: '${key}'`, options)
    let params = ``
    Object.entries(options).forEach(([k, v]) => {
      Array.isArray(v) ? params = `${params}&${k}=${v.join()}` : params = `${params}&${k}=${v}`
    })
    const request = `${endpoint}?method=${method}&api_key=${key}${params}&format=json&nojsoncallback=1`
    return await fetch(request).then(response => response.json(), error => this.log.error(`Failed to fetch request: '${request}'`, error))
  }

  async getPhotos(album, user = this.user) {
    this.log.debug(`3. Getting Photos for album: '${album}'`)
    const options = {
      user_id: user,
      photoset_id: album,
      extras: [`tags`, `url_m`, `url_o`]
    }
    return await this.request(`flickr.photosets.getPhotos`, options)
      .then(async response => {
        this.log.debug(`4. Successfully fetched photos.`, response)
        return await response.photoset.photo.map(photo => new Photo(photo))
      }, error => this.log.error(`Failed to fetch photos.`, error))
  }

  async getAlbums(user = this.user) {
    this.log.debug(`1. Getting Albums for user: '${user}'`)
    const options = {
      user_id: user,
      primary_photo_extras: [`url_m`, `url_o`]
    }
    return await this.request(`flickr.photosets.getList`, options)
      .then(async response => {
        this.log.debug(`2. Successfully fetched albums.`, response)
        let albums = await response.photosets.photoset.map(async album =>  {
          let photos = await this.getPhotos(album.id).then(res => res)
          let result = new Album(album, photos)
          this.log.debug(`5. Successfully created album.`, result)
          return result
        })
        return albums
      }, error => this.log.error(`Failed to fetch albums.`, error))
  }<commit_msg>feat(flickr): Create Flickr API Service, Album and Photo Models<commit_after>import { LogManager } from "aurelia-framework"
import Album from '../models/album'
import Photo from '../models/photo'
import config from '../../config/app.config'

/**
 * TODO:
 * - Add new methods to retrieve more data from Flickr
 * - Integrate with Redux (persist results to store)
 * - Memoize all fetch operations based on store lookups
 */

export default class Flickr {
  constructor() {
    this.log = LogManager.getLogger(`Saeris.io/${this.constructor.name}`)
    this.endpoint = config.flickr.endpoint
    this.key = config.flickr.key
    this.user = config.flickr.user
  }

  /**
   * Generic fetch method. Generates REST URL from provided method and options,
   * performs the fetch request, and returns the results as JSON.
   */
  async request(method, options, endpoint = this.endpoint, key = this.key ) {
    let params = ``
    Object.entries(options).forEach(([k, v]) => {
      Array.isArray(v) ? params = `${params}&${k}=${v.join()}` : params = `${params}&${k}=${v}`
    })
    const query = `${endpoint}?method=${method}&api_key=${key}${params}&format=json&nojsoncallback=1`
    try {
      this.log.debug(`Fetching request: '${query}'`, options)
      const json = await fetch(query).then(async response => await response.json())
      this.log.debug(`Received json:`, json)
      return await json
    } catch (error) {
      this.log.error(`Failed to complete request.`, error)
    }
  }

  /**
   * Returns an array containing all the albums (and it's photos) for the given user.
   */
  async getAlbums(user = this.user) {
    const options = {
      user_id: user,
      primary_photo_extras: [`url_m`, `url_o`]
    }
    try {
      this.log.debug(`Getting Albums for user: '${user}'...`, options)
      const results = await this.request(`flickr.photosets.getList`, options)
      const albums = await Promise.all(
        results.photosets.photoset.map(async album => new Album(album, await this.getAlbumPhotos(album.id)))
      )
      this.log.debug(`Successfully retrieved albums!`, albums)
      return albums
    } catch (error) {
      this.log.error(`Failed to retrieve albums.`, error)
      return []
    }
  }

  /**
   * Returns an array of all the photos belonging to the given album of the given user.
   */
  async getAlbumPhotos(album, user = this.user) {
    const options = {
      user_id: user,
      photoset_id: album,
      extras: [`tags`, `url_m`, `url_o`]
    }
    try {
      this.log.debug(`Getting Photos for album: '${album}'...`, options)
      const results = await this.request(`flickr.photosets.getPhotos`, options)
      const photos = await Promise.all(results.photoset.photo.map(photo => new Photo(photo)))
      this.log.debug(`Successfully retrieved photos!`, photos)
      return photos
    } catch (error) {
      this.log.error(`Failed to retrieve Photos.`, error)
    }
  }
{'fraction_non_alphanumeric': 0.15080275229357798, 'fraction_numerical': 0.001337920489296636, 'mean_word_length': 3.1302288871349644, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, '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': '5494772', 'n_tokens_mistral': 1620, 'n_tokens_neox': 1585, 'n_words': 414}