Auto Control Budget on GAE

  1. create PubSub budget alert ( Go to Billing > Budgets & Alerts > Select a Cloud Pub/Sub topic * )
  2. create cloud function
    1. Go to https://console.cloud.google.com/functions?_ga=2.91980570.1829355561.1594289961-1678581744.1556958992
    1. Select a Cloud Pub/Sub topic
    2. Souce Code
import base64
import json
import os
from googleapiclient import discovery
APP_NAME = os.getenv('GCP_PROJECT')


def limit_use_appengine(data, context):
    pubsub_data = base64.b64decode(data['data']).decode('utf-8')
    pubsub_json = json.loads(pubsub_data)
    cost_amount = pubsub_json['costAmount']
    budget_amount = pubsub_json['budgetAmount']
    if cost_amount <= budget_amount:
        print(f'No action necessary. (Current cost: {cost_amount})')
        return

    appengine = discovery.build(
        'appengine',
        'v1',
        cache_discovery=False
    )
    apps = appengine.apps()

    # Get the target app's serving status
    target_app = apps.get(appsId=APP_NAME).execute()
    current_status = target_app['servingStatus']

    # Disable target app, if necessary
    if current_status == 'SERVING':
        print(f'Attempting to disable app {APP_NAME}...')
        body = {'servingStatus': 'USER_DISABLED'}
        apps.patch(appsId=APP_NAME, updateMask='serving_status', body=body).execute()

requirements.txt

google-api-python-client==1.10.0

Function to execute

limit_use_appengine

Use Service Account that have “App Engine Admin” role ( to create service account : https://console.cloud.google.com/iam-admin/serviceaccounts?project=YOUR_PROJECT_NAME )

Test your Cloud Function

publish this data

{
    "budgetDisplayName": "name-of-budget",
    "alertThresholdExceeded": 1.0,
    "costAmount": 100.01,
    "costIntervalStart": "2019-01-01T00:00:00Z",
    "budgetAmount": 100.00,
    "budgetAmountType": "SPECIFIED_AMOUNT",
    "currencyCode": "USD"
}
pip install --upgrade google-cloud-pubsub
export GOOGLE_APPLICATION_CREDENTIALS="whatever-download-from-service-account-that-have-pub-sub-publisher-role.json"
"""Publishes multiple messages to a Pub/Sub topic with an error handler."""
import time

from google.cloud import pubsub_v1

# TODO(developer)
# project_id = "your-project-id"
# topic_id = "your-topic-id"

publisher = pubsub_v1.PublisherClient()
topic_path = publisher.topic_path(project_id, topic_id)

futures = dict()

def get_callback(f, data):
    def callback(f):
        try:
            print(f.result())
            futures.pop(data)
        except:  # noqa
            print("Please handle {} for {}.".format(f.exception(), data))

    return callback

for i in range(10):
    data = '''{
    "budgetDisplayName": "no spend",
    "alertThresholdExceeded": 1.0,
    "costAmount": 100.01,
    "costIntervalStart": "2019-01-01T00:00:00Z",
    "budgetAmount": 100.00,
    "budgetAmountType": "SPECIFIED_AMOUNT",
    "currencyCode": "USD"
}'''
    futures.update({data: None})
    # When you publish a message, the client returns a future.
    future = publisher.publish(
        topic_path, data=data.encode("utf-8")  # data must be a bytestring.
    )
    futures[data] = future
    # Publish failures shall be handled in the callback function.
    future.add_done_callback(get_callback(future, data))

# Wait for all the publish futures to resolve before exiting.
while futures:
    time.sleep(5)

print("Published message with error handler.")

Testing

You need to enable “Appengine Admin API” at some point. See the Log ( View Logs ).

It may take few minutes to complete this process.

To verify that the function ran successfully, view the App Engine dashboard. A message appears near the top to indicate that your app is disabled.

ref : rewrite from : https://cloud.google.com/appengine/docs/managing-costs

delete all facebook page activity script

var editButtons = document.querySelectorAll("[data-tooltip-content='Edit']");

for (i = 0; i < editButtons.length; i++) {
  editButtons[i].click();
}

var deleteButtons = document.querySelectorAll("[ajaxify*='/allactivity/removecontent/']");

for (i = 0; i < deleteButtons.length; i++) { deleteButtons[i].click(); setTimeout(() => { console.log('deleting') }, 2000)
}

inspired by https://mjvolk.com/delete-facebook-posts-with-javascript/

[ gulp ] migrate to gulp 4 on macOS

migrate from gulp 3.9.1 to gulp 4

  1. make sure that npm uninstall -g remove gulp package from /usr/local/lib/node_modules, otherwise you will face the error like this
/usr/local/lib/node_modules/gulp/bin/gulp.js:129
    gulpInst.start.apply(gulpInst, toRun);

2. if nvm is used, make sure to switch to system and uninstall from there

$ nvm list
->       v7.6.0
       v10.14.1
         system
$ nvm use system
Now using system version of node: v6.10.0 (npm v5.6.0)
$ npm uninstall -g gulp
removed 174 packages in 1.825s