Automated Printing of Google Documents using Google Apps Script, the DropBox API, and Automator Folder Actions

A couple of years ago, I shared a workflow that we still use to auto generate documents that we use each week. A few months ago, I shared another workflow that showed how I automated printing our weekly Planning Center Online paperwork.

I decided recently that I was tired of still having to manually print these weekly “talking points” documents, while having my Planning Center paperwork fully automated. So, I took a few minutes and wrote a new Google Apps Script to help with this.

We print these every week. I was doing it manually, but not anymore!

Here is what the script does:

  • Searches a specific Google Drive folder for all subfolders with files that match today’s date (the script will run on a weekly trigger)
  • If the file is a match, it opens the file as a PDF and stores the binary contents in a variable
  • An upload request is made to the Dropbox API with that binary data and a file name
  • Dropbox saves the file into the “Automated Printing” folder
  • Dropbox then syncs the file to the local computer (Mac)
  • The local Mac is configured with a Folder Action that automatically prints any files placed in this folder
  • After the Automator Folder Action prints the file, it removes the file

Here’s how you set it up:

First, you want to create a new Dropbox “App”. Go to dropbox.com/developers and click “Create apps”.

Then, you need to fill out these fields:

  1. “Choose an API”: Scoped Access. It’s your only choice.
  2. “Choose the type of access you need”: I chose “Full Dropbox” because I already had a specific folder set up in the root of my Dropbox. If you’re setting up the Automator Folder action for the first time, you could probably keep the scope within “App folder”.
  3. “Name Your App”: Give it a meaningful name. It does have to be unique across all of Dropbox, for some reason, so if you get an error here, just add something unique to you.
  4. “Choose the Dropbox account that will own your app”: If you have personal/business accounts linked, you’ll need to choose the account that owns the app. I’m using a business account for this, so I chose that one.

On the next page, choose the “Permissions” tab.

Then give your app “files.content.write” access.

Now back on the Settings tab, generate a new Token and set the Expiration to “No expiration”.

This will generate a Token key which you will use within the Google Apps Script in the next steps.

Now in Google Drive, click “New”, go down to “More”, and choose “Google Apps Script”. Google Apps Script is essentially Javascript, so it’s super easy to use.

You’ll want to give the project a helpful name, as it will be stored in your Google Drive this way.

Give your project a helpful name.

In the code section, paste in my script below:

/*
EDIT THESE VARIABLES FOR YOUR SETUP
*/
var accessToken = "token"; //Dropbox App Access Token
var rootFolder = "folderID"; // Google Drive Root Folder where these files live
var dropboxPath = "/Automated Printing/"; //Dropbox Folder Path to place file in
var numberOfCopies = 2; //the number of copies you want per file

//Nothing to edit below

function myFunction() {
  var dtDate = new Date();
  const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
  var strDate = monthNames[dtDate.getMonth()] + " " + dtDate.getDate() + ", " + dtDate.getFullYear();
  var mainFolder = DriveApp.getFolderById(rootFolder);
  var subFolders = mainFolder.getFolders();
  while(subFolders.hasNext()) {
    var subFolder = subFolders.next();
    var files = subFolder.getFiles();
    while(files.hasNext()) {
      var file = files.next();
      var fileName = file.getName();
      if ((fileName.indexOf(strDate) > -1) && (fileName.indexOf(".pdf") == -1)) {
        //this is a file we want to print
        Logger.log("Generating PDF: " + file.getName());
        for (let i = 0; i < numberOfCopies; i++) {
          sendToDropbox(file.getName() + ".pdf", file.getAs('application/pdf'));
          Utilities.sleep(15000); // wait 15 seconds before doing the next file, so that Dropbox has time to sync the file, the Automator can print the file, remove it, and close out
        }
      }
    }
  }
}

function sendToDropbox(fileName, fileBlob) {
  var parameters = {
    "path": dropboxPath + fileName,
    "mode": "add",
    "autorename": true,
    "mute": false,
    "strict_conflict": false
  };

  var headers = {
    'Authorization': 'Bearer ' + accessToken,
    'Content-Type': 'application/octet-stream',
    'Dropbox-API-Arg': JSON.stringify(parameters)
  };

  var options = {
    "method": "POST",
    "headers": headers,
    "payload": fileBlob
  };

  var apiUrl = "https://content.dropboxapi.com/2/files/upload";
  var response = JSON.parse(UrlFetchApp.fetch(apiUrl, options).getContentText());
}

