Files
DomGod/app/__pycache__/db.cpython-311.pyc

267 lines
28 KiB
Plaintext
Raw Normal View History

fix: AI worker crash-proof + GDPR/hosting/accessibility analysis AI worker fixes (root cause of "nothing reaches Replicate"): - Worker task died silently — no exception handler around while loop - Added try/except around entire loop body with exc_info logging - Added watchdog task that restarts dead workers every 10 seconds - ensure_workers_alive() called on every /api/ai/assess/batch POST - _assess_one() is now a top-level function (not closure) — avoids subtle scoping bugs with async inner functions in while loops - /api/ai/debug endpoint: shows worker alive status, task exception, last 10 queue entries — browse to /api/ai/debug to diagnose - /api/ai/worker/restart endpoint + UI button - "Restart AI worker" button + "Debug AI queue" link in enrichment tab site_analyzer.py — new signals: - IP resolution + ip-api.com for ASN, org, ISP, host country - EU hosting detection (27 EU + EEA + adequacy countries) - GDPR: detects Cookiebot, OneTrust, CookiePro, Osano, Iubenda, Borlabs, CookieYes, Complianz, Usercentrics + text signals - Privacy policy and GDPR text presence - Accessibility: html lang missing, images without alt count, skip nav link, empty links, inputs without labels Gemini prompt additions: - Hosting section: IP, ASN, org/ISP, EU vs non-EU flag - GDPR section: cookie tool, notice, privacy policy - Accessibility section: all quick-scan results - New output fields: hosting_notes, gdpr_compliance, accessibility_issues[] Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 18:01:34 +02:00
<EFBFBD>
Q<0F>i <<00><00><><00>UddlZddlZddlZddlZddlZddlmZeje<08><00>Z eej
dd<04><00><00><00>Z e dz Z e dz Z e dz ZdZgd <09>Zd
ad
adagaeed <daeed <d <0A>Zd<0E>Zd<0F>Zdefd<11>Zd<12>Zd"d<15>Zde eeffd<16>Z!d<17>Z"d#d<18>Z#dee$fd<1A>Z%d<1B>Z&d$de$dedefd<1F>Z'dee$fd <20>Z(d!<21>Z)dS)%<25>N)<01>Path<74>DATA_DIRz/datazdomains.parquetzdomains.duckdbz enrichment.dba<62>
CREATE TABLE IF NOT EXISTS enriched_domains (
domain TEXT PRIMARY KEY,
is_live INTEGER DEFAULT 0,
status_code INTEGER,
ssl_valid INTEGER DEFAULT 0,
ssl_expiry_days INTEGER,
cms TEXT,
has_mx INTEGER DEFAULT 0,
ip_country TEXT,
page_title TEXT,
server TEXT,
enriched_at TEXT,
error TEXT,
score INTEGER DEFAULT 0,
kit_digital INTEGER DEFAULT 0,
kit_digital_signals TEXT,
contact_info TEXT,
ai_assessment TEXT,
ai_lead_quality TEXT,
ai_pitch TEXT,
ai_contact_channel TEXT,
ai_contact_value TEXT,
ai_assessed_at TEXT,
site_analysis TEXT
);
CREATE TABLE IF NOT EXISTS job_queue (
id INTEGER PRIMARY KEY AUTOINCREMENT,
domain TEXT UNIQUE NOT NULL,
status TEXT DEFAULT 'pending',
created_at TEXT DEFAULT (datetime('now')),
started_at TEXT,
completed_at TEXT,
error TEXT
);
CREATE TABLE IF NOT EXISTS ai_queue (
domain TEXT PRIMARY KEY,
status TEXT DEFAULT 'pending',
created_at TEXT DEFAULT (datetime('now')),
completed_at TEXT,
error TEXT
);
CREATE TABLE IF NOT EXISTS scores (
domain TEXT PRIMARY KEY,
score INTEGER NOT NULL,
scored_at TEXT DEFAULT (datetime('now'))
);
) zEALTER TABLE enriched_domains ADD COLUMN kit_digital INTEGER DEFAULT 0z@ALTER TABLE enriched_domains ADD COLUMN kit_digital_signals TEXTz9ALTER TABLE enriched_domains ADD COLUMN contact_info TEXTz:ALTER TABLE enriched_domains ADD COLUMN ai_assessment TEXTz<ALTER TABLE enriched_domains ADD COLUMN ai_lead_quality TEXTz5ALTER TABLE enriched_domains ADD COLUMN ai_pitch TEXTz?ALTER TABLE enriched_domains ADD COLUMN ai_contact_channel TEXTz=ALTER TABLE enriched_domains ADD COLUMN ai_contact_value TEXTz;ALTER TABLE enriched_domains ADD COLUMN ai_assessed_at TEXTz:ALTER TABLE enriched_domains ADD COLUMN site_analysis TEXTz<54>CREATE TABLE IF NOT EXISTS ai_queue (domain TEXT PRIMARY KEY, status TEXT DEFAULT 'pending', created_at TEXT DEFAULT (datetime('now')), completed_at TEXT, error TEXT)F<>
_tld_cache<EFBFBD> _total_cachec<00><00>rK<00>tjt<00><00>4<00>d{V<00><03>}|<00>t<00><00><00>d{V<00><03>t
D].} |<00>|<01><00><00>d{V<00><03><00>#t$rY<00>+wxYw|<00><00><00><00>d{V<00><03>ddd<00><00><00>d{V<00><03>dS#1<00>d{V<00><03>swxYwYdS<00>N) <09> aiosqlite<74>connect<63> SQLITE_PATH<54> executescript<70>SCHEMA<4D> _MIGRATIONS<4E>execute<74> Exception<6F>commit)<02>db<64>sqls <20>#/home/malin/c0ding/DomGod/app/db.py<70>init_dbrYsq<00><00><00><00><18> <20><1B>-<2D>-<2D><1A><1A><1A><1A><1A><1A><1A><12><10><1E><1E>v<EFBFBD>&<26>&<26>&<26>&<26>&<26>&<26>&<26>&<26>&<26><1E> <15> <15>C<EFBFBD> <15><18>j<EFBFBD>j<EFBFBD><13>o<EFBFBD>o<EFBFBD>%<25>%<25>%<25>%<25>%<25>%<25>%<25>%<25><><1C> <15> <15> <15><14><04> <15><><EFBFBD><EFBFBD><10>i<EFBFBD>i<EFBFBD>k<EFBFBD>k<EFBFBD><19><19><19><19><19><19><19><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><><EFBFBD><EFBFBD><1A><1A><1A><1A><1A>s5<00>*B&<03> A)<04>(B&<03>)
A6<07>3B&<03>5A6<07>6B&<03>&
B0<07>3B0c<00><><00>da tjtt<00><00><00><00>}|<00>d<02><00>|<00>d<03><00> |<00>d<04><00><00><00><00>d}|dkr:|adadat<00>
d|<01><00>|<00> <00><00> dadSn#t$rYnwxYwt<00>
d<08><00>|<00>d tt<00><00>g<01><00>|<00>d
<EFBFBD><00>|<00>d<04><00><00><00><00>da|<00> <00><00>dat<00>
d t<00><00>n2#t$r%}t<00>d |<02><00>Yd}~nd}~wwxYwdadS#dawxYw) NT<4E> SET threads=4zSET memory_limit='2GB'<27>SELECT COUNT(*) FROM domainsrFz$DuckDB index already ready (%d rows)z9Building DuckDB index from parquet (one-time ~2-3 min)...a
CREATE OR REPLACE TABLE domains AS
SELECT
domain,
lower(regexp_extract(domain, '\.([^.]+)$', 1)) AS tld,
len(string_split(domain, '.')) AS parts
FROM read_parquet(?)
z2CREATE INDEX IF NOT EXISTS idx_tld ON domains(tld)zDuckDB index built: %d rowszDuckDB index build failed: %s)<0F>_index_building<6E>duckdbr
<00>str<74> DUCKDB_PATHr<00>fetchone<6E> _index_total<61> _index_ready<64>logger<65>info<66>closer<00> PARQUET_PATH<54>error)<03>conn<6E>n<>es r<00>_build_index_syncr(gs<><00><00><1A>O<EFBFBD># <20><15>~<7E>c<EFBFBD>+<2B>.<2E>.<2E>/<2F>/<2F><04> <0C> <0C> <0C>_<EFBFBD>%<25>%<25>%<25> <0C> <0C> <0C>-<2D>.<2E>.<2E>.<2E>
<11><14> <0C> <0C>;<3B><<3C><<3C>E<>E<>G<>G<><01>J<>A<EFBFBD><10>1<EFBFBD>u<EFBFBD>u<EFBFBD> <20> <0C>#<23> <0C>"'<27><0F><16> <0B> <0B>B<>A<EFBFBD>F<>F<>F<><14>
<EFBFBD>
<EFBFBD> <0C> <0C> <0C><16>* <20><0F><0F><0F>7<15><><19> <11> <11> <11> <10>D<EFBFBD> <11><><EFBFBD><EFBFBD> <0F> <0B> <0B>O<>P<>P<>P<> <0C> <0C> <0C> <0C><12>,<2C><1F><1F> <20> "<22> "<22> "<22> <0A> <0C> <0C>I<>J<>J<>J<><1B>|<7C>|<7C>$B<>C<>C<>L<>L<>N<>N<>q<EFBFBD>Q<> <0C> <0C>
<EFBFBD>
<EFBFBD> <0C> <0C> <0C><1B> <0C><0E> <0B> <0B>1<><<3C>@<40>@<40>@<40>@<40><> <14>9<>9<>9<><0E> <0C> <0C>4<>a<EFBFBD>8<>8<>8<>8<>8<>8<>8<>8<><38><EFBFBD><EFBFBD><EFBFBD>9<><39><EFBFBD><EFBFBD> <20><0F><0F><0F><>%<25><0F><1F><1F><1F>sV<00>AF<00>A(C<00>F<00>
C<03> F<00>C<03>B>F<00>G<00>
F><03>F9<03>4G<00>9F><03>>G<00>G c<00><00>rK<00>tj<00><00>}|<00>dt<00><00><00>d{V<00><03>dSr)<04>asyncio<69>get_event_loop<6F>run_in_executorr()<01>loops r<00>build_duckdb_indexr.<00>sC<00><00><00><00> <12> !<21> #<23> #<23>D<EFBFBD>
<0E>
<1E>
<1E>t<EFBFBD>%6<>
7<EFBFBD>
7<EFBFBD>7<>7<>7<>7<>7<>7<>7<>7<>7<><00>returnc<00>,<00>tttd<01>S)N)<03>ready<64>building<6E>total)rrr<00>r/r<00> index_statusr6<00>s<00><00><1D>#<23><1D> <06> <06>r/c
<00><><00> <0A><0E><0F>g<00> g<00>g<00>tr d}d<1D> <0A><0E>fd<02> }ndt<00>d<04>}d<1D> <0A><0E>fd<05> }|rjtr2|d|<00><00><00><00>d<07><00><00><00>n1|d|<00><00><00><00>d<07><00><00><00>|rtr |d <09><00>n |d
<EFBFBD><00>|r |d <0B><00>|r"|d d |<05><00><00><00>d <0A><03><00><00> rdd<0F><00> <0A><00>znd}|dz
|z} tr)t jtt<00><00>d<12><13><00>}
nt jd<14><00>}
|
<EFBFBD> d<15><00>|
<EFBFBD> d|<06>d|<08><00><04><0E><00><00>
<00><00>d} |
<EFBFBD> d|<06>d|<08>d|<02>d| <09><00><08><0F><00><00> <00><00>} |
<EFBFBD> <00><00>| d<1C>| D<00><00>fS)N<>domainsc<00><><00><03><00><02>|<00><00>|<01>,<2C><03>|<01><00><00><04>|<01><00>dSdSr<00><01>append<6E><05>clause<73>val<61>
conditions<EFBFBD> params_count<6E> params_datas <20><><EFBFBD>r<00>_addz_domains_sync.<locals>._add<64><00>Q<00><><00> <16> <1D> <1D>f<EFBFBD> %<25> %<25> %<25><12><EFBFBD><1C>#<23>#<23>C<EFBFBD>(<28>(<28>(<28><1B>"<22>"<22>3<EFBFBD>'<27>'<27>'<27>'<27>'<27><1F>r/zread_parquet('<27>')c<00><><00><03><00><02>|<00><00>|<01>,<2C><03>|<01><00><00><04>|<01><00>dSdSrr:r<s <20><><EFBFBD>rrBz_domains_sync.<locals>._add<64>rCr/ztld = ?<3F>.z2lower(regexp_extract(domain, '\.([^.]+)$', 1)) = ?z parts = 2z"len(string_split(domain, '.')) = 2z(NOT regexp_matches(domain, '[^a-zA-Z.]')z domain LIKE ?<3F>%<25>WHERE <20> AND <20><00>T<><01> read_only<6C>:memory:rzSELECT COUNT(*) FROM <20> rzSELECT domain FROM z LIMIT z OFFSET c<00><00>g|]
}|d<00><02> S)rr5<00><02>.0<EFBFBD>rs r<00>
<listcomp>z!_domains_sync.<locals>.<listcomp><3E>s<00><00>&<26>&<26>&<26>A<EFBFBD>1<EFBFBD>Q<EFBFBD>4<EFBFBD>&<26>&<26>&r/r) rr#<00>lower<65>lstrip<69>joinrr
rrrr<00>fetchallr")<10>tld<6C>page<67>limit<69>
alpha_only<EFBFBD>no_sld<6C>keyword<72>sourcerB<00>where<72>offsetr%r4<00>rowsr?r@rAs @@@r<00> _domains_syncrc<00>s<><00><><EFBFBD><EFBFBD><00><13>J<EFBFBD><15>L<EFBFBD><14>K<EFBFBD><13>(<28><1A><06> (<28> (<28> (<28> (<28> (<28> (<28> (<28> (<28> (<28> 3<>,<2C>2<>2<>2<><06> (<28> (<28> (<28> (<28> (<28> (<28> (<28> (<28>  <0B>a<01> <17> a<01> <10>D<EFBFBD><19>C<EFBFBD>I<EFBFBD>I<EFBFBD>K<EFBFBD>K<EFBFBD>.<2E>.<2E>s<EFBFBD>3<>3<> 4<> 4<> 4<> 4<> <10>D<EFBFBD>F<><03> <09> <09> <0B> <0B>HZ<48>HZ<48>[^<5E>H_<48>H_<48> `<60> `<60> `<60> <0A>7<> <17> 7<> <10>D<EFBFBD><1B> <1D> <1D> <1D> <1D> <10>D<EFBFBD>5<> 6<> 6<> 6<><11>9<> <0C><04> 7<>8<>8<>8<><0E>6<> <0C><04>_<EFBFBD>4<>'<27>-<2D>-<2D>/<2F>/<2F>4<>4<>4<>5<>5<>5<>5?<3F> G<>X<EFBFBD><07> <0C> <0C>Z<EFBFBD>0<>0<> 0<> 0<>R<EFBFBD>E<EFBFBD><12>Q<EFBFBD>h<EFBFBD>%<25> <1F>F<EFBFBD><13>*<2A><15>~<7E>c<EFBFBD>+<2B>.<2E>.<2E>$<24>?<3F>?<3F>?<3F><04><04><15>~<7E>j<EFBFBD>)<29>)<29><04><08>L<EFBFBD>L<EFBFBD><1F>!<21>!<21>!<21> <10>L<EFBFBD>L<EFBFBD>A<><16>A<>A<>%<25>A<>A<><<3C> P<> P<> Y<> Y<> [<5B> [<5B>\]<5D> ^<5E>E<EFBFBD> <0F><<3C><<3C>L<>f<EFBFBD>L<>L<>u<EFBFBD>L<>L<>U<EFBFBD>L<>L<>F<EFBFBD>L<>L<>k<EFBFBD> <06> <06><0E>h<EFBFBD>j<EFBFBD>j<EFBFBD> <09> <09>J<EFBFBD>J<EFBFBD>L<EFBFBD>L<EFBFBD>L<EFBFBD> <10>&<26>&<26><14>&<26>&<26>&<26> &<26>&r/rK<00>dc
<00><00><>K<00>tj<00><00>}|<07>dt||||||<05><00><00>d{V<00><03>\}} | s|gfSd<01>dt | <09><00>z<00><00>}
t jt<00><00>4<00>d{V<00><03>} t j | _
| <0B> d|
<EFBFBD>d<04>| <09><00>4<00>d{V<00><03> } d<05>| 2<00><00><00>d{V<00><03>} ddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwYddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwYg}| D]G}| <0A> |d|i<01><00>}|r|<10> d<07><00>s<01>2|<0E> |<10><00><00>H||fS)N<>,<2C>?z0SELECT * FROM enriched_domains WHERE domain IN (<28>)c<00><00>JK<00>i|3d{V<00><03>}|dt|<01><00><00><02>6S)N<>domain<69><01>dictrQs r<00>
<dictcomp>zget_domains.<locals>.<dictcomp><3E>s:<00><00><00><00>D<>D<>D<>D<>D<>D<>D<>D<>1<EFBFBD>A<EFBFBD>h<EFBFBD>K<EFBFBD><14>a<EFBFBD><17><17>D<>D<>D<>Ds<00>#rj<00>is_live)r*r+r,rcrW<00>lenr r
r <00>Row<6F> row_factoryr<00>getr;)rYrZr[r\r]r^<00> live_onlyr-r4<00> domain_list<73> placeholdersr<00>cur<75> enriched_map<61>results<74>d<>rows r<00> get_domainsr{<00>s<00><00><00><00> <12> !<21> #<23> #<23>D<EFBFBD>#<23>3<>3<> <0C>m<EFBFBD>S<EFBFBD>$<24><05>z<EFBFBD>6<EFBFBD>7<EFBFBD> <06> <06><06><06><06><06><06><06><16>E<EFBFBD>;<3B> <17><19><14>b<EFBFBD>y<EFBFBD><18><16>8<EFBFBD>8<EFBFBD>C<EFBFBD>#<23>k<EFBFBD>"2<>"2<>2<>3<>3<>L<EFBFBD><18> <20><1B>-<2D>-<2D>E<01>E<01>E<01>E<01>E<01>E<01>E<01><12>"<22><1D><02><0E><15>:<3A>:<3A> N<>|<7C> N<> N<> N<> <17>
<EFBFBD>
<EFBFBD> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01><11>D<>D<><03>D<>D<>D<>D<>D<>D<>D<>D<>D<>L<EFBFBD>  E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01> E<01><><EFBFBD><EFBFBD> E<01> E<01> E<01> E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01>E<01><><EFBFBD><EFBFBD>E<01>E<01>E<01>E<01><11>G<EFBFBD> <18><1C><1C><01><1A><1E><1E>q<EFBFBD>8<EFBFBD>Q<EFBFBD>-<2D>0<>0<><03> <14> <15>S<EFBFBD>W<EFBFBD>W<EFBFBD>Y<EFBFBD>/<2F>/<2F> <15> <14><0F><0E><0E>s<EFBFBD><1B><1B><1B><1B> <10>'<27>><3E>s6<00>
2D<03>=C"<05>D<03>"
C, <09>,D<03>/C, <09>0D<03>
D<07>Dc<00><><00>tr<>tjtt<00><00>d<01><02><00>}|<00>d<03><00><00><00><00>d}|<00>d<05><00><00><00><00>}|<00><00><00>n<>tt<00><00>}tjd<06><00>}|<00>d<07><00>|<00>d|<03>d <09><03><00><00><00><00>d}|<00>d
|<03>d <0B><03><00><00><00><00>}|<00><00><00>|d <0C>|D<00><00>fS) NTrLrrz<>
SELECT tld, COUNT(*) AS cnt FROM domains
WHERE tld != ''
GROUP BY tld ORDER BY cnt DESC LIMIT 20
rNrz#SELECT COUNT(*) FROM read_parquet('rDzz
SELECT lower(regexp_extract(domain, '\.([^.]+)$', 1)) AS tld, COUNT(*) AS cnt
FROM read_parquet('z?')
GROUP BY tld ORDER BY cnt DESC LIMIT 20
c<00>0<00>g|]}|d|dd<02><02><02>S)rrK)rY<00>countr5rQs rrTz#_tld_stats_sync.<locals>.<listcomp> s(<00><00>><3E>><3E>><3E>A<EFBFBD>1<EFBFBD>Q<EFBFBD>4<EFBFBD>!<21>A<EFBFBD>$<24>/<2F>/<2F>><3E>><3E>>r/)
rrr
rrrrrXr"r#)r%r4rb<00>ps r<00>_tld_stats_syncr<63><00>s><00><00><13><15><15>~<7E>c<EFBFBD>+<2B>.<2E>.<2E>$<24>?<3F>?<3F>?<3F><04><14> <0C> <0C>;<3B><<3C><<3C>E<>E<>G<>G<><01>J<><05><13>|<7C>|<7C> <0C> <0A> <0A><16>X<EFBFBD>Z<EFBFBD>Z<EFBFBD> <0A>
<0A>
<EFBFBD>
<EFBFBD> <0C> <0C> <0C> <0C> <0F> <0C> <1D> <1D><01><15>~<7E>j<EFBFBD>)<29>)<29><04> <0C> <0C> <0C>_<EFBFBD>%<25>%<25>%<25><14> <0C> <0C>H<>1<EFBFBD>H<>H<>H<>I<>I<>R<>R<>T<>T<>UV<55>W<><05><13>|<7C>|<7C> <0C> !<21> <0C> <0C> <0C> <0A> <0A><16>X<EFBFBD>Z<EFBFBD>Z<EFBFBD> <0A>
<0A>
<EFBFBD>
<EFBFBD> <0C> <0C> <0C> <10>><3E>><3E><14>><3E>><3E>><3E> ><3E>>r/c <00><00>K<00>ts7tj<00><00>}|<00>dt<00><00><00>d{V<00><03>\aat jt<00><00>4<00>d{V<00><03>}|<01> d<01><00>4<00>d{V<00><03>}|<02>
<00><00><00>d{V<00><03>d}ddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwYttj dd<04><00><00><00>}|<01> d|f<01><00>4<00>d{V<00><03>}|<02>
<00><00><00>d{V<00><03>d}ddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwY|<01> d<06><00>4<00>d{V<00><03>}|<02>
<00><00><00>d{V<00><03>d}ddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwY|<01> d<07><00>4<00>d{V<00><03>}d<08>|2<00><00><00>d{V<00><03>}ddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwYddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwYt
|||tt<00><00>|<07>d d<02><00>|<07>d
d<02><00>|<07>d d<02><00>|<07>d d<02><00>d <0A>d<0E>S)Nz%SELECT COUNT(*) FROM enriched_domainsr<00>SCORE_THRESHOLD<4C>60z6SELECT COUNT(*) FROM enriched_domains WHERE score >= ?z9SELECT COUNT(*) FROM enriched_domains WHERE kit_digital=1<>6SELECT status, COUNT(*) FROM job_queue GROUP BY statusc<00><00><K<00>i|3d{V<00><03>}|d|d<00><02>6S<00>NrrKr5rQs rrmzget_stats.<locals>.<dictcomp>s8<00><00><00><00>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>a<EFBFBD><11>1<EFBFBD><14>q<EFBFBD><11>t<EFBFBD>/<2F>/<2F>/<2F>/<2F><00><04>pending<6E>running<6E>done<6E>failed)r<>r<>r<>r<>)<07> total_domains<6E>enriched<65> hot_leads<64>kit_digital_count<6E> tld_breakdownr6<00>queue)rr*r+r,r<>rr r
r rr<00>int<6E>os<6F>getenvr6rr)r-rrvr<><00> thresholdr<64>r<><00>qs r<00> get_statsr<73>s.<00><00><00><00> <16>U<01><16>%<25>'<27>'<27><04>)-<2D>)=<3D>)=<3D>d<EFBFBD>O<EFBFBD>)T<>)T<>#T<>#T<>#T<>#T<>#T<>#T<> <20> <0C>j<EFBFBD><18> <20><1B>-<2D>-<2D> 0<> 0<> 0<> 0<> 0<> 0<> 0<><12><15>:<3A>:<3A>E<>F<>F<> 1<> 1<> 1<> 1<> 1<> 1<> 1<>#<23>!<21>l<EFBFBD>l<EFBFBD>n<EFBFBD>n<EFBFBD>,<2C>,<2C>,<2C>,<2C>,<2C>,<2C>a<EFBFBD>0<>H<EFBFBD> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<> 1<><31><EFBFBD><EFBFBD> 1<> 1<> 1<> 1<><17><02> <09>"3<>T<EFBFBD>:<3A>:<3A>;<3B>;<3B> <09><15>:<3A>:<3A>V<>Yb<59>Xd<58>e<>e<> 2<> 2<> 2<> 2<> 2<> 2<> 2<>il<69>"<22>|<7C>|<7C>~<7E>~<7E>-<2D>-<2D>-<2D>-<2D>-<2D>-<2D>q<EFBFBD>1<>I<EFBFBD> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<> 2<><32><EFBFBD><EFBFBD> 2<> 2<> 2<> 2<><15>:<3A>:<3A>Y<>Z<>Z<> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A>^a<>'*<2A>|<7C>|<7C>~<7E>~<7E>!5<>!5<>!5<>!5<>!5<>!5<>q<EFBFBD> 9<> <1D> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A> :<3A><><EFBFBD><EFBFBD> :<3A> :<3A> :<3A> :<3A><15>:<3A>:<3A>V<>W<>W<> 0<> 0<> 0<> 0<> 0<> 0<> 0<>[^<5E>/<2F>/<2F>3<EFBFBD>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>A<EFBFBD> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<><30><EFBFBD><EFBFBD> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<><30><EFBFBD><EFBFBD> 0<> 0<> 0<> 0<>&<26><1C><1E>.<2E>#<23>$<24><0E><0E><18>u<EFBFBD>u<EFBFBD>Y<EFBFBD><01>*<2A>*<2A><18>u<EFBFBD>u<EFBFBD>Y<EFBFBD><01>*<2A>*<2A><15>E<EFBFBD>E<EFBFBD>&<26>!<21>$<24>$<24><17>e<EFBFBD>e<EFBFBD>H<EFBFBD>a<EFBFBD>(<28>(<28> 
<EFBFBD>
<EFBFBD> <06> <06> s<><00> H<03><!B/<05>H<03>/
B9 <09>9H<03><B9 <09>=AH<03>?!D2<05> H<03>2
D< <09><H<03>?D< <09>H<03>!F<05>?H<03>
F <09>H<03>F <09>H<03>=G"<05>H<03>"
G, <09>,H<03>/G, <09>0H<03>
H<07>Hc<00><00><>K<00>|dz
|z}dg}|g}|r*|<07>d<03><00>|<08>|<01><00>|r*|<07>d<04><00>|<08>|<02><00>|<03>.|<07>d<05><00>|<08>|rdnd<06><00>dd<08>|<07><00>z} tjt<00><00>4<00>d{V<00><03>}
tj|
_|
<EFBFBD>d | <09>d
<EFBFBD>|||gz<00><00>4<00>d{V<00><03> } d <0B>| 2<00><00><00>d{V<00><03>} ddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwY|
<EFBFBD>d | <09><00>|<08><00>4<00>d{V<00><03> } | <0B><00><00><00>d{V<00><03>d} ddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwYddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwY| | fS) NrKz
score >= ?zcms = ?zip_country = ?zkit_digital = ?rrHrIzSELECT * FROM enriched_domains z% ORDER BY score DESC LIMIT ? OFFSET ?c<00><00><K<00>g|3d{V<00><03>}t|<01><00><00><02>6SrrkrQs rrTz get_enriched.<locals>.<listcomp>Gs4<00><00><00><00>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>a<EFBFBD>D<EFBFBD><11>G<EFBFBD>G<EFBFBD>/<2F>/<2F>/<2F>/r<>z&SELECT COUNT(*) FROM enriched_domains ) r;rWr r
r rprqrr)<0E> min_score<72>cms<6D>country<72> kit_digitalrZr[rar?<00>paramsr`rrvrbr4s r<00> get_enrichedr<64>3s<><00><00><00><00><12>Q<EFBFBD>h<EFBFBD>%<25> <1F>F<EFBFBD><1E><1E>J<EFBFBD><1D>;<3B>F<EFBFBD>
<EFBFBD><1B><12><19><19>)<29>$<24>$<24>$<24><0E> <0A> <0A>c<EFBFBD><1A><1A><1A><0E><1F><12><19><19>*<2A>+<2B>+<2B>+<2B><0E> <0A> <0A>g<EFBFBD><1E><1E><1E><12><1E><12><19><19>+<2B>,<2C>,<2C>,<2C><0E> <0A> <0A>;<3B>-<2D>a<EFBFBD>a<EFBFBD>A<EFBFBD>.<2E>.<2E>.<2E> <14>w<EFBFBD>|<7C>|<7C>J<EFBFBD>/<2F>/<2F> /<2F>E<EFBFBD><18> <20><1B>-<2D>-<2D>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E><12>"<22><1D><02><0E><15>:<3A>:<3A> Z<>e<EFBFBD> Z<> Z<> Z<> <12>e<EFBFBD>V<EFBFBD>_<EFBFBD> $<24>
<EFBFBD>
<EFBFBD> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<><11>/<2F>/<2F>3<EFBFBD>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>/<2F>D<EFBFBD>  0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<> 0<><30><EFBFBD><EFBFBD> 0<> 0<> 0<> 0<>
<16>:<3A>:<3A> <<3C>U<EFBFBD> <<3C> <<3C>f<EFBFBD>
<EFBFBD>
<EFBFBD> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> <10><1E><<3C><<3C>><3E>><3E>)<29>)<29>)<29>)<29>)<29>)<29>1<EFBFBD>-<2D>E<EFBFBD> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E> .<2E><><EFBFBD><EFBFBD> .<2E> .<2E> .<2E> .<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E>
.<2E><><EFBFBD><EFBFBD>
.<2E>
.<2E>
.<2E>
.<2E> <11>$<24>;<3B>sZ<00>7F4<03>D-<05>F4<03>-
D7 <09>7F4<03>:D7 <09>;"F4<03>!F<05>?F4<03>
F <09>F4<03>F <09>F4<03>4
F><07>F>r8c<00><00>K<00>tjt<00><00>4<00>d{V<00><03>}|<01>dd<02>|D<00><00><00><00><00>d{V<00><03>|<01><00><00><00>d{V<00><03>ddd<00><00><00>d{V<00><03>dS#1<00>d{V<00><03>swxYwYdS)Nz2INSERT OR IGNORE INTO ai_queue (domain) VALUES (?)c<00><00>g|]}|f<01><02>Sr5r5<00>rRrys rrTzqueue_ai.<locals>.<listcomp>S<00><00><00> #<23> #<23> #<23>a<EFBFBD>a<EFBFBD>T<EFBFBD> #<23> #<23> #r/<00>r r
r <00> executemanyr<00>r8rs r<00>queue_air<69>Os<<00><00><00><00><18> <20><1B>-<2D>-<2D><1A><1A><1A><1A><1A><1A><1A><12><10>n<EFBFBD>n<EFBFBD> @<40> #<23> #<23>7<EFBFBD> #<23> #<23> #<23>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD><11>i<EFBFBD>i<EFBFBD>k<EFBFBD>k<EFBFBD><19><19><19><19><19><19><19> <1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><><EFBFBD><EFBFBD><1A><1A><1A><1A><1A><1A><00>AA6<03>6
B<07>Bc<00><00>K<00>tjt<00><00>4<00>d{V<00><03>}|<00>d<01><00>4<00>d{V<00><03>}d<02>|2<00><00><00>d{V<00><03>}ddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwYddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwY|<02>dd<04><00>|<02>dd<04><00>|<02>dd<04><00>|<02>dd<04><00>t |<02><00><00><00><00>d<08>S) Nz5SELECT status, COUNT(*) FROM ai_queue GROUP BY statusc<00><00><K<00>i|3d{V<00><03>}|d|d<00><02>6Sr<>r5rQs rrmz'get_ai_queue_status.<locals>.<dictcomp>[<00>8<00><00><00><00>2<>2<>2<>2<>2<>2<>2<>2<><11>A<EFBFBD>a<EFBFBD>D<EFBFBD>!<21>A<EFBFBD>$<24>2<>2<>2<>2r<32>r<>rr<>r<>r<>)r<>r<>r<>r<>r4)r r
r rrr<00>sum<75>values)rrvrbs r<00>get_ai_queue_statusr<73>Xs<00><00><00><00><18> <20><1B>-<2D>-<2D>3<>3<>3<>3<>3<>3<>3<><12><15>:<3A>:<3A>U<>V<>V<> 3<> 3<> 3<> 3<> 3<> 3<> 3<>Z]<5D>2<>2<>c<EFBFBD>2<>2<>2<>2<>2<>2<>2<>2<>2<>D<EFBFBD> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<><33><EFBFBD><EFBFBD> 3<> 3<> 3<> 3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<><33><EFBFBD><EFBFBD>3<>3<>3<>3<><18>8<EFBFBD>8<EFBFBD>I<EFBFBD>q<EFBFBD>)<29>)<29><17>8<EFBFBD>8<EFBFBD>I<EFBFBD>q<EFBFBD>)<29>)<29><14><08><08><16><11>#<23>#<23><16>(<28>(<28>8<EFBFBD>Q<EFBFBD>'<27>'<27><14>T<EFBFBD>[<5B>[<5B>]<5D>]<5D>#<23>#<23>  <06> <06><06>4<00>B<03>A#<05>B<03>#
A- <09>-B<03>0A- <09>1B<03>
B<07>Brj<00>
assessment<EFBFBD> site_analysisc <00><00>K<00>ddl}tjt<00><00>4<00>d{V<00><03>}|<04>d|f<01><00><00>d{V<00><03>|<04>d|<03>|<01><00>|<01>d<04><00>|<01>d<05><00>|<01>d<06><00>|<01>d<07><00>|r|<03>|<02><00>nd|f<07><00><00>d{V<00><03>|r<>|<02>dg<00><00>|<02>d g<00><00>|<02>d
g<00><00>|<02>d g<00><00>d <0C>}|<04>d t|<02>dd<0F><00><00><00>|<03>|<02>dg<00><00><00><00>|<03>|<05><00>|f<04><00><00>d{V<00><03>|<04>d|f<01><00><00>d{V<00><03>|<04><00><00><00>d{V<00><03>ddd<00><00><00>d{V<00><03>dS#1<00>d{V<00><03>swxYwYdS)NrzOINSERT INTO enriched_domains (domain) VALUES (?) ON CONFLICT(domain) DO NOTHINGz<47>UPDATE enriched_domains SET
ai_assessment=?, ai_lead_quality=?, ai_pitch=?,
ai_contact_channel=?, ai_contact_value=?, ai_assessed_at=datetime('now'),
site_analysis=?
WHERE domain=?<3F> lead_quality<74> pitch_angle<6C>best_contact_channel<65>best_contact_value<75>emails<6C>phones<65>whatsapp<70> social_links)r<>r<>r<><00>socialz<6C>UPDATE enriched_domains SET
kit_digital=?, kit_digital_signals=?, contact_info=?
WHERE domain=?r<>F<>kit_digital_signalszNUPDATE ai_queue SET status='done', completed_at=datetime('now') WHERE domain=?) <09>jsonr r
r r<00>dumpsrrr<>r)rjr<>r<><00>_jsonr<00>contactss r<00>save_ai_assessmentr<74>es<00><00><00><00><18><18><18><18><18> <20><1B>-<2D>-<2D>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A><12><10>j<EFBFBD>j<EFBFBD> a<> <13>I<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD><11>j<EFBFBD>j<EFBFBD> !<21> <16> <0B> <0B>J<EFBFBD>'<27>'<27><1A><0E><0E>~<7E>.<2E>.<2E><1A><0E><0E>}<7D>-<2D>-<2D><1A><0E><0E>5<>6<>6<><1A><0E><0E>3<>4<>4<>.;<3B>E<><05> <0B> <0B>M<EFBFBD>*<2A>*<2A>*<2A><14><16> <0E> 
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>" <19> <0E>)<29>-<2D>-<2D>h<EFBFBD><02>;<3B>;<3B>)<29>-<2D>-<2D>h<EFBFBD><02>;<3B>;<3B>)<29>-<2D>-<2D>j<EFBFBD>"<22>=<3D>=<3D>)<29>-<2D>-<2D>n<EFBFBD>b<EFBFBD>A<>A<> <0E><0E>H<EFBFBD> <15>*<2A>*<2A>%<25><18> <0A>)<29>)<29>-<2D><15>?<3F>?<3F>@<40>@<40><19>K<EFBFBD>K<EFBFBD> <0A> 1<> 1<>2G<32><12> L<> L<>M<>M<><19>K<EFBFBD>K<EFBFBD><08>)<29>)<29><1A> <12>
<0E>
<0E>
<0E>
<0E>
<0E>
<0E>
<0E>
<0E>
<0E><11>j<EFBFBD>j<EFBFBD> \<5C> <13>I<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD><11>i<EFBFBD>i<EFBFBD>k<EFBFBD>k<EFBFBD><19><19><19><19><19><19><19>[-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A>-<1A><><EFBFBD><EFBFBD>-<1A>-<1A>-<1A>-<1A>-<1A>-s<00>GG;<03>;
H<07>Hc<00><00>K<00>tjt<00><00>4<00>d{V<00><03>}|<01>dd<02>|D<00><00><00><00><00>d{V<00><03>|<01><00><00><00>d{V<00><03>ddd<00><00><00>d{V<00><03>dS#1<00>d{V<00><03>swxYwYdS)Nz3INSERT OR IGNORE INTO job_queue (domain) VALUES (?)c<00><00>g|]}|f<01><02>Sr5r5r<>s rrTz!queue_domains.<locals>.<listcomp><3E>r<>r/r<>r<>s r<00> queue_domainsr<73><00>s<<00><00><00><00><18> <20><1B>-<2D>-<2D><1A><1A><1A><1A><1A><1A><1A><12><10>n<EFBFBD>n<EFBFBD> A<> #<23> #<23>7<EFBFBD> #<23> #<23> #<23>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD><11>i<EFBFBD>i<EFBFBD>k<EFBFBD>k<EFBFBD><19><19><19><19><19><19><19> <1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><1A><><EFBFBD><EFBFBD><1A><1A><1A><1A><1A>r<>c<00><00><>K<00>tjt<00><00>4<00>d{V<00><03>}|<00>d<01><00>4<00>d{V<00><03>}d<02>|2<00><00><00>d{V<00><03>}ddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwYddd<00><00><00>d{V<00><03>n#1<00>d{V<00><03>swxYwY|<02>dd<04><00>}|<02>dd<04><00>}|<02>dd<04><00>}|<02>dd<04><00>}t |<02><00><00><00><00>}ttj dd <09><00><00><00>}||zdkr||zt|d
z d <0B><00>z nd} |||||| d <0C>S) Nr<4E>c<00><00><K<00>i|3d{V<00><03>}|d|d<00><02>6Sr<>r5rQs rrmz$get_queue_status.<locals>.<dictcomp><3E>r<>r<>r<>rr<>r<>r<><00>CONCURRENCY_LIMIT<49>50<35>
rK)r4r<>r<>r<>r<><00> eta_seconds) r r
r rrrr<>r<>r<>r<>r<><00>max)
rrvrbr<>r<>r<>r<>r4<00>rater<65>s
r<00>get_queue_statusr<73><00>sp<00><00><00><00><18> <20><1B>-<2D>-<2D>3<>3<>3<>3<>3<>3<>3<><12><15>:<3A>:<3A>V<>W<>W<> 3<> 3<> 3<> 3<> 3<> 3<> 3<>[^<5E>2<>2<>c<EFBFBD>2<>2<>2<>2<>2<>2<>2<>2<>2<>D<EFBFBD> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<> 3<><33><EFBFBD><EFBFBD> 3<> 3<> 3<> 3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<>3<><33><EFBFBD><EFBFBD>3<>3<>3<>3<><13>h<EFBFBD>h<EFBFBD>y<EFBFBD>!<21>$<24>$<24>G<EFBFBD><12>h<EFBFBD>h<EFBFBD>y<EFBFBD>!<21>$<24>$<24>G<EFBFBD> <0F>8<EFBFBD>8<EFBFBD>F<EFBFBD>A<EFBFBD> <1E> <1E>D<EFBFBD> <11>X<EFBFBD>X<EFBFBD>h<EFBFBD><01> "<22> "<22>F<EFBFBD> <0F><04> <0B> <0B> <0A> <0A> <1E> <1E>E<EFBFBD> <0E>r<EFBFBD>y<EFBFBD>,<2C>d<EFBFBD>3<>3<> 4<> 4<>D<EFBFBD>>E<><07>>O<>ST<53>=T<>=T<>7<EFBFBD>W<EFBFBD>$<24><03>D<EFBFBD>2<EFBFBD>I<EFBFBD>q<EFBFBD>(9<>(9<>9<>9<>Z^<5E>K<EFBFBD><1A>w<EFBFBD>7<EFBFBD>D<EFBFBD>\b<>s~<7E> <> <>r<7F>)NrKrdFFNF)rNNNrKrdr)*r<>r*<00>loggingr r<00>pathlibr<00> getLogger<65>__name__r r<>rr#rr r rrrrr<00>list<73>__annotations__rr<>rr(r.rlr6rcr{<00>tupler<65>r<>r<>rr<>r<>r<>r<>r<>r5r/r<00><module>r<>s3<00><01> <09> <09> <09> <09> <09><0E><0E><0E><0E><0E><0E><0E><0E><10><10><10><10> <0A> <0A> <0A> <0A><18><18><18><18><18><18> <1A><17> <1A>8<EFBFBD> $<24> $<24><06> <0F>4<EFBFBD> <09><02> <09>*<2A>g<EFBFBD>.<2E>.<2E> /<2F> /<2F><08><17>+<2B>+<2B> <0C><16>)<29>)<29> <0B><16><1F>(<28> <0B>/
<04><06>d <02> <02> <02> <0B><15> <0C><17><0F><10> <0C><16>
<EFBFBD>D<EFBFBD><15><15><15><15> <0C>c<EFBFBD><15><15><15> <1A> <1A> <1A>& <20>& <20>& <20>R8<>8<>8<>
<06>d<EFBFBD><06><06><06><06>6'<27>6'<27>6'<27>r<1A><1A><1A><1A><?<3F><15>s<EFBFBD>D<EFBFBD>y<EFBFBD>)<29>?<3F>?<3F>?<3F>?<3F>0 <06> <06> <06>J<17><17><17><17>8<1A>D<EFBFBD><13>I<EFBFBD><1A><1A><1A><1A>
<06>
<06>
<06>/<1A>/<1A>S<EFBFBD>/<1A>d<EFBFBD>/<1A>4<EFBFBD>/<1A>/<1A>/<1A>/<1A>d<1A><14>c<EFBFBD><19><1A><1A><1A><1A> @<02> @<02> @<02> @<02> @r/