Name

x_snc_pointsthing.PointsThing

Description

No description available

Script

var PointsThing = Class.create();
PointsThing.prototype = {
  initialize: function() {
      this.token = gs.getProperty("pointsthing.token");
  },

  establish_user: function(payload_user, increment_point, set_points) {
      var userSysID = '';
      var user = new GlideRecord('x_snc_pointsthing_user');
      if (user.get('user_id', payload_user)) {
          userSysID = user.getUniqueValue();
      } else {
          user.newRecord();
          user.setValue('user_id', payload_user);
          userSysID = user.insert();
      }
      if (increment_point) {
          var score = parseInt(user.getValue('points'));
          score++;
          user.setValue('points', score);
          user.update();
      } else if (set_points) {
          if (user.getValue('points') != set_points) user.setValue('points', set_points);
          user.update();
      }
      if (!user.getValue('user_name')) {
          this.get_user_info(payload_user, userSysID);
      }
      return userSysID;
  },

  send_chat: function(chat_gr, message, force_thread) {
      var rm = new sn_ws.RESTMessageV2();
      rm.setHttpMethod('POST');
      rm.setEndpoint('https://slack.com/api/chat.postMessage');
      rm.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
      rm.setRequestHeader("Authorization", "Bearer " + this.token);
      //rm.setLogLevel('all');

      var bodyString = '';
      bodyString += '&channel=' + gs.urlEncode(chat_gr.channel);
      if (chat_gr.thread_ts) {
          bodyString += '&thread_ts=' + gs.urlEncode(chat_gr.thread_ts);
      } else if (force_thread) {
          bodyString += '&thread_ts=' + gs.urlEncode(chat_gr.ts);
      }
      if (typeof message == 'object' && message.blocks) {
          bodyString += '&text=' + gs.urlEncode(message.text);
          bodyString += '&blocks=' + gs.urlEncode(JSON.stringify(message.blocks));
      } else {
          bodyString += '&text=' + gs.urlEncode(message);
      }
      rm.setRequestBody(bodyString);
      return rm.execute();
  },

  update_tag_chat: function(send_response, users) {
      var rm = new sn_ws.RESTMessageV2();
      rm.setHttpMethod('POST');
      rm.setEndpoint('https://slack.com/api/chat.update');
      rm.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
      rm.setRequestHeader("Authorization", "Bearer " + this.token);
      //rm.setLogLevel('all');

      var responseObj = JSON.parse(send_response.getBody());

      // Replace names with tags
      var message = responseObj.message.text;
      for (var user in users) {
          var expr = new RegExp('\\b' + users[user].name + '\\b(?= \\(| - \\()', "gmi");
          message = message.replace(expr, '<@' + users[user].id + '>');
      }
      var bodyString = '';
      bodyString += '&channel=' + gs.urlEncode(responseObj.channel);
      bodyString += '&ts=' + gs.urlEncode(responseObj.ts); // Update format relies on ts, regardless of thread or not
      bodyString += '&text=' + gs.urlEncode(message);

      rm.setRequestBody(bodyString);
      return rm.execute();
  },

  get_user_info: function(slack_id, record_id) {
      var rm = new sn_ws.RESTMessageV2();
      rm.setHttpMethod('POST');
      rm.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
      rm.setRequestHeader("Authorization", "Bearer " + gs.getProperty("pointsthing.token"));
      //rm.setLogLevel('all');

      var bodyString = '';
      bodyString += 'user=' + gs.urlEncode(slack_id);
      rm.setEndpoint('https://slack.com/api/users.info' + '?' + bodyString);
      var response = rm.execute();
      var response_body = JSON.parse(response.getBody());

      if (response_body.user.name) {
          var grupdate = new GlideRecord('x_snc_pointsthing_user');
          grupdate.get(record_id);
          grupdate.setValue('user_name', response_body.user.real_name);
          grupdate.update();
          return true;
      } else {
          return false;
      }
  },

  broadcast_points: function(matches, current) {
      var messages = [];
      var users_completed = [];
      for (var i in matches) {

          if (users_completed.indexOf(matches[i]) > -1) continue;
          else users_completed.push(matches[i]);

          if (current.user.user_id == matches[i]) {
              messages.push('<@' + matches[i] + '> No self points!');
              continue;
          } else {
              var pointsTotal = new GlideRecord("x_snc_pointsthing_user");
              pointsTotal.get('user_id', matches[i]);
              var total = pointsTotal.getValue('points');

              var gaPoints = new GlideAggregate('x_snc_pointsthing_point');
              gaPoints.addQuery('target', pointsTotal.getUniqueValue());
              gaPoints.addAggregate('COUNT');
              gaPoints.query();
              if (gaPoints.next()) {
                  var points = gaPoints.getAggregate('COUNT');
              }

              var user = '<@' + matches[i] + '>';
              var message_gr = this.milestone_check(total);
              var emoji = ' ' + this.my_points(matches[i]).emoji;
              var message = new GlideScopedEvaluator().evaluateScript(message_gr, 'message', {
                  'user': user,
                  'total': total,
                  'points': points
              });
              if (message_gr.getValue('send_to_channel') === '1') this.send_chat({
                  'channel': gs.getProperty('x_snc_pointsthing.milestone_channel')
              }, message, false);
              messages.push([
                  message,
                  '(' + total + ' total)' + emoji
              ].join(' '));
          }
      }
      this.send_chat(current, messages.join('\n'), false);
  },

  milestone_check: function(total) {
      var milestone = new GlideRecord('x_snc_pointsthing_message');
      milestone.addQuery('point', total.toString());
      milestone.query();
      if (milestone.hasNext()) {
          var random_milestone = Math.floor(Math.random() * milestone.getRowCount()) + 1;
          for (var i = 0; i < random_milestone; i++) {
              milestone.next();
          }
          return milestone;
      } else {
          var default_message = new GlideRecord('x_snc_pointsthing_message');
          default_message.addEncodedQuery('point=0^ORpoint=NULL');
          default_message.query();
          var random_default = Math.floor(Math.random() * default_message.getRowCount()) + 1;
          for (var j = 0; j < random_default; j++) {
              default_message.next();
          }
          return default_message;
      }
  },

  tell_points: function(chat_gr) {
      var my_points = this.my_points(chat_gr.user.user_id);
      var emoji = ' ' + my_points.emoji;
      this.send_chat(chat_gr, '<@' + chat_gr.user.user_id + '> You have received *' + my_points.points + '* points in the last 90 days, for a total of *' + my_points.total + '* all time.' + emoji, false);
  },

  my_points: function(id) {
      var count = new GlideAggregate('x_snc_pointsthing_point');
      count.addEncodedQuery('sys_created_onONLast 90 days@javascript:gs.beginningOfLast90Days()@javascript:gs.endOfLast90Days()^targetISNOTEMPTY');
      count.addAggregate('COUNT(DISTINCT', 'target');
      count.setGroup(false);
      count.query();
      count.next();
      var total_users = parseInt(count.getAggregate('COUNT(DISTINCT', 'target'));

      count.orderByAggregate('COUNT', 'target');
      count.addAggregate('COUNT', 'target');
      count.setGroup(true);
      count.query();
      var rank = 1;
      while (count.next()) {
          if (count.target.user_id.includes(id)) {
              var emoji = '';
              if (rank == 1) emoji = ':first_place_medal:';
              else if (rank == 2) emoji = ':second_place_medal:';
              else if (rank == 3) emoji = ':third_place_medal:';
              else if (rank < Math.ceil(total_users * .05)) emoji = ':star2:';
              else if (rank < Math.ceil(total_users * .1)) emoji = ':star:';
              else if (rank < Math.ceil(total_users * .25)) emoji = ':sparkles:';
              return {
                  'id': id,
                  'points': count.getAggregate('COUNT', 'target'),
                  'total': count.target.points.toString(),
                  'emoji': emoji,
                  'percentile': Math.round(((total_users - rank) / total_users * 100) / 10) * 10,
                  'total_users': total_users,
                  'rank': rank
              };
          } else {
              rank++;
              continue;
          }
      }
  },

  leaderboard: function(chat_gr, send, all) {
      var items = [];
      var lb_tagging = (gs.getProperty('x_snc_pointsthing.leaderboard_tagging') === 'true');
      try {
          items.push('Points leaderboard (top ' + (all ? '25%' : '5%') + ' of users in past 90 days):');
          var count = new GlideAggregate('x_snc_pointsthing_point');
          count.addEncodedQuery('sys_created_onONLast 90 days@javascript:gs.beginningOfLast90Days()@javascript:gs.endOfLast90Days()^targetISNOTEMPTY');
          count.addAggregate('COUNT(DISTINCT', 'target');
          count.setGroup(false);
          count.query();
          count.next();
          var total_users = parseInt(count.getAggregate('COUNT(DISTINCT', 'target'));
          var top_5_percent = Math.ceil(total_users * .05);
          var top_10_percent = Math.ceil(total_users * .1);
          var top_25_percent = Math.ceil(total_users * .25);

          count.orderByAggregate('COUNT', 'target');
          count.addAggregate('COUNT', 'target');
          count.setGroup(true);
          count.query();

          var rank = 1;
          var not_displayed = 0;
          var complete = false;
          if (lb_tagging) var userArr = [];
          while (count.next() && !complete) {
              var item = '';
              var points = count.getAggregate('COUNT', 'target');
              var user_name = count.target.user_name.toString();
              if (lb_tagging) {
                  userArr.push({
                      name: count.target.user_name.toString(),
                      id: count.target.user_id.toString()
                  });
              }

              if (rank == 1) item = ':first_place_medal: ' + user_name + ' (' + points + ' points)';
              else if (rank == 2) item = ':second_place_medal: ' + user_name + ' (' + points + ')';
              else if (rank == 3) item = ':third_place_medal: ' + user_name + ' (' + points + ')';
              else if (rank > 3 && rank < top_5_percent) item = ':star2: ' + user_name + ' (' + points + ')';
              else if (all & rank > 3 && rank < top_10_percent) item = '⭐ ' + user_name + ' (' + points + ')';
              else if (all & rank > 3 && rank < top_25_percent) item = '✨ ' + user_name + ' (' + points + ')';
              else if (chat_gr && chat_gr.user && count.target.user_id.includes(chat_gr.user.user_id)) {
                  item = '...' + user_name + ' - (' + points + ' points, ~' + (Math.round(((total_users - rank) / total_users * 100) / 10) * 10) + 'th percentile)';
                  complete = true;
              } else {
                  rank++;
                  not_displayed++;
                  continue;
              }
              rank++;

              items.push(item);
          }
      } catch (em) {
          /*items.push('```Error:');
          for (var i in em){
          	items.push(i + ': ' + em[i]);
          }
          items.push('```');*/
      } finally {
          items.push(not_displayed + ' users not displayed');
      }

      if (send) {
          items.push('');
          items.push('https://' + gs.getProperty('instance_name') + '.service-now.com/sndevs?id=leaderboard');
          if (lb_tagging) {
              var handleTags = this.send_chat(chat_gr, items.join('\n'), true);
              this.update_tag_chat(handleTags, userArr);
          } else {
              this.send_chat(chat_gr, items.join('\n'), true);
          }
      } else return items;
  },

  points_party: function(chat_gr, send) {
      var message = '';
      var thread_ts = chat_gr.getValue('thread_ts');
      var user_id = chat_gr.user.getRefRecord().getValue('user_id');
      var user_sysid = chat_gr.getValue('user');
      var recipients = [];

      if (!thread_ts) {
          message = 'You cannot throw a points party in public. Get a thread!';
          this.send_chat(chat_gr, message, false);
          return null;
      }

      var grChat = new GlideRecord('x_snc_pointsthing_chat');
      grChat.addQuery('thread_ts', thread_ts);
      grChat.addQuery('user', '!=', user_sysid);
      grChat.query();
      while (grChat.next()) {
          recipients.push(grChat.user.getRefRecord().getValue('user_id'));
      }

      recipients = recipients.filter(function(recipient, idx, arr) {
          return arr.indexOf(recipient) == idx;
      });

      recipients.forEach(function(recipient) {
          // Create points
          var point = new GlideRecord("x_snc_pointsthing_point");
          point.newRecord();
          point.setValue('giver', chat_gr.user);
          point.setValue('target', new x_snc_pointsthing.PointsThing().establish_user(recipient, true));
          point.setValue('chat', chat_gr.getUniqueValue());
          point.insert();
      });

      this.broadcast_points(recipients, chat_gr);
  },

  type: 'PointsThing'
};

Sys ID

88dd9085db629150791d8f8d13961998

Offical Documentation

Official Docs: