Course/movie labeling solution using Firebase and ViolentMonkey

Course/movie labeling solution using Firebase and ViolentMonkey

There are pages that do not show information about items you watched, want to watch or don’t want to. May it be a movie database, TV guide, list of online courses, and so on. One such page is Highbrow which, for an unknown reason, has no account feature yet lists a lot of courses. It may be easy to forget which you completed and even harder to find a new course to start.

I’ll show how to create a kind of addon – a GreaseMonkey/ViolentMonkey script that will be run automatically once you enter that page (here: Highbrow) and show the items you marked as completed or todo. That script will connect with a free cloud database Google Firebase to store your list and provide an easy ability to mark every course. Here it is in action:

GreaseMonkey (for Firefox) and ViolentMonkey (for Chrome, Firefox, Opera) are free browser add-ons that allow executing scripts on certain pages. Both provide directories of useful scripts for various pages and are safe as long as you know JavaScript ;). You can find or create scripts to allow download on Instagram, hide YouTube ads, add features to Trello or Notion, automatically fill in complex forms or log in to sites with masked passwords.

Create a Firebase project

Firebase is a free (under certain conditions) cloud database that you can use in your projects. First, create a free Spark account at https://console.firebase.google.com/.

Now create a new project by clicking Add project:

Supply the name for your project:

and disable analytics for this simple database as you will be the only one using this database:

Create a Firestore database

Once the account is created, set up a database. Click Database and Create database:

Use the production mode, because the test mode will stop working in a month anyway:

and choose the location for your database. It does not really matter for such low volume application, nonetheless select the one that’s closest to you:

Create a Firebase application

It’s time (if you didn’t have an occasion before) to register our application for the Firebase database.

Click the Settings button and the Web icon in the applications section:

Name your application and exclude hosting unless you will need it. My application will work in my web browser, so I won’t need hosting.

In result, you will get the code to put to your JavaScript file, like this:

HTML

We will use it in our script.

Remove the authentication

Currently only administrators can read and update the database. You can see it in the Database > Rules menu:

JSON

For a quick connectivity test, let’s remove all authentication rules and check if we can connect to the database.

Go to Database > Rules and change the rule from false (no access) to true (anyone can access):

Test the database

Advice

Save hours of debugging and googling and make sure you read documentation and samples for Cloud Firestore, not Realtime Database product.
Here you can find the Firestore documentation.

Create a new GreaseMonkey/ViolentMonkey script to check the connectivity.

The import <script src="https://www.gstatic.com/firebasejs/7.6.1/firebase-app.js"></script> will be written as a require in the script’s metadata. We’ll also need another import for the database access.

First, let’s open a destination page. In my case it’s https://gohighbrow.com/courses/. Now click the ViolentMonkey icon in Chrome and the plus button to create a script for this page. You’ll see a file like this:

JS

Replace it with:

JS

Save the script, refresh the page the script applies to (in my case it’s https://gohighbrow.com/courses/) twice, open the console and you should see the new entry printed. You’ll also see it saved in the database in the Data tab in your Firebase console.

first-key  =>  {fullUrl: "https://gohighbrow.com/courses/"}

One remark about the database storage. It’s a NoSQL database, so it doesn’t have tables, rows and relations. Instead, it has collections of data (which can be treated as tables) and documents with data (which can be treated as rows). A document has an identifier and arbitrary amount of fields. In Firestore, a document may store a collection of another documents. Moreover, two documents in the same collection may have completely different sets of fields.

In the case above, we created a document with ID = first-key, with one field fullUrl that has the value of current URL (location.href). That document was stored in the links collection.

Set up the authentication

There are many authentication options available to Firebase projects, as you can read in the documentation. Because our application will be used only in our browser, we can use password authentication and hardcode it into the script.

Avoid

Never store password in publicly available code.

First go to Authentication > Set up sign-in method:

and enable the e-mail method:

Make up an email address and password, write them in a secure place and enter to the form that opens after you click the Add user button:

Now go back to the Database > Rules tab and enable only authorized users access:

Test the authorization

Edit the ViolentMonkey script. We need to add the firebase-auth.js library and authentication logic:

JS

Encapsulation

Although the code is working, it’s a bit messy. Let’s clean it up:

JS

The database() function connects to the Firestore, authenticates and returns an object that has three methods: save(), get() and getAll(). I have also added methods urlEncode() and urlDecode() to remove and bring back characters that are valid in a URL but forbidden in document keys.

The database part is complete. Let’s proceed to the application.

Display labels

JS

This is quite simple JavaScript code that handler the user interface.

It begins with a configuration that allows the solution to adapt to different pages:

  • CLICKABLE_SELECTOR is the CSS selector that defines every item (here: course) that can be clicked. Moreover, this should be something neutral that normally isn’t clickable, like a paragraph.
  • GET_URL_FROM_CLICKABLE – once the user clicks that above selector, this function should return the link or other unique identifier associated with that item (course).
  • GET_LABEL_PARENT_FROM_URL is a function that should return the HTML container to which the label should be appended. It takes the URL as an input. It’s used to find the item on the page when we know only its URL.
  • LABEL_CLASS is the class name used by the labeler. In case the default label is already used or you want to style it otherwise.
  • EXTRA_LABEL_STYLES is a string containing extra inline styles for the labels.

Then two functions are called:

  1. showLabels() which retrieves all information from the database and displays it on the page.
    • showLabel() determines color and text based on the label’s status. I anticipated 3 statuses: TODO, DONE, and NOT (NOT INTERESTED).
    • colorize() adds the label to the page.
  2. handleClick() adds the style for the mouse cursor to all CLICKABLE_SELECTORs and turns them into actions that call rotateLabel().
    • rotateLabel determines the next status for a label with every click: (none) -> DONE -> TODO -> NOT.

You can get the whole source code from my Gist.

Import data

I have previously stored completed courses in files as links (file.url). Each file had exactly two lines:

[InternetShortcut]
URL=https://gohighbrow.com/portfolio/hacking-your-inbox-for-maximum-productivity/

I quickly extracted all links from these files using a short PowerShell script:

Plain Text

Since Get-Content returned an array of lines, I used $s[1] to refer to the second line. The rest is formatting – `t stands for the TAB character, and Substring(4) gets rid of the URL= prefix.

The result were items that I pasted to an array in JavaScript and called and save() method for each.

Leave a Reply

avatar
  Subscribe  
Notify of