From c3924c742ec32322fa742006051f9a60e466df51 Mon Sep 17 00:00:00 2001 From: moo <48740106+moom0o@users.noreply.github.com> Date: Tue, 27 Jun 2023 11:39:15 -0400 Subject: [PATCH] Reformat and fix domain error --- README.md | 52 ++++++--- config.json | 2 +- index.js | 17 +-- package.json | 1 + public/assets/drag-and-drop.js | 86 +++++++------- public/assets/leaflet/js/map.js | 12 +- public/assets/style.css | 201 ++++++++++++++++++-------------- views/pages/error.ejs | 4 +- views/pages/success.ejs | 4 +- views/pages/upload.ejs | 81 +++++++------ views/partials/footer.ejs | 43 +++---- views/partials/header.ejs | 30 ++--- 12 files changed, 297 insertions(+), 236 deletions(-) diff --git a/README.md b/README.md index 38fefe0..3831c7f 100644 --- a/README.md +++ b/README.md @@ -5,23 +5,29 @@ # Overview + Upload 360° photos to Google Maps without using Google's app. -The main reason why I created this is because Google Maps isn't a good replacement of the former app. You are only able to upload 360 photos to specific places on the map. With this project, it is possible to upload them at any coordinates. +The main reason why I created this is because Google Maps isn't a good replacement of the former app. You are only able +to upload 360 photos to specific places on the map. With this project, it is possible to upload them at any coordinates. If you want to try it out, there are publicly available instances: | **URL** | **Country** | **Status** | **Hosted By** | |------------------------------------------------|-------------|------------|---------------| -| [maps.moomoo.me](https://maps.moomoo.me) | 🇺🇸 | Up | @moom0o | -| [map.winscloud.net](https://map.winscloud.net) | 🇹🇭 | Up | @WinsDominoes | +| [maps.moomoo.me](https://maps.moomoo.me) | 🇺🇸 | Up | @moom0o | +| [map.winscloud.net](https://map.winscloud.net) | 🇹🇭 | Up | @WinsDominoes | ## Quick start + In order to get the Google api keys required for the oauth follow these steps: ### Client ID + 1) Create a new project at https://console.cloud.google.com/ -2) Head over to the API library and enable the Street View Publish API +2) Head over to the API library and enable + the Street View Publish + API 3) Select 'Create Credentials', select 'User Data', enter any app name/email. @@ -29,16 +35,21 @@ In order to get the Google api keys required for the oauth follow these steps: 5) Select 'Web application' for type, and name it anything. -6) Add http://localhost:7000 to authorized javascript origins. (If you are running on another domain/port, replace localhost) +6) Add http://localhost:7000 to authorized javascript origins. (If you are running on another domain/port, replace + localhost) -7) Add http://localhost:7000/auth/ to authorized redirect URIs (If you are running on another domain/port, replace localhost) +7) Add http://localhost:7000/auth/ to authorized redirect URIs (If you are running on another domain/port, replace + localhost) 8) You should now copy the Client ID into the config.json file. ### Client Secret -Head to the main credentials screen and click the pencil. (Edit OAuth Client) You will be able to find the Client Secret and copy that to your config.json. + +Head to the main credentials screen and click the pencil. (Edit OAuth Client) You will be able to find the Client Secret +and copy that to your config.json. ### Consent Screen + 1) Select 'OAuth consent screen', use any name/email 2) Make sure the authorized domain and email is correct, then select 'Save and Continue'. @@ -47,12 +58,16 @@ Head to the main credentials screen and click the pencil. (Edit OAuth Client) Yo 4) For test users, add the email address of the account where you want to upload 360 photos. -5) **Make sure to also copy the client ID into index.html**, after '&client_id=' and before '&scope', if needed, change the port and domain here as well. +5) **Make sure to also copy the client ID into index.html**, after '&client_id=' and before '&scope', if needed, change + the port and domain here as well. ### Config File -There are many options in the config file that might confuse you, so here's a simple guide (I think?) to help you get through it. -| **Keys** | **Default values** | **Usage** | +There are many options in the config file that might confuse you, so here's a simple guide (I think?) to help you get +through it. + +| **Keys** | **Default values** | ** +Usage** | |------------------|----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------| | `https` | `false` (boolean) | This is an option whether if you want to enable https or not, this uses boolean values. `false` = http:// and `true` = https:// | | `host` | `localhost` (string) | Your host or domain, if you are hosting on a local machine, set this to `localhost`, if you are hosting this publicly, set it to your domain. | @@ -61,13 +76,16 @@ There are many options in the config file that might confuse you, so here's a si | `clientId` | string | Paste your Google OAuth Client ID here, check the previous steps on how to get it. | | `clientSecret` | string | Paste your Google OAuth Client Secret ID here, check the previous steps on how to get it. | -**INFO: Your authorized JavaScript origins and authorized redirect URIs should be the same as the one you have set in your config file.** +**INFO: Your authorized JavaScript origins and authorized redirect URIs should be the same as the one you have set in +your config file.** **Scenario 1 - Public Instance** -This example is for those who are hosting a public instance, your https, host and port would look something like this. Change `maps.moomoo.me` to your domain. +This example is for those who are hosting a public instance, your https, host and port would look something like this. +Change `maps.moomoo.me` to your domain. You must use a nginx reverse proxy pointing to localhost:7000 for this to work. + ``` { "https": true, @@ -75,13 +93,16 @@ You must use a nginx reverse proxy pointing to localhost:7000 for this to work. "port": 7000 } ``` + Your **authorized JavaScript origin** would be: `https://maps.moomoo.me` Your **authorized redirect URIs** would be: `https://maps.moomoo.me/auth/` (don't forget the slash after `auth`) **Scenario 2 - Private Instance** -This example is for those who are running PhotoSphereStudio on a local machine, your https, host and port would look something like this. +This example is for those who are running PhotoSphereStudio on a local machine, your https, host and port would look +something like this. + ``` { "https": false, @@ -89,9 +110,12 @@ This example is for those who are running PhotoSphereStudio on a local machine, "port" 7000 } ``` + Your **authorized JavaScript origin** would be: `http://localhost:7000` Your **authorized redirect URIs** would be: `http://localhost:7000/auth/` (don't forget the slash after `auth`) ## Support -If you have any questions about how to set this up or about the source code, feel free to ask either **moom0o** (moo#0529 on Discord) or **WinsDominoes** (Win#7206 on Discord). + +If you have any questions about how to set this up or about the source code, feel free to ask either **moom0o** ( +moo#0529 on Discord) or **WinsDominoes** (Win#7206 on Discord). diff --git a/config.json b/config.json index 23ff039..9f7d2b6 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "https": false, - "host": "localhost", + "host": "localhost", "port": 7000, "openWebBrowser": false, "clientId": "XXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com", diff --git a/index.js b/index.js index dff9b37..7fd616a 100644 --- a/index.js +++ b/index.js @@ -6,13 +6,13 @@ const openWebBrowser = config.openWebBrowser; // Set to false if running as a se let full_url = ""; let protocol = ""; -if(config.https) { +if (config.https) { protocol = "https://" } else { protocol = "http://" } -if(port && !config.https) { +if (port && !config.https) { full_url = protocol + host + ":" + port } else { full_url = protocol + host @@ -59,11 +59,12 @@ app.use(favicon(__dirname + '/public/assets/icons/favicon.ico')); app.get('/', function (req, res) { res.render('pages/index', { full_url: full_url, - clientId: clientId + clientId: clientId, + domain: config.host }); }) -app.get('/upload', function(req, res){ +app.get('/upload', function (req, res) { res.render('pages/upload'); }) @@ -116,7 +117,7 @@ app.post('/upload', function (req, res) { }; request(options, function (error) { if (error) { - console.log(error) + console.log(error) res.status(500).render('pages/error', { errorCode: 500, @@ -175,9 +176,9 @@ app.post('/upload', function (req, res) { errorCode: JSON.parse(response.body)["error"]["code"], errorStatus: JSON.parse(response.body)["error"]["status"], errorMessage: JSON.parse(response.body)["error"]["message"], - response: JSON.stringify(JSON.parse(response.body), null, 4), + response: JSON.stringify(JSON.parse(response.body), null, 4), }); - } else { + } else { let shareLink = JSON.parse(response.body)["shareLink"] res.status(200).render('pages/success', { status: JSON.parse(response.body)["mapsPublishStatus"], @@ -205,7 +206,7 @@ app.get('/auth', function (req, res) { request(options, function (error, response) { if (error) console.log(error) && res.send("Error: Check console"); let body = JSON.parse(response.body) - if(body["error"] || !body["access_token"]){ + if (body["error"] || !body["access_token"]) { res.redirect('/') } else { res.cookie('oauth', JSON.parse(response.body)["access_token"], { diff --git a/package.json b/package.json index e673796..a4dc27f 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "body-parser": "^1.20.1", "cookie-parser": "^1.4.6", "ejs": "^3.1.9", + "exif-js": "^2.3.0", "express": "^4.18.2", "express-fileupload": "^1.4.0", "open": "^8.4.0", diff --git a/public/assets/drag-and-drop.js b/public/assets/drag-and-drop.js index 34bc209..03a0e69 100644 --- a/public/assets/drag-and-drop.js +++ b/public/assets/drag-and-drop.js @@ -1,63 +1,63 @@ function convertDMSToDD([degrees, minutes, seconds], ref) { - decimal_degrees = degrees + minutes / 60 + seconds / 3600; - if (ref == 'S' || ref == 'W') { - decimal_degrees = -decimal_degrees; - } - return decimal_degrees; + decimal_degrees = degrees + minutes / 60 + seconds / 3600; + if (ref == 'S' || ref == 'W') { + decimal_degrees = -decimal_degrees; + } + return decimal_degrees; } function readURL(input) { - if (input.files && input.files[0]) { - var reader = new FileReader(); + if (input.files && input.files[0]) { + var reader = new FileReader(); - reader.onload = function (e) { - $('.image-upload-wrap').hide(); + reader.onload = function (e) { + $('.image-upload-wrap').hide(); - $('.file-upload-image').attr('src', e.target.result); - $('.file-upload-content').show(); + $('.file-upload-image').attr('src', e.target.result); + $('.file-upload-content').show(); - $('.image-title').html(input.files[0].name); + $('.image-title').html(input.files[0].name); - var img = document.createElement('img'); - img.src = e.target.result; + var img = document.createElement('img'); + img.src = e.target.result; - // Render thumbnail. - img.onload = function () { - EXIF.getData(img, function () { - var allMetaData = EXIF.getAllTags(this); - var allMetaDataSpan = document.getElementById('allMetaDataSpan'); - // allMetaDataSpan.innerHTML = JSON.stringify(allMetaData, null, '\t'); - var lat = convertDMSToDD( - EXIF.getTag(this, 'GPSLatitude'), - EXIF.getTag(this, 'GPSLatitudeRef') - ); - var long = convertDMSToDD( - EXIF.getTag(this, 'GPSLongitude'), - EXIF.getTag(this, 'GPSLongitudeRef') - ); - $('#lat').val(lat); - $('#long').val(long); - console.log(`lat: ${lat}, long: ${long}`); - }); - }; - }; + // Render thumbnail. + img.onload = function () { + EXIF.getData(img, function () { + var allMetaData = EXIF.getAllTags(this); + var allMetaDataSpan = document.getElementById('allMetaDataSpan'); + // allMetaDataSpan.innerHTML = JSON.stringify(allMetaData, null, '\t'); + var lat = convertDMSToDD( + EXIF.getTag(this, 'GPSLatitude'), + EXIF.getTag(this, 'GPSLatitudeRef') + ); + var long = convertDMSToDD( + EXIF.getTag(this, 'GPSLongitude'), + EXIF.getTag(this, 'GPSLongitudeRef') + ); + $('#lat').val(lat); + $('#long').val(long); + console.log(`lat: ${lat}, long: ${long}`); + }); + }; + }; - reader.readAsDataURL(input.files[0]); - } else { - removeUpload(); - } + reader.readAsDataURL(input.files[0]); + } else { + removeUpload(); + } } function removeUpload() { - $('.file-upload-input').replaceWith($('.file-upload-input').clone()); - $('.file-upload-content').hide(); - $('.image-upload-wrap').show(); + $('.file-upload-input').replaceWith($('.file-upload-input').clone()); + $('.file-upload-content').hide(); + $('.image-upload-wrap').show(); } $('.image-upload-wrap').bind('dragover', function () { - $('.image-upload-wrap').addClass('image-dropping'); + $('.image-upload-wrap').addClass('image-dropping'); }); $('.image-upload-wrap').bind('dragleave', function () { - $('.image-upload-wrap').removeClass('image-dropping'); + $('.image-upload-wrap').removeClass('image-dropping'); }); diff --git a/public/assets/leaflet/js/map.js b/public/assets/leaflet/js/map.js index b4adbb8..2c7fb8c 100644 --- a/public/assets/leaflet/js/map.js +++ b/public/assets/leaflet/js/map.js @@ -8,10 +8,10 @@ var defaultIcon = L.icon({ iconUrl: '/assets/icons/marker-icon.png', shadowUrl: '/assets/icons/marker-shadow.png', }); - + // Creating a map object let map = new L.map('map', mapOptions); - + // Creating a Layer object let layer = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' @@ -25,15 +25,15 @@ map.addLayer(layer); // Marker let marker = null; -map.on('click', (event)=> { +map.on('click', (event) => { - if(marker !== null){ + if (marker !== null) { map.removeLayer(marker); } - marker = L.marker([event.latlng.lat , event.latlng.lng], {icon: defaultIcon}).addTo(map); + marker = L.marker([event.latlng.lat, event.latlng.lng], {icon: defaultIcon}).addTo(map); document.getElementById('lat').value = event.latlng.lat; document.getElementById('long').value = event.latlng.lng; - + }) diff --git a/public/assets/style.css b/public/assets/style.css index a21c4e3..28fc69b 100644 --- a/public/assets/style.css +++ b/public/assets/style.css @@ -1,139 +1,162 @@ body { - margin: 0; - padding: 0; + margin: 0; + padding: 0; } + button { - border: none; - border-radius: 2px; - padding: 12px 18px; - font-size: 16px; - text-transform: uppercase; - cursor: pointer; - color: white; - background-color: #2196f3; - box-shadow: 0 0 4px #999; - outline: none; + border: none; + border-radius: 2px; + padding: 12px 18px; + font-size: 16px; + text-transform: uppercase; + cursor: pointer; + color: white; + background-color: #2196f3; + box-shadow: 0 0 4px #999; + outline: none; } + pre { - white-space: pre-line; + white-space: pre-line; } + form, input, label, p { - color: white !important; + color: white !important; } + #icon { - max-width: 45px; - height: auto; - border-radius: 50%; + max-width: 45px; + height: auto; + border-radius: 50%; } + .column { - flex-grow: 1; - display: inline-block; + flex-grow: 1; + display: inline-block; } + /* Ripple effect */ .ripple { - background-position: center; - transition: background 0.8s; + background-position: center; + transition: background 0.8s; } + .ripple:hover { - background: #47a7f5 radial-gradient(circle, transparent 1%, #47a7f5 1%) center/15000%; + background: #47a7f5 radial-gradient(circle, transparent 1%, #47a7f5 1%) center/15000%; } + .ripple:active { - background-color: #6eb9f7; - background-size: 100%; - transition: background 0s; + background-color: #6eb9f7; + background-size: 100%; + transition: background 0s; } + /* DRAG AND DROP */ .file-upload { - width: 100%; - margin: 0 auto; + width: 100%; + margin: 0 auto; } + .file-upload-btn { - width: 100%; - margin: 0; - color: #fff; - background: #2196f3; - border: none; - padding: 10px; - border-radius: 4px; - border-bottom: 4px solid #2879f3; - transition: all .2s ease; - outline: none; - text-transform: uppercase; - font-weight: 700; + width: 100%; + margin: 0; + color: #fff; + background: #2196f3; + border: none; + padding: 10px; + border-radius: 4px; + border-bottom: 4px solid #2879f3; + transition: all .2s ease; + outline: none; + text-transform: uppercase; + font-weight: 700; } + .file-upload-btn:hover { - background: #2175f3; - color: #ffffff; - transition: all .2s ease; - cursor: pointer; + background: #2175f3; + color: #ffffff; + transition: all .2s ease; + cursor: pointer; } + .file-upload-btn:active { - border: 0; - transition: all .2s ease; + border: 0; + transition: all .2s ease; } + .file-upload-content { - display: none; - text-align: center; + display: none; + text-align: center; } + .file-upload-input { - position: absolute; - margin: 0; - padding: 0; - width: 100%; - height: 100%; - outline: none; - opacity: 0; - cursor: pointer; + position: absolute; + margin: 0; + padding: 0; + width: 100%; + height: 100%; + outline: none; + opacity: 0; + cursor: pointer; } + .image-upload-wrap { - margin-top: 20px; - border: 4px dashed #2196f3; - position: relative; + margin-top: 20px; + border: 4px dashed #2196f3; + position: relative; } + .image-dropping, .image-upload-wrap:hover { - background-color: #2196f3; - border: 4px dashed #ffffff; + background-color: #2196f3; + border: 4px dashed #ffffff; } + .image-title-wrap { - padding: 0 15px 15px 15px; - color: #222; + padding: 0 15px 15px 15px; + color: #222; } + .drag-text { - text-align: center; + text-align: center; } + .drag-text .buttonText { - font-weight: 100; - text-transform: uppercase; - color: #fff; - padding: 60px 0; + font-weight: 100; + text-transform: uppercase; + color: #fff; + padding: 60px 0; } + .file-upload-image { - max-height: 200px; - max-width: 200px; - margin: auto; - padding: 20px; + max-height: 200px; + max-width: 200px; + margin: auto; + padding: 20px; } + .remove-image { - width: 200px; - margin: 0; - color: #fff; - background: #cd4535; - border: none; - padding: 10px; - border-radius: 4px; - border-bottom: 4px solid #b02818; - transition: all .2s ease; - outline: none; - text-transform: uppercase; - font-weight: 700; + width: 200px; + margin: 0; + color: #fff; + background: #cd4535; + border: none; + padding: 10px; + border-radius: 4px; + border-bottom: 4px solid #b02818; + transition: all .2s ease; + outline: none; + text-transform: uppercase; + font-weight: 700; } + .remove-image:hover { - background: #c13b2a; - color: #ffffff; - transition: all .2s ease; - cursor: pointer; + background: #c13b2a; + color: #ffffff; + transition: all .2s ease; + cursor: pointer; } + .remove-image:active { - border: 0; - transition: all .2s ease; + border: 0; + transition: all .2s ease; } diff --git a/views/pages/error.ejs b/views/pages/error.ejs index 6b3504e..34b4aa7 100644 --- a/views/pages/error.ejs +++ b/views/pages/error.ejs @@ -13,10 +13,10 @@
- <%= errorMessage %> + <%= errorMessage %>
- +This page will allow you to upload photo spheres to Google Maps after the idiots at Google removed their perfectly working StreetView app.
- +This page will allow you to upload photo spheres to Google Maps after the idiots at Google removed + their perfectly working StreetView app.
+