diff --git a/.DS_Store b/.DS_Store index 5b928bb7..c4187498 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 41635879..ad4d0412 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,10 @@ service-account-credentials.json # File Types *.env *.zip + +# Python bytecode +__pycache__/ +*.pyc + +# macOS +.DS_Store \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index efb2be08..0263584f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,26 @@ services: image: cornellappdev/transit-dev:${IMAGE_TAG} env_file: .env volumes: - - ./service-account-credentials.json:/app/service-account-credentials.json:ro + - .:/usr/src/app + - /usr/src/app/node_modules + + ghopper: + image: cornellappdev/transit-ghopper:03_01_25 ports: - - "8080:3000" - + - "8988:8988" + + map: + image: cornellappdev/transit-map + ports: + - "8989:8989" + + ghopper-walking: + image: cornellappdev/transit-ghopper-walking:latest + ports: + - "8987:8987" + + live-tracking: + image: cornellappdev/transit-python:03_01_25 + env_file: python.envrc + ports: + - "5000:5000" diff --git a/package-lock.json b/package-lock.json index 826744f3..605701ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3242,6 +3242,7 @@ "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", "dev": true, + "license": "MIT", "dependencies": { "chokidar": "^3.5.2", "debug": "^4", diff --git a/python.envrc b/python.envrc new file mode 100644 index 00000000..f426cffc --- /dev/null +++ b/python.envrc @@ -0,0 +1,5 @@ +TOKEN=TOKEN +TWITTER_KEY=TWITTER_KEY +TWITTER_KEY_SECRET=TWITTER_KEY_SECRET +TWITTER_TOKEN=TWITTER_TOKEN +TWITTER_TOKEN_SECRET=TWITTER_TOKEN_SECRET diff --git a/src/.DS_Store b/src/.DS_Store index a39c96c4..13a4eedd 100644 Binary files a/src/.DS_Store and b/src/.DS_Store differ diff --git a/src/controllers/EcosystemController.js b/src/controllers/EcosystemController.js index b302eb29..4dc6ed8e 100644 --- a/src/controllers/EcosystemController.js +++ b/src/controllers/EcosystemController.js @@ -25,4 +25,15 @@ router.get("/printers", async (req, res) => { } }); +// Fetch all restaurants +router.get("/restaurants", async (req, res) => { + try { + const restaurants = await EcosystemUtils.fetchAllRestaurants(); + res.status(200).json({ success: true, data: restaurants }); + } catch (error) { + console.error("Error fetching restaurants:", error.message); + res.status(500).json({ error: "Failed to fetch restaurants" }); + } +}); + export default router; diff --git a/src/data/.DS_Store b/src/data/.DS_Store new file mode 100644 index 00000000..8230c96c Binary files /dev/null and b/src/data/.DS_Store differ diff --git a/src/data/db/__pycache__/database.cpython-312.pyc b/src/data/db/__pycache__/database.cpython-312.pyc new file mode 100644 index 00000000..bdff2262 Binary files /dev/null and b/src/data/db/__pycache__/database.cpython-312.pyc differ diff --git a/src/data/db/__pycache__/models.cpython-312.pyc b/src/data/db/__pycache__/models.cpython-312.pyc new file mode 100644 index 00000000..ec7e1f0c Binary files /dev/null and b/src/data/db/__pycache__/models.cpython-312.pyc differ diff --git a/src/data/db/database.py b/src/data/db/database.py index 8ef6331f..608300a0 100644 --- a/src/data/db/database.py +++ b/src/data/db/database.py @@ -32,5 +32,18 @@ def insert_printer(location, description, latitude, longitude): VALUES (?, ?, ?, ?) ''', (location, description, latitude, longitude)) + conn.commit() + conn.close() + +def insert_restaurant(name, category, address, latitude, longitude, image_url, web_url): + """Insert a restaurant into the database.""" + conn = get_db_connection() + cursor = conn.cursor() + + cursor.execute(''' + INSERT OR IGNORE INTO restaurants (name, category, address, latitude, longitude, image_url, web_url) + VALUES (?, ?, ?, ?, ?, ?, ?) + ''', (name, category, address, latitude, longitude, image_url, web_url)) + conn.commit() conn.close() \ No newline at end of file diff --git a/src/data/db/models.py b/src/data/db/models.py index d35f9269..69567993 100644 --- a/src/data/db/models.py +++ b/src/data/db/models.py @@ -30,6 +30,19 @@ def create_tables(): ) ''') + cursor.execute(''' + CREATE TABLE IF NOT EXISTS restaurants ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT UNIQUE, + category TEXT, + address TEXT, + latitude REAL, + longitude REAL, + image_url TEXT, + web_url TEXT + ) + ''') + conn.commit() conn.close() diff --git a/src/data/scrapers/__pycache__/libraries.cpython-312.pyc b/src/data/scrapers/__pycache__/libraries.cpython-312.pyc new file mode 100644 index 00000000..3781a20b Binary files /dev/null and b/src/data/scrapers/__pycache__/libraries.cpython-312.pyc differ diff --git a/src/data/scrapers/__pycache__/printers.cpython-312.pyc b/src/data/scrapers/__pycache__/printers.cpython-312.pyc new file mode 100644 index 00000000..8a76130d Binary files /dev/null and b/src/data/scrapers/__pycache__/printers.cpython-312.pyc differ diff --git a/src/data/scrapers/__pycache__/restaurants.cpython-312.pyc b/src/data/scrapers/__pycache__/restaurants.cpython-312.pyc new file mode 100644 index 00000000..733477b7 Binary files /dev/null and b/src/data/scrapers/__pycache__/restaurants.cpython-312.pyc differ diff --git a/src/data/scrapers/libraries.py b/src/data/scrapers/libraries.py index 51a7eb84..20fe79be 100644 --- a/src/data/scrapers/libraries.py +++ b/src/data/scrapers/libraries.py @@ -1,26 +1,32 @@ -import requests +from playwright.sync_api import sync_playwright from bs4 import BeautifulSoup -# URL of the CU Print directory page -URL = "https://www.cornell.edu/about/maps/directory/?notes=Library&caption=%20Libraries" +URL = "https://www.cornell.edu/about/maps/directory/?layer=Library&sublayer=" def scrape_libraries(): - # Send a GET request to fetch the HTML content - response = requests.get(URL) - soup = BeautifulSoup(response.text, 'html.parser') + with sync_playwright() as p: + browser = p.chromium.launch(headless=True) + page = browser.new_page() + page.goto(URL, wait_until="networkidle") - # Locate the table + # Get the rendered HTML after JS loads + content = page.content() + browser.close() + + soup = BeautifulSoup(content, 'html.parser') table = soup.find("table", {"id": "directoryTable"}) - rows = table.find("tbody").find_all("tr") + if not table: + print("Could not find the table.") + return [] - # Extract data + rows = table.find("tbody").find_all("tr") data = [] for row in rows: cols = row.find_all("td") if len(cols) < 3: continue - - location_name = cols[0].text.strip().split('\n\n\n')[0] + + location_name = cols[0].text.strip() address = cols[1].text.strip() coordinates_string = cols[2].text.strip() coordinates = [float(x) for x in coordinates_string.split(', ')] @@ -30,5 +36,8 @@ def scrape_libraries(): "Address": address, "Coordinates": coordinates }) - - return data \ No newline at end of file + + return data + +if __name__ == "__main__": + scrape_libraries() \ No newline at end of file diff --git a/src/data/scrapers/printers.py b/src/data/scrapers/printers.py index e972046f..1cc7242b 100644 --- a/src/data/scrapers/printers.py +++ b/src/data/scrapers/printers.py @@ -1,37 +1,33 @@ -import requests -from bs4 import BeautifulSoup - -# URL of the CU Print directory page -URL = "https://www.cornell.edu/about/maps/directory/?layer=CUPrint&caption=%20CU%20Print%20Printers" # Replace with the actual URL +from playwright.sync_api import sync_playwright def scrape_printers(): - # Send a GET request to fetch the HTML content - response = requests.get(URL) - soup = BeautifulSoup(response.text, 'html.parser') + with sync_playwright() as p: + browser = p.chromium.launch(headless=True) + page = browser.new_page() + page.goto("https://www.cornell.edu/about/maps/directory/?layer=CUPrint") + + # Wait for the dynamic table to load + page.wait_for_selector("table#directoryTable") + + rows = page.query_selector_all("table#directoryTable > tbody > tr") + data = [] - # Locate the table - table = soup.find("table", {"id": "directoryTable"}) - rows = table.find("tbody").find_all("tr") + for row in rows: + cols = row.query_selector_all("td") + if len(cols) < 3: + continue + location = cols[0].inner_text().strip() + description = cols[1].inner_text().strip() + coordinates = [float(x.strip()) for x in cols[2].inner_text().split(",")] - # Extract data - data = [] - for row in rows: - cols = row.find_all("td") - if len(cols) < 3: # Ensure row has enough columns - continue - - location_name = cols[0].text.strip() - description = cols[1].text.strip() - - # Extract coordinates from the hyperlink tag inside