Actor picture

Page Visits Counter

juansgaitan/counter

Counts the current page visits inside an act.

No credit card required

Author's avatarJuan Gaitán Villamizar
  • Modified
  • Users21
  • Runs338
Actor picture
Page Visits Counter

Dockerfile

# This is a template for a Dockerfile used to run acts in Actor system.
# The base image name below is set during the act build, based on user settings.
# IMPORTANT: The base image must set a correct working directory, such as /usr/src/app or /home/user
FROM apify/actor-node-puppeteer-chrome:15-10.1.0

# Second, copy just package.json and package-lock.json since it should be
# the only file that affects "npm install" in the next step, to speed up the build
COPY package*.json ./

# Install NPM packages, skip optional and development dependencies to
# keep the image small. Avoid logging too much and print the dependency
# tree for debugging
RUN npm --quiet set progress=false \
 && npm install --only=prod --no-optional \
 && echo "Installed NPM packages:" \
 && (npm list --all || true) \
 && echo "Node.js version:" \
 && node --version \
 && echo "NPM version:" \
 && npm --version

# Copy source code to container
# Do this in the last step, to have fast build if only the source code changed
COPY  . ./

# NOTE: The CMD is already defined by the base image.
# Uncomment this for local node inspector debugging:
# CMD [ "node", "--inspect=0.0.0.0:9229", "main.js" ]

main.js

const Apify = require('apify');

const { log } = console;

Apify.main(async () => {
  const input = await Apify.getValue('INPUT');

  const { client } = Apify;
  const { keyValueStores } = client;
  const {
    count, limit, actName, email
  } = input;
  if (!count || !limit || !actName || !email) {
    throw new Error('Missing input value.');
  }
  const { id: storeId } = await keyValueStores.getOrCreateStore({
    storeName: actName
  });
  client.setOptions({ storeId });

  const record = await keyValueStores.getRecord({ key: 'STATE' });

  const storeRecord = record && record.body ? record.body : {};

  const previousState = typeof storeRecord === 'string' ?
    JSON.parse(storeRecord) : storeRecord;
  log('Previous STATE:', previousState);

  const currentCount = Number(count) || 0;
  const previousCount = Number(previousState.count) || 0;
  const nextCount = previousCount + currentCount;

  if (nextCount > Number(limit)) {
    const text = `
      The ${actName} has reached its current page visits limit.

      Current limit: ${limit},
      Current count: ${nextCount}

      Please notify the user to updgrade its current plan!
    `;
    log('Sending notification email...');
    await Apify.call('apify/send-mail', {
      to: email,
      subject: `The ${actName} act has reached its limit!`,
      text
    });
  }

  const nextState = Object.assign({}, { count: nextCount, limit });
  log('Next STATE:', nextState);

  await keyValueStores.putRecord({
    key: 'STATE',
    body: JSON.stringify(nextState)
  });
});

package.json

{
    "name": "apify-project",
    "version": "0.0.1",
    "description": "",
    "author": "It's not you it's me",
    "license": "ISC",
    "dependencies": {
        "apify": "0.16.0",
        "underscore": "latest"
    },
    "scripts": {
        "start": "node main.js"
    }
}