
    DjM                    v   d dl mZmZmZ d dlmZ d dlZd dlZd dlZd dl	m	Z	 d dl
Z
d dlZd dlmZmZ d dlZd dlZd dlZ ej$                  ej&                         d dlZd dlZd dlmZ d dlZd dlmZ d d	lmZ d dlZd dlZd dlZd d
l m Z m!Z! d dlm"Z"  ee#      Z$ ee$       dddddZ%d dlZd dl&m'Z' d dl(m)Z) ddddddZ*d Z+d Z,d Z-d Z.d Z/d Z0dZ1h d Z2d! Z3d_d"Z4e$jk                  d#d$g%      d&        Z6e$jk                  d'd(g%      d)        Z7e$jk                  d*d$g%      d+        Z8e$jk                  d,      d-        Z9d. Z:d/ Z;e$jk                  d0d$g%      d1        Z<e$jk                  d0d(g%      d2        Z=e$jk                  d3d4g%      d5        Z>e$jk                  d3d(g%      d6        Z?e$jk                  d7d(g%      d8        Z@e$jk                  d7d$g%      d9        ZAe$jk                  d:d4g%      d;        ZBe$jk                  d:d<g%      d=        ZCe$jk                  d3d<g%      d>        ZDe$jk                  d?d$g%      d@        ZEe$jk                  dAd(g%      dB        ZFe$jk                  dCd$g%      dD        ZGe$jk                  dEd(g%      dF        ZHe$jk                  dGd(g%      dH        ZIe$jk                  dId$g%      dJ        ZJe$jk                  dKd(g%      dL        ZKdM ZLe$jk                  dNd$g%      dO        ZMe$jk                  dPd(g%      dQ        ZNe$jk                  dRd(g%      e,dS               ZOe$jk                  dTd(g%      e,dU               ZPe$jk                  dVd$g%      e,dW               ZQe$jk                  dXd$g%      e,dY               ZRe#dZk(  re$j                  d[d\d]^       yy)`    )Flaskrequestjsonify)CORSN)datetime)urlparseparse_qs)level)secure_filenameEmailMessagewraps)Responsemake_response)	b64decodez	127.0.0.1aliexpress_automationpostgresPostgresPass123)hostdatabaseuserpassword)MIMEText)MIMEMultipartzsmtp.gmail.comiK  kampervan.fun@gmail.comzcxqn pvmj kdmi zhprz"CamperVAN <no-reply@kampervan.fun>)r   portr   passfromc                 r    t        j                  dd      }t        j                  dd      }| |k(  xr ||k(  S )N
ADMIN_USERadmin
ADMIN_PASS)osgetenv)usernamer   
admin_user
admin_passs       </var/www/html/mycamper/aliexpress-site/backend/api/server.pycheck_admin_authr*   9   s7    <1J<1Jz!<h*&<<    c                 .     t                fd       }|S )Nc                      t         j                  }|r t        |j                  |j                        st        ddddi      S  | i |S )NzAuthentication requiredi  zWWW-AuthenticatezBasic realm="Login Required")r   authorizationr*   r&   r   r   )argskwargsauthfs      r)   	decoratedz!requires_admin.<locals>.decorated?   sJ    $$+DMM4==I5s=OPn<opp$!&!!r+   r   )r2   r3   s   ` r)   requires_adminr4   >   s!    
1X" "
 r+   c                    ddl m} dd l} |       }t        d   |d<   | |d<   ||d<   |j	                  |d       	  |j
                  t        d	   t        d
   d      }|j                          |j                          |j                          |j                  t        d   t        d          |j                  |       |j                          y# t        $ r%}t        d|        dt        |      fcY d }~S d }~ww xY w)Nr   r   r   FromToSubjecthtml)subtyper   r      )timeoutr   r   )TNzSMTP ERROR: F)email.messager   smtplibSMTP_CONFIGadd_alternativeSMTPehlostarttlsloginsend_messagequit	Exceptionprintstr)to_emailsubject	body_htmlr   r>   msgserveres           r)   send_email_genericrP   H   s    *
.Cf%CKCIC	N	62k&1;v3FPRS[(+f*=>C  QC !c!f}s   BC 	C?C:4C?:C?c                      	 t        dt                t        j                  di t        } t        d       | S # t        $ r}t        d|         d}~ww xY w)uB   Получение соединения с базой данныхuN   🔌 Попытка подключения к БД с параметрами: uF   ✅ Соединение с БД установлено успешноu1   ❌ Ошибка подключения к БД: N )rH   	DB_CONFIGpsycopg2connectrG   )connrO   s     r)   get_db_connectionrW   `   s]    ^_h^ijk,),VW A!EFs   7: 	AAAc                 j    	 t        |       }t        |j                  |j                  g      S #  Y yxY w)u   Валидация URLF)r   allschemenetloc)urlresults     r)   validate_urlr^   k   s2    #FMM6==122s   +. 2c                     	 t        j                  d|       }|r|j                  d      S t        j                  d|       }|r|j                  d      S y#  Y yxY w)u8   Извлечение ID товара из URL AliExpressz(\d+)\.html   z
item/(\d+)N)researchgroup)r\   matchs     r)   extract_product_id_from_urlre   s   sX    		.#.;;q>! 		--;;q>!s   (A (A Az?/var/www/html/mycamper/aliexpress-site/frontend/images/products>   gifjpgpngjpegwebpc                 `    d| v xr) | j                  dd      d   j                         t        v S )N.r`   )rsplitlowerALLOWED_EXTENSIONS)filenames    r)   allowed_filerq      s0    (?WxsA6q9??AEWWWr+   c                 N   	 d| v r8| j                  dd      \  }}d|v rd}n d|v sd|v rd}nd|v rd}nd|v rd}nd}n| }d}t        t        j                               }|rd	| d
| d| }nd| d| }t        j
                  j                  t        |      }t	        j                  t        d       t        j                  |      }t        |d      5 }	|	j                  |       ddd       d| }
|
dfS # 1 sw Y   xY w# t        $ r}dt        |      fcY d}~S d}~ww xY w)u>   Сохранение base64 изображения в файлdata:image/,r`   rh   ri   rg   rf   rj   product__rl   image_T)exist_okwbNz/frontend/images/products/)splitrI   uuiduuid4r$   pathjoinUPLOAD_FOLDERmakedirsbase64r   openwriterG   )base64_data
product_idheaderdataext	unique_idrp   filepath
image_datar2   file_urlrO   s               r)   save_base64_imager      sG   *K'&,,S!4LFD6!Uf_&6!DC 

%	!*Qyk3%@H	{!C51H 77<<x8 	MD1 %%d+
(D! 	 QGGJ	  0z:~	  	   SV|s6   CD C8'D 8D=D 	D$DD$D$z/api/upload-imagePOST)methodsc                  H   	 t        j                         } | rd| vrt        ddd      dfS | d   }| j                  d      }t	        ||      \  }}|rt        dd| d      dfS t        d	|d
d      S # t
        $ r#}t        dt        |      d      dfcY d}~S d}~ww xY w)u7   Endpoint для загрузки изображенийimageFu6   Изображение не предоставленоsuccesserror  r   u:   Ошибка сохранения изображения:   Tu8   Изображение успешно загружено)r   	image_urlmessageN)r   get_jsonr   getr   rG   rI   )r   base64_imager   r   r   rO   s         r)   upload_imager      s    !wd* Q   
 G}XXl+
 ,L*E% UV[U\]   
 !Q
  	  V
   	s(   )A5 9A5 &A5 5	B!>BB!B!z!/api/newsletter/subscribers-countGETc                  :   	 t               } | j                         }|j                  d       |j                         d   }|j	                          | j	                          t        d|d      S # t        $ r#}t        dt        |      d      dfcY d }~S d }~ww xY w)NzCSELECT COUNT(*) FROM newsletter_subscribers WHERE confirmed = TRUE;r   T)r   countFr   r   )rW   cursorexecutefetchonecloser   rG   rI   )rV   curr   rO   s       r)   get_subscribers_countr      s    
