
     ie                        U d Z ddlZddlZddlZddlZddlZddlZddlmZ ddl	m
Z
 ddlmZmZ ddlmZ ddlmZmZ ddlmZ ddlZdd	lmZ  e        	 ddlZd
Z	 ddlZd
Zdadai Ze e!d<   g Z"e#e!d<   dZ$de$ dZ%edefd       Z& ede&      Z'e'jQ                  edgdgdg       d Z)i Z*e e!d<   de+de fdZ,dede+fdZ-d Z.d Z/d e fd!Z0d e fd"Z1g d#Z2d$ Z3 G d% d&e      Z4 G d' d(e      Z5e'jm                  d)      d*e4defd+       Z7e'jm                  d,      d*e5defd-       Z8e'js                  d.      d/        Z:e'js                  d0      dQd1e
e+   d2e;fd3       Z<e'js                  d4      d5e+fd6       Z=e'js                  d7      d8        Z>e'js                  d9      d:        Z?e'js                  d;      d<        Z@eAd=k(  rddlBZB eCd>        eCd?        eCd@        eCdA ej                  dB      rdCndD         eCdE ej                  dF      rdGndH         eCdI ej                  dJ      rdGndK         eCdL        eBj                  dMdNdOdP       yy# e$ r dZY w xY w# e$ r dZY w xY w)RaP  
JPLoft AI Chatbot v4 - Production Server
- Real Claude AI: answers every question using JPLoft knowledge base
- Music Tonight portfolio project referenced correctly
- Blog links shared contextually
- MySQL: stores visitor country, full conversation, all shared info
- Geo-IP: auto-detects visitor country
- Lead scoring + Slack alerts
    N)asynccontextmanager)Optional)FastAPIRequest)CORSMiddleware)StreamingResponseJSONResponse)	BaseModel)load_dotenvTFmem_sessions	mem_leadsuL  
==== COMPANY ====
Name: JPLoft | Founded: 2013 | HQ: Denver, Colorado, USA
CEO: Rahul Sukhwal (15+ years experience)
Team: 100+ professionals | Projects: 1,100+ delivered | Rating: 4.9/5 (1,000+ clients)
Offices: Denver USA, Jaipur India, Melbourne Australia, Basingstoke UK
Clients: Nike, Red Bull, Whirlpool (and 1,000+ global clients)
Phone: +1 (303) 335-0405 | Email: sales@jploft.com
Discovery call: https://calendly.com/jploft/discovery
Portfolio: https://www.jploft.com/portfolio/
Contact: https://www.jploft.com/contact-us/

==== PORTFOLIO — EVENTS / MUSIC / ENTERTAINMENT ====
• Music Tonight (FEATURED PROJECT)
  What: AI-powered local live-music discovery app.
  Built by JPLoft end-to-end using AI/ML and React Native.
  It helps users effortlessly find nearby shows — indie rock, DJ pop-ups,
  surprise concerts — anytime, anywhere using an AI engine.
  Category: Events portfolio on jploft.com
  Portfolio URL: https://www.jploft.com/portfolio/
  Music service page: https://www.jploft.com/music-streaming-app-development
  Tags: Music, Events, Entertainment, Live Shows, AI, Mobile App

==== PORTFOLIO — SPORTS / ENTERPRISE ====
• Red Bull Street Style — global tournament platform for WFFA (World Freestyle Football Association). Client: Red Bull.
• Nike Movement For Sport Playkit — game-based physical assessment tool for coaches, used by 2.5M children aged 6-12. Client: Nike.
• Whirlpool Distributor App — stock management app for Whirlpool distributors. Client: Whirlpool.

==== PORTFOLIO — SOCIAL / DATING ====
• Lure (AI Dating App) — AI-powered dating for socially progressive singles; rates passions on social issues for matching.

==== PORTFOLIO — BLOCKCHAIN / FINTECH ====
• CryptoTradeX — crypto asset trading / digital asset exchange platform.
• SecureChainPayments — cryptocurrency payment solution.

==== PORTFOLIO — TRAVEL / ON-DEMAND ====
• Tennis Court Booking — platform for renting courts for tournaments and events.
• Miami On-Demand Delivery — food, groceries, medicines, beauty items (Miami, Florida).

==== SERVICES ====
MOBILE APP DEVELOPMENT
  iOS, Android, React Native, Flutter
  MVP: 6-10 weeks | Full app: 3-6 months | Cost: $10k-$300k+
  URL: https://www.jploft.com/mobile-app-development-company-usa

