Why I Created Thousands Google Meet Links and Rate Limited My Account
Tags: python, automation, showdev, devjournal
Published: 2022-09-03 08:04:41


## The Idea
It's simple really. What if you could have a Google Meeting with a code of your choosing.

As you might already know, creating a new meeting with Google Meet creates a new link with a pattern of random unique letters at the end. The pattern looks like this `xxx-xxxx-xxx`.

My idea is to create thousands of these URLs in the hope that maybe one pops up with a phrase in it that I liked, maybe my name, maybe my initials, it could be anything.

All in all, It's a project purely for fun. It's fun to just mess around every once in a while!

## What I Already Knew
- A new link can be generated by visiting a specific [url](https://meet.google.com/new)
- Links are always unique and random
- A Google Account which creates a link is always its host
- A meeting link is re-usable after leaving

## How To Approach This Problem
There were a few ideas on how to generate these meetings and get their links.

 - Python + Selenium

Selenium is a web browser automation tool, and there's bindings for the Selenium API in Python

The Good
  1. An advantage of using Selenium would be the ability to hide a browser window completely whilst it generated links using [Headless Mode](https://stackoverflow.com/questions/46920243/how-to-configure-chromedriver-to-initiate-chrome-browser-in-headless-mode-throug). This would allow the program to run in the background even when you were using your device

The Bad
  1. Accessing a Google account in a Selenium driven window requires you to jump through quite a few hoops because of the possible breach in security this could lead to. This project needed to be built quickly, the quality of the code didn't matter too much because at the end of the day, this project won't ever serve a real purpose
  2. Before this, I'd only ever heard of Selenium and had a glance at the documentation, and never actually used it in a project, so there'd be a learning curve to overcome during this project too

- Python + `pyautogui`

The second idea, and the one I ended up going with was using Python and `pyautogui` (a package to use a Python script to control the mouse and keyboard).

The Good
  1. There would be no browser compatibility issue, since I would be using my normal browser with its default Google Account.
  2. And, there'd be a easy and quick way to click on elements on screen. Simply take a screenshot of the element you want to click and reference it in your code. This completely avoids going through the pain of finding out which selector is precise enough in Selenium. 
  3. Another positive for me was the fact that I had been using `pyautogui` for a while before this for [AutoClass](https://github.com/DaKheera47/autoclass), so using it was almost second nature to me

The Bad
  1. It's slower than Selenium for sure, but absolute speed just wasn't the main goal here.


## A Laundry List of Problems
- How To Find Out When The URL Has Changed

  The way I first imagined the program working was by looking at the URL bar of the browser. With Edge, whenever I joined a meeting, it would show a camera icon, indicating that the camera was being used. This of course would only happen after the page loaded up completely (and hence the link in the URL bar had changed from `https://meet.google.com/new` to a new URL with the pattern), and since I could easily take a screenshot of anything on the screen and detect its presence and location, I felt this was a good place to start.

  Coding this up wasn't an issue, especially with the helper functions like [`findImageTimeout`](https://github.com/DaKheera47/autoclass/blob/43b13c9a090a34a332265e94a7df091eb76d1de4/helpers.py#L197) I had made previously which add some functionality which is actually on the roadmap of the `pyautogui` package. As the name suggests `findImageTimeout` attempts to find an image on screen using `pyautogui`, and keeps attempting to find it until the specified timeout is up.

- How To Get The URL From The URL Bar

  Now I knew when the URL had updated to the new one, however I still hadn't gotten around to actually getting the URL into a variable. Checking to see if the camera was visible did help me in this case because the new URL is just slightly left of the where the camera icon appears. Now we know how to tell the program where to find the URL, but how to get it into a variable?

  Purely by chance, I had stumbled across this exact problem in an earlier project (more on that in another post), and I knew how to solve it now. Using `pyautogui`, you can send hotkeys like `ctrl + c` to copy and in Python, you can access the contents of the clipboard in a few different ways.

   1. The one I used was `pyperclip` because of its simplicity, and reliability.
   2. The second option was using `win32`, which had extremely verbose syntax, and had to be executed with quite a few pauses with `time.sleep()` to get it to work reliably, so it far slower, and more clunky to work with.

- The Complete Roadmap

  So to get the URL from the browser, I can have the program click the URL bar slightly left of the coordinates of the camera icon, which automatically selects all the text in the field, then I can send a `ctrl + c` using `pyautogui` to copy the created URL into the clipboard. I can then read the clipboard using `pyperclip`, and store it in a file.


## v1.0
After implementing the very initial concept of the project laid out above, here's some gripes I still had with the program.
- Clunky Codebase

  The code base at this time was very bodged together, almost feeling like it was different pieces of code just duct taped together without thought. The program wasn't too reliable either, eg if a link failed to load, then the program would be unable to handle it.
- Speed

  I measured the performance of the script in terms of seconds per link. In its current state, the script was taking around 13-15 seconds per link. This was directly and severely impacted by my (at the time) subpar internet performance, and other factors like when Edge decided to show the camera icon.

## v2.0
Here comes the single biggest improvement to the speed of the program. 

The [Google Meet Homepage](https://meet.google.com/) has an option to create the link for a later time. 

![Create a link later](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wyjccan756oofgr92tdz.png)

Crucially for us, to create a new link, this option doesn't refresh the whole page. It loads a modal on the page, with just the link and a copy button.

Conveniently, it also has a close button on the modal, which resets the state of the webpage. This means this loop can be repeated extremely quickly.


![Create a link later modal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0fvp5dks6ysc2le6r7q9.png)


With this method, I brought the program down to about 2 seconds per link. We're looking at roughly a 750% improvement from our initial starting point of 15 seconds per link.

## v2.1
Previously, processes taking up fractions of a second wouldn't have made a significant performance improvement, since one link was taking 15 seconds. However now, with our time down to 2 seconds per link, I had to optimize these processes to improve speed further.

### Find Images In Screenshots More Effectively

One of the main areas where I could still improve was finding elements on the screen. Now seems like a good time to mention that just taking a screenshot of a 1080p display takes ~100ms, according to the `pyautogui` [docs](https://pyautogui.readthedocs.io/en/latest/screenshot.html#the-locate-functions:~:text=On%20a%201920%20x%201080%20screen%2C%20the%20screenshot()%20function%20takes%20roughly%20100%20milliseconds%20%2D%20it%E2%80%99s%20not%20fast%20but%20it%E2%80%99s%20not%20slow.). Finding an image within this screenshot would take far more time, and so this was a main point of concern for performance. This can be improved significantly and we'll see how later.

### Fractional Improvement
- To prevent `pyautogui` from attempting to find static objects (eg the "close" button and other similar non moving objects) on the entire screen, I had to hard code the exact pixel coordinates of these locations, and clicking on these pre-defined points as opposed to taking time to find them on screen.
- There was at least one element I couldn't hard code however, and that was the copy button in the modal. This is because there's no set time for it to appear. It could appear in 300ms, or it could take up to 1000ms, all subject to my internet connection.

  I could optimize this further however. Considering we already know that the copy button will appear only in a specific area, we can search for the copy button in that (far smaller) area instead of the entire screen. This makes the search process as efficient as it can be.  


  All of this improvement resulted in sub-second time for each link generally around 0.75 seconds for every link. The largest performance bottleneck now was my internet connection, and I considered this a good enough place to stop working on it, and also because I got the link I wanted to find, a link with `dak` in its pattern.

## Being Rate Limited by Google
Since this program was creating links automatically (and in sub-second time), of course I left it running overnight. After a few nights of creating links, I ran into a limitation set in place by Google. If I generated more than 5000 links in a span of one hour, I got rate limited. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dt8qgnay8u63z9dpiik6.png)


This was evident because the modal, instead of showing the copy button with a new link, showed an error message. I found out this limitation was account-specific, and switching to another account meant you could go all the way again. I felt quite good about myself since this was one of my first web scraping / web automation projects, and getting rate limited by Google seemed like quite an achievement.

## Some Interesting Observations
- Google doesn't use the letter `L` in any of its link patterns
- Google avoids common words in its links

## Github
The Github Repo for the completed project is available [here](https://github.com/DaKheera47/meet-link-generator). Run `laterMethod.py` to use the Homepage method.

## Get In Touch
👋 Hi, I’m [@DaKheera47](https://portfolio-dakheera47.vercel.app/), you may know me as Shaheer Sarfaraz

👀 I’m interested in making web apps in React and Node, and you can view more of my projects [here](https://portfolio-dakheera47.vercel.app/)

💻 I'm also passionate about automating everything to improve my day-to-day life

🌱 Currently, I’m working as a Full Stack Web Developer at [Project Mirage](https://www.pro-mirage.com), a Design And Development Consultancy

📫 I'm free to talk any time on my email address, shaheer30sarfaraz@gmail.com