Files
MarketingTool/api/__pycache__/server.cpython-313.pyc
T

115 lines
21 KiB
Plaintext
Raw Normal View History

2026-09-05 14:05:11 +02:00
ó
Tœj71ãó€•SrSSKJr SSKrSSKrSSKrSSKrSSKrSSKrSSK r SSK
J
r
J r SSK J
r
Jr SSKJr SSKJr SSKJrJrJr \R.R1S S
5rS r1S kr\R8"5rSS
jrSSjrSSjr SSjr!SSjr"SSjr#SSjr$"SS\
5r%SSjr&\'S:Xa\&"5 gg) aSmall browser-only prospect discovery service.
The service deliberately has one live source (Google in a headless browser),
keeps a local catalog for deduplication, and exposes only review actions.
There is no email scraping, outreach, CRM automation, or source registry.
é)Ú annotationsN)ÚdatetimeÚtimezone)ÚBaseHTTPRequestHandlerÚThreadingHTTPServer)ÚPath)ÚAny)Úparse_qsÚ
quote_plusÚurlparseÚ PROSPECT_DBz/data/prospects.dbé>ÚpendingÚapprovedÚrejectedÚ contactedcó€•[R"[R5R SS9R 5$)Nr)Ú microsecond)rÚnowrÚutcÚreplaceÚ isoformat©óÚ
api/server.pyrrs,€Ü �<Š<œŸ ™ Ó %× -Ñ -¸!Ð -Ð <× FÑ FÓ HÐHrcóF•[R"[RR[5=(d SSS9 [
R "[5n[
RUlURS5 URS5 UR5 U$)NÚ.T)Úexist_oka CREATE TABLE IF NOT EXISTS prospects (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
website TEXT NOT NULL,
domain TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
query TEXT NOT NULL,
discovered_at TEXT NOT NULL,
review_status TEXT NOT NULL DEFAULT 'pending',
review_notes TEXT NOT NULL DEFAULT '',
UNIQUE(domain)
)aqCREATE TABLE IF NOT EXISTS runs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
query TEXT NOT NULL,
location TEXT NOT NULL,
requested INTEGER NOT NULL,
found INTEGER NOT NULL DEFAULT 0,
added INTEGER NOT NULL DEFAULT 0,
status TEXT NOT NULL,
error TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL
)) ÚosÚmakedirsÚpathÚdirnameÚDB_PATHÚsqlite3ÚconnectÚRowÚ row_factoryÚexecuteÚcommit)Úconns rÚdbr+!sp€Ü‡K‚K”—‘—‘¤Ó(×/¨C¸$Ò?Ü �?Š?œ7Ó #€DÜ—{‘{€DÔØ‡L�Lð  ô 
ð ‡L�Lð
 ô

ð ‡K�K„MØ €KrcóJ•[R"USS9RS5$)NF)Ú ensure_asciizutf-8)ÚjsonÚdumpsÚencode)Úvalues rÚ
json_bytesr2@s€Ü �:Š:�e¨%Ñ 0× 7Ñ 7¸Ó @Ð@rcóè•[SU;aUOSU-5nUR=(d SR5R5R S5nUR S5(aUSSnU$)Nz://úhttps://Úrzwww.é)r ÚhostnameÚlowerÚstripÚrstripÚ
startswith)ÚurlÚparsedÚhosts rÚ clean_domainr?Dsc€Ü
˜U c›\‘c¨z¸CÑ/?Ó
@€FØ �O‰O× !˜r× (Ñ (Ó *× 0Ñ 0Ó 2× 9Ñ 9¸#Ó >€DØ ‡��v×ÑØ�A�BˆxˆØ €KrcóN^•UR5m[U4SjS55$)Nc3ó,># •UH oT;v• M g7f)Nr)Ú.0ÚmarkerÚlowereds €rÚ <genexpr>Úblocked.<locals>.<genexpr>Nsøé€ðò0 V˜Ö ò0ùsƒ)zunusual trafficÚ recaptchaÚcaptchazautomated queriesz
access deniedzsorry...zdetected unusual traffic)r8Úany)ÚtextrDs @rÚblockedrKLs*ø€Ø�j‰j‹l€GÜ ôñ0óó ðrc ó¦•SSKJnJn S[ U5-S-[
U5-n[RRSS5R5nSS 0nU(aXgS
'U"5nURR"S#0UD6n U RS S S S
SS.S9n
U
R5n U RS5 U R!USSS9 U R#S5 U R%S5R'5n U R)5n
[+U 5(d[+U
5(a [ S5e/nU R%S5n[-[/UR15US-55HönUR3U5nSR5UR%S5R'5=(d SR755SSnUR9S5=(d Sn[;U5nU(aU(a
US;dU(dMžUR=S5(dM¶UUVs1sHnUSiM
sn;aUR?UUUS .5 [AU5U:¼dMö O UU
RC5 U RC5 sSSS5 $![an[ S5UeSnAff=fs snf![Da NIf=f!W
RC5 O![Da Of=fU RC5 f=f!,(df  g=f![a eUan[ S!5UeSnAf[Dan[ S"5UeSnAff=f)$Nr)Úsync_playwrightÚ TimeoutErrorÚplaywright_not_installedz https://www.google.com/search?q=z&num=Ú#PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATHr5ÚheadlessTÚexecutable_pathzen-ZAÚblockii„)ÚwidthÚheight)ÚlocaleÚjava_script_enabledÚservice_workersÚviewporti˜:Údomcontentloaded)Ú
wait_untilÚtimeoutéúÚbodyÚgoogle_blockedz a:has(h3)éÚ Úh3éÈÚhref>ú
google.comú google.co.za)zhttp://r4Údomain)ÚnameÚwebsitergÚbrowser_timeoutÚ
browser_errorr)#Úplaywright.sync_apirMrNÚ ImportErrorÚ RuntimeErrorr ÚstrrÚenvironÚgetr9ÚchromiumÚlaunchÚ new_contextÚnew_pageÚset_default_timeoutÚgotoÚwait_for_timeoutÚlocatorÚ
inner_textÚcontentrKÚrangeÚminÚcountÚnthÚjoinÚsplitÚ
get_attributer?r;ÚappendÚlenÚcloseÚ Exception)ÚqueryÚ requestedrMÚPlaywrightTimeoutÚexcr<Ú
executableÚoptionsÚpÚbrowserÚcontextÚpager^ÚhtmlÚoutputÚanchorsÚiÚanchorÚtitlerdrgÚitems rÚ
google_searchr˜Tsÿ€ð@ßZð -¬z¸%Ó/@Ñ
@À7Ñ
JÌSÐQZË^Ñ
[€CÜ—‘—‘Ð EÀrÓJ×PÑPÓR€JØ)¨4Ð0€GÞØ%/Ð!Ñ"ð-5Ù
Ô
 !Ø—j‘j×'Ò'Ñ2¨'Ñ2ˆGð$
Ø!×-Ñ-Ø"Ø(,Ø$+Ø'+°sÑ;ð .ð�ð ×'Ñ'Ó)�Ø×(Ñ(¨Ô/Ø— ‘ ˜#Ð*<Àe� ÑLØ×%Ñ% cÔ*Ø—|‘| FÓ+×6Ñ6Ó8�Ø—|‘|“~�ܘ4—=‘=¤G¨D§M¡MÜ&Ð'7Ó8Ð8Ø/1�ØŸ,™, {Ó3�Üœs 7§=¡=£?°IÀ±MÓBÖC�AØ$Ÿ[™[¨›^�FØŸH™H f§n¡n°TÓ&:×&EÑ&EÓ&G×&MÈ2×%TÑ%TÓ%VÓWÐX\ÐY\Ð]�EØ!×/Ñ/°Ó7×=¸2�DÜ)¨$Ó/�FÞ ®°Ð:XÓ0XÖ`fÙ ØŸ?™?Ð+B×CÑCÙ ØÁÓ%H¸ d¨8¤nÁÑ%HÓHØŸ
™
¨uÀÐQWÑ&XÔYܘ6“{ iÕ/ÙñDððØ—M‘M”Oð—
‘
”÷MÑ
øô ó@ÜÐ5Ó6¸CÐ?ûð@üòH&Iøô!óÙðûðØ—M‘M•OøÜ óÙðúà—
‘
•ú÷MÕ
ûôN óØ
Ø ó7ÜÐ,Ó-°3Ð6ûÜ ó5ܘ?Ó+°Ð4ûð5úsÌ‚JÁ%LÁ,LÂ
F&KÈ0J9
È?(KÉ+KÉ1J>ÊLÊ LÊ
J6Ê% J1Ê1J6Ê9KÊ>
K ËLË
K Ë LËLËK!Ë LË!
K. Ë+LË-K. Ë.LÌLÌ
LÌLÌLÌMÌ& L2Ì2
MÌ? M Í Mc ó
•[URSS55R5n[URSS55R5n[URSS55R5=(d SnU(aU(d [S5e[ S[ [ [URSS 5555nUS US U3R5n[ [5nURS XcUS
[545nURn UR5 [Xd5n
Sn U
H2n URSU SU SU SSU[545 U S-
n M4 URS[%U
5X¹45 UR5 U SU[%U
5XºS.UR'5 sSSS5 $![[4an[S
5UeSnAff=f![ R"a MÈf=f![(aAn[U5SSn
URSXÙ45 UR5 [+U
5eSnAff=f!UR'5 f=f!,(df  g=f)NÚcategoryr5ÚkeywordsÚlocationz South AfricaÚcategory_and_keywords_requiredéÚ max_resultsé
Úinvalid_max_resultsrazNINSERT INTO runs(query,location,requested,status,created_at) VALUES(?,?,?,?,?)Úrunningrz^INSERT INTO prospects(name,website,domain,description,query,discovered_at) VALUES(?,?,?,?,?,?)rhrirgzGoogle search resultz=UPDATE runs SET found=?,added=?,status='succeeded' WHERE id=?Ú succeeded)ÚidÚstatusr‡ÚfoundÚaddedÚresultséxz2UPDATE runs SET status='failed',error=? WHERE id=?)rorqr9Ú
ValueErrorÚmaxr}Ú MAX_RESULTSÚintÚ TypeErrorÚ_discover_lockr+r(rÚ lastrowidr)r˜r$ÚIntegrityErrorr„r…r†rn)Úpayloadršr›rœrˆrŠr‡r*ÚcurÚrun_idr¨r§r—Úerrors rÚ
run_discoveryr¶Žsš€Ü�7—;‘;˜z¨2Ó.Ó/×5Ñ5Ó7€HÜ�7—;‘;˜z¨2Ó.Ó/×5Ñ5Ó7€HÜ�7—;‘;˜z¨>Ó:Ó;×AÑAÓC×UÀ~€HÞ ž8ÜÐ9Ó:Ð:ð9ܘœ3œ{¬C°· ± ¸MÈ2Ó0NÓ,OÓPÓQˆ ðˆj˜˜(˜ 1 X JÐ /× 5Ñ 5Ó 7€EÞ Ü‹tˆØ�l‰lÐkÐnsð@IðKTôVYóV[ðn\ó]ˆØ—‘ˆØ � ‰ Œ
ð Ü# EÓ5ˆG؈EÛ�ðØ—L‘Lð"BðEIðJPñEQðSWðXañSbðdhðiqñdrðtJðLQôSVóSXðDYôZؘQ‘J’Eñ ð
�L‰LÐXÔ[^Ð_fÓ[gÐinÐZwÔ xØ �K‰KŒMØ ¨KÀ%ÔRUÐV]ÓR^ÐinñDð
�J‰JŒL÷/
‰øô
”zÐ "ó9ÜÐ.Ó/°SÐ8ûð9ûô×-Ñ-óÚðûô
ó &ܘ“H˜T˜c�NˆEØ �L‰LÐMÐPUÈÔ _Ø �K‰KŒMܘuÓ%Ð %ûð  &ûð
�J‰J�Lú÷/
�úszÂ3GÃ0AI4Ä6HÅ .G6Å7AHÆ8I4ÇG3Ç" G.Ç.G3Ç6HÈ
HÈ
HÈHÈ
IÈ<IÉIÉIÉI1É1I4É4
JcóT•\rSrSrSrS SjrS SjrS