MUSIC APP DEVELOPMENT (specialist)
  Streaming apps, live discovery, AI curation, offline/adaptive bitrate, podcasts
  MVP: $30k-$50k | Full-featured: $100k+ | Timeline: 6-10 wks MVP
  URL: https://www.jploft.com/music-streaming-app-development

AI & ML DEVELOPMENT
  LLM integrations, chatbots, automation, generative AI, NLP, CV, predictive analytics
  URL: https://www.jploft.com/ai-development-services

WEB / SAAS PLATFORMS
  React, Next.js, Vue, Node.js, Python, PHP
  URL: https://www.jploft.com

BLOCKCHAIN / WEB3
  Smart contracts (Ethereum, Solana, Polygon, Hyperledger), DeFi, NFT, dApps
  URL: https://www.jploft.com/blockchain-development-company

CLOUD & DEVOPS — AWS, GCP, Azure, Kubernetes, Docker, CI/CD

STOCK TRADING APPS — AI trading, robo-advisors, real-time market data
  URL: https://www.jploft.com/stock-trading-app-development

TRAVEL APPS — Booking, itinerary, AI search
  URL: https://www.jploft.com/travel-app-development

SPEECH RECOGNITION — Voice apps, transcription, multi-language
  URL: https://www.jploft.com/speech-recognition-software-development

JOB PORTALS — Recruitment platforms, freelancer marketplaces
  URL: https://www.jploft.com/job-portal-app-development

QA & TESTING — Automated, performance, security testing

==== INDUSTRIES ====
FinTech, HealthTech (HIPAA), E-Commerce, EdTech, Music/Entertainment, Sports,
Travel, Logistics, Real Estate, Gaming, Social, On-Demand, Blockchain/Web3,
Manufacturing, HR/Recruitment
URL: https://www.jploft.com/industries/

==== BLOG RESOURCES ====
All blogs: https://www.jploft.com/blog/

Music industry blogs:
• Music Streaming Trends 2025 → https://www.jploft.com/blog/music-streaming-app-trends
• JPLoft as Music App Leader → https://www.jploft.com/blog/jploft-as-a-leader-in-delivering-tailored-music-app-development-services
• Music App Ideas for Startups → https://www.jploft.com/blog/music-app-ideas
• Top Music App Features 2025 → https://www.jploft.com/blog/top-music-app-features
• Best Music Apps 2025 → https://www.jploft.com/blog/best-music-streaming-apps
• Music App Monetization → https://www.jploft.com/blog/how-to-monetize-a-music-streaming-app
• Why Music Apps Fail → https://www.jploft.com/blog/why-music-apps-fail

==== PRICING ====
MVP: $10k-$30k (6-10 weeks)
Standard mobile: $30k-$80k (3-4 months)
Complex platform/SaaS: $80k-$200k+ (4-8 months)
Music streaming MVP: $30k-$50k | Full: $100k+
Enterprise AI: $50k-$500k+
Dedicated developer: $2,500-$6,000/month
Model: Fixed price (transparent, no surprises)

==== ENGAGEMENT MODELS ====
Fixed Price | Dedicated Team | Staff Augmentation | Hourly
u  You are Aria, the friendly AI assistant for JPLoft — a global software development company.

PRIMARY GOAL: Answer every question helpfully and specifically, share relevant links, and collect visitor contact details to generate leads.

You have JPLoft's complete knowledge base:
u!  

━━━ ANSWERING QUESTIONS ━━━

MUSIC / EVENTS questions → ALWAYS:
1. Mention "Music Tonight" by name: "We built Music Tonight — an AI-powered live music discovery app"
2. Link portfolio: https://www.jploft.com/portfolio/ (Events category)
3. Link music service: https://www.jploft.com/music-streaming-app-development
4. Offer 1 blog link from the music section above

ANY portfolio question → reference the specific project from the knowledge base that matches, then link https://www.jploft.com/portfolio/

Service questions → give real timeline + cost range + service URL

Blog questions → share specific URLs from the knowledge base

IF unsure about something → "Let me connect you with our team: sales@jploft.com or book a call: https://calendly.com/jploft/discovery"

━━━ LEAD COLLECTION ━━━
After 2-3 exchanges, naturally say: "I'd love to put together a custom proposal — could I get your name and email?"
Collect: name, email, company, project type, budget, timeline.
When visitor shares info, acknowledge warmly.