A "kkmYZq!		

4%899 A53q6:;S@@As   A+A. .	B7BBBz/api/newsletter/sendc                     t         j                  } | j                  d      }| j                  d      }| j                  dd      }|r|st        ddd      dfS 	 t	               }|j                         }|rt        d   g}n1|j                  d	       |j                         D cg c]  }|d
   	 }}|j                          |j                          |st        ddd      dfS d
}|D ]  }	t        |	||      \  }
}|
s|dz  } t        d|d      S c c}w # t        $ r#}t        dt        |      d      dfcY d }~S d }~ww xY w)NrK   bodyisTestFu-   Тема и текст обязательныr   r   r   z@SELECT email FROM newsletter_subscribers WHERE confirmed = TRUE;r   u.   Нет активных подписчиков  r`   T)r   
sent_countr   )r   jsonr   r   rW   r   r?   r   fetchallr   rP   rG   rI   )r   rK   r   is_testrV   r   emailsrowr   emailr   errrO   s                r)   send_newsletterr      sL    <<Dhhy!G88FDhhx'G$53bcdfiiiA "kkm!&)*F KKZ[(+7c!f7F7		

u7ghiknnn
 	 E-eWdCLGSa
		  4zBCC 8"  A53q6:;S@@As=   A
D $D03D $D >D D 	E!D?9E?Ez"/static/images/products/<filename>c                 8    	 ddl m}  |t        |       S #  Y yxY w)u:   Отдача загруженных изображенийr   )send_from_directory)zFile not foundr   )flaskr   r   )rp   r   s     r)   uploaded_filer     s!    %-"=(;;%$s    c                     | dz   |z   j                         g dg dg dg dg dg dg dd	}|j                         D ]  \  }}t        fd
|D              s|c S  y)uS   Автоматическое определение категории товара )u   panel słonecznybateriafalowniku
   ładowarkalatarkaradiogps	nawigatorr   z
power bankz	dioda LEDu   oświetlenie)przewodzarowkagniazdko	sterowniku   Złącze)	kuchenkagarnekpatelniau   lodówkatermosnaczyniagazpalnikrondel)
u   śpiwórpoduszkamaterackocu   krzesłou   stółu   leżankahamaknamiotmarkiza)	u
   narzędzieu   śrubokrętkluczpompau   sprężarkau
   podnośnikkabellinau   wyciągarka)apteczkau   gaśnicaalarmzameksejfczujnikkamerazabezpieczenia)	filtrr   zbiornikkranu   wążprysznictoaletaszamboczyszczenie)electronics	electricscookingcomforttoolssafetywaterc              3   &   K   | ]  }|v  
 y wNrR   ).0keywordtexts     r)   	<genexpr>z%categorize_product.<locals>.<genexpr>5  s     77w$7s   other)rn   itemsany)titledescription
categoriescategorykeywordsr   s        @r)   categorize_productr   %  sp    CK+%,,.D oPr}}kpJ )..0 (7h77O r+   c           
         	 t               }|j                  t        j                  j                        }|j                  d| f       g }|j                         D ]A  }|j                  |d   |d   |d   |d   |d   |d   r|d   j                         nd	d
       C |j                          |j                          |S # t        $ r}t        d|        g cY d	}~S d	}~ww xY w)?   Получение всех изображений товараcursor_factoryz
            SELECT id, image_url, is_main, sort_order, alt_text, created_at
            FROM product_images
            WHERE product_id = %s
            ORDER BY sort_order ASC, id ASC
        idr   is_main
sort_orderalt_text
created_atN)r   r   r   r   r   r  zError getting product images: )rW   r   rT   extras
DictCursorr   r   append	isoformatr   rG   rH   )r   rV   r   imagesr   rO   s         r)   get_product_imagesr  :  s     "HOO,F,FG 
 ]	 ??$ 	CMM$i -y>!,/
O?B<?Pc,/99;VZ 	 	

 .qc23	s   B>C 	C$
CC$C$z/api/productsc                     d} d}	 t        j                         }t        d|        g d}|D ])  }|j                  |      rt	        dd| dd      dfc S  t        |d	         st	        dd
d      dfS 	 t        |d         }|dk  rt	        ddd      dfS 	 t        |d	         }|j                  d      }|st        |d   |j                  dd            }t               } | j                         }d| _        t        d       |j                  d|d	   |f       |j                         }|r!t        d|d           t	        ddd      dfS |j                  d      }	|	rOt        |	t               rt#        j$                  |	      }	n)t        |	t&              r	 t#        j(                  |	       nd}	dpd}
dqd}drd}t        d|	        t        d       d} ||j                  d      d       ||j                  d             ||j                  d             |
|j                  d      d      |j                  d       r |
|j                  d             nd ||j                  d!             ||       ||j                  d"             ||j                  d	      d       |
|j                  d#      d       ||j                  d$      d       ||      d%t-        j.                         t-        j.                         g}t        d&       t1        |      D ]'  \  }}t        d'|d(z   d)d*| d+t3        |       d,       ) t        d-       |j                  ||       |j                         d   }t        d.|        g }g }d}|	r;t        |	t               rt#        j$                  |	      }nt        |	t&              r|	}nd} ||j                  d/            | ||j                  d0             ||j                  d1            |j                  d2      r |
|j                  d2            nd ||j                  d3             ||j                  d4            d5}t        d6       |j5                         D ]k  \  }}t        d'| d7| d+t3        |       d,       t        |t               s5t        d8| d9       t#        j$                  |      }|||<   t        d:|        m |j5                         D ]3  \  }}|	|dk7  s|j7                  | d;       |j7                  |       5 |r_|j7                  |       d<d=j9                  |       d>}t        d?|        t        d@|        |j                  ||       t        dA       |j                  dBg       }t        dCt;        |       dD       |rt        dEt;        |       dF       	 |j                  dG       t        dH       t1        |      D ]y  \  }}	 d}t        dJ|d(z           t        |t&              r|j?                         }nCt        |t               r!|j                  dKd      j?                         }nt        dL|d(z           |jA                  dM      rOt        dN|d(z    dO       tC        ||      \  }}|rt        dP|d(z    d7|        |}t        dQ|d(z    dR|        n@|jA                  dS      rt        dT|d(z    dU|ddV  dW       |}nt        dX|d(z    dY       |rYt        dZ|d(z    d[       |j                  d\|||dk(  |d]|d(z    f       |j                         d   }t        dQ|d(z    d^|        | |j                  d`|f       |j                         d   }!t        da|!        nt        db       t        dc       | jI                          |j                  dd|f       |j                         d   }"t        de|" df|        |jK                          | jK                          t        dg| dh       t	        didj|dk      dlfS # t        $ r t	        ddd      dfcY S w xY w# t"        j*                  $ r d}	Y w xY w# t<        $ r}t        dI|        Y d}~d}~ww xY w# t<        $ r3}t        d_|d(z    d7|        ddl"} | jG                          Y d}~d}~ww xY w# t<        $ r}#t        dm|#        ddl"} | jG                          | r$	 | jM                          t        dn       n#  Y nxY w|r|jK                          | r| jK                          t	        dt'        |#      d      dofcY d}#~#S d}#~#ww xY w)su.   Добавление нового товараNuM   📥 Получены данные для добавления товара: r   pricealiexpress_linkF	   Поле 3    обязательно для заполненияr   r   r  !   Неверный формат URLr
  r   <   Цена не может быть отрицательной&   Неверный формат ценыr   r   original_description *   🔄 Начинаем транзакциюz
            SELECT id FROM products 
            WHERE aliexpress_link = %s OR (external_product_id = %s AND external_product_id IS NOT NULL)
        >   ❌ Товар с таким URL уже существует: 8   Товар с таким URL уже существует  specificationsc                 d    | 
