Last active
April 10, 2023 20:41
-
-
Save s-nt-s/fd24c8c331ac4e6265b528550814a3c0 to your computer and use it in GitHub Desktop.
Filtrar chats de Idealista para que solo aparezcan personas con perfil relleno según nuestras necesidades
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Idealista | |
// @version 1 | |
// @include https://www.idealista.com/conversations | |
// @run-at document-end | |
// @grant none | |
// ==/UserScript== | |
function my_hack_ajax() { | |
const CHAT_URL = "/conversations/list.ajax"; | |
(function(XHR) { | |
const open = XHR.prototype.open; | |
XHR.prototype.open = function(method, url, async, user, pass) { | |
if (url.startsWith(CHAT_URL)) url = url.replace(/\bsize=\d+/, "size=200"); | |
open.call(this, method, url, async, user, pass); | |
}; | |
})(XMLHttpRequest); | |
const waitForGlobal = function(key, callback) { | |
const gvar = window[key]; | |
if (gvar == null) | |
setTimeout(waitForGlobal, 100, arguments); | |
else | |
callback.apply(gvar, Array.from(arguments).slice(2)); | |
}; | |
const gJSON = function(obj) { | |
if (typeof obj === "string") obj = { | |
dataType: "json", | |
url: obj, | |
async: false | |
} | |
return $.ajax(obj).responseJSON; | |
} | |
const dJSON = function(file, obj) { | |
const a = document.createElement("a"); | |
const b = new Blob([JSON.stringify(obj, null, 2)], { | |
'type': 'text/plain' | |
}); | |
a.href = URL.createObjectURL(b); | |
a.download = file; | |
a.click(); | |
} | |
const gChat = function(id) { | |
return gJSON({ | |
contentType: "application/json; charset=utf-8", | |
dataType: "json", | |
type: "POST", | |
url: "https://www.idealista.com/conversations/messages/summary.ajax", | |
async: false, | |
data: '{"conversationId":"' + id + '"}' | |
}).messages; | |
} | |
const addMethods = function(obj, flds) { | |
Object.entries(flds).forEach(([key, value]) => { | |
obj[key] = (function(cached, fnc) { | |
if (this[cached] == null) { | |
this[cached] = fnc.apply(this, Array.from(arguments).slice(2)); | |
} | |
return this[cached]; | |
}).bind(obj, "_" + key, value); | |
}); | |
} | |
const partition = function(array, isValid) { | |
return array.reduce(([pass, fail], elem) => { | |
return isValid(elem) ? [ | |
[...pass, elem], fail | |
] : [pass, [...fail, elem]]; | |
}, [ | |
[], | |
[] | |
]); | |
} | |
class CHAT { | |
constructor(file) { | |
this._conversations = []; | |
this._file = file; | |
} | |
get chats() { | |
return this._conversations; | |
} | |
add(chats) { | |
if (chats.conversations) chats = chats.conversations; | |
const ids = chats.map(c => c.id); | |
this._conversations = this._conversations.filter(c => !ids.includes(c.id)).concat(chats); | |
} | |
save(full) { | |
if (full) { | |
this._conversations.forEach(c => { | |
c.getMessages(); | |
c.hasMe(); | |
}); | |
} | |
dJSON(this._file, this._conversations); | |
} | |
} | |
window.DEBUG_CONVERSATIONS = { | |
"ok": new CHAT("idealista-ok.json"), | |
"ko": new CHAT("idealista-ko.json") | |
} | |
waitForGlobal( | |
"jQuery", | |
(chat_filter) => { | |
jQuery.ajaxSetup({ | |
dataFilter: function(data, type) { | |
if (type != "json") return data; | |
if (!this.url.startsWith(CHAT_URL)) return data; | |
const js = JSON.parse(data); | |
if (!js.conversations) return data; | |
/* Añadir funcionalidad al objeto */ | |
js.conversations.forEach(c => { | |
addMethods(c, { | |
getMessages: function() { | |
return gChat(this.id); | |
}, | |
hasMe: function() { | |
if (this.lastMessage && this.lastMessage.isFromMe) return true; | |
return this.getMessages().filter(m => m.fromMe).length > 0; | |
} | |
}); | |
}); | |
/* Filtrar */ | |
const [ok, ko] = partition(js.conversations, chat_filter); | |
if (ok.length != js.conversations.length) { | |
console.log("conversations", js.conversations.length, "->", ok.length); | |
js.conversations = ok; | |
data = JSON.stringify(js); | |
console.log(js); | |
} | |
window.DEBUG_CONVERSATIONS.ok.add(ok); | |
window.DEBUG_CONVERSATIONS.ko.add(ko); | |
return data; | |
} | |
}) | |
}, | |
(c) => { | |
/* Only my ads */ | |
if (c.role != "ADVERTISER") return false; | |
/* NO fraud, agency, counteroffer or empty profile */ | |
if (c.isFraudWarning) return false; | |
if (c.agencyName && c.agencyName.length) return false; | |
if (c.lastMessage && c.lastMessage.counterOffer != null) return false; | |
if (!(c.userProfilePreview && c.seekerHasUserProfile)) return false; | |
/* Only one person */ | |
const w1 = c.userProfilePreview.replace(/[, ].*$/, "").toLowerCase(); | |
if (["familia", "pareja"].includes(w1)) return false; | |
const n1 = parseInt(w1, 10); | |
if (!isNaN(n1) && n1 > 1) return false; | |
if (/con mascota/.test(c.userProfilePreview)) return false; | |
const prf = gJSON("/conversations/" + c.id + "/seeker-profile.ajax").body; | |
/* NO in Spain yet */ | |
if (prf.phone && prf.phone.prefix && prf.phone.prefix != "34") return false; | |
/* NO rent over 40% income */ | |
const rent = parseInt(c.ads[0].priceInfo.split()[0], 10); | |
if (prf.income && rent > (prf.income * 0.40)) return false; | |
return true; | |
} | |
); | |
} | |
const script = document.createElement("script"); | |
script.textContent = "(" + my_hack_ajax.toString() + ")();"; | |
document.head.appendChild(script); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment