All files / src/instagram stream.js

100% Statements 34/34
100% Branches 19/19
100% Functions 10/10
100% Lines 31/31
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103                                                      20x 20x 20x 20x   20x 20x 20x 20x 20x 7x                 11x   11x   11x   11x                   10x 10x 1x   10x   9x   15x 11x   11x 8x 1x 1x   8x 6x 10x           1x                 21x 11x            
import EventEmitter from 'events';
 
/**
 * @class InstagramStream
 * @description InstagramStream class
 * @example
 *
 * // Streaming can be used on all endpoints taking MIN_TAG_ID as parameter
 * const stream = instagram.stream('tags/:tag-name/media/recent');
 *
 * stream.on('message', (message) => {
 *  console.log(message);
 * });
 *
 * // handle stream error
 * stream.on('error', (err) => {
 *  // An error occur
 *  console.log(err);
 * });
 */
class Stream extends EventEmitter {
  /**
   * @private
   * @memberof InstagramStream
   * @description Create a new instance of stream class
   */
  constructor(instagram, endpoint, options = {}) {
    super();
    this.instagram = instagram;
    this.endpoint = endpoint;
    this.runOnCreation =
      options.runOnCreation === false ? options.runOnCreation : true;
    this.interval = options.interval || 10000;
    this.minTagId = options.minTagId;
    this.intervalId = null;
    this.cache = [];
    if (this.runOnCreation) {
      this.start();
    }
  }
 
  /**
   * @memberof InstagramStream
   * @description Start the stream.
   */
  start() {
    this.startDate = new Date();
    // Stop the old stream if there is one
    this.stop();
    // Call a first request
    this.makeRequest();
    // Start setInterval and store id
    this.intervalId = setInterval(this.makeRequest.bind(this), this.interval);
  }
 
  /**
   * @memberof InstagramStream
   * @private
   * @description Make a request on instagram API.<br />
   * Cache the result and emit only new messages.
   */
  makeRequest() {
    const params = {};
    if (this.minTagId) {
      params.min_tag_id = this.minTagId;
    }
    this.instagram.get(this.endpoint, params)
      .then((data) => {
        if (data.data.length > 0) {
          // Only return messages not in cache
          let newPosts = data.data.filter(post => this.cache.indexOf(post.id) === -1);
          this.cache.push(...newPosts.map(post => post.id));
          // Only return messages created after the stream
          newPosts = newPosts.filter(post => this.startDate < post.created_time * 1000);
          if (data.pagination.min_tag_id) {
            this.minTagId = data.pagination.min_tag_id;
            this.cache = [];
          }
          if (newPosts.length > 0) {
            newPosts.forEach((newPost) => {
              this.emit('message', newPost);
            });
          }
        }
      })
      .catch((err) => {
        this.emit('error', err.error || err);
      });
  }
 
  /**
   * @memberof InstagramStream
   * @description Stop the stream.
   */
  stop() {
    if (this.intervalId) {
      clearInterval(this.intervalId);
    }
  }
}
 
export default Stream;