| dk(  s| dk(  r|S 	 t        |       S # t        t        f$ r |cY S w xY wNr  Nonefloat
ValueError	TypeErrorvaluedefaults     r)   
safe_floatzadd_product.<locals>.safe_float  @    }uU|#	*    
 //c                 v    | 
| dk(  s| dk(  r|S 	 t        t        |             S # t        t        f$ r |cY S w xY wr  intr  r  r  r  s     r)   safe_intzadd_product.<locals>.safe_int  E    }u5<((	*    $ 88c                     | 
| dk(  s| dk(  r|S t        | t        t        f      rt        j                  |       S t        |       S r  
isinstancedictlistr   dumpsrI   r  s     r)   safe_strzadd_product.<locals>.safe_str  s?    }u%$.zz%((u:r+   u<   📊 Подготовленные спецификации: u@   🔄 Используем упрощенную вставку...a  
            INSERT INTO products (
                title, ai_description, original_description, price, original_price,
                main_image, category, epn_link, aliexpress_link, rating, orders_count,
                external_product_id, status, created_at, updated_at
            ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            RETURNING id
        ai_descriptionoriginal_price
main_imageepn_linkratingorders_countactiveu@   🔍 Проверка упрощенных параметров:z  r`   2dz. u
    (тип: )uK   🚀 Выполняем упрощенную вставку товара...u'   ✅ Товар вставлен с ID: detailed_descriptionshipping_info	video_urlweight
dimensionswarranty_info)r;  r  r<  r=  r>  r?  r@  u>   🔍 Проверка дополнительных полей:: u       ❌ СЛОВАРЬ в u   ! Преобразуем...u$       ✅ Преобразовано:  = %sz6
                UPDATE products 
                SET , z+
                WHERE id = %s
            u?   🔄 Обновляем дополнительные поля: u.   🔢 Параметры обновления: u<   ✅ Дополнительные поля обновленыr  uM   🖼️ Получены изображения для добавления:     шт.u,   🖼️ Начинаем обработку u    изображенийa  
                    CREATE TABLE IF NOT EXISTS product_images (
                        id SERIAL PRIMARY KEY,
                        product_id INTEGER NOT NULL,
                        image_url TEXT NOT NULL,
                        is_main BOOLEAN DEFAULT FALSE,
                        sort_order INTEGER DEFAULT 0,
                        alt_text VARCHAR(255),
                        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                        
                        CONSTRAINT fk_product_images_product_id 
                            FOREIGN KEY (product_id) 
                            REFERENCES products(id) 
                            ON DELETE CASCADE
                    );
                u.   ✅ Таблица product_images готоваu2   ❌ Ошибка создания таблицы: u/   🔍 Обработка изображения r   <   ⚠️ Неизвестный тип изображения rs      📥 Изображение @    в формате base64, сохраняем как файл...=   ❌ Ошибка сохранения изображения    ✅ Изображение %    сохранено как файл: zhttp://zhttps://   🔗 Изображение     по URL: d   ...   ⚠️ Изображение E    имеет неизвестный формат, пропускаем/   🚀 Добавляем изображение     в БД
                            INSERT INTO product_images (product_id, image_url, is_main, sort_order, alt_text)
                            VALUES (%s, %s, %s, %s, %s)
                            RETURNING id
                        Image     добавлено с ID B   ❌ Ошибка при обработке изображения z9SELECT COUNT(*) FROM product_images WHERE product_id = %su;   📊 Итого добавлено изображений: u=   ℹ️ Изображения не предоставлены-   💾 Коммитим транзакцию...z+SELECT COUNT(*) FROM products WHERE id = %su9   🔍 Финальная проверка: найдено u    товаров с ID    ✅ Товар ID uQ    успешно добавлен и закоммичен в базу данныхTu*   Товар успешно добавленr   r   r      u;   ❌ Ошибка при добавлении товара: *   🔄 Транзакция откаченаr   g        r   )r  )'r   r   rH   r   r   r^   r  r  re   r   rW   r   
autocommitr   r   r-  r.  r   r0  rI   loadsJSONDecodeErrorr   now	enumeratetyper   r  r~   lenrG   strip
startswithr   	traceback	print_exccommitr   rollback)$rV   r   r   required_fieldsfieldr
  r   r   existingr  r"  r(  r1  simple_insert_querysimple_paramsir   new_product_idupdate_fieldsupdate_paramssafe_specificationsadditional_fieldsupdate_queryr  create_errorr   r   r   r   r   image_id	img_errorrh  added_images_countfinal_checkrO   s$                                       r)   add_productr}  \  s
    DFS!]^b]cde @$ 	E88E?$(/bc    	 D!234 <   	$w-(Eqy$[      16G1HI
 88J')W/4H !"  :; 	  $%z2	4
 ??$RS[\]S^R_`a S    "23.$/!%N!;NC0*JJ~. "&			 	L^L\]^ 	PQ TXXg&+TXX./0TXX456txx(!,6:hh?O6PJtxx 012VZTXXl+,XTXXj)*TXX/0"5txx)1-TXXn-q1Z LLNLLN
$ 	PQ!-0 	BHAuBqs2hbz$u+a@A	B 	[\*M:  *1-77GHI  #.$/&*jj&@#NC0&4#&*# %-TXX6L-M$N1%dhh&?@!$((;"788<8Jj(!34PT"488L#9:%dhh&?@
 	NO-335 	FLE5BugRwjeQ?@%&25'9TUV

5)+0!%(<UGDE	F .335 	,LE5 Ub[$$we_5$$U+	,
   0 YY}-. /L
 STaSbcdB=/RSNN<7PQ
 (B']^abh^i]jjpqr@VMdef[     FG
 &f- 958 $IKAaC5QR!%-%*[[]
#E40%*YY{B%?%E%E%G
 \]^_`]`\abc  ",,]; <QqSE  BB  C  D +<J*W% !$abcdebeaffhinho"pq$$,	 ;AaC5@efoepqr#../FG <QqSEZX\Y\M]L^^abc$.	  >qse  DI  J  K   OPQRSPSuT\]^ (
 +%F$QqSEN	
 $*??#4Q#7 ;AaC5@Z[cZdefg9x NNVYgXij!'!21!5OPbOcdeQR
 	=> 	D~FWXoo'*I+Vlm{l|}~

">"2  3D  E  	FC(
  	 	w  	 A   	^ ++ *%)N*l  [J<.YZZ[r ! ^_`ab_b^ccefoepqr$'')	F  KA3OP BC LLNJJLV
   	's$  <c. c. c. 9"a B6c. A	c. a. 2L c. 3Ac. c. Cc. b
 5c. A6b/>c. ?Ab/c. Ab/c. Ab/:Cc. a+(c. *a++c. .bc. bc. 
	b,b'!c. 'b,,c. /	c+8(c& c. &c++c. .	f7$fd87f8d<:Af;ffc                     	 t        d       t        t        j                  j	                  dd            } t        t        j                  j	                  dd            }t        j                  j	                  d      }t        j                  j	                  d      }t        j                  j	                  dd	      j                         }t        j                  j	                  d
      }|d}|dkD  rd}| dz
  |z  }t        d|  d| d| d| d| 
       d}|g}|r|dz  }|j                  |       |rs|dk(  r|dz  }|j                  d       nW|dk(  r|dz  }|j                  ddg       n9|dk(  r|dz  }|j                  ddg       n|dk(  r|dz  }|j                  d       |r |dz  }d | d }	|j                  |	|	|	|g       |r|d!z  }|j                  |       n|d"z  }|d#z  }|j                  ||g       t        j                  j                  d$| d%       t        j                  j                  d&| d%       t        j                  j                          t               }
|
j                  t        j                  j                   '      }|j#                  ||       |j%                         }t        d(t'        |              g }|D ]
  }|j#                  d)|d*   f       |j%                         D cg c]!  }t)        |d*   |d+   |d,   |d-   |d.   /      # }}|j                  i d*|d*   d0|d0   d1|d1   d2|d2   d3|d3   rt+        |d3         nd4d5|d5   rt+        |d5         ndd6|d6   d|d   d7|d7   d8|d8   d9|d9   d:|d:   rt+        |d:         nd4d;|d;   xs d4d
|d
   d<|d<   r|d<   j-                         ndd=|        |j/                          |
j/                          t1        d>|| |d?      S c c}w # t2        $ rE}t        d@|        d4dl}|j7                          t1        dAt9        |      dB      dfcY d}~S d}~ww xY w)Cu|   Получение списка товаров с фильтрацией, поиском и автоподстановкойu5   🔍 Начало выполнения get_products()pager`   limit   r   price_rangerb   r  statusNr8     u   📋 Параметры: page=z, limit=z, category=z
, search='z
', status=a)  
            SELECT id, title, ai_description, original_description, price, 
                   original_price, main_image, category, epn_link, 
                   aliexpress_link, video_url, rating, orders_count, status, created_at
            FROM products
            WHERE status = %s
        z AND category = %sz0-100z AND price <= %srN  z100-500z AND price > %s AND price <= %sr   z500-1000i  z1000+z AND price > %sz
                AND (
                    title ILIKE %s
                    OR ai_description ILIKE %s
                    OR original_description ILIKE %s
                    OR title %% %s
                )
            %z- ORDER BY similarity(title, %s) DESC, id DESCz ORDER BY id DESCz LIMIT %s OFFSET %su   
📋 SQL запрос: 
u   🔢 Параметры: r   u&   📈 Получено товаров: z
                SELECT id, image_url, is_main, sort_order, alt_text
                FROM product_images
                WHERE product_id = %s
                ORDER BY sort_order ASC, id ASC
            r   r   r   r   r   )r   r   r   r   r   r   r2  r  r
  r   r3  r4  r5  r  r=  r6  r7  r  r  T)r   productsr  r  u$   ❌ ОШИБКА в get_products(): Fr   )rH   r'  r   r/   r   rf  r  extendsysstdoutr   flushrW   r   rT   r  r  r   r   re  r.  r  r  r   r   rG   rh  ri  rI   )r  r  r   r  rb   r  offsetqueryparamslikerV   r   rowsr  r   rq  r  rO   rh  s                      r)   get_productsr    s   ZAEF7<<##FA./GLL$$Wb12<<##J/ll&&}5!!(B/557!!(+>F3;E(e#.tfHUG;xjXbcibjjtu{t|}~
 
 ))EMM(#
 g%++c"	)::sCj)
*::sDk*'**d#
   E vha=DMM4tV45
 DDEMM&!((E
 	&&ufo&

4UG2>?

4VHB?@


 !"HOO,F,FGuf% 6s4ykBC
  	CNN 
 d)  *  $1[>1Y< !,!J-IF  OO c$iW !#&6"7 ',B(C	
 Gs7|,! !#FVBW%,<(=">]a c,/ C
O C
O "3'8#9 S- #h-%H.Q N 3 8q #h- s<?Pc,/99;VZ  &! 	B 	

 	
  	9F  A4QC8953q6:;S@@	As1   L P &P(C+P P 	Q'":Q"Q'"Q'z/api/products/<int:product_id>PUTc                    d}d}	 t        j                         }t        d|  d|        g d}|D ])  }|j                  |      rt	        dd| dd      d	fc S  t        |d
         st	        ddd      d	fS 	 t        |d         }|dk  rt	        ddd      d	fS 	 t        |d
         }t               }|j                         }d|_        t        d       |j                  d| f       |j                         s0|j                          |j                          t	        ddd      dfS |j                  d|d
   || f       |j                         }|r!t        d|d           t	        ddd      dfS dUd}	dVd}
dWd}g d} ||j                  d      d       ||j                  d      d !       ||j                  d"      d !       |	|j                  d      d      |j                  d#      r |	|j                  d#            nd ||j                  d$      d !       ||j                  d%t         ||j                  dd             ||j                  d"d      d !      xs d            d&       ||j                  d'      d !       ||j                  d
      d !       |	|j                  d(      d       |
|j                  d)      d       ||      t!        j"                          ||j                  d*      d !       ||j                  d+      d !       ||j                  d,      d !      |j                  d-      r |	|j                  d-            nd ||j                  d.      d !       ||j                  d/      d !      g}d0d1j%                  |       d2}|j'                  |        t        d3|  d4       |j                  ||       |j                  d5g       }|rt        d6|  dt)        |       d7       t+        |      D ]~  \  }}	 d}t-        |t.              r|j1                         }nCt-        |t2              r!|j                  d8d      j1                         }nt        d9|d:z           n|j5                  d;      rOt        d<|d:z    d=       t7        ||       \  }}|rt        d>|d:z    d|        |}t        d?|d:z    d@|        n@|j5                  dA      rt        dB|d:z    dC|ddD  d4       |}nt        dE|d:z    dF       |rot        dG|d:z    dH       |j                  dI| ||dk(  | ||j                  ddJ|d:z                f       |j                         d   }t        d?|d:z    dK|         t        dM       |j;                          |j                          |j                          t        dN|  dO       t	        d dP| dQ      S # t        $ r t	        ddd      d	fcY S w xY w# t8        $ r}t        dL|d:z    d|        Y d}~d}~ww xY w# t8        $ r}t        dR|        ddl}|j?                          |r$	 |jA                          t        dS       n#  Y nxY w|r|j                          |r|j                          t	        dt/        |      d      dTfcY d}~S d}~ww xY w)Xu<   Обновление существующего товараNuL   📥 Получены данные для обновления товара rA  r	  Fr  r  r   r   r  r  r
  r   r  r  r  %SELECT id FROM products WHERE id = %s   Товар не найденr   z
            SELECT id FROM products 
            WHERE (aliexpress_link = %s OR (external_product_id = %s AND external_product_id IS NOT NULL))
            AND id != %s
        r  r  r  c                 d    | 
| dk(  s| dk(  r|S 	 t        |       S # t        t        f$ r |cY S w xY wr  r  r  s     r)   r"  z"update_product.<locals>.safe_float  r#  r$  c                 v    | 
| dk(  s| dk(  r|S 	 t        t        |             S # t        t        f$ r |cY S w xY wr  r&  r  s     r)   r(  z update_product.<locals>.safe_int  r)  r*  r  c                     | 
| dk(  s| dk(  r|rd S |S t        | t        t        f      rt        j                  |       S t        |       S r  r,  )r   r!  
allow_nulls      r)   r1  z update_product.<locals>.safe_str  sG    }u(d5g5%$.jj''u:r+   )z
title = %szai_description = %szoriginal_description = %sz
price = %szoriginal_price = %szmain_image = %szcategory = %szepn_link = %szaliexpress_link = %szrating = %szorders_count = %szexternal_product_id = %szupdated_at = %szdetailed_description = %szshipping_info = %szvideo_url = %szweight = %szdimensions = %szwarranty_info = %sr   )r!  r2  T)r  r  r3  r4  r   r   r5  r6  r7  r;  r<  r=  r>  r?  r@  z.
            UPDATE products 
            SET rC  z#
            WHERE id = %s
        u:   🔄 Выполняем обновление товара rO  r  uF   🖼️ Обновляем изображения для товара rD  r   rE  r`   rs   rF  rG  rH  rI  rJ  rK  rL  rM  rN  rP  rQ  rR  rS  rT  rU  rV  rW  rX  rY  u     успешно обновлёнu*   Товар успешно обновлёнrZ  u;   ❌ Ошибка при обновлении товара: r\  r   r]  r^  )r  F)!r   r   rH   r   r   r^   r  r  re   rW   r   r_  r   r   r   r   r   rb  r~   r  re  rc  r-  rI   rf  r.  rg  r   rG   rj  rh  ri  rk  )r   rV   r   r   rl  rm  r
  external_product_idrn  r"  r(  r1  rs  rt  rw  r  rq  r   r   r   r   r   ry  rz  rO   rh  s                             r)   update_productr  W  s    DFy!\]g\hhjkojpqr @$ 	E88E?$(/bc    	 D!234 <   	$w-(Eqy$[      :$?P:QR !":;>N LLNJJL 7    	  $%':JG		I ??$RS[\]S^R_`a S   .			
. TXXg&3TXX./DATXX45$Gtxx(!,6:hh?O6PJtxx 012VZTXXl+=TXXj*<TXXgr*+Xdhh?UWY6Zgk-l-rpr+ ! TXXj)d;TXX/0TBtxx)1-TXXn-q1()LLNTXX45$GTXXo.4@TXXk*t<.2hhx.@Jtxx)*dTXXl+=TXXo.4@+
0=)* +	
 	Z(J:,VYZ[|]3 (B'Z[eZffhilmsithuu{|} &f- +5* $I!%-%*[[]
#E40%*YY{B%?%E%E%G
 \]^_`]`\abc !,,]; <QqSE  BB  C  D*;J