Now modify the top section to include your Dropbox access token (the one you generated earlier), the Google Drive folder ID (the folder ID is in the URL of the page when you open that folder in Google Drive), the Dropbox path to save to, and the number of copies you need for each matching document. In our case, I need 2 copies of each document.

I learned in testing that if Dropbox syncs the files too fast while my Automator folder action is still running, the new files that were added don’t get included in the folder action, and the folder action doesn’t re-run those new files. So, what this script does is it uploads a new PDF for every copy needed, but it waits 15 seconds in-between. This gives Google time to upload to Dropbox, Dropbox time to sync to my local Mac with the Automator action, and Automator time to run its script and print the file and delete it. It’s not very efficient, but the files are not that large.

Now that your script is in place, you need to assign a trigger to it. Click “Triggers” on the left-hand side of the screen:

Add a new trigger. I used the following settings to have it run weekly on Sundays between 6 and 7am. Be sure to target the “myFunction” function as that’s the main one we are using.

You’ll need to create the folder action in Automator. Follow my previous post on how to do this, as the steps are the same. I didn’t have to change that at all!

Here’s a tutorial video if you learn better that way:

I hope this helps you think of ways to automate what you’re doing in Google Drive so you can spend more time on ministry and less on manual tasks!

Automating Lights, Sending Advanced MIDI Messages, HTTP Requests, and More through ProPresenter Slide Notation and the new PresentationBridge Client

A couple of years ago, I wrote about the real-time lyrics sharing software I created to help us be able to send lyrics from ProPresenter straight to people’s phones and tablets at our outdoor worship night. Since then, we have not used this software too much, but I have helped countless other churches get it going for them, especially in this era of doing church differently in a pandemic. Many churches have found this free software valuable so that they could share worship lyrics and other messages while doing outdoor or distanced services.

Now, I have an update!

I have created a client-side app that runs in the system tray to facilitate the connection to ProPresenter and send the lyrics to the cloud server. It also supports several unique “slide notations” that allow you to automate nearly everything just by having a ProPresenter operator click on a slide.

An example of slide notation that PresentationBridge Client supports.

These slide notations are interpreted by the PresentationBridge Client software and are triggered when they are a part of the current slide.

The PresentationBridge Client interface.

The software can also detect instances of ProPresenter (and midi-relay!) running on your network to help make it easier to get connected. It supports sending all of the midi-voice messages that midi-relay supports, as well as a custom shortcode for Chroma-Q Vista, which requires MIDI Show Control in order to remotely execute specific cues on specific cuelists. It can also send out HTTP GET/POST requests, and it can virtually press a Companion button on your remote instance of Companion. This means that you can do just about anything automatically, just by clicking on a slide.

We had a chance to use it in our outdoor worship night back in October, and it worked great! I was making tweaks to it in real-time as people were using it.

We used the new PresentationBridge Client at our outdoor night of worship and it worked very well.

Here’s a video that shows it in action:

This project will be released open-source at some point, but currently I am looking for a few testers to give their feedback. If you’d like to be considered, please reach out to me via the contact form and I will be in touch.

Using cronicle, the planning center online api, and automator on a mac to automate printing weekly paperwork

In my never-ending quest to automate anything I ever have to do more than once, I thought that it might be nice if I could have my paperwork/custom reports that I manually print out every Sunday to print out automatically for me. I do the same thing every week – open Matrix view, select the next plan of each service type, click Print, and choose my report.

I’ve written about and shared my PCO custom reports before. I’ve also shared about how Planning Center makes a robust API available to get data and information about your plans.

So, I whipped up a new Cronicle plugin that does the following:

  • Accepts a PCO AppID and Secret Key
  • Accepts a list of PCO Service Type Id’s, delimited by semicolon
  • Accepts the PCO Matrix Custom Report ID and printing parameters (page size, print orientation, print margin)
  • Loops through the list of provided service types and determines the “next plan id” of each service type and adds that to a list. For us, that’s the next plan in Auditorium 1, and the next plan in Auditorium 2.
  • Then it builds the URL to generate the PDF just like PCO would do within the browser.

