feat: added the ability for linkedin

This commit is contained in:
Andre Henriques 2024-10-03 14:10:09 +01:00
parent aa461e65a2
commit fb6f1b35fd
4 changed files with 90 additions and 76 deletions

View File

@ -2,10 +2,8 @@ package com.andr3h3nriqu3s.applications
import java.sql.ResultSet import java.sql.ResultSet
import java.util.UUID import java.util.UUID
import kotlin.collections.setOf
import kotlin.collections.emptyList import kotlin.collections.emptyList
import okhttp3.OkHttpClient import kotlin.collections.setOf
import okhttp3.Request
import org.springframework.http.MediaType import org.springframework.http.MediaType
import org.springframework.jdbc.core.JdbcTemplate import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.core.RowMapper import org.springframework.jdbc.core.RowMapper
@ -69,7 +67,12 @@ data class FlairRequest(val id: String, val text: String)
data class UpdateUrl(val id: String, val url: String) data class UpdateUrl(val id: String, val url: String)
data class CVData(val company: String, val recruiter: String, val message: String, val flairs: List<SimpleFlair>) data class CVData(
val company: String,
val recruiter: String,
val message: String,
val flairs: List<SimpleFlair>
)
@RestController @RestController
@ControllerAdvice @ControllerAdvice
@ -82,23 +85,20 @@ class ApplicationsController(
) { ) {
@GetMapping(path = ["/cv/{id}"], produces = [MediaType.APPLICATION_JSON_VALUE]) @GetMapping(path = ["/cv/{id}"], produces = [MediaType.APPLICATION_JSON_VALUE])
public fun getCV( public fun getCV(@PathVariable id: String, @RequestHeader("token") token: String?): CVData? {
@PathVariable id: String, val user = sessionService.verifyToken(token)
@RequestHeader("token") token: String?
): CVData? {
val user = sessionService.verifyToken(token);
val application = applicationService.findApplicationByIdNoUser(id); val application = applicationService.findApplicationByIdNoUser(id)
if (application == null) return null; if (application == null) return null
if (user == null) { if (user == null) {
viewService.create(application.id) viewService.create(application.id)
} }
val flairs = application.flairs.map {it.toFlairSimple()}; val flairs = application.flairs.map { it.toFlairSimple() }
return CVData(application.company, application.recruiter, application.message, flairs); return CVData(application.company, application.recruiter, application.message, flairs)
} }
@PostMapping(path = ["/text"], produces = [MediaType.APPLICATION_JSON_VALUE]) @PostMapping(path = ["/text"], produces = [MediaType.APPLICATION_JSON_VALUE])
@ -144,7 +144,15 @@ class ApplicationsController(
print(urls.size) print(urls.size)
print(" links\n") print(" links\n")
urls = urls.filter { predicate -> predicate.contains("jobListing") } // jobListing is for glassdoor urls
// jobs/view is for linkeding urls
urls =
urls.filter { predicate ->
print("url: ")
print(predicate)
print("\n")
predicate.contains("jobListing") || predicate.contains("jobs/view")
}
print("found fileted: ") print("found fileted: ")
print(urls.size) print(urls.size)
@ -156,56 +164,13 @@ class ApplicationsController(
print(urls.size) print(urls.size)
print(" links\n") print(" links\n")
var client = OkHttpClient()
var applications = var applications =
urls.map { elm -> urls.map { elm ->
var request =
Request.Builder()
.url(elm)
.header(
"User-Agent",
"Mozilla/5.0 (X11; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0"
)
.addHeader(
"Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"
)
.addHeader(
"Cookie",
"gdId=aafdcb86-c37d-4bfd-8d84-4a07f11dbfc2; AWSALB=Qj3Rvldo90lFQhsChPHFXcGlVxdaZOEwr1ZP4d+whxBTlXCprKj+utUCz4DHXoC6fFrewDdFdRCPBbM0v2WQQdY4URUD4lYXd0GsBEWS/5AzZX0i9yk4C7Cfz5xA; AWSALBCORS=Qj3Rvldo90lFQhsChPHFXcGlVxdaZOEwr1ZP4d+whxBTlXCprKj+utUCz4DHXoC6fFrewDdFdRCPBbM0v2WQQdY4URUD4lYXd0GsBEWS/5AzZX0i9yk4C7Cfz5xA; indeedCtk=1i17t757dk2mo801; at=Sf_nQa0d6HxrGoYn305KELOfsWT0o-KrKdraenJrTJMqApEH4LO70x3i0oOafGWes13u8kOSq8PzPD1pZAxAVOEz0hrNnOhRnLGl3Ako4I-CYx_oCB_YhFe7M-do__yNC-ipCVlbzUujwQzCW83mKFLMHk9N12RSjhzsPEQi6Xw4n66wvXSttDChGCpY-BMSn862U-OQ9gnNzy3j214vctizTPC3g2Ig7Qysg3AY7lo-HPkHaq9fojbituLfbtgtpkCDtWAwR2-3XCWu6d2H_gk7ZWn6CH1FgLf640fd1Kep7K3kArceNq046PEalzHnJMLPSnvusS_jJatdk-x4k2rxF1FJvK0MLkPiKr39V8i7J27uOMwFLRD-49EoJUOZzTxQ1wb3lyt503NuwPhYolRGr3Xla2b6wyzYRSk2e-RHHElzvCn-FlWXaTQqEiZXKEjAGihlagUz8HFmY6bRf0FLCKvA26oVjT1vEoICmn32FOHr9M65YDllTbgHj3dDeTUczzxf_nrDSyide_UL08LsZIYJAtyueUSBqvqq49WlKemvhyKBMUloNP68A_MfT5suKPasvQu-n_ZvXahY7O5KbgtIR0QVnSimFC8yaVy8Sqjo5cq2f1VnZ6kxXj9frSK-v_jz1J7hobOAo8Mlfy_EfzBDV_3nywqjT1pKgzRRmHcNLnj_cn2rPga3NUjxpYzl485eevPDv9Gj62qAMHh1w5S6v1QkSBmgaSyKpBKYD1zD86JLJ6Upf0bVM8WcHv9u33GuKX0CgC_P-P3189AgLgtISr-2NuIaNTkKMxenagCvri6oGLj6OYMD6nO9JQ_jKUqS6ShRMhDD9K1bSUE42c2_ePhBDLWFyb3AZiJvVjcL1v1k1dO93jCn7XUQZkE7x7m1QeGC0f_5OK1IZeGuJn8Jsx-u2EvT7DNSV0LNY1hfIXauy9KCLFdTeoqDuGSumi81cg; uc=8013A8318C98C5171B57B9070099BAD115C8BBA5C5A6DB94DFFE7C86F37B699E2B54A4621F700A694011D5B5CA447CCC87B1BAC35D51A1AA5B5FF13CBDC5343400624A80C8E3C3A1966ED67EBC62D473CD7C57C9E6D138AD745B36C8625AD88EA13CE3458B51AD202B52198961B4D49007278A9385005B27B951F0F7091D61DCBBD54D21C8CFBCAD7AABEF4EA398F978; trs=direct:direct:direct:2024-06-25+07%3A59%3A23.686:undefined:undefined; cf_clearance=IZpDoUoDUUNidzYbSZRoIq6S93FXgL7hmz6.PdfEiUM-1720205316-1.0.1.1-tNL38ZNHbQw9XbL3J9g4oL4aHwiAoXXuYdOb4Xi8Z3B4yWKOuL31FrrPrqPRcxVUV7BNEdlqSMaNF3k8q.Tv0A; rl_session=RudderEncrypt%3AU2FsdGVkX19OL1VCjdlEuacjPBxOQ%2FsqFNPp5d9Dke5bKES7onFGAEFzkA4iuW3rfqQ8v2sfoX19gn7Zm3Qd83i6PWHRHESeelsza78DN%2B2U7IwWQEiyEeptsuZyTPhHxb5ALLCzUhgHcvnsh3GhQw%3D%3D; rl_user_id=RudderEncrypt%3AU2FsdGVkX19%2BQEGQCkE9Cg3Ikh5t8h65RqO0N24wvgA%3D; rl_trait=RudderEncrypt%3AU2FsdGVkX1%2B1EoAGj4RTTyGWbZRPkyuua9oOW4YQPaE%3D; rl_group_id=RudderEncrypt%3AU2FsdGVkX18STRtzoe4K%2FzJKt8zfNqQwMj7KTzQDhfQ%3D; rl_group_trait=RudderEncrypt%3AU2FsdGVkX1%2B5Kbrex9bI6O0Gr524R6IRASVZGgrWNco%3D; rl_anonymous_id=RudderEncrypt%3AU2FsdGVkX19X88n4GXRAtkOTDXcuHojO%2BetO8p7n37y2YLe6nWW5P87Stu9l86nJ4zGDs7e8D5MEUPW6KrCywQ%3D%3D; rl_page_init_referrer=RudderEncrypt%3AU2FsdGVkX19MgsL8FFX%2BSjRpwcg0nu4XxNDvIPdg2WGEivR2%2BsH1%2BqAvvlaEZmiQ; rl_page_init_referring_domain=RudderEncrypt%3AU2FsdGVkX18kgmzvlkMRtIo%2BzqUQ%2FVRfcuCvngKkmV8qAgqKAKraZOr9Qpqc6loH; _cfuvid=ezdGXFBaF3Eh.jiKZrHkmaV7GItIbZ4qPUy7gOyHgns-1720604124536-0.0.1.1-604800000; gdGPCset=true; _urc=293647244; AFSID=MTQ3YTQxNzEtZmYwMC00N2Y0LWJiOGMtNzVjMmRjZWM5MTQ4; gdsid=1720604123405:1720637554591:4466F8BAFD3D2D34B6058423B0F90392; JSESSIONID=BA9AA08792C5E981A69CF079E7A91B35; GSESSIONID=undefined; cass=0; asst=1720637634.1; __cf_bm=6b1QlZvq2zEE.Cqvcg0g2a0OiPObgL0IKFr.vZwZSwQ-1720637555-1.0.1.1-qaRfjwA.xRIpqzfJiksMvc_hWVvVnfGJ1YnRToNwK.m3Od0BXKUvOVnvhrpiR9bP311eCdI.EAYQZvKpwD7KHQ; bs=oiDddWzpeaDeES0KI7rnsQ:NDp0g4i9mXeF0vvvvYq2Ud_auNQosyTqd2NVCprviXG0nOGhPzqbVJa16DxpiFQkIluzbbDJqHLht66Dwrqn4yi7u_FvaGOojP_y91QEUZU:Hex7BRo2zXhuIdlGhiQR8uO5nGn2VCjpx6dF2aJPIxk"
)
.addHeader("Accept-Language", "en-US,en;q=0.7,pt;q=0.3")
.addHeader("Accept-Encoding", "gzip, deflate, br, zstd")
.addHeader("Connection", "keep-alive")
.build()
var new_url: String =
client.newCall(request).execute().use { response ->
print("response:")
print(response)
print("\n")
response.request.url.toString()
}
var unique: String? = new_url!!.split("?")[0]
var original_url: String? = elm
if (new_url == elm) {
original_url = null
unique = null
}
Thread.sleep(2000)
print("Got new url!\n")
Application( Application(
UUID.randomUUID().toString(), UUID.randomUUID().toString(),
new_url, if (elm.contains("linkedin")) elm.split("?")[0] else elm,
original_url, if (elm.contains("linkedin")) elm.split("?")[0] else null,
unique, if (elm.contains("linkedin")) elm.split("?")[0] else null,
"New Aplication", "New Aplication",
user.id, user.id,
"", "",
@ -419,7 +384,11 @@ class ApplicationsController(
} }
@Service @Service
class ApplicationService(val db: JdbcTemplate, val flairService: FlairService, val viewService: ViewService) { class ApplicationService(
val db: JdbcTemplate,
val flairService: FlairService,
val viewService: ViewService
) {
public fun findApplicationByUrl(user: UserDb, url: String, unique_url: String?): Application? { public fun findApplicationByUrl(user: UserDb, url: String, unique_url: String?): Application? {
if (unique_url != null) { if (unique_url != null) {
@ -473,7 +442,8 @@ class ApplicationService(val db: JdbcTemplate, val flairService: FlairService, v
} }
public fun findApplicationByIdNoUser(id: String): Application? { public fun findApplicationByIdNoUser(id: String): Application? {
var applications = db.query("select * from applications where id=?", arrayOf(id), Application).toList() var applications =
db.query("select * from applications where id=?", arrayOf(id), Application).toList()
if (applications.size == 0) { if (applications.size == 0) {
return null return null

View File

@ -29,6 +29,15 @@ browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
browser.tabs.sendMessage(a, message); browser.tabs.sendMessage(a, message);
}); });
return; return;
}
if (message.type === "R_GET_DATA_FROM_PAGE") {
let windowList = (await browser.storage.local.get("windows")).windows ?? [];
if (windowList.length !== 1) return;
const tab = await browser.tabs.get(windowList[0]);
browser.tabs.sendMessage(tab.id, {
type: "GET_DATA_FROM_PAGE",
});
return;
} }
if (message.type !== "MY_GET_URL") return; if (message.type !== "MY_GET_URL") return;

View File

@ -2,6 +2,21 @@ browser.runtime.onMessage.addListener((message) => {
if (message.type === "MY_GET_URL_R") { if (message.type === "MY_GET_URL_R") {
window.postMessage(message); window.postMessage(message);
} else if (message.type === "GET_DATA_FROM_PAGE") { } else if (message.type === "GET_DATA_FROM_PAGE") {
// Parse things for linkedin
if (window.location.host.includes("linkedin")) {
if (window.location.host.includes("merchantpool1")) {
return;
}
const jobTitle = document.querySelector('h1').textContent;
const company = document.querySelector('.relative a[target="_self"]').textContent;
const money = document.querySelector('ul li div div div li-icon[type="job"]')?.parentNode?.parentNode?.parentNode?.parentNode?.children[1]?.children[0]?.textContent?.replaceAll(/\s{2,}/g, '') ?? '';
const description = document.querySelector('article').textContent;
browser.runtime.sendMessage({ type: "GOT_INFO_R", company, jobTitle, money, description });
return;
}
// Ignore everything that is no glassdoor
if (!window.location.host.includes("glassdoor")) return;
const company = document.querySelector('header[data-test="job-details-header"]') const company = document.querySelector('header[data-test="job-details-header"]')
.children[0].children[0].querySelector("h4").innerHTML; .children[0].children[0].querySelector("h4").innerHTML;
const jobTitle = document const jobTitle = document
@ -30,5 +45,7 @@ window.addEventListener("message", (e) => {
window.postMessage({ type: "HAS_EXTENSION" }); window.postMessage({ type: "HAS_EXTENSION" });
} else if (e.data.type === "REGISTER_INTEREST") { } else if (e.data.type === "REGISTER_INTEREST") {
browser.runtime.sendMessage({ type: "REGISTER_INTEREST" }); browser.runtime.sendMessage({ type: "REGISTER_INTEREST" });
} else if (e.data.type === "R_GET_DATA_FROM_PAGE") {
browser.runtime.sendMessage({ type: "R_GET_DATA_FROM_PAGE" });
} }
}); });

View File

@ -20,6 +20,7 @@
let changeUrl: HTMLDialogElement; let changeUrl: HTMLDialogElement;
let lastExtData: any = $state(undefined); let lastExtData: any = $state(undefined);
let autoExtData = false;
async function activate(item?: Application) { async function activate(item?: Application) {
if (!item) { if (!item) {
@ -61,6 +62,7 @@
} }
applicationStore.loadApplications(true); applicationStore.loadApplications(true);
autoExtData = false;
lastExtData = undefined; lastExtData = undefined;
} }
@ -101,6 +103,11 @@
function onMessage(e: MessageEvent) { function onMessage(e: MessageEvent) {
if (e.data.type === 'GOT_INFO_R') { if (e.data.type === 'GOT_INFO_R') {
lastExtData = e.data; lastExtData = e.data;
if (autoExtData) {
window.requestAnimationFrame(() => {
setExtData();
});
}
} }
} }
@ -126,12 +133,11 @@
} }
await post('application/text/flair', { await post('application/text/flair', {
id: activeItem?.id ?? '', id: activeItem?.id ?? '',
text: lastExtData.description, text: lastExtData.description
}); });
loadActive(); loadActive();
lastExtData = undefined; lastExtData = undefined;
}); });
}); });
} }
@ -341,6 +347,16 @@
</button> </button>
{#if lastExtData !== undefined} {#if lastExtData !== undefined}
<button class="btn-primary" onclick={() => setExtData()}> Ext Data </button> <button class="btn-primary" onclick={() => setExtData()}> Ext Data </button>
{:else}
<button
class="btn-primary"
onclick={() => {
autoExtData = true;
window.postMessage({ type: 'R_GET_DATA_FROM_PAGE' });
}}
>
Get Ext Data
</button>
{/if} {/if}
{#if activeItem.original_url == null} {#if activeItem.original_url == null}
<button class="btn-primary" onclick={() => changeUrl.showModal()}> <button class="btn-primary" onclick={() => changeUrl.showModal()}>
@ -353,7 +369,9 @@
</div> </div>
</div> </div>
{#if applicationStore.dragging} {#if applicationStore.dragging}
<div class="flex w-full flex-grow rounded-lg p-3 gap-2 absolute bottom-0 left-0 right-0 bg-white"> <div
class="flex w-full flex-grow rounded-lg p-3 gap-2 absolute bottom-0 left-0 right-0 bg-white"
>
<!-- Do nothing --> <!-- Do nothing -->
<DropZone <DropZone
icon="box-arrow-down" icon="box-arrow-down"