automatizar-mercadolibre/static/index.html

228 lines
7.6 KiB
HTML
Raw Permalink Normal View History

2022-10-08 21:45:43 +00:00
<!doctype html>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0">
<style>
html, body {
margin: 0;
}
#files-preview {
height: 50vh;
overflow: scroll;
border: 1px solid;
}
#files-preview img {
width: 50%;
}
</style>
<fieldset>
<legend>Fotos</legend>
<input multiple type=file accept="image/*" capture=environment>
<ul id=files-preview></ul>
</fieldset>
<fieldset>
<legend>ISBN/metadatos</legend>
<div id="reader" width="1800px"></div>
<input name=isbn placeholder=ISBN>
<input name=title placeholder=Titulo>
<input name=author placeholder=Autor>
<input name=publish-year placeholder="Año publicación">
<input name=publisher placeholder=Editorial>
</fieldset>
<fieldset>
<input name=price placeholder=Precio type=number>
<button id=force-prices-preview>Buscar con titulo y autor</button>
<ul id=prices-preview></ul>
</fieldset>
<button id=go>Go!</button>
<ul id=log></ul>
<script src=html5-qrcode.min.js></script>
<script>
const goAuthorize = () =>
location.href = `https://auth.mercadolibre.com.ar/authorization?response_type=code&client_id=${CLIENT_ID}&redirect_uri=${location.protocol}//${location.host}`
const code = (new URLSearchParams(location.search)).get('code')
if (!code && !localStorage.accessToken) goAuthorize()
async function getAccessToken() {
if (localStorage.accessToken) return localStorage.accessToken
const request = await fetch("/authorize?code="+code)
const json = await request.json()
if (json.error === 'invalid_grant') {
goAuthorize()
return
}
localStorage.accessToken = json.access_token
return json.access_token
}
const $ = s => document.querySelector(s)
const filesEl = $('input[type=file]')
const filesPreviewEl = $('#files-preview')
const pricesPreviewEl = $('#prices-preview')
const logEl = $('#log')
function appendLog (msg) {
const itemEl = document.createElement('li')
itemEl.append(msg)
logEl.append(itemEl)
}
const goEl = $('#go')
const inputs = Object.fromEntries([
'isbn',
'title',
'author',
'publish-year',
'publisher',
'price',
'access-token',
].map(
name => [name, $(`input[name=${name}]`)]
))
async function onScanSuccess(decodedText, decodedResult) {
alert(`Code matched = ${decodedText}`);
inputs.isbn.value = decodedText
const bibkey = `ISBN:${decodedText}`
const request = await fetch(`https://openlibrary.org/api/books?bibkeys=${bibkey}&jscmd=details&format=json`)
const json = await request.json()
inputs.title.value = json[bibkey]?.details?.title || ''
inputs.author.value = json[bibkey]?.details?.authors[0]?.name || ''
getPricePreview()
inputs.publisher.value = json[bibkey]?.details?.publishers[0] || ''
inputs['publish-year'].value = json[bibkey]?.details?.publish_date?.match(/\d{4}/)[0] || ''
}
async function getPricePreview() {
let params = new URLSearchParams()
params.set('q', `${inputs.title.value} ${inputs.author.value} usado`)
params.set('limit', '50')
try {
const request = await fetch(`https://api.mercadolibre.com/sites/MLA/search?${params}`)
const json = await request.json()
if (!json.results) throw new Error(JSON.stringify(json))
pricesPreviewEl.innerHTML=''
for (const result of json.results) {
const itemEl = document.createElement('li')
itemEl.append(`${result.title} - ${result.condition} - ${result.price}`)
pricesPreviewEl.append(itemEl)
}
} catch (error) { alert(error) }
}
$('#force-prices-preview').addEventListener('click', getPricePreview)
function onScanFailure(error) {
console.warn(`Code scan error = ${error}`);
}
let html5QrcodeScanner = new Html5QrcodeScanner(
"reader",
{
fps: 10,
formatsToSupport: [Html5QrcodeSupportedFormats.EAN_13],
experimentalFeatures: {
useBarCodeDetectorIfSupported: true
},
rememberLastUsedCamera: true,
aspectRatio: 1.7777778
},
/* verbose= */ false)
html5QrcodeScanner.render(onScanSuccess, onScanFailure);
filesEl.addEventListener('change', async event => {
for (const file of event.target.files) {
const itemEl = document.createElement('li')
const imgEl = new Image
imgEl.src = URL.createObjectURL(file)
itemEl.append(imgEl)
const deleteBtnEl = document.createElement('button')
deleteBtnEl.append("Borrar")
deleteBtnEl.addEventListener('click', event => {
event.target.parentElement.remove()
})
itemEl.append(deleteBtnEl)
const id = await uploadImageToML(file)
imgEl.dataset.id = id
filesPreviewEl.append(itemEl)
}
})
async function uploadImageToML(file) {
const formData = new FormData
formData.set("file", file)
appendLog(`Subiendo ${file.name}`)
//https://api.mercadolibre.com proxy
const request = await fetch('/pictures/items/upload', {
method: 'POST',
headers: {
'Authorization': `Bearer ${await getAccessToken()}`,
},
body: formData,
})
const json = await request.json()
appendLog(`[${file.name}] Subido con ID ${json.id}`)
return json.id
}
// categoria Libros, Revistas y Comics: MLA3025
goEl.addEventListener('click', async event => {
try {
const imageIds = [...filesPreviewEl.querySelectorAll('img')].map(
img => img.dataset.id
)
// https://developers.mercadolibre.com.ar/es_ar/publica-productos
const publishing = {
"title":inputs.title.value,
"category_id":"MLA412445",
"price":inputs.price.value,
"currency_id":"ARS",
"available_quantity":1,
"buying_mode":"buy_it_now",
"condition":"used",
"listing_type_id":"free",
"sale_terms":[
],
"pictures": imageIds.map(id => ({id})),
"attributes":[
//https://api.mercadolibre.com/categories/MLA3025/attributes
{ "id":"BOOK_TITLE", "value_name":inputs.title.value },
{ "id":"AUTHOR", "value_name":inputs.author.value },
{ "id":"BOOK_PUBLISHER", "value_name":inputs.publisher.value },
{ "id":"GTIN", "value_name":inputs.isbn.value },
{ "id":"FORMAT", "value_name":"Fisico" },
{ "id":"ITEM_CONDITION", "value_name":"Usado" },
]
}
appendLog(`Creando publicación`)
//https://api.mercadolibre.com proxy
const request = await fetch("/items", {
method: 'POST',
headers: {
'Authorization': `Bearer ${await getAccessToken()}`,
},
body: JSON.stringify(publishing),
})
const json = await request.json()
if (!json.permalink) throw new Error(JSON.stringify(json))
location.href = json.permalink
} catch (error) {
alert(error)
}
})
</script>