Then, the plugin sends a TCP message to a computer running VICREO Listener to open the URL which generates the PDF. This free program is used to send hotkeys remotely to other computers, but it can also execute files and shell scripts. It sends a command to the computer to open the Safari browser with this URL. Safari automatically downloads it to a folder I have in Dropbox, called “Automated Printing”. I do have to keep Safari logged into my PCO account for this to work, and I chose Safari for this task because it’s a browser that’s already installed which I don’t often use, so it’s fine to have all downloads automatically go to that Dropbox folder.

Lastly, I made a Folder Action in Automator. If you haven’t heard about Automator for MacOS before, I strongly suggest checking it out. It can do so much. I’ve used it for all kinds of things. This folder action watches for new files in that “Automated Printing” folder, filters out any newly added files that aren’t PDF files (just in case something else gets put in there by accident), prints out any added files to the default printer, and then deletes the files 5 seconds later. I don’t need to keep them anyway.

Here’s a video of the whole plugin in action:

You can get this plugin from my Github repository, https://github.com/josephdadams/CroniclePlugins

Additional Cronicle Plugins

A few weeks back, I shared about how I am using a Chromebox running Node.js to run an automated scheduling server to control our production equipment. It uses the open-source project, Cronicle, to do this.

Since sharing that post, I’ve created a couple more plugins:

  • This one is probably obvious, but I’ve made a plugin for Companion. It accepts the IP of the computer running Companion, the TCP listening port (51234), and the page and button you want to press.
  • The second plugin I’ve made is to control TP-Link HS100 wifi outlets. We have a lot of these around here and we use them to turn on and off equipment remotely. I did some work awhile back to determine the protocol necessary to control them over the network without having to use the TP-Link app. Now we can do this through Cronicle which makes it super easy to automate turning on and off equipment for events.

These are available in the Github repository, so go check them out: http://github.com/josephdadams/cronicleplugins/

automating production equipment using a chromebox and a scheduling server

Have I mentioned before how I love automation? Efficiency at its best.

One of the things I like to automate is the turning on of production equipment on Sunday mornings. It’s nice to walk in for the day and already have equipment turned on and ready to go. It saves me time so I can focus on other things.

In the past, we’ve used crontab on some of the production Macs to send HTTP requests via CURL commands. It worked, but it’s hard to manage when there’s a lot of commands to keep up with. We even tried using GUI interfaces for crontab like Cronnix, but the end result is the same. How do we track and manage all of the commands from a central place?

I came across a tool awhile back called Cronicle. It’s a multi-server task scheduler and runner, with a web based front-end UI. It’s essentially cron but written in Node.js. It can create scheduled and repeating jobs, perfect for ministry activities that tend to repeat.

Cronicle screenshot from their Github repository.

I knew that I wanted to set up a dedicated server to run Cronicle for us. Awhile back, I picked up a used Asus Chromebox CN60 off eBay for $37. I originally bought it hoping to be able to use it with my LiveCaption project, but that didn’t work out. However, the specs on the box are just as good (if not better) than a Raspberry Pi, so I decided to turn it into the server for this project.

Pretty small so it’s not too bad sitting in the rack!

It’s a fairly simple process to remove ChromeOS and install Ubuntu. I won’t detail that here but you can read about it. Installing Cronicle is just as easy if you follow the instructions on the Cronicle Github repo.

Once the server is up and running, it’s time to make some events! I decided to break our scheduled events into some basic categories:

  • Auditorium 1 (events for equipment primarily in Aud 1 related to regular ministry activities like Sunday mornings)
  • Auditorium 2
  • Campus Speakers
  • Automated Video Recording
  • General

For example, I have a scheduled event for every Sunday, at 6am, to turn the Auditorium 1 projectors on. It sends an HTTP request using the built-in Cronicle HTTP Request plugin to my Dashboard Production Control system which contains the code to turn the projectors on/off.

Screenshot of an event

I also have the lights turn on using my midi-relay software. It automatically routes the side screens on our Ross Carbonite switchers to the pre-service slides, turns on the campus speakers, etc.

A really nice feature of Cronicle is the ability to add your own plugins. They can be written in virtually any programming language and receive JSON input from Cronicle, so you can customize parameters and commands that get passed to them.

For some of our needs, I’ve created a few plugins so far which I have made available on my Github repository:

  • Rosstalk – to send commands to Ross Carbonite switchers
  • VICREO Listener File Opener – to open files, scripts, and programs on remote devices (requires the free VICREO Listener program)
  • VICREO Listener Hotkey – to send hotkey commands to remote devices
  • Videohub – to change routes on Blackmagic Videohub routers

I decided to write all of my plugins in Python because the linux server can run them right out of the box with little modifications needed, especially since they are just using simple TCP protocols to send information.

Some of the events I have created so far.

I’m always forgetting to run the video recording, so I automated that. We have a speaker system throughout the campus that has various amps that need to be turned on, so now we can turn them on with a schedule, and even start Spotify playing at a specific time! (This is done by executing an AppleScript on the computer running Spotify.)

We also have an 8-week event coming up in the fall for a Bible study that is at 6am in Auditorium 2. The tech needs are minimal, but they want lights on, a microphone, video recorded, to project some slides, etc. So, we created events to:

  • Open Vista (VICREO File Opener)
  • Go to a specific light cue on a specific cue list (midi-relay)
  • Turn on the projectors (HTTP request)
  • Turn off the LED wall (HTTP request)
  • Take the PTZ camera to a specific preset position (HTTP request)
  • Turn on a mic (midi-relay to a Raspberry Pi connected to the S6L via MIDI)
  • Route the program audio and video to the Ki Pro recorder (Videohub)
  • Start the Recording

And then later in the morning at specific times, everything will turn off and go back to normal. We will train someone to be on-site in the event of a change in plan, but this will greatly minimize the need to train someone all of the necessary buttons to press to turn everything on in the right order – it will just happen for them automatically based on the time of day!

Here’s a walkthrough video of it in action:

Overall, I’m very glad to have a centralized system in place to manage these scheduled events to automate our systems and am looking forward to making it even better as we continue to use it. If you want to try Cronicle out for yourself, you can read more about it on their website. It’s a free tool so definitely worth checking out. I have made my simple plugins free as well, and you can get them here: https://github.com/josephdadams/CroniclePlugins

Using the iOS Shortcuts app to automate production workflows

I love automation. I love making things more efficient and consistent, and I’ve found that on a particular level, automating or simplifying certain tasks through automation can make it easier for volunteers when working in a church production environment.

The latest app that I’ve been enjoying is the iOS “Shortcuts” app that was added to my phone in a recent iOS upgrade. It allows you to use actions within apps or activity on your phone to spawn other actions. Things like “Text my wife how long it will take me to get home, when I leave work” by using the GPS location on my phone. Or, make a shortcut that when you take a picture using the camera app, it is automatically posted to Facebook.

1200x630wa
Look for this app on your iOS device.

If you’ve ever used the service IFTTT, you’ll find familiarity with the Shortcuts app in some of the concepts. Of course, the integration into the phone at a core level with Shortcuts is much nicer. One thing I particularly like is that, once you name a shortcut, you can simply say, “Hey Siri, [shortcut name]” and it will run it.

And, Shortcuts can make HTTP requests (GET, POST, with JSON, etc.) as actions. So, it’s super easy to add a shortcut that triggers a Companion button or a task in a Ross Dashboard custom panel, for example. And that’s one of the ways I’m using the Shortcuts app.

In our production workflow, we use Ross Dashboard custom panels that I created to control nearly every aspect of our video system (and slowly, audio and lighting as I create the connections). It’s very easy to trigger a button via HTTP request, so I set up several shortcuts that I can use to save me time, especially when I am away from the production area or not near a computer running one of the Dashboard panels, as long as my phone is connected to the production network wifi (or I’m connected via VPN if remote).

Photo Nov 18, 2 22 59 PM
Here are a few of the shortcuts I’ve created.

Photo Nov 18, 2 23 21 PM.png
All this particular shortcut does is make an HTTP GET request to my master Ross Dashboard Custom Panel, which is listening to Port 5400, and triggers the GPI, “aud1_psl”.

Screen Shot 2019-11-18 at 2.23.52 PM
It’s the same as clicking on this yellow button, but I can run it from my phone, as long as I am connected to the production network!

So, just like that, it’s very easy to do something like this: “Hey Siri, go to Pre Service in Auditorium 1”, and have all of the lights change (by sending a midi-relay command to a MIDI Show Control message to our Vista lighting console) and the program screens go to the pre-service loop (by sending a RossTalk command to execute a custom control on the Carbonite to change inputs).

Here’s a video of it in action!

[wpvideo URjPHb4M]

Go check out the Shortcuts app if you aren’t using it already in your production workflow!