diff --git a/serverless/alpr_cache/deploy.sh b/serverless/alpr_cache/deploy.sh index de6cfe9..e3c18da 100755 --- a/serverless/alpr_cache/deploy.sh +++ b/serverless/alpr_cache/deploy.sh @@ -20,7 +20,7 @@ docker buildx build --platform linux/arm64 -t $ECR_REPO_URL:latest --load . docker push $ECR_REPO_URL:latest # update lambda function -# export AWS_PAGER="" -# aws lambda update-function-code --function-name alpr_cache --image-uri $ECR_REPO_URL:latest +export AWS_PAGER="" +aws lambda update-function-code --function-name alpr_cache --image-uri $ECR_REPO_URL:latest echo "Deployed!" diff --git a/serverless/alpr_cache/src/alpr_cache.py b/serverless/alpr_cache/src/alpr_cache.py index 9cf3b78..f4f6235 100644 --- a/serverless/alpr_cache/src/alpr_cache.py +++ b/serverless/alpr_cache/src/alpr_cache.py @@ -38,7 +38,8 @@ WHITELISTED_TAGS = [ "camera:direction", "surveillance:brand", "surveillance:operator", - "surveillance:manufacturer" + "surveillance:manufacturer", + "wikimedia_commons" ] def get_all_nodes(): diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 484a356..6630492 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -12,6 +12,7 @@ "@unhead/vue": "^1.11.14", "axios": "^1.7.7", "countup.js": "^2.8.0", + "js-md5": "^0.8.3", "leaflet.markercluster": "^1.5.3", "pinia": "^2.3.0", "vue": "^3.4.29", @@ -1594,6 +1595,12 @@ "dev": true, "license": "ISC" }, + "node_modules/js-md5": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/js-md5/-/js-md5-0.8.3.tgz", + "integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ==", + "license": "MIT" + }, "node_modules/json-parse-even-better-errors": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", diff --git a/webapp/package.json b/webapp/package.json index 935a43c..a917be8 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -16,6 +16,7 @@ "@unhead/vue": "^1.11.14", "axios": "^1.7.7", "countup.js": "^2.8.0", + "js-md5": "^0.8.3", "leaflet.markercluster": "^1.5.3", "pinia": "^2.3.0", "vue": "^3.4.29", diff --git a/webapp/src/components/DFMapPopup.vue b/webapp/src/components/DFMapPopup.vue index 6893dc9..853e0d1 100644 --- a/webapp/src/components/DFMapPopup.vue +++ b/webapp/src/components/DFMapPopup.vue @@ -2,9 +2,9 @@
- +
- {{ manufacturer }} LPR + {{ manufacturer }} {{ manufacturer.endsWith(' LPR') ? '' : ' LPR' }}
@@ -45,6 +45,7 @@
mdi-open-in-newView on OSM + mdi-imageView image
@@ -55,6 +56,7 @@ import type { PropType } from 'vue'; import type { ALPR } from '@/types'; import { VIcon, VList, VSheet, VListItem, VBtn, VImg, VListItemSubtitle, VDivider } from 'vuetify/components'; import { useVendorStore } from '@/stores/vendorStore'; +import { md5 } from 'js-md5'; const props = defineProps({ alpr: { @@ -72,11 +74,15 @@ const manufacturer = computed(() => ( )); const store = useVendorStore(); -const imageUrl = ref(undefined); +const vendorImageUrl = ref(undefined); onMounted(async () => { const url = await store.getFirstImageForManufacturer(manufacturer.value as string); - if (url) imageUrl.value = url; + if (url) vendorImageUrl.value = url; +}); + +const imageUrl = computed(() => { + return wikimediaImages.value?.thumbnail ?? vendorImageUrl.value; }); const abbreviatedOperator = computed(() => { @@ -104,6 +110,26 @@ const abbreviatedOperator = computed(() => { return operator; }); +const wikimediaImages = computed(() => { + if (!props.alpr.tags.hasOwnProperty("wikimedia_commons")) { + return; + } + const filename = props.alpr.tags["wikimedia_commons"]; + const thumbnailWidth = 300; + + const cleanFilename = filename.replace(/^File:/, '').replace(/ /g, '_'); + + const md5Hash = md5(cleanFilename); + const hashPath = `${md5Hash[0]}/${md5Hash.slice(0, 2)}`; + + const encodedFilename = encodeURIComponent(cleanFilename); + + const wiki = `https://commons.wikimedia.org/wiki/${encodeURIComponent(filename)}`; + const thumbnail = `https://upload.wikimedia.org/wikipedia/commons/thumb/${hashPath}/${encodedFilename}/${thumbnailWidth}px-${encodedFilename}`; + + return { wiki, thumbnail }; +}); + function osmNodeLink(id: string): string { return `https://www.openstreetmap.org/node/${id}`; }