
    ik/              
       ^   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Zd dlZd dlmZm	Z	 d dl
mZmZmZmZ d dlmZ d dlmZ d dlZd dlmZmZ d dlmZmZ d dlmZ erd d	lmZ d d
lmZ d dl m!Z! d dlm"Z"  ejF                  d      Z$ ejJ                  d      Z ed      Z& ed      Z' ed      Z( ed      Z) ed      Z*i d ed      de&de&de&de&de&de&d ed      d ed      de(de(d e(d!e)d"e)d# ed$      d% ed&      d' ed(       ed)       ed*      e'e'e'e'e*e*d+Z+dJd,Z, G d- d.      Z-d/e-d0d1d2dfd3Z. G d4 d5ej^                        Z/d6d7d0d1d2e0fd8Z1d9 Z2d2e3e0   fd:Z4d; Z5d< Z6d= Z7dKd>Z8d?e0d2e9fd@Z:dAe0d2e0fdBZ;dC Z<dDed2e0fdEZ=dFZ>dGdHd2eee0dHf      fdIZ?y)L    N)datetime	timedelta)IterableListTupleTYPE_CHECKING)StringIO)getincrementalencoder)gettextformat_date)loggerget_setting)DEFAULT_CATEGORY)Engine)ResultContainer)SearchQuery)UnresponsiveEnginez^[a-z]{2,3}(-[a-zA-Z]{2})?$webutilstimeoutzparsing errorzHTTP protocol errorznetwork errorz,SSL error: certificate validation has failedzunexpected crashzasyncio.TimeoutErrorzhttpx.TimeoutExceptionzhttpx.ConnectTimeoutzhttpx.ReadTimeoutzhttpx.WriteTimeoutzhttpx.HTTPStatusErrorz
HTTP errorzhttpx.ConnectErrorzHTTP connection errorzhttpx.RemoteProtocolErrorzhttpx.LocalProtocolErrorzhttpx.ProtocolErrorzhttpx.ReadErrorzhttpx.WriteErrorzhttpx.ProxyErrorzproxy errorz,searx.exceptions.SearxEngineCaptchaExceptionCAPTCHAz4searx.exceptions.SearxEngineTooManyRequestsExceptionztoo many requestszaccess deniedzserver API error)z1searx.exceptions.SearxEngineAccessDeniedExceptionz(searx.exceptions.SearxEngineAPIExceptionz*searx.exceptions.SearxEngineXPathExceptionKeyErrorzjson.decoder.JSONDecodeErrorzlxml.etree.ParserErrorzssl.SSLCertVerificationErrorzssl.CertificateErrorc                    g }| D ]q  }t         j                  |j                        }|s	t         d    }t        |      }|j                  rt        d      dz   |z   }|j                  |j                  |f       s t        |d       S )N	Suspendedz: c                     | d   S Nr    )es    /root/searxng/searx/webutils.py<lambda>z'get_translated_errors.<locals>.<lambda>R   s
    1Q4     key)exception_classname_to_textget
error_typer   	suspendedappendenginesorted)unresponsive_enginestranslated_errorsunresponsive_engineerror_user_text	error_msgs        r   get_translated_errorsr/   F   s    3 J599:M:X:XY9$?OO,	((,t3i?I  "5"<"<i!HIJ #88r    c                   <    e Zd ZdZej
                  dfdZd Zd Zy)	CSVWriterz_A CSV writer which will write rows to CSV file "f", which is encoded in
    the given encoding.zutf-8c                     t               | _        t        j                  | j                  fd|i|| _        || _         t        |             | _        y )Ndialect)r	   queuecsvwriterstreamr
   encoder)selffr3   encodingkwdss        r   __init__zCSVWriter.__init__Y   sB    Z
jjEWEE6,X68r    c                 N   | j                   j                  |       | j                  j                         }|j	                  d      }| j
                  j                  |      }| j                  j                  |j                                | j                  j                  d       y )N r   )r6   writerowr4   getvaluestripr8   encoder7   writedecodetruncate)r9   rowdatas      r   r@   zCSVWriter.writerow`   sr    S!zz""$zz&!||""4($++-(

Ar    c                 4    |D ]  }| j                  |        y N)r@   )r9   rowsrG   s      r   	writerowszCSVWriter.writerowsl   s     	CMM#	r    N)	__name__
__module____qualname____doc__r5   excelr=   r@   rL   r   r    r   r1   r1   U   s!     #&))g 9
r    r1   r5   rcr   returnc           
      
   d} | j                   |       |j                         D ]Y  }|j                         }|d   j                  |d<   d|d<    | j                   |D cg c]  }|j	                  |d       c}       [ |j
                  D ]T  }|j                         }|d   j                  |d<    | j                   |D cg c]  }|j	                  |d       c}       V |j                  D ]7  }|dd} | j                   |D cg c]  }|j	                  |d       c}       9 |j                  D ]7  }|d	d} | j                   |D cg c]  }|j	                  |d       c}       9 y
c c}w c c}w c c}w c c}w )a:  Write rows of the results to a query (``application/csv``) into a CSV
    table (:py:obj:`CSVWriter`).  First line in the table contain the column
    names.  The column "type" specifies the type, the following types are
    included in the table:

    - result
    - answer
    - suggestion
    - correction

    )titleurlcontenthostr(   scoretype
parsed_urlrX   resultrZ    
suggestion)rU   rZ   
correctionN)r@   get_ordered_resultsas_dictnetlocr$   answerssuggestionscorrections)r5   rR   keysresrG   r"   as          r   write_csv_responseri   q   sn    JDCLL%%' 9kkm,'..FF$73cggc2&78	9 ZZ 9iik,'..F$73cggc2&789
 ^^ 9<0$73cggc2&789 ^^ 9<0$73cggc2&789 8
 8 8 8s   E1
E6
E;
F 
c                        e Zd Z fdZ xZS )JSONEncoderc                 6   t        |t        j                        rt        j                  |      S t        |t              r|j                         S t        |t              r|j                         S t        |t              rt        |      S t        | -  |      S rJ   )
isinstancemsgspecStructto_builtinsr   	isoformatr   total_secondssetlistsuperdefault)r9   o	__class__s     r   rv   zJSONEncoder.default   sq    a(&&q))a";;= a#??$$a7Nwq!!r    )rM   rN   rO   rv   __classcell__)rx   s   @r   rk   rk      s    	" 	"r    rk   sqr   c           
         | j                   |j                  |j                         D cg c]  }|j                          c}|j                  D cg c]  }|j                          c}t        |j                        |j                  t        |j                        t        |j                        d}t        j                  |t              }|S c c}w c c}w )zHReturns the JSON string of the results to a query (``application/json``))querynumber_of_resultsresultsrc   re   	infoboxesrd   r*   )cls)r|   r}   r`   ra   rc   rt   re   r   rd   r/   r*   jsondumpsrk   )rz   rR   _rH   responses        r   get_json_responser      s     11)+)?)?)ABAAIIKB)+4AAIIK4BNN+\\BNN+ 5b6M6M N	D zz$K0HO C4s   CC
c                 ,    t        j                  |       S )zReturns available themes list.)oslistdir)templates_paths    r   
get_themesr      s    ::n%%r    c                       g t        j                  t        t        d                  dt         j                  f fd          S )Nzui.static_pathpathc                    | j                         D ]p  }|j                  j                  d      r|j                         r)j	                  t        |j                                     |j                         si |       r y )N.)iterdirname
startswithis_filer'   strrelative_tois_dir)r   r:   _walk	file_liststatic_paths     r   r   z#get_static_file_list.<locals>._walk   sb     	Avv  %yy{  Q]];%?!@Axxza	r    )pathlibPathr   r   )r   r   r   s   @@@r   get_static_file_listr      sA    I,,s;/?#@ABKGLL  
+r    c                    t               }t        |       dz   }t        j                  |       D ]S  \  }}}|j	                  d      s|D ]6  }t        j
                  j                  ||d  |      }|j                  |       8 U |S )N   result_templates)rs   lenr   walkendswithr   joinadd)r   r   templates_path_length	directoryr   filesfilenamer:   s           r   get_result_templatesr      s    u/!3!ww~6 (	1e01! (GGLL+@+A!BHM $$Q'((
 r    c                     t        j                  | j                         |t        j                        j                         S rJ   )hmacnewrC   hashlibsha256	hexdigest)
secret_keyrV   s     r   new_hmacr      s+    88J%%'gnn=GGIIr    c                 x    t        | |      }t        |      t        |      k(  xr t        j                  ||      S rJ   )r   r   r   compare_digest)r   valuehmac_to_checkhmac_of_values       r   
is_hmac_ofr      s6    Z/M}]!33i8K8KM[h8iir    c                 v    t        |       |kD  r*t        |dz  dz         }dj                  | d | | | d        S | S )N   r   z{0}[...]{1})r   intformat)rV   
max_length	chunk_lens      r   prettify_urlr      sH    
3x*
Q*+	##C
OS)5EFFJr    sc                 L    d}t        t        j                  d| d|             S )a\  This function check whether or not a string contains Chinese, Japanese,
    or Korean characters. It employs regex and uses the u escape sequence to
    match any character in a set of Unicode ranges.

    Args:
        s (str): string to be checked.

    Returns:
        bool: True if the input s contains the characters and False otherwise.
    u*   一-鿿぀-ゟ゠-ヿ一-龯가-힯ᄀ-ᇿ[])boolresearch)r   unicode_rangess     r   contains_cjkor      s.    	  		Q~.a0!455r    wordc                 Z    t        j                  |       }t        |      rd| dS d| dS )a  Generate the regex pattern to match for a given word according
    to whether or not the word contains CJK characters or not.
    If the word is and/or contains CJK character, the regex pattern
    will match standalone word by taking into account the presence
    of whitespace before and after it; if not, it will match any presence
    of the word throughout the text, ignoring the whitespace.

    Args:
        word (str): the word to be matched with regex pattern.

    Returns:
        str: the regex pattern for the word.
    ()z\b(z)(?!\w))r   escaper   )r   rwords     r   regex_highlight_cjkr      s6     IIdOEUE7!}%  r    c           	      0   | sy | j                  d      dk7  r| S |j                         }g }|D ]  }|j                  dd      j                  dd      j                  dd      }t        |      dkD  sD|j	                  t        j                  t        |      | t
        j                  t
        j                  z                t        |      dkD  rEt        j                  d	j                  t        t        |                  }|j                  d
 |       S | S )N<'r]   " r   )flags|c                 L    d| j                  d       dj                  dd      S )Nz<span class="highlight">r   z</span>\z\\)groupreplace)matchs    r   r   z#highlight_content.<locals>.<lambda>  s)    )A%++a.AQQX'Y'a'abfhm'n r    )findsplitr   r   extendr   findallr   IUcompiler   mapsub)rW   r|   
querysplitqueriesqsregexs         r   highlight_contentr     s     ||CBJG \ZZR ((b199#rBr7Q;NN2::&9"&=wbddUWUYUYkZ[\ 7|a

388C(;W$EFGyynpwxxNr    dtc                    | j                         }| j                         }|j                  dk(  rQ|j                  dk(  rB|j                  dk(  r3|j
                  dk(  r$|j                  dk(  rt        |j                        S | j                  d      t        j                         t        d      z
  k\  rt        j                         | j                  d      z
  }t        |j                  dz  dz        }t        |j                  dz  dz        }|dk(  rt        d      j!                  |      S t        d	      j!                  ||
      S t#        |       S )zReturns a human-readable and translated string indicating how long ago
    a date was in the past / the time span of the date to the present.

    On January 1st, midnight, the returned string only indicates how many years
    ago the date was.
    r   r   N)tzinfo)days<   z{minutes} minute(s) ago)minutesz({hours} hour(s), {minutes} minute(s) ago)hoursr   )datetimemonthdayhourminutesecondr   yearr   r   nowr   r   secondsr   r   r   )r   dttimedifferencer   r   s         r   searxng_l10n_timespanr   #  s    		A
	Aww!|
qvv{qxx1}UV166{	zzz(,,.9!3D"DD!"**D**AA~--2b89N**R/"45A:45<<W<MMABIIPU_fIggr?r    zwithout further subgroupingengineszIterable[Engine]c           	      b  
 
fd}d }d }t        t        d      j                               
t        j                  t        | |      |      }t        d |D        |      }g }|D ]D  \  }}|t        k7  rd|j                  dd	      z   nd
}	|j                  ||	t        ||      f       F |S )zNGroups an Iterable of engines by their first non tab category (first subgroup)c                     | j                   D cg c]  }|t        gz   vs| }}t        |      dkD  r|d   S t        S c c}w r   )
categoriesr   r   NO_SUBGROUPING)engcnon_tab_categoriestabss      r   get_subgroupz*group_engines_in_tab.<locals>.get_subgroup?  sO    ),^A1DL\K]D];]a^^(+,>(?!(C!!$WW _s
   AAc                 @    | d   t         k(  | d   j                         fS r   )r  lower)r   s    r   group_sort_keyz,group_engines_in_tab.<locals>.group_sort_keyC  s!    aN*E!HNN,<==r    c                 R    | j                   j                  dd      | j                  fS )Nlanguager]   )aboutr$   r   )r(   s    r   engine_sort_keyz-group_engines_in_tab.<locals>.engine_sort_keyF  s"      R0&++>>r    categories_as_tabsr!   c              3   <   K   | ]  \  }}|t        |      f  y wrJ   )rt   ).0r   r   s      r   	<genexpr>z'group_engines_in_tab.<locals>.<genexpr>K  s     QmdGT4=1Qs   !r   r   r]   )	rt   r   rf   	itertoolsgroupbyr)   r  r   r'   )r   r  r
  r  	subgroupssorted_groupsret_val	groupname_engines
group_bangr  s             @r   group_engines_in_tabr  <  s    X>? 016689D!!&l"C\RIQyQWefMG, W	8:C~:US9,,S#66[]
	:vhO/TUVW Nr    )r*   zIterable[UnresponsiveEngine])J   )@r   r   r5   r   r   r   r  r   r   r   typingr   r   r   r   ior	   codecsr
   rn   flask_babelr   r   searxr   r   searx.enginesr   searx.enginelibr   searx.resultsr   searx.searchr   r   r   VALID_LANGUAGE_CODEgetChildtimeout_textparsing_error_texthttp_protocol_error_textnetwork_error_textssl_cert_error_textr#   r/   r1   ri   rk   r   r   r   rt   r   r   r   r   r   r   r   r   r   r   r  r  r   r    r   <module>r.     s  
 
  
   	   ( 7 7  (  , % *&-(0 bjj!?@ 		$y!_- "#89 _- LM '$
%| L l	
 L  , W\2 '"9:  !9  8 3 ) * .  3GI4F!" ;GDW<X#$ :A9Q078J0K2D"$60$7/3 :9 8!9I !9+< !9 !9H
"$"" 
"- -> 3  &
d3i $Jj
6S 6T 6,!c !c !(*h 3 , /"4 eCI[D[>\9] r    