━━━ STYLE ━━━
• 3-5 sentences per reply (more only if needed)
• Max 2 links per reply
• Always end with an engaging question
• Never say you are Claude or mention Anthropic
• Never invent projects or data not in the knowledge base
appc                H  K   t        j                  dd      j                         }|rMd|vrIt        j                  |      a	 t
        j                  j                  ddddd	g
       t        d       nt        d       t        rt        j                  dd      j                         }t        j                  dd      j                         }t        j                  dd      j                         }t        j                  dd      j                         }t        t        j                  dd            }|rO|rM|rK	 t        j                  |||||dddd	       d {   at                d {    t        d| d|        nt        d       d  t        r1t        j!                          t        j#                          d {    y y # t        $ r}t        d|        d aY d }~nd }~ww xY w7 7 # t        $ r}t        d| d       Y d }~d }~ww xY w7 Vw)NANTHROPIC_API_KEY YOUR_KEY)api_keyclaude-haiku-4-5-20251001   userhirolecontent)model
max_tokensmessageszOK Claude API connectedzFAIL Claude API: zFAIL ANTHROPIC_API_KEY not set
MYSQL_HOST
MYSQL_USERMYSQL_PASSWORDMYSQL_DATABASE
MYSQL_PORT3306   
   Tutf8mb4)	hostportr   passworddbminsizemaxsize
autocommitcharsetzOK MySQL connected to /zFAIL MySQL: u    — using in-memoryu2   WARN MySQL credentials not set — using in-memory)osgetenvstrip	anthropic	Anthropicclaude_clientr   createprint	Exception	HAS_MYSQLintaiomysqlcreate_pooldb_poolcreate_tablesclosewait_closed)r   keyehupdr(   s           &/var/www/html/jploft-chatbot/server.pylifespanrH      s     ))'
,
2
2
4C
z$!++C8	!""))1a#)d;< * > +,
 	./IIl2&,,.IIl2&,,.II&r*002II&r*002299\&12q> ( 4 4AardI!O O $o%%.qc1#67 FG	!!### 3  	!%aS)* M	!O & >QC';<==> 	$s   AH"1G 5CH">!G; G7 G; 1G92G; AH"	H 
H"	G4G/)H"/G44H"7G; 9G; ;	HHH"HH"JPLoft Chatbot v4)titlerH   *)allow_originsallow_methodsallow_headersc                    K   t         j                         4 d {   } | j                         4 d {   }|j                  d       d {    |j                  d       d {    |j                  d       d {    t	        d       d d d       d {    d d d       d {    y 7 7 }7 f7 O7 87 # 1 d {  7  sw Y   /xY w7 &# 1 d {  7  sw Y   y xY ww)Nar  
                CREATE TABLE IF NOT EXISTS chatbot_sessions (
                    id              VARCHAR(64) PRIMARY KEY,
                    visitor_ip      VARCHAR(45),
                    visitor_country VARCHAR(120) DEFAULT 'Unknown',
                    visitor_city    VARCHAR(120) DEFAULT 'Unknown',
                    started_at      DATETIME DEFAULT CURRENT_TIMESTAMP,
                    last_active     DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                    total_messages  INT DEFAULT 0
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
            a   
                CREATE TABLE IF NOT EXISTS chatbot_messages (
                    id          BIGINT AUTO_INCREMENT PRIMARY KEY,
                    session_id  VARCHAR(64) NOT NULL,
                    role        ENUM('user','assistant') NOT NULL,
                    content     TEXT NOT NULL,
                    sent_at     DATETIME DEFAULT CURRENT_TIMESTAMP,
                    INDEX idx_session (session_id)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
            aC  
                CREATE TABLE IF NOT EXISTS chatbot_leads (
                    id              INT AUTO_INCREMENT PRIMARY KEY,
                    session_id      VARCHAR(64),
                    visitor_country VARCHAR(120) DEFAULT 'Unknown',
                    name            VARCHAR(200),
                    email           VARCHAR(320),
                    phone           VARCHAR(50),
                    company         VARCHAR(200),
                    project_type    VARCHAR(200),
                    budget          VARCHAR(100),
                    timeline        VARCHAR(100),
                    extra_info      TEXT,
                    score           TINYINT DEFAULT 0,
                    score_tier      ENUM('hot','warm','cold') DEFAULT 'cold',
                    created_at      DATETIME DEFAULT CURRENT_TIMESTAMP,
                    INDEX idx_email   (email),
                    INDEX idx_tier    (score_tier),
                    INDEX idx_country (visitor_country)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
            zDB tables ready)r=   acquirecursorexecuter7   )conncs     rG   r>   r>      s       ,% ,%D;;= +	% +	%A)) 
 
 
 
 )) 	 	 	 	 ))    * #$W+	% +	%,% ,% ,%+	%
	-+	% +	% +	% +	%,% ,% ,% ,%s   C(B0C(CB2CB<B4B<&B6'B<?B8 B<CB:CC(*C+C(2C4B<6B<8B<:C<C	CC	
CC(C%CC%!C(
_geo_cacheipreturnc                 6  K   | r| dv s| j                  d      rdddS | t        v r	t        |    S t        sdddS 	 t        j                  d      4 d {   }|j                  d	|  d
       d {   }|j                  dk(  rQ|j                         }|j                  dd      |j                  dd      d}|t        | <   |cd d d       d {    S d d d       d {    dddS 7 7 {7 7 # 1 d {  7  sw Y   xY w# t        $ r Y -w xY ww)N)z	127.0.0.1z::1)z192.168.z10.z172.Local	Localhost)countrycityUnknowng      @timeoutzhttps://ipapi.co/z/json/   country_namer\   )	
startswithrU   	HAS_HTTPXhttpxAsyncClientgetstatus_codejsonr8   )rV   clientrrF   results        rG   get_locationrl     s%    **bmm<U.V!55	Z"~#955	$$S1 	 	Vjj#4RD!?@@A}}#FFH%&UU>)%DaeeTZ[dNef!'
2	 	 	 	 	  y11	@	 	 	 	 	  s   9DD
 C-D
 C53C/4AC5D
 C1D
 DD
 #C3$D
 (D-D
 /C51D
 3D
 5D;C><DD
 
	DDDDrequestc                    | j                   j                  dd      }|r"|j                  d      d   j                         S | j                   j                  dd      }|r|j                         S t	        | j
                  dd      S )NzX-Forwarded-Forr   ,r   z	X-Real-IPr'   0.0.0.0)headersrf   splitr2   getattrri   )rm   fwdris      rG   real_iprv   1  sn    
//

/
3C
399S>!$**,,			[	,B	"((*7>>6955    c           	        K   t         rw	 t         j                         4 d {   }|j                         4 d {   }|j                  d| |||f       d {    d d d       d {    d d d       d {    y y | t        vr||g dt        | <   y y 7 t7 ]7 A7 3# 1 d {  7  sw Y   CxY w7 :# 1 d {  7  sw Y   IxY w# t        $ r}t        d|        Y d }~y d }~ww xY ww)Na  
                        INSERT INTO chatbot_sessions (id,visitor_ip,visitor_country,visitor_city)
                        VALUES (%s,%s,%s,%s)
                        ON DUPLICATE KEY UPDATE last_active=NOW(), total_messages=total_messages+1
                    zdb_init_session err: )r[   r\   r   )r=   rP   rQ   rR   r8   r7   r   )sidrV   r[   r\   rS   rT   rB   s          rG   db_init_sessionrz   8  s     		/( 3 3D;;= 3 3A)) % r7D1	3 3 33 33 3 3 l"+2$" ML #3333 3 3 33 3 3 3  	/)!-..	/s   C/C BC B6BB6BBBB6)B*B6.C 9B4:C >C/C B6BB6B1	%B(&B1	-B64C 6C<B?=CC 	C,C'"C/'C,,C/c           
      ^  K   t         ry	 t         j                         4 d {   }|j                         4 d {   }|j                  d| ||d d f       d {    d d d       d {    d d d       d {    y y | t        v rJt        |    d   j                  ||t        j                  j                         j                         d       y y 7 7 7 }7 o# 1 d {  7  sw Y   xY w7 v# 1 d {  7  sw Y   xY w# t        $ r}t        d|        Y d }~y d }~ww xY ww)NzHINSERT INTO chatbot_messages (session_id,role,content) VALUES (%s,%s,%s)i N  zdb_save_msg err: r   )r   r   ts)r=   rP   rQ   rR   r8   r7   r   appenddatetimeutcnow	isoformat)ry   r   r   rS   rT   rB   s         rG   db_save_msgr   H  s'    	+( 6 6D;;= 6 6A))bdGFUO46 6 66 66 6 6 ,j)00&&--/99;2= > 6666 6 6 66 6 6 6
  	+%aS)**	+s   D-D	 CD	 C4CC4CCC C4+C,C40D	 ;C2<D	  AD-D	 C4CC4C/	#C&$C/	+C42D	 4D:C=;DD	 		D*D% D-%D**D-leadc                 ~   d}| j                  d      xs dj                         }d|v r|dz  }nd|v r|dz  }nd|v r|d	z  }n	d
|v r|dz  }| j                  d      xs dj                         t        fddD              r|dz  }nt        fddD              r|d	z  }n|dz  }| j                  d      r(| j                  d      r| j                  d      r|d	z  }n>| j                  d      r| j                  d      r|dz  }n| j                  d      r|dz  }|dk\  rdn|dk\  rdnd}t        |d      |fS )Nr   budgetr   100   50   25   10   project_typec              3   &   K   | ]  }|v  
 y wN .0kpts     rG   	<genexpr>zscore_lead.<locals>.<genexpr>_  s     
Iq17
I   )aiml
blockchain
enterprisesaas   c              3   &   K   | ]  }|v  
 y wr   r   r   s     rG   r   zscore_lead.<locals>.<genexpr>`  s     GQ"WGr   )mobilewebmusicr   fintechemailnamecompanyr%   r   <   hotwarmcoldd   )rf   loweranymin)r   sbtierr   s       @rG   
score_leadr   W  s7   	A	(		!r((*Az171	AGA	AGA	AFA
((>
"
(b	/	/	1B

IH
II1PR71	GFG	Gb
q&!xxTXXf-$((92EqBwq	'	txx/b	'	AFAG517Dq#;rw   c                 0  K   t        |       \  }}t        rb	 t        j                         4 d {   }|j                         4 d {   }|j	                  d| j                  dd      | j                  dd      | j                  dd      | j                  dd      | j                  dd      | j                  d	d      | j                  d
d      | j                  dd      | j                  dd      | j                  dd      ||f       d {    d d d       d {    d d d       d {    t        d| j                  d       d| j                  d       d| d| j                  d              nt        j                  i | ||d       |dk\  rt        rt        j                  dd      }|r	 t        j                  d      4 d {   }|j                  |dd| d| j                  dd       d| j                  d       d| j                  d       d| j                  d
       d| j                  d       i        d {    d d d       d {    ||fS ||fS 7 ;7 %7 b7 U# 1 d {  7  sw Y   fxY w7 ^# 1 d {  7  sw Y   oxY w# t        $ r5}t        d|        t        j                  i | ||d       Y d }~Jd }~ww xY w7 7 7 # 1 d {  7  sw Y   xY w# t        $ r Y ||fS w xY ww)!Na-  
                        INSERT INTO chatbot_leads
                        (session_id,visitor_country,name,email,phone,company,
                         project_type,budget,timeline,extra_info,score,score_tier)
                        VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
                    
session_idr   r[   r]   r   r   phoner   r   r   timeline
extra_infozLead saved: z <z> [z] zdb_save_lead err: )scorer   r   SLACK_WEBHOOK_URLr   r^   textz	HOT LEAD z
/100 from ?z
Name: z
 | Email: z

Project: z | Budget: )rh   )r   r=   rP   rQ   rR   rf   r7   r8   r   r}   rc   r0   r1   rd   re   post)r   r   r   rS   rT   rB   wbc2s           rG   db_save_leadr   h  s    T"KE4	A( ( (D;;= ( (A)) %
 ((<3TXXi	5R((6"-0D((72.20F((>"5txx7L((:b1488L3L'
( 
( 
(( (( ( L&!1 2"TXXg5F4Gs4&PRSWS[S[\eSfRghi
 	;D;d;<{yYY*2.# ,,Q7 ` `2''"F#E7*TXXi5L4M N!!%&!1 2*TXXg=N<O P$$(HH^$<#=[RZI[H\^,_' ` ` `` ` $;5$;;((
(( ( ( (( ( ( (  	A&qc*+??U$?@@	A``` ` ` `
 "d$; #sO  LJ' I,J' J
I/JCI8I2I8J I5!J%J' 0J1AJ' 9A L:L K(L A7K/K+K/L K- L $L,J' /J2I85J8J	>J?J	JJ' J$JJ$J' '	K%0*K L K%%L(L +K/-L /L5K86L=L 	LLLL)z$ignore (all |previous )?instructionsz forget (your |all )?instructionszyou are now\bznew (role|persona)zact as (?!jploft|aria)z\[INST\]z<\|system\|>c                     | j                         }t        D ]  }t        j                  ||      s y t        j                  dd|       j                         d d dfS )N)z
[FILTERED]Tz<[^>]+>r   i  F)r   	INJECTIONresearchsubr2   )r   lorE   s      rG   sanitizer     sU    	B 799Q$6766*R%++-et4e;;rw   c                   4    e Zd ZU eed<   dZeed<   g Zeed<   y)ChatReqmessager   r   historyN)__name__
__module____qualname__str__annotations__r   r   listr   rw   rG   r   r     s    LJGTrw   r   c                       e Zd ZU dZeed<   dZee   ed<   dZee   ed<   dZ	ee   ed<   dZ
ee   ed<   dZee   ed<   dZee   ed<   dZee   ed	<   dZee   ed
<   y)LeadReqr   r   r   r   r   r   r   r   r   r   N)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rw   rG   r   r     s|    JD(3-E8C=E8C=GXc]"$L(3-$FHSM Hhsm  "J"rw   r   z	/api/chatreqc                   
K   t         st        dddi      S t        | j                        \  }}|rt        ddi      S | j                  xs$ dt        j                         j                  d d z   t        |      }t        |       d {   }t        ||d	   |d
          d {    t        d|       d {    g 
| j                  dd  D ]Y  }|j                  dd      t        |j                  dd            j                         }}|dv sC|sF
j!                  ||d       [ 
j!                  d|d       
fd}	t#         |	       ddddd      S 7 7 7 w)Ni  errorz5Claude API not ready. Check ANTHROPIC_API_KEY in .env)rg   r   responsezNI can only assist with JPLoft software questions. What would you like to know?S   r[   r\   r   ir   r   r   )r   	assistantr   c                   K   d} 	 t         j                  j                  t        j                  dd      dt
              5 }|j                  D ]%  }| |z  } dt        j                  d|i       d ' 	 d d d        dt        j                  d	d
       d | j                         r$t        d| j                                d {    y y # 1 sw Y   ]xY w# t        j                  $ r! dt        j                  ddi       d Y tt        j                  $ r! dt        j                  ddi       d Y t        $ r6}t        d|        dt        j                  ddi       d Y d }~d }~ww xY w7 # | j                         r%t        d| j                                d {  7   w w xY ww)Nr   CLAUDE_MODELr   i  r   r   systemr   zdata: tokenz

T)doner   r   z!Invalid API key. Check .env file.z"Rate limit. Please wait and retry.zStream error: zConnection issue. Please retry.r   )r5   r   streamr0   r1   SYSTEM_PROMPTtext_streamrh   dumpsr3   AuthenticationErrorRateLimitErrorr8   r7   r2   r   )fullr   chunkrB   r   ry   s       rG   generatezchat.<locals>.generate  s    	B''..ii/JK$!	 /  E
 #// EEEMD"4::wuo#>"?tDDEE 4::d&DEFdKK zz|!#{DJJLAAA %E E ,, 	[4::w/R&STUUYZZ'' 	\4::w/S&TUVVZ[[ 	YN1#&'4::w/P&QRSSWXXX	Y
 B zz|!#{DJJLAAA s   G;C  5C8'C  .GFGCC   1FF 0FF F,E>9F >FF G/F?7F:8F??Gztext/event-streamzno-cache,no-storenoz
