<commit_before>const User = require('./database/models').User;
const Meeting = require('./database/models').Meeting;
const UserMeeting = require('./database/models').UserMeeting;
const Timeslot = require('./database/models').Timeslot;
// const utils = require('../lib/server_utility.js');

/*
** Expected request body: {owner_id(integer): 'user id', time(date): 'datetime for meeting'}
** Expected response: 201 Created status
** Expected response on database error: 500 Internal Server Error status
*/
exports.addMeeting = function(req, res) {
  Meeting.create(req.body)
  .then(function(newMeeting) {
    res.status(201).send();
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request query: {id(integer): 'id'}
** Expected resposne: 200 OK status
** Expected response on database error: 500 Internal Server Error status
*/
exports.deleteMeeting = function(req, res) {
  Meeting.destroy({where: req.query})
  .then(function(affectedRows) {
    res.status(200).send();
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request body: {username(string): 'username', email(string): 'user email'}
** Expected response if user exists: 409 Conflict status
** Expected response if user does not exist: 201 Created status, {username(string): 'username', email(string): 'user email'}
** Expected response on database error: 500 Internal Server Error status
*/
exports.addUser = function(req, res) {
  // See if email already exists in database
  User.findOne({where: {email: req.body.email}})
  .then(function(foundUser)  {
    if (foundUser) {
      res.status(409).send(foundUser);
    } else {
      // username and email do not exist in database so create new user
      User.create(req.body)
      .then(function(newUser) {
        res.status(201).send(newUser);
      }).catch(function(err) {
        console.error(err);
        res.status(500).send(err);
      });
    }
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request body: {username(string): 'username', email(string): 'user email'}
** Expected response if user exists: 200 OK status, {username(string): 'username', email(string): 'user email'}
** Expected response if user does not exist: 201 Created status, {username(string): 'username', email(string): 'user email'}
** Expected response on database error: 500 Internal Server Error status
*/
exports.checkGmailUser = function(req, res) {
  User.findOrCreate({where: {email: req.body.email}, defaults: {username: req.body.username}})
  .spread(function(newUser, created) {
    if (created) {
      res.status(201).send(newUser);
    } else {
      res.status(200).send(newUser);
    }
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request body: {user_id(integer): 'user id', meeting_id(integer): 'meeting id'}
** Expected response if usermeeting exists: 409 Conflict status
** Expected response if usermeeting does not exist: 201 Created status
** Expected response on database error: 500 Internal Server Error status
*/
exports.addUserMeeting = function(req, res) {
  UserMeeting.findOrCreate({where: req.body})
  .spread(function(newUserMeeting, created) {
    if (created) {
      console.log(newUserMeeting);
      res.status(201).send(newUserMeeting);
    } else {
      res.status(409).send(newUserMeeting);
    }
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected response: 200 OK status, {usermeetings(array): [{id(integer): 'id', user_id(integer): 'user id', meeting_id(integer): 'meeting id', createdAt(date): 'creation date', updatedAt(date): 'last updated date'}]}
** Expected response on database error: 500 Internal Server Error status
*/
exports.listAllUserMeetings = function(req, res) {
  UserMeeting.findAll()
  .then(function(foundUserMeetings) {
    res.status(200).send(foundUserMeetings);
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request query: {user_id(integer): 'user id'}
** Expected response: 200 OK status, {usermeetings(array): [{id(integer): 'id', user_id(integer): 'user id', meeting_id(integer): 'meeting id', createdAt(date): 'creation date', updatedAt(date): 'last updated date'}]}
** Expected response on database error: 500 Internal Server Error status
*/
exports.listUserMeetings = function(req, res) {
  UserMeeting.findAll({where: req.query})
  .then(function(foundUserMeetings) {
    res.status(200).send(foundUserMeetings);
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request query: {id: 'id'}
** Expected response: 200 OK status
** Expected response on database error: 500 Internal Server Error status
*/
exports.deleteUserMeeting = function(req, res) {
  UserMeeting.destroy({where: req.query})
  .then(function(affectedRows) {
    res.status(200).send();
  }).catch(function(err) {
    console.error(err);
    res.status(500).send();
  });
};

/*
** Expected request body: {owner_id(integer): 'user id', start(date): 'start time', end(date): 'end time'}
** Expected response: 201 Created status
** Expected response on database error: 500 Internal Server Error status
*/
exports.addTimeslot = function(req, res) {
  Timeslot.create(req.body)
  .then(function(newTimeslot) {
    res.status(201).send(newTimeslot);
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request body: {timeslots: [{owner_id(integer): 'user id', start(date): 'start time', end(date): 'end time'}]}
** Expected response: 201 Created status
** Expected response on database error: 500 Internal Server Error status
*/
exports.addMultipleTimeslots = function(req, res) {
  Timeslot.bulkCreate(req.body.timeslots)
  .then(function() {
    res.status(201).send();
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected response: 200 OK status, {id(integer): 'id', owner_id(integer): 'owner id', start(date): 'start time', end(date): 'end time', createdAt(date): 'creation date', updatedAt(date): 'last updated date'}
** Expected response on database error: 500 Internal Server Error status
*/
exports.listAllTimeslots = function(req, res) {
  Timeslot.findAll()
  .then(function(foundTimeslots) {
    res.status(200).send(foundTimeslots);
  }).catch(function(err) {
    res.status(500).send(err);
  });
};

/*
** Expected request query: {owner_id(integer): 'user id'}
** Expected response: 200 OK status, {id(integer): 'id', owner_id(integer): 'owner id', start(date): 'start time', end(date): 'end time', createdAt(date): 'creation date', updatedAt(date): 'last updated date'}
** Expected response on database error: 500 Internal Server Error status
*/
exports.listTimeslots = function(req, res) {
  Timeslot.findAll({where: req.query})
  .then(function(foundTimeslots) {
    res.status(200).send(foundTimeslots);
  }).catch(function(err) {
    res.status(500).send(err);
  });
};

/*
** Expected request query: {id: id}
** Expected response: 200 OK status
** Expected response on database error: 500 Internal Server Error status
*/
exports.deleteTimeslot = function(req, res) {
  Timeslot.destroy({where: {id: req.query.id}})
  .then(function(affectedRows) {
    res.status(200).send();
  }).catch(function(err) {
    res.status(500).send(err);
  });
};
<commit_msg>Updated expected request body for addMeeting<commit_after>const User = require('./database/models').User;
const Meeting = require('./database/models').Meeting;
const UserMeeting = require('./database/models').UserMeeting;
const Timeslot = require('./database/models').Timeslot;
// const utils = require('../lib/server_utility.js');

/*
** Expected request body: {owner_id(integer): 'user id', job_position(date): 'position for the job'}
** Expected response: 201 Created status
** Expected response on database error: 500 Internal Server Error status
*/
exports.addMeeting = function(req, res) {
  Meeting.create(req.body)
  .then(function(newMeeting) {
    res.status(201).send();
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request query: {id(integer): 'id'}
** Expected resposne: 200 OK status
** Expected response on database error: 500 Internal Server Error status
*/
exports.deleteMeeting = function(req, res) {
  Meeting.destroy({where: req.query})
  .then(function(affectedRows) {
    res.status(200).send();
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request body: {username(string): 'username', email(string): 'user email'}
** Expected response if user exists: 409 Conflict status
** Expected response if user does not exist: 201 Created status, {username(string): 'username', email(string): 'user email'}
** Expected response on database error: 500 Internal Server Error status
*/
exports.addUser = function(req, res) {
  // See if email already exists in database
  User.findOne({where: {email: req.body.email}})
  .then(function(foundUser)  {
    if (foundUser) {
      res.status(409).send(foundUser);
    } else {
      // username and email do not exist in database so create new user
      User.create(req.body)
      .then(function(newUser) {
        res.status(201).send(newUser);
      }).catch(function(err) {
        console.error(err);
        res.status(500).send(err);
      });
    }
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request body: {username(string): 'username', email(string): 'user email'}
** Expected response if user exists: 200 OK status, {username(string): 'username', email(string): 'user email'}
** Expected response if user does not exist: 201 Created status, {username(string): 'username', email(string): 'user email'}
** Expected response on database error: 500 Internal Server Error status
*/
exports.checkGmailUser = function(req, res) {
  User.findOrCreate({where: {email: req.body.email}, defaults: {username: req.body.username}})
  .spread(function(newUser, created) {
    if (created) {
      res.status(201).send(newUser);
    } else {
      res.status(200).send(newUser);
    }
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request body: {user_id(integer): 'user id', meeting_id(integer): 'meeting id'}
** Expected response if usermeeting exists: 409 Conflict status
** Expected response if usermeeting does not exist: 201 Created status
** Expected response on database error: 500 Internal Server Error status
*/
exports.addUserMeeting = function(req, res) {
  UserMeeting.findOrCreate({where: req.body})
  .spread(function(newUserMeeting, created) {
    if (created) {
      console.log(newUserMeeting);
      res.status(201).send(newUserMeeting);
    } else {
      res.status(409).send(newUserMeeting);
    }
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected response: 200 OK status, {usermeetings(array): [{id(integer): 'id', user_id(integer): 'user id', meeting_id(integer): 'meeting id', createdAt(date): 'creation date', updatedAt(date): 'last updated date'}]}
** Expected response on database error: 500 Internal Server Error status
*/
exports.listAllUserMeetings = function(req, res) {
  UserMeeting.findAll()
  .then(function(foundUserMeetings) {
    res.status(200).send(foundUserMeetings);
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request query: {user_id(integer): 'user id'}
** Expected response: 200 OK status, {usermeetings(array): [{id(integer): 'id', user_id(integer): 'user id', meeting_id(integer): 'meeting id', createdAt(date): 'creation date', updatedAt(date): 'last updated date'}]}
** Expected response on database error: 500 Internal Server Error status
*/
exports.listUserMeetings = function(req, res) {
  UserMeeting.findAll({where: req.query})
  .then(function(foundUserMeetings) {
    res.status(200).send(foundUserMeetings);
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request query: {id: 'id'}
** Expected response: 200 OK status
** Expected response on database error: 500 Internal Server Error status
*/
exports.deleteUserMeeting = function(req, res) {
  UserMeeting.destroy({where: req.query})
  .then(function(affectedRows) {
    res.status(200).send();
  }).catch(function(err) {
    console.error(err);
    res.status(500).send();
  });
};

/*
** Expected request body: {owner_id(integer): 'user id', start(date): 'start time', end(date): 'end time'}
** Expected response: 201 Created status
** Expected response on database error: 500 Internal Server Error status
*/
exports.addTimeslot = function(req, res) {
  Timeslot.create(req.body)
  .then(function(newTimeslot) {
    res.status(201).send(newTimeslot);
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected request body: {timeslots: [{owner_id(integer): 'user id', start(date): 'start time', end(date): 'end time'}]}
** Expected response: 201 Created status
** Expected response on database error: 500 Internal Server Error status
*/
exports.addMultipleTimeslots = function(req, res) {
  Timeslot.bulkCreate(req.body.timeslots)
  .then(function() {
    res.status(201).send();
  }).catch(function(err) {
    console.error(err);
    res.status(500).send(err);
  });
};

/*
** Expected response: 200 OK status, {id(integer): 'id', owner_id(integer): 'owner id', start(date): 'start time', end(date): 'end time', createdAt(date): 'creation date', updatedAt(date): 'last updated date'}
** Expected response on database error: 500 Internal Server Error status
*/
exports.listAllTimeslots = function(req, res) {
  Timeslot.findAll()
  .then(function(foundTimeslots) {
    res.status(200).send(foundTimeslots);
  }).catch(function(err) {
    res.status(500).send(err);
  });
};

/*
** Expected request query: {owner_id(integer): 'user id'}
** Expected response: 200 OK status, {id(integer): 'id', owner_id(integer): 'owner id', start(date): 'start time', end(date): 'end time', createdAt(date): 'creation date', updatedAt(date): 'last updated date'}
** Expected response on database error: 500 Internal Server Error status
*/
exports.listTimeslots = function(req, res) {
  Timeslot.findAll({where: req.query})
  .then(function(foundTimeslots) {
    res.status(200).send(foundTimeslots);
  }).catch(function(err) {
    res.status(500).send(err);
  });
};

/*
** Expected request query: {id: id}
** Expected response: 200 OK status
** Expected response on database error: 500 Internal Server Error status
*/
exports.deleteTimeslot = function(req, res) {
  Timeslot.destroy({where: {id: req.query.id}})
  .then(function(affectedRows) {
    res.status(200).send();
  }).catch(function(err) {
    res.status(500).send(err);
  });
};
<|endoftext|>


<commit_before>/* eslint no-undef: [0]*/
module.exports = {
  title: "mAlbum",
  style: "m-album.less",
  template: 'm-album.html',
  i18n: {
    pt: "lang/pt-BR.json",
    en: "lang/en-US.json"
  },
  link: function() {},
  controller: function(
    $scope,
    $rootScope,
    $filter,
    $timeout,
    $mState,
    $stateParams,
    $mDataLoader,
    $element,
    $ionicModal,
    $ionicScrollDelegate,
    $mDaia,
    $mAuth,
    $ionicPopover,
    $mAlert
  ) {
    var dataLoadOptions;
    var userLikeId;
    var list = {
      /**
       * Set the view and update the needed parameters
       * @param  {object} data Data received from Moblets backend
       * @param  {boolean} more If called by "more" function, it will add the
       * data to the items array
       */
      setView: function(data, more) {
        if (isDefined(data)) {
          $scope.error = false;
          $scope.emptyData = false;

          // If it was called from the "more" function, concatenate the items
          $scope.items = (more) ? $scope.items.concat(data.items) : data.items;

          // Set "noContent" if the items lenght = 0
          $scope.moblet.noContent = $scope.items === undefined ||
            $scope.items.length === 0;

          // set empty itens if no content
          if ($scope.moblet.noContent) {
            $scope.items = [];
          }

          // Check if the page is loading the list or a detail
          $scope.isDetail = list.isDetail();

          // Disable the "more" function if the API don't have more items
          $scope.more = (data.hasMoreItems && !$scope.isDetail) ? list.more : undefined;
        } else {
          $scope.error = true;
          $scope.emptyData = true;
        }

        // Broadcast complete refresh and infinite scroll
        $rootScope.$broadcast('scroll.refreshComplete');
        $rootScope.$broadcast('scroll.infiniteScrollComplete');

        // If the view is showing the detail, call showDetail
        if ($scope.isDetail) {
          list.showDetail();
        }

        // Remove the loading animation
        $scope.moblet.isLoading = false;
      },
      /**
       * Check if the view is showing a detail or the list. The function checks
       * if $stateParams.detail is set.
       * @return {boolean} True if the view must show a detail.
       */
      isDetail: function() {
        return $stateParams.detail !== "";
      },
      /**
       * Show the detail getting the index from $stateParams.detail. Set "item"
       * to the selected detail
       */
      showDetail: function(detailIndex) {
        console.log($stateParams.detail);
        if(detailIndex !== undefined) {
          $stateParams.detail = $scope.items[detailIndex].id;
        }
        $scope.detail = {
          likesCount: 0,
          commentsCount: 0
        }
        $mDaia.get('m-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/likes')
        .then(function(response) {
          $scope.detail.likesCount = response.total;
        });

        $mDaia.get('m-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/comments')
        .then(function(response) {
          $scope.detail.commentsCount = response.total;
        });

        // If the user is logged
        $mAuth.user.isLogged(function(isLogged) {
          if (isLogged) {
            var url = 'm-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/likes/search';
            var query = {
              query: {
                match: {
                  user: $mAuth.user.get().user.id
                }
              }
            };
            $mDaia.post(url, query).then(function(response) {
              if (response.total === 0) {
                $scope.detail.userLikedPhoto = false;
              } else {
                $scope.detail.userLikedPhoto = true;
                userLikeId = response.results[0]._id;
              }
            });
          }
        });
        if (isDefined($stateParams.detail) && $stateParams.detail !== "") {
          // $scope.imageH = calculatedImageHeight();
          var itemIndex = _.findIndex($scope.items, function(item) {
            return item.id.toString() === $stateParams.detail;
          });
          if (itemIndex === -1) {
            dataLoadOptions = {
              //offset: $scope.items === undefined ? 0 : $scope.items.length,
              items: 1000,
              cache: false
            };
            // Comentei o bloco abaixo para evitar um loop infinito de requisições
            // list.load(false, function() {
            //   list.showDetail();
            // });
          } else {
            $scope.detail = $scope.items[itemIndex];
            $scope.detail.index = itemIndex;
          }
        } else if (isDefined(detailIndex)) {
          $scope.detail = $scope.items[detailIndex];
          $scope.detail.index = detailIndex;
        }
      },
      /**
       * Load data from the Moblets backend:
       * - show the page loader if it's called by init (sets showLoader to true)
       * - Use $mDataLoader.load to get the moblet data from Moblets backend.
       * 	 The parameters passed to $mDataLoader.load are:
       * 	 - $scope.moblet - the moblet created in the init function
       * 	 - false - A boolean that sets if you want to load data from the
       * 	   device storage or from the Moblets API
       * 	 - dataLoadOptions - An object with parameters for pagination
       * @param  {boolean} showLoader Boolean to determine if the page loader
       * is active
       * @param {function} callback Callback
       */
      load: function(showLoader, callback) {
        if ($stateParams.detail === '') {
          $stateParams.pageTitle = null;
        }
        $scope.moblet.isLoading = showLoader || false;
        // Reset the pagination
        if (showLoader === true || showLoader === undefined) {
          dataLoadOptions.offset = 0;
        }
        // mDataLoader also saves the response in the local cache. It will be
        // used by the "showDetail" function
        $mDataLoader.load($scope.moblet, dataLoadOptions)
          .then(function(data) {
            list.setView(data);
            if (typeof callback === 'function') {
              callback();
            }
          }
        );
      },
      /**
       * Load more data from the backend if there are more items.
       * - Update the offset summing the number of items
       - Use $mDataLoader.load to get the moblet data from Moblets backend.
       * 	 The parameters passed to $mDataLoader.load are:
       * 	 - $scope.moblet - the moblet created in the init function
       * 	 - false - A boolean that sets if you want to load data from the
       * 	   device storage or from the Moblets API
       * 	 - dataLoadOptions - An object with parameters for pagination
       */
      more: function() {
        // Add the items to the offset

        dataLoadOptions.offset += dataLoadOptions.items;

        $mDataLoader.load($scope.moblet, dataLoadOptions)
          .then(function(data) {
            list.setView(data, true);
            $timeout(function() {}, 500);
          });

      },
      /**
       * Initiate the list moblet:
       * - put the list.load function in the $scope
       * - run list.load function
       */
      /*
       * TODO go to detail if url is called
       */
      init: function() {
        dataLoadOptions = {
          offset: 0,
          items: 25,
          listKey: 'items',
          cache: false
        };
        $scope.load(true);
        $scope.reload = function(){
          if($stateParams.detail !== ""){
            $scope.load();
          } else {
            $rootScope.$broadcast('scroll.refreshComplete');
            $rootScope.$broadcast('scroll.infiniteScrollComplete');
          }
        }
      }
    };

    var listItem = {

      next: function(detail) {
        if (detail.index !== -1 && detail.index < $scope.items.length - 1) {
          $scope.nextAnimation = true;
          $scope.nextDetail = $scope.items[detail.index + 1];
          $scope.nextDetail.index = detail.index + 1;
          $timeout(function() {
            //$stateParams.detail = $scope.items[$scope.detail.index].id;
            list.showDetail($scope.nextDetail.index);
            $scope.detail = $scope.nextDetail;
            $scope.nextAnimation = false;
          }, 500);
        }
      },
      prev: function(detail) {
        if (detail.index > 0) {
          $scope.prevAnimation = true;
          $scope.prevDetail = $scope.items[detail.index - 1];
          $scope.prevDetail.index = detail.index - 1;
          $timeout(function() {
            //$stateParams.detail = $scope.items[$scope.detail.index].id;
            console.log($stateParams.detail);
            list.showDetail($scope.prevDetail.index);
            $scope.detail = $scope.prevDetail;
            $scope.prevAnimation = false;
          }, 500);
        }
      },
      showPrev: function(detail) {
        if(isDefined(detail))
        {
          return detail.index > 0;
        } else {
          return false
        }
      },
      showNext: function(detail) {
         if(isDefined(detail))
        {
           return detail.index !== -1 && detail.index < $scope.items.length - 1;
        } else {
          return false
        }

      },
      getDetailImage: function(detail) {
        if(isDefined(detail)){
          return {
            "background-image": "url('" + detail.image + "')"
          };
        }
      },
      goTo: function(detail) {
        $stateParams.pageTitle = detail.title;
        $stateParams.detail = detail.id;
        $mState.go('u-moblets', 'page', {
          detail: detail.id
        });
      },
      likeOrUnlike: function() {
        $mAuth.user.isLogged(function(isLogged) {
          if (isLogged) {
            if ($scope.detail.userLikedPhoto) {
              var url = 'm-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/likes/' + userLikeId;
              $mDaia.remove(url)
              .then(function() {
                $scope.detail.userLikedPhoto = false;
                $scope.detail.likesCount -= 1;
              });
            } else {
              var url = 'm-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/likes';
              $mDaia.post(url, {
                body: {
                  user: true,
                  date: true
                }
              }).then(function() {
                $scope.detail.userLikedPhoto = true;
                if ($scope.detail.likesCount === undefined) {
                  $scope.detail.likesCount = 0;
                }
                $scope.detail.likesCount += 1;
              });
            }
          } else {
            $scope.commentsModal.hide();
            $mAuth.login();
          }
        });
      }
    };

    var modal = {
      created: function() {
        $ionicModal.fromTemplateUrl('malbum-zoom-modal.html', {
          scope: $scope,
          hardwareBackButtonClose:true,
          animation: 'scale-in'
        }).then(function(modal) {
          $scope.modal = modal;
          $scope.modal.hide();
        });

        $scope.openModal = function() {
          $scope.modal.show();
        };

        $scope.closeModal = function() {
          $scope.modal.hide();
          $timeout(function(){
            $ionicScrollDelegate.$getByHandle('m-album-zoom-scroll').zoomTo(1);
          }, 500);
        };

        $scope.destroyModal = function() {
          $scope.modal.remove();
        };
      }
    }

    var commentsModal = {
      created: function() {
        $ionicModal.fromTemplateUrl('malbum-comments-modal.html', {
          scope: $scope,
          hardwareBackButtonClose:true,
          animation: 'scale-in'
        }).then(function(modal) {
          $scope.commentsModal = modal;
          $scope.commentsModal.hide();
        });

        $scope.openCommentsModal = function() {
          $scope.malbumUserComment = "";
          $scope.commentsModal.show();
          $mDaia.get('m-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/comments', {
            profile: true
          }).then(function(res) {
            $scope.comments = res.results;
          });
        };

        $scope.closeCommentsModal = function() {
          $scope.commentsModal.hide();
        };

        $scope.destroyCommentsModal = function() {
          $scope.commentsModal.remove();
        };

        $scope.sendMessage = function() {
          $mAuth.user.isLogged(function(isLogged) {
            if (isLogged) {
              var comment = document.getElementById('albumCommentsInput').value;
              if (comment != '') {
                $mDaia.post('m-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/comments', {
                  body: {
                    user: true,
                    date: true,
                    comment: comment
                  }
                }).then(function(res) {
                  $mDaia.get('m-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/comments', {
                    profile: true
                  }).then(function(res) {
                    $scope.comments = res.results;
                  });
                  document.getElementById('albumCommentsInput').value = "";
                });
              }
            } else {
              $scope.commentsModal.hide();
              $mAuth.login();
            }
          });
        };

        $scope.openPopover = function($event , item){
          $scope.item = item;
          var template = fs.readFileSync(path.join(__dirname,
            'm-album-report.html'), 'utf8');
          $scope.popover = $ionicPopover.fromTemplate(template, {
            scope: $scope
          });
          $scope.popover.show($event);
        };

        $scope.report = function() {
          $scope.popover.hide();
          $mAlert.dialog($filter('translate')("report_title"),
            $filter('translate')("report_confirm"),
            [$filter('translate')("cancel_button"),
            $filter('translate')("report_button")])
            .then(function(success) {
              if (success) {
                var url = 'm-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/reports';
                $mDaia.post(url, {
                  body: {
                    user: true,
                    date: true,
                    commentId: $scope.item._id
                  }
                });
              }
            });
        };
      }
    }

    $scope.stripHtml = function(str) {
      return str.replace(/<[^>]+>/ig, " ");
    };

    function calculatedImageHeight() {
      console.log($element);

      var top = parseInt(window.getComputedStyle(document.querySelector(".pane[nav-view='active'] ion-content.scroll-content"))["top"]);
      var bottom = parseInt(window.getComputedStyle(document.querySelector(".pane[nav-view='active'] ion-content.scroll-content"))["bottom"]);
      var currentHeight = document.documentElement.clientHeight;
      var frame = currentHeight - top - bottom

      var descount = 5 * (100 / document.documentElement.clientWidth) + 90;
      return frame - descount + "px"
    }

    window.malbumImageLoaded = function(element) {
      element.parentElement.classList.add("loaded");
    }

    $scope.load = list.load;
    $scope.init = list.init;
    $scope.nextDetail = {};
    $scope.prevDetail = {};
    $scope.goTo = listItem.goTo;
    $scope.getDetailImage = listItem.getDetailImage;
    $scope.next = listItem.next;
    $scope.prev = listItem.prev;
    $scope.showNext = listItem.showNext;
    $scope.showPrev = listItem.showPrev;
    $scope.likeOrUnlike = listItem.likeOrUnlike;
    modal.created();
    commentsModal.created();

    $scope.$on('$stateChangeStart', $scope.destroyModal);
    $scope.$on('$destroy', $scope.destroyModal);
    $scope.$on('$stateChangeStart', $scope.destroyCommentsModal);
    $scope.$on('$destroy', $scope.destroyCommentsModal);

    list.init();
  }
};
<commit_msg>fix(m-album): comment modal after login<commit_after>/* eslint no-undef: [0]*/
module.exports = {
  title: "mAlbum",
  style: "m-album.less",
  template: 'm-album.html',
  i18n: {
    pt: "lang/pt-BR.json",
    en: "lang/en-US.json"
  },
  link: function() {},
  controller: function(
    $scope,
    $rootScope,
    $filter,
    $timeout,
    $mState,
    $stateParams,
    $mDataLoader,
    $element,
    $ionicModal,
    $ionicScrollDelegate,
    $mDaia,
    $mAuth,
    $ionicPopover,
    $mAlert
  ) {
    var dataLoadOptions;
    var userLikeId;
    var list = {
      /**
       * Set the view and update the needed parameters
       * @param  {object} data Data received from Moblets backend
       * @param  {boolean} more If called by "more" function, it will add the
       * data to the items array
       */
      setView: function(data, more) {
        if (isDefined(data)) {
          $scope.error = false;
          $scope.emptyData = false;

          // If it was called from the "more" function, concatenate the items
          $scope.items = (more) ? $scope.items.concat(data.items) : data.items;

          // Set "noContent" if the items lenght = 0
          $scope.moblet.noContent = $scope.items === undefined ||
            $scope.items.length === 0;

          // set empty itens if no content
          if ($scope.moblet.noContent) {
            $scope.items = [];
          }

          // Check if the page is loading the list or a detail
          $scope.isDetail = list.isDetail();

          // Disable the "more" function if the API don't have more items
          $scope.more = (data.hasMoreItems && !$scope.isDetail) ? list.more : undefined;
        } else {
          $scope.error = true;
          $scope.emptyData = true;
        }

        // Broadcast complete refresh and infinite scroll
        $rootScope.$broadcast('scroll.refreshComplete');
        $rootScope.$broadcast('scroll.infiniteScrollComplete');

        // If the view is showing the detail, call showDetail
        if ($scope.isDetail) {
          list.showDetail();
        }

        // Remove the loading animation
        $scope.moblet.isLoading = false;
      },
      /**
       * Check if the view is showing a detail or the list. The function checks
       * if $stateParams.detail is set.
       * @return {boolean} True if the view must show a detail.
       */
      isDetail: function() {
        return $stateParams.detail !== "";
      },
      /**
       * Show the detail getting the index from $stateParams.detail. Set "item"
       * to the selected detail
       */
      showDetail: function(detailIndex) {
        console.log($stateParams.detail);
        if(detailIndex !== undefined) {
          $stateParams.detail = $scope.items[detailIndex].id;
        }
        $scope.detail = {
          likesCount: 0,
          commentsCount: 0
        }
        $mDaia.get('m-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/likes')
        .then(function(response) {
          $scope.detail.likesCount = response.total;
        });

        $mDaia.get('m-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/comments')
        .then(function(response) {
          $scope.detail.commentsCount = response.total;
        });

        // If the user is logged
        $mAuth.user.isLogged(function(isLogged) {
          if (isLogged) {
            var url = 'm-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/likes/search';
            var query = {
              query: {
                match: {
                  user: $mAuth.user.get().user.id
                }
              }
            };
            $mDaia.post(url, query).then(function(response) {
              if (response.total === 0) {
                $scope.detail.userLikedPhoto = false;
              } else {
                $scope.detail.userLikedPhoto = true;
                userLikeId = response.results[0]._id;
              }
            });
          }
        });
        if (isDefined($stateParams.detail) && $stateParams.detail !== "") {
          // $scope.imageH = calculatedImageHeight();
          var itemIndex = _.findIndex($scope.items, function(item) {
            return item.id.toString() === $stateParams.detail;
          });
          if (itemIndex === -1) {
            dataLoadOptions = {
              //offset: $scope.items === undefined ? 0 : $scope.items.length,
              items: 1000,
              cache: false
            };
            // Comentei o bloco abaixo para evitar um loop infinito de requisições
            // list.load(false, function() {
            //   list.showDetail();
            // });
          } else {
            $scope.detail = $scope.items[itemIndex];
            $scope.detail.index = itemIndex;
          }
        } else if (isDefined(detailIndex)) {
          $scope.detail = $scope.items[detailIndex];
          $scope.detail.index = detailIndex;
        }
      },
      /**
       * Load data from the Moblets backend:
       * - show the page loader if it's called by init (sets showLoader to true)
       * - Use $mDataLoader.load to get the moblet data from Moblets backend.
       * 	 The parameters passed to $mDataLoader.load are:
       * 	 - $scope.moblet - the moblet created in the init function
       * 	 - false - A boolean that sets if you want to load data from the
       * 	   device storage or from the Moblets API
       * 	 - dataLoadOptions - An object with parameters for pagination
       * @param  {boolean} showLoader Boolean to determine if the page loader
       * is active
       * @param {function} callback Callback
       */
      load: function(showLoader, callback) {
        if ($stateParams.detail === '') {
          $stateParams.pageTitle = null;
        }
        $scope.moblet.isLoading = showLoader || false;
        // Reset the pagination
        if (showLoader === true || showLoader === undefined) {
          dataLoadOptions.offset = 0;
        }
        // mDataLoader also saves the response in the local cache. It will be
        // used by the "showDetail" function
        $mDataLoader.load($scope.moblet, dataLoadOptions)
          .then(function(data) {
            list.setView(data);
            if (typeof callback === 'function') {
              callback();
            }
          }
        );
      },
      /**
       * Load more data from the backend if there are more items.
       * - Update the offset summing the number of items
       - Use $mDataLoader.load to get the moblet data from Moblets backend.
       * 	 The parameters passed to $mDataLoader.load are:
       * 	 - $scope.moblet - the moblet created in the init function
       * 	 - false - A boolean that sets if you want to load data from the
       * 	   device storage or from the Moblets API
       * 	 - dataLoadOptions - An object with parameters for pagination
       */
      more: function() {
        // Add the items to the offset

        dataLoadOptions.offset += dataLoadOptions.items;

        $mDataLoader.load($scope.moblet, dataLoadOptions)
          .then(function(data) {
            list.setView(data, true);
            $timeout(function() {}, 500);
          });

      },
      /**
       * Initiate the list moblet:
       * - put the list.load function in the $scope
       * - run list.load function
       */
      /*
       * TODO go to detail if url is called
       */
      init: function() {
        dataLoadOptions = {
          offset: 0,
          items: 25,
          listKey: 'items',
          cache: false
        };
        $scope.load(true);
        $scope.reload = function(){
          if($stateParams.detail !== ""){
            $scope.load();
          } else {
            $rootScope.$broadcast('scroll.refreshComplete');
            $rootScope.$broadcast('scroll.infiniteScrollComplete');
          }
        }
      }
    };

    var listItem = {

      next: function(detail) {
        if (detail.index !== -1 && detail.index < $scope.items.length - 1) {
          $scope.nextAnimation = true;
          $scope.nextDetail = $scope.items[detail.index + 1];
          $scope.nextDetail.index = detail.index + 1;
          $timeout(function() {
            //$stateParams.detail = $scope.items[$scope.detail.index].id;
            list.showDetail($scope.nextDetail.index);
            $scope.detail = $scope.nextDetail;
            $scope.nextAnimation = false;
          }, 500);
        }
      },
      prev: function(detail) {
        if (detail.index > 0) {
          $scope.prevAnimation = true;
          $scope.prevDetail = $scope.items[detail.index - 1];
          $scope.prevDetail.index = detail.index - 1;
          $timeout(function() {
            //$stateParams.detail = $scope.items[$scope.detail.index].id;
            console.log($stateParams.detail);
            list.showDetail($scope.prevDetail.index);
            $scope.detail = $scope.prevDetail;
            $scope.prevAnimation = false;
          }, 500);
        }
      },
      showPrev: function(detail) {
        if(isDefined(detail))
        {
          return detail.index > 0;
        } else {
          return false
        }
      },
      showNext: function(detail) {
         if(isDefined(detail))
        {
           return detail.index !== -1 && detail.index < $scope.items.length - 1;
        } else {
          return false
        }

      },
      getDetailImage: function(detail) {
        if(isDefined(detail)){
          return {
            "background-image": "url('" + detail.image + "')"
          };
        }
      },
      goTo: function(detail) {
        $stateParams.pageTitle = detail.title;
        $stateParams.detail = detail.id;
        $mState.go('u-moblets', 'page', {
          detail: detail.id
        });
      },
      likeOrUnlike: function() {
        $mAuth.user.isLogged(function(isLogged) {
          if (isLogged) {
            if ($scope.detail.userLikedPhoto) {
              var url = 'm-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/likes/' + userLikeId;
              $mDaia.remove(url)
              .then(function() {
                $scope.detail.userLikedPhoto = false;
                $scope.detail.likesCount -= 1;
              });
            } else {
              var url = 'm-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/likes';
              $mDaia.post(url, {
                body: {
                  user: true,
                  date: true
                }
              }).then(function() {
                $scope.detail.userLikedPhoto = true;
                if ($scope.detail.likesCount === undefined) {
                  $scope.detail.likesCount = 0;
                }
                $scope.detail.likesCount += 1;
              });
            }
          } else {
            $scope.commentsModal.hide();
            $mAuth.login();
          }
        });
      }
    };

    var modal = {
      created: function() {
        $ionicModal.fromTemplateUrl('malbum-zoom-modal.html', {
          scope: $scope,
          hardwareBackButtonClose:true,
          animation: 'scale-in'
        }).then(function(modal) {
          $scope.modal = modal;
          $scope.modal.hide();
        });

        $scope.openModal = function() {
          $scope.modal.show();
        };

        $scope.closeModal = function() {
          $scope.modal.hide();
          $timeout(function(){
            $ionicScrollDelegate.$getByHandle('m-album-zoom-scroll').zoomTo(1);
          }, 500);
        };

        $scope.destroyModal = function() {
          $scope.modal.remove();
        };
      }
    }

    var commentsModal = {
      created: function() {
        $ionicModal.fromTemplateUrl('malbum-comments-modal.html', {
          scope: $scope,
          hardwareBackButtonClose:true,
          animation: 'scale-in'
        }).then(function(modal) {
          $scope.commentsModal = modal;
          $scope.commentsModal.hide();
        });

        $scope.openCommentsModal = function() {
          $scope.malbumUserComment = "";
          $scope.commentsModal.show();
          $mDaia.get('m-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/comments', {
            profile: true
          }).then(function(res) {
            $scope.comments = res.results;
          });
        };

        $scope.closeCommentsModal = function() {
          $scope.commentsModal.hide();
        };

        $scope.destroyCommentsModal = function() {
          $scope.commentsModal.remove();
        };

        $scope.sendMessage = function() {
          $mAuth.user.isLogged(function(isLogged) {
            if (isLogged) {
              var comment = document.getElementById('albumCommentsInput').value;
              if (comment != '') {
                $mDaia.post('m-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/comments', {
                  body: {
                    user: true,
                    date: true,
                    comment: comment
                  }
                }).then(function(res) {
                  $mDaia.get('m-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/comments', {
                    profile: true
                  }).then(function(res) {
                    $scope.comments = res.results;
                  });
                  document.getElementById('albumCommentsInput').value = "";
                });
              }
            } else {
              $scope.commentsModal.hide();
              $mAuth.login();
            }
          });
        };

        $scope.openPopover = function($event , item){
          $scope.item = item;
          var template = fs.readFileSync(path.join(__dirname,
            'm-album-report.html'), 'utf8');
          $scope.popover = $ionicPopover.fromTemplate(template, {
            scope: $scope
          });
          $scope.popover.show($event);
        };

        $scope.report = function() {
          $scope.popover.hide();
          $mAlert.dialog($filter('translate')("report_title"),
            $filter('translate')("report_confirm"),
            [$filter('translate')("cancel_button"),
            $filter('translate')("report_button")])
            .then(function(success) {
              if (success) {
                var url = 'm-album/' + $stateParams.pageId + '/' + $stateParams.detail + '/reports';
                $mDaia.post(url, {
                  body: {
                    user: true,
                    date: true,
                    commentId: $scope.item._id
                  }
                });
              }
            });
        };
      }
    }

    $scope.stripHtml = function(str) {
      return str.replace(/<[^>]+>/ig, " ");
    };

    function calculatedImageHeight() {
      console.log($element);

      var top = parseInt(window.getComputedStyle(document.querySelector(".pane[nav-view='active'] ion-content.scroll-content"))["top"]);
      var bottom = parseInt(window.getComputedStyle(document.querySelector(".pane[nav-view='active'] ion-content.scroll-content"))["bottom"]);
      var currentHeight = document.documentElement.clientHeight;
      var frame = currentHeight - top - bottom

      var descount = 5 * (100 / document.documentElement.clientWidth) + 90;
      return frame - descount + "px"
    }

    window.malbumImageLoaded = function(element) {
      element.parentElement.classList.add("loaded");
    }

    $scope.load = list.load;
    $scope.init = list.init;
    $scope.nextDetail = {};
    $scope.prevDetail = {};
    $scope.goTo = listItem.goTo;
    $scope.getDetailImage = listItem.getDetailImage;
    $scope.next = listItem.next;
    $scope.prev = listItem.prev;
    $scope.showNext = listItem.showNext;
    $scope.showPrev = listItem.showPrev;
    $scope.likeOrUnlike = listItem.likeOrUnlike;
    modal.created();
    commentsModal.created();

    $scope.$on('$stateChangeStart', $scope.destroyModal);
    $scope.$on('$destroy', $scope.destroyModal);

    list.init();
  }
};
<|endoftext|>


<commit_before>var express = require('express');
var _ = require('lodash');
var request = require('request');
var fs = require('fs');

var google = require('googleapis');
var googleAuth = require('google-auth-library');

var graph = require('fbgraph');

var slackWebClient = require('@slack/client').WebClient;

var authTokens = require(__base + 'secret/auth-tokens.json');
var authConf = {
    'facebook' : {
        'clientID' : authTokens.fbClientID, // also refer to as app-ID
        'clientSecret' : authTokens.fbClientSecret, // also refer to as app-secret
        'scope' : 'email, public_profile, user_friends, user_posts',
        'redirectUri' : 'https://lynxapp.me/api/auth/facebook'
    },
    'gmail' : {
        'clientID': authTokens.gmailClientID,
        'clientSecret' : authTokens.gmailClientSecret,
        'scope' : ['https://www.googleapis.com/auth/plus.me',
                   'https://www.googleapis.com/auth/gmail.modify'],
        'redirectUri' : 'https://lynxapp.me/api/auth/gmail'
    },
    'slack' : {
        'clientID' : authTokens.slackClientID,
        'clientSecret' : authTokens.slackClientSecret,
        'scope': 'channels%3Ahistory+channels%3Aread+im%3Aread+im%3Ahistory+mpim%3Aread+mpim%3Ahistory',
        'redirectUri' : 'https://lynxapp.me/api/auth/slack'
    }
};

var oauth2 = google.auth.OAuth2;
var oauth2Client = new oauth2(
    authConf.gmail.clientID,
    authConf.gmail.clientSecret,
    authConf.gmail.redirectUri
);

module.exports.Router = function () {
	var router = express.Router();

    /* Parses a string and returns an array of links if there are any. */
    var regParser = function(text) {
        // Resource: https://gist.github.com/dperini/729294
        // Might need to remove escape slashes
        console.log('The test is: ' + text);
        var re = new RegExp('^(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$');
        var words = text.replace(/[<>]/g,'').split(' ');
        console.log(words);
        var results = {};
        var url = 'https://info344api.enamarkovic.com/v1/summary?url=';
        for (var word in words) {
            // if it is a link, we will call the link summary API
            if (re.test(word)) {
                console.log("Yep! it's a link!");
                request(url + word, function (error, response, body) {
                    var JSONresponse = JSON.parse(body);
                    if (!error){
                        console.log(JSONresponse);
                    } else {
                        console.log(error);
                    }
                });
            }
        }
        return results;
    };

    // Facebook oauth: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow
    router.get('/facebook_oauth', function(req, res) {
        var oauthUrl = 'https://www.facebook.com/v2.9/dialog/oauth?client_id='
            + authConf.facebook.clientID
            + '&scope=' + authConf.facebook.scope
            + '&redirect_uri=' + authConf.facebook.redirectUri;
        res.redirect(oauthUrl);
    });

    router.get('/facebook', function(facebookReq, facebookRes) {
        // Exchanging an authorization code for an API access token
        var apiTokenUrl = 'https://graph.facebook.com/v2.9/oauth/access_token?client_id='
            + authConf.facebook.clientID
            + '&redirect_uri=' + authConf.facebook.redirectUri
            + '&client_secret=' + authConf.facebook.clientSecret
            + '&code=' + facebookReq.query.code;

        request(apiTokenUrl, function (err, res, body) {
            if (!err && res.statusCode == 200) {
                var info = JSON.parse(body);
                graph.setAccessToken(info.access_token);

                var fboptions = {
                    timeout:  3000
                    , pool:     { maxSockets:  Infinity }
                    , headers:  { connection:  "keep-alive" }
                };

                var reqParam = {
                    fields:"type,caption,description,link"
                };

                // Grab all the statuses on the feed.
                graph.setOptions(fboptions).get("/me/feed", reqParam, function(err, res) {
                    console.log(res);
                });

            } else {
                console.error('Facebook API call error: ' + err);
            }
        });

        // After we are done, redirect back to the main website.
        facebookRes.redirect('https://lynxapp.me');
    });

    // Facebook webhook: https://developers.facebook.com/docs/graph-api/webhooks
    router.post('/facebook_incoming', function(req, res) {
        // Facebook challenge. Saving just in case.
        // if (req.query['hub.mode'] === 'subscribe' && req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
        //     console.log("Validating webhook");
        //     res.status(200).send(req.query['hub.challenge']);
        // } else {
        //     console.error("Failed validation. Make sure the validation tokens match.");
        //     res.sendStatus(403);
        // }
        //
        // changes: [ { field: 'status',
        //              id: '44444444_444444444',
        //              value: 'This is an Example Status.' } ]
        console.log(req.body.entry[0].changes[0].value);
        res.status(200);

    });

    // Gmail Oauth: https://developers.google.com/identity/protocols/OAuth2WebServer
    router.get('/gmail_oauth', function(req, res) {
        /* var oauthUrl = 'https://accounts.google.com/o/oauth2/v2/auth?client_id='
        + authConf.gmail.clientID
        + '&redirect_uri' + authConf.gmail.redirectUri
        + '&response_type=code&scope=' + auth.gmail.scope;
        res.redirect(oauthUrl); */
        var oauthUrl = oauth2Client.generateAuthUrl({
            access_type: 'offline',
            scope: authConf.gmail.scope
        });
        res.redirect(oauthUrl);
    });

    router.get('/gmail', function(gmailReq, gmailRes) {
        console.log('in /api/auth/gmail');

        oauth2Client.getToken(gmailReq.query.code, function(err, tokens) {
            if (!err) {
                oauth2Client.setCredentials(tokens);
                var gmail = google.gmail('v1');

                gmail.users.messages.list({auth: oauth2Client, userId: 'me', maxResults: 100}, function(listErr, listRes) {
                    if (listErr) {
                        console.log('The list messages API call returned an error: ' + listErr);
                        return;
                    } else {
                        var emailIDs = listRes.messages;
                        for (var i in emailIDs) {
                            gmail.users.messages.get({auth: auth2Client, id: emailIDs[i],userId: 'me'}, function(getErr, getResponse) {
                                if (getErr) {
                                    console.log('The get messages API call returned an error for email with ID: ' + emailIDs[i]);
                                } else {
                                    console.log(getResponse);
                                }
                            });
                        }
                    }
                });
            } else {
                console.log('Getting the API token returned an error: ' + err);
            }
        });

        // request(apiTokenUrl, function (err, res, body) {
        //     if (!err && res.statusCode == 200) {
        //         var info = JSON.parse(body);
        //         graph.setAccessToken(info.access_token);
        //
        //         var fboptions = {
        //             timeout:  3000
        //             , pool:     { maxSockets:  Infinity }
        //             , headers:  { connection:  "keep-alive" }
        //         };
        //
        //         var reqParam = {
        //             fields:"type,caption,description,link"
        //         };
        //
        //         graph.setOptions(fboptions).get("/me/feed", reqParam, function(err, res) {
        //             console.log(res);
        //         });
        //
        //     } else {
        //         console.error('Facebook API call error: ' + err);
        //     }
        // });
        // facebookRes.redirect('https://lynxapp.me');
    });

    // Slack Oauth: https://api.slack.com/docs/oauth
    router.get('/slack_oauth', function (req, res, next) {
        var oauthUrl = 'https://slack.com/oauth/authorize?client_id='
            + authConf.slack.clientID
            + '&scope=' + authConf.slack.scope
            + '&redirect_uri=' + authConf.slack.redirectUri;
        res.redirect(oauthUrl);
    });

    router.get('/slack', function(slackReq, slackRes) {
        console.log("in /api/auth/slack");

        var apiTokenUrl = 'https://slack.com/api/oauth.access?client_id='
            + authConf.slack.clientID
            + '&client_secret=' + authConf.slack.clientSecret
            + '&code=' + slackReq.query.code
            + '&redirect_uri=' + authConf.slack.redirectUri;

        request(apiTokenUrl, function (err, res, body) {
            console.log("getting access token");
            if (!err && res.statusCode == 200) {
                var info = JSON.parse(body);
                authConf.slack.accessToken = info.access_token;
                var slackWeb = new slackWebClient(authConf.slack.accessToken);

                var channelIDs = [];

                // all public channels
                slackWeb.channels.list(function(channelListErr, channelListInfo) {
                    if (channelListErr || !channelListInfo.ok) {
                        console.error('Error: Unable to retrieve public channel list.');
                    } else {
                        for (var i in channelListInfo.channels) {
                            slackWeb.channels.history(channelListInfo.channels[i].id, function(channelHistErr, channelHistInfo) {
                                if (channelHistErr || !channelHistInfo.ok) {
                                    console.error('Error: Unable to retrieve messages for channel with ID: ' + channelListInfo.channels[i].id);
                                } else {
                                    console.log(channelHistInfo.messages);
                                }
                            });
                        }
                    }
                });

                // all direct messages
                slackWeb.im.list(function(imListErr, imListInfo) {
                    if (imListErr || !imListInfo.ok) {
                        console.error('Error: Unable to retrieve direct message list.');
                    } else {
                        for (var i in imListInfo.ims) {
                            slackWeb.im.history(imListInfo.ims[i].id, function(imHistErr, imHistInfo) {
                                if (imHistErr || !imHistInfo.ok) {
                                    console.error('Error: Unable to retrieve messages for direct message with ID: ' + imListInfo.ims[i].id);
                                } else {
                                    console.log(imHistInfo.messages);
                                }
                            });
                        }
                    }

                });

                // all group direct messages
                slackWeb.mpim.list(function(mpimListErr, mpimListInfo) {
                    if (mpimListErr || !mpimListInfo.ok) {
                        console.error('Error: Unable to retrieve group direct message list.');
                    } else {
                        for (var i in mpimListInfo.groups) {
                            slackWeb.mpim.history(mpimListInfo.groups[i].id, function(mpimHistErr, mpimHistInfo) {
                                if (mpimHistErr || !mpimHistInfo.ok) {
                                    console.error('Error: Unable to retrieve messages for group direct message with ID: ' + mpimHistInfo.groups[i].id);
                                } else {
                                    console.log(mpimHistInfo.messages);
                                }
                            });
                        }
                    }
                });
            } else {
                console.error('Slack API call error: ' + err);
            }
        });
        // When we are done, redirects back the main page
        slackRes.redirect('https://lynxapp.me');
    });

    router.post('/slack_incoming', function(req, res) {
        // This is used to respond to slack challenges. Saved in case
        // the verification expires in the future.
        // res.type('html');
        // res.status(200).send(req.body.challenge);
        //
        //   event:
        //          { type: 'message',
        //            user: 'U50SS1PLJ',
        //            text: 'denver',
        //            ts: '1495684015.632873',
        //            channel: 'D51MCEQ1M',
        //            event_ts: '1495684015.632873' },
        res.status(200);
        console.log('The test is: ' + req.body.event.text);
        return regParser(req.body.event.text);

    });

	return router;
};
<commit_msg>fix webhook response logic<commit_after>var express = require('express');
var _ = require('lodash');
var request = require('request');
var fs = require('fs');

var google = require('googleapis');
var googleAuth = require('google-auth-library');

var graph = require('fbgraph');

var slackWebClient = require('@slack/client').WebClient;

var authTokens = require(__base + 'secret/auth-tokens.json');
var authConf = {
    'facebook' : {
        'clientID' : authTokens.fbClientID, // also refer to as app-ID
        'clientSecret' : authTokens.fbClientSecret, // also refer to as app-secret
        'scope' : 'email, public_profile, user_friends, user_posts',
        'redirectUri' : 'https://lynxapp.me/api/auth/facebook'
    },
    'gmail' : {
        'clientID': authTokens.gmailClientID,
        'clientSecret' : authTokens.gmailClientSecret,
        'scope' : ['https://www.googleapis.com/auth/plus.me',
                   'https://www.googleapis.com/auth/gmail.modify'],
        'redirectUri' : 'https://lynxapp.me/api/auth/gmail'
    },
    'slack' : {
        'clientID' : authTokens.slackClientID,
        'clientSecret' : authTokens.slackClientSecret,
        'scope': 'channels%3Ahistory+channels%3Aread+im%3Aread+im%3Ahistory+mpim%3Aread+mpim%3Ahistory',
        'redirectUri' : 'https://lynxapp.me/api/auth/slack'
    }
};

var oauth2 = google.auth.OAuth2;
var oauth2Client = new oauth2(
    authConf.gmail.clientID,
    authConf.gmail.clientSecret,
    authConf.gmail.redirectUri
);

module.exports.Router = function () {
	var router = express.Router();

    /* Parses a string and returns an array of links if there are any. */
    function regParser(text) {
        // Resource: https://gist.github.com/dperini/729294
        // Might need to remove escape slashes
        if (text) {
            console.log('The test is: ' + text);
            var re = new RegExp('^(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$');
            var words = text.replace(/[<>]/g,'').split(' ');
            console.log(words);
            var results = {};
            var url = 'https://info344api.enamarkovic.com/v1/summary?url=';
            for (var word in words) {
                // if it is a link, we will call the link summary API
                if (re.test(word)) {
                    console.log("Yep! it's a link!");
                    request(url + word, function (error, response, body) {
                        var JSONresponse = JSON.parse(body);
                        if (!error){
                            console.log(JSONresponse);
                        } else {
                            console.log(error);
                        }
                    });
                }
            }
            return results;
        }
    }

    // Facebook oauth: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow
    router.get('/facebook_oauth', function(req, res) {
        var oauthUrl = 'https://www.facebook.com/v2.9/dialog/oauth?client_id='
            + authConf.facebook.clientID
            + '&scope=' + authConf.facebook.scope
            + '&redirect_uri=' + authConf.facebook.redirectUri;
        res.redirect(oauthUrl);
    });

    router.get('/facebook', function(facebookReq, facebookRes) {
        // Exchanging an authorization code for an API access token
        var apiTokenUrl = 'https://graph.facebook.com/v2.9/oauth/access_token?client_id='
            + authConf.facebook.clientID
            + '&redirect_uri=' + authConf.facebook.redirectUri
            + '&client_secret=' + authConf.facebook.clientSecret
            + '&code=' + facebookReq.query.code;

        request(apiTokenUrl, function (err, res, body) {
            if (!err && res.statusCode == 200) {
                var info = JSON.parse(body);
                graph.setAccessToken(info.access_token);

                var fboptions = {
                    timeout:  3000
                    , pool:     { maxSockets:  Infinity }
                    , headers:  { connection:  "keep-alive" }
                };

                var reqParam = {
                    fields:"type,caption,description,link"
                };

                // Grab all the statuses on the feed.
                graph.setOptions(fboptions).get("/me/feed", reqParam, function(err, res) {
                    console.log(res);
                });

            } else {
                console.error('Facebook API call error: ' + err);
            }
        });

        // After we are done, redirect back to the main website.
        facebookRes.redirect('https://lynxapp.me');
    });

    // Facebook webhook: https://developers.facebook.com/docs/graph-api/webhooks
    router.post('/facebook_incoming', function(req, res) {
        // Facebook challenge. Saving just in case.
        // if (req.query['hub.mode'] === 'subscribe' && req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
        //     console.log("Validating webhook");
        //     res.status(200).send(req.query['hub.challenge']);
        // } else {
        //     console.error("Failed validation. Make sure the validation tokens match.");
        //     res.sendStatus(403);
        // }
        //
        // changes: [ { field: 'status',
        //              id: '44444444_444444444',
        //              value: 'This is an Example Status.' } ]
        console.log(req.body.entry[0].changes[0].value);
        res.status(200);

    });

    // Gmail Oauth: https://developers.google.com/identity/protocols/OAuth2WebServer
    router.get('/gmail_oauth', function(req, res) {
        /* var oauthUrl = 'https://accounts.google.com/o/oauth2/v2/auth?client_id='
        + authConf.gmail.clientID
        + '&redirect_uri' + authConf.gmail.redirectUri
        + '&response_type=code&scope=' + auth.gmail.scope;
        res.redirect(oauthUrl); */
        var oauthUrl = oauth2Client.generateAuthUrl({
            access_type: 'offline',
            scope: authConf.gmail.scope
        });
        res.redirect(oauthUrl);
    });

    router.get('/gmail', function(gmailReq, gmailRes) {
        console.log('in /api/auth/gmail');

        oauth2Client.getToken(gmailReq.query.code, function(err, tokens) {
            if (!err) {
                oauth2Client.setCredentials(tokens);
                var gmail = google.gmail('v1');

                gmail.users.messages.list({auth: oauth2Client, userId: 'me', maxResults: 100}, function(listErr, listRes) {
                    if (listErr) {
                        console.log('The list messages API call returned an error: ' + listErr);
                        return;
                    } else {
                        var emailIDs = listRes.messages;
                        for (var i in emailIDs) {
                            gmail.users.messages.get({auth: auth2Client, id: emailIDs[i],userId: 'me'}, function(getErr, getResponse) {
                                if (getErr) {
                                    console.log('The get messages API call returned an error for email with ID: ' + emailIDs[i]);
                                } else {
                                    console.log(getResponse);
                                }
                            });
                        }
                    }
                });
            } else {
                console.log('Getting the API token returned an error: ' + err);
            }
        });

        // request(apiTokenUrl, function (err, res, body) {
        //     if (!err && res.statusCode == 200) {
        //         var info = JSON.parse(body);
        //         graph.setAccessToken(info.access_token);
        //
        //         var fboptions = {
        //             timeout:  3000
        //             , pool:     { maxSockets:  Infinity }
        //             , headers:  { connection:  "keep-alive" }
        //         };
        //
        //         var reqParam = {
        //             fields:"type,caption,description,link"
        //         };
        //
        //         graph.setOptions(fboptions).get("/me/feed", reqParam, function(err, res) {
        //             console.log(res);
        //         });
        //
        //     } else {
        //         console.error('Facebook API call error: ' + err);
        //     }
        // });
        // facebookRes.redirect('https://lynxapp.me');
    });

    // Slack Oauth: https://api.slack.com/docs/oauth
    router.get('/slack_oauth', function (req, res, next) {
        var oauthUrl = 'https://slack.com/oauth/authorize?client_id='
            + authConf.slack.clientID
            + '&scope=' + authConf.slack.scope
            + '&redirect_uri=' + authConf.slack.redirectUri;
        res.redirect(oauthUrl);
    });

    router.get('/slack', function(slackReq, slackRes) {
        console.log("in /api/auth/slack");

        var apiTokenUrl = 'https://slack.com/api/oauth.access?client_id='
            + authConf.slack.clientID
            + '&client_secret=' + authConf.slack.clientSecret
            + '&code=' + slackReq.query.code
            + '&redirect_uri=' + authConf.slack.redirectUri;

        request(apiTokenUrl, function (err, res, body) {
            console.log("getting access token");
            if (!err && res.statusCode == 200) {
                var info = JSON.parse(body);
                authConf.slack.accessToken = info.access_token;
                var slackWeb = new slackWebClient(authConf.slack.accessToken);

                var channelIDs = [];

                // all public channels
                slackWeb.channels.list(function(channelListErr, channelListInfo) {
                    if (channelListErr || !channelListInfo.ok) {
                        console.error('Error: Unable to retrieve public channel list.');
                    } else {
                        for (var i in channelListInfo.channels) {
                            slackWeb.channels.history(channelListInfo.channels[i].id, function(channelHistErr, channelHistInfo) {
                                if (channelHistErr || !channelHistInfo.ok) {
                                    console.error('Error: Unable to retrieve messages for channel with ID: ' + channelListInfo.channels[i].id);
                                } else {
                                    console.log(channelHistInfo.messages);
                                }
                            });
                        }
                    }
                });

                // all direct messages
                slackWeb.im.list(function(imListErr, imListInfo) {
                    if (imListErr || !imListInfo.ok) {
                        console.error('Error: Unable to retrieve direct message list.');
                    } else {
                        for (var i in imListInfo.ims) {
                            slackWeb.im.history(imListInfo.ims[i].id, function(imHistErr, imHistInfo) {
                                if (imHistErr || !imHistInfo.ok) {
                                    console.error('Error: Unable to retrieve messages for direct message with ID: ' + imListInfo.ims[i].id);
                                } else {
                                    console.log(imHistInfo.messages);
                                }
                            });
                        }
                    }

                });

                // all group direct messages
                slackWeb.mpim.list(function(mpimListErr, mpimListInfo) {
                    if (mpimListErr || !mpimListInfo.ok) {
                        console.error('Error: Unable to retrieve group direct message list.');
                    } else {
                        for (var i in mpimListInfo.groups) {
                            slackWeb.mpim.history(mpimListInfo.groups[i].id, function(mpimHistErr, mpimHistInfo) {
                                if (mpimHistErr || !mpimHistInfo.ok) {
                                    console.error('Error: Unable to retrieve messages for group direct message with ID: ' + mpimHistInfo.groups[i].id);
                                } else {
                                    console.log(mpimHistInfo.messages);
                                }
                            });
                        }
                    }
                });
            } else {
                console.error('Slack API call error: ' + err);
            }
        });
        // When we are done, redirects back the main page
        slackRes.redirect('https://lynxapp.me');
    });

    router.post('/slack_incoming', function(req, res) {
        // This is used to respond to slack challenges. Saved in case
        // the verification expires in the future.
        // res.type('html');
        // res.status(200).send(req.body.challenge);
        //
        //   event:
        //          { type: 'message',
        //            user: 'U50SS1PLJ',
        //            text: 'denver',
        //            ts: '1495684015.632873',
        //            channel: 'D51MCEQ1M',
        //            event_ts: '1495684015.632873' },

        if (req.body.event.text) {
            res.status(200).send(regParser(req.body.event.text));
        } else {
            res.status(200).send("non-text event");
        }
    });

	return router;
};
<|endoftext|>


<commit_before>import HttpResponseHandler from "../../common/src/HttpResponseHandler";
import ApplicationConfig from "./config/ApplicationConfig";
import { userDetails } from "./Factory";
import NodeErrorHandler from "./NodeErrorHandler";
import Logger, { logCategories } from "./logging/Logger";
import request from "request";

export default class CouchClient {
    static instance(accessToken, dbName, dbUrl = null) {
        return new CouchClient(accessToken, dbName, dbUrl);
    }

    async getUserName() {
        const response = await this.get("/_session");
        return response.userCtx.name;
    }

    static logger() {
        return Logger.instance(logCategories.DATABASE);
    }

    constructor(accessToken, dbName, dbUrl) {
        this.accessToken = accessToken;
        this.dbUrl = dbUrl || ApplicationConfig.instance().dbUrl();
        if(dbName) {
            this.dbName = dbName;
        } else if(accessToken) {
            const userInfo = userDetails.getUser(accessToken);
            if(userInfo) {
                this.dbName = userInfo.dbName;
            }
        }
    }

    static async createInstance(accessToken) {
        let instance = CouchClient.getDbInstance(accessToken);
        if (!instance) {
            instance = new CouchClient(null, accessToken);
            instance.dbName = await instance.getUserDbName();
        }
        return instance;
    }

    saveDocument(documentId, documentObj, customHeaders = {}) {
        const path = "/" + this.dbName + "/" + documentId;
        return this.put(path, documentObj, customHeaders);
    }

    saveBulkDocuments(body, customHeaders = {}) {
        const path = "/" + this.dbName + "/_bulk_docs";
        return this.post(path, body, customHeaders);
    }

    deleteBulkDocuments(docs) {
        const docsToDelete = docs.map(doc => {
            doc._deleted = true;
            return doc;
        });
        return this.saveBulkDocuments({ "docs": docsToDelete });
    }

    getDocument(documentId, customHeaders = {}) {
        const path = "/" + this.dbName + "/" + documentId;
        return this.get(path, {}, customHeaders);
    }

    async deleteDocument(documentId, revision) {
        let rev = revision;
        if(!rev) {
            const doc = await this.getDocument(documentId);
            rev = doc._rev;
        }
        const url = `${this.dbUrl}/${this.dbName}/${documentId}?rev=${rev}`;
        return new Promise((resolve, reject) => {
            request.delete({
                "uri": url,
                "headers": this._headers({}),
                "json": true
            }, (error, response) => {
                this.handleResponse(error, response, resolve, reject);
            });
        });
    }

    async findDocuments(query, customHeaders = {}) {
        const path = "/" + this.dbName + "/_find";
        return await this.post(path, query, customHeaders);
    }

    createIndex(indexDoc, customHeaders = {}) {
        const path = "/" + this.dbName + "/_index";
        return this.post(path, indexDoc, customHeaders);
    }

    updateDocument(documentObj, customHeaders = {}) {
        const path = "/" + this.dbName;
        return this.post(path, documentObj, customHeaders);
    }

    post(path, body, customHeaders = {}) {
        return new Promise((resolve, reject) => {
            request.post({
                "uri": this.dbUrl + path,
                "headers": this._headers(customHeaders),
                "body": body,
                "json": true
            }, (error, response) => {
                this.handleResponse(error, response, resolve, reject);
            });
        });
    }

    put(path, body, customHeaders = {}) {
        return new Promise((resolve, reject) => {
            request.put({
                "uri": this.dbUrl + path,
                "headers": this._headers(customHeaders),
                "body": body || {},
                "json": true
            }, (error, response) => {
                this.handleResponse(error, response, resolve, reject);
            });
        });
    }

    get(path, data = {}, customHeaders = {}) {
        return new Promise((resolve, reject) => {
            request.get({
                "uri": this.dbUrl + path,
                "headers": this._headers(customHeaders),
                "data": data,
                "json": true
            }, (error, response) => {
                this.handleResponse(error, response, resolve, reject);
            });
        });
    }

    handleResponse(error, response, resolve, reject) {
        if (NodeErrorHandler.noError(error)) {
            if (new HttpResponseHandler(response.statusCode).success()) {
                CouchClient.logger().debug("CouchClient:: successful response from database.");
                resolve(response.body);
            } else {
                CouchClient.logger().debug(`unexpected response from the db with status ${response.statusCode} and Error: ${JSON.stringify(response.body)}`);
                reject({ "status": response.statusCode, "message": response.body });
            }
        } else {
            CouchClient.logger().debug(`Error from database. Error: ${JSON.stringify(error)}`);
            reject(error);
        }
    }

    static getAllDbs() {
        return new Promise((resolve, reject) => {
            request.get({
                "uri": ApplicationConfig.instance().dbUrl() + "/_all_dbs"
            },
            (error, response) => {
                if (NodeErrorHandler.noError(error)) {
                    if (response.statusCode === HttpResponseHandler.codes.OK) {
                        const userDbs = JSON.parse(response.body).filter(dbName => dbName !== "_replicator" && dbName !== "_users");
                        CouchClient.logger().debug("CouchClient:: successful response from database.");
                        resolve(userDbs);
                    } else {
                        CouchClient.logger().debug("unexpected response from the db with status %s.", response.statusCode);
                        reject("unexpected response from the db");
                    }
                } else {
                    CouchClient.logger().debug("Error from database. Error: %s", error);
                    reject(error);
                }
            });
        });
    }

    _headers(customHeaders) {
        const defaultHeaders = {
            "Cookie": "AuthSession=" + this.accessToken,
            "Content-Type": "application/json",
            "Accept": "application/json"
        };

        return Object.assign({}, defaultHeaders, customHeaders);
    }
}
<commit_msg>Log warning in findDocuments<commit_after>import HttpResponseHandler from "../../common/src/HttpResponseHandler";
import ApplicationConfig from "./config/ApplicationConfig";
import {userDetails} from "./Factory";
import NodeErrorHandler from "./NodeErrorHandler";
import Logger, {logCategories} from "./logging/Logger";
import request from "request";

export default class CouchClient {
    static instance(accessToken, dbName, dbUrl = null) {
        return new CouchClient(accessToken, dbName, dbUrl);
    }

    async getUserName() {
        const response = await this.get("/_session");
        return response.userCtx.name;
    }

    static logger() {
        return Logger.instance(logCategories.DATABASE);
    }

    constructor(accessToken, dbName, dbUrl) {
        this.accessToken = accessToken;
        this.dbUrl = dbUrl || ApplicationConfig.instance().dbUrl();
        if (dbName) {
            this.dbName = dbName;
        } else if (accessToken) {
            const userInfo = userDetails.getUser(accessToken);
            if (userInfo) {
                this.dbName = userInfo.dbName;
            }
        }
    }

    static async createInstance(accessToken) {
        let instance = CouchClient.getDbInstance(accessToken);
        if (!instance) {
            instance = new CouchClient(null, accessToken);
            instance.dbName = await instance.getUserDbName();
        }
        return instance;
    }

    saveDocument(documentId, documentObj, customHeaders = {}) {
        const path = "/" + this.dbName + "/" + documentId;
        return this.put(path, documentObj, customHeaders);
    }

    saveBulkDocuments(body, customHeaders = {}) {
        const path = "/" + this.dbName + "/_bulk_docs";
        return this.post(path, body, customHeaders);
    }

    deleteBulkDocuments(docs) {
        const docsToDelete = docs.map(doc => {
            doc._deleted = true;
            return doc;
        });
        return this.saveBulkDocuments({"docs": docsToDelete});
    }

    getDocument(documentId, customHeaders = {}) {
        const path = "/" + this.dbName + "/" + documentId;
        return this.get(path, {}, customHeaders);
    }

    async deleteDocument(documentId, revision) {
        let rev = revision;
        if (!rev) {
            const doc = await this.getDocument(documentId);
            rev = doc._rev;
        }
        const url = `${this.dbUrl}/${this.dbName}/${documentId}?rev=${rev}`;
        return new Promise((resolve, reject) => {
            request.delete({
                "uri": url,
                "headers": this._headers({}),
                "json": true
            }, (error, response) => {
                this.handleResponse(error, response, resolve, reject);
            });
        });
    }

    async findDocuments(query, customHeaders = {}) {
        const path = "/" + this.dbName + "/_find";
        const response = await this.post(path, query, customHeaders);
        if (response.warning) {
            CouchClient.logger().debug("CouchClient:: " + response.warning);
        }
        return response;

    }

    createIndex(indexDoc, customHeaders = {}) {
        const path = "/" + this.dbName + "/_index";
        return this.post(path, indexDoc, customHeaders);
    }

    updateDocument(documentObj, customHeaders = {}) {
        const path = "/" + this.dbName;
        return this.post(path, documentObj, customHeaders);
    }

    post(path, body, customHeaders = {}) {
        return new Promise((resolve, reject) => {
            request.post({
                "uri": this.dbUrl + path,
                "headers": this._headers(customHeaders),
                "body": body,
                "json": true
            }, (error, response) => {
                this.handleResponse(error, response, resolve, reject);
            });
        });
    }

    put(path, body, customHeaders = {}) {
        return new Promise((resolve, reject) => {
            request.put({
                "uri": this.dbUrl + path,
                "headers": this._headers(customHeaders),
                "body": body || {},
                "json": true
            }, (error, response) => {
                this.handleResponse(error, response, resolve, reject);
            });
        });
    }

    get(path, data = {}, customHeaders = {}) {
        return new Promise((resolve, reject) => {
            request.get({
                "uri": this.dbUrl + path,
                "headers": this._headers(customHeaders),
                "data": data,
                "json": true
            }, (error, response) => {
                this.handleResponse(error, response, resolve, reject);
            });
        });
    }

    handleResponse(error, response, resolve, reject) {
        if (NodeErrorHandler.noError(error)) {
            if (new HttpResponseHandler(response.statusCode).success()) {
                CouchClient.logger().debug("CouchClient:: successful response from database.");
                resolve(response.body);
            } else {
                CouchClient.logger().debug(`unexpected response from the db with status ${response.statusCode} and Error: ${JSON.stringify(response.body)}`);
                reject({"status": response.statusCode, "message": response.body});
            }
        } else {
            CouchClient.logger().debug(`Error from database. Error: ${JSON.stringify(error)}`);
            reject(error);
        }
    }

    static getAllDbs() {
        return new Promise((resolve, reject) => {
            request.get({
                    "uri": ApplicationConfig.instance().dbUrl() + "/_all_dbs"
                },
                (error, response) => {
                    if (NodeErrorHandler.noError(error)) {
                        if (response.statusCode === HttpResponseHandler.codes.OK) {
                            const userDbs = JSON.parse(response.body).filter(dbName => dbName !== "_replicator" && dbName !== "_users");
                            CouchClient.logger().debug("CouchClient:: successful response from database.");
                            resolve(userDbs);
                        } else {
                            CouchClient.logger().debug("unexpected response from the db with status %s.", response.statusCode);
                            reject("unexpected response from the db");
                        }
                    } else {
                        CouchClient.logger().debug("Error from database. Error: %s", error);
                        reject(error);
                    }
                });
        });
    }

    _headers(customHeaders) {
        const defaultHeaders = {
            "Cookie": "AuthSession=" + this.accessToken,
            "Content-Type": "application/json",
            "Accept": "application/json"
        };

        return Object.assign({}, defaultHeaders, customHeaders);
    }
}
<|endoftext|>


<commit_before>let React = require("react"),
  Router = require("react-router"),
  Link = Router.Link,
  {AbstractShot} = require("../../../shared/dist/shot.js");

class Snippet extends React.Component {
  onClickComment(e) {
    e.preventDefault();
    let node = React.findDOMNode(this.refs.commentHolder),
      img = React.findDOMNode(this.refs.commentBubble);

    if (node.style.display === "none") {
      node.style.display = "inline-block";
    } else {
      node.style.display = "none";
    }
    console.log("img.src", img.src);
    if (img.src.indexOf("/img/comment-bubble-open.png") !== -1) {
      img.src = this.props.linkify("/img/comment-bubble.png");
    } else {
      img.src = this.props.linkify("/img/comment-bubble-open.png");
    }
  }

  render() {
    let clip = this.props.clip,
      node = null,
      comments_nodes = [];

    if (clip.image === undefined) {
      node =

;
    } else {
      node = ;
    }

    let comments = clip.comments,
      closed = false;
    if (comments.length === 0) {
      comments = [{text: "No comments."}];
      closed = true;
    }

    for (let i = 0, l = comments.length; i < l; i++) {
      let c = comments[i];
      // FIXME add the username once implemented
      //           { c.user }
      comments_nodes.push(
        <div
          key={ `comment.${i}` }
          className="comment">
          { c.text }

      );
    }

    return

      <Link to="shot" params={{shotId: this.props.shotId, shotDomain: this.props.shotDomain}} query={{clip: clip.id}}>
        { node }
      </Link>

        <Link to="shot" params={{shotId: this.props.shotId, shotDomain: this.props.shotDomain}} query={{clip: clip.id}}>
          See in full page
        </Link>

        { comments_nodes }

;
  }
}

// FIXME: I can't convert this to an es6 class because I get an exception related
// to the way this class uses contextTypes, even though I am doing what
// google searches appear to indicate is the right thing:
// export class Frame extends React.Component {
//   ...
// }
// Frame.contextTypes = {
//    router: React.PropTypes.func
// }

exports.Frame = React.createClass({
  contextTypes: {
    router: React.PropTypes.func
  },
  render: function () {
    if (this.props.data === null) {
      return
Not Found
;
    }

    let shot = new AbstractShot(this.props.backend, this.props.id, this.props.shot),
      params = this.context.router.getCurrentParams(),
      query = this.context.router.getCurrentQuery(),
      shotId = params.shotId,
      shotDomain = params.shotDomain;

    let favicon = "";
    if (shot.favicon) {
      favicon = <link rel="shortcut icon" href={shot.favicon} />;
    }

    let snippets = [],
      clipNames = shot.clipNames(),
      previousClip = null,
      nextClip = null;

    for (let i = 0; i < clipNames.length; i++) {
      let name = clipNames[i],
        clip = shot.getClip(name);

      snippets.push(<Snippet key={ name } clip={ clip } linkify={ this.props.linkify } shotId={ shotId } shotDomain={ shotDomain } previousClip={ previousClip } nextClip={ nextClip } />);

      if (query.clip === name) {
        if (typeof window !== "undefined") {
          let frame = document.getElementById("frame"),
            showElement = null,
            location = null;

          if (clip.image !== undefined) {
            showElement = clip.image.location.topLeftElement.slice(1);
            location = clip.image.location;
          } else {
            showElement = clip.text.location.selectionStart;
            location = clip.text.location;
          }

          if (showElement) {
            function cb() {
              frame.contentWindow.postMessage({
                show: showElement,
                location: location
              }, window.location.origin);
            }
            if (frame.contentDocument.readyState === "complete") {
              cb()
            } else {
              frame.contentWindow.onload = cb;
            }
          }
        }

        if (i > 0) {
          previousClip = clipNames[i - 1];
        }
        if (i < clipNames.length) {
          nextClip = clipNames[i + 1];
        }
      }
    }

    let previousClipNode = "",
      nextClipNode = "";

    if (previousClip) {
      previousClipNode = <Link to="shot" params={{shotId: shotId, shotDomain: shotDomain}} query={{clip: previousClip}}>

      </Link>;
    }

    if (nextClip || query.clip === undefined) {
      nextClipNode = <Link to="shot" params={{shotId: shotId, shotDomain: shotDomain}} query={{clip: nextClip || clipNames[0]}}>

      </Link>;
    }

    let numberOfClips = clipNames.length;
    if (numberOfClips === 1) {
      numberOfClips = "1 clip";
    } else if (numberOfClips === 0) {
      numberOfClips = "No clips";
    } else {
      numberOfClips = numberOfClips + " clips";
    }

    let linkTextShort = "";
    if (shot.url) {
      let txt = shot.url;
      if (txt.length > 50) {
        txt = txt.slice(0, 50) + '...';
      }
      linkTextShort = txt;
    }

    return