*S% !$abcdebeaffhinho"pq$$,	 ;AaC5@efoepqr#../FG <QqSEZX\Y\M]L^^abc$.	 >qse  DI  J  K   OPQRSPSuT\]^ (
 '%F$TXXg!u~%FG	
 $*??#4Q#7 ;AaC5@Z[cZdefQ+Z 	=>

":,.NOPC$
  	O  	 A   	v ! ^_`ab_b^ccefoepqr"  KA3OPBCLLNJJLV
   	s   ?X? X? X? <"W5 BX? -A
X? 8J)X? "A%XX? AXX? AX&X? (A1XAX? 5XX? XX? 	X<X71X? 7X<<X? ?	[$[-Z	[	ZA[[[c           	      0   	 t               }|j                  t        j                  j                        }|j                  d| f       |j                         }|s0|j                          |j                          t        ddd      dfS |j                  d| f       |j                         }|r
|d   r|d   nd	}|j                          |j                          i d
|d
   d|d   d|d   d|d   d|d   d|d   rt        |d         nd	d|d   rt        |d         ndd|d   d|d   d|d   d|d   d|d   rt        |d         nd	d|d   xs d	d|d   d|d   r|d   j                         ndd|d   d|d   |d   |d   rt        |d         nd|d   |d   |j                  d       rt        j                  |d          ng |d!}t        d"|d#      S # t        $ r#}t        dt        |      d      d$fcY d}~S d}~ww xY w)%uJ   Получение детальной информации о товареr   a  
            SELECT p.*, 
                   COALESCE(
                       (SELECT json_agg(
                           json_build_object(
                               'id', pi.id,
                               'image_url', pi.image_url,
                               'is_main', pi.is_main,
                               'sort_order', pi.sort_order,
                               'alt_text', pi.alt_text
                           ) ORDER BY pi.sort_order ASC, pi.id ASC
                       )
                       FROM product_images pi 
                       WHERE pi.product_id = p.id),
                       '[]'::json
                   ) as images
            FROM products p
            WHERE p.id = %s
        Fr  r   r   zu
            SELECT SUM(clicks) as total_clicks
            FROM analytics
            WHERE product_id = %s
        total_clicksr   r   r   r2  r  r;  r
  r3  Nr4  r   r5  r  r6  r7  r  r  r  r<  r=  r>  r?  r@  product_images_list)r=  r>  r?  r@  r  r  T)r   productr   )rW   r   rT   r  r  r   r   r   r   r  r  r   r   r`  rG   rI   )r   rV   r   r  statsr  product_datarO   s           r)   get_product_detailr  Y  s   S "HOO,F,FG 	 $ ]%	( //#LLNJJL 7    	  ]		 !05%:Ou^,UV


'$-
WW%
 g&67
 #G,B$C	

 #G,B$C
 0@U77+,a
 'JZB[eG,<$=>ae
 ',/
 
+
 
+
 w'89
 '(2CeGH-.
 GN38q
 gh'
 w|?T',/99;Z^
  g&67!
" W_5#
$ !-29(2CeGH-.!,/$_5DKKKPeDfdjj)>!?@ln(/
4 #
  	
  V
   	s%   BG) EG) )	H2H
HHz%/api/products/<int:product_id>/imagesc                     	 t        |       }t        d|d      S # t        $ r#}t        dt        |      d      dfcY d}~S d}~ww xY w)r   T)r   r  Fr   r   N)r  r   rG   rI   )r   r  rO   s      r)   get_product_images_apir    sa    #J/
  	
  V
   	s    	AAAAc                 L   	 t        j                         }|j                  d      }|j                  dd      }|j                  dd      }|j                  dd      }|st        ddd	      d
fS t	        |      st        ddd	      d
fS t               }|j                         }|j                  d| f       |j                         s0|j                          |j                          t        ddd	      dfS |r|j                  d| f       |j                  d| ||||f       |j                         d   }|j                          |j                          |j                          t        dd|d      dfS # t        $ r#}	t        dt        |	      d	      dfcY d}	~	S d}	~	ww xY w)u;   Добавление изображения к товаруr   r   Fr   r   r   r  u   image_url обязателенr   r   u8   Неверный формат URL изображенияr  r  r   
                UPDATE product_images 
                SET is_main = FALSE 
                WHERE product_id = %s
            z
            INSERT INTO product_images (product_id, image_url, is_main, sort_order, alt_text)
            VALUES (%s, %s, %s, %s, %s)
            RETURNING id
        Tu8   Изображение успешно добавлено)r   r   ry  r[  r   N)r   r   r   r   r^   rW   r   r   r   r   rj  rG   rI   )
r   r   r   r   r   r   rV   r   ry  rO   s
             r)   add_product_imager    s   @!HH[)	((9e,XXlA.
88J+ 9   
 I& S   
 !" 	>N LLNJJL 7    NN  	  	  )Wj(C		E ??$Q'

Q 
  	 	  V
   	s2   A,E7 /E7 
A,E7 7A?E7 7	F# FF#F#z4/api/products/<int:product_id>/images/<int:image_id>c                    	 t        j                         }t               }|j                         }|j	                  d|| f       |j                         s0|j                          |j                          t        ddd      dfS |j                  d      r|j	                  d| f       g }g }dD ]/  }||v s|j                  | d	       |j                  ||          1 |r8|j                  || g       |j	                  d
dj                  |       d|       |j                          |j                          |j                          t        ddd      S # t        $ r#}t        dt        |      d      dfcY d}~S d}~ww xY w)u8   Обновление изображения товараb
            SELECT id FROM product_images 
            WHERE id = %s AND product_id = %s
        F*   Изображение не найденоr   r   r   r  )r   r   r   r   rB  z<
                UPDATE product_images 
                SET rC  z?
                WHERE id = %s AND product_id = %s
            Tu8   Изображение успешно обновленоr   r   r   N)r   r   rW   r   r   r   r   r   r   r  r  r~   rj  rG   rI   )	r   ry  r   rV   r   rs  r  rm  rO   s	            r)   update_product_imager    s   :! " 	  
#	%
  LLNJJL E    88INN  	  G 	+E}$$we_5d5k*	+
 MM8Z01NN  YY}-. / 	 	

Q
  	
  V
   	s+   BE 1E 6B!E 	F!E?9F?FDELETEc                    	 t               }|j                         }|j                  d|| f       |j                         s0|j	                          |j	                          t        ddd      dfS |j                  d|| f       |j                          |j	                          |j	                          t        ddd	      S # t        $ r#}t        dt        |      d      d
fcY d}~S d}~ww xY w)u4   Удаление изображения товараr  Fr  r   r   z_
            DELETE FROM product_images 
            WHERE id = %s AND product_id = %s
        Tu4   Изображение успешно удаленоr  r   N)	rW   r   r   r   r   r   rj  rG   rI   )r   ry  rV   r   rO   s        r)   delete_product_imager  F  s   % " 	  
#	%
  LLNJJL E    	  
#	%
 	