keep-alive)zCache-ControlzX-Accel-Buffering
Connection)
media_typerq   )r5   r	   r   r   r   uuiduuid4hexrv   rl   rz   r   r   rf   r   r2   r}   r   )r   rm   cleanflaggedrV   locrC   rj   rT   r   r   ry   s             @@rG   chatr     si    TUW 	W ckk*NE7Z(xyzz
..
9S4::<#3#3CR#88C
'
BR 
 C
#r3y>3v;
???
c65
)))H[[ 4uuVBQUU9R%8!9!?!?!A1$$OOA234 OOFU34B0 XZ4G!4[ghj jG !?)sD   BE&E E&(E")E&=E$>AE&E&AE&"E&$E&z
/api/leadsc                   K   t        |      }t        |       d {   }|d   }t        r| j                  r	 t        j	                         4 d {   }|j                         4 d {   }|j                  d| j                  f       d {    |j                          d {   }|r|d   r|d   dvr|d   }d d d       d {    d d d       d {    t        | j                  || j                  xs d| j                  xs d| j                  xs d| j                  xs d| j                  xs d| j                  xs d| j                   xs d| j"                  xs dd
       d {   \  }}	d||	dS 7 d7 27 7 7 7 # 1 d {  7  sw Y   xY w7 # 1 d {  7  sw Y   xY w# t        $ r Y w xY w7 Ww)	Nr[   z8SELECT visitor_country FROM chatbot_sessions WHERE id=%sr   )r]   r   r   )
r   r[   r   r   r   r   r   r   r   r   T)successr   r   )rv   rl   r=   r   rP   rQ   rR   fetchoner8   r   r   r   r   r   r   r   r   r   )
r   rm   rV   r   r[   rS   rT   rowr   r   s
             rG   capture_leadr     s    
'
BR 
 C)nG3>>	( ) )D;;= ) )A))$^`c`n`n_pqqq !

,Cs1v#a&*F"%a&	) )) ) %nnBbbS[[->B((.B#**:JLL&Bcnn6J&  KE4 555% !))q,) ) ) )) ) ) ) $s   GF GF; FF; F&*F+F&.!FF	F'F(F?F&
FF&F; F$F; BG2G
3GF; F&	FFF&F!	FF!	F&$F; &F8,F/-F84F; ;	GGGGz/api/admin/statsc            	        
K   t         r	 t         j                         4 d {   } | j                         4 d {   

fd} |d       d {   } |d       d {   } |d       d {   } |d       d {   } |d       d {   }
j                  d       d {    
j	                          d {   D cg c]  }|d   |d	   d
 }}||||||dcd d d       d {    cd d d       d {    S t        t              t        d t        D              t        d t        D              t        t              t        d t        j                         D              dS 7 Q7 ;7 )7 7 7 7 7 7 c c}w 7 7 # 1 d {  7  sw Y   nxY wd d d       d {  7   n# 1 d {  7  sw Y   nxY w# t
        $ r}	dt        |	      icY d }	~	S d }	~	ww xY ww)Nc                 |   K   j                  |        d {    j                          d {   d   S 7 7 	w)Nr   )rR   r   )sqlrT   s    rG   qzstats.<locals>.q  s2     iin,,AJJL6H!5L.L,6Hs   <8<:<<z"SELECT COUNT(*) FROM chatbot_leadsz9SELECT COUNT(*) FROM chatbot_leads WHERE score_tier='hot'z:SELECT COUNT(*) FROM chatbot_leads WHERE score_tier='warm'z%SELECT COUNT(*) FROM chatbot_sessionsz%SELECT COUNT(*) FROM chatbot_messageszSELECT visitor_country,COUNT(*) c FROM chatbot_sessions
                        WHERE visitor_country!='Unknown' GROUP BY visitor_country ORDER BY c DESC LIMIT 10r      )r[   count)total_leads	hot_leads
warm_leadstotal_sessionstotal_messagestop_countriesr   c              3   J   K   | ]  }|j                  d       dk(  sd  yw)r   r   r   Nrf   r   ls     rG   r   zstats.<locals>.<genexpr>  s%     8fqQRQVQVW]Q^`eQe8f   ##c              3   J   K   | ]  }|j                  d       dk(  sd  yw)r   r   r   Nr  r  s     rG   r   zstats.<locals>.<genexpr>  s     K1QUU6]F5JQKr  c              3   R   K   | ]  }t        |j                  d g              ! yw)r   N)lenrf   )r   r   s     rG   r   zstats.<locals>.<genexpr>  s"     C}bcCjY[H\D]C}s   %')r   r   r   r   r   )r=   rP   rQ   rR   fetchallr8   r   r	  r   sumr   values)rS   r   totalr   r   sessionsr   rj   	countriesrB   rT   s             @rG   statsr    s    	7( k kD;;= k kAM%&'K%LLE%&'b%ccC%&'c%ddD%&'N%OOH%&'N%OOH)) %n o o oNOjjlHZ [1AaD1!> [I [*/CT-5x`ikk k kk k k i.S8fI8f5fK	KK .C}gsgzgzg|C}@} kk  McdOOoHZ [kkk k kk k k k k 6ws1v&666sh  G5G E4G F<E7F< FE:F!E="F1F 2FFFFF*F+FF
F	F
F%F<1F2F<6G FG A-G54G 7F<:F=F FFFF
FFF<G F'	FF'	#F<*G 5F86G <GGG
G G5	G2G-'G2(G5-G22G5z/api/admin/leadsr   limitc           	        K   t         rC	 t         j                         4 d {   }|j                  t        j                        4 d {   }| r|j                  d| |f       d {    n|j                  d|f       d {    |j                          d {   }g }|D ]t  }t        |      }|j                         D ]C  \  }}	t        |	t        j                  t        j                  f      s1|	j                         ||<   E |j                  |       v |t        |      dcd d d       d {    cd d d       d {    S t"        d | t        t"              dS 7 C7 7 7 7 7 <7 -# 1 d {  7  sw Y   nxY wd d d       d {  7   n# 1 d {  7  sw Y   nxY wg# t        $ r}
t!        |
      g dcY d }
