Inspiration

Our inspiration for this project is the WayBack Machine located here. link

Our internet is a very wonderful place with a history of over 30 years. However, while looking through the Wayback Machine archives, you'll notice entries are missing and internet history is often lost. People want to take snapshots of sites before they are modified or deleted and the original is gone. As a result, we created an extension to fix the issues of lost website data. This extension would recover a websites data and store it for later. Hence, the introduction of the phrase "Say Cheese!"

What it does

This extension would allow users to recover their website data and create a customizable postcard of the site that they want to keep. The extension would provide a window of the website from the host server and output it, so that you can gain an insight into how the website runs and information from the time period. The site would be useful in showing a history of the internet and prevent information that you don't want to get lost from being lost.

How we built it

The first idea was to build a multiplatform app that would perform the same operations, but after loading the app onto Android, iOS, the web, and a Discord bot, we realized that there were certain aspects of the internet that couldn't be captured via using these.

As a result, the following projects were scrapped:

# Python code to make Discord Bot
# main.py
import os
import discord
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
from discord.ext import commands

intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix='$', intents=intents)

@bot.event
async def on_ready():
    print(f'Logged in as {bot.user}')

@bot.command()
async def screenshot(ctx, url):
    chrome_options = Options()
    chrome_options.add_argument("--headless")
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")

    driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=chrome_options)
    driver.get(url)
    driver.set_window_size(1920, 1080)
    screenshot_path = "screenshot.png"
    driver.save_screenshot(screenshot_path)
    driver.quit()

    await ctx.send(file=discord.File(screenshot_path))

token = os.getenv("TOKEN") or ""
if token == "":
    raise Exception("TOKEN is not set in the environment.")
bot.run(token)
<!-- index.html -->
<!-- Code for webapp frontend -->

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Say Cheese</title>
    <link rel="stylesheet" href="style.css">
    <link rel="manifest" href="/manifest.json">
    <link rel="icon" type="image/png" href="cheese.png">

</head>

<body>
    <main>
        <div id="helpModal" class="modal hidden">
            <div class="modal-content">
                <span class="close">&times;</span>
                <p>Welcome to the Say Cheese tool! This tool allows you to capture a screenshot of any website by simply entering its URL. Below you'll find step-by-step instructions, tips for troubleshooting common issues, and ways to contact support if you need further assistance.</p>
                <h3>How to Use:</h3>
                <ol>
                    <li>Enter the complete URL of the website you want to capture in the 'Enter website URL here' field.</li>
                    <li>To customize the background color of the screenshot, click on the 'Choose Background Color' button and select a color of your choice.</li>
                    <li>Once you are ready, click the 'Capture Screenshot' button to generate your screenshot.</li>
                </ol>
                <h3>Support:</h3>
                <p>If you encounter issues that are not addressed in the troubleshooting guide, please contact our support team at support@saycheese.com. We are available 24/7 and ready to assist you!</p>

            </div>
        </div>
        <div id="header">
            <h1>Say Cheese! 🧀</h1>
        </div>
        <button id="helpBtn"><i class="fas fa-question-circle"></i> Help</button>
        <div id="inputArea">
            <input type="url" id="websiteAddress" placeholder="Enter website URL here" value='https://www.google.com'>
            <br>
            <p> Pick color here:</p>
            <div class="color-picker">
                <button id="colorBtn" onclick="document.getElementById('bgColor').click();">
                    <span><i class="fas fa-paint-brush"></i> Choose Background Color</span>
                </button>
                <input type="color" id="bgColor" value="#71A6D2" style="display:none;">                
            </div>
            <br>
            <button id="submitBtn">Capture Screenshot</button>
        </div>
        <div id="loadingScreen" class="hidden">
            <p>Loading...</p>
        </div>
        <div id="resultScreen" class="hidden">
            <img alt="Screenshot" id='resultImg'>
            <button id="downloadBtn">Download Image</button>
        </div>
    </main>
    <script src="index.js"></script>
    <script>
        if ('serviceWorker' in navigator) {
            window.addEventListener('load', () => {
                navigator.serviceWorker.register('/service-worker.js').then(registration => {
                    console.log('Service Worker registered with scope:', registration.scope);
                }, err => {
                    console.log('Service Worker registration failed:', err);
                });
            });
        }
    </script>
</body>

</html>
// Code to Translate Webapp Frontend to Android and iOS
// service-worker.js
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open('v1').then((cache) => {
      return cache.addAll([
        '/',
        'index.html',
        'style.css',
        'index.js',
        'cheese.png'
      ]);
    })
  );
});

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then((response) => {
      return response || fetch(event.request);
    })
  );
});

Challenges we ran into

Ethan is an English major, so Ethan has never made a project this intense before let alone made a project in such limited time constraints. Ethan also ran a 10k the week prior, so his legs are completely destroyed prior to building this project. 😔

Jin is a very accomplished software engineer, but that also means he's working very hard almost 24/7, so time constraints were not in his favor when building this project. As a Boeing SDE, he is blocked from time period 9 am to 5 pm, so it is not easy to make time for building this project.

Additionally, there was very confusing output at first because initially, when building this project, we took note of the fact that the extension would only output sites based on their host server's location, which was very confusing at first, and we both spent a lot of time trying to figure out how to translate the image into an Engrish language. However, after realizing that the snapshot of the site in its host country's native language could provide more insight for the user, we decided to let it be.

Another thing that came up was UX design. As a user, we'd like the tool to be intuitive and easy to use. Initially, we planned to make it a multi-platform tool on Web, Android, iOS, and Discord. However, after realizing that there were major flaws with it such as bad design, that idea was scrapped and user experience was prioritized.

Accomplishments that we're proud of

We are proud that we met each other!

We are working at the same company too!

Jokes aside, we are definitely proud that somehow, despite the large amount of work piled onto our lives, we still made time to make a side project that we are proud of.

What we learned

Throughout this process, we learned that sometimes more isn't better, and in this case, the concept was more prevalent as more features only made it more confusing. Additionally, we also learned that Google is the slowest at deployment because Ethan paid the five dollar developer fee and he was scammed out of his money as it takes forever to deploy his extension to the Google Web Extensions Store. We also learned that we live in a multicultural world, and learning new languages is good, hence why Google is in German (Deutsch).

What's next for Say Cheese!

Hopefully, this extension makes it onto the Google Marketplace, but if not, we'll have to wait and see...

Share this project:

Updates