M
  	
  V
   	s%   A-C 0AC 	C.C)#C.)C.c                    	 t               }|j                         }|j                  d| f       |j                         s0|j	                          |j	                          t        ddd      dfS |j                  dt        j                         | f       |j                          |j	                          |j	                          t        ddd	      S # t        $ r#}t        dt        |      d      d
fcY d}~S d}~ww xY w)u=   Удаление товара (мягкое удаление)r  Fr  r   r   zt
            UPDATE products 
            SET status = 'deleted', updated_at = %s
            WHERE id = %s
        Tu&   Товар успешно удаленr  r   N)rW   r   r   r   r   r   r   rb  rj  rG   rI   )r   rV   r   rO   s       r)   delete_productr  v  s    " " 	>N LLNJJL 7    	  llnj)		+ 	

?
  	
  V
   	s%   A,C /A#C 	C?C:4C?:C?z/api/products/bulkc                  	   	 t        j                         } | j                  dg       }|st        ddd      dfS t	               }|j                         }d}g }t        |      D ]E  \  }	 t        fddD              s|j                  d	|d
z    d       5t        d         s|j                  d	|d
z    d       \t        d         }|j                  dd   |f       |j                         r|j                  d	|d
z    d       j                  d      }|st        d   j                  dd            }j                  d      }	|	rOt        |	t              rt!        j"                  |	      }	n)t        |	t$              r	 t!        j&                  |	       nd}	d}
|j                  |
d   j                  d      j                  d      j                  d      t+        d         j                  d      rt+        d         ndj                  d      |j                  d      d   t+        j                  dd            t-        j                  dd            |dt/        j0                         t/        j0                         |	j                  d       j                  d!      j                  d"      rt+        j                  d"            ndj                  d#      j                  d$      f       |j                         d   }j                  d%g       }|ryt        |      D ]k  \  }}t        |j                  d&d            s"|j                  d'||d&   |j                  d(d      |j                  d)|      |j                  d*d      f       m |d
z  }H |j5                          |j7                          |j7                          t        d,d-t9        |       d.| ||d/      S # t         j(                  $ r d}	Y rw xY w# t2        $ r.}|j                  d	|d
z    d+t%        |              Y d}~d}~ww xY w# t2        $ r#}t        dt%        |      d      d0fcY d}~S d}~ww xY w)1u4   Массовое добавление товаровr  FuA   Список товаров не может быть пустымr   r   r   c              3   @   K   | ]  }j                  |        y wr   )r   )r   rm  r  s     r)   r   z$add_products_bulk.<locals>.<genexpr>  s     a%7;;u-as   r	  u   Товар r`   u:   : отсутствуют обязательные поляr  u#   : неверный формат URLz
                    SELECT id FROM products 
                    WHERE aliexpress_link = %s OR (external_product_id = %s AND external_product_id IS NOT NULL)
                u   : дубликат URLr   r   r  r  r  NaV  
                    INSERT INTO products (
                        title, ai_description, original_description, detailed_description,
                        price, original_price, main_image, category, epn_link, aliexpress_link, 
                        rating, orders_count, external_product_id, status, created_at, updated_at,
                        specifications, shipping_info, video_url, weight, dimensions, warranty_info
                    ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                    RETURNING id
                r2  r;  r
  r3  r4  r5  r6  r7  r8  r<  r=  r>  r?  r@  additional_imagesr   z
                                INSERT INTO product_images (product_id, image_url, is_main, sort_order, alt_text)
                                VALUES (%s, %s, %s, %s, %s)
                            r   r   r   rA  Tu%   Обработано товаров: u   , добавлено: )r   r   added_counterrorsr   )r   r   r   r   rW   r   rc  rY   r  r^   re   r   r   r   r-  r.  r   r0  rI   r`  ra  r  r'  r   rb  rG   rj  r   re  )r   r  rV   r   r  r  rq  r   r   r  insert_queryrr  r  idxr   rO   r  s                   @r)   add_products_bulkr    sv   H!88J+ \   
 !"#H- g	=JAwf=a;`aaMMK!u4n"op $G,=$>?MMK!u4W"XY 9AR9ST
    /0*=?
 ??$MMK!u4J"KL #;;z21($:B? H ")-=!>!!.$7)-N)C#NC82 JJ~6 *.  |G$KK 01KK 67KK 67''*+8?DT8UE'"234[_KK-KK
+-.'++h23NA67LLNLLN"KK0KK,4;KK4IE'++h/0tKK-KK0-. 2 "(!21!5 %,KK0CR$H!$+45F+G Z'
{B(GH"NN ,  !/ *; 7 *y% @ *|S A *z2 >"	 q Ig	=R 	

>s8}oMcdocpq&	
  	I  $33 2-1N2z  =AaC53q6(;<<=  V
   	s   7Q 0Q ,,PQ &P?Q  APQ A;P
O<F9PAP*AQ <PPPP	Q!#Q
Q 
QQ 	Q>Q93Q>9Q>z/api/categoriesc                     	 t               } | j                  t        j                  j                        }|j                  d       |j                         D cg c]  }|d   |d   d }}|j                          | j                          t        d|d      S c c}w # t        $ r#}t        dt        |      d	      d
fcY d}~S d}~ww xY w)u2   Получение списка категорийr   
            SELECT category, COUNT(*) as count
            FROM products 
            WHERE status = 'active'
            GROUP BY category
            ORDER BY count DESC
        r   r   )namer   T)r   r   Fr   r   N)rW   r   rT   r  r  r   r   r   r   rG   rI   )rV   r   r   r   rO   s        r)   get_categoriesr  +  s     "HOO,F,FG  	 !' 13  #:WF 3
 3 	

$
  	3  V
   	s0   AB  B+/B  B   	C)CCCz/api/analytics/clickc                  D   	 t        j                         } | j                  d      }| j                  dd      }|st        ddd      dfS t	               }|j                         }|j                  d||f       |j                         }|r|j                  d	|d
   f       n|j                  d||f       |j                          |j                          |j                          t        ddi      S # t        $ r#}t        dt        |      d      dfcY d}~S d}~ww xY w)u/   Трекинг кликов по товарамr   sourcewebsiteFzproduct_id is requiredr   r   zy
            SELECT id FROM analytics 
            WHERE product_id = %s AND date = CURRENT_DATE AND source = %s
        zv
                UPDATE analytics 
                SET clicks = clicks + 1 
                WHERE id = %s
            r   z
                INSERT INTO analytics (product_id, clicks, source, date) 
                VALUES (%s, 1, %s, CURRENT_DATE)
            r   Tr   N)r   r   r   r   rW   r   r   r   rj  r   rG   rI   )r   r   r  rV   r   rn  rO   s          r)   track_clickr  K  s    (A!XXl+
(I.u7OPQSVVV " 	  &!	#
 ??$NN  1+	! NN  f%'
 	

	4()) A53q6:;S@@As%   AC3 B'C3 3	D<DDDz
/api/statsc                     	 t               } | j                  t        j                  j                        }|j                  d       |j                         }|j                  d       |j                         D cg c]  }|d   |d   d }}|j                  d       |j                         D cg c]  }|d   j                         |d	   d
 }}|j                  d       |j                         }|j                          | j                          t        d|d   |d   |d   |||d   |d   dd      S c c}w c c}w # t        $ r#}t        dt        |      d      dfcY d}~S d}~ww xY w)u'   Получение статистикиr   a  
            SELECT 
                COUNT(*) as total_products,
                COUNT(CASE WHEN status = 'active' THEN 1 END) as active_products,
                COUNT(CASE WHEN created_at::date = CURRENT_DATE THEN 1 END) as today_products
            FROM products
        r  r   r   )r   r   z
            SELECT DATE(date) as date, SUM(clicks) as clicks
            FROM analytics
            WHERE date >= CURRENT_DATE - INTERVAL '7 days'
            GROUP BY DATE(date)
            ORDER BY date
        dateclicks)r  r  z
            SELECT COUNT(*) as total_images,
                   COUNT(DISTINCT product_id) as products_with_images
            FROM product_images
        Ttotal_productsactive_productstoday_productstotal_imagesproducts_with_images)r  r  r  r   clicks_last_7_daysr  r  )r   r  Fr   r   N)rW   r   rT   r  r  r   r   r   r  r   r   rG   rI   )rV   r   r  r   r   clicks_dataimages_statsrO   s           r)   	get_statsr  x  s   AA "HOO,F,FG 	  	 ! 	  	 !' 13 $'z?S\J 3
 3 	  	 "(!24 !$F 5 5 73x=Q 4 4 	  	 (

"'(8"9#():#;"'(8"9(&1 ,^ <(45K(L
  	7348  A53q6:;S@@As=   A8E :D9%E 1 D>A'E 9
E 	E/E*$E/*E/z/api/healthc                  `    t        ddt        j                         j                         d      S )u7   Проверка работоспособности APITu'   API работает корректно)r   r   	timestamp)r   r   rb  r  rR   r+   r)   health_checkr    s.     <\\^--/  r+   z/api/parser/startc                     	 t        j                         } | j                  dg       | j                  dd      st        ddd      dfS t	        t
              r>j                  d      D cg c]#  }|j                         s|j                         % c}t        d	t               d
       t        d        ddl
}fd}|j                  |      }d|_        |j                          t        ddt               dd      S c c}w # t        $ r1}t        d|        t        dt        |      d      dfcY d}~S d}~ww xY w)uD   Запуск парсера с официальным API AliExpressqueries	max_pagesr`   Fu5   Не указаны поисковые запросыr   r   r  u,   🎯 Запуск API парсера для u    запросовu   📝 Запросы: r   Nc                     	 ddl m} m} ddlm} t        d        || |      }t        dz  d      }t        d|        |j                  	|      }t        d	t        |              y # t        $ r#}t        d
|        t        d       Y d }~y d }~wt        $ r,}t        d|        dd l}|j                          Y d }~y d }~ww xY w)Nr   )ALIEXPRESS_APP_KEYALIEXPRESS_APP_SECRET)AliExpressAPIParseru5   🔑 Инициализация API парсера...   
   u8   📊 Максимум товаров на запрос: )max_products_per_queryuM   🎉 API парсинг завершен! Добавлено товаров: u!   ❌ Ошибка импорта: ue   🔧 Проверьте, что файлы config.py и aliexpress_api_parser.py существуютu(   ❌ Ошибка в API парсере: )configr  r  aliexpress_api_parserr  rH   minparse_and_savere  ImportErrorrG   rh  ri  )
r  r  r  parsermax_productsr  rO   rh  r  search_queriess
           r)   run_api_parserz$start_parser.<locals>.run_api_parser  s    &LEMO,-?AVW"9q="5PQ]P^_`!00Xd0eefijrfsetuv 9!=>}~~ &@DE ##%%&s$   A)A- -	C6BC "CC)targetTu)   API парсинг запущен для uq    запросов. Используется официальный API AliExpress с вашими ключами!r  u4   ❌ Ошибка запуска API парсера: r   )r   r   r   r   r-  rI   rz   rf  rH   re  	threadingThreaddaemonstartrG   )r   qr  r  threadrO   r  r  s         @@r)   start_parserr    sf   :!)R0HH[!,	 P    nc*1?1E1Ed1KYAqwwyaggiYN<S=P<QQbcd%n%567	&0 !!!8B3~CVBW  XI  J
  	G ZP  DQCHIV
   	s=   A	D #D 1DDA6D D 	E&E
E
Ez/api/parser/queriesc                  6    g dg dg dd} t        d| d      S )u^   Получение предустановленных запросов для парсинга)zcamping solar panelzrv battery 12vzportable camping stovezcamping mattress inflatable)zcar inverter 12v 220vzled strip 12vzcar charger usbzportable power bank)zcar tire pumpzemergency car kitzcar jump starterzautomotive tools set)campingr   r   T)r   r  )r   )r  s    r)   get_parser_queriesr    s2    


G*   r+   c                     t        j                  dd      j                  d      }| d| }d}d| d}t        | ||      S )NSITE_URLzhttps://campervan.fun/z/confirm-subscription?token=u)   Potwierdź subskrypcję — campervan.funu   
    <html>
    <body>
        <h2>Witaj!</h2>
        <p>Dziękujemy za zapisanie się na nowości campervan.fun</p>
        <p>Kliknij przycisk poniżej, aby potwierdzić subskrypcję:</p>
        <a href="u)  " style="background-color: #007bff; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px;">Potwierdzam subskrypcję</a>
        <p>Jeśli to nie Ty — zignoruj tę wiadomość.</p>
        <hr>
        <p>Pozdrawiamy, Zespół campervan.fun</p>
    </body>
    </html>
    )r$   r%   rstriprP   )r   tokensite_urlconfirm_urlrK   r   s         r)   send_confirmation_emailr  +  s]    yy%<=DDSIHJ:5'BK9G  D eWd33r+   z/api/subscribec                     	 t        j                         xs i } | j                  d      xs dj                         j	                         }|st        ddd      dfS dd l} |j                  d|      st        dd	d      dfS t               }|j                         }|j                  d
|f       |j                         }|r5|d   r0|j                          |j                          t        ddd      dfS t        j                  d      }|r|j                  d||d   f       |d   }n'|j                  d||f       |j                         d   }|j                          |j                          |j                          t!        ||      \  }}	d}
d}d| d}t#        |
||      \  }}|st        dd|	 d      dfS t        ddd      S # t$        $ r1}t'        dt)        |              t        ddd      dfcY d }~S d }~ww xY w)Nr   r  FzAdres e-mail jest wymaganyr   r   r   z[^@]+@[^@]+\.[^@]+u   Nieprawidłowy adres e-mailASELECT id, confirmed FROM newsletter_subscribers WHERE email = %sr`   u:   Wiadomość e-mail została już podpisana i potwierdzona.r      z
                UPDATE newsletter_subscribers
                SET token = %s, confirmed = FALSE, created_at = NOW(), confirmed_at = NULL
                WHERE id = %s
            z
                INSERT INTO newsletter_subscribers (email, token, confirmed, created_at)
                VALUES (%s, %s, FALSE, NOW())
                RETURNING id
            r   zNowy subskrybent na stronie!u  
            <div style="font-family: Arial, sans-serif; border: 1px solid #eee; padding: 20px;">
                <h2 style="color: #4f46e5;">🚀 Nowy subskrybent!</h2>
                <p>Ktoś właśnie zapisał się do newslettera:</p>
                <p><b>Adres e-mail:</b> u  </p> 
                <p><b>Data:</b> 14 Luty 2026</p>
                <hr style="border: 0; border-top: 1px solid #eee;">
                <p style="font-size: 12px; color: #666;">Wiadomość wygenerowana automatycznie przez campervan.fun</p>
            </div>
        u)   Błąd podczas wysyłania potwierdzenia: r   TuD   E-mail z potwierdzeniem został wysłany. Sprawdź swoją skrzynkę.r  zSERVER ERROR: u&   Wystąpił błąd wewnętrzny serwera.)r   r   r   rf  rn   r   ra   rd   rW   r   r   r   r   secretstoken_urlsaferj  r  rP   rG   rH   rI   )r   r   ra   rV   r   r   r  subscriber_idsentr   admin_emailsubject_admin
body_adminsuccess_adminerror_adminrO   s                   r)   	subscriber  @  s,   Hc!'R'"(b//1779u7STUWZZZ 	rxx-u5u7TUVX[[[ " 	Z]b\deoo3q6LLNJJLu7stuwzzz%%b)NN  Q	"
  FMNN  	!
 #OO-a0M

+E59	c 06) */ 0			
 &8]T^%_"{u9bcfbg7hijlooo44z{|| cs1vh'(53[\]_bbbcs8   AG &G A3G 8CG G 	H	&H>H	H	z/confirm-subscriptionc                     	 t         j                  j                  d      } | st        dd      S t	               }|j                         }|j                  d| f       |j                         }|s,|j                          |j                          t        dd      S |d   |d   |d	   }}}|r,|j                          |j                          t        d
d      S |j                  d|f       |j                          |j                          |j                          d| dt        j                  dd       d}t        |d      S # t        $ r}t        t        |      d      cY d }~S d }~ww xY w)Nr  zToken not providedr   zHSELECT id, email, confirmed FROM newsletter_subscribers WHERE token = %szToken invalid or expiredr   r   r`      zSubscription already confirmed.r  z
            UPDATE newsletter_subscribers
            SET confirmed = TRUE, confirmed_at = NOW(), token = NULL
            WHERE id = %s
        uN   
        <html><body>
        <h2>Dziękujemy!</h2>
        <p>E-mail <strong>uq   </strong> został potwierdzony. Otrzymasz od nas wiadomości z promocjami i artykułami.</p>
        <p><a href="r  r  u<   ">Powrót na stronę</a></p>
        </body></html>
        r   )r   r/   r   r   rW   r   r   r   r   rj  r$   r%   rG   rI   )	r  rV   r   r   r  r   	confirmedr9   rO   s	            r)   confirm_subscriptionr    sQ   (*  ) !5s;; "adicklooLLNJJL !;SAA*-a&#a&#a&iuLLNJJL !BCHH  		
 	

 !' "YYz#./ 0		 T3'' *SVS))*s0   ,E A*E <E A+E 	E+E& E+&E+z/admin/subscribersc                  0   	 t               } | j                  t        j                  j                        }|j                  d       |j                         }|j                          | j                          d}|D ]]  }|d   rdnd}|d   r|d   j                         nd}|d|d	    d
|d    d
| d
|d   j                          d
| d|d    d|d    dz  }_ d| d}t        |d      S # t        $ r}t        t        |      d      cY d }~S d }~ww xY w)Nr   z
            SELECT id, email, confirmed, created_at, confirmed_at
            FROM newsletter_subscribers
            ORDER BY created_at DESC
            LIMIT 1000
        r  r  u   Даu   Нетconfirmed_atz$
            <tr>
              <td>r   z</td>
              <td>r   r  z</td>
              <td>
                <form method="post" action="/admin/resend-confirmation" style="display:inline">
                  <input type="hidden" name="email" value="a  ">
                  <button type="submit">Resend</button>
                </form>
                <form method="post" action="/admin/delete-subscriber" style="display:inline" onsubmit="return confirm('Delete?')">
                  <input type="hidden" name="email" value="z">
                  <button type="submit">Delete</button>
                </form>
              </td>
            </tr>
            a  
        <html>
        <head><meta charset="utf-8"><title>Admin - Subscribers</title></head>
        <body>
          <h1>Subscribers</h1>
          <p><a href="/admin/export-subscribers">Export CSV</a></p>
          <table border="1" cellpadding="6" cellspacing="0">
            <thead>
              <tr><th>ID</th><th>Email</th><th>Confirmed</th><th>Created at</th><th>Confirmed at</th><th>Actions</th></tr>
            </thead>
            <tbody>
              zQ
            </tbody>
          </table>
        </body>
        </html>
        r  r   )rW   r   rT   r  r  r   r   r   r  r   rG   rI   )	rV   r   r  	rows_htmlrconfirmed_textr	  r9   rO   s	            r)   admin_subscribersr    sa   9* "HOO,F,FG  	  

 	 	A'(~V8N<=n<M1^,668SUL T7) W:, !" #\?,,./ 0. !< =>gJ< H< =>gJ< H I	. k 	" T3'' *SVS))*s   C*C- -	D6D
DDz/admin/export-subscribersc            	         	 t               } | j                         }|j                  d       |j                         }|j	                          | j	                          t        j                         }t        j                  |      }|j                  g d       |D ]Q  }|j                  |d   |d   |d   |d   r|d   j                         nd|d   r|d   j                         ndg       S |j                  d       |j                         j                  d	      }t        |      }d
|j                  d<   d|j                  d<   |S # t         $ r}t        t#        |      d      cY d }~S d }~ww xY w)NzjSELECT id, email, confirmed, created_at, confirmed_at FROM newsletter_subscribers ORDER BY created_at DESC)r   r   r  r  r	  r   r`   r  r  r     zutf-8ztext/csv; charset=utf-8zContent-Typez$attachment; filename=subscribers.csvzContent-Dispositionr   )rW   r   r   r   r   ioStringIOcsvwriterwriterowr  seekgetvalueencoder   headersrG   rI   )	rV   r   r  outputr  r  	csv_bytesresponserO   s	            r)   export_subscribersr    sG   * "  D  	E 

F#RS 	AOO!!!$%aD! b$%aD! b 	 	AOO%,,W5	 ++D(2X./ *SVS))*s   EE
 
	E2E-'E2-E2z/admin/resend-confirmationc                  <   	 t         j                  j                  d      xs dj                         j	                         } | st        dd      S t               }|j                         }|j                  d| f       |j                         }|s,|j                          |j                          t        dd      S |d   r,|j                          |j                          t        d	d      S t        j                  d
      }|j                  d||d   f       |j                          |j                          |j                          t        | |      \  }}|st        d| d      S t        dd      S # t        $ r}t        t!        |      d      cY d }~S d }~ww xY w)Nr   r  email requiredr   r  zSubscriber not foundr   r`   zSubscriber already confirmedr  zNUPDATE newsletter_subscribers SET token = %s, created_at = NOW() WHERE id = %sr   zError sending email: r   zConfirmation resentr  )r   formr   rf  rn   r   rW   r   r   r   r   r  r  rj  r  rG   rI   )r   rV   r   r   r  r  r   rO   s           r)   admin_resend_confirmationr     s]   *!!'*0b779??A !1377 "Z]b\deooLLNJJL !7==q6LLNJJL !?EE%%b)gjoqtuvqwixy

+E59	c #8!>DD2C88 *SVS))*s8   AE3 A*E3 :0E3 +A;E3 'E3 3	F<FFFz/admin/delete-subscriberc                     	 t         j                  j                  d      xs dj                         j	                         } | st        dd      S t               }|j                         }|j                  d| f       |j                          |j                          |j                          t        dd      S # t        $ r}t        t        |      d      cY d }~S d }~ww xY w)	Nr   r  r  r   z3DELETE FROM newsletter_subscribers WHERE email = %sDeletedr  r   )r   r  r   rf  rn   r   rW   r   r   rj  r   rG   rI   )r   rV   r   rO   s       r)   admin_delete_subscriberr#  >  s    *!!'*0b779??A !1377 "LuhW

Y,, *SVS))*s%   AB8 A(B8 8	C CC C __main__Tz0.0.0.0ip  )debugr   r   r   )Tr   r   r   r   
flask_corsr   rT   psycopg2.extrasr$   r   r   requestsurllib.parser   r	   ra   r  loggingbasicConfigDEBUGr   r{   werkzeug.utilsr   r>   r=   r   	functoolsr   r  r  r  r   r   r   __name__apprS   email.mime.textr   email.mime.multipartr   r?   r*   r4   rP   rW   r^   re   r   ro   rq   r   router   r   r   r   r   r  r}  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r#  runrR   r+   r)   <module>r5     s	   ) )    	    + 	 
    '-- (   *  &  
 	  ) Ho S	 '!		  $ . %!0=
0	& R: X,\ 1! 2!J .@A AA !F84%A 5%AP /0% 1%*D ?VH-W .Wt
 ?UG,\A -\A~ +eW=} >}B +eW=U >Un 2UGD E  2VHEB FBH AE7S< T<| AH:V' W'^ +hZ@$ A$L &2J 3JZ ug. /> !F84*A 5*AX <%)CA *CAJ =5'* + 1< 2<~  5'2 3F4* fX.Ic /IcX "UG4)* 5)*X %1:*  2:*z &8*  9*< '&: *  ; *F %x8*  9** zGG$YTG2 r+   