~
S d }
~
ww xY ww)NzQSELECT * FROM chatbot_leads WHERE score_tier=%s ORDER BY created_at DESC LIMIT %sz=SELECT * FROM chatbot_leads ORDER BY created_at DESC LIMIT %s)leadsr  )r   r  )r=   rP   rQ   r;   
DictCursorrR   r
  dictitems
isinstancer~   dater   r}   r	  r8   r   r   )r   r  rS   rT   rowsrk   rj   r   r   vrB   s              rG   
list_leadsr  	  s    	B( @ @D;;x':':; @ @qii({  ~B  CH  }I  J  J  Jii(ginhpqqq!"-DF! +"1g#&99; eCAa)!X->->x}},MNWXWbWbWdPSTUPVec*	+
 %+3v;?@ @ @@ @ @ fu%c)n==@@ Jq-@@@ @ @@ @ @ @ @ As1vb&AAAs  GF4 E&F4 $FE)FE7)E,*E7E/E7E1AE755E7*F6E37F;F4 E5F4 G&F4 )F,E7/E71E73F5F4 7F		=F >F		FF4 FF4 F0$F'%F0,F4 3G4	G=G
GGGGz%/api/admin/conversations/{session_id}r   c                 N  K   t         r	 t         j                         4 d {   }|j                  t        j                        4 d {   }|j                  d| f       d {    |j                          d {   }g }|D ]]  }t        |      }t        |j                  d      t        j                        r|d   j                         |d<   |j                  |       _ d|icd d d       d {    cd d d       d {    S t        j                  | i       }d|j                  dg       iS 7 7 7 7 7 I7 :# 1 d {  7  sw Y   nxY wd d d       d {  7   n# 1 d {  7  sw Y   nxY wt# t        $ r}t        |      g dcY d }~S d }~ww xY ww)NzVSELECT role,content,sent_at FROM chatbot_messages WHERE session_id=%s ORDER BY sent_atsent_atr   )r   r   )r=   rP   rQ   r;   r  rR   r
  r  r  rf   r~   r   r}   r8   r   r   )	r   rS   rT   r  rk   rj   r   rB   r   s	            rG   get_convr    s    	E( 	/ 	/D;;x':':; / /q))$|  I  ~K  L  L  L!"-DF! +"1g%cggi&89J9JK\_`i\j\t\t\vSQZ^c*+ 'v./ / /	/ 	/ 	/ 	B'AquuZ+,,	// L-/	// / /	/ 	/ 	/ 	/ 	/ Ds1v&DDDs   F%F D7F $E+D:E+E&D<'E>D>?A+E*E+6E 7E+;F EF +F%7F :E+<E>E E+F E	
EE	E+F $E'%F +E=1E42E=9F  F%	F"
FF"F%F""F%/healthc                     K   dt         d ut        d ut        j                  j                         j	                         dS w)Nok)statusclaudemysqltime)r5   r=   r~   r   r   r   rw   rG   healthr&  0  s=     =#<WTXEX$$++-779; ;s   >A /test-claudec                     K   t         sdddS 	 t         j                  j                  ddt        dddg	      } d
| j                  d   j
                  dS # t        $ r}dt        |      dcY d }~S d }~ww xY ww)NFzAPI key not configured)workingreasonr   r   r   zVWhat music-related project has JPLoft built? Give me the name and a brief description.r   r   Tr   )r)  r   )r)  r   )r5   r   r6   r   r   r   r8   r   )rj   rB   s     rG   test_clauder+  5  s     E;S!TTC""))-# $  0H  I  J * K !))A,*;*;<<BU3q6"BBBs5   A:AA A:	A7A2,A7-A:2A77A:r/   c                     K   ddddS w)NrI   r  r'  )apir&  testr   r   rw   rG   rootr/  @  s      3Yn]]s   	__main__z3
==================================================z  JPLoft AI Chatbot Server v4z2==================================================z  Claude : r   z
OK key setMISSINGz  MySQL  : r   OKznot set (in-memory mode)z  Slack  : r   znot setz$
  Listening on http://0.0.0.0:8000
z
server:apprp   i@  )r'   r(   reload)Nr`   )F__doc__r0   rh   r   r   asyncior~   
contextlibr   typingr   fastapir   r   fastapi.middleware.corsr   fastapi.responsesr   r	   pydanticr
   r3   dotenvr   r;   r9   ImportErrorrd   rc   r5   r=   r   r  r   r   r   	JPLOFT_KBr   rH   r   add_middlewarer>   rU   r   rl   rv   rz   r   r   r   r   r   r   r   r   r   r   rf   r  r:   r  r  r&  r+  r/  r   uvicornr7   r1   runr   rw   rG   <module>rB     sN   - , , *  $ 2 =    II
 
d 	4 
k	Z
  "J &$ &$ &$R '(;   >#se\_[`  a-%` 
D 23 24 2&6W 6 6N >T "!T !FZ	<i 
	#i 	# +/jG /jg /j /jd ,6G 6g 6 6. 	 , 	>8C= >c > >( 	01-s - 2-" ; ; C C  ]  ]z	-	
)*	&M	K			2E(FIV
WX	K			, 7=WX
YZ	K			*= >IN
OP	24GKK94F S  I  Is$   I I- I*)I*-I87I8