diff --git a/conf/settings.yml b/conf/settings.yml index ea7666e..3ddf222 100644 --- a/conf/settings.yml +++ b/conf/settings.yml @@ -1,16 +1,37 @@ +general: + debug : False # Debug mode, only for development + +search: + safe_search : 0 # Filter results. 0: None, 1: Moderate, 2: Strict + autocomplete : "duckduckgo" # Existing autocomplete backends: "dbpedia", "duckduckgo", "google", "startpage", "wikipedia" - leave blank to turn it off by default + server: port : 8888 + bind_address : "127.0.0.1" # address to listen on secret_key : "ultrasecretkey" # change this! - debug : False # Debug mode, only for development - request_timeout : 2.0 # seconds base_url : ynhbaseurl # Set custom base_url. Possible values: False or "https://your.custom.host/location/" + image_proxy : False # Proxying image results through searx + +ui: themes_path : "" # Custom ui themes path - leave it blank if you didn't change default_theme : oscar # ui theme - https_rewrite : True # Force rewrite result urls. See searx/https_rewrite.py - useragent_suffix : "" # suffix of searx_useragent, could contain informations like an email address to the administrator - image_proxy : False # Proxying image results through searx default_locale : "" # Default interface locale - leave blank to detect from browser information or use codes from the 'locales' config section +outgoing: # communication with search engines + request_timeout : 2.0 # seconds + useragent_suffix : "" # suffix of searx_useragent, could contain informations like an email address to the administrator +# uncomment below section if you want to use a proxy +# see http://docs.python-requests.org/en/latest/user/advanced/#proxies +# SOCKS proxies are not supported : see https://github.com/kennethreitz/requests/pull/478 +# proxies : +# http : http://127.0.0.1:8080 +# https: http://127.0.0.1:8080 +# uncomment below section only if you have more than one network interface +# which can be the source of outgoing search requests +# source_ips: +# - 1.1.1.1 +# - 1.1.1.2 + engines: - name : wikipedia engine : mediawiki @@ -20,17 +41,14 @@ engines: - name : bing engine : bing - locale : en-US shortcut : bi - name : bing images engine : bing_images - locale : en-US shortcut : bii - name : bing news engine : bing_news - locale : en-US shortcut : bin - name : btdigg @@ -73,12 +91,6 @@ engines: # shortcut : fa # api_key : 'apikey' # required! -# down - website is under criminal investigation by the UK -# - name : filecrop -# engine : filecrop -# categories : files -# shortcut : fc - - name : 500px engine : www500px shortcut : px @@ -98,10 +110,10 @@ engines: # Or you can use the html non-stable engine, activated by default engine : flickr_noapi - - name : general-file - engine : generalfile - shortcut : gf - disabled : True + - name : gigablast + engine : gigablast + shortcut : gb + disabled: True - name : github engine : github @@ -164,6 +176,28 @@ engines: - name : piratebay engine : piratebay shortcut : tpb + disabled : True + + - name : qwant + engine : qwant + shortcut : qw + categories : general + disabled : True + + - name : qwant images + engine : qwant + shortcut : qwi + categories : images + + - name : qwant news + engine : qwant + shortcut : qwn + categories : news + + - name : qwant social + engine : qwant + shortcut : qws + categories : social media - name : kickass engine : kickass @@ -186,6 +220,10 @@ engines: shortcut : scc disabled : True + - name : spotify + engine : spotify + shortcut : stf + - name : subtitleseeker engine : subtitleseeker shortcut : ss @@ -196,12 +234,21 @@ engines: - name : startpage engine : startpage shortcut : sp + timeout : 6.0 + disabled : True -# +30% page load time -# - name : ixquick -# engine : startpage -# base_url : 'https://www.ixquick.com/' -# search_url : 'https://www.ixquick.com/do/search' + - name : ixquick + engine : startpage + base_url : 'https://www.ixquick.com/' + search_url : 'https://www.ixquick.com/do/search' + shortcut : iq + timeout : 6.0 + disabled : True + + - name : swisscows + engine : swisscows + shortcut : sw + disabled : True - name : twitter engine : twitter @@ -232,8 +279,13 @@ engines: shortcut : yhn - name : youtube - engine : youtube shortcut : yt + # You can use the engine using the official stable API, but you need an API key + # See : https://console.developers.google.com/project + # engine : youtube_api + # api_key: 'apikey' # required! + # Or you can use the html non-stable engine, activated by default + engine : youtube_noapi - name : dailymotion engine : dailymotion @@ -241,9 +293,14 @@ engines: - name : vimeo engine : vimeo - locale : en-US shortcut : vm +#The blekko technology and team have joined IBM Watson! -> https://blekko.com/ +# - name : blekko images +# engine : blekko_images +# locale : en-US +# shortcut : bli + # - name : yacy # engine : yacy # shortcut : ya @@ -254,6 +311,7 @@ engines: locales: en : English de : Deutsch + he : Hebrew hu : Magyar fr : Français es : Español @@ -261,4 +319,7 @@ locales: nl : Nederlands ja : 日本語 (Japanese) tr : Türkçe + pt : Português ru : Russian + ro : Romanian + zh : 中文 (Chinese) diff --git a/sources/AUTHORS.rst b/sources/AUTHORS.rst index f329efb..3e719fe 100644 --- a/sources/AUTHORS.rst +++ b/sources/AUTHORS.rst @@ -1,11 +1,11 @@ -Searx was created and is maintained by Adam Tauber. +Searx was created by Adam Tauber and is maintained by Adam Tauber and Alexandre Flament. Major contributing authors: - Adam Tauber `@asciimoo `_ - Matej Cotman - Thomas Pointhuber -- Alexandre Flament +- Alexandre Flament `@dalf `_ - @Cqoicebordel People who have submitted patches/translates, reported bugs, consulted features or @@ -34,3 +34,7 @@ generally made searx better: - @opi - @dimqua - Giorgos Logiotatidis +- Luc Didry +- Niklas Haas +- @underr +- Emmanuel Benazera diff --git a/sources/CHANGELOG.rst b/sources/CHANGELOG.rst index f9ab188..f2c192d 100644 --- a/sources/CHANGELOG.rst +++ b/sources/CHANGELOG.rst @@ -1,3 +1,49 @@ +0.8.0 2015.09.08 +================ + +- New engines + + - Blekko (image) + - Gigablast (general) + - Spotify (music) + - Swisscows (general, images) + - Qwant (general, images, news, social media) +- Plugin system +- New plugins + + - HTTPS rewrite + - Search on cagetory select + - User information + - Tracker url part remover +- Multiple outgoing IP and HTTP/HTTPS proxy support +- New autocompleter: startpage +- New theme: pix-art +- Settings file structure change +- Fabfile, docker deployment +- Optional safesearch result filter +- Force HTTPS in engines if possible +- Disabled HTTP referrer on outgoing links +- Display cookie information +- Prettier search URLs +- Right-to-left text handling in themes +- Translation updates (New locales: Chinese, Hebrew, Portuguese, Romanian) + + +New dependencies +~~~~~~~~~~~~~~~~ + +- pyopenssl +- ndg-httpsclient +- pyasn1 +- pyasn1-modules +- certifi + + +News +~~~~ + +@dalf joined the maintainer "team" + 0.7.0 2015.02.03 ================ diff --git a/sources/Dockerfile b/sources/Dockerfile index 831a429..543c74d 100644 --- a/sources/Dockerfile +++ b/sources/Dockerfile @@ -1,21 +1,22 @@ -FROM debian:stable +FROM python:2.7-slim -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - python-dev python2.7-minimal python-virtualenv \ - python-pybabel python-pip zlib1g-dev \ - libxml2-dev libxslt1-dev build-essential \ - openssl +WORKDIR /app RUN useradd searx -WORKDIR /app -RUN pip install uwsgi +EXPOSE 5000 +CMD ["/usr/local/bin/uwsgi", "--uid", "searx", "--gid", "searx", "--http", ":5000", "-w", "searx.webapp"] + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + zlib1g-dev libxml2-dev libxslt1-dev libffi-dev build-essential \ + libssl-dev openssl && \ + rm -rf /var/lib/apt/lists/* + +RUN pip install --no-cache uwsgi + COPY requirements.txt /app/requirements.txt -RUN pip install -r requirements.txt +RUN pip install --no-cache -r requirements.txt COPY . /app RUN sed -i -e "s/ultrasecretkey/`openssl rand -hex 16`/g" searx/settings.yml - -EXPOSE 5000 -CMD ["/usr/local/bin/uwsgi", "--uid", "searx", "--gid", "searx", "--http", ":5000", "-w", "searx.webapp"] diff --git a/sources/LICENSE b/sources/LICENSE index b403467..dba13ed 100644 --- a/sources/LICENSE +++ b/sources/LICENSE @@ -1,14 +1,661 @@ -searx is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 -searx is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. -You should have received a copy of the GNU Affero General Public License -along with searx. If not, see < http://www.gnu.org/licenses/ >. + Preamble -(C) 2013- by Adam Tauber, + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/sources/Makefile b/sources/Makefile index 9f4cf2e..0568555 100644 --- a/sources/Makefile +++ b/sources/Makefile @@ -51,6 +51,7 @@ styles: @lessc -x searx/static/themes/courgette/less/style-rtl.less > searx/static/themes/courgette/css/style-rtl.css @lessc -x searx/static/less/bootstrap/bootstrap.less > searx/static/css/bootstrap.min.css @lessc -x searx/static/themes/oscar/less/oscar/oscar.less > searx/static/themes/oscar/css/oscar.min.css + @lessc -x searx/static/themes/pix-art/less/style.less > searx/static/themes/pix-art/css/style.css grunt: @grunt --gruntfile searx/static/themes/oscar/gruntfile.js diff --git a/sources/requirements.txt b/sources/requirements.txt index 2d43482..e021c4a 100644 --- a/sources/requirements.txt +++ b/sources/requirements.txt @@ -5,3 +5,8 @@ lxml pyyaml pygments python-dateutil +ndg-httpsclient +pyopenssl +pyasn1 +pyasn1-modules +certifi diff --git a/sources/searx/__init__.py b/sources/searx/__init__.py index 110f46a..ea21e8f 100644 --- a/sources/searx/__init__.py +++ b/sources/searx/__init__.py @@ -36,26 +36,15 @@ if 'SEARX_SETTINGS_PATH' in environ: else: settings_path = join(searx_dir, 'settings.yml') -if 'SEARX_HTTPS_REWRITE_PATH' in environ: - https_rewrite_path = environ['SEARX_HTTPS_REWRITE_PATH'] -else: - https_rewrite_path = join(searx_dir, 'https_rules') - # load settings with open(settings_path) as settings_yaml: settings = load(settings_yaml) -if settings.get('server', {}).get('debug'): +if settings.get('general', {}).get('debug'): logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.WARNING) logger = logging.getLogger('searx') -# load https rules only if https rewrite is enabled -if settings.get('server', {}).get('https_rewrite'): - # loade https rules - from searx.https_rewrite import load_https_rules - load_https_rules(https_rewrite_path) - logger.info('Initialisation done') diff --git a/sources/searx/autocomplete.py b/sources/searx/autocomplete.py index 9d31aa3..264d0cc 100644 --- a/sources/searx/autocomplete.py +++ b/sources/searx/autocomplete.py @@ -19,11 +19,19 @@ along with searx. If not, see < http://www.gnu.org/licenses/ >. from lxml import etree from json import loads from urllib import urlencode +from searx import settings from searx.languages import language_codes from searx.engines import ( categories, engines, engine_shortcuts ) -from searx.poolrequests import get +from searx.poolrequests import get as http_get + + +def get(*args, **kwargs): + if 'timeout' not in kwargs: + kwargs['timeout'] = settings['outgoing']['request_timeout'] + + return http_get(*args, **kwargs) def searx_bang(full_query): @@ -49,17 +57,17 @@ def searx_bang(full_query): # check if query starts with categorie name for categorie in categories: if categorie.startswith(engine_query): - results.append(first_char+'{categorie}'.format(categorie=categorie)) + results.append(first_char + '{categorie}'.format(categorie=categorie)) # check if query starts with engine name for engine in engines: if engine.startswith(engine_query.replace('_', ' ')): - results.append(first_char+'{engine}'.format(engine=engine.replace(' ', '_'))) + results.append(first_char + '{engine}'.format(engine=engine.replace(' ', '_'))) # check if query starts with engine shortcut for engine_shortcut in engine_shortcuts: if engine_shortcut.startswith(engine_query): - results.append(first_char+'{engine_shortcut}'.format(engine_shortcut=engine_shortcut)) + results.append(first_char + '{engine_shortcut}'.format(engine_shortcut=engine_shortcut)) # check if current query stats with :bang elif first_char == ':': @@ -103,8 +111,8 @@ def searx_bang(full_query): def dbpedia(query): - # dbpedia autocompleter - autocomplete_url = 'http://lookup.dbpedia.org/api/search.asmx/KeywordSearch?' # noqa + # dbpedia autocompleter, no HTTPS + autocomplete_url = 'http://lookup.dbpedia.org/api/search.asmx/KeywordSearch?' response = get(autocomplete_url + urlencode(dict(QueryString=query))) @@ -131,7 +139,7 @@ def duckduckgo(query): def google(query): # google autocompleter - autocomplete_url = 'http://suggestqueries.google.com/complete/search?client=toolbar&' # noqa + autocomplete_url = 'https://suggestqueries.google.com/complete/search?client=toolbar&' response = get(autocomplete_url + urlencode(dict(q=query))) @@ -145,9 +153,19 @@ def google(query): return results +def startpage(query): + # wikipedia autocompleter + url = 'https://startpage.com/do/suggest?{query}' + + resp = get(url.format(query=urlencode({'query': query}))).text.split('\n') + if len(resp) > 1: + return resp + return [] + + def wikipedia(query): # wikipedia autocompleter - url = 'https://en.wikipedia.org/w/api.php?action=opensearch&{0}&limit=10&namespace=0&format=json' # noqa + url = 'https://en.wikipedia.org/w/api.php?action=opensearch&{0}&limit=10&namespace=0&format=json' resp = loads(get(url.format(urlencode(dict(search=query)))).text) if len(resp) > 1: @@ -158,5 +176,6 @@ def wikipedia(query): backends = {'dbpedia': dbpedia, 'duckduckgo': duckduckgo, 'google': google, + 'startpage': startpage, 'wikipedia': wikipedia } diff --git a/sources/searx/data/currencies.json b/sources/searx/data/currencies.json new file mode 100644 index 0000000..bfde5a7 --- /dev/null +++ b/sources/searx/data/currencies.json @@ -0,0 +1,7655 @@ +{ + "names": { + "francos franceses": [ + "FRF" + ], + "bulgarischer lew": [ + "BGN" + ], + "o\u0308rme\u0301ny dram": [ + "AMD" + ], + "oekrai\u0308ense hryvnja": [ + "UAH" + ], + "guatemalan quetzal": [ + "GTQ" + ], + "ghana cedi": [ + "GHS" + ], + "livre de sainte helene": [ + "SHP" + ], + "papua new guinean kina": [ + "PGK" + ], + "aud": [ + "AUD" + ], + "\u20ab": [ + "VND" + ], + "olasz li\u0301ra": [ + "ITL" + ], + "aserbaidschan manat": [ + "AZN" + ], + "ethiopian dollar": [ + "ETB" + ], + "norwegische krone": [ + "NOK" + ], + "papoea nieuw guinese kina": [ + "PGK" + ], + "som uzbeko": [ + "UZS" + ], + "yuan chino": [ + "CNY" + ], + "nuevo dolar de taiwan": [ + "TWD" + ], + "zweedse kronen": [ + "SEK" + ], + "dollar des i\u0302les cai\u0308mans": [ + "KYD" + ], + "do\u0301lar de singapur": [ + "SGD" + ], + "gru\u0301z lari": [ + "GEL" + ], + "escudo mozambiquen\u0303o": [ + "MZE" + ], + "peso filipino": [ + "PHP" + ], + "grivnia ucraniana": [ + "UAH" + ], + "salamon szigeteki dolla\u0301r": [ + "SBD" + ], + "barbados dollar": [ + "BBD" + ], + "fuang": [ + "THB" + ], + "dirham marroqui": [ + "MAD" + ], + "sri lankan rupees": [ + "LKR" + ], + "qindarka": [ + "ALL" + ], + "dinaro macedone": [ + "MKD" + ], + "togrog": [ + "MNT" + ], + "q\u0259pik": [ + "AZN" + ], + "special drawing rights": [ + "XDR" + ], + "gibralta\u0301ri font": [ + "GIP" + ], + "dinar bahraini": [ + "BHD" + ], + "marokkaanse dirham": [ + "MAD" + ], + "rouble sovie\u0301tique": [ + "SUR" + ], + "tanzanian shilling": [ + "TZS" + ], + "libra de siria": [ + "SYP" + ], + "rand sudafricano": [ + "ZAR" + ], + "seychelse roepie": [ + "SCR" + ], + "seychelse roepia": [ + "SCR" + ], + "forint": [ + "HUF" + ], + "dinar algerino": [ + "DZD" + ], + "roupie du sri lanka": [ + "LKR" + ], + "katar riyal": [ + "QAR" + ], + "schekalim": [ + "ILS" + ], + "corona checoslovaca": [ + "CSK" + ], + "baht tailande\u0301s": [ + "THB" + ], + "nuevo peso": [ + "ARS", + "UYU" + ], + "cuna croata": [ + "HRK" + ], + "nieuwe israe\u0308lische shekel": [ + "ILS" + ], + "nieuwe israelische shekel": [ + "ILS" + ], + "dollar des i\u0302les fidji": [ + "FJD" + ], + "nieuw zeelandse dollar": [ + "NZD" + ], + "tanza\u0301niai shilling": [ + "TZS" + ], + "gold franc": [ + "XFO" + ], + "tongan pa`anga": [ + "TOP" + ], + "francia frank": [ + "FRF" + ], + "brl": [ + "BRL" + ], + "isla\u0308ndische wa\u0308hrung": [ + "ISK" + ], + "guyana dollar": [ + "GYD" + ], + "dollaro australiano": [ + "AUD" + ], + "nakfa e\u0301rythre\u0301en": [ + "ERN" + ], + "kap verde escudo": [ + "CVE" + ], + "dinar iraqui\u0301": [ + "IQD" + ], + "vietnamese dong": [ + "VND" + ], + "neuer sol": [ + "PEN" + ], + "peso de argentina": [ + "ARS" + ], + "ddr mark": [ + "DDM" + ], + "br$": [ + "BND" + ], + "e\u0301szak koreai von": [ + "KPW" + ], + "japanse yen": [ + "JPY" + ], + "franco svizzero": [ + "CHF" + ], + "afghani afgano": [ + "AFN" + ], + "lira siriana": [ + "SYP" + ], + "boliviano": [ + "BOB" + ], + "vanuatui vatu": [ + "VUV" + ], + "tnd": [ + "TND" + ], + "manat turkmene": [ + "TMT" + ], + "namibia dollar": [ + "NAD" + ], + "ern": [ + "ERN" + ], + "manat turkmeno": [ + "TMT" + ], + "bds$": [ + "BBD" + ], + "bhutaanse ngultrum": [ + "BTN" + ], + "peso chilien": [ + "CLP" + ], + "dolar jamaicano": [ + "JMD" + ], + "bahamas dollar": [ + "BSD" + ], + "eritrese nakfa": [ + "ERN" + ], + "czk": [ + "CZK" + ], + "engels pond": [ + "GBP" + ], + "dolar de bermudas": [ + "BMD" + ], + "taka bangladeshi\u0301": [ + "BDT" + ], + "riyal del qatar": [ + "QAR" + ], + "kuwaiti dinar": [ + "KWD" + ], + "seychellen rupie": [ + "SCR" + ], + "boli\u0301var ve\u0301ne\u0301zue\u0301lien": [ + "VEF" + ], + "sri lanka rupie": [ + "LKR" + ], + "do\u0301lar de brunei": [ + "BND" + ], + "do\u0301lar de las islas salomo\u0301n": [ + "SBD" + ], + "lak": [ + "LAK" + ], + "sum uzbeko": [ + "UZS" + ], + "kurus\u0327": [ + "TRY" + ], + "iraqi dinar": [ + "IQD" + ], + "livre sterling": [ + "GBP" + ], + "angolai kwanza": [ + "AOA" + ], + "lat": [ + "LVL" + ], + "lek albanais": [ + "ALL" + ], + "brunei dolla\u0301r": [ + "BND" + ], + "tetri": [ + "GEL" + ], + "sterlina sudsudanese": [ + "SSP" + ], + "mo\u0308ngo\u0308": [ + "MNT" + ], + "mexican un peso coinage": [ + "MXN" + ], + "djiboutische frank": [ + "DJF" + ], + "seychelle i ru\u0301pia": [ + "SCR" + ], + "litauischer litas": [ + "LTL" + ], + "zambiaanse kwacha": [ + "ZMW" + ], + "maldi\u0301v szigeteki ru\u0301fia": [ + "MVR" + ], + "dinar bahreini\u0301": [ + "BHD" + ], + "barbadiaanse dollar": [ + "BBD" + ], + "drachme": [ + "GRD" + ], + "emalangeni": [ + "SZL" + ], + "canadese dollar": [ + "CAD" + ], + "mx$": [ + "MXN" + ], + "chinesischer renminbi": [ + "CNY" + ], + "macedonian denar": [ + "MKD" + ], + "uic franc": [ + "XFU" + ], + "won surcoreano": [ + "KRW" + ], + "nuevo shekel": [ + "ILS" + ], + "arubaanse florin": [ + "AWG" + ], + "ruanda franc": [ + "RWF" + ], + "franco burundes": [ + "BIF" + ], + "makao\u0301i pataca": [ + "MOP" + ], + "koruna c\u030ceska\u0301": [ + "CZK" + ], + "dirham des e\u0301mirats": [ + "AED" + ], + "mozambiki metical": [ + "MZN" + ], + "panamanian balboa": [ + "PAB" + ], + "syrian pound": [ + "SYP" + ], + "ki\u0301nai ju\u0308an": [ + "CNY" + ], + "mxn": [ + "MXN" + ], + "dolar fijiano": [ + "FJD" + ], + "a\u0308thiopischer birr": [ + "ETB" + ], + "kirgiz szom": [ + "KGS" + ], + "dinar du ye\u0301men du sud": [ + "YER" + ], + "peso moneda nacional": [ + "ARS" + ], + "scellino somalo": [ + "SOS" + ], + "cseh korona": [ + "CZK" + ], + "uruguayan peso": [ + "UYU" + ], + "cl$": [ + "CLP" + ], + "convertibele peso": [ + "CUC" + ], + "britisches pfund": [ + "GBP" + ], + "tonga dollar": [ + "TOP" + ], + "peso cubain convertible": [ + "CUC" + ], + "argentin peso": [ + "ARS" + ], + "lira maltesa": [ + "MTL" + ], + "bosnische konvertibilna marka": [ + "BAM" + ], + "francs suisse": [ + "CHF" + ], + "gourde haitienne": [ + "HTG" + ], + "shilling somali": [ + "SOS" + ], + "nt$": [ + "TWD" + ], + "rp": [ + "IDR" + ], + "dolar de las bahamas": [ + "BSD" + ], + "rs": [ + "BRL" + ], + "monnaie danoise": [ + "DKK" + ], + "swaziland lilangeni": [ + "SZL" + ], + "tugrig": [ + "MNT" + ], + "gersh": [ + "ETB" + ], + "rouble russe": [ + "RUB" + ], + "tugrik": [ + "MNT" + ], + "kip": [ + "LAK" + ], + "dirham de los emiratos arabes unidos": [ + "AED" + ], + "escudo capverdien": [ + "CVE" + ], + "jemeni ria\u0301l": [ + "YER" + ], + "fcfp": [ + "XPF" + ], + "rwanda franc": [ + "RWF" + ], + "bolivar venezolano": [ + "VEF" + ], + "zambiai kwacha": [ + "ZMW" + ], + "lev bulgaro": [ + "BGN" + ], + "lev bulgare": [ + "BGN" + ], + "nakfa eritreo": [ + "ERN" + ], + "danish krone": [ + "DKK" + ], + "monnaie britannique": [ + "GBP" + ], + "r$": [ + "BRL" + ], + "di\u0301rham marroqui\u0301": [ + "MAD" + ], + "institut d'e\u0301mission d'outre mer": [ + "XPF" + ], + "manat azerbaiyano": [ + "AZN" + ], + "vietnami \u0111o\u0302\u0300ng": [ + "VND" + ], + "riyal iraniano": [ + "IRR" + ], + "franco guineano": [ + "GNF" + ], + "fiorino arubano": [ + "AWG" + ], + "rand": [ + "ZAR" + ], + "schekel": [ + "ILS" + ], + "sterlina di sant'elena": [ + "SHP" + ], + "pound sterling": [ + "GBP" + ], + "nacfa eritreo": [ + "ERN" + ], + "dolar taiwanes": [ + "TWD" + ], + "koruna c\u030ceska": [ + "CZK" + ], + "\u20ad": [ + "LAK" + ], + "kro\u0301na": [ + "ISK" + ], + "denar macedonio": [ + "MKD" + ], + "libra libanesa": [ + "LBP" + ], + "dolar belicen\u0303o": [ + "BZD" + ], + "lesotho\u0301i loti": [ + "LSL" + ], + "colombian peso": [ + "COP" + ], + "do\u0301lar de brune\u0301i": [ + "BND" + ], + "szingapu\u0301ri dolla\u0301r": [ + "SGD" + ], + "franc poincare": [ + "XFO" + ], + "metical mozambiqueno": [ + "MZN" + ], + "filipijnse peso": [ + "PHP" + ], + "somoni": [ + "TJS" + ], + "lempire hondurien": [ + "HNL" + ], + "angolan kwanza": [ + "AOA" + ], + "schwedenkrone": [ + "SEK" + ], + "lire maltaise": [ + "MTL" + ], + "balboa paname\u0301en": [ + "PAB" + ], + "israelische lire": [ + "ILS" + ], + "nzd": [ + "NZD" + ], + "hryvnia ucraina": [ + "UAH" + ], + "pataca": [ + "MOP" + ], + "coronas suecas": [ + "SEK" + ], + "cape verde escudo": [ + "CVE" + ], + "rupia pakistani": [ + "PKR" + ], + "hungarian forint": [ + "HUF" + ], + "rupia pakistana": [ + "PKR" + ], + "bs.": [ + "BOB" + ], + "kopeken": [ + "RUB" + ], + "dolar bahameno": [ + "BSD" + ], + "de\u0301l koreai von": [ + "KRW" + ], + "zo\u0308ld foki ko\u0308zta\u0301rsasa\u0301gi escudo": [ + "CVE" + ], + "romanian leu": [ + "RON" + ], + "etio\u0301p birr": [ + "ETB" + ], + "indiai ru\u0301pia": [ + "INR" + ], + "livre de gibraltar": [ + "GIP" + ], + "pa\u2019anga": [ + "TOP" + ], + "mexiko\u0301i pezo\u0301": [ + "MXN" + ], + "tansania schilling": [ + "TZS" + ], + "omanitische rial": [ + "OMR" + ], + "rial omani\u0301": [ + "OMR" + ], + "milandor": [ + "RSD" + ], + "canadischer dollar": [ + "CAD" + ], + "dollaro delle isole salomone": [ + "SBD" + ], + "noorse kronen": [ + "NOK" + ], + "samoan ta\u0304la\u0304": [ + "WST" + ], + "aruban florin": [ + "AWG" + ], + "iraakse dinar": [ + "IQD" + ], + "malaysian ringgit": [ + "MYR" + ], + "som usbeco": [ + "UZS" + ], + "ariary": [ + "MGA" + ], + "kyat": [ + "MMK" + ], + "austral (moneda de argentina)": [ + "ARA" + ], + "bruneise dollar": [ + "BND" + ], + "leu romeno": [ + "RON" + ], + "kolumbiai peso": [ + "COP" + ], + "oezbeekse sum": [ + "UZS" + ], + "burundese frank": [ + "BIF" + ], + "austral (argentina)": [ + "ARA" + ], + "riyal qatarien": [ + "QAR" + ], + "quetzal guatemalteque": [ + "GTQ" + ], + "taiwan dollar": [ + "TWD" + ], + "dolar de namibia": [ + "NAD" + ], + "indiase rupee": [ + "INR" + ], + "dollaro delle figi": [ + "FJD" + ], + "cfa franc beac": [ + "XAF" + ], + "hrk": [ + "HRK" + ], + "peso dominicano": [ + "DOP" + ], + "sh.so.": [ + "SOS" + ], + "kwacha zambiano": [ + "ZMW" + ], + "\u0441\u043e\u043c": [ + "KGS" + ], + "roupie nepalaise": [ + "NPR" + ], + "bermudian dollar": [ + "BMD" + ], + "cookinseln dollar": [ + "NZD" + ], + "bam": [ + "BAM" + ], + "kwanza angolen\u0303o": [ + "AOA" + ], + "dinaro libico": [ + "LYD" + ], + "malagasy ariary": [ + "MGA" + ], + "dolar liberiano": [ + "LRD" + ], + "falklandeilands pond": [ + "FKP" + ], + "nouvelle livre turque": [ + "TRY" + ], + "szovjet rubel": [ + "SUR" + ], + "magyar forint": [ + "HUF" + ], + "peso cubain": [ + "CUP" + ], + "xfo": [ + "XFO" + ], + "pakiszta\u0301ni ru\u0301pia": [ + "PKR" + ], + "georgische lari": [ + "GEL" + ], + "loti": [ + "LSL" + ], + "moldawischer leu": [ + "MDL" + ], + "dollaro statunitense": [ + "USD" + ], + "do\u0301lar bahame\u0301s": [ + "BSD" + ], + "lat leto\u0301n": [ + "LVL" + ], + "peso cileno": [ + "CLP" + ], + "dinar libio": [ + "LYD" + ], + "salomon dollar": [ + "SBD" + ], + "rupia nepali": [ + "NPR" + ], + "cop": [ + "COP" + ], + "sri\u0301 lanka i ru\u0301pia": [ + "LKR" + ], + "maloti": [ + "LSL" + ], + "drtrigonbot:exchange rate data:hrk": [ + "HRK" + ], + "franco ruandese": [ + "RWF" + ], + "ils": [ + "ILS" + ], + "bangladeshi taka": [ + "BDT" + ], + "konvertierbarer peso": [ + "CUC" + ], + "she\u0301kel": [ + "ILS" + ], + "kwd": [ + "KWD" + ], + "bahrain dinar": [ + "BHD" + ], + "sfr.": [ + "CHF" + ], + "livre syrienne": [ + "SYP" + ], + "macao pataca": [ + "MOP" + ], + "dolar de las islas caiman": [ + "KYD" + ], + "dollaro del brunei": [ + "BND" + ], + "chil$": [ + "CLP" + ], + "honduranischer lempira": [ + "HNL" + ], + "frf": [ + "FRF" + ], + "nakfa": [ + "ERN" + ], + "ghanese cedi": [ + "GHS" + ], + "dalasi gambien": [ + "GMD" + ], + "braziliaanse real": [ + "BRL" + ], + "frw": [ + "RWF" + ], + "libra falkland": [ + "FKP" + ], + "algerijnse dinar": [ + "DZD" + ], + "dinar du bahrei\u0308n": [ + "BHD" + ], + "dinar serbio": [ + "RSD" + ], + "rupias indias": [ + "INR" + ], + "lesotho loti": [ + "LSL" + ], + "do\u0301lar guyane\u0301s": [ + "GYD" + ], + "mauritanian ouguiya": [ + "MRO" + ], + "greek drachma": [ + "GRD" + ], + "east caribbean dollar": [ + "XCD" + ], + "dirham de emiratos a\u0301rabes unidos": [ + "AED" + ], + "scellino tanzaniano": [ + "TZS" + ], + "aurar": [ + "ISK" + ], + "oost duitse mark": [ + "DDM" + ], + "franc guine\u0301en": [ + "GNF" + ], + "dollaro hongkonghese": [ + "HKD" + ], + "sll": [ + "SLL" + ], + "\u09f3": [ + "BDT" + ], + "rial saudita": [ + "SAR" + ], + "tzs": [ + "TZS" + ], + "real bresilien": [ + "BRL" + ], + "irakischer dinar": [ + "IQD" + ], + "rupias": [ + "INR" + ], + "sistema u\u0301nico de compensacio\u0301n regional": [ + "XSU" + ], + "franco frances": [ + "FRF" + ], + "costaricaanse colo\u0301n": [ + "CRC" + ], + "lita lituano": [ + "LTL" + ], + "\u20ae": [ + "MNT" + ], + "\u0434\u043e\u043b\u0430\u0440": [ + "MKD" + ], + "peso filippino": [ + "PHP" + ], + "dolar neocelandes": [ + "NZD" + ], + "to\u0308gro\u0308g": [ + "MNT" + ], + "rupiah": [ + "IDR" + ], + "zersto\u0308\u00dft sterling": [ + "GBP" + ], + "can$": [ + "CAD" + ], + "pgk": [ + "PGK" + ], + "rupia india": [ + "INR" + ], + "do\u0301lar belicen\u0303o": [ + "BZD" + ], + "nis": [ + "ILS" + ], + "letse lats": [ + "LVL" + ], + "slrs": [ + "LKR" + ], + "dominikanischer peso": [ + "DOP" + ], + "emira\u0301tusi dirham": [ + "AED" + ], + "litas lituano": [ + "LTL" + ], + "litas lituana": [ + "LTL" + ], + "rupia nepali\u0301": [ + "NPR" + ], + "thb": [ + "THB" + ], + "swazi lilangeni": [ + "SZL" + ], + "yen": [ + "JPY" + ], + "flori\u0301n hungaro": [ + "HUF" + ], + "gourde hai\u0308tienne": [ + "HTG" + ], + "yer": [ + "YER" + ], + "argentinischer austral": [ + "ARA" + ], + "bolivar ve\u0301ne\u0301zue\u0301lien": [ + "VEF" + ], + "bolivianischer boliviano": [ + "BOB" + ], + "sheqalim": [ + "ILS" + ], + "\u20af": [ + "GRD" + ], + "brits pond": [ + "GBP" + ], + "sterlina sudanese": [ + "SDG" + ], + "koruna cesko slovenska": [ + "CSK" + ], + "argent chinois": [ + "CNY" + ], + "libische dinar": [ + "LYD" + ], + "libanese pond": [ + "LBP" + ], + "burundian franc": [ + "BIF" + ], + "nuevo sol peruano": [ + "PEN" + ], + "singapore dollar": [ + "SGD" + ], + "dollar hai\u0308tien": [ + "HTG" + ], + "balboa panameen": [ + "PAB" + ], + "aserbaidschanischer manat": [ + "AZN" + ], + "co\u0301rdoba": [ + "NIO" + ], + "sterlina delle falkland": [ + "FKP" + ], + "peso messicano": [ + "MXN" + ], + "millime": [ + "TND" + ], + "omaanse rial": [ + "OMR" + ], + "sjekel": [ + "ILS" + ], + "vatu": [ + "VUV" + ], + "colo\u0301n": [ + "CRC" + ], + "bosnisch herzegowinische konvertible mark": [ + "BAM" + ], + "dollar guyanien": [ + "GYD" + ], + "cedi": [ + "GHS" + ], + "rupia de mauricio": [ + "MUR" + ], + "cny": [ + "CNY" + ], + "pataca di macao": [ + "MOP" + ], + "argentine austral": [ + "ARA" + ], + "austral (wa\u0308hrung)": [ + "ARA" + ], + "nuevo do\u0301lar taiwane\u0301s": [ + "TWD" + ], + "dinar bahraini\u0301": [ + "BHD" + ], + "som kirghizo": [ + "KGS" + ], + "baht": [ + "THB" + ], + "sri lanka rupee": [ + "LKR" + ], + "zsenminpi": [ + "CNY" + ], + "ryal saoudien": [ + "SAR" + ], + "djibouti franc": [ + "DJF" + ], + "pula del botswana": [ + "BWP" + ], + "mauritiaanse rupee": [ + "MUR" + ], + "syrische lira": [ + "SYP" + ], + "centas": [ + "LTL" + ], + "dollars": [ + "USD" + ], + "guineai frank": [ + "GNF" + ], + "panamai balboa": [ + "PAB" + ], + "dollaro": [ + "BBD", + "BZD" + ], + "us dollar": [ + "USD" + ], + "ta\u0304la\u0304": [ + "WST" + ], + "peso dominicain": [ + "DOP" + ], + "\u4eba\u6c11\u5e01": [ + "CNY" + ], + "libra de gibraltar": [ + "GIP" + ], + "mark est allemand": [ + "DDM" + ], + "libra jamaicana": [ + "JMD" + ], + "eritrean nakfa": [ + "ERN" + ], + "som": [ + "KGS", + "UZS" + ], + "sol": [ + "PEN" + ], + "bath": [ + "THB" + ], + "do\u0301lar surinames": [ + "SRD" + ], + "srilankaanse roepie": [ + "LKR" + ], + "oma\u0301ni ria\u0301l": [ + "OMR" + ], + "dolar guyane\u0301s": [ + "GYD" + ], + "dollaro delle bahamas": [ + "BSD" + ], + "georgischer lari": [ + "GEL" + ], + "sa\u0303o tome\u0301 e\u0301s pri\u0301ncipe i dobra": [ + "STD" + ], + "namibische dollar": [ + "NAD" + ], + "lira turca": [ + "TRY" + ], + "austral": [ + "ARA" + ], + "tune\u0301ziai dina\u0301r": [ + "TND" + ], + "pyg": [ + "PYG" + ], + "\u060b": [ + "AFN" + ], + "tajikistani somoni": [ + "TJS" + ], + "fiji dollar": [ + "FJD" + ], + "south african rand": [ + "ZAR" + ], + "seychelse rupee": [ + "SCR" + ], + "anciens francs": [ + "FRF" + ], + "nuevo sheqel": [ + "ILS" + ], + "amerikai dolla\u0301r": [ + "USD" + ], + "do\u0301lar canadiense": [ + "CAD" + ], + "turkmenistan manat": [ + "TMT" + ], + "litas": [ + "LTL" + ], + "peso cubano": [ + "CUP" + ], + "maltese lira": [ + "MTL" + ], + "azn": [ + "AZN" + ], + "maltese lire": [ + "MTL" + ], + "sve\u0301d korona": [ + "SEK" + ], + "konvertibilna marka": [ + "BAM" + ], + "peso": [ + "COP", + "DOP", + "MXN" + ], + "franse frank": [ + "FRF" + ], + "mexiko\u0301i peso": [ + "MXN" + ], + "pesos": [ + "MXN" + ], + "shilling kenyan": [ + "KES" + ], + "iqd": [ + "IQD" + ], + "colo\u0301n costaricain": [ + "CRC" + ], + "dinar soudanais": [ + "SDG" + ], + "peso colombien": [ + "COP" + ], + "renminbi cinese": [ + "CNY" + ], + "mark der deutschen notenbank": [ + "DDM" + ], + "re\u0301al": [ + "BRL" + ], + "mauritius rupie": [ + "MUR" + ], + "tongai pa'anga": [ + "TOP" + ], + "deutsche mark der deutschen notenbank": [ + "DDM" + ], + "ddr geld": [ + "DDM" + ], + "usbekistan som": [ + "UZS" + ], + "trinidad und tobago dollar": [ + "TTD" + ], + "guyanai dolla\u0301r": [ + "GYD" + ], + "do\u0301lar de bermuda": [ + "BMD" + ], + "peso convertible": [ + "CUC" + ], + "livre britannique": [ + "GBP" + ], + "italienische lira": [ + "ITL" + ], + "italienische lire": [ + "ITL" + ], + "kenyai shilling": [ + "KES" + ], + "li\u0301biai dina\u0301r": [ + "LYD" + ], + "nuevo dolar taiwanes": [ + "TWD" + ], + "fijan dollar": [ + "FJD" + ], + "uruguayischer peso": [ + "UYU" + ], + "neuseela\u0308ndischer dollar": [ + "NZD" + ], + "csendes o\u0301cea\u0301ni valutako\u0308zo\u0308sse\u0301gi frank": [ + "XPF" + ], + "poisha": [ + "BDT" + ], + "lat letton": [ + "LVL" + ], + "n$": [ + "NAD" + ], + "rwandan franc": [ + "RWF" + ], + "lempira": [ + "HNL" + ], + "speciale trekkingsrechten": [ + "XDR" + ], + "maldivian rufiyaa": [ + "MVR" + ], + "rwandan frank": [ + "RWF" + ], + "israe\u0308lische lire": [ + "ILS" + ], + "afgani": [ + "AFN" + ], + "rol": [ + "RON" + ], + "u+20bd": [ + "RUB" + ], + "s\u0192": [ + "SRD" + ], + "dinar bahreini": [ + "BHD" + ], + "tongai pa\u02bbanga": [ + "TOP" + ], + "franco suizo": [ + "CHF" + ], + "marco convertible": [ + "BAM" + ], + "forint hongrois": [ + "HUF" + ], + "som kirguis": [ + "KGS" + ], + "israeli new shekel": [ + "ILS" + ], + "som kirguiz": [ + "KGS" + ], + "albanischer lek": [ + "ALL" + ], + "vef": [ + "VEF" + ], + "kongo franc": [ + "CDF" + ], + "mexicaanse peso": [ + "MXN" + ], + "argentine peso": [ + "ARS" + ], + "guatemaltekischer quetzal": [ + "GTQ" + ], + "novo kwanza": [ + "AOA" + ], + "zuid soedanese pond": [ + "SSP" + ], + "horva\u0301t kuna": [ + "HRK" + ], + "dolar neozelandes": [ + "NZD" + ], + "tu\u0308rkme\u0301n manat": [ + "TMT" + ], + "lilangeni sign": [ + "SZL" + ], + "new taiwan dollar": [ + "TWD" + ], + "swazische lilangeni": [ + "SZL" + ], + "stotinki": [ + "BGN" + ], + "\u0111o\u0302\u0300ng vietnamita": [ + "VND" + ], + "franco burunde\u0301s": [ + "BIF" + ], + "stotinka": [ + "BGN" + ], + "cordoba nicaragu\u0308ense": [ + "NIO" + ], + "lebanese pound": [ + "LBP" + ], + "flori\u0301n aruben\u0303o": [ + "AWG" + ], + "algerian dinar": [ + "DZD" + ], + "dinar jordano": [ + "JOD" + ], + "rial saoudien": [ + "SAR" + ], + "litva\u0301n litas": [ + "LTL" + ], + "scellino ugandese": [ + "UGX" + ], + "zai\u0308re": [ + "CDF" + ], + "florin d\u2019aruba": [ + "AWG" + ], + "grivnia ucraina": [ + "UAH" + ], + "sambischer kwacha": [ + "ZMW" + ], + "filler": [ + "HUF" + ], + "ringgit": [ + "MYR" + ], + "rupia del pakistan": [ + "PKR" + ], + "nieuwe turkse lira": [ + "TRY" + ], + "chilei peso": [ + "CLP" + ], + "iranian rial": [ + "IRR" + ], + "tadzjiekse somoni": [ + "TJS" + ], + "metical mozambiquen\u0303o": [ + "MZN" + ], + "sterlina inglese": [ + "GBP" + ], + "mauritian rupee": [ + "MUR" + ], + "dinaro del bahrain": [ + "BHD" + ], + "venezuelai boli\u0301var": [ + "VEF" + ], + "ruma\u0308nischer ban": [ + "RON" + ], + "dolar de las islas salomo\u0301n": [ + "SBD" + ], + "roepiah": [ + "IDR" + ], + "dinaro serbo": [ + "RSD" + ], + "riyal catari\u0301": [ + "QAR" + ], + "dollaro surinamese": [ + "SRD" + ], + "libra sursudanesa": [ + "SSP" + ], + "south sudanese pound": [ + "SSP" + ], + "boli\u0301var venezuelano": [ + "VEF" + ], + "shilling ke\u0301nyan": [ + "KES" + ], + "dolar suriname\u0301s": [ + "SRD" + ], + "bolivares fuertes": [ + "VEF" + ], + "francos suizos": [ + "CHF" + ], + "botsuanischer pula": [ + "BWP" + ], + "nieuwe israe\u0308lische sjekel": [ + "ILS" + ], + "bahama dollar": [ + "BSD" + ], + "sierra leonischer leone": [ + "SLL" + ], + "bob": [ + "BOB" + ], + "botswana pula": [ + "BWP" + ], + "nepa\u0301li ru\u0301pia": [ + "NPR" + ], + "dollaro taiwanese": [ + "TWD" + ], + "dolar de belice": [ + "BZD" + ], + "sierra leonean leone": [ + "SLL" + ], + "franco gibutiano": [ + "DJF" + ], + "franco": [ + "RWF", + "DJF", + "CDF", + "XPF" + ], + "nouveau dollar de tai\u0308wan": [ + "TWD" + ], + "libras esterlinas": [ + "GBP" + ], + "paraguayischer guarani\u0301": [ + "PYG" + ], + "drachme (antike)": [ + "GRD" + ], + "\u20b1": [ + "PHP" + ], + "s\u20a3": [ + "CHF" + ], + "csehszlova\u0301k korona": [ + "CSK" + ], + "lithuanian litas": [ + "LTL" + ], + "malagassische ariary": [ + "MGA" + ], + "afl.": [ + "AWG" + ], + "flori\u0301n hu\u0301ngaro": [ + "HUF" + ], + "izraeli u\u0301j se\u0301kel": [ + "ILS" + ], + "nigeriaanse naira": [ + "NGN" + ], + "kazakhstani tenge": [ + "KZT" + ], + "south korean won": [ + "KRW" + ], + "dollar de hong kong": [ + "HKD" + ], + "su\u0308dkoreanischer won": [ + "KRW" + ], + "peso mejicano": [ + "MXN" + ], + "won nordcoreano": [ + "KPW" + ], + "mark der ddr": [ + "DDM" + ], + "tschechische krone": [ + "CZK" + ], + "solomon islands dollar": [ + "SBD" + ], + "boli\u0301viai boliviano": [ + "BOB" + ], + "costaricaanse colon": [ + "CRC" + ], + "jemen rial": [ + "YER" + ], + "mga": [ + "MGA" + ], + "kyd": [ + "KYD" + ], + "mauritaanse ouguiya": [ + "MRO" + ], + "gambiaanse dalasi": [ + "GMD" + ], + "gibraltar pound": [ + "GIP" + ], + "tsjechoslowaakse kroon": [ + "CSK" + ], + "gourde": [ + "HTG" + ], + "corona sueca": [ + "SEK" + ], + "colon costaricano": [ + "CRC" + ], + "franc congolais": [ + "CDF" + ], + "florin arubeno": [ + "AWG" + ], + "kaapverdische escudo": [ + "CVE" + ], + "venezolaanse bolivar": [ + "VEF" + ], + "s/": [ + "PEN" + ], + "dolar de nueva zelanda": [ + "NZD" + ], + "do\u0301lar suriname\u0301s": [ + "SRD" + ], + "francs suisses": [ + "CHF" + ], + "s$": [ + "SGD" + ], + "italiaanse lire": [ + "ITL" + ], + "italiaanse lira": [ + "ITL" + ], + "bahreinse dinar": [ + "BHD" + ], + "sr": [ + "SAR" + ], + "corona": [ + "SEK" + ], + "font sterling": [ + "GBP" + ], + "peso chileno": [ + "CLP" + ], + "tala": [ + "WST" + ], + "libra gibraltarena": [ + "GIP" + ], + "saoedi arabische riyal": [ + "SAR" + ], + "guinese frank": [ + "GNF" + ], + "dracma (moderna)": [ + "GRD" + ], + "franco de burundi": [ + "BIF" + ], + "thaise baht": [ + "THB" + ], + "koruna": [ + "CZK" + ], + "koruna ceska": [ + "CZK" + ], + "dram armeno": [ + "AMD" + ], + "st. helena pfund": [ + "SHP" + ], + "lek albanese": [ + "ALL" + ], + "trinidad en tobagodollar": [ + "TTD" + ], + "cuban peso": [ + "CUP" + ], + "gtq": [ + "GTQ" + ], + "djf": [ + "DJF" + ], + "east german mark": [ + "DDM" + ], + "yuan cinese": [ + "CNY" + ], + "jordaanse dinar": [ + "JOD" + ], + "guinean franc": [ + "GNF" + ], + "szoma\u0301liai shilling": [ + "SOS" + ], + "nok": [ + "NOK" + ], + "do\u0301lar de namibia": [ + "NAD" + ], + "shilingi": [ + "TZS" + ], + "franco yibuti": [ + "DJF" + ], + "rufiyah": [ + "MVR" + ], + "col$": [ + "COP" + ], + "rufiyaa": [ + "MVR" + ], + "tt$": [ + "TTD" + ], + "cheli\u0301n": [ + "UGX", + "TZS", + "SOS" + ], + "gryvnia": [ + "UAH" + ], + "cfp franc": [ + "XPF" + ], + "real brasiliano": [ + "BRL" + ], + "cfp frank": [ + "XPF" + ], + "taka bengalese": [ + "BDT" + ], + "ngwee": [ + "ZMW" + ], + "metical mozambicano": [ + "MZN" + ], + "lempira honduregna": [ + "HNL" + ], + "libra malvinense": [ + "FKP" + ], + "nuevo she\u0301quel": [ + "ILS" + ], + "rial omanais": [ + "OMR" + ], + "arg$": [ + "ARS" + ], + "nicaraguanischer co\u0301rdoba": [ + "NIO" + ], + "colon costaricien": [ + "CRC" + ], + "drtrigonbot:exchange rate data:dkk": [ + "DKK" + ], + "goldfranken": [ + "XFO" + ], + "roupie indienne": [ + "INR" + ], + "afghani": [ + "AFN" + ], + "franc cfp": [ + "XPF" + ], + "seychelle szigeteki ru\u0301pia": [ + "SCR" + ], + "franco ruandes": [ + "RWF" + ], + "pesification": [ + "ARS" + ], + "dirham des emirats arabes unis": [ + "AED" + ], + "$can": [ + "CAD" + ], + "franc cfa": [ + "XAF", + "XOF" + ], + "nepalese roepie": [ + "NPR" + ], + "lwei": [ + "AOA" + ], + "nuovo peso argentino": [ + "ARS" + ], + "indonesian rupiah": [ + "IDR" + ], + "guatemalai quetzal": [ + "GTQ" + ], + "dolar de singapur": [ + "SGD" + ], + "peso de me\u0301xico": [ + "MXN" + ], + "surinamese guilder": [ + "SRG" + ], + "nigerian naira": [ + "NGN" + ], + "peso philippin": [ + "PHP" + ], + "mongoolse tugrik": [ + "MNT" + ], + "franc pacifique": [ + "XPF" + ], + "haitianischer gourde": [ + "HTG" + ], + "jemenitische rial": [ + "YER" + ], + "do\u0301lar": [ + "USD", + "FJD" + ], + "kolumbianischer peso": [ + "COP" + ], + "co\u0301rdoba nicaraguense": [ + "NIO" + ], + "dollar ne\u0301oze\u0301landais": [ + "NZD" + ], + "meticais": [ + "MZN" + ], + "uqiya": [ + "MRO" + ], + "grivnia": [ + "UAH" + ], + "lakhs": [ + "BDT" + ], + "zar": [ + "ZAR" + ], + "bahamian dollar": [ + "BSD" + ], + "qa\u0308pik": [ + "AZN" + ], + "ukp": [ + "GBP" + ], + "paraguayaanse guarani\u0301": [ + "PYG" + ], + "mauritiusi ru\u0301pia": [ + "MUR" + ], + "philippinischer peso": [ + "PHP" + ], + "kambodschanischer riel": [ + "KHR" + ], + "huf": [ + "HUF" + ], + "dollar de singapour": [ + "SGD" + ], + "dom$": [ + "DOP" + ], + "dinar du kowei\u0308t": [ + "KWD" + ], + "australian dollar": [ + "AUD" + ], + "namibian dollar": [ + "NAD" + ], + "arubaanse gulden": [ + "AWG" + ], + "drachme moderne grecque": [ + "GRD" + ], + "dinar kowe\u0301itien": [ + "KWD" + ], + "nieuwe israelische sheqel": [ + "ILS" + ], + "salyn": [ + "THB" + ], + "moldova\u0301n lej": [ + "MDL" + ], + "nepalesische rupie": [ + "NPR" + ], + "marka convertible": [ + "BAM" + ], + "bulgarian lev": [ + "BGN" + ], + "tengue": [ + "KZT" + ], + "currency of somalia": [ + "SOS" + ], + "franc franc\u0327ais": [ + "FRF" + ], + "do\u0301lar bahames": [ + "BSD" + ], + "som de kirguistan": [ + "KGS" + ], + "kip laotiano": [ + "LAK" + ], + "sar": [ + "SAR" + ], + "ngultrum butane\u0301s": [ + "BTN" + ], + "birr etiope": [ + "ETB" + ], + "fening": [ + "BAM" + ], + "dominicaanse peso": [ + "DOP" + ], + "taka": [ + "BDT" + ], + "\u20b2": [ + "PYG" + ], + "do\u0301lar neozelandes": [ + "NZD" + ], + "rial ye\u0301me\u0301nite": [ + "YER" + ], + "sterlina sud sudanese": [ + "SSP" + ], + "dolar de bermuda": [ + "BMD" + ], + "dollar taiwanais": [ + "TWD" + ], + "afghanis": [ + "AFN" + ], + "uyu": [ + "UYU" + ], + "cordoba": [ + "NIO" + ], + "bahamaanse dollar": [ + "BSD" + ], + "\u0111ong": [ + "VND" + ], + "baiza": [ + "OMR" + ], + "kazachse tenge": [ + "KZT" + ], + "vietnamesischer \u0111o\u0302\u0300ng": [ + "VND" + ], + "dollar de brunei": [ + "BND" + ], + "dollar du belize": [ + "BZD" + ], + "jordanian dinar": [ + "JOD" + ], + "nuevo sol peruviano": [ + "PEN" + ], + "livre turque": [ + "TRY" + ], + "fidschi dollar": [ + "FJD" + ], + "franco cfa de africa central": [ + "XAF" + ], + "kyrgyzstani som": [ + "KGS" + ], + "dolar taiwane\u0301s": [ + "TWD" + ], + "quetzales": [ + "GTQ" + ], + "pa\u0301pua u\u0301j guineai kina": [ + "PGK" + ], + "won nord core\u0301en": [ + "KPW" + ], + "couronne danoise": [ + "DKK" + ], + "nuevo do\u0301lar de taiwa\u0301n": [ + "TWD" + ], + "uruguay peso": [ + "UYU" + ], + "boli\u0301vares fuertes": [ + "VEF" + ], + "rupia de pakistan": [ + "PKR" + ], + "lilangeni": [ + "SZL" + ], + "rupia dell'india": [ + "INR" + ], + "libra esterlina": [ + "GBP" + ], + "koruna ceska\u0301": [ + "CZK" + ], + "\u20b3": [ + "ARA" + ], + "co\u0301rdoba nicaragu\u0308ense": [ + "NIO" + ], + "hongaarse forint": [ + "HUF" + ], + "loti lesothan": [ + "LSL" + ], + "baht thailandese": [ + "THB" + ], + "real brasileno": [ + "BRL" + ], + "katari ria\u0301l": [ + "QAR" + ], + "uzbekistani som": [ + "UZS" + ], + "armenischer dram": [ + "AMD" + ], + "jorda\u0301n dina\u0301r": [ + "JOD" + ], + "bulgaarse lev": [ + "BGN" + ], + "hondurasi lempira": [ + "HNL" + ], + "do\u0302\u0300ng vietnamita": [ + "VND" + ], + "gel": [ + "GEL" + ], + "trinidad en tobago dollar": [ + "TTD" + ], + "rupia de maldivas": [ + "MVR" + ], + "do\u0301lar liberiano": [ + "LRD" + ], + "vanuatuaanse vatu": [ + "VUV" + ], + "libe\u0301riai dolla\u0301r": [ + "LRD" + ], + "colon costarricense": [ + "CRC" + ], + "dobra di sa\u0303o tome\u0301 e pri\u0301ncipe": [ + "STD" + ], + "croatian kuna": [ + "HRK" + ], + "nouveau sol": [ + "PEN" + ], + "wo\u0306n norcoreano": [ + "KPW" + ], + "de\u0301l afrikai rand": [ + "ZAR" + ], + "dolar bermuden\u0303o": [ + "BMD" + ], + "tu\u0308rkische lira": [ + "TRY" + ], + "rmb": [ + "CNY" + ], + "ringgit malese": [ + "MYR" + ], + "marco de la republica democra\u0301tica alemana": [ + "DDM" + ], + "j$": [ + "JMD" + ], + "lire turque": [ + "TRY" + ], + "tunisian dinar": [ + "TND" + ], + "falkland pfund": [ + "FKP" + ], + "pakistani rupee": [ + "PKR" + ], + "central african cfa franc": [ + "XAF" + ], + "rouble": [ + "SUR" + ], + "ytl": [ + "TRY" + ], + "trinidad e\u0301s tobago\u0301 i dolla\u0301r": [ + "TTD" + ], + "orosz rubel": [ + "RUB" + ], + "dollar de surinam": [ + "SRD" + ], + "franco delle comore": [ + "KMF" + ], + "so\u02bbm": [ + "UZS" + ], + "franse franc": [ + "FRF" + ], + "kuna croata": [ + "HRK" + ], + "droits de tirage spe\u0301ciaux": [ + "XDR" + ], + "kuna croate": [ + "HRK" + ], + "dinar de kuwait": [ + "KWD" + ], + "dschibuti franc": [ + "DJF" + ], + "guinea franc": [ + "GNF" + ], + "kwacha zambese": [ + "ZMW" + ], + "guatemalteekse quetzal": [ + "GTQ" + ], + "chelin keniano": [ + "KES" + ], + "livre libanaise": [ + "LBP" + ], + "dkk": [ + "DKK" + ], + "ouguiya della mauritana": [ + "MRO" + ], + "kaaimaneilandse dollar": [ + "KYD" + ], + "drtrigonbot:exchange rate data:ltl": [ + "LTL" + ], + "comorese frank": [ + "KMF" + ], + "us $": [ + "USD" + ], + "lats lettone": [ + "LVL" + ], + "griwna": [ + "UAH" + ], + "qatari riyal": [ + "QAR" + ], + "colon": [ + "CRC" + ], + "franc germinal": [ + "FRF", + "XFO" + ], + "roupie ne\u0301palaise": [ + "NPR" + ], + "dollar jamai\u0308cain": [ + "JMD" + ], + "mark": [ + "DDM" + ], + "indische rupie": [ + "INR" + ], + "angolese kwanza": [ + "AOA" + ], + "dollar de fidji": [ + "FJD" + ], + "khr": [ + "KHR" + ], + "krona": [ + "SEK" + ], + "dollaro di trinidad e tobago": [ + "TTD" + ], + "krone": [ + "DKK" + ], + "szoma\u0301li shilling": [ + "SOS" + ], + "rupia indiana": [ + "INR" + ], + "bolivar fuerte": [ + "VEF" + ], + "euro\u0301": [ + "EUR" + ], + "rupia de indonesia": [ + "IDR" + ], + "libra gibraltaren\u0303a": [ + "GIP" + ], + "indonesische rupiah": [ + "IDR" + ], + "panamaischer balboa": [ + "PAB" + ], + "ethiopian birr": [ + "ETB" + ], + "kubai konvertibilis peso": [ + "CUC" + ], + "clp": [ + "CLP" + ], + "florin d'aruba": [ + "AWG" + ], + "dolar bahames": [ + "BSD" + ], + "ouguiya mauritanien": [ + "MRO" + ], + "salomonen dollar": [ + "SBD" + ], + "chavito": [ + "CUC" + ], + "kanadai dolla\u0301r": [ + "CAD" + ], + "britische pfund": [ + "GBP" + ], + "singaporese dollar": [ + "SGD" + ], + "chinese renminbi": [ + "CNY" + ], + "saudische riyal": [ + "SAR" + ], + "neuer taiwan dollar": [ + "TWD" + ], + "do\u0301lar taiwanes": [ + "TWD" + ], + "keniaanse shilling": [ + "KES" + ], + "do\u0301lar de bahamas": [ + "BSD" + ], + "bhutanese ngultrum": [ + "BTN" + ], + "corona noruega": [ + "NOK" + ], + "dollaro giamaicano": [ + "JMD" + ], + "afgani afgano": [ + "AFN" + ], + "pab": [ + "PAB" + ], + "aruba florin": [ + "AWG" + ], + "tajikistani ruble": [ + "TJR" + ], + "franzo\u0308sischer franc": [ + "FRF" + ], + "lira italiana": [ + "ITL" + ], + "$ can": [ + "CAD" + ], + "marco de la rda": [ + "DDM" + ], + "ostkaribische wa\u0308hrungsunion": [ + "XCD" + ], + "naf": [ + "ANG" + ], + "drtrigonbot:exchange rate data:jpy": [ + "JPY" + ], + "afghaanse afghani": [ + "AFN" + ], + "peruviaanse sol": [ + "PEN" + ], + "livre de sainte he\u0301le\u0300ne": [ + "SHP" + ], + "sa\u0303o tome\u0301 and pri\u0301ncipe dobra": [ + "STD" + ], + "co\u0301rdoba oro": [ + "NIO" + ], + "moneda nacional": [ + "CUP" + ], + "macanese pataca": [ + "MOP" + ], + "couronne tcheque": [ + "CZK" + ], + "chelin ugande\u0301s": [ + "UGX" + ], + "peso cubano convertible": [ + "CUC" + ], + "eritreai nakfa": [ + "ERN" + ], + "ira\u0301ni ria\u0301l": [ + "IRR" + ], + "dollar canadien": [ + "CAD" + ], + "litouwse litas": [ + "LTL" + ], + "venezuelan boli\u0301var": [ + "VEF" + ], + "lib$": [ + "LRD" + ], + "cheli\u0301n keniata": [ + "KES" + ], + "riyal saoudien": [ + "SAR" + ], + "usbekistan sum": [ + "UZS" + ], + "chelin keniata": [ + "KES" + ], + "peso cubano convertibile": [ + "CUC" + ], + "euros": [ + "EUR" + ], + "dollar des bermudes": [ + "BMD" + ], + "liberianischer dollar": [ + "LRD" + ], + "peso convertibile": [ + "CUC" + ], + "grd": [ + "GRD" + ], + "tschechoslowakische krone": [ + "CSK" + ], + "tongan pa'anga": [ + "TOP" + ], + "szamoai tala": [ + "WST" + ], + "namibischer dollar": [ + "NAD" + ], + "manat azerbai\u0308djanais": [ + "AZN" + ], + "real": [ + "BRL" + ], + "tanzanian shilingi": [ + "TZS" + ], + "dollar liberien": [ + "LRD" + ], + "do\u0301lar neocelandes": [ + "NZD" + ], + "do\u0301lar taiwane\u0301s": [ + "TWD" + ], + "dinaro del bahrein": [ + "BHD" + ], + "florin hu\u0301ngaro": [ + "HUF" + ], + "zambian kwacha": [ + "ZMW" + ], + "dracma greca": [ + "GRD" + ], + "italian lira": [ + "ITL" + ], + "antilliaanse gulden": [ + "ANG" + ], + "som uzbeco": [ + "UZS" + ], + "yuan renminbi": [ + "CNY" + ], + "tenge kazajo": [ + "KZT" + ], + "dolar trinitense": [ + "TTD" + ], + "dollaro bahamense": [ + "BSD" + ], + "yeni kurus\u0327": [ + "TRY" + ], + "brunei dollar": [ + "BND" + ], + "lek albanes": [ + "ALL" + ], + "yua\u0301n chino": [ + "CNY" + ], + "\u20adn": [ + "LAK" + ], + "som kirgui\u0301s": [ + "KGS" + ], + "britse pond": [ + "GBP" + ], + "\u20b4": [ + "UAH" + ], + "nuevo dolar de taiwa\u0301n": [ + "TWD" + ], + "dominican peso": [ + "DOP" + ], + "mosambikanischer escudo": [ + "MZE" + ], + "do\u0301lar de las islas caima\u0301n": [ + "KYD" + ], + "gibraltar pfund": [ + "GIP" + ], + "lats leto\u0301n": [ + "LVL" + ], + "kanadische dollar": [ + "CAD" + ], + "srd": [ + "SRD" + ], + "sre": [ + "SCR" + ], + "comore i frank": [ + "KMF" + ], + "peso colombiano": [ + "COP" + ], + "leke\u0308": [ + "ALL" + ], + "\u0433\u0440\u0438\u0432\u043d\u044f": [ + "UAH" + ], + "alu chip": [ + "DDM" + ], + "kanadischer dollar": [ + "CAD" + ], + "suriname dollar": [ + "SRD" + ], + "corona ceca": [ + "CZK" + ], + "serbischer dinar": [ + "RSD" + ], + "dollar de brune\u0301i": [ + "BND" + ], + "denar": [ + "MKD" + ], + "dinar macedonio": [ + "MKD" + ], + "lira maltese": [ + "MTL" + ], + "frans geld": [ + "FRF" + ], + "naira nigeriana": [ + "NGN" + ], + "nuevo do\u0301lar taiwanes": [ + "TWD" + ], + "dollaro neozelandese": [ + "NZD" + ], + "dinar bahrei\u0308nien": [ + "BHD" + ], + "zweedse kroon": [ + "SEK" + ], + "swedish krona": [ + "SEK" + ], + "new israeli shekel": [ + "ILS" + ], + "leu moldave": [ + "MDL" + ], + "rupia de nepal": [ + "NPR" + ], + "leu moldavo": [ + "MDL" + ], + "fidzsi dolla\u0301r": [ + "FJD" + ], + "pula": [ + "BWP" + ], + "drachmai": [ + "GRD" + ], + "marco bosnio": [ + "BAM" + ], + "roupie seychelloise": [ + "SCR" + ], + "u\u0308zbe\u0301g szom": [ + "UZS" + ], + "tanzanian schilling": [ + "TZS" + ], + "gib\u00a3": [ + "GIP" + ], + "lett lat": [ + "LVL" + ], + "kc\u030cs": [ + "CSK" + ], + "mark der deutschen demokratischen republik": [ + "DDM" + ], + "yeni tu\u0308rk liras\u0131": [ + "TRY" + ], + "\u3012": [ + "KZT" + ], + "bosnische convertibele mark": [ + "BAM" + ], + "libra siria": [ + "SYP" + ], + "peso oro": [ + "DOP" + ], + "rupia indonesia": [ + "IDR" + ], + "pakistaanse rupee": [ + "PKR" + ], + "riel cambogiano": [ + "KHR" + ], + "haitian gourde": [ + "HTG" + ], + "tschechische wa\u0308hrung": [ + "CZK" + ], + "bosnia and herzegovina convertible mark": [ + "BAM" + ], + "francs franc\u0327ais": [ + "FRF" + ], + "griechische drachme": [ + "GRD" + ], + "nuovo sol": [ + "PEN" + ], + "swiss franc": [ + "CHF" + ], + "swiss frank": [ + "CHF" + ], + "somoni tayiko": [ + "TJS" + ], + "rial yemeni\u0301": [ + "YER" + ], + "nueva lira turca": [ + "TRY" + ], + "engelse pond": [ + "GBP" + ], + "chelin tanzano": [ + "TZS" + ], + "peso de repu\u0301blica dominicana": [ + "DOP" + ], + "dalasi gambese": [ + "GMD" + ], + "nicaraguaanse co\u0301rdoba": [ + "NIO" + ], + "lira libanese": [ + "LBP" + ], + "baht tailandes": [ + "THB" + ], + "khoum": [ + "MRO" + ], + "lek albane\u0301s": [ + "ALL" + ], + "botswanischer pula": [ + "BWP" + ], + "dinar mace\u0301donien": [ + "MKD" + ], + "dollar": [ + "USD" + ], + "dolar bahame\u0301s": [ + "BSD" + ], + "\u20ac": [ + "EUR" + ], + "dollar singapourien": [ + "SGD" + ], + "israe\u0308lische sjekel": [ + "ILS" + ], + "wo\u0306n surcoreano": [ + "KRW" + ], + "ukra\u0301n hrivnya": [ + "UAH" + ], + "dinar algerien": [ + "DZD" + ], + "cedi ghanese": [ + "GHS" + ], + "cfa franc bceao": [ + "XOF" + ], + "scr": [ + "SCR" + ], + "\u0442\u04e9\u0433\u0440\u04e9\u0433": [ + "MNT" + ], + "izlandi korona": [ + "ISK" + ], + "englisches pfund": [ + "GBP" + ], + "ws$": [ + "WST" + ], + "wikipedia:raadsel/netties20070405": [ + "GRD" + ], + "dolar neozelande\u0301s": [ + "NZD" + ], + "samoanischer tala": [ + "WST" + ], + "syrisch pond": [ + "SYP" + ], + "caymaneilandse dollar": [ + "KYD" + ], + "cordoba oro": [ + "NIO" + ], + "kina papuana": [ + "PGK" + ], + "szent ilona i font": [ + "SHP" + ], + "sudanese pound": [ + "SDG" + ], + "gourde haitiano": [ + "HTG" + ], + "dollar hongkongais": [ + "HKD" + ], + "haiti gourde": [ + "HTG" + ], + "eyrir": [ + "ISK" + ], + "australes": [ + "ARA" + ], + "livres turques": [ + "TRY" + ], + "dollar barbadien": [ + "BBD" + ], + "congolese franc": [ + "CDF" + ], + "wst": [ + "WST" + ], + "t$": [ + "TOP" + ], + "congolese frank": [ + "CDF" + ], + "nafka": [ + "ERN" + ], + "dansk krone": [ + "DKK" + ], + "jordanischer dinar": [ + "JOD" + ], + "dolar de bahamas": [ + "BSD" + ], + "brasilianischer real": [ + "BRL" + ], + "nz$": [ + "NZD" + ], + "leone sierra le\u0301onais": [ + "SLL" + ], + "tunesische dinar": [ + "TND" + ], + "do\u0301lar namibio": [ + "NAD" + ], + "$ca": [ + "CAD" + ], + "bengalese taka": [ + "BDT" + ], + "dollar fidjien": [ + "FJD" + ], + "ungarischer forint": [ + "HUF" + ], + "dinar serbe": [ + "RSD" + ], + "do\u0301lar de trinidad y tobago": [ + "TTD" + ], + "belize dollar": [ + "BZD" + ], + "sum": [ + "UZS" + ], + "franc rwandais": [ + "RWF" + ], + "dinar jordanien": [ + "JOD" + ], + "moldauischer leu": [ + "MDL" + ], + "dolar de las islas salomon": [ + "SBD" + ], + "lire italienne": [ + "ITL" + ], + "ang": [ + "ANG" + ], + "\u0e3f": [ + "THB" + ], + "sucre": [ + "XSU" + ], + "kzt": [ + "KZT" + ], + "kronor": [ + "SEK" + ], + "somalische shilling": [ + "SOS" + ], + "dollaro namibiano": [ + "NAD" + ], + "omanischer rial": [ + "OMR" + ], + "do\u0301lar bermuden\u0303o": [ + "BMD" + ], + "marka": [ + "BAM" + ], + "marco convertibile": [ + "BAM" + ], + "rublo ruso": [ + "RUB" + ], + "uae dirham": [ + "AED" + ], + "vae dirham": [ + "AED" + ], + "ngultrum del bhutan": [ + "BTN" + ], + "samoaanse tala": [ + "WST" + ], + "maltesische lira": [ + "MTL" + ], + "couronne norvegienne": [ + "NOK" + ], + "franc burundais": [ + "BIF" + ], + "flori\u0301n arubeno": [ + "AWG" + ], + "georgian kupon lari": [ + "GEL" + ], + "dollar de trinidad et tobago": [ + "TTD" + ], + "t\u0323a\u0304ka\u0304": [ + "BDT" + ], + "tonga pa\u02bbanga": [ + "TOP" + ], + "dinar kuwaiti": [ + "KWD" + ], + "kenia schilling": [ + "KES" + ], + "\u20a1": [ + "CRC" + ], + "guarani paraguayen": [ + "PYG" + ], + "lats letton": [ + "LVL" + ], + "quetzal guate\u0301malte\u0300que": [ + "GTQ" + ], + "netherlands antillean guilder": [ + "ANG" + ], + "balboa panamen\u0303o": [ + "PAB" + ], + "dolar de brune\u0301i": [ + "BND" + ], + "sheqel": [ + "ILS" + ], + "escudo capoverdiano": [ + "CVE" + ], + "boli\u0301var fuerte": [ + "VEF" + ], + "franco della guinea": [ + "GNF" + ], + "boli\u0301var": [ + "VEF" + ], + "lilangeni swazilandais": [ + "SZL" + ], + "dracma griega moderna": [ + "GRD" + ], + "tenge kazako": [ + "KZT" + ], + "tenge kazakh": [ + "KZT" + ], + "mexican centavo": [ + "MXN" + ], + "peso uruguaiano": [ + "UYU" + ], + "franco cfp": [ + "XPF" + ], + "so'm": [ + "UZS" + ], + "drtrigonbot:exchange rate data:chf": [ + "CHF" + ], + "konvertible mark": [ + "BAM" + ], + "nouveau manat aze\u0301ri": [ + "AZN" + ], + "nordjemenitischer rial": [ + "YER" + ], + "bolivares": [ + "VEF" + ], + "\u043b\u0435\u0432": [ + "BGN" + ], + "deg": [ + "XDR" + ], + "guarani paraguaiano": [ + "PYG" + ], + "scellino keniano": [ + "KES" + ], + "f$": [ + "FJD" + ], + "couronne islandaise": [ + "ISK" + ], + "dollar de la barbade": [ + "BBD" + ], + "macause pataca": [ + "MOP" + ], + "do\u0301lar bermudeno": [ + "BMD" + ], + "isk": [ + "ISK" + ], + "west african cfa franc": [ + "XOF" + ], + "armeense dram": [ + "AMD" + ], + "renminbi yuan": [ + "CNY" + ], + "aussie dollar": [ + "AUD" + ], + "franco francese": [ + "FRF" + ], + "tetradrachmon": [ + "GRD" + ], + "dinar irakien": [ + "IQD" + ], + "tongan pa\u02bbanga": [ + "TOP" + ], + "fr": [ + "FRF" + ], + "ft": [ + "HUF" + ], + "nuevo sol": [ + "PEN" + ], + "peso convertible argentino": [ + "ARS" + ], + "ff": [ + "FRF" + ], + "dollar de taiwan": [ + "TWD" + ], + "azerbaijani manat": [ + "AZN" + ], + "dirham": [ + "AED" + ], + "antillen gulden": [ + "ANG" + ], + "lari ge\u0301orgien": [ + "GEL" + ], + "fijian dollar": [ + "FJD" + ], + "mark convertible de bosnie herze\u0301govine": [ + "BAM" + ], + "nuovo siclo israeliano": [ + "ILS" + ], + "bhuta\u0301ni ngultrum": [ + "BTN" + ], + "guarani\u0301 paraguayen": [ + "PYG" + ], + "jamaican dollar": [ + "JMD" + ], + "rupia": [ + "LKR", + "SCR", + "INR", + "NPR" + ], + "dinar libyen": [ + "LYD" + ], + "dinaro giordano": [ + "JOD" + ], + "paraguayan guarani\u0301": [ + "PYG" + ], + "maldivische rufiyaa": [ + "MVR" + ], + "marokkanischer dirham": [ + "MAD" + ], + "franco pacifico": [ + "XPF" + ], + "lats": [ + "LVL" + ], + "forinto": [ + "HUF" + ], + "dollar be\u0301lizien": [ + "BZD" + ], + "forints": [ + "HUF" + ], + "do\u0301lar bahameno": [ + "BSD" + ], + "hrywen": [ + "UAH" + ], + "roupie pakistanaise": [ + "PKR" + ], + "rwf": [ + "RWF" + ], + "iraanse rial": [ + "IRR" + ], + "chetrum": [ + "BTN" + ], + "do\u0301lar de las bahamas": [ + "BSD" + ], + "lesothischer loti": [ + "LSL" + ], + "djiboutian franc": [ + "DJF" + ], + "soviet ruble": [ + "SUR" + ], + "madagascan ariary": [ + "MGA" + ], + "hryvna": [ + "UAH" + ], + "komoren franc": [ + "KMF" + ], + "sterlina britannica": [ + "GBP" + ], + "sonderziehungsrecht": [ + "XDR" + ], + "jamaicai dolla\u0301r": [ + "JMD" + ], + "sierra leone i leone": [ + "SLL" + ], + "laoszi kip": [ + "LAK" + ], + "ma\u0301ltai li\u0301ra": [ + "MTL" + ], + "dolar de fiji": [ + "FJD" + ], + "dirham de los emiratos a\u0301rabes unidos": [ + "AED" + ], + "dollaro della namibia": [ + "NAD" + ], + "vn\u0111": [ + "VND" + ], + "dollar des carai\u0308bes orientales": [ + "XCD" + ], + "kelet karibi dolla\u0301r": [ + "XCD" + ], + "dinar argelino": [ + "DZD" + ], + "dolar de barbados": [ + "BBD" + ], + "sbd": [ + "SBD" + ], + "saoedische riyal": [ + "SAR" + ], + "dinar bareini\u0301": [ + "BHD" + ], + "do\u0301lar de guyana": [ + "GYD" + ], + "won norcoreano": [ + "KPW" + ], + "dram arme\u0301nien": [ + "AMD" + ], + "peso de me\u0301jico": [ + "MXN" + ], + "kuna": [ + "HRK" + ], + "kubanischer peso": [ + "CUP" + ], + "sambia kwacha": [ + "ZMW" + ], + "sri lankaanse roepie": [ + "LKR" + ], + "neue tu\u0308rkische lira": [ + "TRY" + ], + "algerischer dinar": [ + "DZD" + ], + "hong kong dollar": [ + "HKD" + ], + "$a": [ + "ARP" + ], + "rupia nepalese": [ + "NPR" + ], + "bhat": [ + "THB" + ], + "maleisische ringgit": [ + "MYR" + ], + "rupia nepalesa": [ + "NPR" + ], + "tsjechische kroon": [ + "CZK" + ], + "dong": [ + "VND" + ], + "xof": [ + "XOF" + ], + "chilean peso": [ + "CLP" + ], + "nordkoreanischer won": [ + "KPW" + ], + "soedanese pond": [ + "SDG" + ], + "angol font": [ + "GBP" + ], + "kip laosiano": [ + "LAK" + ], + "dollaro delle barbados": [ + "BBD" + ], + "gpb": [ + "GBP" + ], + "nuovo dollaro taiwanese": [ + "TWD" + ], + "pond sterling": [ + "GBP" + ], + "nouveau shekel": [ + "ILS" + ], + "libanees pond": [ + "LBP" + ], + "kuvaiti dina\u0301r": [ + "KWD" + ], + "kenyan shilling": [ + "KES" + ], + "dolar bahamen\u0303o": [ + "BSD" + ], + "surinaamse gulden": [ + "SRG" + ], + "tschang": [ + "THB" + ], + "north korean won": [ + "KPW" + ], + "fiorino ungherese": [ + "HUF" + ], + "franco yibuti\u0301": [ + "DJF" + ], + "servische dinar": [ + "RSD" + ], + "manat turkme\u0300ne": [ + "TMT" + ], + "swiss franken": [ + "CHF" + ], + "costa rica colo\u0301n": [ + "CRC" + ], + "franco yibutiense": [ + "DJF" + ], + "venezolaanse boli\u0301var": [ + "VEF" + ], + "marco de la repu\u0301blica democratica alemana": [ + "DDM" + ], + "karod": [ + "NPR" + ], + "riyal": [ + "SAR" + ], + "birr e\u0301thiopien": [ + "ETB" + ], + "francs pacifique": [ + "XPF" + ], + "rufiyaa delle maldive": [ + "MVR" + ], + "libyan dinar": [ + "LYD" + ], + "siclo israeliano": [ + "ILS" + ], + "santomese dobra": [ + "STD" + ], + "mauritiaanse roepie": [ + "MUR" + ], + "srilankaanse rupee": [ + "LKR" + ], + "sum uzbeco": [ + "UZS" + ], + "laari": [ + "MVR" + ], + "dolar de trinidad y tobago": [ + "TTD" + ], + "austral argentino": [ + "ARA" + ], + "do\u0301lar fijiano": [ + "FJD" + ], + "bz$": [ + "BZD" + ], + "argentijnse peso": [ + "ARS" + ], + "vnd": [ + "VND" + ], + "dong vietnamien": [ + "VND" + ], + "ngultrum butanes": [ + "BTN" + ], + "do\u0301lar del caribe este": [ + "XCD" + ], + "pakistaanse roepie": [ + "PKR" + ], + "drtrigonbot:exchange rate data:usd": [ + "USD" + ], + "indone\u0301z ru\u0301pia": [ + "IDR" + ], + "riyal dell'oman": [ + "OMR" + ], + "gambiai dalasi": [ + "GMD" + ], + "dollaro delle salomone": [ + "SBD" + ], + "bermuda dollar": [ + "BMD" + ], + "km": [ + "BAM" + ], + "kr": [ + "DKK" + ], + "mozambican escudo": [ + "MZE" + ], + "samoan tala": [ + "WST" + ], + "brazil real": [ + "BRL" + ], + "dollaro della guyana": [ + "GYD" + ], + "norve\u0301g korona": [ + "NOK" + ], + "dobra di sao tome\u0301 e principe": [ + "STD" + ], + "cdf": [ + "CDF" + ], + "azerbeidzjaanse manat": [ + "AZN" + ], + "droits de tirage speciaux": [ + "XDR" + ], + "paanga": [ + "TOP" + ], + "livre des i\u0302les malouines": [ + "FKP" + ], + "ugx": [ + "UGX" + ], + "holland antilla\u0301kbeli forint": [ + "ANG" + ], + "\u20a3": [ + "FRF" + ], + "costa rican colo\u0301n": [ + "CRC" + ], + "roupie indone\u0301sienne": [ + "IDR" + ], + "rd$": [ + "DOP" + ], + "dollar australien": [ + "AUD" + ], + "russian ruble": [ + "RUB" + ], + "mianmari kjap": [ + "MMK" + ], + "nicaraguan co\u0301rdoba": [ + "NIO" + ], + "florin aruben\u0303o": [ + "AWG" + ], + "rupie indiane": [ + "INR" + ], + "florin arubain": [ + "AWG" + ], + "dinar kuwaiti\u0301": [ + "KWD" + ], + "hryvnya": [ + "UAH" + ], + "tamil rupee": [ + "LKR" + ], + "oegandese shilling": [ + "UGX" + ], + "corona cecoslovacca": [ + "CSK" + ], + "clp$": [ + "CLP" + ], + "cheli\u0301n ugandes": [ + "UGX" + ], + "kina": [ + "PGK" + ], + "noord koreaanse won": [ + "KPW" + ], + "chilenischer peso": [ + "CLP" + ], + "uganda schilling": [ + "UGX" + ], + "uruguayaanse peso": [ + "UYU" + ], + "metical": [ + "MZN" + ], + "\u0440\u0443\u0431": [ + "RUB" + ], + "marokko\u0301i dirham": [ + "MAD" + ], + "ars": [ + "ARS" + ], + "iraki dina\u0301r": [ + "IQD" + ], + "tugrik mongolo": [ + "MNT" + ], + "soedanees pond": [ + "SDG" + ], + "honduran lempira": [ + "HNL" + ], + "rial dell'oman": [ + "OMR" + ], + "sek": [ + "SEK" + ], + "franc malgache": [ + "MGA" + ], + "fille\u0301r": [ + "HUF" + ], + "piso": [ + "PHP" + ], + "cayman islands dollar": [ + "KYD" + ], + "guyaanse dollar": [ + "GYD" + ], + "won": [ + "KRW" + ], + "barbadosi dolla\u0301r": [ + "BBD" + ], + "bosnische inwisselbare mark": [ + "BAM" + ], + "\u20b8": [ + "KZT" + ], + "dollar neo zelandais": [ + "NZD" + ], + "leone sierraleonese": [ + "SLL" + ], + "franco comorano": [ + "KMF" + ], + "guineese frank": [ + "GNF" + ], + "renminbi": [ + "CNY" + ], + "alba\u0301n lek": [ + "ALL" + ], + "ethiopische birr": [ + "ETB" + ], + "sterlina di sant\u2019elena": [ + "SHP" + ], + "corona islandesa": [ + "ISK" + ], + "corona islandese": [ + "ISK" + ], + "dolar bermudeno": [ + "BMD" + ], + "surinamese dollar": [ + "SRD" + ], + "nicaraguaanse cordoba": [ + "NIO" + ], + "loti lesothiano": [ + "LSL" + ], + "australischer dollar": [ + "AUD" + ], + "canadian dollar": [ + "CAD" + ], + "yen giapponese": [ + "JPY" + ], + "mongolian to\u0308gro\u0308g": [ + "MNT" + ], + "chelin ugandes": [ + "UGX" + ], + "chinese yuan": [ + "CNY" + ], + "shilling somalien": [ + "SOS" + ], + "hongkongse dollar": [ + "HKD" + ], + "bolivar": [ + "VEF" + ], + "riyal yemenita": [ + "YER" + ], + "florin des antilles ne\u0301erlandaises": [ + "ANG" + ], + "\u20b9": [ + "INR" + ], + "xaf": [ + "XAF" + ], + "philippine peso": [ + "PHP" + ], + "afghan afghani": [ + "AFN" + ], + "dominikai peso": [ + "DOP" + ], + "zuid koreaanse won": [ + "KRW" + ], + "cubaanse peso": [ + "CUP" + ], + "nepalese rupee": [ + "NPR" + ], + "kyat birmano": [ + "MMK" + ], + "franc or": [ + "XFO" + ], + "fiorino surinamese": [ + "SRG" + ], + "czech koruna": [ + "CZK" + ], + "verenigde arabische emiraten dirham": [ + "AED" + ], + "tanzaniaanse shilling": [ + "TZS" + ], + "rupia mauriziana": [ + "MUR" + ], + "monnaie canadienne": [ + "CAD" + ], + "do\u0301lar bruneano": [ + "BND" + ], + "koruna c\u030cesko slovenska\u0301": [ + "CSK" + ], + "pound": [ + "GBP" + ], + "pounds sterling": [ + "GBP" + ], + "jpy": [ + "JPY" + ], + "bs$": [ + "BSD" + ], + "pula botswanais": [ + "BWP" + ], + "haitiaanse gourde": [ + "HTG" + ], + "dinar de bahrein": [ + "BHD" + ], + "dollar jamaicain": [ + "JMD" + ], + "peso ley": [ + "ARS" + ], + "do\u0301lares neozelandeses": [ + "NZD" + ], + "ten\u030cn\u030ce": [ + "TMT" + ], + "pondteken": [ + "GBP" + ], + "\u5143": [ + "CNY" + ], + "franc uic": [ + "XFU" + ], + "syp": [ + "SYP" + ], + "dzsibuti frank": [ + "DJF" + ], + "dollar de la jamai\u0308que": [ + "JMD" + ], + "dinaro tunisino": [ + "TND" + ], + "yuan": [ + "CNY" + ], + "sudanesisches pfund": [ + "SDG" + ], + "euro": [ + "EUR" + ], + "peruanischer nuevo sol": [ + "PEN" + ], + "falkland pound": [ + "FKP" + ], + "forint hungaro": [ + "HUF" + ], + "couronne suedoise": [ + "SEK" + ], + "peso uruguayen": [ + "UYU" + ], + "nami\u0301biai dolla\u0301r": [ + "NAD" + ], + "do\u0301lar bahamen\u0303o": [ + "BSD" + ], + "leone": [ + "SLL" + ], + "libanon pfund": [ + "LBP" + ], + "riyal saudi": [ + "SAR" + ], + "mozambican metical": [ + "MZN" + ], + "dollaro liberiano": [ + "LRD" + ], + "dolar de guyana": [ + "GYD" + ], + "brazilian real": [ + "BRL" + ], + "do\u0301lar de las islas caiman": [ + "KYD" + ], + "$": [ + "USD", + "MXN", + "ARS", + "CAD" + ], + "cup": [ + "CUP" + ], + "real brasilen\u0303o": [ + "BRL" + ], + "peso mexicain": [ + "MXN" + ], + "cuc": [ + "CUC" + ], + "\u0433\u0440\u043d": [ + "UAH" + ], + "monnaie franc\u0327aise": [ + "FRF" + ], + "guarani\u0301 de paraguay": [ + "PYG" + ], + "pa\u02bbanga": [ + "TOP" + ], + "marco": [ + "DDM" + ], + "panamese balboa": [ + "PAB" + ], + "dolar caimano": [ + "KYD" + ], + "feninga": [ + "BAM" + ], + "kazah tenge": [ + "KZT" + ], + "na\u0192": [ + "ANG" + ], + "belgian congolese franc": [ + "CDF" + ], + "jamaika dollar": [ + "JMD" + ], + "to\u0308ro\u0308k u\u0301j li\u0301ra": [ + "TRY" + ], + "nige\u0301riai naira": [ + "NGN" + ], + "oude metical": [ + "MZN" + ], + "singapur dollar": [ + "SGD" + ], + "b$": [ + "BSD" + ], + "metical del mozambico": [ + "MZN" + ], + "ariary malgascio": [ + "MGA" + ], + "bolivar venezuelano": [ + "VEF" + ], + "corona norvegese": [ + "NOK" + ], + "s/.": [ + "PEN" + ], + "franco del burundi": [ + "BIF" + ], + "yemeni rial": [ + "YER" + ], + "dirham de emiratos arabes unidos": [ + "AED" + ], + "riel": [ + "KHR" + ], + "venezolanischer boli\u0301var": [ + "VEF" + ], + "de\u0301l szuda\u0301ni font": [ + "SSP" + ], + "\u20a4": [ + "ITL" + ], + "dolar de brunei": [ + "BND" + ], + "colo\u0301n costaricano": [ + "CRC" + ], + "dinaro kuwaitiano": [ + "KWD" + ], + "re\u0301aux bre\u0301siliens": [ + "BRL" + ], + "pen": [ + "PEN" + ], + "indiase roepie": [ + "INR" + ], + "rupia delle seychelles": [ + "SCR" + ], + "lari": [ + "GEL" + ], + "dollaro di barbados": [ + "BBD" + ], + "xang": [ + "THB" + ], + "taiwanese dollar": [ + "TWD" + ], + "paraguayi guarani\u0301": [ + "PYG" + ], + "cambodian riel": [ + "KHR" + ], + "rub": [ + "RUB" + ], + "dinaro algerino": [ + "DZD" + ], + "bs": [ + "BSD", + "BOB" + ], + "syrisches pfund": [ + "SYP" + ], + "rial iranien": [ + "IRR" + ], + "dollar namibien": [ + "NAD" + ], + "couronne tche\u0301coslovaque": [ + "CSK" + ], + "couronne tchecoslovaque": [ + "CSK" + ], + "peruvian nuevo sol": [ + "PEN" + ], + "lat leton": [ + "LVL" + ], + "costa ricaanse colon": [ + "CRC" + ], + "schweizer franken": [ + "CHF" + ], + "dollar tai\u0308wanais": [ + "TWD" + ], + "japanese yen": [ + "JPY" + ], + "malediven rupie": [ + "MVR" + ], + "arubaanse florijn": [ + "AWG" + ], + "grivna": [ + "UAH" + ], + "ostkaribischer dollar": [ + "XCD" + ], + "mkd": [ + "MKD" + ], + "\u00a5": [ + "JPY" + ], + "ci$": [ + "KYD" + ], + "yuans": [ + "CNY" + ], + "xpf": [ + "XPF" + ], + "lao kip": [ + "LAK" + ], + "franco congoleno": [ + "CDF" + ], + "marco bosnioherzegovino": [ + "BAM" + ], + "sdr": [ + "XDR" + ], + "dollaro del belize": [ + "BZD" + ], + "peso argentino": [ + "ARP" + ], + "dinaro iracheno": [ + "IQD" + ], + "hongkong dollar": [ + "HKD" + ], + "guarani\u0301 paraguaiano": [ + "PYG" + ], + "flori\u0301n antillano neerlande\u0301s": [ + "ANG" + ], + "dirham marocain": [ + "MAD" + ], + "rial irani": [ + "IRR" + ], + "peso d'uruguay": [ + "UYU" + ], + "forinto hu\u0301ngaro": [ + "HUF" + ], + "escudo cap verdien": [ + "CVE" + ], + "mongol tugrik": [ + "MNT" + ], + "gha\u0301nai cedi": [ + "GHS" + ], + "do\u0301lar del caribe oriental": [ + "XCD" + ], + "riyal saudita": [ + "SAR" + ], + "omani rial": [ + "OMR" + ], + "dinar tunisien": [ + "TND" + ], + "cape verdean escudo": [ + "CVE" + ], + "peso do\u0301lar": [ + "ARS" + ], + "dolar namibio": [ + "NAD" + ], + "lyd": [ + "LYD" + ], + "sint heleens pond": [ + "SHP" + ], + "nieuwe israe\u0308lische sheqel": [ + "ILS" + ], + "laotiaanse kip": [ + "LAK" + ], + "bolivian boliviano": [ + "BOB" + ], + "kirgizische som": [ + "KGS" + ], + "denaro macedone": [ + "MKD" + ], + "swiss franco": [ + "CHF" + ], + "birr eti\u0301ope": [ + "ETB" + ], + "barbadian dollar": [ + "BBD" + ], + "dolar canadiense": [ + "CAD" + ], + "swiss francs": [ + "CHF" + ], + "tonga pa`anga": [ + "TOP" + ], + "dinar de bahrei\u0308n": [ + "BHD" + ], + "dollar des iles salomon": [ + "SBD" + ], + "dobra santotomense": [ + "STD" + ], + "leu rumano": [ + "RON" + ], + "lisente": [ + "LSL" + ], + "manat turcomano": [ + "TMT" + ], + "taka bangladeshi": [ + "BDT" + ], + "dram": [ + "AMD" + ], + "macedonische denar": [ + "MKD" + ], + "israelische sjekel": [ + "ILS" + ], + "dop": [ + "DOP" + ], + "vanuatu vatu": [ + "VUV" + ], + "dollar des i\u0302les salomon": [ + "SBD" + ], + "franzo\u0308sischer franken": [ + "FRF" + ], + "guarani": [ + "PYG" + ], + "su\u0308dsudan pfund": [ + "SSP" + ], + "roemeense leu": [ + "RON" + ], + "mark convertible": [ + "BAM" + ], + "franco de djibouti": [ + "DJF" + ], + "ugandan shilling": [ + "UGX" + ], + "pazifik franc": [ + "XPF" + ], + "rublo tayiko": [ + "TJR" + ], + "argentinischer peso": [ + "ARS" + ], + "bahraini dinar": [ + "BHD" + ], + "amerikaanse dollar": [ + "USD" + ], + "franc comorien": [ + "KMF" + ], + "dolar neocelande\u0301s": [ + "NZD" + ], + "libra sudanesa": [ + "SDG" + ], + "ugandai shilling": [ + "UGX" + ], + "peso argentin": [ + "ARS" + ], + "tugrik mongol": [ + "MNT" + ], + "fiorino delle antille olandesi": [ + "ANG" + ], + "hryvnia": [ + "UAH" + ], + "ma\u0308tonya": [ + "ETB" + ], + "dalasi": [ + "GMD" + ], + "couronne tche\u0300que": [ + "CZK" + ], + "lkr": [ + "LKR" + ], + "clps": [ + "CLP" + ], + "dolar surinames": [ + "SRD" + ], + "kuwait dinar": [ + "KWD" + ], + "ruma\u0308nischer leu": [ + "RON" + ], + "do\u0301lar jamaicano": [ + "JMD" + ], + "nuevo dolar taiwane\u0301s": [ + "TWD" + ], + "venezolanischer bolivar": [ + "VEF" + ], + "qatarese rial": [ + "QAR" + ], + "do\u0301lar de surinam": [ + "SRD" + ], + "livres sterling": [ + "GBP" + ], + "g$": [ + "GYD" + ], + "ruma\u0308nischer lei": [ + "RON" + ], + "leone della sierra leone": [ + "SLL" + ], + "manat azero": [ + "AZN" + ], + "rwandese frank": [ + "RWF" + ], + "ancien franc": [ + "FRF" + ], + "naira": [ + "NGN" + ], + "koruna ceskoslovenska": [ + "CSK" + ], + "colo\u0301n costarricense": [ + "CRC" + ], + "kubai peso": [ + "CUP" + ], + "riel camboyano": [ + "KHR" + ], + "pa'anga tongano": [ + "TOP" + ], + "sri lankan rupee": [ + "LKR" + ], + "hk$": [ + "HKD" + ], + "dollar libe\u0301rien": [ + "LRD" + ], + "pa'anga di tonga": [ + "TOP" + ], + "norwegian krone": [ + "NOK" + ], + "scudo capoverdiano": [ + "CVE" + ], + "franco congolese": [ + "CDF" + ], + "birr": [ + "ETB" + ], + "schwedische krone": [ + "SEK" + ], + "boliviano bolivien": [ + "BOB" + ], + "bdt": [ + "BTN" + ], + "do\u0301lar guyanes": [ + "GYD" + ], + "lilangeni dello swaziland": [ + "SZL" + ], + "libanesisches pfund": [ + "LBP" + ], + "schottische pfund": [ + "GBP" + ], + "griekse drachme": [ + "GRD" + ], + "moldovan leu": [ + "MDL" + ], + "lek": [ + "ALL" + ], + "\u00a3": [ + "GBP" + ], + "do\u0301lar australiano": [ + "AUD" + ], + "lev": [ + "BGN" + ], + "lew": [ + "BGN" + ], + "uganda shilling": [ + "UGX" + ], + "hkd": [ + "HKD" + ], + "bd$": [ + "BMD" + ], + "re\u0301al bre\u0301silien": [ + "BRL" + ], + "tunesischer dinar": [ + "TND" + ], + "austral (monnaie)": [ + "ARA" + ], + "tongaanse pa'anga": [ + "TOP" + ], + "couronne sue\u0301doise": [ + "SEK" + ], + "franc de djibouti": [ + "DJF" + ], + "madagaszka\u0301ri ariary": [ + "MGA" + ], + "rupia mauricia": [ + "MUR" + ], + "solomon dollar": [ + "SBD" + ], + "kro\u0301nur": [ + "ISK" + ], + "khoums": [ + "MRO" + ], + "su\u0308dsudan pound": [ + "SSP" + ], + "sgd": [ + "SGD" + ], + "russischer rubel": [ + "RUB" + ], + "usd": [ + "USD" + ], + "livre des i\u0302les falkland": [ + "FKP" + ], + "comorian franc": [ + "KMF" + ], + "chf": [ + "CHF" + ], + "ush": [ + "UGX" + ], + "costa rica colon": [ + "CRC" + ], + "rial yemenita": [ + "YER" + ], + "marco bosniaco": [ + "BAM" + ], + "rial yemenite": [ + "YER" + ], + "brit font": [ + "GBP" + ], + "tercera dracma griega": [ + "GRD" + ], + "tala samoano": [ + "WST" + ], + "manat azeri": [ + "AZN" + ], + "santi\u0304ms": [ + "LVL" + ], + "ostmark": [ + "DDM" + ], + "f": [ + "ANG" + ], + "nuova lira turca": [ + "TRY" + ], + "zuid soedanees pond": [ + "SSP" + ], + "turkish lira": [ + "TRY" + ], + "rupia indonesiana": [ + "IDR" + ], + "da\u0308nische krone": [ + "DKK" + ], + "diritti speciali di prelievo": [ + "XDR" + ], + "do\u0301lar de nueva zelanda": [ + "NZD" + ], + "aluchip": [ + "DDM" + ], + "peso uruguayo": [ + "UYU" + ], + "xcd": [ + "XCD" + ], + "nuevo do\u0301lar de taiwan": [ + "TWD" + ], + "k.s.": [ + "KGS" + ], + "dinars alge\u0301rien": [ + "DZD" + ], + "russische roebel": [ + "RUB" + ], + "afn": [ + "AFN" + ], + "\u20a6": [ + "NGN" + ], + "corona danese": [ + "DKK" + ], + "corona danesa": [ + "DKK" + ], + "moneda canadiense": [ + "CAD" + ], + "ruandai frank": [ + "RWF" + ], + "libra de santa helena": [ + "SHP" + ], + "manat azeri\u0301": [ + "AZN" + ], + "do\u0301lar de hong kong": [ + "HKD" + ], + "armenian dram": [ + "AMD" + ], + "tetradrachme": [ + "GRD" + ], + "chileense peso": [ + "CLP" + ], + "franchi svizzeri": [ + "CHF" + ], + "boliviaanse boliviano": [ + "BOB" + ], + "do\u0301lar de bermudas": [ + "BMD" + ], + "colon costaricain": [ + "CRC" + ], + "dollar bahame\u0301en": [ + "BSD" + ], + "dollaro delle cayman": [ + "KYD" + ], + "do\u0301lar neozelande\u0301s": [ + "NZD" + ], + "riyal saudi\u0301": [ + "SAR" + ], + "georgian lari": [ + "GEL" + ], + "kiwi dollar": [ + "NZD" + ], + "shekkel": [ + "ILS" + ], + "si$": [ + "SBD" + ], + "dobra santome\u0301en": [ + "STD" + ], + "dolar neoze\u0301landes": [ + "NZD" + ], + "fiorino di aruba": [ + "AWG" + ], + "dobra": [ + "STD" + ], + "british pound": [ + "GBP" + ], + "to\u0308mling": [ + "THB" + ], + "afg": [ + "AFN" + ], + "thai ba\u0301t": [ + "THB" + ], + "fu\u0308lo\u0308p szigeteki peso": [ + "PHP" + ], + "noorse kroon": [ + "NOK" + ], + "dollar de trinite\u0301 et tobago": [ + "TTD" + ], + "tsh": [ + "TZS" + ], + "lm": [ + "MTL" + ], + "saudi arabische riyal": [ + "SAR" + ], + "ausztra\u0301l dolla\u0301r": [ + "AUD" + ], + "oekraiense hryvnja": [ + "UAH" + ], + "deense kroon": [ + "DKK" + ], + "eur": [ + "EUR" + ], + "uruguayi peso": [ + "UYU" + ], + "liberian dollar": [ + "LRD" + ], + "livre sud soudanaise": [ + "SSP" + ], + "do\u0301lar de fiji": [ + "FJD" + ], + "dollar de la carai\u0308be orientale": [ + "XCD" + ], + "franc poincare\u0301": [ + "XFO" + ], + "gepik": [ + "AZN" + ], + "fl\u00a3": [ + "FKP" + ], + "mexican peso": [ + "MXN" + ], + "diram": [ + "TJS" + ], + "denar mace\u0301donien": [ + "MKD" + ], + "hongkongi dolla\u0301r": [ + "HKD" + ], + "belizaanse dollar": [ + "BZD" + ], + "azeri manat": [ + "AZN" + ], + "dong vietnamita": [ + "VND" + ], + "rublo russo": [ + "RUB" + ], + "dolar beliceno": [ + "BZD" + ], + "su\u0308dsudanesisches pfund": [ + "SSP" + ], + "dolar de las islas caima\u0301n": [ + "KYD" + ], + "ec$": [ + "XCD" + ], + "dirham degli emirati arabi uniti": [ + "AED" + ], + "surinaamse dollar": [ + "SRD" + ], + "franco cfa de africa occidental": [ + "XOF" + ], + "french franc": [ + "FRF" + ], + "\u0192": [ + "ANG" + ], + "roma\u0301n lej": [ + "RON" + ], + "pa'anga": [ + "TOP" + ], + "dollaro dei caraibi orientali": [ + "XCD" + ], + "tyiyn": [ + "KGS" + ], + "cuban convertible peso": [ + "CUC" + ], + "dirham des e\u0301mirats arabes unis": [ + "AED" + ], + "japa\u0301n jen": [ + "JPY" + ], + "kroatische kuna": [ + "HRK" + ], + "sowjetischer rubel": [ + "SUR" + ], + "won sudcoreano": [ + "KRW" + ], + "chelin somali\u0301": [ + "SOS" + ], + "santims": [ + "LVL" + ], + "franc": [ + "CHF", + "FRF" + ], + "halalas": [ + "SAR" + ], + "sva\u0301jci frank": [ + "CHF" + ], + "shekel": [ + "ILS" + ], + "dinar kowei\u0308tien": [ + "KWD" + ], + "l\u00a3": [ + "LBP" + ], + "moroccan dirham": [ + "MAD" + ], + "goldfranc": [ + "XFO" + ], + "jod": [ + "JOD" + ], + "oost carai\u0308bische dollar": [ + "XCD" + ], + "ouguiya mauritana": [ + "MRO" + ], + "cambodjaanse riel": [ + "KHR" + ], + "taka bangladesi\u0301": [ + "BDT" + ], + "ltl": [ + "LTL" + ], + "lettischer lat": [ + "LVL" + ], + "santi\u0304mu": [ + "LVL" + ], + "marco de la repu\u0301blica democra\u0301tica alemana": [ + "DDM" + ], + "franco di gibuti": [ + "DJF" + ], + "santi\u0304mi": [ + "LVL" + ], + "couronne norve\u0301gienne": [ + "NOK" + ], + "libanoni font": [ + "LBP" + ], + "belize i dolla\u0301r": [ + "BZD" + ], + "da\u0301n korona": [ + "DKK" + ], + "serbian dinar": [ + "RSD" + ], + "rial omani": [ + "OMR" + ], + "mark convertible bosniaque": [ + "BAM" + ], + "dollar du be\u0301lize": [ + "BZD" + ], + "pesos argentinos": [ + "ARS" + ], + "lesothaanse loti": [ + "LSL" + ], + "tu\u0308rk liras\u0131": [ + "TRY" + ], + "kwacha zambien": [ + "ZMW" + ], + "dollar trinidadien": [ + "TTD" + ], + "moldavische leu": [ + "MDL" + ], + "tughrik": [ + "MNT" + ], + "leu roumain": [ + "RON" + ], + "szva\u0301zifo\u0308ldi lilangeni": [ + "SZL" + ], + "morocota": [ + "VEF" + ], + "haitianische gourde": [ + "HTG" + ], + "eritreischer nakfa": [ + "ERN" + ], + "mongolischer to\u0308gro\u0308g": [ + "MNT" + ], + "escudo di capo verde": [ + "CVE" + ], + "zwitserse frank": [ + "CHF" + ], + "afga\u0301n afga\u0301ni": [ + "AFN" + ], + "neet": [ + "GBP" + ], + "zwitserse franc": [ + "CHF" + ], + "roupie mauricienne": [ + "MUR" + ], + "do\u0301lar trinitense": [ + "TTD" + ], + "marco de la republica democratica alemana": [ + "DDM" + ], + "tongai pa\u2019anga": [ + "TOP" + ], + "israeli new sheqel": [ + "ILS" + ], + "bermudai dolla\u0301r": [ + "BMD" + ], + "\u20ba": [ + "TRY" + ], + "oost caribische dollar": [ + "XCD" + ], + "ugandese shilling": [ + "UGX" + ], + "derechos especiales de giro": [ + "XDR" + ], + "rupaya": [ + "INR" + ], + "suriname gulden": [ + "SRD" + ], + "tajvani u\u0301j dolla\u0301r": [ + "TWD" + ], + "costa rica i colo\u0301n": [ + "CRC" + ], + "pakistanische rupie": [ + "PKR" + ], + "irak dinar": [ + "IQD" + ], + "alge\u0301riai dina\u0301r": [ + "DZD" + ], + "perui u\u0301j sol": [ + "PEN" + ], + "do\u0301lar caribe este": [ + "XCD" + ], + "kurus": [ + "TRY" + ], + "sfr": [ + "CHF" + ], + "huard canadien": [ + "CAD" + ], + "new zealand dollar": [ + "NZD" + ], + "so\u0308m": [ + "UZS" + ], + "awg": [ + "AWG" + ], + "dollar de guyana": [ + "GYD" + ], + "bosnya\u0301k konvertibilis ma\u0301rka": [ + "BAM" + ], + "suriname i dolla\u0301r": [ + "SRD" + ], + "ukrainische hrywnja": [ + "UAH" + ], + "ngultrum": [ + "BTN" + ], + "gde.": [ + "HTG" + ], + "mexican nuevo peso": [ + "MXN" + ], + "fjd": [ + "FJD" + ], + "dolar jamaiquino": [ + "JMD" + ], + "libyscher dinar": [ + "LYD" + ], + "nuevo shequel": [ + "ILS" + ], + "cheli\u0301n keniano": [ + "KES" + ], + "dollar surinamien": [ + "SRD" + ], + "rublo sovietico": [ + "SUR" + ], + "kaiman dollar": [ + "KYD" + ], + "dollar ne\u0301o ze\u0301landais": [ + "NZD" + ], + "bolga\u0301r leva": [ + "BGN" + ], + "cub$": [ + "CUP" + ], + "szl": [ + "SZL" + ], + "aruba gulden": [ + "AWG" + ], + "mexikanischer peso": [ + "MXN" + ], + "australische dollar": [ + "AUD" + ], + "roupie indonesienne": [ + "IDR" + ], + "albanese lek": [ + "ALL" + ], + "lettische wa\u0308hrung": [ + "LVL" + ], + "dollar ame\u0301ricain": [ + "USD" + ], + "zo\u0308ld foki szigeteki escudo": [ + "CVE" + ], + "saudi riyal": [ + "SAR" + ], + "libra": [ + "GBP" + ], + "isla\u0308ndische krone": [ + "ISK" + ], + "saudi rial": [ + "SAR" + ], + "dollaro della bermuda": [ + "BMD" + ], + "macedo\u0301n de\u0301na\u0301r": [ + "MKD" + ], + "kwanza": [ + "AOA" + ], + "dollar du guyana": [ + "GYD" + ], + "nuevo peso argentino": [ + "ARS" + ], + "dollaro del suriname": [ + "SRD" + ], + "ariary malgache": [ + "MGA" + ], + "saint helena pound": [ + "SHP" + ], + "kambodzsai riel": [ + "KHR" + ], + "surinam dollar": [ + "SRD" + ], + "ouguiya": [ + "MRO" + ], + "mala\u0301j ringgit": [ + "MYR" + ], + "united states dollar": [ + "USD" + ], + "icelandic kro\u0301na": [ + "ISK" + ], + "gbp": [ + "GBP" + ], + "falkland szigeteki font": [ + "FKP" + ], + "sa\u0303o tome\u0301ischer dobra": [ + "STD" + ], + "kwanza angolano": [ + "AOA" + ], + "scellino": [ + "KES" + ], + "dollars canadiens": [ + "CAD" + ], + "guarani\u0301": [ + "PYG" + ], + "kwanza angolana": [ + "AOA" + ], + "litas lituanien": [ + "LTL" + ], + "kajma\u0301n szigeteki dolla\u0301r": [ + "KYD" + ], + "som de kirguista\u0301n": [ + "KGS" + ], + "btn": [ + "BTN" + ], + "chelin somali": [ + "SOS" + ], + "dracma griego moderno": [ + "GRD" + ], + "hai\u0308tiaanse gourde": [ + "HTG" + ], + "kc\u030c": [ + "CZK" + ], + "peso de chile": [ + "CLP" + ], + "mazedonischer denar": [ + "MKD" + ], + "sierra leoonse leone": [ + "SLL" + ], + "franco france\u0301s": [ + "FRF" + ], + "marco della germania est": [ + "DDM" + ], + "cordoba nicaraguense": [ + "NIO" + ], + "do\u0301lar jamaiquino": [ + "JMD" + ], + "cordoba nicaraguayen": [ + "NIO" + ], + "rupia de pakista\u0301n": [ + "PKR" + ], + "pfund sterling": [ + "GBP" + ], + "dollar jamai\u0308quain": [ + "JMD" + ], + "koruna c\u030ceskoslovenska\u0301": [ + "CSK" + ], + "vatu di vanuatu": [ + "VUV" + ], + "nicaraguai co\u0301rdoba": [ + "NIO" + ], + "salu\u0308ng": [ + "THB" + ], + "drachmon": [ + "GRD" + ], + "somalia schilling": [ + "SOS" + ], + "dinar iraqui": [ + "IQD" + ], + "escudo": [ + "CVE" + ], + "hrywni": [ + "UAH" + ], + "libra de santa elena": [ + "SHP" + ], + "couronnes tche\u0300ques": [ + "CZK" + ], + "dolar fiyiano": [ + "FJD" + ], + "\u20a9": [ + "KRW" + ], + "rial iraniano": [ + "IRR" + ], + "bbd": [ + "BBD" + ], + "e\u0301szak i\u0301r font": [ + "GBP" + ], + "$ ca": [ + "CAD" + ], + "quid": [ + "GBP" + ], + "ta\u0301dzsik szomoni": [ + "TJS" + ], + "dram armenio": [ + "AMD" + ], + "rupia singalese": [ + "LKR" + ], + "botswaanse pula": [ + "BWP" + ], + "co\u0301rdoba nicaraguayen": [ + "NIO" + ], + "c$": [ + "NIO", + "CAD" + ], + "oost caraibische dollar": [ + "XCD" + ], + "guyanese dollar": [ + "GYD" + ], + "indonesische roepia": [ + "IDR" + ], + "corone ceche": [ + "CZK" + ], + "franco cfa de a\u0301frica occidental": [ + "XOF" + ], + "currency of mexico": [ + "MXN" + ], + "kwanza reajustado": [ + "AOA" + ], + "botswanai pula": [ + "BWP" + ], + "reais": [ + "BRL" + ], + "cve": [ + "CVE" + ], + "flori\u0301n suriname\u0301s": [ + "SRG" + ], + "franc djibouti": [ + "DJF" + ], + "do\u0301lar beliceno": [ + "BZD" + ], + "forint hu\u0301ngaro": [ + "HUF" + ], + "iranischer rial": [ + "IRR" + ], + "tenge": [ + "KZT" + ], + "czechoslovak koruna": [ + "CSK" + ], + "grivna ucraniana": [ + "UAH" + ], + "dinar alge\u0301rien": [ + "DZD" + ], + "rupia esrilanquesa": [ + "LKR" + ], + "kyrgyz som": [ + "KGS" + ], + "turkmeense manat": [ + "TMT" + ], + "hryvnia ukrainienne": [ + "UAH" + ], + "dollaro di singapore": [ + "SGD" + ], + "dolar de belize": [ + "BZD" + ], + "boli\u0301vares": [ + "VEF" + ], + "sterlina di gibilterra": [ + "GIP" + ], + "shilling ougandais": [ + "UGX" + ], + "rupia pakistani\u0301": [ + "PKR" + ], + "united arab emirates dirham": [ + "AED" + ], + "php": [ + "PHP" + ], + "\u03b4\u03c1": [ + "GRD" + ], + "lari georgiano": [ + "GEL" + ], + "kip laotien": [ + "LAK" + ], + "uquiya": [ + "MRO" + ], + "francs or": [ + "XFO" + ], + "dinar": [ + "TND", + "DZD" + ], + "shilling tanzanien": [ + "TZS" + ], + "kongo\u0301i frank": [ + "CDF" + ], + "franco de yibuti": [ + "DJF" + ], + "dirham marroqui\u0301": [ + "MAD" + ], + "florin hungaro": [ + "HUF" + ], + "tyjyn": [ + "KGS" + ], + "di\u0301rham de los emiratos a\u0301rabes unidos": [ + "AED" + ], + "florin arubais": [ + "AWG" + ], + "la couronne danoise": [ + "DKK" + ], + "gambian dalasi": [ + "GMD" + ], + "szuda\u0301ni font": [ + "SDG" + ], + "corona svedese": [ + "SEK" + ], + "colombiaanse peso": [ + "COP" + ], + "dirham marocchino": [ + "MAD" + ], + "won sud core\u0301en": [ + "KRW" + ], + "seychellois rupee": [ + "SCR" + ], + "gibraltarees pond": [ + "GIP" + ], + "franc fort": [ + "FRF" + ], + "schweizerfranken": [ + "CHF" + ], + "livre soudanaise": [ + "SDG" + ], + "manat aze\u0301ri": [ + "AZN" + ], + "nuevo she\u0301kel": [ + "ILS" + ], + "paraguayaanse guarani": [ + "PYG" + ], + "trinidad and tobago dollar": [ + "TTD" + ], + "tiyin": [ + "UZS" + ], + "dollar de belize": [ + "BZD" + ], + "nuovo siclo": [ + "ILS" + ], + "pyas": [ + "MMK" + ], + "liberiaanse dollar": [ + "LRD" + ], + "quetzal guatemalteco": [ + "GTQ" + ], + "naira nige\u0301rian": [ + "NGN" + ], + "balboa panameno": [ + "PAB" + ], + "indian rupee": [ + "INR" + ], + "bahreini dina\u0301r": [ + "BHD" + ], + "zuid afrikaanse rand": [ + "ZAR" + ], + "roepia": [ + "IDR" + ], + "dollar bermudien": [ + "BMD" + ], + "loti del lesotho": [ + "LSL" + ], + "hondurese lempira": [ + "HNL" + ], + "tsjecho slowaakse kroon": [ + "CSK" + ], + "do\u0301lar de barbados": [ + "BBD" + ], + "su\u0308dafrikanischer rand": [ + "ZAR" + ], + "szau\u0301di ria\u0301l": [ + "SAR" + ], + "szerb dina\u0301r": [ + "RSD" + ], + "roupie du ne\u0301pal": [ + "NPR" + ], + "dinaro": [ + "BHD" + ], + "balboa": [ + "PAB" + ], + "rublo sovie\u0301tico": [ + "SUR" + ], + "dollar de la caraibe orientale": [ + "XCD" + ], + "dolar bruneano": [ + "BND" + ], + "dollaro canadese": [ + "CAD" + ], + "arubai florin": [ + "AWG" + ], + "somali shilling": [ + "SOS" + ], + "peso oro dominicano": [ + "DOP" + ], + "bangladesi taka": [ + "BDT" + ], + "lettischer lats": [ + "LVL" + ], + "marco della repubblica democratica tedesca": [ + "DDM" + ], + "ijslandse kroon": [ + "ISK" + ], + "burundi franc": [ + "BIF" + ], + "rand sud africain": [ + "ZAR" + ], + "corone norvegesi": [ + "NOK" + ], + "do\u0301lar caimano": [ + "KYD" + ], + "burundi frank": [ + "BIF" + ], + "new israeli sheqel": [ + "ILS" + ], + "metical mozambicain": [ + "MZN" + ], + "dolar de surinam": [ + "SRD" + ], + "falkland islands pound": [ + "FKP" + ], + "maurita\u0301niai ouguiya": [ + "MRO" + ], + "u\u0301j ze\u0301landi dolla\u0301r": [ + "NZD" + ], + "lats leton": [ + "LVL" + ], + "somoni tagico": [ + "TJS" + ], + "mozambikaanse metical": [ + "MZN" + ], + "dollaro delle bermuda": [ + "BMD" + ], + "dolar de hong kong": [ + "HKD" + ], + "dollaro delle bermude": [ + "BMD" + ], + "balboa panamense": [ + "PAB" + ], + "roupie srilankaise": [ + "LKR" + ], + "fya\u0308n": [ + "THB" + ], + "dolar guyanes": [ + "GYD" + ], + "franc suisse": [ + "CHF" + ], + "rial irani\u0301": [ + "IRR" + ], + "myanmarese kyat": [ + "MMK" + ], + "costa ricaanse colo\u0301n": [ + "CRC" + ], + "corona checa": [ + "CZK" + ], + "thai baht": [ + "THB" + ], + "djiboutiaanse frank": [ + "DJF" + ], + "schkalim": [ + "ILS" + ], + "\u17db": [ + "KHR" + ], + "franc djiboutien": [ + "DJF" + ], + "dinar koweitien": [ + "KWD" + ], + "loonie": [ + "CAD" + ], + "denari": [ + "MKD" + ], + "lvl": [ + "LVL" + ], + "hryvnja": [ + "UAH" + ], + "lempira hondurien": [ + "HNL" + ], + "franc guineen": [ + "GNF" + ], + "seychelles rupee": [ + "SCR" + ], + "leu rumeno": [ + "RON" + ], + "dirham emirati": [ + "AED" + ], + "co\u0301rdoba nicarague\u0301en": [ + "NIO" + ], + "neuseeland dollar": [ + "NZD" + ], + "\u20aa": [ + "ILS" + ], + "bahamai dolla\u0301r": [ + "BSD" + ], + "szi\u0301r font": [ + "SYP" + ], + "nieuwe israelische sjekel": [ + "ILS" + ], + "franc francais": [ + "FRF" + ], + "jamaicaanse dollar": [ + "JMD" + ], + "burmese kyat": [ + "MMK" + ], + "do\u0301lar de belize": [ + "BZD" + ], + "tunis dinar": [ + "TND" + ], + "hrywnja": [ + "UAH" + ], + "do\u0301lar de belice": [ + "BZD" + ], + "koeweitse dinar": [ + "KWD" + ], + "rial yemeni": [ + "YER" + ], + "quetzal": [ + "GTQ" + ], + "livres sterlings": [ + "GBP" + ], + "hnl": [ + "HNL" + ], + "franco cfa de a\u0301frica central": [ + "XAF" + ], + "scellino keniota": [ + "KES" + ] + }, + "iso4217": { + "DZD": { + "fr": "Dinar alg\u00e9rien", + "en": "Algerian dinar", + "nl": "Algerijnse dinar", + "de": "Algerischer Dinar", + "it": "Dinaro algerino", + "hu": "alg\u00e9riai din\u00e1r", + "es": "Dinar argelino" + }, + "NAD": { + "fr": "Dollar namibien", + "en": "Namibian dollar", + "nl": "Namibische dollar", + "de": "Namibia-Dollar", + "it": "Dollaro namibiano", + "hu": "Nam\u00edbiai doll\u00e1r", + "es": "D\u00f3lar namibio" + }, + "GHS": { + "fr": "Cedi", + "en": "Ghana cedi", + "nl": "Ghanese cedi", + "de": "Cedi", + "it": "Cedi ghanese", + "hu": "Gh\u00e1nai cedi", + "es": "Cedi" + }, + "BZD": { + "fr": "Dollar b\u00e9lizien", + "en": "Belize dollar", + "nl": "Belizaanse dollar", + "de": "Belize-Dollar", + "it": "Dollaro del Belize", + "hu": "Belize-i doll\u00e1r", + "es": "D\u00f3lar belice\u00f1o" + }, + "BGN": { + "fr": "Lev bulgare", + "en": "Bulgarian lev", + "nl": "Bulgaarse lev", + "de": "Lew", + "it": "Lev bulgaro", + "hu": "bolg\u00e1r leva", + "es": "Lev" + }, + "PAB": { + "fr": "Balboa", + "en": "Panamanian balboa", + "nl": "Panamese balboa", + "de": "Panamaischer Balboa", + "it": "Balboa panamense", + "hu": "Panamai balboa", + "es": "Balboa" + }, + "BOB": { + "fr": "boliviano", + "en": "boliviano", + "nl": "Boliviaanse boliviano", + "de": "Boliviano", + "it": "boliviano", + "hu": "bol\u00edviai boliviano", + "es": "boliviano" + }, + "DKK": { + "fr": "Couronne danoise", + "en": "Danish krone", + "nl": "Deense kroon", + "de": "D\u00e4nische Krone", + "it": "Corona danese", + "hu": "d\u00e1n korona", + "es": "Corona danesa" + }, + "BWP": { + "fr": "Pula", + "en": "Botswana pula", + "nl": "Botswaanse pula", + "de": "Botswanischer Pula", + "it": "Pula del Botswana", + "hu": "Botswanai pula", + "es": "Pula" + }, + "LBP": { + "fr": "livre libanaise", + "en": "Lebanese pound", + "nl": "Libanees pond", + "de": "Libanesisches Pfund", + "it": "Lira libanese", + "hu": "libanoni font", + "es": "Libra libanesa" + }, + "TZS": { + "fr": "shilling tanzanien", + "en": "Tanzanian shilling", + "nl": "Tanzaniaanse shilling", + "de": "Tansania-Schilling", + "it": "Scellino tanzaniano", + "hu": "Tanz\u00e1niai shilling", + "es": "chel\u00edn" + }, + "VND": { + "fr": "Dong", + "en": "Vietnamese dong", + "nl": "Vietnamese dong", + "de": "Vietnamesischer \u0110\u1ed3ng", + "it": "\u0110\u1ed3ng vietnamita", + "hu": "vietnami \u0111\u1ed3ng", + "es": "\u0111\u1ed3ng vietnamita" + }, + "AOA": { + "fr": "Kwanza", + "en": "Angolan kwanza", + "nl": "Angolese kwanza", + "de": "Kwanza", + "it": "Kwanza angolano", + "hu": "angolai kwanza", + "es": "Kwanza angole\u00f1o" + }, + "KHR": { + "fr": "Riel", + "en": "riel", + "nl": "Cambodjaanse riel", + "de": "Kambodschanischer Riel", + "it": "Riel cambogiano", + "hu": "kambodzsai riel", + "es": "Riel camboyano" + }, + "MYR": { + "fr": "Ringgit", + "en": "Malaysian ringgit", + "nl": "Maleisische ringgit", + "de": "Ringgit", + "it": "Ringgit malese", + "hu": "mal\u00e1j ringgit", + "es": "Ringgit" + }, + "KYD": { + "fr": "Dollar des \u00eeles Ca\u00efmans", + "en": "Cayman Islands dollar", + "nl": "Kaaimaneilandse dollar", + "de": "Kaiman-Dollar", + "it": "Dollaro delle Cayman", + "hu": "Kajm\u00e1n-szigeteki doll\u00e1r", + "es": "D\u00f3lar de las Islas Caim\u00e1n" + }, + "LYD": { + "fr": "Dinar libyen", + "en": "Libyan dinar", + "nl": "Libische dinar", + "de": "Libyscher Dinar", + "it": "Dinaro libico", + "hu": "L\u00edbiai din\u00e1r", + "es": "Dinar libio" + }, + "UAH": { + "fr": "Hryvnia", + "en": "hryvnia", + "nl": "Oekra\u00efense hryvnja", + "de": "Hrywnja", + "it": "Grivnia ucraina", + "hu": "ukr\u00e1n hrivnya", + "es": "Grivna" + }, + "JOD": { + "fr": "Dinar jordanien", + "en": "Jordanian dinar", + "nl": "Jordaanse dinar", + "de": "Jordanischer Dinar", + "it": "Dinaro giordano", + "hu": "jord\u00e1n din\u00e1r", + "es": "Dinar jordano" + }, + "SUR": { + "fr": "Rouble sovi\u00e9tique", + "en": "Soviet ruble", + "de": "Sowjetischer Rubel", + "it": "Rublo sovietico", + "hu": "Szovjet rubel", + "es": "Rublo sovi\u00e9tico" + }, + "AWG": { + "fr": "Florin arubais", + "en": "Aruban florin", + "nl": "Arubaanse florin", + "de": "Aruba-Florin", + "it": "Fiorino arubano", + "hu": "Arubai florin", + "es": "Flor\u00edn arube\u00f1o" + }, + "SAR": { + "fr": "Riyal saoudien", + "en": "Saudi riyal", + "nl": "Saoedi-Arabische riyal", + "de": "Saudi-Rial", + "it": "Riyal saudita", + "hu": "sza\u00fadi ri\u00e1l", + "es": "Riyal saud\u00ed" + }, + "EUR": { + "fr": "euro", + "en": "euro", + "nl": "euro", + "de": "Euro", + "it": "euro", + "hu": "eur\u00f3", + "es": "euro" + }, + "HKD": { + "fr": "Dollar de Hong Kong", + "en": "Hong Kong dollar", + "nl": "Hongkongse dollar", + "de": "Hongkong-Dollar", + "it": "dollaro hongkonghese", + "hu": "hongkongi doll\u00e1r", + "es": "D\u00f3lar de Hong Kong" + }, + "SRG": { + "en": "Surinamese guilder", + "nl": "Surinaamse gulden", + "it": "Fiorino surinamese", + "es": "Flor\u00edn surinam\u00e9s" + }, + "CHF": { + "fr": "Franc suisse", + "en": "Swiss franc", + "nl": "Zwitserse frank", + "de": "Schweizer Franken", + "it": "franco svizzero", + "hu": "sv\u00e1jci frank", + "es": "franco suizo" + }, + "GIP": { + "fr": "Livre de Gibraltar", + "en": "Gibraltar pound", + "nl": "Gibraltarees pond", + "de": "Gibraltar-Pfund", + "it": "Sterlina di Gibilterra", + "hu": "Gibralt\u00e1ri font", + "es": "Libra gibraltare\u00f1a" + }, + "ALL": { + "fr": "Lek", + "en": "lek", + "nl": "Albanese lek", + "de": "Albanischer Lek", + "it": "Lek albanese", + "hu": "alb\u00e1n lek", + "es": "Lek alban\u00e9s" + }, + "MRO": { + "fr": "Ouguiya", + "en": "Mauritanian ouguiya", + "nl": "Mauritaanse ouguiya", + "de": "Ouguiya", + "it": "Ouguiya mauritana", + "hu": "Maurit\u00e1niai ouguiya", + "es": "Uquiya" + }, + "HRK": { + "fr": "Kuna croate", + "en": "Croatian kuna", + "nl": "Kroatische kuna", + "de": "Kroatische Kuna", + "it": "Kuna croata", + "hu": "horv\u00e1t kuna", + "es": "Kuna croata" + }, + "DJF": { + "fr": "franc Djibouti", + "en": "Djiboutian franc", + "nl": "Djiboutiaanse frank", + "de": "Dschibuti-Franc", + "it": "Franco gibutiano", + "hu": "Dzsibuti frank", + "es": "franco" + }, + "THB": { + "fr": "Baht", + "en": "Thai baht", + "nl": "Thaise baht", + "de": "Baht", + "it": "Baht thailandese", + "hu": "thai b\u00e1t", + "es": "Baht tailand\u00e9s" + }, + "XAF": { + "fr": "Franc CFA", + "en": "Central African CFA franc", + "de": "CFA-Franc BEAC", + "es": "Franco CFA de \u00c1frica Central" + }, + "BND": { + "fr": "Dollar de Brunei", + "en": "Brunei dollar", + "nl": "Bruneise dollar", + "de": "Brunei-Dollar", + "it": "Dollaro del Brunei", + "hu": "brunei doll\u00e1r", + "es": "D\u00f3lar de Brun\u00e9i" + }, + "VUV": { + "fr": "Vatu", + "en": "Vanuatu vatu", + "nl": "Vanuatuaanse vatu", + "de": "Vatu", + "it": "Vatu di Vanuatu", + "hu": "Vanuatui vatu", + "es": "Vatu" + }, + "UYU": { + "fr": "Peso uruguayen", + "en": "Uruguayan peso", + "nl": "Uruguayaanse peso", + "de": "Uruguayischer Peso", + "it": "Peso uruguaiano", + "hu": "Uruguayi peso", + "es": "peso" + }, + "NIO": { + "fr": "C\u00f3rdoba", + "en": "Nicaraguan c\u00f3rdoba", + "nl": "Nicaraguaanse c\u00f3rdoba", + "de": "C\u00f3rdoba Oro", + "it": "C\u00f3rdoba nicaraguense", + "hu": "Nicaraguai c\u00f3rdoba", + "es": "C\u00f3rdoba" + }, + "LAK": { + "fr": "Kip laotien", + "en": "Lao kip", + "nl": "Laotiaanse kip", + "de": "Kip", + "it": "Kip laotiano", + "hu": "laoszi kip", + "es": "Kip laosiano" + }, + "MZE": { + "de": "Mosambikanischer Escudo", + "en": "Mozambican escudo", + "es": "Escudo mozambique\u00f1o" + }, + "SYP": { + "fr": "Livre syrienne", + "en": "Syrian pound", + "nl": "Syrisch pond", + "de": "Syrische Lira", + "it": "Lira siriana", + "hu": "Sz\u00edr font", + "es": "Libra siria" + }, + "MAD": { + "fr": "Dirham marocain", + "en": "Moroccan dirham", + "nl": "Marokkaanse dirham", + "de": "Marokkanischer Dirham", + "it": "Dirham marocchino", + "hu": "Marokk\u00f3i dirham", + "es": "D\u00edrham marroqu\u00ed" + }, + "MZN": { + "fr": "Metical", + "en": "Mozambican metical", + "nl": "Mozambikaanse metical", + "de": "Metical", + "it": "Metical mozambicano", + "hu": "Mozambiki metical", + "es": "Metical mozambique\u00f1o" + }, + "SCR": { + "fr": "roupie seychelloise", + "en": "Seychellois rupee", + "nl": "Seychelse roepie", + "de": "Seychellen-Rupie", + "it": "Rupia delle Seychelles", + "hu": "Seychelle-i r\u00fapia", + "es": "rupia" + }, + "ZAR": { + "fr": "rand", + "en": "South African rand", + "nl": "Zuid-Afrikaanse rand", + "de": "S\u00fcdafrikanischer Rand", + "it": "Rand sudafricano", + "hu": "D\u00e9l-afrikai rand", + "es": "Rand sudafricano" + }, + "NPR": { + "fr": "Roupie n\u00e9palaise", + "en": "Nepalese rupee", + "nl": "Nepalese roepie", + "de": "Nepalesische Rupie", + "it": "Rupia nepalese", + "hu": "nep\u00e1li r\u00fapia", + "es": "Rupia nepal\u00ed" + }, + "XSU": { + "fr": "Sucre", + "en": "SUCRE", + "nl": "SUCRE", + "es": "SUCRE", + "de": "SUCRE" + }, + "NGN": { + "fr": "Naira", + "en": "Nigerian naira", + "nl": "Nigeriaanse naira", + "de": "Naira", + "it": "Naira nigeriana", + "hu": "Nig\u00e9riai naira", + "es": "Naira" + }, + "CRC": { + "fr": "col\u00f3n", + "en": "Costa Rican col\u00f3n", + "nl": "Costa Ricaanse colon", + "de": "Costa-Rica-Col\u00f3n", + "it": "Col\u00f3n costaricano", + "hu": "Costa Rica-i col\u00f3n", + "es": "Col\u00f3n" + }, + "AED": { + "fr": "Dirham des \u00c9mirats arabes unis", + "en": "United Arab Emirates dirham", + "nl": "VAE-Dirham", + "de": "VAE-Dirham", + "it": "Dirham degli Emirati Arabi Uniti", + "hu": "emir\u00e1tusi dirham", + "es": "D\u00edrham de los Emiratos \u00c1rabes Unidos" + }, + "GBP": { + "fr": "livre sterling", + "en": "pound sterling", + "nl": "pond sterling", + "de": "Pfund Sterling", + "it": "sterlina britannica", + "hu": "font sterling", + "es": "libra esterlina" + }, + "LKR": { + "fr": "roupie srilankaise", + "en": "Sri Lankan rupee", + "nl": "Sri Lankaanse roepie", + "de": "Sri-Lanka-Rupie", + "it": "Rupia singalese", + "hu": "Sr\u00ed Lanka-i r\u00fapia", + "es": "rupia" + }, + "PKR": { + "fr": "Roupie pakistanaise", + "en": "Pakistani rupee", + "nl": "Pakistaanse roepie", + "de": "Pakistanische Rupie", + "it": "Rupia pakistana", + "hu": "pakiszt\u00e1ni r\u00fapia", + "es": "Rupia pakistan\u00ed" + }, + "HUF": { + "fr": "Forint", + "en": "Hungarian forint", + "nl": "Hongaarse forint", + "de": "Forint", + "it": "Fiorino ungherese", + "hu": "magyar forint", + "es": "Forinto h\u00fangaro" + }, + "SZL": { + "fr": "Lilangeni", + "en": "Swazi lilangeni", + "nl": "Swazische lilangeni", + "de": "Lilangeni", + "it": "Lilangeni dello Swaziland", + "hu": "Szv\u00e1zif\u00f6ldi lilangeni", + "es": "lilangeni" + }, + "LSL": { + "fr": "Loti", + "en": "Lesotho loti", + "nl": "Lesothaanse loti", + "de": "Lesothischer Loti", + "it": "Loti lesothiano", + "hu": "Lesoth\u00f3i loti", + "es": "Loti" + }, + "MNT": { + "fr": "Tugrik", + "en": "Mongolian t\u00f6gr\u00f6g", + "nl": "Mongoolse tugrik", + "de": "T\u00f6gr\u00f6g", + "it": "Tugrik mongolo", + "hu": "mongol tugrik", + "es": "Tugrik mongol" + }, + "AMD": { + "fr": "Dram", + "en": "Armenian dram", + "nl": "Armeense dram", + "de": "Armenischer Dram", + "it": "Dram armeno", + "hu": "\u00f6rm\u00e9ny dram", + "es": "Dram armenio" + }, + "UGX": { + "fr": "shilling ougandais", + "en": "Ugandan shilling", + "nl": "Oegandese shilling", + "de": "Uganda-Schilling", + "it": "Scellino ugandese", + "hu": "Ugandai shilling", + "es": "chel\u00edn" + }, + "QAR": { + "fr": "Riyal qatarien", + "en": "Qatari riyal", + "nl": "Qatarese rial", + "de": "Katar-Riyal", + "it": "Riyal del Qatar", + "hu": "katari ri\u00e1l", + "es": "Riyal catar\u00ed" + }, + "XDR": { + "fr": "Droits de tirage sp\u00e9ciaux", + "en": "Special drawing rights", + "nl": "Speciale trekkingsrechten", + "de": "Sonderziehungsrecht", + "it": "Diritti speciali di prelievo", + "hu": "SDR", + "es": "Derechos Especiales de Giro" + }, + "ITL": { + "fr": "Lire italienne", + "en": "Italian lira", + "nl": "Italiaanse lire", + "de": "Italienische Lira", + "it": "lira italiana", + "hu": "Olasz l\u00edra", + "es": "Lira italiana" + }, + "JMD": { + "fr": "Dollar jama\u00efcain", + "en": "Jamaican dollar", + "nl": "Jamaicaanse dollar", + "de": "Jamaika-Dollar", + "it": "Dollaro giamaicano", + "hu": "Jamaicai doll\u00e1r", + "es": "D\u00f3lar jamaiquino" + }, + "GEL": { + "fr": "lari", + "en": "Georgian lari", + "nl": "Georgische lari", + "de": "Georgischer Lari", + "it": "Lari georgiano", + "hu": "gr\u00faz lari", + "es": "lari" + }, + "SHP": { + "fr": "Livre de Sainte-H\u00e9l\u00e8ne", + "en": "Saint Helena pound", + "nl": "Sint-Heleens pond", + "de": "St.-Helena-Pfund", + "it": "Sterlina di Sant'Elena", + "hu": "Szent Ilona-i font", + "es": "Libra de Santa Elena" + }, + "AFN": { + "fr": "Afghani", + "en": "Afghan afghani", + "nl": "Afghaanse afghani", + "de": "Afghani", + "it": "Afghani afgano", + "hu": "afg\u00e1n afg\u00e1ni", + "es": "Afgani afgano" + }, + "MMK": { + "fr": "Kyat", + "en": "kyat", + "nl": "Myanmarese kyat", + "de": "Kyat", + "it": "Kyat birmano", + "hu": "mianmari kjap", + "es": "Kyat birmano" + }, + "CSK": { + "fr": "couronne tch\u00e9coslovaque", + "en": "Czechoslovak koruna", + "nl": "Tsjecho-Slowaakse kroon", + "de": "Tschechoslowakische Krone", + "it": "Corona cecoslovacca", + "hu": "csehszlov\u00e1k korona", + "es": "Corona checoslovaca" + }, + "KPW": { + "fr": "Won nord-cor\u00e9en", + "en": "North Korean won", + "nl": "Noord-Koreaanse won", + "de": "Nordkoreanischer Won", + "it": "Won nordcoreano", + "hu": "\u00e9szak-koreai von", + "es": "W\u014fn norcoreano" + }, + "TRY": { + "fr": "Livre turque", + "en": "Turkish lira", + "nl": "Nieuwe Turkse lira", + "de": "T\u00fcrkische Lira", + "it": "Nuova lira turca", + "hu": "t\u00f6r\u00f6k \u00faj l\u00edra", + "es": "Lira turca" + }, + "BDT": { + "fr": "Taka", + "en": "taka", + "nl": "Bengalese taka", + "de": "Taka", + "it": "Taka bengalese", + "hu": "bangladesi taka", + "es": "Taka banglades\u00ed" + }, + "GRD": { + "fr": "Drachme moderne grecque", + "en": "Greek drachma", + "nl": "Drachme", + "de": "Griechische Drachme", + "it": "Dracma greca", + "es": "Dracma griega moderna" + }, + "YER": { + "fr": "rial y\u00e9m\u00e9nite", + "en": "Yemeni rial", + "nl": "Jemenitische rial", + "de": "Jemen-Rial", + "it": "riyal yemenita", + "hu": "Jemeni ri\u00e1l", + "es": "rial yemen\u00ed" + }, + "DDM": { + "fr": "Mark est-allemand", + "en": "East German mark", + "nl": "Oost-Duitse mark", + "de": "Mark", + "it": "Marco della Repubblica Democratica Tedesca", + "es": "Marco de la Rep\u00fablica Democr\u00e1tica Alemana" + }, + "HTG": { + "fr": "Gourde", + "en": "Haitian gourde", + "nl": "Ha\u00eftiaanse gourde", + "de": "Gourde", + "it": "Gourde haitiano", + "hu": "haiti gourde", + "es": "Gourde" + }, + "XOF": { + "fr": "Franc CFA", + "en": "West African CFA franc", + "de": "CFA-Franc BCEAO", + "es": "Franco CFA de \u00c1frica Occidental" + }, + "MGA": { + "fr": "ariary", + "en": "Malagasy ariary", + "nl": "Malagassische ariary", + "de": "Ariary", + "it": "Ariary malgascio", + "hu": "Madagaszk\u00e1ri ariary", + "es": "ariary" + }, + "PHP": { + "fr": "peso philippin", + "en": "Philippine peso", + "nl": "Filipijnse peso", + "de": "Philippinischer Peso", + "it": "peso filippino", + "hu": "F\u00fcl\u00f6p-szigeteki peso", + "es": "peso" + }, + "LRD": { + "fr": "Dollar lib\u00e9rien", + "en": "Liberian dollar", + "nl": "Liberiaanse dollar", + "de": "Liberianischer Dollar", + "it": "Dollaro liberiano", + "hu": "Lib\u00e9riai doll\u00e1r", + "es": "D\u00f3lar liberiano" + }, + "RWF": { + "fr": "franc rwandais", + "en": "Rwandan franc", + "nl": "Rwandese frank", + "de": "Ruanda-Franc", + "it": "Franco ruandese", + "hu": "Ruandai frank", + "es": "franco" + }, + "NOK": { + "fr": "Couronne norv\u00e9gienne", + "en": "Norwegian krone", + "nl": "Noorse kroon", + "de": "Norwegische Krone", + "it": "Corona norvegese", + "hu": "norv\u00e9g korona", + "es": "Corona noruega" + }, + "MOP": { + "fr": "Pataca", + "en": "Macanese pataca", + "nl": "Macause pataca", + "de": "Macao-Pataca", + "it": "Pataca di Macao", + "hu": "Maka\u00f3i pataca", + "es": "Pataca" + }, + "SSP": { + "fr": "Livre sud-soudanaise", + "en": "South Sudanese pound", + "nl": "Zuid-Soedanees pond", + "de": "S\u00fcdsudanesisches Pfund", + "it": "Sterlina sudsudanese", + "hu": "D\u00e9l-szud\u00e1ni font", + "es": "Libra sursudanesa" + }, + "INR": { + "fr": "Roupie indienne", + "en": "Indian rupee", + "nl": "Indiase roepie", + "de": "Indische Rupie", + "it": "rupia indiana", + "hu": "Indiai r\u00fapia", + "es": "Rupia india" + }, + "MXN": { + "fr": "peso mexicain", + "en": "Mexican peso", + "nl": "Mexicaanse peso", + "de": "Mexikanischer Peso", + "it": "Peso messicano", + "hu": "mexik\u00f3i peso", + "es": "peso" + }, + "CZK": { + "fr": "Couronne tch\u00e8que", + "en": "Czech koruna", + "nl": "Tsjechische kroon", + "de": "Tschechische Krone", + "it": "Corona ceca", + "hu": "cseh korona", + "es": "Corona checa" + }, + "TJS": { + "fr": "Somoni", + "en": "Tajikistani somoni", + "nl": "Tadzjiekse somoni", + "de": "Somoni", + "it": "Somoni tagico", + "hu": "t\u00e1dzsik szomoni", + "es": "Somoni tayiko" + }, + "TJR": { + "en": "Tajikistani ruble", + "es": "Rublo tayiko" + }, + "BTN": { + "fr": "ngultrum", + "en": "Bhutanese ngultrum", + "nl": "Bhutaanse ngultrum", + "de": "Ngultrum", + "it": "Ngultrum del Bhutan", + "hu": "bhut\u00e1ni ngultrum", + "es": "Ngultrum butan\u00e9s" + }, + "KMF": { + "fr": "Franc comorien", + "en": "Comorian franc", + "nl": "Comorese frank", + "de": "Komoren-Franc", + "it": "Franco delle Comore", + "hu": "Comore-i frank", + "es": "Franco comorano" + }, + "TMT": { + "fr": "Manat turkm\u00e8ne", + "en": "Turkmenistan manat", + "nl": "Turkmeense manat", + "de": "Turkmenistan-Manat", + "it": "Manat turkmeno", + "hu": "T\u00fcrkm\u00e9n manat", + "es": "Manat turkmeno" + }, + "MUR": { + "fr": "Roupie mauricienne", + "en": "Mauritian rupee", + "nl": "Mauritiaanse roepie", + "de": "Mauritius-Rupie", + "it": "Rupia mauriziana", + "hu": "Mauritiusi r\u00fapia", + "es": "Rupia de Mauricio" + }, + "IDR": { + "fr": "Roupie indon\u00e9sienne", + "en": "Indonesian Rupiah", + "nl": "Indonesische roepia", + "de": "Indonesische Rupiah", + "it": "Rupia indonesiana", + "hu": "indon\u00e9z r\u00fapia", + "es": "Rupia indonesia" + }, + "HNL": { + "fr": "Lempira", + "en": "Honduran lempira", + "nl": "Hondurese lempira", + "de": "Lempira", + "it": "Lempira honduregna", + "hu": "hondurasi lempira", + "es": "lempira" + }, + "ETB": { + "fr": "Birr", + "en": "Ethiopian birr", + "nl": "Ethiopische birr", + "de": "\u00c4thiopischer Birr", + "it": "Birr etiope", + "hu": "eti\u00f3p birr", + "es": "Birr et\u00edope" + }, + "FJD": { + "fr": "dollar de Fidji", + "en": "Fijian dollar", + "nl": "Fiji-dollar", + "de": "Fidschi-Dollar", + "it": "Dollaro delle Figi", + "hu": "Fidzsi doll\u00e1r", + "es": "d\u00f3lar" + }, + "ISK": { + "fr": "Couronne islandaise", + "en": "Icelandic kr\u00f3na", + "nl": "IJslandse kroon", + "de": "Isl\u00e4ndische Krone", + "it": "Corona islandese", + "hu": "izlandi korona", + "es": "corona islandesa" + }, + "PEN": { + "fr": "nouveau sol", + "en": "Peruvian nuevo sol", + "nl": "Peruviaanse sol", + "de": "Nuevo Sol", + "it": "nuevo sol peruviano", + "hu": "perui \u00faj sol", + "es": "nuevo sol" + }, + "MKD": { + "fr": "Dinar mac\u00e9donien", + "en": "Macedonian denar", + "nl": "Macedonische denar", + "de": "Mazedonischer Denar", + "it": "Denaro macedone", + "hu": "maced\u00f3n d\u00e9n\u00e1r", + "es": "Denar macedonio" + }, + "ILS": { + "fr": "Shekel", + "en": "Israeli new shekel", + "nl": "Isra\u00eblische sjekel", + "de": "Schekel", + "it": "nuovo siclo israeliano", + "hu": "izraeli \u00faj s\u00e9kel", + "es": "Nuevo sh\u00e9quel" + }, + "DOP": { + "fr": "Peso dominicain", + "en": "Dominican peso", + "nl": "Dominicaanse peso", + "de": "Dominikanischer Peso", + "it": "Peso dominicano", + "hu": "Dominikai peso", + "es": "peso" + }, + "AZN": { + "fr": "Manat azerba\u00efdjanais", + "en": "Azerbaijani manat", + "nl": "Azerbeidzjaanse manat", + "de": "Aserbaidschan-Manat", + "it": "Manat azero", + "hu": "Azeri manat", + "es": "Manat azerbaiyano" + }, + "MDL": { + "fr": "Leu moldave", + "en": "Moldovan leu", + "nl": "Moldavische leu", + "de": "Moldauischer Leu", + "it": "Leu moldavo", + "hu": "moldov\u00e1n lej", + "es": "Leu moldavo" + }, + "BSD": { + "fr": "Dollar baham\u00e9en", + "en": "Bahamian dollar", + "nl": "Bahamaanse dollar", + "de": "Bahama-Dollar", + "it": "Dollaro delle Bahamas", + "hu": "bahamai doll\u00e1r", + "es": "D\u00f3lar bahame\u00f1o" + }, + "SEK": { + "fr": "Couronne su\u00e9doise", + "en": "Swedish krona", + "nl": "Zweedse kroon", + "de": "Schwedische Krone", + "it": "Corona svedese", + "hu": "Sv\u00e9d korona", + "es": "Corona sueca" + }, + "MVR": { + "fr": "Rufiyaa", + "en": "Maldivian rufiyaa", + "nl": "Maldivische rufiyaa", + "de": "Rufiyaa", + "it": "Rufiyaa delle Maldive", + "hu": "Mald\u00edv-szigeteki r\u00fafia", + "es": "Rupia de Maldivas" + }, + "FRF": { + "fr": "Franc fran\u00e7ais", + "en": "French franc", + "nl": "Franse frank", + "de": "Franz\u00f6sischer Franc", + "it": "Franco francese", + "hu": "Francia frank", + "es": "Franco franc\u00e9s" + }, + "SRD": { + "fr": "Dollar de Surinam", + "en": "Surinamese dollar", + "nl": "Surinaamse dollar", + "de": "Suriname-Dollar", + "it": "Dollaro surinamese", + "hu": "suriname-i doll\u00e1r", + "es": "D\u00f3lar surinam\u00e9s" + }, + "CUP": { + "fr": "peso cubain", + "en": "Cuban peso", + "nl": "Cubaanse peso", + "de": "Kubanischer Peso", + "it": "peso cubano", + "hu": "kubai peso", + "es": "peso" + }, + "BBD": { + "fr": "dollar barbadien", + "en": "Barbadian dollar", + "nl": "Barbadiaanse dollar", + "de": "Barbados-Dollar", + "it": "Dollaro di Barbados", + "hu": "barbadosi doll\u00e1r", + "es": "D\u00f3lar de Barbados" + }, + "KRW": { + "fr": "Won sud-cor\u00e9en", + "en": "South Korean won", + "nl": "Zuid-Koreaanse won", + "de": "S\u00fcdkoreanischer Won", + "it": "Won sudcoreano", + "hu": "D\u00e9l-koreai von", + "es": "W\u014fn surcoreano" + }, + "GMD": { + "fr": "Dalasi", + "en": "Gambian dalasi", + "nl": "Gambiaanse dalasi", + "de": "Dalasi", + "it": "Dalasi gambese", + "hu": "Gambiai dalasi", + "es": "Dalasi" + }, + "VEF": { + "fr": "Bol\u00edvar v\u00e9n\u00e9zu\u00e9lien", + "en": "Venezuelan bol\u00edvar", + "nl": "Venezolaanse bol\u00edvar", + "de": "Venezolanischer Bol\u00edvar", + "it": "Bol\u00edvar venezuelano", + "hu": "venezuelai bol\u00edvar", + "es": "Bol\u00edvar" + }, + "GTQ": { + "fr": "Quetzal", + "en": "Guatemalan quetzal", + "nl": "Guatemalteekse quetzal", + "de": "Guatemaltekischer Quetzal", + "it": "Quetzal guatemalteco", + "hu": "Guatemalai quetzal", + "es": "Quetzal" + }, + "ANG": { + "fr": "Florin des Antilles n\u00e9erlandaises", + "en": "Netherlands Antillean guilder", + "nl": "Antilliaanse gulden", + "de": "Antillen-Gulden", + "it": "Fiorino delle Antille Olandesi", + "hu": "Holland antill\u00e1kbeli forint", + "es": "Flor\u00edn antillano neerland\u00e9s" + }, + "CUC": { + "fr": "Peso cubain convertible", + "en": "Cuban convertible peso", + "nl": "Convertibele peso", + "de": "Peso convertible", + "it": "Peso cubano convertibile", + "hu": "Kubai konvertibilis peso", + "es": "peso convertible" + }, + "CLP": { + "fr": "Peso chilien", + "en": "Chilean peso", + "nl": "Chileense peso", + "de": "Chilenischer Peso", + "it": "Peso cileno", + "hu": "chilei peso", + "es": "peso" + }, + "ZMW": { + "fr": "Kwacha zambien", + "en": "Zambian kwacha", + "nl": "Zambiaanse kwacha", + "de": "Sambischer Kwacha", + "it": "Kwacha zambiano", + "hu": "Zambiai kwacha", + "es": "Kwacha zambiano" + }, + "LTL": { + "fr": "Litas", + "en": "Lithuanian litas", + "nl": "Litouwse litas", + "de": "Litas", + "it": "Litas lituano", + "hu": "litv\u00e1n litas", + "es": "Litas lituana" + }, + "CDF": { + "fr": "Franc congolais", + "en": "Congolese franc", + "nl": "Congolese frank", + "de": "Kongo-Franc", + "it": "Franco congolese", + "hu": "Kong\u00f3i frank", + "es": "franco" + }, + "XCD": { + "fr": "dollar des Cara\u00efbes orientales", + "en": "East Caribbean dollar", + "nl": "Oost-Caribische dollar", + "de": "ostkaribischer Dollar", + "it": "dollaro dei Caraibi Orientali", + "hu": "kelet-karibi doll\u00e1r", + "es": "d\u00f3lar del Caribe Oriental" + }, + "KZT": { + "fr": "Tenge kazakh", + "en": "Kazakhstani tenge", + "nl": "Kazachse tenge", + "de": "Tenge", + "it": "Tenge kazako", + "hu": "kazah tenge", + "es": "Tenge kazajo" + }, + "XPF": { + "fr": "Franc Pacifique", + "en": "CFP Franc", + "nl": "CFP-frank", + "de": "CFP-Franc", + "it": "Franco CFP", + "hu": "Csendes-\u00f3ce\u00e1ni valutak\u00f6z\u00f6ss\u00e9gi frank", + "es": "Franco CFP" + }, + "RUB": { + "fr": "Rouble russe", + "en": "Russian ruble", + "nl": "Russische roebel", + "de": "Russischer Rubel", + "it": "Rublo russo", + "hu": "orosz rubel", + "es": "Rublo ruso" + }, + "XFU": { + "fr": "Franc UIC", + "en": "UIC franc" + }, + "TTD": { + "fr": "Dollar de Trinit\u00e9-et-Tobago", + "en": "Trinidad and Tobago dollar", + "nl": "Trinidad en Tobagodollar", + "de": "Trinidad-und-Tobago-Dollar", + "it": "Dollaro di Trinidad e Tobago", + "hu": "Trinidad \u00e9s Tobag\u00f3-i doll\u00e1r", + "es": "D\u00f3lar trinitense" + }, + "RON": { + "fr": "Leu roumain", + "en": "Romanian leu", + "nl": "Roemeense leu", + "de": "Rum\u00e4nischer Leu", + "it": "Leu romeno", + "hu": "rom\u00e1n lej", + "es": "Leu rumano" + }, + "OMR": { + "fr": "Rial omanais", + "en": "Omani rial", + "nl": "Omaanse rial", + "de": "Omanischer Rial", + "it": "Riyal dell'Oman", + "hu": "Om\u00e1ni ri\u00e1l", + "es": "Rial oman\u00ed" + }, + "BRL": { + "fr": "r\u00e9al br\u00e9silien", + "en": "Brazilian real", + "nl": "Braziliaanse real", + "de": "Brasilianischer Real", + "it": "Real brasiliano", + "hu": "brazil real", + "es": "Real brasile\u00f1o" + }, + "SBD": { + "fr": "dollar des \u00eeles Salomon", + "en": "Solomon Islands dollar", + "nl": "Salomon-dollar", + "de": "Salomonen-Dollar", + "it": "Dollaro delle Salomone", + "hu": "Salamon-szigeteki doll\u00e1r", + "es": "d\u00f3lar de las Islas Salom\u00f3n" + }, + "PYG": { + "fr": "Guaran\u00ed", + "en": "Paraguayan guaran\u00ed", + "nl": "Paraguayaanse guaran\u00ed", + "de": "Paraguayischer Guaran\u00ed", + "it": "Guaran\u00ed paraguaiano", + "hu": "Paraguayi guaran\u00ed", + "es": "Guaran\u00ed" + }, + "KES": { + "fr": "Shilling k\u00e9nyan", + "en": "Kenyan shilling", + "nl": "Keniaanse shilling", + "de": "Kenia-Schilling", + "it": "Scellino keniota", + "hu": "Kenyai shilling", + "es": "Chel\u00edn keniano" + }, + "USD": { + "fr": "dollar am\u00e9ricain", + "en": "United States dollar", + "nl": "Amerikaanse dollar", + "de": "US-Dollar", + "it": "dollaro statunitense", + "hu": "amerikai doll\u00e1r", + "es": "d\u00f3lar" + }, + "TWD": { + "fr": "Nouveau dollar de Ta\u00efwan", + "en": "New Taiwan dollar", + "nl": "Taiwanese dollar", + "de": "Neuer Taiwan-Dollar", + "it": "Dollaro taiwanese", + "hu": "Tajvani \u00faj doll\u00e1r", + "es": "Nuevo d\u00f3lar taiwan\u00e9s" + }, + "TOP": { + "fr": "pa\u2019anga", + "en": "Tongan pa\u02bbanga", + "nl": "Tongaanse pa'anga", + "de": "Pa\u02bbanga", + "it": "Pa'anga tongano", + "hu": "Tongai pa\u02bbanga", + "es": "pa\u02bbanga" + }, + "COP": { + "fr": "Peso colombien", + "en": "peso", + "nl": "Colombiaanse peso", + "de": "Kolumbianischer Peso", + "it": "Peso colombiano", + "hu": "Kolumbiai peso", + "es": "peso" + }, + "GNF": { + "fr": "Franc guin\u00e9en", + "en": "Guinean franc", + "nl": "Guineese frank", + "de": "Franc Guin\u00e9en", + "it": "Franco guineano", + "hu": "Guineai frank", + "es": "Franco guineano" + }, + "WST": { + "fr": "Tala", + "en": "Samoan t\u0101l\u0101", + "nl": "Samoaanse tala", + "de": "Samoanischer Tala", + "it": "Tala samoano", + "hu": "Szamoai tala", + "es": "tala" + }, + "IQD": { + "fr": "Dinar irakien", + "en": "Iraqi dinar", + "nl": "Iraakse dinar", + "de": "Irakischer Dinar", + "it": "Dinaro iracheno", + "hu": "iraki din\u00e1r", + "es": "Dinar iraqu\u00ed" + }, + "ERN": { + "fr": "Nakfa \u00e9rythr\u00e9en", + "en": "Eritrean nakfa", + "nl": "Eritrese nakfa", + "de": "Eritreischer Nakfa", + "it": "Nacfa eritreo", + "hu": "Eritreai nakfa", + "es": "Nakfa" + }, + "CVE": { + "fr": "Escudo cap-verdien", + "en": "Cape Verdean escudo", + "nl": "Kaapverdische escudo", + "de": "Kap-Verde-Escudo", + "it": "Escudo capoverdiano", + "hu": "Z\u00f6ld-foki k\u00f6zt\u00e1rsas\u00e1gi escudo", + "es": "escudo" + }, + "AUD": { + "fr": "dollar australien", + "en": "Australian dollar", + "nl": "Australische dollar", + "de": "Australischer Dollar", + "it": "Dollaro australiano", + "hu": "Ausztr\u00e1l doll\u00e1r", + "es": "D\u00f3lar australiano" + }, + "BAM": { + "fr": "Mark convertible de Bosnie-Herz\u00e9govine", + "en": "Bosnia and Herzegovina convertible mark", + "nl": "Bosnische inwisselbare mark", + "de": "Konvertible Mark", + "it": "Marco bosniaco", + "hu": "bosny\u00e1k konvertibilis m\u00e1rka", + "es": "Marco bosnioherzegovino" + }, + "KWD": { + "fr": "Dinar kowe\u00eftien", + "en": "Kuwaiti dinar", + "nl": "Koeweitse dinar", + "de": "Kuwait-Dinar", + "it": "Dinaro kuwaitiano", + "hu": "kuvaiti din\u00e1r", + "es": "Dinar kuwait\u00ed" + }, + "BIF": { + "fr": "Franc burundais", + "en": "Burundian franc", + "nl": "Burundese frank", + "de": "Burundi-Franc", + "it": "Franco del Burundi", + "hu": "Burundi frank", + "es": "Franco de Burundi" + }, + "PGK": { + "fr": "Kina", + "en": "Papua New Guinean kina", + "nl": "Papoea-Nieuw-Guinese kina", + "de": "Kina", + "it": "Kina papuana", + "hu": "P\u00e1pua \u00faj-guineai kina", + "es": "Kina" + }, + "SOS": { + "fr": "shilling somalien", + "en": "Somali shilling", + "nl": "Somalische shilling", + "de": "Somalia-Schilling", + "it": "Scellino somalo", + "hu": "Szom\u00e1liai shilling", + "es": "chel\u00edn" + }, + "CAD": { + "fr": "Dollar canadien", + "en": "Canadian dollar", + "nl": "Canadese dollar", + "de": "Kanadischer Dollar", + "it": "Dollaro canadese", + "hu": "kanadai doll\u00e1r", + "es": "D\u00f3lar canadiense" + }, + "SGD": { + "fr": "Dollar de Singapour", + "en": "Singapore dollar", + "nl": "Singaporese dollar", + "de": "Singapur-Dollar", + "it": "Dollaro di Singapore", + "hu": "szingap\u00fari doll\u00e1r", + "es": "D\u00f3lar de Singapur" + }, + "UZS": { + "fr": "Sum", + "en": "Uzbekistani som", + "nl": "Oezbeekse sum", + "de": "So\u02bbm", + "it": "Som uzbeco", + "hu": "\u00dczb\u00e9g szom", + "es": "som" + }, + "STD": { + "fr": "Dobra", + "en": "S\u00e3o Tom\u00e9 and Pr\u00edncipe dobra", + "nl": "Santomese dobra", + "de": "S\u00e3o-tom\u00e9ischer Dobra", + "it": "Dobra di S\u00e3o Tom\u00e9 e Pr\u00edncipe", + "hu": "S\u00e3o Tom\u00e9 \u00e9s Pr\u00edncipe-i dobra", + "es": "Dobra santotomense" + }, + "XFO": { + "fr": "Franc-or", + "en": "Gold franc", + "de": "Goldfranken" + }, + "IRR": { + "fr": "Rial iranien", + "en": "Iranian rial", + "nl": "Iraanse rial", + "de": "Iranischer Rial", + "it": "Riyal iraniano", + "hu": "ir\u00e1ni ri\u00e1l", + "es": "Rial iran\u00ed" + }, + "CNY": { + "fr": "Yuan", + "en": "renminbi", + "nl": "Chinese renminbi", + "de": "Renminbi", + "it": "Renminbi cinese", + "hu": "Renminbi", + "es": "Yuan chino" + }, + "SLL": { + "fr": "leone", + "en": "Sierra Leonean leone", + "nl": "Sierra Leoonse leone", + "de": "Sierra-leonischer Leone", + "it": "Leone sierraleonese", + "hu": "Sierra Leone-i leone", + "es": "leone" + }, + "TND": { + "fr": "Dinar tunisien", + "en": "Tunisian dinar", + "nl": "Tunesische dinar", + "de": "Tunesischer Dinar", + "it": "Dinaro tunisino", + "hu": "Tun\u00e9ziai din\u00e1r", + "es": "dinar" + }, + "GYD": { + "fr": "Dollar guyanien", + "en": "Guyanese dollar", + "nl": "Guyaanse dollar", + "de": "Guyana-Dollar", + "it": "Dollaro della Guyana", + "hu": "Guyanai doll\u00e1r", + "es": "D\u00f3lar guyan\u00e9s" + }, + "MTL": { + "fr": "Lire maltaise", + "en": "Maltese lira", + "nl": "Maltese lire", + "de": "Maltesische Lira", + "it": "Lira maltese", + "hu": "M\u00e1ltai l\u00edra", + "es": "Lira maltesa" + }, + "NZD": { + "fr": "dollar n\u00e9o-z\u00e9landais", + "en": "New Zealand dollar", + "nl": "Nieuw-Zeelandse dollar", + "de": "Neuseeland-Dollar", + "it": "Dollaro neozelandese", + "hu": "\u00faj-z\u00e9landi doll\u00e1r", + "es": "D\u00f3lar neozeland\u00e9s" + }, + "FKP": { + "fr": "Livre des \u00celes Malouines", + "en": "Falkland Islands pound", + "nl": "Falklandeilands pond", + "de": "Falkland-Pfund", + "it": "Sterlina delle Falkland", + "hu": "Falkland-szigeteki font", + "es": "Libra malvinense" + }, + "LVL": { + "fr": "Lats", + "en": "lats", + "nl": "Letse lats", + "de": "Lats", + "it": "Lats lettone", + "hu": "lett lat", + "es": "Lats let\u00f3n" + }, + "ARP": { + "fr": "peso argentino", + "en": "peso argentino", + "nl": "peso argentino", + "it": "peso argentino", + "es": "peso argentino" + }, + "KGS": { + "fr": "Som", + "en": "Kyrgyzstani som", + "nl": "Kirgizische som", + "de": "Som", + "it": "som kirghizo", + "hu": "kirgiz szom", + "es": "Som kirgu\u00eds" + }, + "ARS": { + "fr": "peso argentin", + "en": "peso", + "nl": "Argentijnse peso", + "de": "Argentinischer Peso", + "it": "peso argentino", + "hu": "argentin peso", + "es": "peso" + }, + "BMD": { + "fr": "Dollar bermudien", + "en": "Bermudian dollar", + "nl": "Bermuda-dollar", + "de": "Bermuda-Dollar", + "it": "Dollaro della Bermuda", + "hu": "bermudai doll\u00e1r", + "es": "D\u00f3lar bermude\u00f1o" + }, + "RSD": { + "fr": "Dinar serbe", + "en": "Serbian dinar", + "nl": "Servische dinar", + "de": "Serbischer Dinar", + "it": "Dinaro serbo", + "hu": "szerb din\u00e1r", + "es": "Dinar serbio" + }, + "BHD": { + "fr": "Dinar bahre\u00efnien", + "en": "Bahraini dinar", + "nl": "Bahreinse dinar", + "de": "Bahrain-Dinar", + "it": "Dinaro del Bahrain", + "hu": "bahreini din\u00e1r", + "es": "Dinar barein\u00ed" + }, + "JPY": { + "fr": "Yen", + "en": "Japanese yen", + "nl": "Japanse yen", + "de": "Yen", + "it": "Yen giapponese", + "hu": "Jap\u00e1n jen", + "es": "yen" + }, + "ARA": { + "fr": "Austral (monnaie)", + "en": "Argentine austral", + "de": "Austral (W\u00e4hrung)", + "it": "Austral argentino", + "es": "Austral" + }, + "SDG": { + "fr": "Livre soudanaise", + "en": "Sudanese pound", + "nl": "Soedanees pond", + "de": "Sudanesisches Pfund", + "it": "Sterlina sudanese", + "hu": "Szud\u00e1ni font", + "es": "Libra sudanesa" + } + } +} \ No newline at end of file diff --git a/sources/searx/engines/__init__.py b/sources/searx/engines/__init__.py index 21a3075..447138d 100644 --- a/sources/searx/engines/__init__.py +++ b/sources/searx/engines/__init__.py @@ -71,8 +71,11 @@ def load_engine(engine_data): if not hasattr(engine, 'language_support'): engine.language_support = True + if not hasattr(engine, 'safesearch'): + engine.safesearch = False + if not hasattr(engine, 'timeout'): - engine.timeout = settings['server']['request_timeout'] + engine.timeout = settings['outgoing']['request_timeout'] if not hasattr(engine, 'shortcut'): engine.shortcut = '' @@ -86,7 +89,7 @@ def load_engine(engine_data): continue if getattr(engine, engine_attr) is None: logger.error('Missing engine config attribute: "{0}.{1}"' - .format(engine.name, engine_attr)) + .format(engine.name, engine_attr)) sys.exit(1) engine.stats = { @@ -106,7 +109,7 @@ def load_engine(engine_data): if engine.shortcut: if engine.shortcut in engine_shortcuts: logger.error('Engine config error: ambigious shortcut: {0}' - .format(engine.shortcut)) + .format(engine.shortcut)) sys.exit(1) engine_shortcuts[engine.shortcut] = engine.name return engine diff --git a/sources/searx/engines/bing.py b/sources/searx/engines/bing.py index f9c323d..171606c 100644 --- a/sources/searx/engines/bing.py +++ b/sources/searx/engines/bing.py @@ -1,15 +1,17 @@ -## Bing (Web) -# -# @website https://www.bing.com -# @provide-api yes (http://datamarket.azure.com/dataset/bing/search), -# max. 5000 query/month -# -# @using-api no (because of query limit) -# @results HTML (using search portal) -# @stable no (HTML can change) -# @parse url, title, content -# -# @todo publishedDate +""" + Bing (Web) + + @website https://www.bing.com + @provide-api yes (http://datamarket.azure.com/dataset/bing/search), + max. 5000 query/month + + @using-api no (because of query limit) + @results HTML (using search portal) + @stable no (HTML can change) + @parse url, title, content + + @todo publishedDate +""" from urllib import urlencode from cgi import escape @@ -50,7 +52,7 @@ def request(query, params): def response(resp): results = [] - dom = html.fromstring(resp.content) + dom = html.fromstring(resp.text) # parse results for result in dom.xpath('//div[@class="sa_cc"]'): diff --git a/sources/searx/engines/bing_images.py b/sources/searx/engines/bing_images.py index b8c61c1..06850df 100644 --- a/sources/searx/engines/bing_images.py +++ b/sources/searx/engines/bing_images.py @@ -1,17 +1,19 @@ -## Bing (Images) -# -# @website https://www.bing.com/images -# @provide-api yes (http://datamarket.azure.com/dataset/bing/search), -# max. 5000 query/month -# -# @using-api no (because of query limit) -# @results HTML (using search portal) -# @stable no (HTML can change) -# @parse url, title, img_src -# -# @todo currently there are up to 35 images receive per page, -# because bing does not parse count=10. -# limited response to 10 images +""" + Bing (Images) + + @website https://www.bing.com/images + @provide-api yes (http://datamarket.azure.com/dataset/bing/search), + max. 5000 query/month + + @using-api no (because of query limit) + @results HTML (using search portal) + @stable no (HTML can change) + @parse url, title, img_src + + @todo currently there are up to 35 images receive per page, + because bing does not parse count=10. + limited response to 10 images +""" from urllib import urlencode from lxml import html @@ -26,7 +28,7 @@ safesearch = True # search-url base_url = 'https://www.bing.com/' search_string = 'images/search?{query}&count=10&first={offset}' -thumb_url = "http://ts1.mm.bing.net/th?id={ihk}" +thumb_url = "https://www.bing.com/th?id={ihk}" # safesearch definitions safesearch_types = {2: 'STRICT', @@ -61,7 +63,7 @@ def request(query, params): def response(resp): results = [] - dom = html.fromstring(resp.content) + dom = html.fromstring(resp.text) # init regex for yaml-parsing p = re.compile('({|,)([a-z]+):(")') @@ -76,7 +78,7 @@ def response(resp): title = link.attrib.get('t1') ihk = link.attrib.get('ihk') - #url = 'http://' + link.attrib.get('t3') + # url = 'http://' + link.attrib.get('t3') url = yaml_data.get('surl') img_src = yaml_data.get('imgurl') diff --git a/sources/searx/engines/bing_news.py b/sources/searx/engines/bing_news.py index e6adb26..943bf88 100644 --- a/sources/searx/engines/bing_news.py +++ b/sources/searx/engines/bing_news.py @@ -1,21 +1,22 @@ -## Bing (News) -# -# @website https://www.bing.com/news -# @provide-api yes (http://datamarket.azure.com/dataset/bing/search), -# max. 5000 query/month -# -# @using-api no (because of query limit) -# @results HTML (using search portal) -# @stable no (HTML can change) -# @parse url, title, content, publishedDate +""" + Bing (News) + + @website https://www.bing.com/news + @provide-api yes (http://datamarket.azure.com/dataset/bing/search), + max. 5000 query/month + + @using-api no (because of query limit) + @results RSS (using search portal) + @stable yes (except perhaps for the images) + @parse url, title, content, publishedDate, thumbnail +""" from urllib import urlencode -from cgi import escape -from lxml import html -from datetime import datetime, timedelta +from urlparse import urlparse, parse_qsl +from datetime import datetime from dateutil import parser -import re -from searx.engines.xpath import extract_text +from lxml import etree +from searx.utils import list_get # engine dependent config categories = ['news'] @@ -24,7 +25,25 @@ language_support = True # search-url base_url = 'https://www.bing.com/' -search_string = 'news/search?{query}&first={offset}' +search_string = 'news/search?{query}&first={offset}&format=RSS' + + +# remove click +def url_cleanup(url_string): + parsed_url = urlparse(url_string) + if parsed_url.netloc == 'www.bing.com' and parsed_url.path == '/news/apiclick.aspx': + query = dict(parse_qsl(parsed_url.query)) + return query.get('url', None) + return url_string + + +# replace the http://*bing4.com/th?id=... by https://www.bing.com/th?id=... +def image_url_cleanup(url_string): + parsed_url = urlparse(url_string) + if parsed_url.netloc.endswith('bing4.com') and parsed_url.path == '/th': + query = dict(parse_qsl(parsed_url.query)) + return "https://www.bing.com/th?id=" + query.get('id') + return url_string # do search-request @@ -40,8 +59,6 @@ def request(query, params): query=urlencode({'q': query, 'setmkt': language}), offset=offset) - params['cookies']['_FP'] = "ui=en-US" - params['url'] = base_url + search_path return params @@ -51,48 +68,44 @@ def request(query, params): def response(resp): results = [] - dom = html.fromstring(resp.content) + rss = etree.fromstring(resp.text) + + ns = rss.nsmap # parse results - for result in dom.xpath('//div[@class="sn_r"]'): - link = result.xpath('.//div[@class="newstitle"]/a')[0] - url = link.attrib.get('href') - title = extract_text(link) - contentXPath = result.xpath('.//div[@class="sn_txt"]/div//span[@class="sn_snip"]') - content = escape(extract_text(contentXPath)) + for item in rss.xpath('./channel/item'): + # url / title / content + url = url_cleanup(item.xpath('./link/text()')[0]) + title = list_get(item.xpath('./title/text()'), 0, url) + content = list_get(item.xpath('./description/text()'), 0, '') - # parse publishedDate - publishedDateXPath = result.xpath('.//div[@class="sn_txt"]/div' - '//span[contains(@class,"sn_ST")]' - '//span[contains(@class,"sn_tm")]') + # publishedDate + publishedDate = list_get(item.xpath('./pubDate/text()'), 0) + try: + publishedDate = parser.parse(publishedDate, dayfirst=False) + except TypeError: + publishedDate = datetime.now() + except ValueError: + publishedDate = datetime.now() - publishedDate = escape(extract_text(publishedDateXPath)) - - if re.match("^[0-9]+ minute(s|) ago$", publishedDate): - timeNumbers = re.findall(r'\d+', publishedDate) - publishedDate = datetime.now() - timedelta(minutes=int(timeNumbers[0])) - elif re.match("^[0-9]+ hour(s|) ago$", publishedDate): - timeNumbers = re.findall(r'\d+', publishedDate) - publishedDate = datetime.now() - timedelta(hours=int(timeNumbers[0])) - elif re.match("^[0-9]+ hour(s|), [0-9]+ minute(s|) ago$", publishedDate): - timeNumbers = re.findall(r'\d+', publishedDate) - publishedDate = datetime.now()\ - - timedelta(hours=int(timeNumbers[0]))\ - - timedelta(minutes=int(timeNumbers[1])) - elif re.match("^[0-9]+ day(s|) ago$", publishedDate): - timeNumbers = re.findall(r'\d+', publishedDate) - publishedDate = datetime.now() - timedelta(days=int(timeNumbers[0])) - else: - try: - publishedDate = parser.parse(publishedDate, dayfirst=False) - except TypeError: - publishedDate = datetime.now() + # thumbnail + thumbnail = list_get(item.xpath('./News:Image/text()', namespaces=ns), 0) + if thumbnail is not None: + thumbnail = image_url_cleanup(thumbnail) # append result - results.append({'url': url, - 'title': title, - 'publishedDate': publishedDate, - 'content': content}) + if thumbnail is not None: + results.append({'template': 'videos.html', + 'url': url, + 'title': title, + 'publishedDate': publishedDate, + 'content': content, + 'thumbnail': thumbnail}) + else: + results.append({'url': url, + 'title': title, + 'publishedDate': publishedDate, + 'content': content}) # return results return results diff --git a/sources/searx/engines/blekko_images.py b/sources/searx/engines/blekko_images.py index 2e7ec90..93ac661 100644 --- a/sources/searx/engines/blekko_images.py +++ b/sources/searx/engines/blekko_images.py @@ -1,12 +1,14 @@ -## Blekko (Images) -# -# @website https://blekko.com -# @provide-api yes (inofficial) -# -# @using-api yes -# @results JSON -# @stable yes -# @parse url, title, img_src +""" + Blekko (Images) + + @website https://blekko.com + @provide-api yes (inofficial) + + @using-api yes + @results JSON + @stable yes + @parse url, title, img_src +""" from json import loads from urllib import urlencode diff --git a/sources/searx/engines/btdigg.py b/sources/searx/engines/btdigg.py index 9442506..bde8661 100644 --- a/sources/searx/engines/btdigg.py +++ b/sources/searx/engines/btdigg.py @@ -1,12 +1,14 @@ -## BTDigg (Videos, Music, Files) -# -# @website https://btdigg.org -# @provide-api yes (on demand) -# -# @using-api no -# @results HTML (using search portal) -# @stable no (HTML can change) -# @parse url, title, content, seed, leech, magnetlink +""" + BTDigg (Videos, Music, Files) + + @website https://btdigg.org + @provide-api yes (on demand) + + @using-api no + @results HTML (using search portal) + @stable no (HTML can change) + @parse url, title, content, seed, leech, magnetlink +""" from urlparse import urljoin from cgi import escape diff --git a/sources/searx/engines/currency_convert.py b/sources/searx/engines/currency_convert.py index 4618c82..26830a1 100644 --- a/sources/searx/engines/currency_convert.py +++ b/sources/searx/engines/currency_convert.py @@ -1,21 +1,49 @@ from datetime import datetime import re +import os +import json +import unicodedata + categories = [] -url = 'http://finance.yahoo.com/d/quotes.csv?e=.csv&f=sl1d1t1&s={query}=X' +url = 'https://download.finance.yahoo.com/d/quotes.csv?e=.csv&f=sl1d1t1&s={query}=X' weight = 100 -parser_re = re.compile(r'^\W*(\d+(?:\.\d+)?)\W*([a-z]{3})\W*(?:in)?\W*([a-z]{3})\W*$', re.I) # noqa +parser_re = re.compile(u'^\W*(\d+(?:\.\d+)?)\W*([^.0-9].+)\W+in?\W+([^\.]+)\W*$', re.I) # noqa + +db = 1 + + +def normalize_name(name): + name = name.lower().replace('-', ' ') + name = re.sub(' +', ' ', name) + return unicodedata.normalize('NFKD', name).lower() + + +def name_to_iso4217(name): + global db + + name = normalize_name(name) + currencies = db['names'].get(name, [name]) + return currencies[0] + + +def iso4217_to_name(iso4217, language): + global db + + return db['iso4217'].get(iso4217, {}).get(language, iso4217) def request(query, params): - m = parser_re.match(query) + m = parser_re.match(unicode(query, 'utf8')) if not m: # wrong query return params ammount, from_currency, to_currency = m.groups() ammount = float(ammount) + from_currency = name_to_iso4217(from_currency.strip()) + to_currency = name_to_iso4217(to_currency.strip()) q = (from_currency + to_currency).upper() @@ -23,6 +51,8 @@ def request(query, params): params['ammount'] = ammount params['from'] = from_currency params['to'] = to_currency + params['from_name'] = iso4217_to_name(from_currency, 'en') + params['to_name'] = iso4217_to_name(to_currency, 'en') return params @@ -35,16 +65,18 @@ def response(resp): except: return results - answer = '{0} {1} = {2} {3} (1 {1} = {4} {3})'.format( + answer = '{0} {1} = {2} {3}, 1 {1} ({5}) = {4} {3} ({6})'.format( resp.search_params['ammount'], resp.search_params['from'], resp.search_params['ammount'] * conversion_rate, resp.search_params['to'], - conversion_rate + conversion_rate, + resp.search_params['from_name'], + resp.search_params['to_name'], ) now_date = datetime.now().strftime('%Y%m%d') - url = 'http://finance.yahoo.com/currency/converter-results/{0}/{1}-{2}-to-{3}.html' # noqa + url = 'https://finance.yahoo.com/currency/converter-results/{0}/{1}-{2}-to-{3}.html' # noqa url = url.format( now_date, resp.search_params['ammount'], @@ -55,3 +87,15 @@ def response(resp): results.append({'answer': answer, 'url': url}) return results + + +def load(): + global db + + current_dir = os.path.dirname(os.path.realpath(__file__)) + json_data = open(current_dir + "/../data/currencies.json").read() + + db = json.loads(json_data) + + +load() diff --git a/sources/searx/engines/dailymotion.py b/sources/searx/engines/dailymotion.py index 03b1dbb..4eb8947 100644 --- a/sources/searx/engines/dailymotion.py +++ b/sources/searx/engines/dailymotion.py @@ -1,14 +1,16 @@ -## Dailymotion (Videos) -# -# @website https://www.dailymotion.com -# @provide-api yes (http://www.dailymotion.com/developer) -# -# @using-api yes -# @results JSON -# @stable yes -# @parse url, title, thumbnail, publishedDate, embedded -# -# @todo set content-parameter with correct data +""" + Dailymotion (Videos) + + @website https://www.dailymotion.com + @provide-api yes (http://www.dailymotion.com/developer) + + @using-api yes + @results JSON + @stable yes + @parse url, title, thumbnail, publishedDate, embedded + + @todo set content-parameter with correct data +""" from urllib import urlencode from json import loads @@ -48,7 +50,7 @@ def response(resp): search_res = loads(resp.text) # return empty array if there are no results - if not 'list' in search_res: + if 'list' not in search_res: return [] # parse results @@ -60,6 +62,9 @@ def response(resp): publishedDate = datetime.fromtimestamp(res['created_time'], None) embedded = embedded_url.format(videoid=res['id']) + # http to https + thumbnail = thumbnail.replace("http://", "https://") + results.append({'template': 'videos.html', 'url': url, 'title': title, diff --git a/sources/searx/engines/deezer.py b/sources/searx/engines/deezer.py index 433ceff..0530bc0 100644 --- a/sources/searx/engines/deezer.py +++ b/sources/searx/engines/deezer.py @@ -1,12 +1,14 @@ -## Deezer (Music) -# -# @website https://deezer.com -# @provide-api yes (http://developers.deezer.com/api/) -# -# @using-api yes -# @results JSON -# @stable yes -# @parse url, title, content, embedded +""" + Deezer (Music) + + @website https://deezer.com + @provide-api yes (http://developers.deezer.com/api/) + + @using-api yes + @results JSON + @stable yes + @parse url, title, content, embedded +""" from json import loads from urllib import urlencode @@ -16,11 +18,11 @@ categories = ['music'] paging = True # search-url -url = 'http://api.deezer.com/' +url = 'https://api.deezer.com/' search_url = url + 'search?{query}&index={offset}' embedded_url = '' @@ -45,6 +47,10 @@ def response(resp): if result['type'] == 'track': title = result['title'] url = result['link'] + + if url.startswith('http://'): + url = 'https' + url[4:] + content = result['artist']['name'] +\ " • " +\ result['album']['title'] +\ diff --git a/sources/searx/engines/deviantart.py b/sources/searx/engines/deviantart.py index 4198e8c..60c8d7e 100644 --- a/sources/searx/engines/deviantart.py +++ b/sources/searx/engines/deviantart.py @@ -1,14 +1,16 @@ -## Deviantart (Images) -# -# @website https://www.deviantart.com/ -# @provide-api yes (https://www.deviantart.com/developers/) (RSS) -# -# @using-api no (TODO, rewrite to api) -# @results HTML -# @stable no (HTML can change) -# @parse url, title, thumbnail_src, img_src -# -# @todo rewrite to api +""" + Deviantart (Images) + + @website https://www.deviantart.com/ + @provide-api yes (https://www.deviantart.com/developers/) (RSS) + + @using-api no (TODO, rewrite to api) + @results HTML + @stable no (HTML can change) + @parse url, title, thumbnail_src, img_src + + @todo rewrite to api +""" from urllib import urlencode from urlparse import urljoin @@ -22,7 +24,7 @@ paging = True # search-url base_url = 'https://www.deviantart.com/' -search_url = base_url+'search?offset={offset}&{query}' +search_url = base_url+'browse/all/?offset={offset}&{query}' # do search-request @@ -56,6 +58,12 @@ def response(resp): thumbnail_src = link.xpath('.//img')[0].attrib.get('src') img_src = regex.sub('/', thumbnail_src) + # http to https, remove domain sharding + thumbnail_src = re.sub(r"https?://(th|fc)\d+.", "https://th01.", thumbnail_src) + thumbnail_src = re.sub(r"http://", "https://", thumbnail_src) + + url = re.sub(r"http://(.*)\.deviantart\.com/", "https://\\1.deviantart.com/", url) + # append result results.append({'url': url, 'title': title, diff --git a/sources/searx/engines/digg.py b/sources/searx/engines/digg.py index 1b5f2c8..000f66b 100644 --- a/sources/searx/engines/digg.py +++ b/sources/searx/engines/digg.py @@ -1,12 +1,14 @@ -## Digg (News, Social media) -# -# @website https://digg.com/ -# @provide-api no -# -# @using-api no -# @results HTML (using search portal) -# @stable no (HTML can change) -# @parse url, title, content, publishedDate, thumbnail +""" + Digg (News, Social media) + + @website https://digg.com/ + @provide-api no + + @using-api no + @results HTML (using search portal) + @stable no (HTML can change) + @parse url, title, content, publishedDate, thumbnail +""" from urllib import quote_plus from json import loads @@ -58,6 +60,9 @@ def response(resp): pubdate = result.xpath(pubdate_xpath)[0].attrib.get('datetime') publishedDate = parser.parse(pubdate) + # http to https + thumbnail = thumbnail.replace("http://static.digg.com", "https://static.digg.com") + # append result results.append({'url': url, 'title': title, diff --git a/sources/searx/engines/duckduckgo.py b/sources/searx/engines/duckduckgo.py index e35a633..4ac2099 100644 --- a/sources/searx/engines/duckduckgo.py +++ b/sources/searx/engines/duckduckgo.py @@ -1,17 +1,19 @@ -## DuckDuckGo (Web) -# -# @website https://duckduckgo.com/ -# @provide-api yes (https://duckduckgo.com/api), -# but not all results from search-site -# -# @using-api no -# @results HTML (using search portal) -# @stable no (HTML can change) -# @parse url, title, content -# -# @todo rewrite to api -# @todo language support -# (the current used site does not support language-change) +""" + DuckDuckGo (Web) + + @website https://duckduckgo.com/ + @provide-api yes (https://duckduckgo.com/api), + but not all results from search-site + + @using-api no + @results HTML (using search portal) + @stable no (HTML can change) + @parse url, title, content + + @todo rewrite to api + @todo language support + (the current used site does not support language-change) +""" from urllib import urlencode from lxml.html import fromstring diff --git a/sources/searx/engines/dummy.py b/sources/searx/engines/dummy.py index c60b7a5..50b56ef 100644 --- a/sources/searx/engines/dummy.py +++ b/sources/searx/engines/dummy.py @@ -1,7 +1,9 @@ -## Dummy -# -# @results empty array -# @stable yes +""" + Dummy + + @results empty array + @stable yes +""" # do search-request diff --git a/sources/searx/engines/faroo.py b/sources/searx/engines/faroo.py index 4a5e60a..43df14e 100644 --- a/sources/searx/engines/faroo.py +++ b/sources/searx/engines/faroo.py @@ -1,12 +1,14 @@ -## Faroo (Web, News) -# -# @website http://www.faroo.com -# @provide-api yes (http://www.faroo.com/hp/api/api.html), require API-key -# -# @using-api yes -# @results JSON -# @stable yes -# @parse url, title, content, publishedDate, img_src +""" + Faroo (Web, News) + + @website http://www.faroo.com + @provide-api yes (http://www.faroo.com/hp/api/api.html), require API-key + + @using-api yes + @results JSON + @stable yes + @parse url, title, content, publishedDate, img_src +""" from urllib import urlencode from json import loads diff --git a/sources/searx/engines/flickr.py b/sources/searx/engines/flickr.py index 4040236..68d45bc 100644 --- a/sources/searx/engines/flickr.py +++ b/sources/searx/engines/flickr.py @@ -1,15 +1,17 @@ #!/usr/bin/env python -## Flickr (Images) -# -# @website https://www.flickr.com -# @provide-api yes (https://secure.flickr.com/services/api/flickr.photos.search.html) -# -# @using-api yes -# @results JSON -# @stable yes -# @parse url, title, thumbnail, img_src -#More info on api-key : https://www.flickr.com/services/apps/create/ +""" + Flickr (Images) + + @website https://www.flickr.com + @provide-api yes (https://secure.flickr.com/services/api/flickr.photos.search.html) + + @using-api yes + @results JSON + @stable yes + @parse url, title, thumbnail, img_src + More info on api-key : https://www.flickr.com/services/apps/create/ +""" from urllib import urlencode from json import loads @@ -48,10 +50,10 @@ def response(resp): search_results = loads(resp.text) # return empty array if there are no results - if not 'photos' in search_results: + if 'photos' not in search_results: return [] - if not 'photo' in search_results['photos']: + if 'photo' not in search_results['photos']: return [] photos = search_results['photos']['photo'] diff --git a/sources/searx/engines/flickr_noapi.py b/sources/searx/engines/flickr_noapi.py index 3a83fdc..87b912e 100644 --- a/sources/searx/engines/flickr_noapi.py +++ b/sources/searx/engines/flickr_noapi.py @@ -1,14 +1,16 @@ #!/usr/bin/env python -# Flickr (Images) -# -# @website https://www.flickr.com -# @provide-api yes (https://secure.flickr.com/services/api/flickr.photos.search.html) -# -# @using-api no -# @results HTML -# @stable no -# @parse url, title, thumbnail, img_src +""" + Flickr (Images) + + @website https://www.flickr.com + @provide-api yes (https://secure.flickr.com/services/api/flickr.photos.search.html) + + @using-api no + @results HTML + @stable no + @parse url, title, thumbnail, img_src +""" from urllib import urlencode from json import loads @@ -20,10 +22,10 @@ logger = logger.getChild('flickr-noapi') categories = ['images'] -url = 'https://secure.flickr.com/' -search_url = url + 'search/?{query}&page={page}' +url = 'https://www.flickr.com/' +search_url = url + 'search?{query}&page={page}' photo_url = 'https://www.flickr.com/photos/{userid}/{photoid}' -regex = re.compile(r"\"search-photos-models\",\"photos\":(.*}),\"totalItems\":", re.DOTALL) +regex = re.compile(r"\"search-photos-lite-models\",\"photos\":(.*}),\"totalItems\":", re.DOTALL) image_sizes = ('o', 'k', 'h', 'b', 'c', 'z', 'n', 'm', 't', 'q', 's') paging = True @@ -36,6 +38,7 @@ def build_flickr_url(user_id, photo_id): def request(query, params): params['url'] = search_url.format(query=urlencode({'text': query}), page=params['pageno']) + return params @@ -73,10 +76,10 @@ def response(resp): logger.debug('cannot find valid image size: {0}'.format(repr(photo))) continue - if 'id' not in photo['owner']: + if 'ownerNsid' not in photo: continue -# For a bigger thumbnail, keep only the url_z, not the url_n + # For a bigger thumbnail, keep only the url_z, not the url_n if 'n' in photo['sizes']: thumbnail_src = photo['sizes']['n']['url'] elif 'z' in photo['sizes']: @@ -84,20 +87,14 @@ def response(resp): else: thumbnail_src = img_src - url = build_flickr_url(photo['owner']['id'], photo['id']) + url = build_flickr_url(photo['ownerNsid'], photo['id']) title = photo.get('title', '') content = '' +\ - photo['owner']['username'] +\ + photo['username'] +\ '
' - if 'description' in photo: - content = content +\ - '' +\ - photo['description'] +\ - '' - # append result results.append({'url': url, 'title': title, diff --git a/sources/searx/engines/generalfile.py b/sources/searx/engines/generalfile.py index b7d7162..3bb2744 100644 --- a/sources/searx/engines/generalfile.py +++ b/sources/searx/engines/generalfile.py @@ -1,14 +1,16 @@ -## General Files (Files) -# -# @website http://www.general-files.org -# @provide-api no (nothing found) -# -# @using-api no (because nothing found) -# @results HTML (using search portal) -# @stable no (HTML can change) -# @parse url, title, content -# -# @todo detect torrents? +""" + General Files (Files) + + @website http://www.general-files.org + @provide-api no (nothing found) + + @using-api no (because nothing found) + @results HTML (using search portal) + @stable no (HTML can change) + @parse url, title, content + + @todo detect torrents? +""" from lxml import html diff --git a/sources/searx/engines/gigablast.py b/sources/searx/engines/gigablast.py index 8749c32..b852de9 100644 --- a/sources/searx/engines/gigablast.py +++ b/sources/searx/engines/gigablast.py @@ -1,12 +1,14 @@ -## Gigablast (Web) -# -# @website http://gigablast.com -# @provide-api yes (http://gigablast.com/api.html) -# -# @using-api yes -# @results XML -# @stable yes -# @parse url, title, content +""" + Gigablast (Web) + + @website http://gigablast.com + @provide-api yes (http://gigablast.com/api.html) + + @using-api yes + @results XML + @stable yes + @parse url, title, content +""" from urllib import urlencode from cgi import escape @@ -17,7 +19,7 @@ categories = ['general'] paging = True number_of_results = 5 -# search-url +# search-url, invalid HTTPS certificate base_url = 'http://gigablast.com/' search_string = 'search?{query}&n={number_of_results}&s={offset}&xml=1&qh=0' diff --git a/sources/searx/engines/github.py b/sources/searx/engines/github.py index a68aed1..cc1fc47 100644 --- a/sources/searx/engines/github.py +++ b/sources/searx/engines/github.py @@ -1,12 +1,14 @@ -## Github (It) -# -# @website https://github.com/ -# @provide-api yes (https://developer.github.com/v3/) -# -# @using-api yes -# @results JSON -# @stable yes (using api) -# @parse url, title, content +""" + Github (It) + + @website https://github.com/ + @provide-api yes (https://developer.github.com/v3/) + + @using-api yes + @results JSON + @stable yes (using api) + @parse url, title, content +""" from urllib import urlencode from json import loads @@ -37,7 +39,7 @@ def response(resp): search_res = loads(resp.text) # check if items are recieved - if not 'items' in search_res: + if 'items' not in search_res: return [] # parse results diff --git a/sources/searx/engines/google.py b/sources/searx/engines/google.py index 9c76826..0e78a9e 100644 --- a/sources/searx/engines/google.py +++ b/sources/searx/engines/google.py @@ -8,39 +8,126 @@ # @stable no (HTML can change) # @parse url, title, content, suggestion +import re from urllib import urlencode from urlparse import urlparse, parse_qsl from lxml import html from searx.poolrequests import get from searx.engines.xpath import extract_text, extract_url + # engine dependent config categories = ['general'] paging = True language_support = True +use_locale_domain = True + +# based on https://en.wikipedia.org/wiki/List_of_Google_domains and tests +default_hostname = 'www.google.com' + +country_to_hostname = { + 'BG': 'www.google.bg', # Bulgaria + 'CZ': 'www.google.cz', # Czech Republic + 'DE': 'www.google.de', # Germany + 'DK': 'www.google.dk', # Denmark + 'AT': 'www.google.at', # Austria + 'CH': 'www.google.ch', # Switzerland + 'GR': 'www.google.gr', # Greece + 'AU': 'www.google.com.au', # Australia + 'CA': 'www.google.ca', # Canada + 'GB': 'www.google.co.uk', # United Kingdom + 'ID': 'www.google.co.id', # Indonesia + 'IE': 'www.google.ie', # Ireland + 'IN': 'www.google.co.in', # India + 'MY': 'www.google.com.my', # Malaysia + 'NZ': 'www.google.co.nz', # New Zealand + 'PH': 'www.google.com.ph', # Philippines + 'SG': 'www.google.com.sg', # Singapore + # 'US': 'www.google.us', # United State, redirect to .com + 'ZA': 'www.google.co.za', # South Africa + 'AR': 'www.google.com.ar', # Argentina + 'CL': 'www.google.cl', # Chile + 'ES': 'www.google.es', # Span + 'MX': 'www.google.com.mx', # Mexico + 'EE': 'www.google.ee', # Estonia + 'FI': 'www.google.fi', # Finland + 'BE': 'www.google.be', # Belgium + 'FR': 'www.google.fr', # France + 'IL': 'www.google.co.il', # Israel + 'HR': 'www.google.hr', # Croatia + 'HU': 'www.google.hu', # Hungary + 'IT': 'www.google.it', # Italy + 'JP': 'www.google.co.jp', # Japan + 'KR': 'www.google.co.kr', # South Korean + 'LT': 'www.google.lt', # Lithuania + 'LV': 'www.google.lv', # Latvia + 'NO': 'www.google.no', # Norway + 'NL': 'www.google.nl', # Netherlands + 'PL': 'www.google.pl', # Poland + 'BR': 'www.google.com.br', # Brazil + 'PT': 'www.google.pt', # Portugal + 'RO': 'www.google.ro', # Romania + 'RU': 'www.google.ru', # Russia + 'SK': 'www.google.sk', # Slovakia + 'SL': 'www.google.si', # Slovenia (SL -> si) + 'SE': 'www.google.se', # Sweden + 'TH': 'www.google.co.th', # Thailand + 'TR': 'www.google.com.tr', # Turkey + 'UA': 'www.google.com.ua', # Ikraine + # 'CN': 'www.google.cn', # China, only from china ? + 'HK': 'www.google.com.hk', # Hong kong + 'TW': 'www.google.com.tw' # Taiwan +} + +# osm +url_map = 'https://www.openstreetmap.org/'\ + + '?lat={latitude}&lon={longitude}&zoom={zoom}&layers=M' # search-url -google_hostname = 'www.google.com' search_path = '/search' -redirect_path = '/url' -images_path = '/images' -search_url = ('https://' + - google_hostname + +search_url = ('https://{hostname}' + search_path + '?{query}&start={offset}&gbv=1') +# other URLs +map_hostname_start = 'maps.google.' +maps_path = '/maps' +redirect_path = '/url' +images_path = '/images' + # specific xpath variables results_xpath = '//li[@class="g"]' url_xpath = './/h3/a/@href' title_xpath = './/h3' content_xpath = './/span[@class="st"]' +content_misc_xpath = './/div[@class="f slp"]' suggestion_xpath = '//p[@class="_Bmc"]' +# map : detail location +map_address_xpath = './/div[@class="s"]//table//td[2]/span/text()' +map_phone_xpath = './/div[@class="s"]//table//td[2]/span/span' +map_website_url_xpath = 'h3[2]/a/@href' +map_website_title_xpath = 'h3[2]' + +# map : near the location +map_near = 'table[@class="ts"]//tr' +map_near_title = './/h4' +map_near_url = './/h4/a/@href' +map_near_phone = './/span[@class="nobr"]' + +# images images_xpath = './/div/a' image_url_xpath = './@href' image_img_src_xpath = './img/@src' +# property names +# FIXME : no translation +property_address = "Address" +property_phone = "Phone number" + +# cookies pref_cookie = '' +nid_cookie = {} # see https://support.google.com/websearch/answer/873?hl=en @@ -52,8 +139,21 @@ def get_google_pref_cookie(): return pref_cookie +def get_google_nid_cookie(google_hostname): + global nid_cookie + if google_hostname not in nid_cookie: + resp = get('https://' + google_hostname) + nid_cookie[google_hostname] = resp.cookies.get("NID", None) + return nid_cookie[google_hostname] + + # remove google-specific tracking-url -def parse_url(url_string): +def parse_url(url_string, google_hostname): + # sanity check + if url_string is None: + return url_string + + # normal case parsed_url = urlparse(url_string) if (parsed_url.netloc in [google_hostname, ''] and parsed_url.path == redirect_path): @@ -63,20 +163,45 @@ def parse_url(url_string): return url_string +# returns extract_text on the first result selected by the xpath or None +def extract_text_from_dom(result, xpath): + r = result.xpath(xpath) + if len(r) > 0: + return extract_text(r[0]) + return None + + # do search-request def request(query, params): offset = (params['pageno'] - 1) * 10 if params['language'] == 'all': language = 'en' + country = 'US' else: - language = params['language'].replace('_', '-').lower() + language_array = params['language'].lower().split('_') + if len(language_array) == 2: + country = language_array[1] + else: + country = 'US' + language = language_array[0] + ',' + language_array[0] + '-' + country + + if use_locale_domain: + google_hostname = country_to_hostname.get(country.upper(), default_hostname) + else: + google_hostname = default_hostname params['url'] = search_url.format(offset=offset, - query=urlencode({'q': query})) + query=urlencode({'q': query}), + hostname=google_hostname) params['headers']['Accept-Language'] = language - params['cookies']['PREF'] = get_google_pref_cookie() + params['headers']['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' + if google_hostname == default_hostname: + params['cookies']['PREF'] = get_google_pref_cookie() + params['cookies']['NID'] = get_google_nid_cookie(google_hostname) + + params['google_hostname'] = google_hostname return params @@ -85,33 +210,63 @@ def request(query, params): def response(resp): results = [] + # detect google sorry + resp_url = urlparse(resp.url) + if resp_url.netloc == 'sorry.google.com' or resp_url.path == '/sorry/IndexRedirect': + raise RuntimeWarning('sorry.google.com') + + # which hostname ? + google_hostname = resp.search_params.get('google_hostname') + google_url = "https://" + google_hostname + + # convert the text to dom dom = html.fromstring(resp.text) # parse results for result in dom.xpath(results_xpath): title = extract_text(result.xpath(title_xpath)[0]) try: - url = parse_url(extract_url(result.xpath(url_xpath), search_url)) - parsed_url = urlparse(url) - if (parsed_url.netloc == google_hostname - and parsed_url.path == search_path): - # remove the link to google news - continue + url = parse_url(extract_url(result.xpath(url_xpath), google_url), google_hostname) + parsed_url = urlparse(url, google_hostname) + + # map result + if ((parsed_url.netloc == google_hostname and parsed_url.path.startswith(maps_path)) + or (parsed_url.netloc.startswith(map_hostname_start))): + x = result.xpath(map_near) + if len(x) > 0: + # map : near the location + results = results + parse_map_near(parsed_url, x, google_hostname) + else: + # map : detail about a location + results = results + parse_map_detail(parsed_url, result, google_hostname) + + # google news + elif (parsed_url.netloc == google_hostname + and parsed_url.path == search_path): + # skipping news results + pass # images result - if (parsed_url.netloc == google_hostname - and parsed_url.path == images_path): + elif (parsed_url.netloc == google_hostname + and parsed_url.path == images_path): # only thumbnail image provided, # so skipping image results - # results = results + parse_images(result) + # results = results + parse_images(result, google_hostname) pass + else: # normal result - content = extract_text(result.xpath(content_xpath)[0]) + content = extract_text_from_dom(result, content_xpath) + if content is None: + continue + content_misc = extract_text_from_dom(result, content_misc_xpath) + if content_misc is not None: + content = content_misc + "
" + content # append result results.append({'url': url, 'title': title, - 'content': content}) + 'content': content + }) except: continue @@ -124,10 +279,10 @@ def response(resp): return results -def parse_images(result): +def parse_images(result, google_hostname): results = [] for image in result.xpath(images_xpath): - url = parse_url(extract_text(image.xpath(image_url_xpath)[0])) + url = parse_url(extract_text(image.xpath(image_url_xpath)[0]), google_hostname) img_src = extract_text(image.xpath(image_img_src_xpath)[0]) # append result @@ -135,6 +290,77 @@ def parse_images(result): 'title': '', 'content': '', 'img_src': img_src, - 'template': 'images.html'}) + 'template': 'images.html' + }) return results + + +def parse_map_near(parsed_url, x, google_hostname): + results = [] + + for result in x: + title = extract_text_from_dom(result, map_near_title) + url = parse_url(extract_text_from_dom(result, map_near_url), google_hostname) + attributes = [] + phone = extract_text_from_dom(result, map_near_phone) + add_attributes(attributes, property_phone, phone, 'tel:' + phone) + results.append({'title': title, + 'url': url, + 'content': attributes_to_html(attributes) + }) + + return results + + +def parse_map_detail(parsed_url, result, google_hostname): + results = [] + + # try to parse the geoloc + m = re.search('@([0-9\.]+),([0-9\.]+),([0-9]+)', parsed_url.path) + if m is None: + m = re.search('ll\=([0-9\.]+),([0-9\.]+)\&z\=([0-9]+)', parsed_url.query) + + if m is not None: + # geoloc found (ignored) + lon = float(m.group(2)) # noqa + lat = float(m.group(1)) # noqa + zoom = int(m.group(3)) # noqa + + # attributes + attributes = [] + address = extract_text_from_dom(result, map_address_xpath) + phone = extract_text_from_dom(result, map_phone_xpath) + add_attributes(attributes, property_address, address, 'geo:' + str(lat) + ',' + str(lon)) + add_attributes(attributes, property_phone, phone, 'tel:' + phone) + + # title / content / url + website_title = extract_text_from_dom(result, map_website_title_xpath) + content = extract_text_from_dom(result, content_xpath) + website_url = parse_url(extract_text_from_dom(result, map_website_url_xpath), google_hostname) + + # add a result if there is a website + if website_url is not None: + results.append({'title': website_title, + 'content': (content + '
' if content is not None else '') + + attributes_to_html(attributes), + 'url': website_url + }) + + return results + + +def add_attributes(attributes, name, value, url): + if value is not None and len(value) > 0: + attributes.append({'label': name, 'value': value, 'url': url}) + + +def attributes_to_html(attributes): + retval = '' + for a in attributes: + value = a.get('value') + if 'url' in a: + value = '' + value + '' + retval = retval + '' + retval = retval + '
' + a.get('label') + '' + value + '
' + return retval diff --git a/sources/searx/engines/google_images.py b/sources/searx/engines/google_images.py index 1c0e62f..85963a1 100644 --- a/sources/searx/engines/google_images.py +++ b/sources/searx/engines/google_images.py @@ -1,13 +1,15 @@ -## Google (Images) -# -# @website https://www.google.com -# @provide-api yes (https://developers.google.com/web-search/docs/), -# deprecated! -# -# @using-api yes -# @results JSON -# @stable yes (but deprecated) -# @parse url, title, img_src +""" + Google (Images) + + @website https://www.google.com + @provide-api yes (https://developers.google.com/web-search/docs/), + deprecated! + + @using-api yes + @results JSON + @stable yes (but deprecated) + @parse url, title, img_src +""" from urllib import urlencode, unquote from json import loads @@ -56,6 +58,9 @@ def response(resp): continue thumbnail_src = result['tbUrl'] + # http to https + thumbnail_src = thumbnail_src.replace("http://", "https://") + # append result results.append({'url': href, 'title': title, diff --git a/sources/searx/engines/google_news.py b/sources/searx/engines/google_news.py index 3e4371b..95d15cf 100644 --- a/sources/searx/engines/google_news.py +++ b/sources/searx/engines/google_news.py @@ -1,13 +1,15 @@ -## Google (News) -# -# @website https://www.google.com -# @provide-api yes (https://developers.google.com/web-search/docs/), -# deprecated! -# -# @using-api yes -# @results JSON -# @stable yes (but deprecated) -# @parse url, title, content, publishedDate +""" + Google (News) + + @website https://www.google.com + @provide-api yes (https://developers.google.com/web-search/docs/), + deprecated! + + @using-api yes + @results JSON + @stable yes (but deprecated) + @parse url, title, content, publishedDate +""" from urllib import urlencode from json import loads diff --git a/sources/searx/engines/json_engine.py b/sources/searx/engines/json_engine.py index 708b999..5525b7f 100644 --- a/sources/searx/engines/json_engine.py +++ b/sources/searx/engines/json_engine.py @@ -6,7 +6,7 @@ search_url = None url_query = None content_query = None title_query = None -#suggestion_xpath = '' +# suggestion_xpath = '' def iterate(iterable): diff --git a/sources/searx/engines/kickass.py b/sources/searx/engines/kickass.py index ea7f17c..4c5d240 100644 --- a/sources/searx/engines/kickass.py +++ b/sources/searx/engines/kickass.py @@ -1,12 +1,14 @@ -## Kickass Torrent (Videos, Music, Files) -# -# @website https://kickass.so -# @provide-api no (nothing found) -# -# @using-api no -# @results HTML (using search portal) -# @stable yes (HTML can change) -# @parse url, title, content, seed, leech, magnetlink +""" + Kickass Torrent (Videos, Music, Files) + + @website https://kickass.so + @provide-api no (nothing found) + + @using-api no + @results HTML (using search portal) + @stable yes (HTML can change) + @parse url, title, content, seed, leech, magnetlink +""" from urlparse import urljoin from cgi import escape @@ -34,10 +36,6 @@ def request(query, params): params['url'] = search_url.format(search_term=quote(query), pageno=params['pageno']) - # FIX: SSLError: hostname 'kickass.so' - # doesn't match either of '*.kickass.to', 'kickass.to' - params['verify'] = False - return params diff --git a/sources/searx/engines/mediawiki.py b/sources/searx/engines/mediawiki.py index 8ca32c6..9fb72e8 100644 --- a/sources/searx/engines/mediawiki.py +++ b/sources/searx/engines/mediawiki.py @@ -1,14 +1,16 @@ -## general mediawiki-engine (Web) -# -# @website websites built on mediawiki (https://www.mediawiki.org) -# @provide-api yes (http://www.mediawiki.org/wiki/API:Search) -# -# @using-api yes -# @results JSON -# @stable yes -# @parse url, title -# -# @todo content +""" + general mediawiki-engine (Web) + + @website websites built on mediawiki (https://www.mediawiki.org) + @provide-api yes (http://www.mediawiki.org/wiki/API:Search) + + @using-api yes + @results JSON + @stable yes + @parse url, title + + @todo content +""" from json import loads from string import Formatter diff --git a/sources/searx/engines/mixcloud.py b/sources/searx/engines/mixcloud.py index 676e6f8..312d297 100644 --- a/sources/searx/engines/mixcloud.py +++ b/sources/searx/engines/mixcloud.py @@ -1,12 +1,14 @@ -## Mixcloud (Music) -# -# @website https://http://www.mixcloud.com/ -# @provide-api yes (http://www.mixcloud.com/developers/ -# -# @using-api yes -# @results JSON -# @stable yes -# @parse url, title, content, embedded, publishedDate +""" + Mixcloud (Music) + + @website https://http://www.mixcloud.com/ + @provide-api yes (http://www.mixcloud.com/developers/ + + @using-api yes + @results JSON + @stable yes + @parse url, title, content, embedded, publishedDate +""" from json import loads from urllib import urlencode @@ -17,7 +19,7 @@ categories = ['music'] paging = True # search-url -url = 'http://api.mixcloud.com/' +url = 'https://api.mixcloud.com/' search_url = url + 'search/?{query}&type=cloudcast&limit=10&offset={offset}' embedded_url = '' +base_youtube_url = 'https://www.youtube.com/watch?v=' + # do search-request def request(query, params): - index = (params['pageno'] - 1) * 5 + 1 - params['url'] = search_url.format(query=urlencode({'q': query}), - index=index) + api_key=api_key) # add language tag if specified if params['language'] != 'all': - params['url'] += '&lr=' + params['language'].split('_')[0] + params['url'] += '&relevanceLanguage=' + params['language'].split('_')[0] return params @@ -47,36 +48,25 @@ def response(resp): search_results = loads(resp.text) # return empty array if there are no results - if not 'feed' in search_results: + if 'items' not in search_results: return [] - feed = search_results['feed'] - # parse results - for result in feed['entry']: - url = [x['href'] for x in result['link'] if x['type'] == 'text/html'] + for result in search_results['items']: + videoid = result['id']['videoId'] - if not url: - continue - - # remove tracking - url = url[0].replace('feature=youtube_gdata', '') - if url.endswith('&'): - url = url[:-1] - - videoid = url[32:] - - title = result['title']['$t'] + title = result['snippet']['title'] content = '' thumbnail = '' - pubdate = result['published']['$t'] + pubdate = result['snippet']['publishedAt'] publishedDate = parser.parse(pubdate) - if 'media$thumbnail' in result['media$group']: - thumbnail = result['media$group']['media$thumbnail'][0]['url'] + thumbnail = result['snippet']['thumbnails']['high']['url'] - content = result['content']['$t'] + content = result['snippet']['description'] + + url = base_youtube_url + videoid embedded = embedded_url.format(videoid=videoid) diff --git a/sources/searx/engines/youtube_noapi.py b/sources/searx/engines/youtube_noapi.py new file mode 100644 index 0000000..401fca4 --- /dev/null +++ b/sources/searx/engines/youtube_noapi.py @@ -0,0 +1,81 @@ +# Youtube (Videos) +# +# @website https://www.youtube.com/ +# @provide-api yes (https://developers.google.com/apis-explorer/#p/youtube/v3/youtube.search.list) +# +# @using-api no +# @results HTML +# @stable no +# @parse url, title, content, publishedDate, thumbnail, embedded + +from urllib import quote_plus +from lxml import html +from searx.engines.xpath import extract_text +from searx.utils import list_get + +# engine dependent config +categories = ['videos', 'music'] +paging = True +language_support = False + +# search-url +base_url = 'https://www.youtube.com/results' +search_url = base_url + '?search_query={query}&page={page}' + +embedded_url = '' + +base_youtube_url = 'https://www.youtube.com/watch?v=' + +# specific xpath variables +results_xpath = "//ol/li/div[contains(@class, 'yt-lockup yt-lockup-tile yt-lockup-video vve-check')]" +url_xpath = './/h3/a/@href' +title_xpath = './/div[@class="yt-lockup-content"]/h3/a' +content_xpath = './/div[@class="yt-lockup-content"]/div[@class="yt-lockup-description yt-ui-ellipsis yt-ui-ellipsis-2"]' + + +# returns extract_text on the first result selected by the xpath or None +def extract_text_from_dom(result, xpath): + r = result.xpath(xpath) + if len(r) > 0: + return extract_text(r[0]) + return None + + +# do search-request +def request(query, params): + params['url'] = search_url.format(query=quote_plus(query), + page=params['pageno']) + + return params + + +# get response from search-request +def response(resp): + results = [] + + dom = html.fromstring(resp.text) + + # parse results + for result in dom.xpath(results_xpath): + videoid = list_get(result.xpath('@data-context-item-id'), 0) + if videoid is not None: + url = base_youtube_url + videoid + thumbnail = 'https://i.ytimg.com/vi/' + videoid + '/hqdefault.jpg' + + title = extract_text_from_dom(result, title_xpath) or videoid + content = extract_text_from_dom(result, content_xpath) + + embedded = embedded_url.format(videoid=videoid) + + # append result + results.append({'url': url, + 'title': title, + 'content': content, + 'template': 'videos.html', + 'embedded': embedded, + 'thumbnail': thumbnail}) + + # return results + return results diff --git a/sources/searx/plugins/__init__.py b/sources/searx/plugins/__init__.py new file mode 100644 index 0000000..a4d7ad8 --- /dev/null +++ b/sources/searx/plugins/__init__.py @@ -0,0 +1,77 @@ +''' +searx is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +searx is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with searx. If not, see < http://www.gnu.org/licenses/ >. + +(C) 2015 by Adam Tauber, +''' +from sys import exit +from searx import logger + +logger = logger.getChild('plugins') + +from searx.plugins import (https_rewrite, + self_info, + search_on_category_select, + tracker_url_remover) + +required_attrs = (('name', str), + ('description', str), + ('default_on', bool)) + +optional_attrs = (('js_dependencies', tuple), + ('css_dependencies', tuple)) + + +class Plugin(): + default_on = False + name = 'Default plugin' + description = 'Default plugin description' + + +class PluginStore(): + + def __init__(self): + self.plugins = [] + + def __iter__(self): + for plugin in self.plugins: + yield plugin + + def register(self, *plugins): + for plugin in plugins: + for plugin_attr, plugin_attr_type in required_attrs: + if not hasattr(plugin, plugin_attr) or not isinstance(getattr(plugin, plugin_attr), plugin_attr_type): + logger.critical('missing attribute "{0}", cannot load plugin: {1}'.format(plugin_attr, plugin)) + exit(3) + for plugin_attr, plugin_attr_type in optional_attrs: + if not hasattr(plugin, plugin_attr) or not isinstance(getattr(plugin, plugin_attr), plugin_attr_type): + setattr(plugin, plugin_attr, plugin_attr_type()) + plugin.id = plugin.name.replace(' ', '_') + self.plugins.append(plugin) + + def call(self, plugin_type, request, *args, **kwargs): + ret = True + for plugin in request.user_plugins: + if hasattr(plugin, plugin_type): + ret = getattr(plugin, plugin_type)(request, *args, **kwargs) + if not ret: + break + + return ret + + +plugins = PluginStore() +plugins.register(https_rewrite) +plugins.register(self_info) +plugins.register(search_on_category_select) +plugins.register(tracker_url_remover) diff --git a/sources/searx/https_rewrite.py b/sources/searx/plugins/https_rewrite.py similarity index 90% rename from sources/searx/https_rewrite.py rename to sources/searx/plugins/https_rewrite.py index 71aec1c..a24f15a 100644 --- a/sources/searx/https_rewrite.py +++ b/sources/searx/plugins/https_rewrite.py @@ -18,11 +18,22 @@ along with searx. If not, see < http://www.gnu.org/licenses/ >. import re from urlparse import urlparse from lxml import etree -from os import listdir +from os import listdir, environ from os.path import isfile, isdir, join -from searx import logger +from searx.plugins import logger +from flask.ext.babel import gettext +from searx import searx_dir +name = "HTTPS rewrite" +description = gettext('Rewrite HTTP links to HTTPS if possible') +default_on = True + +if 'SEARX_HTTPS_REWRITE_PATH' in environ: + rules_path = environ['SEARX_rules_path'] +else: + rules_path = join(searx_dir, 'plugins/https_rules') + logger = logger.getChild("https_rewrite") # https://gitweb.torproject.org/\ @@ -33,7 +44,7 @@ https_rules = [] # load single ruleset from a xml file -def load_single_https_ruleset(filepath): +def load_single_https_ruleset(rules_path): ruleset = () # init parser @@ -41,7 +52,7 @@ def load_single_https_ruleset(filepath): # load and parse xml-file try: - tree = etree.parse(filepath, parser) + tree = etree.parse(rules_path, parser) except: # TODO, error message return () @@ -207,3 +218,13 @@ def https_url_rewrite(result): # target has matched, do not search over the other rules break return result + + +def on_result(request, ctx): + result = ctx['result'] + if result['parsed_url'].scheme == 'http': + https_url_rewrite(result) + return True + + +load_https_rules(rules_path) diff --git a/sources/searx/https_rules/00README b/sources/searx/plugins/https_rules/00README similarity index 100% rename from sources/searx/https_rules/00README rename to sources/searx/plugins/https_rules/00README diff --git a/sources/searx/https_rules/Bing.xml b/sources/searx/plugins/https_rules/Bing.xml similarity index 100% rename from sources/searx/https_rules/Bing.xml rename to sources/searx/plugins/https_rules/Bing.xml diff --git a/sources/searx/https_rules/Dailymotion.xml b/sources/searx/plugins/https_rules/Dailymotion.xml similarity index 100% rename from sources/searx/https_rules/Dailymotion.xml rename to sources/searx/plugins/https_rules/Dailymotion.xml diff --git a/sources/searx/https_rules/Deviantart.xml b/sources/searx/plugins/https_rules/Deviantart.xml similarity index 100% rename from sources/searx/https_rules/Deviantart.xml rename to sources/searx/plugins/https_rules/Deviantart.xml diff --git a/sources/searx/https_rules/DuckDuckGo.xml b/sources/searx/plugins/https_rules/DuckDuckGo.xml similarity index 100% rename from sources/searx/https_rules/DuckDuckGo.xml rename to sources/searx/plugins/https_rules/DuckDuckGo.xml diff --git a/sources/searx/https_rules/Flickr.xml b/sources/searx/plugins/https_rules/Flickr.xml similarity index 100% rename from sources/searx/https_rules/Flickr.xml rename to sources/searx/plugins/https_rules/Flickr.xml diff --git a/sources/searx/https_rules/Github-Pages.xml b/sources/searx/plugins/https_rules/Github-Pages.xml similarity index 100% rename from sources/searx/https_rules/Github-Pages.xml rename to sources/searx/plugins/https_rules/Github-Pages.xml diff --git a/sources/searx/https_rules/Github.xml b/sources/searx/plugins/https_rules/Github.xml similarity index 100% rename from sources/searx/https_rules/Github.xml rename to sources/searx/plugins/https_rules/Github.xml diff --git a/sources/searx/https_rules/Google-mismatches.xml b/sources/searx/plugins/https_rules/Google-mismatches.xml similarity index 100% rename from sources/searx/https_rules/Google-mismatches.xml rename to sources/searx/plugins/https_rules/Google-mismatches.xml diff --git a/sources/searx/https_rules/Google.org.xml b/sources/searx/plugins/https_rules/Google.org.xml similarity index 100% rename from sources/searx/https_rules/Google.org.xml rename to sources/searx/plugins/https_rules/Google.org.xml diff --git a/sources/searx/https_rules/GoogleAPIs.xml b/sources/searx/plugins/https_rules/GoogleAPIs.xml similarity index 100% rename from sources/searx/https_rules/GoogleAPIs.xml rename to sources/searx/plugins/https_rules/GoogleAPIs.xml diff --git a/sources/searx/https_rules/GoogleCanada.xml b/sources/searx/plugins/https_rules/GoogleCanada.xml similarity index 100% rename from sources/searx/https_rules/GoogleCanada.xml rename to sources/searx/plugins/https_rules/GoogleCanada.xml diff --git a/sources/searx/https_rules/GoogleImages.xml b/sources/searx/plugins/https_rules/GoogleImages.xml similarity index 100% rename from sources/searx/https_rules/GoogleImages.xml rename to sources/searx/plugins/https_rules/GoogleImages.xml diff --git a/sources/searx/https_rules/GoogleMainSearch.xml b/sources/searx/plugins/https_rules/GoogleMainSearch.xml similarity index 100% rename from sources/searx/https_rules/GoogleMainSearch.xml rename to sources/searx/plugins/https_rules/GoogleMainSearch.xml diff --git a/sources/searx/https_rules/GoogleMaps.xml b/sources/searx/plugins/https_rules/GoogleMaps.xml similarity index 100% rename from sources/searx/https_rules/GoogleMaps.xml rename to sources/searx/plugins/https_rules/GoogleMaps.xml diff --git a/sources/searx/https_rules/GoogleMelange.xml b/sources/searx/plugins/https_rules/GoogleMelange.xml similarity index 100% rename from sources/searx/https_rules/GoogleMelange.xml rename to sources/searx/plugins/https_rules/GoogleMelange.xml diff --git a/sources/searx/https_rules/GoogleSearch.xml b/sources/searx/plugins/https_rules/GoogleSearch.xml similarity index 100% rename from sources/searx/https_rules/GoogleSearch.xml rename to sources/searx/plugins/https_rules/GoogleSearch.xml diff --git a/sources/searx/https_rules/GoogleServices.xml b/sources/searx/plugins/https_rules/GoogleServices.xml similarity index 100% rename from sources/searx/https_rules/GoogleServices.xml rename to sources/searx/plugins/https_rules/GoogleServices.xml diff --git a/sources/searx/https_rules/GoogleShopping.xml b/sources/searx/plugins/https_rules/GoogleShopping.xml similarity index 100% rename from sources/searx/https_rules/GoogleShopping.xml rename to sources/searx/plugins/https_rules/GoogleShopping.xml diff --git a/sources/searx/https_rules/GoogleSorry.xml b/sources/searx/plugins/https_rules/GoogleSorry.xml similarity index 100% rename from sources/searx/https_rules/GoogleSorry.xml rename to sources/searx/plugins/https_rules/GoogleSorry.xml diff --git a/sources/searx/https_rules/GoogleTranslate.xml b/sources/searx/plugins/https_rules/GoogleTranslate.xml similarity index 100% rename from sources/searx/https_rules/GoogleTranslate.xml rename to sources/searx/plugins/https_rules/GoogleTranslate.xml diff --git a/sources/searx/https_rules/GoogleVideos.xml b/sources/searx/plugins/https_rules/GoogleVideos.xml similarity index 100% rename from sources/searx/https_rules/GoogleVideos.xml rename to sources/searx/plugins/https_rules/GoogleVideos.xml diff --git a/sources/searx/https_rules/GoogleWatchBlog.xml b/sources/searx/plugins/https_rules/GoogleWatchBlog.xml similarity index 100% rename from sources/searx/https_rules/GoogleWatchBlog.xml rename to sources/searx/plugins/https_rules/GoogleWatchBlog.xml diff --git a/sources/searx/https_rules/Google_App_Engine.xml b/sources/searx/plugins/https_rules/Google_App_Engine.xml similarity index 100% rename from sources/searx/https_rules/Google_App_Engine.xml rename to sources/searx/plugins/https_rules/Google_App_Engine.xml diff --git a/sources/searx/https_rules/Googleplex.com.xml b/sources/searx/plugins/https_rules/Googleplex.com.xml similarity index 100% rename from sources/searx/https_rules/Googleplex.com.xml rename to sources/searx/plugins/https_rules/Googleplex.com.xml diff --git a/sources/searx/https_rules/OpenStreetMap.xml b/sources/searx/plugins/https_rules/OpenStreetMap.xml similarity index 100% rename from sources/searx/https_rules/OpenStreetMap.xml rename to sources/searx/plugins/https_rules/OpenStreetMap.xml diff --git a/sources/searx/https_rules/Rawgithub.com.xml b/sources/searx/plugins/https_rules/Rawgithub.com.xml similarity index 100% rename from sources/searx/https_rules/Rawgithub.com.xml rename to sources/searx/plugins/https_rules/Rawgithub.com.xml diff --git a/sources/searx/https_rules/Soundcloud.xml b/sources/searx/plugins/https_rules/Soundcloud.xml similarity index 100% rename from sources/searx/https_rules/Soundcloud.xml rename to sources/searx/plugins/https_rules/Soundcloud.xml diff --git a/sources/searx/https_rules/ThePirateBay.xml b/sources/searx/plugins/https_rules/ThePirateBay.xml similarity index 100% rename from sources/searx/https_rules/ThePirateBay.xml rename to sources/searx/plugins/https_rules/ThePirateBay.xml diff --git a/sources/searx/https_rules/Torproject.xml b/sources/searx/plugins/https_rules/Torproject.xml similarity index 100% rename from sources/searx/https_rules/Torproject.xml rename to sources/searx/plugins/https_rules/Torproject.xml diff --git a/sources/searx/https_rules/Twitter.xml b/sources/searx/plugins/https_rules/Twitter.xml similarity index 100% rename from sources/searx/https_rules/Twitter.xml rename to sources/searx/plugins/https_rules/Twitter.xml diff --git a/sources/searx/https_rules/Vimeo.xml b/sources/searx/plugins/https_rules/Vimeo.xml similarity index 100% rename from sources/searx/https_rules/Vimeo.xml rename to sources/searx/plugins/https_rules/Vimeo.xml diff --git a/sources/searx/https_rules/WikiLeaks.xml b/sources/searx/plugins/https_rules/WikiLeaks.xml similarity index 100% rename from sources/searx/https_rules/WikiLeaks.xml rename to sources/searx/plugins/https_rules/WikiLeaks.xml diff --git a/sources/searx/https_rules/Wikimedia.xml b/sources/searx/plugins/https_rules/Wikimedia.xml similarity index 100% rename from sources/searx/https_rules/Wikimedia.xml rename to sources/searx/plugins/https_rules/Wikimedia.xml diff --git a/sources/searx/https_rules/Yahoo.xml b/sources/searx/plugins/https_rules/Yahoo.xml similarity index 100% rename from sources/searx/https_rules/Yahoo.xml rename to sources/searx/plugins/https_rules/Yahoo.xml diff --git a/sources/searx/https_rules/YouTube.xml b/sources/searx/plugins/https_rules/YouTube.xml similarity index 100% rename from sources/searx/https_rules/YouTube.xml rename to sources/searx/plugins/https_rules/YouTube.xml diff --git a/sources/searx/plugins/search_on_category_select.py b/sources/searx/plugins/search_on_category_select.py new file mode 100644 index 0000000..a166702 --- /dev/null +++ b/sources/searx/plugins/search_on_category_select.py @@ -0,0 +1,23 @@ +''' +searx is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +searx is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with searx. If not, see < http://www.gnu.org/licenses/ >. + +(C) 2015 by Adam Tauber, +''' +from flask.ext.babel import gettext +name = gettext('Search on category select') +description = gettext('Perform search immediately if a category selected. ' + 'Disable to select multiple categories. (JavaScript required)') +default_on = True + +js_dependencies = ('js/search_on_category_select.js',) diff --git a/sources/searx/plugins/self_info.py b/sources/searx/plugins/self_info.py new file mode 100644 index 0000000..5ca9945 --- /dev/null +++ b/sources/searx/plugins/self_info.py @@ -0,0 +1,44 @@ +''' +searx is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +searx is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with searx. If not, see < http://www.gnu.org/licenses/ >. + +(C) 2015 by Adam Tauber, +''' +from flask.ext.babel import gettext +import re +name = "Self Informations" +description = gettext('Displays your IP if the query is "ip" and your user agent if the query contains "user agent".') +default_on = True + + +# Self User Agent regex +p = re.compile('.*user[ -]agent.*', re.IGNORECASE) + + +# attach callback to the post search hook +# request: flask request object +# ctx: the whole local context of the pre search hook +def post_search(request, ctx): + if ctx['search'].query == 'ip': + x_forwarded_for = request.headers.getlist("X-Forwarded-For") + if x_forwarded_for: + ip = x_forwarded_for[0] + else: + ip = request.remote_addr + ctx['search'].answers.clear() + ctx['search'].answers.add(ip) + elif p.match(ctx['search'].query): + ua = request.user_agent + ctx['search'].answers.clear() + ctx['search'].answers.add(ua) + return True diff --git a/sources/searx/plugins/tracker_url_remover.py b/sources/searx/plugins/tracker_url_remover.py new file mode 100644 index 0000000..ed71c94 --- /dev/null +++ b/sources/searx/plugins/tracker_url_remover.py @@ -0,0 +1,44 @@ +''' +searx is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +searx is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with searx. If not, see < http://www.gnu.org/licenses/ >. + +(C) 2015 by Adam Tauber, +''' + +from flask.ext.babel import gettext +import re +from urlparse import urlunparse + +regexes = {re.compile(r'utm_[^&]+&?'), + re.compile(r'(wkey|wemail)[^&]+&?'), + re.compile(r'&$')} + +name = gettext('Tracker URL remover') +description = gettext('Remove trackers arguments from the returned URL') +default_on = True + + +def on_result(request, ctx): + query = ctx['result']['parsed_url'].query + + if query == "": + return True + + for reg in regexes: + query = reg.sub('', query) + + if query != ctx['result']['parsed_url'].query: + ctx['result']['parsed_url'] = ctx['result']['parsed_url']._replace(query=query) + ctx['result']['url'] = urlunparse(ctx['result']['parsed_url']) + + return True diff --git a/sources/searx/poolrequests.py b/sources/searx/poolrequests.py index 65853c2..c44bdc7 100644 --- a/sources/searx/poolrequests.py +++ b/sources/searx/poolrequests.py @@ -1,20 +1,63 @@ import requests +from itertools import cycle +from searx import settings -the_http_adapter = requests.adapters.HTTPAdapter(pool_connections=100) -the_https_adapter = requests.adapters.HTTPAdapter(pool_connections=100) +class HTTPAdapterWithConnParams(requests.adapters.HTTPAdapter): + + def __init__(self, pool_connections=requests.adapters.DEFAULT_POOLSIZE, + pool_maxsize=requests.adapters.DEFAULT_POOLSIZE, + max_retries=requests.adapters.DEFAULT_RETRIES, + pool_block=requests.adapters.DEFAULT_POOLBLOCK, + **conn_params): + if max_retries == requests.adapters.DEFAULT_RETRIES: + self.max_retries = requests.adapters.Retry(0, read=False) + else: + self.max_retries = requests.adapters.Retry.from_int(max_retries) + self.config = {} + self.proxy_manager = {} + + super(requests.adapters.HTTPAdapter, self).__init__() + + self._pool_connections = pool_connections + self._pool_maxsize = pool_maxsize + self._pool_block = pool_block + self._conn_params = conn_params + + self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block, **conn_params) + + def __setstate__(self, state): + # Can't handle by adding 'proxy_manager' to self.__attrs__ because + # because self.poolmanager uses a lambda function, which isn't pickleable. + self.proxy_manager = {} + self.config = {} + + for attr, value in state.items(): + setattr(self, attr, value) + + self.init_poolmanager(self._pool_connections, self._pool_maxsize, + block=self._pool_block, **self._conn_params) + + +if settings['outgoing'].get('source_ips'): + http_adapters = cycle(HTTPAdapterWithConnParams(pool_connections=100, source_address=(source_ip, 0)) + for source_ip in settings['outgoing']['source_ips']) + https_adapters = cycle(HTTPAdapterWithConnParams(pool_connections=100, source_address=(source_ip, 0)) + for source_ip in settings['outgoing']['source_ips']) +else: + http_adapters = cycle((HTTPAdapterWithConnParams(pool_connections=100), )) + https_adapters = cycle((HTTPAdapterWithConnParams(pool_connections=100), )) class SessionSinglePool(requests.Session): def __init__(self): - global the_https_adapter, the_http_adapter super(SessionSinglePool, self).__init__() # reuse the same adapters self.adapters.clear() - self.mount('https://', the_https_adapter) - self.mount('http://', the_http_adapter) + self.mount('https://', next(https_adapters)) + self.mount('http://', next(http_adapters)) def close(self): """Call super, but clear adapters since there are managed globaly""" @@ -23,8 +66,10 @@ class SessionSinglePool(requests.Session): def request(method, url, **kwargs): - """same as requests/requests/api.py request(...) except it use SessionSinglePool""" + """same as requests/requests/api.py request(...) except it use SessionSinglePool and force proxies""" + global settings session = SessionSinglePool() + kwargs['proxies'] = settings['outgoing'].get('proxies', None) response = session.request(method=method, url=url, **kwargs) session.close() return response diff --git a/sources/searx/search.py b/sources/searx/search.py index 83163d1..8991712 100644 --- a/sources/searx/search.py +++ b/sources/searx/search.py @@ -23,6 +23,7 @@ from operator import itemgetter from Queue import Queue from time import time from urlparse import urlparse, unquote +from searx import settings from searx.engines import ( categories, engines ) @@ -205,6 +206,10 @@ def score_results(results): # if there is no duplicate found, append result else: res['score'] = score + # if the result has no scheme, use http as default + if res['parsed_url'].scheme == '': + res['parsed_url'] = res['parsed_url']._replace(scheme="http") + results.append(res) results = sorted(results, key=itemgetter('score'), reverse=True) @@ -237,7 +242,7 @@ def score_results(results): for k in categoryPositions: v = categoryPositions[k]['index'] if v >= index: - categoryPositions[k]['index'] = v+1 + categoryPositions[k]['index'] = v + 1 # update this category current['count'] -= 1 @@ -306,7 +311,7 @@ def merge_infoboxes(infoboxes): if add_infobox: results.append(infobox) - infoboxes_id[infobox_id] = len(results)-1 + infoboxes_id[infobox_id] = len(results) - 1 return results @@ -329,8 +334,8 @@ class Search(object): self.blocked_engines = get_blocked_engines(engines, request.cookies) self.results = [] - self.suggestions = [] - self.answers = [] + self.suggestions = set() + self.answers = set() self.infoboxes = [] self.request_data = {} @@ -382,9 +387,19 @@ class Search(object): # otherwise, using defined categories to # calculate which engines should be used else: - # set used categories + # set categories/engines + load_default_categories = True for pd_name, pd in self.request_data.items(): - if pd_name.startswith('category_'): + if pd_name == 'categories': + self.categories.extend(categ for categ in map(unicode.strip, pd.split(',')) if categ in categories) + elif pd_name == 'engines': + pd_engines = [{'category': engines[engine].categories[0], + 'name': engine} + for engine in map(unicode.strip, pd.split(',')) if engine in engines] + if pd_engines: + self.engines.extend(pd_engines) + load_default_categories = False + elif pd_name.startswith('category_'): category = pd_name[9:] # if category is not found in list, skip @@ -398,6 +413,12 @@ class Search(object): # remove category from list if property is set to 'off' self.categories.remove(category) + if not load_default_categories: + if not self.categories: + self.categories = list(set(engine['category'] + for engine in self.engines)) + return + # if no category is specified for this search, # using user-defined default-configuration which # (is stored in cookie) @@ -429,9 +450,6 @@ class Search(object): requests = [] results_queue = Queue() results = {} - suggestions = set() - answers = set() - infoboxes = [] # increase number of searches number_of_searches += 1 @@ -462,12 +480,17 @@ class Search(object): request_params['category'] = selected_engine['category'] request_params['started'] = time() request_params['pageno'] = self.pageno - request_params['language'] = self.lang + + if hasattr(engine, 'language') and engine.language: + request_params['language'] = engine.language + else: + request_params['language'] = self.lang + try: # 0 = None, 1 = Moderate, 2 = Strict - request_params['safesearch'] = int(request.cookies.get('safesearch', 1)) - except ValueError: - request_params['safesearch'] = 1 + request_params['safesearch'] = int(request.cookies.get('safesearch')) + except Exception: + request_params['safesearch'] = settings['search']['safe_search'] # update request parameters dependent on # search-engine (contained in engines folder) @@ -511,7 +534,7 @@ class Search(object): selected_engine['name'])) if not requests: - return results, suggestions, answers, infoboxes + return self # send all search-request threaded_requests(requests) @@ -519,19 +542,19 @@ class Search(object): engine_name, engine_results = results_queue.get_nowait() # TODO type checks - [suggestions.add(x['suggestion']) + [self.suggestions.add(x['suggestion']) for x in list(engine_results) if 'suggestion' in x and engine_results.remove(x) is None] - [answers.add(x['answer']) + [self.answers.add(x['answer']) for x in list(engine_results) if 'answer' in x and engine_results.remove(x) is None] - infoboxes.extend(x for x in list(engine_results) - if 'infobox' in x - and engine_results.remove(x) is None) + self.infoboxes.extend(x for x in list(engine_results) + if 'infobox' in x + and engine_results.remove(x) is None) results[engine_name] = engine_results @@ -541,16 +564,16 @@ class Search(object): engines[engine_name].stats['result_count'] += len(engine_results) # score results and remove duplications - results = score_results(results) + self.results = score_results(results) # merge infoboxes according to their ids - infoboxes = merge_infoboxes(infoboxes) + self.infoboxes = merge_infoboxes(self.infoboxes) # update engine stats, using calculated score - for result in results: + for result in self.results: for res_engine in result['engines']: engines[result['engine']]\ .stats['score_count'] += result['score'] # return results, suggestions, answers and infoboxes - return results, suggestions, answers, infoboxes + return self diff --git a/sources/searx/settings.yml b/sources/searx/settings.yml index 8e2833e..ffc3502 100644 --- a/sources/searx/settings.yml +++ b/sources/searx/settings.yml @@ -1,16 +1,37 @@ +general: + debug : False # Debug mode, only for development + +search: + safe_search : 0 # Filter results. 0: None, 1: Moderate, 2: Strict + autocomplete : "" # Existing autocomplete backends: "dbpedia", "duckduckgo", "google", "startpage", "wikipedia" - leave blank to turn it off by default + server: port : 8888 + bind_address : "127.0.0.1" # address to listen on secret_key : "ultrasecretkey" # change this! - debug : False # Debug mode, only for development - request_timeout : 2.0 # seconds base_url : False # Set custom base_url. Possible values: False or "https://your.custom.host/location/" + image_proxy : False # Proxying image results through searx + +ui: themes_path : "" # Custom ui themes path - leave it blank if you didn't change default_theme : oscar # ui theme - https_rewrite : True # Force rewrite result urls. See searx/https_rewrite.py - useragent_suffix : "" # suffix of searx_useragent, could contain informations like an email address to the administrator - image_proxy : False # Proxying image results through searx default_locale : "" # Default interface locale - leave blank to detect from browser information or use codes from the 'locales' config section +outgoing: # communication with search engines + request_timeout : 2.0 # seconds + useragent_suffix : "" # suffix of searx_useragent, could contain informations like an email address to the administrator +# uncomment below section if you want to use a proxy +# see http://docs.python-requests.org/en/latest/user/advanced/#proxies +# SOCKS proxies are not supported : see https://github.com/kennethreitz/requests/pull/478 +# proxies : +# http : http://127.0.0.1:8080 +# https: http://127.0.0.1:8080 +# uncomment below section only if you have more than one network interface +# which can be the source of outgoing search requests +# source_ips: +# - 1.1.1.1 +# - 1.1.1.2 + engines: - name : wikipedia engine : mediawiki @@ -20,24 +41,16 @@ engines: - name : bing engine : bing - locale : en-US shortcut : bi - name : bing images engine : bing_images - locale : en-US shortcut : bii - name : bing news engine : bing_news - locale : en-US shortcut : bin - - name : blekko images - engine : blekko_images - locale : en-US - shortcut : bli - - name : btdigg engine : btdigg shortcut : bt @@ -78,12 +91,6 @@ engines: # shortcut : fa # api_key : 'apikey' # required! -# down - website is under criminal investigation by the UK -# - name : filecrop -# engine : filecrop -# categories : files -# shortcut : fc - - name : 500px engine : www500px shortcut : px @@ -103,14 +110,10 @@ engines: # Or you can use the html non-stable engine, activated by default engine : flickr_noapi - - name : general-file - engine : generalfile - shortcut : gf - disabled : True - - name : gigablast engine : gigablast shortcut : gb + disabled: True - name : github engine : github @@ -173,6 +176,28 @@ engines: - name : piratebay engine : piratebay shortcut : tpb + disabled : True + + - name : qwant + engine : qwant + shortcut : qw + categories : general + disabled : True + + - name : qwant images + engine : qwant + shortcut : qwi + categories : images + + - name : qwant news + engine : qwant + shortcut : qwn + categories : news + + - name : qwant social + engine : qwant + shortcut : qws + categories : social media - name : kickass engine : kickass @@ -195,6 +220,10 @@ engines: shortcut : scc disabled : True + - name : spotify + engine : spotify + shortcut : stf + - name : subtitleseeker engine : subtitleseeker shortcut : ss @@ -205,12 +234,21 @@ engines: - name : startpage engine : startpage shortcut : sp + timeout : 6.0 + disabled : True -# +30% page load time -# - name : ixquick -# engine : startpage -# base_url : 'https://www.ixquick.com/' -# search_url : 'https://www.ixquick.com/do/search' + - name : ixquick + engine : startpage + base_url : 'https://www.ixquick.com/' + search_url : 'https://www.ixquick.com/do/search' + shortcut : iq + timeout : 6.0 + disabled : True + + - name : swisscows + engine : swisscows + shortcut : sw + disabled : True - name : twitter engine : twitter @@ -241,8 +279,13 @@ engines: shortcut : yhn - name : youtube - engine : youtube shortcut : yt + # You can use the engine using the official stable API, but you need an API key + # See : https://console.developers.google.com/project + # engine : youtube_api + # api_key: 'apikey' # required! + # Or you can use the html non-stable engine, activated by default + engine : youtube_noapi - name : dailymotion engine : dailymotion @@ -250,9 +293,14 @@ engines: - name : vimeo engine : vimeo - locale : en-US shortcut : vm +#The blekko technology and team have joined IBM Watson! -> https://blekko.com/ +# - name : blekko images +# engine : blekko_images +# locale : en-US +# shortcut : bli + # - name : yacy # engine : yacy # shortcut : ya @@ -271,4 +319,7 @@ locales: nl : Nederlands ja : 日本語 (Japanese) tr : Türkçe + pt : Português ru : Russian + ro : Romanian + zh : 中文 (Chinese) diff --git a/sources/searx/settings_robot.yml b/sources/searx/settings_robot.yml index c6fe228..f14443c 100644 --- a/sources/searx/settings_robot.yml +++ b/sources/searx/settings_robot.yml @@ -1,13 +1,25 @@ +general: + debug : False + +search: + safe_search : 0 + autocomplete : 0 + server: port : 11111 + bind_address : 127.0.0.1 secret_key : "ultrasecretkey" # change this! - debug : False - request_timeout : 3.0 # seconds - base_url: False + base_url : False + image_proxy : False + +ui: themes_path : "" default_theme : default - https_rewrite : True - image_proxy : False + default_locale : "" + +outgoing: + request_timeout : 1.0 # seconds + useragent_suffix : "" engines: - name : general_dummy diff --git a/sources/searx/static/js/search_on_category_select.js b/sources/searx/static/js/search_on_category_select.js new file mode 100644 index 0000000..5ecc2cd --- /dev/null +++ b/sources/searx/static/js/search_on_category_select.js @@ -0,0 +1,16 @@ +$(document).ready(function() { + if($('#q').length) { + $('#categories label').click(function(e) { + $('#categories input[type="checkbox"]').each(function(i, checkbox) { + $(checkbox).prop('checked', false); + }); + $('#categories label').removeClass('btn-primary').removeClass('active').addClass('btn-default'); + $(this).removeClass('btn-default').addClass('btn-primary').addClass('active'); + $($(this).children()[0]).prop('checked', 'checked'); + if($('#q').val()) { + $('#search_form').submit(); + } + return false; + }); + } +}); diff --git a/sources/searx/static/themes/courgette/img/favicon.png b/sources/searx/static/themes/courgette/img/favicon.png index cefbac4..1a43d7f 100644 Binary files a/sources/searx/static/themes/courgette/img/favicon.png and b/sources/searx/static/themes/courgette/img/favicon.png differ diff --git a/sources/searx/static/themes/courgette/img/github_ribbon.png b/sources/searx/static/themes/courgette/img/github_ribbon.png index 146ef8a..3799c2e 100644 Binary files a/sources/searx/static/themes/courgette/img/github_ribbon.png and b/sources/searx/static/themes/courgette/img/github_ribbon.png differ diff --git a/sources/searx/static/themes/courgette/img/preference-icon.png b/sources/searx/static/themes/courgette/img/preference-icon.png index 039db04..57e991c 100644 Binary files a/sources/searx/static/themes/courgette/img/preference-icon.png and b/sources/searx/static/themes/courgette/img/preference-icon.png differ diff --git a/sources/searx/static/themes/courgette/img/search-icon.png b/sources/searx/static/themes/courgette/img/search-icon.png index 52c2678..9bc7a22 100644 Binary files a/sources/searx/static/themes/courgette/img/search-icon.png and b/sources/searx/static/themes/courgette/img/search-icon.png differ diff --git a/sources/searx/static/themes/courgette/img/searx-mobile.png b/sources/searx/static/themes/courgette/img/searx-mobile.png index 2b9383a..b5af386 100644 Binary files a/sources/searx/static/themes/courgette/img/searx-mobile.png and b/sources/searx/static/themes/courgette/img/searx-mobile.png differ diff --git a/sources/searx/static/themes/courgette/img/searx.png b/sources/searx/static/themes/courgette/img/searx.png index e162da5..68c2e4f 100644 Binary files a/sources/searx/static/themes/courgette/img/searx.png and b/sources/searx/static/themes/courgette/img/searx.png differ diff --git a/sources/searx/static/themes/default/img/favicon.png b/sources/searx/static/themes/default/img/favicon.png index 28afb01..1a43d7f 100644 Binary files a/sources/searx/static/themes/default/img/favicon.png and b/sources/searx/static/themes/default/img/favicon.png differ diff --git a/sources/searx/static/themes/default/img/github_ribbon.png b/sources/searx/static/themes/default/img/github_ribbon.png index 146ef8a..3799c2e 100644 Binary files a/sources/searx/static/themes/default/img/github_ribbon.png and b/sources/searx/static/themes/default/img/github_ribbon.png differ diff --git a/sources/searx/static/themes/default/img/preference-icon.png b/sources/searx/static/themes/default/img/preference-icon.png index 300279d..8bdee64 100644 Binary files a/sources/searx/static/themes/default/img/preference-icon.png and b/sources/searx/static/themes/default/img/preference-icon.png differ diff --git a/sources/searx/static/themes/default/img/searx.png b/sources/searx/static/themes/default/img/searx.png index e69e9ee..a98f12a 100644 Binary files a/sources/searx/static/themes/default/img/searx.png and b/sources/searx/static/themes/default/img/searx.png differ diff --git a/sources/searx/static/themes/oscar/img/favicon.png b/sources/searx/static/themes/oscar/img/favicon.png index cefbac4..1a43d7f 100644 Binary files a/sources/searx/static/themes/oscar/img/favicon.png and b/sources/searx/static/themes/oscar/img/favicon.png differ diff --git a/sources/searx/static/themes/oscar/img/icons/github.png b/sources/searx/static/themes/oscar/img/icons/github.png index bf09bae..e643971 100644 Binary files a/sources/searx/static/themes/oscar/img/icons/github.png and b/sources/searx/static/themes/oscar/img/icons/github.png differ diff --git a/sources/searx/static/themes/oscar/img/icons/searchcode code.png b/sources/searx/static/themes/oscar/img/icons/searchcode code.png index 884c266..968a7ce 100644 Binary files a/sources/searx/static/themes/oscar/img/icons/searchcode code.png and b/sources/searx/static/themes/oscar/img/icons/searchcode code.png differ diff --git a/sources/searx/static/themes/oscar/img/icons/searchcode doc.png b/sources/searx/static/themes/oscar/img/icons/searchcode doc.png index 884c266..968a7ce 100644 Binary files a/sources/searx/static/themes/oscar/img/icons/searchcode doc.png and b/sources/searx/static/themes/oscar/img/icons/searchcode doc.png differ diff --git a/sources/searx/static/themes/oscar/img/icons/wikipedia.png b/sources/searx/static/themes/oscar/img/icons/wikipedia.png index 37997fb..f771683 100644 Binary files a/sources/searx/static/themes/oscar/img/icons/wikipedia.png and b/sources/searx/static/themes/oscar/img/icons/wikipedia.png differ diff --git a/sources/searx/static/themes/oscar/img/icons/youtube.png b/sources/searx/static/themes/oscar/img/icons/youtube.png index ba2484d..de64dff 100644 Binary files a/sources/searx/static/themes/oscar/img/icons/youtube.png and b/sources/searx/static/themes/oscar/img/icons/youtube.png differ diff --git a/sources/searx/static/themes/oscar/img/map/layers-2x.png b/sources/searx/static/themes/oscar/img/map/layers-2x.png index a2cf7f9..0b30da6 100644 Binary files a/sources/searx/static/themes/oscar/img/map/layers-2x.png and b/sources/searx/static/themes/oscar/img/map/layers-2x.png differ diff --git a/sources/searx/static/themes/oscar/img/map/layers.png b/sources/searx/static/themes/oscar/img/map/layers.png index bca0a0e..4297fd9 100644 Binary files a/sources/searx/static/themes/oscar/img/map/layers.png and b/sources/searx/static/themes/oscar/img/map/layers.png differ diff --git a/sources/searx/static/themes/oscar/img/map/marker-icon-2x-green.png b/sources/searx/static/themes/oscar/img/map/marker-icon-2x-green.png index c359abb..7446bb0 100644 Binary files a/sources/searx/static/themes/oscar/img/map/marker-icon-2x-green.png and b/sources/searx/static/themes/oscar/img/map/marker-icon-2x-green.png differ diff --git a/sources/searx/static/themes/oscar/img/map/marker-icon-2x-orange.png b/sources/searx/static/themes/oscar/img/map/marker-icon-2x-orange.png index c3c8632..ecd6773 100644 Binary files a/sources/searx/static/themes/oscar/img/map/marker-icon-2x-orange.png and b/sources/searx/static/themes/oscar/img/map/marker-icon-2x-orange.png differ diff --git a/sources/searx/static/themes/oscar/img/map/marker-icon-2x-red.png b/sources/searx/static/themes/oscar/img/map/marker-icon-2x-red.png index 1c26e9f..1d2e197 100644 Binary files a/sources/searx/static/themes/oscar/img/map/marker-icon-2x-red.png and b/sources/searx/static/themes/oscar/img/map/marker-icon-2x-red.png differ diff --git a/sources/searx/static/themes/oscar/img/map/marker-icon-green.png b/sources/searx/static/themes/oscar/img/map/marker-icon-green.png index 56db5ea..f48ef41 100644 Binary files a/sources/searx/static/themes/oscar/img/map/marker-icon-green.png and b/sources/searx/static/themes/oscar/img/map/marker-icon-green.png differ diff --git a/sources/searx/static/themes/oscar/img/map/marker-icon-orange.png b/sources/searx/static/themes/oscar/img/map/marker-icon-orange.png index fbbce7b..d0d2220 100644 Binary files a/sources/searx/static/themes/oscar/img/map/marker-icon-orange.png and b/sources/searx/static/themes/oscar/img/map/marker-icon-orange.png differ diff --git a/sources/searx/static/themes/oscar/img/map/marker-icon-red.png b/sources/searx/static/themes/oscar/img/map/marker-icon-red.png index 3e64e06..7a92b9e 100644 Binary files a/sources/searx/static/themes/oscar/img/map/marker-icon-red.png and b/sources/searx/static/themes/oscar/img/map/marker-icon-red.png differ diff --git a/sources/searx/static/themes/oscar/img/searx_logo.png b/sources/searx/static/themes/oscar/img/searx_logo.png index 26be6de..ea4837b 100644 Binary files a/sources/searx/static/themes/oscar/img/searx_logo.png and b/sources/searx/static/themes/oscar/img/searx_logo.png differ diff --git a/sources/searx/static/themes/pix-art/css/style.css b/sources/searx/static/themes/pix-art/css/style.css new file mode 100644 index 0000000..229cf86 --- /dev/null +++ b/sources/searx/static/themes/pix-art/css/style.css @@ -0,0 +1 @@ +html{font-family:"Courier New",Courier,monospace;font-size:.9em;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%;color:#444;padding:0;margin:0}body,#container{padding:0;margin:0}canvas{image-rendering:optimizeSpeed;image-rendering:-moz-crisp-edges;image-rendering:-webkit-optimize-contrast;image-rendering:optimize-contrast;image-rendering:pixelated;-ms-interpolation-mode:nearest-neighbor;width:32px;height:32px}#container{width:100%;position:absolute;top:0}.search{padding:0;margin:0}#search_wrapper{position:relative;width:50em;padding:10px}.center #search_wrapper{margin-left:auto;margin-right:auto}.q{background:none repeat scroll 0 0 #fff;border:1px solid #3498db;color:#222;font-size:16px;font-family:"Courier New",Courier,monospace;height:28px;margin:0;outline:medium none;padding:2px;padding-left:8px;padding-right:0 !important;width:100%;z-index:2}#search_submit{position:absolute;top:15px;right:5px;padding:0;border:0;background:url('../img/search-icon-pixel.png') no-repeat;background-size:24px 24px;opacity:.8;width:24px;height:24px;font-size:0}@media screen and (max-width:50em){#search_wrapper{width:90%;clear:both;overflow:hidden}}.row{max-width:800px;margin:20px auto;text-align:justify}.row h1{font-size:3em;margin-top:50px}.row p{padding:0 10px;max-width:700px}.row h3,.row ul{margin:4px 8px}.hmarg{margin:0 20px;border:1px solid #3498db;padding:4px 10px}a:link.hmarg{color:#3498db}a:visited.hmarg{color:#3498db}a:active.hmarg{color:#3498db}a:hover.hmarg{color:#3498db}.top_margin{margin-top:60px}.center{text-align:center}h1{font-size:5em}div.title{background:url('../img/searx-pixel.png') no-repeat;width:100%;min-height:80px;background-position:center}div.title h1{visibility:hidden}input[type="button"],input[type="submit"]{font-family:"Courier New",Courier,monospace;padding:4px 12px;margin:2px 4px;display:inline-block;background:#3498db;color:#fff;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:0;cursor:pointer}input[type="button"]:disabled{cursor:progress}input[type="checkbox"]{visibility:hidden}fieldset{margin:8px;border:1px solid #3498db}#logo{position:absolute;top:13px;left:10px}#categories{margin:0 10px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox_container{display:inline-block;position:relative;margin:0 3px;padding:0}.checkbox_container input{display:none}.checkbox_container label,.engine_checkbox label{cursor:pointer;padding:4px 10px;margin:0;display:block;text-transform:capitalize;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox_container input[type="checkbox"]:checked+label{background:#3498db;color:#fff}.engine_checkbox{padding:4px}label.allow{background:#e74c3c;padding:4px 8px;color:#fff;display:none}label.deny{background:#2ecc71;padding:4px 8px;color:#444;display:inline}.engine_checkbox input[type="checkbox"]:checked+label:nth-child(2)+label{display:none}.engine_checkbox input[type="checkbox"]:checked+label.allow{display:inline}a{text-decoration:none;color:#1a11be}a:visited{color:#8e44ad}.engines{color:#888}.small_font{font-size:.8em}.small p{margin:2px 0}.right{float:right}.invisible{display:none}.left{float:left}.highlight{color:#094089}.content .highlight{color:#000}.percentage{position:relative;width:300px}.percentage div{background:#444}table{width:100%}td{padding:0 4px}tr:hover{background:#ddd}#results{margin:auto;padding:0;width:50em;margin-bottom:20px}#search_url{margin-top:8px}#search_url input{border:1px solid #888;padding:4px;color:#444;width:14em;display:block;margin:4px;font-size:.8em}#preferences{top:10px;padding:0;border:0;background:url('../img/preference-icon-pixel.png') no-repeat;background-size:28px 28px;opacity:.8;width:28px;height:30px;display:block}#preferences *{display:none}#pagination{clear:both;text-align:center}#pagination br{clear:both}#apis{margin-top:8px;clear:both}#categories_container{position:relative}@media screen and (max-width:50em){#results{margin:auto;padding:0;width:90%}.checkbox_container{display:block;width:90%}.checkbox_container label{border-bottom:0}.preferences_container{display:none;postion:fixed !important;top:100px;right:0}}@media screen and (max-width:75em){div.title h1{font-size:1em}html.touch #categories{width:95%;height:30px;text-align:left;overflow-x:scroll;overflow-y:hidden;-webkit-overflow-scrolling:touch}html.touch #categories #categories_container{width:1000px;width:-moz-max-content;width:-webkit-max-content;width:max-content}html.touch #categories #categories_container .checkbox_container{display:inline-block;width:auto}#categories{font-size:90%;clear:both}#categories .checkbox_container{margin-top:2px;margin:auto}#categories{font-size:90%;clear:both}#categories .checkbox_container{margin-top:2px;margin:auto}#apis{display:none}#search_url{display:none}#logo{display:none}}.favicon{float:left;margin-right:4px;margin-top:2px}.preferences_back{background:none repeat scroll 0 0 #3498db;border:0 none;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;cursor:pointer;display:inline-block;margin:2px 4px;padding:4px 6px}.preferences_back a{color:#fff}.hidden{opacity:0;overflow:hidden;font-size:.8em;position:absolute;bottom:-20px;width:100%;text-position:center;background:white;transition:opacity 1s ease}#categories_container:hover .hidden{transition:opacity 1s ease;opacity:.8} \ No newline at end of file diff --git a/sources/searx/static/themes/pix-art/img/favicon.png b/sources/searx/static/themes/pix-art/img/favicon.png new file mode 100644 index 0000000..1a43d7f Binary files /dev/null and b/sources/searx/static/themes/pix-art/img/favicon.png differ diff --git a/sources/searx/static/themes/pix-art/img/preference-icon-pixel.png b/sources/searx/static/themes/pix-art/img/preference-icon-pixel.png new file mode 100644 index 0000000..424e01e Binary files /dev/null and b/sources/searx/static/themes/pix-art/img/preference-icon-pixel.png differ diff --git a/sources/searx/static/themes/pix-art/img/search-icon-pixel.png b/sources/searx/static/themes/pix-art/img/search-icon-pixel.png new file mode 100644 index 0000000..8235882 Binary files /dev/null and b/sources/searx/static/themes/pix-art/img/search-icon-pixel.png differ diff --git a/sources/searx/static/themes/pix-art/img/searx-pixel-small.png b/sources/searx/static/themes/pix-art/img/searx-pixel-small.png new file mode 100644 index 0000000..75b476c Binary files /dev/null and b/sources/searx/static/themes/pix-art/img/searx-pixel-small.png differ diff --git a/sources/searx/static/themes/pix-art/img/searx-pixel.png b/sources/searx/static/themes/pix-art/img/searx-pixel.png new file mode 100644 index 0000000..6b8dbac Binary files /dev/null and b/sources/searx/static/themes/pix-art/img/searx-pixel.png differ diff --git a/sources/searx/static/themes/pix-art/js/searx.js b/sources/searx/static/themes/pix-art/js/searx.js new file mode 100644 index 0000000..5eb0af9 --- /dev/null +++ b/sources/searx/static/themes/pix-art/js/searx.js @@ -0,0 +1,141 @@ +if(searx.autocompleter) { + window.addEvent('domready', function() { + new Autocompleter.Request.JSON('q', '/autocompleter', { + postVar:'q', + postData:{ + 'format': 'json' + }, + ajaxOptions:{ + timeout: 5 // Correct option? + }, + 'minLength': 4, + 'selectMode': false, + cache: true, + delay: 300 + }); + }); +} + +(function (w, d) { + 'use strict'; + function addListener(el, type, fn) { + if (el.addEventListener) { + el.addEventListener(type, fn, false); + } else { + el.attachEvent('on' + type, fn); + } + } + + function placeCursorAtEnd() { + if (this.setSelectionRange) { + var len = this.value.length * 2; + this.setSelectionRange(len, len); + } + } + + addListener(w, 'load', function () { + var qinput = d.getElementById('q'); + if (qinput !== null && qinput.value === "") { + addListener(qinput, 'focus', placeCursorAtEnd); + qinput.focus(); + } + }); + + if (!!('ontouchstart' in window)) { + document.getElementsByTagName("html")[0].className += " touch"; + } + +})(window, document); + +var xmlHttp + +function GetXmlHttpObject(){ + + var xmlHttp = null; + + try { + // Firefox, Opera 8.0+, Safari + xmlHttp = new XMLHttpRequest(); + } + catch (e) { + // Internet Explorer + try { + xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); + } + catch (e){ + xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); + } + } + return xmlHttp; +} + +var timer; + +// Load more results +function load_more(query,page){ + + xmlHttp = GetXmlHttpObject(); + clearTimeout(timer); + + if(xmlHttp == null){ + alert ("Your browser does not support AJAX!"); + return; + } + + favicons[page] = []; + + xmlHttp.onreadystatechange = function(){ + + var loader = document.getElementById('load_more'); + + // If 4, response OK + if (xmlHttp.readyState == 4){ + + var res = xmlHttp.responseText; + + clearTimeout(timer); + timer = setTimeout(function(){},6000); + + var results = document.getElementById('results_list'); + + var newNode = document.createElement('span'); + newNode.innerHTML = res; + results_list.appendChild(newNode); + + var scripts = newNode.getElementsByTagName('script'); + for (var ix = 0; ix < scripts.length; ix++) { + eval(scripts[ix].text); + } + + load_images(page); + document.getElementById("load_more").onclick = function() { load_more(query, (page+1)); } + loader.removeAttribute("disabled"); + + } else { + loader.disabled = 'disabled'; + } + } + var url = "/"; + var params = "q="+query+"&pageno="+page+"&category_general=1&category_files=1&category_images=1&category_it=1&category_map=1&category_music=1&category_news=1&category_social+media=1&category_videos=1"; + xmlHttp.open("POST",url,true); + xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + xmlHttp.setRequestHeader("Content-length", params.length); + xmlHttp.setRequestHeader("Connection", "close"); + xmlHttp.send(params); +} + +// Load the images on the canvas in the page +function load_images(page){ + var arrayLength = favicons[page].length; + for (var i = 1; i < arrayLength+1; i++) { + var img = new Image(); + img.setAttribute("i",i) + img.onload = function () { + var id = 'canvas-'+page+'-'+this.getAttribute("i"); + var can = document.getElementById(id); + var ctx = can.getContext("2d"); + ctx.drawImage(this, 0, 0, 16, 16); + }; + img.src = favicons[page][i]; + } +} \ No newline at end of file diff --git a/sources/searx/static/themes/pix-art/less/definitions.less b/sources/searx/static/themes/pix-art/less/definitions.less new file mode 100644 index 0000000..0ac0cc9 --- /dev/null +++ b/sources/searx/static/themes/pix-art/less/definitions.less @@ -0,0 +1,119 @@ +/* + * searx, A privacy-respecting, hackable metasearch engine + * + * To change the colors of the site, simple edit this variables + */ + +/// Basic Colors + +@color-base: #3498DB; +@color-base-dark: #2980B9; +@color-base-light: #ECF0F1; +@color-highlight: #094089; +@color-black: #000000; + +/// General + +@color-font: #444; +@color-font-light: #888; + +@color-red: #C0392B; + +@color-url-font: #1a11be; +@color-url-visited-font: #8E44AD; +@results-width: 50em; + + +/// Start-Screen + +// hmarg +@color-hmarg-border: @color-base; +@color-hmarg-font: @color-base; +@color-hmarg-font-hover: @color-base; + + +/// Search-Input + +@color-search-border: @color-base; +@color-search-background: #FFF; +@color-search-font: #222; + +/// Autocompleter + +@color-autocompleter-choices-background: #FFF; +@color-autocompleter-choices-border: @color-base; +@color-autocompleter-choices-border-left-right: @color-base; +@color-autocompleter-choices-border-bottom: @color-base; + +@color-autocompleter-choices-font: #444; + +/// Answers +@color-answers-border: @color-base-dark; + +// Selected +@color-autocompleter-selected-background: #444; +@color-autocompleter-selected-font: #FFF; +@color-autocompleter-selected-queried-font: #9FCFFF; + +/// Categories + +@color-categories-item-selected: @color-base; +@color-categories-item-selected-font: #FFF; + +@color-categories-item-border-selected: @color-base-dark; +@color-categories-item-border-unselected: #E8E7E6; +@color-categories-item-border-unselected-hover: @color-base; + + +/// Results + +@color-suggestions-button-background: @color-base; +@color-suggestions-button-font: #FFF; + +@color-download-button-background: @color-base; +@color-download-button-font: #FFF; + +@color-result-search-background: @color-base-light; + +@color-result-definition-border: gray; +@color-result-torrent-border: lightgray; +@color-result-top-border: #E8E7E6; + +// Link to result +@color-result-link-font: @color-base-dark; +@color-result-link-visited-font: @color-url-visited-font; + +// Url to result +@color-result-url-font: @color-red; + +// Publish Date +@color-result-publishdate-font: @color-font-light; + +// Images +@color-result-image-span-background-hover: rgba(0, 0, 0, 0.6); +@color-result-image-span-font: #FFF; + +// Search-URL +@color-result-search-url-border: #888; +@color-result-search-url-font: #444; + + +/// Settings + +@color-settings-fieldset: @color-base; +@color-settings-tr-hover: #DDD; + +// Labels +@color-settings-label-allowed-background: #E74C3C; +@color-settings-label-allowed-font: #FFF; + +@color-settings-label-deny-background: #2ECC71; +@color-settings-label-deny-font: @color-font; + +@color-settings-return-background: @color-base; +@color-settings-return-font: #FFF; + +/// Other + +@color-engines-font: @color-font-light; +@color-percentage-div-background: #444; diff --git a/sources/searx/static/themes/pix-art/less/mixins.less b/sources/searx/static/themes/pix-art/less/mixins.less new file mode 100644 index 0000000..dbccce6 --- /dev/null +++ b/sources/searx/static/themes/pix-art/less/mixins.less @@ -0,0 +1,27 @@ +/* + * searx, A privacy-respecting, hackable metasearch engine + */ + +// Mixins + +.text-size-adjust (@property: 100%) { + -webkit-text-size-adjust: @property; + -ms-text-size-adjust: @property; + -moz-text-size-adjust: @property; + text-size-adjust: @property; +} + +.rounded-corners (@radius: 4px) { + -webkit-border-radius: @radius; + -moz-border-radius: @radius; + border-radius: @radius; +} + +.user-select () { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} diff --git a/sources/searx/static/themes/pix-art/less/search.less b/sources/searx/static/themes/pix-art/less/search.less new file mode 100644 index 0000000..f5ac33e --- /dev/null +++ b/sources/searx/static/themes/pix-art/less/search.less @@ -0,0 +1,57 @@ +/* + * searx, A privacy-respecting, hackable metasearch engine + */ + +.search { + padding: 0; + margin: 0; +} + +#search_wrapper { + position: relative; + width: @results-width; + padding: 10px; +} + +.center #search_wrapper { + margin-left: auto; + margin-right: auto; +} + +.q { + background: none repeat scroll 0 0 @color-search-background; + border: 1px solid @color-search-border; + color: @color-search-font; + font-size: 16px; + font-family: "Courier New", Courier, monospace; + height: 28px; + margin: 0; + outline: medium none; + padding: 2px; + padding-left: 8px; + padding-right: 0px !important; + width: 100%; + z-index: 2; +} + +#search_submit { + position: absolute; + top: 15px; + right: 5px; + padding: 0; + border: 0; + background: url('../img/search-icon-pixel.png') no-repeat; + background-size: 24px 24px; + opacity: 0.8; + width: 24px; + height: 24px; + font-size: 0; +} + +@media screen and (max-width: @results-width) { + #search_wrapper { + width: 90%; + clear:both; + overflow: hidden + } +} diff --git a/sources/searx/static/themes/pix-art/less/style.less b/sources/searx/static/themes/pix-art/less/style.less new file mode 100644 index 0000000..a2088e9 --- /dev/null +++ b/sources/searx/static/themes/pix-art/less/style.less @@ -0,0 +1,451 @@ +/* + * searx, A privacy-respecting, hackable metasearch engine + * + * To convert "style.less" to "style.css" run: $make styles + */ + +@import "definitions.less"; + +@import "mixins.less"; + + +// Main LESS-Code + +html { + font-family: "Courier New", Courier, monospace; + font-size: 0.9em; + .text-size-adjust; + color: @color-font; + padding: 0; + margin: 0; +} + +body, #container { + padding: 0; + margin: 0; +} + +canvas { + image-rendering: optimizeSpeed; + image-rendering: -moz-crisp-edges; + image-rendering: -webkit-optimize-contrast; + image-rendering: optimize-contrast; + image-rendering: pixelated; + -ms-interpolation-mode: nearest-neighbor; + width:32px; + height:32px; +} + +#container { + width: 100%; + position: absolute; + top: 0; +} + +// Search-Field + +@import "search.less"; + +.row { + max-width: 800px; + margin: 20px auto; + text-align: justify; + + h1 { + font-size: 3em; + margin-top: 50px; + } + + p { + padding: 0 10px; + max-width: 700px; + } + + h3,ul { + margin: 4px 8px; + } +} + +.hmarg { + margin: 0 20px; + border: 1px solid @color-hmarg-border; + padding: 4px 10px; +} + +a { + &:link.hmarg { + color: @color-hmarg-font; + } + + &:visited.hmarg { + color: @color-hmarg-font; + } + + &:active.hmarg { + color: @color-hmarg-font-hover; + } + + &:hover.hmarg { + color: @color-hmarg-font-hover; + } +} + +.top_margin { + margin-top: 60px; +} + +.center { + text-align: center; +} + +h1 { + font-size: 5em; +} + +div.title { + background: url('../img/searx-pixel.png') no-repeat; + width: 100%; + min-height: 80px; + background-position: center; + + h1 { + visibility: hidden; + } +} + +input[type="button"], +input[type="submit"] { + font-family: "Courier New", Courier, monospace; + padding: 4px 12px; + margin: 2px 4px; + display: inline-block; + background: @color-download-button-background; + color: @color-download-button-font; + .rounded-corners; + border: 0; + cursor: pointer; +} + +input[type="button"]:disabled { + cursor: progress; +} + +input[type="checkbox"] { + visibility: hidden; +} + +fieldset { + margin: 8px; + border: 1px solid @color-settings-fieldset; +} + +#logo { + position: absolute; + top: 13px; + left: 10px; +} + +#categories { + margin: 0 10px; + .user-select; +} + +.checkbox_container { + display: inline-block; + position: relative; + margin: 0 3px; + padding: 0px; + + input { + display: none; + } +} + +.checkbox_container label, .engine_checkbox label { + cursor: pointer; + padding: 4px 10px; + margin: 0; + display: block; + text-transform: capitalize; + .user-select; +} + +.checkbox_container input[type="checkbox"]:checked + label { + background: @color-categories-item-selected; + color: @color-categories-item-selected-font; +} + +.engine_checkbox { + padding: 4px; +} + +label { + &.allow { + background: @color-settings-label-allowed-background; + padding: 4px 8px; + color: @color-settings-label-allowed-font; + display: none; + } + + &.deny { + background: @color-settings-label-deny-background; + padding: 4px 8px; + color: @color-settings-label-deny-font; + display: inline; + } +} + +.engine_checkbox input[type="checkbox"]:checked + label { + &:nth-child(2) + label { + display: none; + } + + &.allow { + display: inline; + } +} + +a { + text-decoration: none; + color: @color-url-font; + + &:visited { + color: @color-url-visited-font; + } +} + +.engines { + color: @color-engines-font; +} + +.small_font { + font-size: 0.8em; +} + +.small p { + margin: 2px 0; +} + +.right { + float: right; +} + +.invisible { + display: none; +} + +.left { + float: left; +} + +.highlight { + color: @color-highlight; +} + +.content .highlight { + color: @color-black; +} + +.percentage { + position: relative; + width: 300px; + + div { + background: @color-percentage-div-background; + } +} + +table { + width: 100%; +} + +td { + padding: 0 4px; +} + +tr { + &:hover { + background: @color-settings-tr-hover; + } +} + +#results { + margin: auto; + padding: 0; + width: @results-width; + margin-bottom: 20px; +} + +#search_url { + margin-top: 8px; + + input { + border: 1px solid @color-result-search-url-border; + padding: 4px; + color: @color-result-search-url-font; + width: 14em; + display: block; + margin: 4px; + font-size: 0.8em; + } +} + +#preferences { + top: 10px; + padding: 0; + border: 0; + background: url('../img/preference-icon-pixel.png') no-repeat; + background-size: 28px 28px; + opacity: 0.8; + width: 28px; + height: 30px; + display: block; + + * { + display: none; + } +} + +#pagination { + clear: both; + text-align: center; + br { + clear: both; + } +} + +#apis { + margin-top: 8px; + clear: both; +} + +#categories_container { + position: relative; +} + +@media screen and (max-width: @results-width) { + + #results { + margin: auto; + padding: 0; + width: 90%; + } + + .checkbox_container { + display: block; + width: 90%; + //float: left; + + label { + border-bottom: 0; + } + } + + .preferences_container { + display: none; + postion: fixed !important; + top: 100px; + right: 0px; + } + +} + +@media screen and (max-width: 75em) { + + div.title { + + h1 { + font-size: 1em; + } + } + + html.touch #categories { + width: 95%; + height: 30px; + text-align: left; + overflow-x: scroll; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + + #categories_container { + width: 1000px; + width: -moz-max-content; + width: -webkit-max-content; + width: max-content; + + .checkbox_container { + display: inline-block; + width: auto; + } + } + } + + #categories { + font-size: 90%; + clear: both; + + .checkbox_container { + margin-top: 2px; + margin: auto; + } + } + + #categories { + font-size: 90%; + clear: both; + + .checkbox_container { + margin-top: 2px; + margin: auto; + } + } + + #apis { + display: none; + } + + #search_url { + display: none; + } + + #logo { + display: none; + } +} + +.favicon { + float: left; + margin-right: 4px; + margin-top: 2px; +} + +.preferences_back { + background: none repeat scroll 0 0 @color-settings-return-background; + border: 0 none; + .rounded-corners; + cursor: pointer; + display: inline-block; + margin: 2px 4px; + padding: 4px 6px; + + a { + color: @color-settings-return-font; + } +} + +.hidden { + opacity: 0; + overflow: hidden; + font-size: 0.8em; + position: absolute; + bottom: -20px; + width: 100%; + text-position: center; + background: white; + transition: opacity 1s ease; +} + +#categories_container:hover .hidden { + transition: opacity 1s ease; + opacity: 0.8; +} diff --git a/sources/searx/templates/courgette/base.html b/sources/searx/templates/courgette/base.html index 5895733..276fae8 100644 --- a/sources/searx/templates/courgette/base.html +++ b/sources/searx/templates/courgette/base.html @@ -5,6 +5,7 @@ + {% block title %}{% endblock %}searx @@ -39,4 +40,4 @@ - \ No newline at end of file + diff --git a/sources/searx/templates/courgette/opensearch.xml b/sources/searx/templates/courgette/opensearch.xml index f39283f..ff9eac5 100644 --- a/sources/searx/templates/courgette/opensearch.xml +++ b/sources/searx/templates/courgette/opensearch.xml @@ -3,6 +3,7 @@ searx Search searx UTF-8 + {{ host }}{{ url_for('static', filename='img/favicon.png') | replace("/", "", 1) }} searx metasearch {% if opensearch_method == 'get' %} diff --git a/sources/searx/templates/courgette/preferences.html b/sources/searx/templates/courgette/preferences.html index 2abfafb..f89915d 100644 --- a/sources/searx/templates/courgette/preferences.html +++ b/sources/searx/templates/courgette/preferences.html @@ -101,8 +101,8 @@ {{ _('Category') }} {{ _('Allow') }} / {{ _('Block') }} - {% for (categ,search_engines) in categs %} - {% for search_engine in search_engines %} + {% for categ in all_categories %} + {% for search_engine in engines_by_category[categ] %} {% if not search_engine.private %} @@ -125,7 +125,8 @@

+ - + {% endblock %} diff --git a/sources/searx/templates/courgette/result_templates/code.html b/sources/searx/templates/courgette/result_templates/code.html index 382ce2a..726f305 100644 --- a/sources/searx/templates/courgette/result_templates/code.html +++ b/sources/searx/templates/courgette/result_templates/code.html @@ -1,8 +1,8 @@
-

{% if result['favicon'] %}{{result['favicon']}}{% endif %}{{ result.title|safe }}

+

{% if result['favicon'] %}{{result['favicon']}}{% endif %}{{ result.title|safe }}

{% if result.publishedDate %}{{ result.publishedDate }}{% endif %}

{% if result.img_src %}{% endif %}{% if result.content %}{{ result.content|safe }}
{% endif %}

- {% if result.repository %}

{{ result.repository }}

{% endif %} + {% if result.repository %}

{{ result.repository }}

{% endif %}
{{ result.codelines|code_highlighter(result.code_language)|safe }}
diff --git a/sources/searx/templates/courgette/result_templates/default.html b/sources/searx/templates/courgette/result_templates/default.html index f5f5ace..585ecf3 100644 --- a/sources/searx/templates/courgette/result_templates/default.html +++ b/sources/searx/templates/courgette/result_templates/default.html @@ -5,9 +5,9 @@ {% endif %}
-

{{ result.title|safe }}

+

{{ result.title|safe }}

{% if result.publishedDate %}{{ result.publishedDate }}{% endif %}

{% if result.content %}{{ result.content|safe }}
{% endif %}

{{ result.pretty_url }}‎

-
\ No newline at end of file + diff --git a/sources/searx/templates/courgette/result_templates/images.html b/sources/searx/templates/courgette/result_templates/images.html index 7228578..87fc774 100644 --- a/sources/searx/templates/courgette/result_templates/images.html +++ b/sources/searx/templates/courgette/result_templates/images.html @@ -1,6 +1,6 @@ diff --git a/sources/searx/templates/courgette/result_templates/map.html b/sources/searx/templates/courgette/result_templates/map.html index f5f5ace..585ecf3 100644 --- a/sources/searx/templates/courgette/result_templates/map.html +++ b/sources/searx/templates/courgette/result_templates/map.html @@ -5,9 +5,9 @@ {% endif %}
-

{{ result.title|safe }}

+

{{ result.title|safe }}

{% if result.publishedDate %}{{ result.publishedDate }}{% endif %}

{% if result.content %}{{ result.content|safe }}
{% endif %}

{{ result.pretty_url }}‎

- \ No newline at end of file + diff --git a/sources/searx/templates/courgette/result_templates/torrent.html b/sources/searx/templates/courgette/result_templates/torrent.html index b961eb0..33b5742 100644 --- a/sources/searx/templates/courgette/result_templates/torrent.html +++ b/sources/searx/templates/courgette/result_templates/torrent.html @@ -2,12 +2,12 @@ {% if "icon_"~result.engine~".ico" in favicons %} {{result.engine}} {% endif %} -

{{ result.title|safe }}

+

{{ result.title|safe }}

{% if result.content %}{{ result.content|safe }}
{% endif %} {{ _('Seeder') }} : {{ result.seed }}, {{ _('Leecher') }} : {{ result.leech }}
{% if result.magnetlink %}{{ _('magnet link') }}{% endif %} - {% if result.torrentfile %}{{ _('torrent file') }}{% endif %} + {% if result.torrentfile %}{{ _('torrent file') }}{% endif %}

{{ result.pretty_url }}‎

- \ No newline at end of file + diff --git a/sources/searx/templates/courgette/result_templates/videos.html b/sources/searx/templates/courgette/result_templates/videos.html index 4e0174b..ceed8b2 100644 --- a/sources/searx/templates/courgette/result_templates/videos.html +++ b/sources/searx/templates/courgette/result_templates/videos.html @@ -3,8 +3,8 @@ {{result.engine}} {% endif %} -

{{ result.title|safe }}

+

{{ result.title|safe }}

{% if result.publishedDate %}{{ result.publishedDate }}
{% endif %} - {{ result.title|striptags }} + {{ result.title|striptags }}

{{ result.pretty_url }}‎

diff --git a/sources/searx/templates/courgette/results.html b/sources/searx/templates/courgette/results.html index 619c997..3ffbd58 100644 --- a/sources/searx/templates/courgette/results.html +++ b/sources/searx/templates/courgette/results.html @@ -10,7 +10,7 @@ -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/sources/searx/templates/default/base.html b/sources/searx/templates/default/base.html index fa96d94..143bdb8 100644 --- a/sources/searx/templates/default/base.html +++ b/sources/searx/templates/default/base.html @@ -5,6 +5,7 @@ + {% block title %}{% endblock %}searx diff --git a/sources/searx/templates/default/infobox.html b/sources/searx/templates/default/infobox.html index 50f5e09..1733f77 100644 --- a/sources/searx/templates/default/infobox.html +++ b/sources/searx/templates/default/infobox.html @@ -17,7 +17,7 @@
diff --git a/sources/searx/templates/default/opensearch.xml b/sources/searx/templates/default/opensearch.xml index f39283f..ff9eac5 100644 --- a/sources/searx/templates/default/opensearch.xml +++ b/sources/searx/templates/default/opensearch.xml @@ -3,6 +3,7 @@ searx Search searx UTF-8 + {{ host }}{{ url_for('static', filename='img/favicon.png') | replace("/", "", 1) }} searx metasearch {% if opensearch_method == 'get' %} diff --git a/sources/searx/templates/default/preferences.html b/sources/searx/templates/default/preferences.html index e03c18e..90006c0 100644 --- a/sources/searx/templates/default/preferences.html +++ b/sources/searx/templates/default/preferences.html @@ -89,8 +89,8 @@ {{ _('Category') }} {{ _('Allow') }} / {{ _('Block') }} - {% for (categ,search_engines) in categs %} - {% for search_engine in search_engines %} + {% for categ in all_categories %} + {% for search_engine in engines_by_category[categ] %} {% if not search_engine.private %} @@ -113,7 +113,8 @@

+ - + {% endblock %} diff --git a/sources/searx/templates/default/result_templates/code.html b/sources/searx/templates/default/result_templates/code.html index 78eda18..ad1d97e 100644 --- a/sources/searx/templates/default/result_templates/code.html +++ b/sources/searx/templates/default/result_templates/code.html @@ -1,9 +1,9 @@
-

{% if result['favicon'] %}{{result['favicon']}}{% endif %}{{ result.title|safe }}

-

{{ result.pretty_url }}‎ {{ _('cached') }}

+

{% if result['favicon'] %}{{result['favicon']}}{% endif %}{{ result.title|safe }}

+

{{ result.pretty_url }}‎ {{ _('cached') }}

{% if result.publishedDate %}

{{ result.publishedDate }}

{% endif %}

{% if result.img_src %}{% endif %}{% if result.content %}{{ result.content|safe }}
{% endif %}

- {% if result.repository %}

{{ result.repository }}

{% endif %} + {% if result.repository %}

{{ result.repository }}

{% endif %}
{{ result.codelines|code_highlighter(result.code_language)|safe }} diff --git a/sources/searx/templates/default/result_templates/default.html b/sources/searx/templates/default/result_templates/default.html index 4cbf231..89091e2 100644 --- a/sources/searx/templates/default/result_templates/default.html +++ b/sources/searx/templates/default/result_templates/default.html @@ -1,6 +1,6 @@
-

{% if "icon_"~result.engine~".ico" in favicons %}{{result.engine}}{% endif %}{{ result.title|safe }}

-

{{ result.pretty_url }}‎ {{ _('cached') }} +

{% if "icon_"~result.engine~".ico" in favicons %}{{result.engine}}{% endif %}{{ result.title|safe }}

+

{{ result.pretty_url }}‎ {{ _('cached') }} {% if result.publishedDate %}{{ result.publishedDate }}{% endif %}

{% if result.img_src %}{% endif %}{% if result.content %}{{ result.content|safe }}
{% endif %}

diff --git a/sources/searx/templates/default/result_templates/images.html b/sources/searx/templates/default/result_templates/images.html index e06dcc1..d85f841 100644 --- a/sources/searx/templates/default/result_templates/images.html +++ b/sources/searx/templates/default/result_templates/images.html @@ -1,6 +1,6 @@ diff --git a/sources/searx/templates/default/result_templates/map.html b/sources/searx/templates/default/result_templates/map.html index e2d00f9..d413742 100644 --- a/sources/searx/templates/default/result_templates/map.html +++ b/sources/searx/templates/default/result_templates/map.html @@ -5,8 +5,8 @@ {% endif %}
-

{{ result.title|safe }}

-

{{ result.pretty_url }}‎ {{ _('cached') }} +

{{ result.title|safe }}

+

{{ result.pretty_url }}‎ {{ _('cached') }} {% if result.publishedDate %}{{ result.publishedDate }}{% endif %}

{% if result.img_src %}{% endif %}{% if result.content %}{{ result.content|safe }}
{% endif %}

diff --git a/sources/searx/templates/default/result_templates/torrent.html b/sources/searx/templates/default/result_templates/torrent.html index b91babf..4b2522a 100644 --- a/sources/searx/templates/default/result_templates/torrent.html +++ b/sources/searx/templates/default/result_templates/torrent.html @@ -2,12 +2,12 @@ {% if "icon_"~result.engine~".ico" in favicons %} {{result.engine}} {% endif %} -

{{ result.title|safe }}

+

{{ result.title|safe }}

{{ result.pretty_url }}‎

{% if result.content %}

{{ result.content|safe }}

{% endif %}

{% if result.magnetlink %}{{ _('magnet link') }}{% endif %} - {% if result.torrentfile %}{{ _('torrent file') }}{% endif %} - + {% if result.torrentfile %}{{ _('torrent file') }}{% endif %} - {{ _('Seeder') }} : {{ result.seed }}, {{ _('Leecher') }} : {{ result.leech }}

diff --git a/sources/searx/templates/default/result_templates/videos.html b/sources/searx/templates/default/result_templates/videos.html index b85b4cf..5a377b7 100644 --- a/sources/searx/templates/default/result_templates/videos.html +++ b/sources/searx/templates/default/result_templates/videos.html @@ -1,6 +1,6 @@
-

{% if "icon_"~result.engine~".ico" in favicons %}{{result.engine}}{% endif %}{{ result.title|safe }}

+

{% if "icon_"~result.engine~".ico" in favicons %}{{result.engine}}{% endif %}{{ result.title|safe }}

{% if result.publishedDate %}{{ result.publishedDate }}
{% endif %} - {{ result.title|striptags }} + {{ result.title|striptags }}

{{ result.url }}‎

diff --git a/sources/searx/templates/default/results.html b/sources/searx/templates/default/results.html index 3f7712e..927b7b8 100644 --- a/sources/searx/templates/default/results.html +++ b/sources/searx/templates/default/results.html @@ -11,7 +11,7 @@
{{ _('Search URL') }}: - + 1 %}&pageno={{ pageno }}{% endif %}" readonly />
{{ _('Download results') }} diff --git a/sources/searx/templates/oscar/base.html b/sources/searx/templates/oscar/base.html index c185f87..a799376 100644 --- a/sources/searx/templates/oscar/base.html +++ b/sources/searx/templates/oscar/base.html @@ -6,20 +6,24 @@ + {% block meta %}{% endblock %} {% block title %}{% endblock %}searx - + - + + {% for css in styles %} + + {% endfor %} - + {% block styles %} @@ -28,7 +32,7 @@ {% endblock %} - + {% endif %} + {% for script in scripts %} + + {% endfor %} diff --git a/sources/searx/templates/oscar/infobox.html b/sources/searx/templates/oscar/infobox.html index 1aa2e5c..2abdbf0 100644 --- a/sources/searx/templates/oscar/infobox.html +++ b/sources/searx/templates/oscar/infobox.html @@ -20,7 +20,7 @@ {% if infobox.urls %}
{% for url in infobox.urls %} -

{{ url.title }}

+

{{ url.title }}

{% endfor %}
{% endif %} diff --git a/sources/searx/templates/oscar/macros.html b/sources/searx/templates/oscar/macros.html index 1ba1617..5866c13 100644 --- a/sources/searx/templates/oscar/macros.html +++ b/sources/searx/templates/oscar/macros.html @@ -11,15 +11,15 @@ {% macro result_header(result, favicons) -%} -

{% if result.engine~".png" in favicons %}{{ draw_favicon(result.engine) }} {% endif %}{{ result.title|safe }}

+

{% if result.engine~".png" in favicons %}{{ draw_favicon(result.engine) }} {% endif %}{{ result.title|safe }}

{%- endmacro %} {% macro result_sub_header(result) -%} {% if result.publishedDate %}{% endif %} - {{ icon('link') }} {{ _('cached') }} + {{ icon('link') }} {{ _('cached') }} {% if result.magnetlink %}{{ icon('magnet') }} {{ _('magnet link') }}{% endif %} - {% if result.torrentfile %}{{ icon('download-alt') }} {{ _('torrent file') }}{% endif %} + {% if result.torrentfile %}{{ icon('download-alt') }} {{ _('torrent file') }}{% endif %} {%- endmacro %} @@ -59,3 +59,11 @@
{% endif %} {%- endmacro %} + +{% macro checkbox_toggle(id, blocked) -%} +
+ + + +
+{%- endmacro %} diff --git a/sources/searx/templates/oscar/messages/no_cookies.html b/sources/searx/templates/oscar/messages/no_cookies.html new file mode 100644 index 0000000..9bebc8a --- /dev/null +++ b/sources/searx/templates/oscar/messages/no_cookies.html @@ -0,0 +1,5 @@ +{% from 'oscar/macros.html' import icon %} + diff --git a/sources/searx/templates/oscar/opensearch.xml b/sources/searx/templates/oscar/opensearch.xml index f39283f..ff9eac5 100644 --- a/sources/searx/templates/oscar/opensearch.xml +++ b/sources/searx/templates/oscar/opensearch.xml @@ -3,6 +3,7 @@ searx Search searx UTF-8 + {{ host }}{{ url_for('static', filename='img/favicon.png') | replace("/", "", 1) }} searx metasearch {% if opensearch_method == 'get' %} diff --git a/sources/searx/templates/oscar/preferences.html b/sources/searx/templates/oscar/preferences.html index 126bdbd..ea36a14 100644 --- a/sources/searx/templates/oscar/preferences.html +++ b/sources/searx/templates/oscar/preferences.html @@ -1,4 +1,4 @@ -{% from 'oscar/macros.html' import preferences_item_header, preferences_item_header_rtl, preferences_item_footer, preferences_item_footer_rtl %} +{% from 'oscar/macros.html' import preferences_item_header, preferences_item_header_rtl, preferences_item_footer, preferences_item_footer_rtl, checkbox_toggle %} {% extends "oscar/base.html" %} {% block title %}{{ _('preferences') }} - {% endblock %} {% block site_alert_warning_nojs %} @@ -12,159 +12,234 @@

{{ _('Preferences') }}

- - + + - - -
-
-
-
-
- {% if rtl %} -
- {% include 'oscar/categories.html' %} -
- - {% else %} - -
- {% include 'oscar/categories.html' %} -
- {% endif %} -
- {% set language_label = _('Search language') %} - {% set language_info = _('What language do you prefer for search?') %} - {{ preferences_item_header(language_info, language_label, rtl) }} - - {{ preferences_item_footer(language_info, language_label, rtl) }} - - {% set locale_label = _('Interface language') %} - {% set locale_info = _('Change the language of the layout') %} - {{ preferences_item_header(locale_info, locale_label, rtl) }} - - {{ preferences_item_footer(locale_info, locale_label, rtl) }} - - {% set autocomplete_label = _('Autocomplete') %} - {% set autocomplete_info = _('Find stuff as you type') %} - {{ preferences_item_header(autocomplete_info, autocomplete_label, rtl) }} - - {{ preferences_item_footer(autocomplete_info, autocomplete_label, rtl) }} - - {% set image_proxy_label = _('Image proxy') %} - {% set image_proxy_info = _('Proxying image results through searx') %} - {{ preferences_item_header(image_proxy_info, image_proxy_label, rtl) }} - - {{ preferences_item_footer(image_proxy_info, image_proxy_label, rtl) }} - - {% set method_label = _('Method') %} - {% set method_info = _('Change how forms are submited, learn more about request methods') %} - {{ preferences_item_header(method_info, method_label, rtl) }} - - {{ preferences_item_footer(method_info, method_label, rtl) }} - - {% set safesearch_label = _('SafeSearch') %} - {% set safesearch_info = _('Filter content') %} - {{ preferences_item_header(safesearch_info, safesearch_label, rtl) }} - - {{ preferences_item_footer(safesearch_info, safesearch_label, rtl) }} - - {% set theme_label = _('Themes') %} - {% set theme_info = _('Change searx layout') %} - {{ preferences_item_header(theme_info, theme_label, rtl) }} - - {{ preferences_item_footer(theme_info, theme_label, rtl) }} -
-
-
-
- - - - - - - -
- {% for (categ,search_engines) in categs %} - -
-
-
- {% for search_engine in search_engines %} - {% if not search_engine.private %} -
- {% if not rtl %} -
{{ search_engine.name }} ({{ shortcuts[search_engine.name] }})
- {% endif %} -
-
- - - -
-
- {% if rtl %} -
{{ search_engine.name }} ({{ shortcuts[search_engine.name] }})‎
- {% endif %} -
+ + +
+
+
+
+
+ {% if rtl %} +
+ {% include 'oscar/categories.html' %} +
+ + {% else %} + +
+ {% include 'oscar/categories.html' %} +
{% endif %} - {% endfor %} -
+ {% set language_label = _('Search language') %} + {% set language_info = _('What language do you prefer for search?') %} + {{ preferences_item_header(language_info, language_label, rtl) }} + + {{ preferences_item_footer(language_info, language_label, rtl) }} + + {% set locale_label = _('Interface language') %} + {% set locale_info = _('Change the language of the layout') %} + {{ preferences_item_header(locale_info, locale_label, rtl) }} + + {{ preferences_item_footer(locale_info, locale_label, rtl) }} + + {% set autocomplete_label = _('Autocomplete') %} + {% set autocomplete_info = _('Find stuff as you type') %} + {{ preferences_item_header(autocomplete_info, autocomplete_label, rtl) }} + + {{ preferences_item_footer(autocomplete_info, autocomplete_label, rtl) }} + + {% set image_proxy_label = _('Image proxy') %} + {% set image_proxy_info = _('Proxying image results through searx') %} + {{ preferences_item_header(image_proxy_info, image_proxy_label, rtl) }} + + {{ preferences_item_footer(image_proxy_info, image_proxy_label, rtl) }} + + {% set method_label = _('Method') %} + {% set method_info = _('Change how forms are submited, learn more about request methods') %} + {{ preferences_item_header(method_info, method_label, rtl) }} + + {{ preferences_item_footer(method_info, method_label, rtl) }} + + {% set safesearch_label = _('SafeSearch') %} + {% set safesearch_info = _('Filter content') %} + {{ preferences_item_header(safesearch_info, safesearch_label, rtl) }} + + {{ preferences_item_footer(safesearch_info, safesearch_label, rtl) }} + + {% set theme_label = _('Themes') %} + {% set theme_info = _('Change searx layout') %} + {{ preferences_item_header(theme_info, theme_label, rtl) }} + + {{ preferences_item_footer(theme_info, theme_label, rtl) }}
- {% endfor %} +
+
+
+ + + + + + + +
+ {% for categ in all_categories %} + +
+
+
+
+ + + {% if not rtl %} + + + + + + + {% else %} + + + + + + + {% endif %} + + {% for search_engine in engines_by_category[categ] %} + {% if not search_engine.private %} + + {% if not rtl %} + + + + + + + {% else %} + + + + + + + {% endif %} + + {% endif %} + {% endfor %} +
{{ _("Allow") }}{{ _("Engine name") }}{{ _("Shortcut") }}{{ _("SafeSearch") }}{{ _("Avg. time") }}{{ _("Max time") }}{{ _("Max time") }}{{ _("Avg. time") }}{{ _("SafeSearch") }}{{ _("Shortcut") }}{{ _("Engine name") }}{{ _("Allow") }}
{{ checkbox_toggle('engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_'), (search_engine.name, categ) in blocked_engines) }}{{ search_engine.name }}{{ shortcuts[search_engine.name] }}{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}{{ search_engine.timeout }}{{ search_engine.timeout }}{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}{{ shortcuts[search_engine.name] }}{{ search_engine.name }}{{ checkbox_toggle('engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_'), (search_engine.name, categ) in blocked_engines) }}
+
+
+
+
+ {% endfor %} +
+
+
+ +
+
+ {% for plugin in plugins %} +
+
+

{{ plugin.name }}

+
+
+
{{ plugin.description }}
+
+ {{ checkbox_toggle('plugin_' + plugin.id, plugin.id not in allowed_plugins) }} +
+
+
+ {% endfor %} +
+
+
+ +
+ +

+ {{ _('This is the list of cookies and their values searx is storing on your computer.') }}
+ {{ _('With that list, you can assess searx transparency.') }}
+

+ {% if cookies %} + + + + + + + {% for cookie in cookies %} + + + + + {% endfor %} +
{{ _('Cookie name') }}{{ _('Value') }}
{{ cookie }}{{ cookies[cookie] }}
+ {% else %} + {% include 'oscar/messages/no_cookies.html' %} + {% endif %}
-
-

{{ _('These settings are stored in your cookies, this allows us not to store this data about you.') }} -
- {{ _("These cookies serve your sole convenience, we don't use these cookies to track you.") }} -

+

{{ _('These settings are stored in your cookies, this allows us not to store this data about you.') }} +
+ {{ _("These cookies serve your sole convenience, we don't use these cookies to track you.") }} +

- -
{{ _('back') }}
+ +
{{ _('back') }}
+
{{ _('Reset defaults') }}
{% endblock %} diff --git a/sources/searx/templates/oscar/result_templates/code.html b/sources/searx/templates/oscar/result_templates/code.html index 6890c78..582a214 100644 --- a/sources/searx/templates/oscar/result_templates/code.html +++ b/sources/searx/templates/oscar/result_templates/code.html @@ -5,7 +5,7 @@ {% if result.content %}

{{ result.content|safe }}

{% endif %} -{% if result.repository %}

{{ icon('file') }} {{ result.repository }}

{% endif %} +{% if result.repository %}

{{ icon('file') }} {{ result.repository }}

{% endif %}
{{ result.codelines|code_highlighter(result.code_language)|safe }} diff --git a/sources/searx/templates/oscar/result_templates/images.html b/sources/searx/templates/oscar/result_templates/images.html index 3f39ca6..1bfff0a 100644 --- a/sources/searx/templates/oscar/result_templates/images.html +++ b/sources/searx/templates/oscar/result_templates/images.html @@ -1,6 +1,6 @@ {% from 'oscar/macros.html' import draw_favicon %} - + {{ result.title|striptags }} @@ -20,8 +20,8 @@ {{ result.engine }}

{{ result.pretty_url }}

- {{ _('Get image') }} - {{ _('View source') }} + {{ _('Get image') }} + {{ _('View source') }}
diff --git a/sources/searx/templates/oscar/result_templates/videos.html b/sources/searx/templates/oscar/result_templates/videos.html index ddf2894..af48414 100644 --- a/sources/searx/templates/oscar/result_templates/videos.html +++ b/sources/searx/templates/oscar/result_templates/videos.html @@ -15,7 +15,7 @@
- {{ result.title|striptags }} {{ result.engine }} + {{ result.title|striptags }} {{ result.engine }} {% if result.content %}

{{ result.content|safe }}

{% endif %}
diff --git a/sources/searx/templates/oscar/results.html b/sources/searx/templates/oscar/results.html index a758256..9f9bdf1 100644 --- a/sources/searx/templates/oscar/results.html +++ b/sources/searx/templates/oscar/results.html @@ -25,8 +25,8 @@ {% endif %} {% endfor %} - - {% if not results %} + + {% if not results and not answers %} {% include 'oscar/messages/no_results.html' %} {% endif %} @@ -82,7 +82,7 @@ {% for infobox in infoboxes %} {% include 'oscar/infobox.html' %} {% endfor %} - {% endif %} + {% endif %} {% if suggestions %}
@@ -108,10 +108,10 @@
- + 1 %}&pageno={{ pageno }}{% endif %}" readonly>
- +
{% for output_type in ('csv', 'json', 'rss') %} @@ -122,7 +122,7 @@ - {% endfor %} + {% endfor %}
diff --git a/sources/searx/templates/pix-art/about.html b/sources/searx/templates/pix-art/about.html new file mode 100644 index 0000000..cb4b351 --- /dev/null +++ b/sources/searx/templates/pix-art/about.html @@ -0,0 +1,65 @@ +{% extends 'pix-art/base.html' %} +{% block content %} +
+

About searx

+ +

Searx is a metasearch engine, aggregating the results of other search engines while not storing information about its users. +

+

Why use Searx?

+
    +
  • Searx may not offer you as personalised results as Google, but it doesn't generate a profile about you
  • +
  • Searx doesn't care about what you search for, never shares anything with a third party, and it can't be used to compromise you
  • +
  • Searx is free software, the code is 100% open and you can help to make it better. See more on github
  • +
+

If you do care about privacy, want to be a conscious user, or otherwise believe + in digital freedom, make Searx your default search engine or run it on your own server

+ +

Technical details - How does it work?

+ +

Searx is a metasearch engine, +inspired by the seeks project.
+It provides basic privacy by mixing your queries with searches on other platforms without storing search data. Queries are made using a POST request on every browser (except chrome*). Therefore they show up in neither our logs, nor your url history. In case of Chrome* users there is an exception, if Searx used from the search bar it performs GET requests.
+Searx can be added to your browser's search bar; moreover, it can be set as the default search engine. +

+ +

How can I make it my own?

+ +

Searx appreciates your concern regarding logs, so take the code and run it yourself!
Add your Searx to this list to help other people reclaim their privacy and make the Internet freer! +
The more decentralized Internet is the more freedom we have!

+ + +

More about searx

+ + + + +
+ +

FAQ

+ +

How to add to firefox?

+

Install searx as a search engine on any version of Firefox! (javascript required)

+ +

Developer FAQ

+ +

New engines?

+ +

Don't forget to restart searx after config edit!

+ +

Installation/WSGI support?

+

See the installation and setup wiki page

+ +

How to debug engines?

+

Stats page contains some useful data about the engines used.

+ +
+{% endblock %} diff --git a/sources/searx/templates/pix-art/base.html b/sources/searx/templates/pix-art/base.html new file mode 100644 index 0000000..578180c --- /dev/null +++ b/sources/searx/templates/pix-art/base.html @@ -0,0 +1,35 @@ + + + + + + + + + + {% block title %}{% endblock %}searx + + + {% block styles %} + {% endblock %} + {% block meta %}{% endblock %} + {% block head %} + {% endblock %} + + + +
+ {% block content %} + {% endblock %} + + + +
+ + diff --git a/sources/searx/templates/pix-art/index.html b/sources/searx/templates/pix-art/index.html new file mode 100644 index 0000000..d398cc8 --- /dev/null +++ b/sources/searx/templates/pix-art/index.html @@ -0,0 +1,12 @@ +{% extends "pix-art/base.html" %} +{% block content %} +
+

Searx Logo

+ {% include 'pix-art/search.html' %} +

+ {{ _('about') }} + {{ _('preferences') }} +

+
+{% endblock %} + diff --git a/sources/searx/templates/pix-art/preferences.html b/sources/searx/templates/pix-art/preferences.html new file mode 100644 index 0000000..0caf31b --- /dev/null +++ b/sources/searx/templates/pix-art/preferences.html @@ -0,0 +1,82 @@ +{% extends "default/base.html" %} +{% block head %} {% endblock %} +{% block content %} +
+

{{ _('Preferences') }}

+ +
+
+ {{ _('Search language') }} +

+ +

+
+
+ {{ _('Interface language') }} +

+ +

+
+
+ {{ _('Method') }} +

+ +

+
+
+ {{ _('Themes') }} +

+ +

+
+
+ {{ _('Currently used search engines') }} + + + + + + + {% for (categ,search_engines) in categs %} + {% for search_engine in search_engines %} + + {% if not search_engine.private %} + + + + + {% endif %} + {% endfor %} + {% endfor %} +
{{ _('Engine name') }}{{ _('Allow') }} / {{ _('Block') }}
{{ search_engine.name }} ({{ shortcuts[search_engine.name] }})‎ + + + +
+
+

{{ _('These settings are stored in your cookies, this allows us not to store this data about you.') }} +
+ {{ _("These cookies serve your sole convenience, we don't use these cookies to track you.") }} +

+ + + +
+
+{% endblock %} diff --git a/sources/searx/templates/pix-art/result_templates/default.html b/sources/searx/templates/pix-art/result_templates/default.html new file mode 100644 index 0000000..ada81e5 --- /dev/null +++ b/sources/searx/templates/pix-art/result_templates/default.html @@ -0,0 +1,7 @@ + + + + + diff --git a/sources/searx/templates/pix-art/result_templates/images.html b/sources/searx/templates/pix-art/result_templates/images.html new file mode 100644 index 0000000..d85f841 --- /dev/null +++ b/sources/searx/templates/pix-art/result_templates/images.html @@ -0,0 +1,6 @@ + diff --git a/sources/searx/templates/pix-art/results.html b/sources/searx/templates/pix-art/results.html new file mode 100644 index 0000000..9385b60 --- /dev/null +++ b/sources/searx/templates/pix-art/results.html @@ -0,0 +1,32 @@ +{% if pageno > 1 %} + {% for result in results %} + {% set index = loop.index %} + {% include 'pix-art/result_templates/default.html' %} + {% endfor %} +{% else %} +{% extends "pix-art/base.html" %} +{% block title %}{{ q }} - {% endblock %} +{% block meta %}{% endblock %} +{% block content %} + + + + +
+ + {% for result in results %} + {% set index = loop.index %} + {% include 'pix-art/result_templates/default.html' %} + {% endfor %} + + +
+{% endblock %} +{% endif %} \ No newline at end of file diff --git a/sources/searx/templates/pix-art/search.html b/sources/searx/templates/pix-art/search.html new file mode 100644 index 0000000..4d129ec --- /dev/null +++ b/sources/searx/templates/pix-art/search.html @@ -0,0 +1,9 @@ +
+
+ + + {% for category in categories %} + + {% endfor %} +
+
diff --git a/sources/searx/templates/pix-art/stats.html b/sources/searx/templates/pix-art/stats.html new file mode 100644 index 0000000..70fe98a --- /dev/null +++ b/sources/searx/templates/pix-art/stats.html @@ -0,0 +1,22 @@ +{% extends "default/base.html" %} +{% block head %} {% endblock %} +{% block content %} +

{{ _('Engine stats') }}

+ +{% for stat_name,stat_category in stats %} +
+ + + + + {% for engine in stat_category %} + + + + + + {% endfor %} +
{{ stat_name }}
{{ engine.name }}{{ '%.02f'|format(engine.avg) }}
 
+
+{% endfor %} +{% endblock %} diff --git a/sources/searx/testing.py b/sources/searx/testing.py index 51c44d8..e22ecf8 100644 --- a/sources/searx/testing.py +++ b/sources/searx/testing.py @@ -56,9 +56,7 @@ class SearxRobotLayer(Layer): ) def tearDown(self): - # send TERM signal to all processes in my group, to stop subprocesses - os.killpg(os.getpgid(self.server.pid), 15) - + os.kill(self.server.pid, 15) # remove previously set environment variable del os.environ['SEARX_SETTINGS_PATH'] diff --git a/sources/searx/tests/engines/test_bing.py b/sources/searx/tests/engines/test_bing.py index 52a049f..bce2214 100644 --- a/sources/searx/tests/engines/test_bing.py +++ b/sources/searx/tests/engines/test_bing.py @@ -29,10 +29,10 @@ class TestBingEngine(SearxTestCase): self.assertRaises(AttributeError, bing.response, '') self.assertRaises(AttributeError, bing.response, '[]') - response = mock.Mock(content='') + response = mock.Mock(text='') self.assertEqual(bing.response(response), []) - response = mock.Mock(content='') + response = mock.Mock(text='') self.assertEqual(bing.response(response), []) html = """ @@ -54,7 +54,7 @@ class TestBingEngine(SearxTestCase): """ - response = mock.Mock(content=html) + response = mock.Mock(text=html) results = bing.response(response) self.assertEqual(type(results), list) self.assertEqual(len(results), 1) @@ -81,7 +81,7 @@ class TestBingEngine(SearxTestCase): """ - response = mock.Mock(content=html) + response = mock.Mock(text=html) results = bing.response(response) self.assertEqual(type(results), list) self.assertEqual(len(results), 1) diff --git a/sources/searx/tests/engines/test_bing_images.py b/sources/searx/tests/engines/test_bing_images.py index a1d96b0..f42dff7 100644 --- a/sources/searx/tests/engines/test_bing_images.py +++ b/sources/searx/tests/engines/test_bing_images.py @@ -31,10 +31,10 @@ class TestBingImagesEngine(SearxTestCase): self.assertRaises(AttributeError, bing_images.response, '') self.assertRaises(AttributeError, bing_images.response, '[]') - response = mock.Mock(content='') + response = mock.Mock(text='') self.assertEqual(bing_images.response(response), []) - response = mock.Mock(content='') + response = mock.Mock(text='') self.assertEqual(bing_images.response(response), []) html = """ @@ -52,14 +52,14 @@ oh:"238",tft:"0",oi:"http://www.image.url/Images/Test%2 """ html = html.replace('\r\n', '').replace('\n', '').replace('\r', '') - response = mock.Mock(content=html) + response = mock.Mock(text=html) results = bing_images.response(response) self.assertEqual(type(results), list) self.assertEqual(len(results), 1) self.assertEqual(results[0]['title'], 'Test Query') self.assertEqual(results[0]['url'], 'http://www.page.url/') self.assertEqual(results[0]['content'], '') - self.assertEqual(results[0]['thumbnail_src'], 'http://ts1.mm.bing.net/th?id=HN.608003696942779811') + self.assertEqual(results[0]['thumbnail_src'], 'https://www.bing.com/th?id=HN.608003696942779811') self.assertEqual(results[0]['img_src'], 'http://test.url/Test%20Query.jpg') html = """ @@ -75,7 +75,7 @@ oh:"238",tft:"0",oi:"http://www.image.url/Images/Test%2 style="height:144px;" width="178" height="144"/> """ - response = mock.Mock(content=html) + response = mock.Mock(text=html) results = bing_images.response(response) self.assertEqual(type(results), list) self.assertEqual(len(results), 0) @@ -263,7 +263,7 @@ oh:"238",tft:"0",oi:"http://www.image.url/Images/Test%2 """ html = html.replace('\r\n', '').replace('\n', '').replace('\r', '') - response = mock.Mock(content=html) + response = mock.Mock(text=html) results = bing_images.response(response) self.assertEqual(type(results), list) self.assertEqual(len(results), 10) diff --git a/sources/searx/tests/engines/test_bing_news.py b/sources/searx/tests/engines/test_bing_news.py index f22b80e..c6c4026 100644 --- a/sources/searx/tests/engines/test_bing_news.py +++ b/sources/searx/tests/engines/test_bing_news.py @@ -2,6 +2,7 @@ from collections import defaultdict import mock from searx.engines import bing_news from searx.testing import SearxTestCase +import lxml class TestBingNewsEngine(SearxTestCase): @@ -16,14 +17,10 @@ class TestBingNewsEngine(SearxTestCase): self.assertIn(query, params['url']) self.assertIn('bing.com', params['url']) self.assertIn('fr', params['url']) - self.assertIn('_FP', params['cookies']) - self.assertIn('en', params['cookies']['_FP']) dicto['language'] = 'all' params = bing_news.request(query, dicto) self.assertIn('en', params['url']) - self.assertIn('_FP', params['cookies']) - self.assertIn('en', params['cookies']['_FP']) def test_response(self): self.assertRaises(AttributeError, bing_news.response, None) @@ -31,206 +28,111 @@ class TestBingNewsEngine(SearxTestCase): self.assertRaises(AttributeError, bing_news.response, '') self.assertRaises(AttributeError, bing_news.response, '[]') - response = mock.Mock(content='') + response = mock.Mock(text='') self.assertEqual(bing_news.response(response), []) - response = mock.Mock(content='') + response = mock.Mock(text='') self.assertEqual(bing_news.response(response), []) - html = """ -
- -
- - - -
-
-
- Article Content - - metronews.fr -  · - 44 minutes ago - -
-
-
- """ - response = mock.Mock(content=html) + html = """ + + + python - Bing News + https://www.bing.com:443/news/search?q=python&setmkt=en-US&first=1&format=RSS + Search results + + http://10.53.64.9/rsslogo.gif + test + https://www.bing.com:443/news/search?q=test&setmkt=en-US&first=1&format=RSS + + Copyright + + Title + https://www.bing.com/news/apiclick.aspx?ref=FexRss&aid=&tid=c237eccc50bd4758b106a5e3c94fce09&url=http%3a%2f%2furl.of.article%2f&c=xxxxxxxxx&mkt=en-us + Article Content + Tue, 02 Jun 2015 13:37:00 GMT + Infoworld + http://a1.bing4.com/th?id=ON.13371337133713371337133713371337&pid=News + w={0}&h={1}&c=7 + + 620 + 413 + + + Another Title + https://www.bing.com/news/apiclick.aspx?ref=FexRss&aid=&tid=c237eccc50bd4758b106a5e3c94fce09&url=http%3a%2f%2fanother.url.of.article%2f&c=xxxxxxxxx&mkt=en-us + Another Article Content + Tue, 02 Jun 2015 13:37:00 GMT + + +""" # noqa + response = mock.Mock(text=html) + results = bing_news.response(response) + self.assertEqual(type(results), list) + self.assertEqual(len(results), 2) + self.assertEqual(results[0]['title'], 'Title') + self.assertEqual(results[0]['url'], 'http://url.of.article/') + self.assertEqual(results[0]['content'], 'Article Content') + self.assertEqual(results[0]['thumbnail'], 'https://www.bing.com/th?id=ON.13371337133713371337133713371337') + self.assertEqual(results[1]['title'], 'Another Title') + self.assertEqual(results[1]['url'], 'http://another.url.of.article/') + self.assertEqual(results[1]['content'], 'Another Article Content') + self.assertNotIn('thumbnail', results[1]) + + html = """ + + + python - Bing News + https://www.bing.com:443/news/search?q=python&setmkt=en-US&first=1&format=RSS + Search results + + http://10.53.64.9/rsslogo.gif + test + https://www.bing.com:443/news/search?q=test&setmkt=en-US&first=1&format=RSS + + Copyright + + Title + http://another.url.of.article/ + Article Content + garbage + Infoworld + http://another.bing.com/image + w={0}&h={1}&c=7 + + 620 + 413 + + +""" # noqa + response = mock.Mock(text=html) results = bing_news.response(response) self.assertEqual(type(results), list) self.assertEqual(len(results), 1) self.assertEqual(results[0]['title'], 'Title') - self.assertEqual(results[0]['url'], 'http://url.of.article/') + self.assertEqual(results[0]['url'], 'http://another.url.of.article/') self.assertEqual(results[0]['content'], 'Article Content') + self.assertEqual(results[0]['thumbnail'], 'http://another.bing.com/image') - html = """ -
- -
- - - -
-
-
- Article Content - - metronews.fr -  · - 44 minutes ago - -
-
-
-
- -
- - - -
-
-
- Article Content - - metronews.fr -  · - 3 hours, 44 minutes ago - -
-
-
-
- -
- - - -
-
-
- Article Content - - metronews.fr -  · - 44 hours ago - -
-
-
-
- -
- - - -
-
-
- Article Content - - metronews.fr -  · - 2 days ago - -
-
-
-
- -
- - - -
-
-
- Article Content - - metronews.fr -  · - 27/01/2015 - -
-
-
-
- -
- - - -
-
-
- Article Content - - metronews.fr -  · - Il y a 3 heures - -
-
-
- """ - response = mock.Mock(content=html) - results = bing_news.response(response) - self.assertEqual(type(results), list) - self.assertEqual(len(results), 6) + html = """ + + + python - Bing News + https://www.bing.com:443/news/search?q=python&setmkt=en-US&first=1&format=RSS + Search results + + http://10.53.64.9/rsslogo.gif + test + https://www.bing.com:443/news/search?q=test&setmkt=en-US&first=1&format=RSS + + +""" # noqa - html = """ - -
- - - -
-
-
- Article Content - - metronews.fr -  · - 44 minutes ago - -
-
- """ - response = mock.Mock(content=html) + response = mock.Mock(text=html) results = bing_news.response(response) self.assertEqual(type(results), list) self.assertEqual(len(results), 0) + + html = """gabarge""" + response = mock.Mock(text=html) + self.assertRaises(lxml.etree.XMLSyntaxError, bing_news.response, response) diff --git a/sources/searx/tests/engines/test_blekko_images.py b/sources/searx/tests/engines/test_blekko_images.py index 793fadb..beb0853 100644 --- a/sources/searx/tests/engines/test_blekko_images.py +++ b/sources/searx/tests/engines/test_blekko_images.py @@ -12,9 +12,14 @@ class TestBlekkoImagesEngine(SearxTestCase): dicto['pageno'] = 0 dicto['safesearch'] = 1 params = blekko_images.request(query, dicto) - self.assertTrue('url' in params) - self.assertTrue(query in params['url']) - self.assertTrue('blekko.com' in params['url']) + self.assertIn('url', params) + self.assertIn(query, params['url']) + self.assertIn('blekko.com', params['url']) + self.assertIn('page', params['url']) + + dicto['pageno'] = 1 + params = blekko_images.request(query, dicto) + self.assertNotIn('page', params['url']) def test_response(self): self.assertRaises(AttributeError, blekko_images.response, None) diff --git a/sources/searx/tests/engines/test_currency_convert.py b/sources/searx/tests/engines/test_currency_convert.py index 271ed03..84ec3b7 100644 --- a/sources/searx/tests/engines/test_currency_convert.py +++ b/sources/searx/tests/engines/test_currency_convert.py @@ -27,9 +27,11 @@ class TestCurrencyConvertEngine(SearxTestCase): def test_response(self): dicto = defaultdict(dict) - dicto['ammount'] = 10 + dicto['ammount'] = float(10) dicto['from'] = "EUR" dicto['to'] = "USD" + dicto['from_name'] = "euro" + dicto['to_name'] = "United States dollar" response = mock.Mock(text='a,b,c,d', search_params=dicto) self.assertEqual(currency_convert.response(response), []) @@ -38,7 +40,7 @@ class TestCurrencyConvertEngine(SearxTestCase): results = currency_convert.response(response) self.assertEqual(type(results), list) self.assertEqual(len(results), 1) - self.assertEqual(results[0]['answer'], '10 EUR = 5.0 USD (1 EUR = 0.5 USD)') + self.assertEqual(results[0]['answer'], '10.0 EUR = 5.0 USD, 1 EUR (euro) = 0.5 USD (United States dollar)') now_date = datetime.now().strftime('%Y%m%d') - self.assertEqual(results[0]['url'], 'http://finance.yahoo.com/currency/converter-results/' + - now_date + '/10-eur-to-usd.html') + self.assertEqual(results[0]['url'], 'https://finance.yahoo.com/currency/converter-results/' + + now_date + '/10.0-eur-to-usd.html') diff --git a/sources/searx/tests/engines/test_deezer.py b/sources/searx/tests/engines/test_deezer.py index c8c2c90..ad09d2a 100644 --- a/sources/searx/tests/engines/test_deezer.py +++ b/sources/searx/tests/engines/test_deezer.py @@ -30,9 +30,9 @@ class TestDeezerEngine(SearxTestCase): json = """ {"data":[ {"id":100, "title":"Title of track", - "link":"http:\/\/www.deezer.com\/track\/1094042","duration":232, + "link":"https:\/\/www.deezer.com\/track\/1094042","duration":232, "artist":{"id":200,"name":"Artist Name", - "link":"http:\/\/www.deezer.com\/artist\/1217","type":"artist"}, + "link":"https:\/\/www.deezer.com\/artist\/1217","type":"artist"}, "album":{"id":118106,"title":"Album Title","type":"album"},"type":"track"} ]} """ @@ -41,14 +41,14 @@ class TestDeezerEngine(SearxTestCase): self.assertEqual(type(results), list) self.assertEqual(len(results), 1) self.assertEqual(results[0]['title'], 'Title of track') - self.assertEqual(results[0]['url'], 'http://www.deezer.com/track/1094042') + self.assertEqual(results[0]['url'], 'https://www.deezer.com/track/1094042') self.assertEqual(results[0]['content'], 'Artist Name • Album Title • Title of track') self.assertTrue('100' in results[0]['embedded']) json = """ {"data":[ {"id":200,"name":"Artist Name", - "link":"http:\/\/www.deezer.com\/artist\/1217","type":"artist"} + "link":"https:\/\/www.deezer.com\/artist\/1217","type":"artist"} ]} """ response = mock.Mock(text=json) diff --git a/sources/searx/tests/engines/test_deviantart.py b/sources/searx/tests/engines/test_deviantart.py index 9cf68d0..78a3913 100644 --- a/sources/searx/tests/engines/test_deviantart.py +++ b/sources/searx/tests/engines/test_deviantart.py @@ -75,7 +75,7 @@ class TestDeviantartEngine(SearxTestCase): self.assertEqual(results[0]['title'], 'Title of image') self.assertEqual(results[0]['url'], 'http://url.of.result/2nd.part.of.url') self.assertNotIn('content', results[0]) - self.assertEqual(results[0]['thumbnail_src'], 'http://url.of.thumbnail') + self.assertEqual(results[0]['thumbnail_src'], 'https://url.of.thumbnail') html = """ diff --git a/sources/searx/tests/engines/test_duckduckgo.py b/sources/searx/tests/engines/test_duckduckgo.py index 6f085cb..14cd9cd 100644 --- a/sources/searx/tests/engines/test_duckduckgo.py +++ b/sources/searx/tests/engines/test_duckduckgo.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from collections import defaultdict import mock from searx.engines import duckduckgo @@ -30,7 +31,7 @@ class TestDuckduckgoEngine(SearxTestCase): response = mock.Mock(text='') self.assertEqual(duckduckgo.response(response), []) - html = """ + html = u"""