[
  {
    "path": ".flake8",
    "content": "[flake8]\nignore = E402,E501\n"
  },
  {
    "path": ".github/workflows/makefile.yml",
    "content": "name: Makefile CI\n\non:\n  push:\n    branches: [ \"master\" ]\n  pull_request:\n    branches: [ \"master\" ]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n\n        # Set up Python environment\n      - name: Set up Python\n        uses: actions/setup-python@v4\n        with:\n          python-version: '3.11'  # Specify the Python version you need (3.11 required for pyjq)\n\n      - name: Create and activate virtual environment\n        run: |\n          python -m venv venv\n          source venv/bin/activate\n          echo \"Virtual environment created and activated.\"\n\n      - name: Install Python dependencies\n        run: |\n          sudo apt-get install libjq-dev\n          source venv/bin/activate\n          pip install -r requirements.txt\n\n      - name: Add Python virtual environment to PATH\n        run: |\n          echo \"${{ github.workspace }}/venv/bin\" >> $GITHUB_PATH\n\n      # Set up Go environment\n      - name: Set up Go\n        uses: actions/setup-go@v4\n        with:\n          go-version: '1.24'  # Replace with the needed Go version\n\n      - name: Install gofumpt\n        run: |\n          go install mvdan.cc/gofumpt@latest\n\n      - name: Install goimports\n        run: |\n          go install golang.org/x/tools/cmd/goimports@latest\n\n      - name: Install swagger\n        run: |\n          cd /tmp \\\n          && go install github.com/go-swagger/go-swagger/cmd/swagger@latest\n\n      - name: Add Go bin to PATH\n        run: |\n          echo \"${{ runner.temp }}/go/bin\" >> $GITHUB_PATH\n\n\n      - name: Install dependencies\n        run: make\n\n      - name: Run check\n        run: make check\n"
  },
  {
    "path": ".gitignore",
    "content": "ve/\nshare/static/fonts/\n*.pyc\ndata/\nlog/\n.idea/\n*.swp\n*.mmdb\n*.dat\n"
  },
  {
    "path": ".golangci.yaml",
    "content": "run:\n  skip-dirs:\n    - pkg/curlator\nlinters:\n  enable-all: true\n  disable:\n    - wsl\n    - wrapcheck\n    - varnamelen\n    - gci\n    - exhaustivestruct\n    - exhaustruct\n    - gomnd\n    - gofmt\n\n    # to be fixed:\n    - ireturn\n    - gosec\n    - noctx\n    - interfacer\n\n    # deprecated:\n    - scopelint\n    - deadcode\n    - varcheck\n    - maligned\n    - ifshort\n    - nosnakecase\n    - structcheck\n    - golint\n"
  },
  {
    "path": ".travis.yml",
    "content": "group: travis_latest\nlanguage: python\ncache: pip\npython:\n    - 3.7\ninstall:\n    - pip install flake8 -r requirements.txt\nbefore_script:\n    # stop the build if there are Python syntax errors or undefined names\n    - flake8 bin lib --count --select=E9,F63,F7,F82 --show-source --statistics\n    # exit-zero treats all errors as warnings.  The GitHub editor is 127 chars wide\n    - flake8 bin lib --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics\nscript:\n    - true  # pytest --capture=sys  # add other tests here\nnotifications:\n    on_success: change\n    on_failure: change  # `always` will be the setting once code changes slow down.\n"
  },
  {
    "path": "Dockerfile",
    "content": "# Build stage\nFROM golang:1-alpine as builder\n\nWORKDIR /app\n\nCOPY ./share/we-lang/ /app\n\nRUN apk add --no-cache git\n\nRUN go get -u github.com/mattn/go-colorable && \\\n    go get -u github.com/klauspost/lctime && \\\n    go get -u github.com/mattn/go-runewidth && \\\n    cd /app && CGO_ENABLED=0 go build .\n\n# Application stage\nFROM alpine:3.21.1\n\nWORKDIR /app\n\nCOPY ./requirements.txt /app\n\nENV LLVM_CONFIG=/usr/bin/llvm11-config\n\nRUN apk add --no-cache --virtual .build \\\n    autoconf \\\n    automake \\\n    g++ \\\n    gcc \\\n    jpeg-dev \\\n    llvm11-dev\\\n    make \\\n    zlib-dev \\\n    && apk add --no-cache \\\n    python3 \\\n    py3-pip \\\n    py3-scipy \\\n    py3-wheel \\\n    py3-gevent \\\n    zlib \\\n    jpeg \\\n    llvm11 \\\n    libtool \\\n    supervisor \\\n    py3-numpy-dev \\\n    python3-dev && \\\n    mkdir -p /app/cache && \\\n    mkdir -p /var/log/supervisor && \\\n    mkdir -p /etc/supervisor/conf.d && \\\n    chmod -R o+rw /var/log/supervisor && \\\n    chmod -R o+rw /var/run && \\\n    pip install -r requirements.txt --no-cache-dir && \\\n    apk del --no-cache -r .build\n\nCOPY --from=builder /app/wttr.in /app/bin/wttr.in\nCOPY ./bin /app/bin\nCOPY ./lib /app/lib\nCOPY ./share /app/share\nCOPY share/docker/supervisord.conf /etc/supervisor/supervisord.conf\n\nENV WTTR_MYDIR=\"/app\"\nENV WTTR_GEOLITE=\"/app/GeoLite2-City.mmdb\"\nENV WTTR_WEGO=\"/app/bin/wttr.in\"\nENV WTTR_LISTEN_HOST=\"0.0.0.0\"\nENV WTTR_LISTEN_PORT=\"8002\"\n\nEXPOSE 8002\n\nCMD [\"/usr/bin/supervisord\", \"-c\", \"/etc/supervisor/supervisord.conf\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n"
  },
  {
    "path": "Makefile",
    "content": "srv: srv.go internal/*/*.go internal/*/*/*.go\n\t#go build -o srv -ldflags '-w -linkmode external -extldflags \"-static\"' ./\n\tgo build -o srv ./\n\ncheck:\n\ttrue\n\ngo-test:\n\tgo test ./...\n\nlint:\n\tgolangci-lint run ./...\n"
  },
  {
    "path": "README.md",
    "content": "\n*wttr.in — the right way to ~check~ `curl` the weather!*\n\nwttr.in is a console-oriented weather forecast service that supports various information\nrepresentation methods like terminal-oriented ANSI-sequences for console HTTP clients\n(curl, httpie, or wget), HTML for web browsers, or PNG for graphical viewers.\n\nOriginally started as a small project, a wrapper for [wego](https://github.com/schachmat/wego),\nintended to demonstrate the power of the console-oriented services,\n*wttr.in* became a popular weather reporting service, handling tens of millions[¹](#wttrin-usage-stats) of queries daily.\n\nYou can see it running here: [wttr.in](https://wttr.in).\n\n[Documentation](https://wttr.in/:help) | [Usage](https://github.com/chubin/wttr.in#usage) | [One-line output](https://github.com/chubin/wttr.in#one-line-output) | [Data-rich output format](https://github.com/chubin/wttr.in#data-rich-output-format-v2) | [Map view](https://github.com/chubin/wttr.in#map-view-v3) | [Output formats](https://github.com/chubin/wttr.in#different-output-formats) | [Moon phases](https://github.com/chubin/wttr.in#moon-phases) | [Internationalization](https://github.com/chubin/wttr.in#internationalization-and-localization) | [Installation](https://github.com/chubin/wttr.in#installation)\n\n## Usage\n\nYou can access the service from a shell or from a Web browser like this:\n\n    $ curl wttr.in\n    Weather for City: Paris, France\n\n         \\   /     Clear\n          .-.      10 – 11 °C\n       ― (   ) ―   ↑ 11 km/h\n          `-’      10 km\n         /   \\     0.0 mm\n\n\nHere is an example weather report:\n\n![Weather Report](share/pics/San_Francisco.png)\n\nOr in PowerShell:\n\n```PowerShell\nInvoke-RestMethod https://wttr.in\n```\n\nWant to get the weather information for a specific location? You can add the desired location to the URL in your\nrequest like this:\n\n    $ curl wttr.in/London\n    $ curl wttr.in/Moscow\n    $ curl wttr.in/Salt+Lake+City\n\nIf you omit the location name, you will get the report for your current location based on your IP address.\n\nUse 3-letter airport codes in order to get the weather information at a certain airport:\n\n    $ curl wttr.in/muc      # Weather for IATA: muc, Munich International Airport, Germany\n    $ curl wttr.in/ham      # Weather for IATA: ham, Hamburg Airport, Germany\n\nLet's say you'd like to get the weather for a geographical location other than a town or city - maybe an attraction\nin a city, a mountain name, or some special location. Add the character `~` before the name to look up that special\nlocation name before the weather is then retrieved:\n\n\t$ curl wttr.in/~Vostok+Station\n\t$ curl wttr.in/~Eiffel+Tower\n\t$ curl wttr.in/~Kilimanjaro\n\nFor these examples, you'll see a line below the weather forecast output that shows the geolocation\nresults of looking up the location:\n\n\tLocation: Vostok Station, станция Восток, AAT, Antarctica [-78.4642714,106.8364678]\n    Location: Tour Eiffel, 5, Avenue Anatole France, Gros-Caillou, 7e, Paris, Île-de-France, 75007, France [48.8582602,2.29449905432]\n\tLocation: Kilimanjaro, Northern, Tanzania [-3.4762789,37.3872648]\n\nYou can also use IP-addresses (direct) or domain names (prefixed with `@`) to specify a location:\n\n    $ curl wttr.in/@github.com\n    $ curl wttr.in/@msu.ru\n\nTo get detailed information online, you can access the [/:help](https://wttr.in/:help) page:\n\n    $ curl wttr.in/:help\n\n### Weather Units\n\nBy default the USCS units are used for the queries from the USA and the metric system for the rest of the world.\nYou can override this behavior by adding `?u`, `?m` or `?M`   to a URL like this:\n\n    $ curl wttr.in/Amsterdam?u  # USCS (used by default in US)\n    $ curl wttr.in/Amsterdam?m  # metric (SI) (used by default everywhere except US)\n    $ curl wttr.in/Amsterdam?M  # metric (SI), but show wind speed in m/s\n\nIf you have several options to pass, write them without delimiters in between for the one-letter options,\nand use `&` as a delimiter for the long options with values:\n\n    $ curl 'wttr.in/Amsterdam?m2&lang=nl'\n\nIt would be a rough equivalent of `-m2 --lang nl` for the GNU CLI syntax.\n\n## Supported output formats and views\n\nwttr.in currently supports five output formats:\n\n* ANSI for the terminal;\n* Plain-text for the terminal and scripts;\n* HTML for the browser;\n* PNG for the graphical viewers;\n* JSON for scripts and APIs;\n* Prometheus metrics for scripts and APIs.\n\nThe ANSI and HTML formats are selected based on the User-Agent string.\n\nTo force plain text, which disables colors:\n\n    $ curl wttr.in/?T\n\nTo restrict output to glyphs available in standard console fonts (e.g. Consolas and Lucida Console):\n\n    $ curl wttr.in/?d\n\nThe PNG format can be forced by adding `.png` to the end of the query:\n\n    $ wget wttr.in/Paris.png\n\nYou can use all of the options with the PNG-format like in an URL, but you have\nto separate them with `_` instead of `?` and `&`:\n\n    $ wget wttr.in/Paris_0tqp_lang=fr.png\n\nUseful options for the PNG format:\n\n* `t` for transparency (`transparency=150`);\n* transparency=0..255 for a custom transparency level.\n\nTransparency is a useful feature when weather PNGs are used to add weather data to pictures:\n\n    $ convert source.jpg <( curl wttr.in/Oymyakon_tqp0.png ) -geometry +50+50 -composite target.jpg\n\nIn this example:\n\n* `source.jpg` - source file;\n* `target.jpg` - target file;\n* `Oymyakon` - name of the location;\n* `tqp0` - options (recommended).\n\n![Picture with weather data](https://pbs.twimg.com/media/C69-wsIW0AAcAD5.jpg)\n\nYou can embed a special wttr.in widget, that displays the weather condition for the current or a selected location, into a HTML page using the [wttr-switcher](https://github.com/midzer/wttr-switcher). That is how it looks like: [wttr-switcher-example](https://midzer.github.io/wttr-switcher/) or on a real world web site: https://feuerwehr-eisolzried.de/.\n\n![Embedded wttr.in example at feuerwehr-eisolzried.de](https://user-images.githubusercontent.com/3875145/65265457-50eac180-db11-11e9-8f9b-2e1711dfc436.png)\n\n## One-line output\n\nOne-line output format is convenient to be used to show weather info\nin status bar of different programs, such as *tmux*, *weechat*, etc.\n\nFor one-line output format, specify additional URL parameter `format`:\n\n```\n$ curl wttr.in/Nuremberg?format=3\nNuremberg: 🌦 +11⁰C\n```\n\nAvailable preconfigured formats: 1, 2, 3, 4 and the custom format using the percent notation (see below).\n* 1: Current weather at location: `🌦 +11⁰C`\n* 2: Current weather at location with more details: `🌦   🌡️+11°C 🌬️↓4km/h`\n* 3: Name of location and current weather at location: `Nuremberg: 🌦 +11⁰C`\n* 4: Name of location and current weather at location with more details: `Nuremberg: 🌦   🌡️+11°C 🌬️↓4km/h`\n\nYou can specify multiple locations separated with `:` (for repeating queries):\n\n```\n$ curl wttr.in/Nuremberg:Hamburg:Berlin?format=3\nNuremberg: 🌦 +11⁰C\n```\nOr to process all this queries at once:\n\n```\n$ curl -s 'wttr.in/{Nuremberg,Hamburg,Berlin}?format=3'\nNuremberg: 🌦 +11⁰C\nHamburg: 🌦 +8⁰C\nBerlin: 🌦 +8⁰C\n```\n\nTo specify your own custom output format, use the special `%`-notation:\n\n```\n    c    Weather condition,\n    C    Weather condition textual name,\n    x    Weather condition, plain-text symbol,\n    h    Humidity,\n    t    Temperature (Actual),\n    f    Temperature (Feels Like),\n    w    Wind,\n    l    Location,\n    m    Moon phase 🌑🌒🌓🌔🌕🌖🌗🌘,\n    M    Moon day,\n    p    Precipitation (mm/3 hours),\n    P    Pressure (hPa),\n    e    Dew point,\n    u    UV index (1-12),\n\n    D    Dawn*,\n    S    Sunrise*,\n    z    Zenith*,\n    s    Sunset*,\n    d    Dusk*,\n    T    Current time*,\n    Z    Local timezone.\n\n(*times are shown in the local timezone)\n```\n\nSo, these two calls are the same:\n\n```\n    $ curl wttr.in/London?format=3\n    London: ⛅️ +7⁰C\n    $ curl wttr.in/London?format=\"%l:+%c+%t\\n\"\n    London: ⛅️ +7⁰C\n```\n\n## Integrations\n\nThanks to the ease of integrating *wttr.in* into any program, there are a\nplethora of popular integrations across various libraries, programming\nlanguages, and systems.\n\n*wttr.in* is compatible with:\n\n* terminal managers,\n* window managers,\n* editors,\n* chat clients,\n\nand more, these integrations enhance workflow efficiency by embedding weather information directly into user interfaces.\n\nSee the full list of integrations here: [wttr.in integrations](doc/integrations.md)\nand some of them below.\n\n### tmux\n\nWhen using in `tmux.conf`, you have to escape `%` with `%`, i.e. write there `%%` instead of `%`.\n\nThe output does not contain new line by default, when the %-notation is used, but it does contain it when preconfigured format (`1`,`2`,`3` etc.)\nare used. To have the new line in the output when the %-notation is used, use '\\n' and single quotes when doing a query from the shell.\n\nIn programs, that are querying the service automatically (such as tmux), it is better to use some reasonable update interval. In tmux, you can configure it with `status-interval`.\n\nIf several, `:` separated locations, are specified in the query, specify update period\nas an additional query parameter `period=`:\n```\nset -g status-interval 60\nWEATHER='#(curl -s wttr.in/London:Stockholm:Moscow\\?format\\=\"%%l:+%%c%%20%%t%%60%%w&period=60\")'\nset -g status-right \"$WEATHER ...\"\n```\n![wttr.in in tmux status bar](https://wttr.in/files/example-tmux-status-line.png)\n\n### WeeChat\n\nTo embed in to an IRC ([WeeChat](https://github.com/weechat/weechat)) client's existing status bar:\n\n```\n/alias add wttr /exec -pipe \"/mute /set plugins.var.wttr\" url:wttr.in/Montreal?format=%l:+%c+%f+%h+%p+%P+%m+%w+%S+%s;/wait 3 /item refresh wttr\n/trigger add wttr timer 60000;0;0 \"\" \"\" \"/wttr\"\n/item add wttr \"\" \"${plugins.var.wttr}\"\n/eval /set weechat.bar.status.items ${weechat.bar.status.items},spacer,wttr\n/eval /set weechat.startup.command_after_plugins ${weechat.startup.command_after_plugins};/wttr\n/wttr\n```\n![wttr.in in WeeChat status bar](https://i.imgur.com/XkYiRU7.png)\n\n\n### conky\n\nConky usage example:\n\n```\n${texeci 1800 curl wttr.in/kyiv_0pq_lang=uk.png\n  | convert - -transparent black $HOME/.config/conky/out.png}\n${image $HOME/.config/conky/out.png -p 0,0}\n```\n\n![wttr.in in conky](https://user-images.githubusercontent.com/3875145/172178453-9e9ed9e3-9815-426a-9a21-afdd6e279fc8.png)\n\n\n### IRC\n\nIRC integration example:\n\n* https://github.com/OpenSourceTreasure/Mirc-ASCII-weather-translate-pixel-editor\n\n### Emojis support\n\nTo see emojis in terminal, you need:\n\n1. Terminal support for emojis (was added to Cairo 1.15.8);\n2. Font with emojis support.\n\nFor the emoji font, we recommend *Noto Color Emoji*, and a good alternative option would be the *Emoji One* font;\nboth of them support all necessary emoji glyphs.\n\nFont configuration:\n\n```xml\n$ cat ~/.config/fontconfig/fonts.conf\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">\n<fontconfig>\n  <alias>\n    <family>serif</family>\n    <prefer>\n      <family>Noto Color Emoji</family>\n    </prefer>\n  </alias>\n  <alias>\n    <family>sans-serif</family>\n    <prefer>\n      <family>Noto Color Emoji</family>\n    </prefer>\n  </alias>\n  <alias>\n    <family>monospace</family>\n    <prefer>\n      <family>Noto Color Emoji</family>\n    </prefer>\n  </alias>\n</fontconfig>\n```\n\n(to apply the configuration, run `fc-cache -f -v`).\n\nIn some cases, `tmux` and the terminal understanding of some emoji characters may differ, which may\ncause strange effects similar to that described in #579.\n\n### Squeak\n\nTo embed into the world main docking bar:\n\n```smalltalk\nwttr := (UpdatingStringMorph on: [(WebClient httpGet: 'https://wttr.in/?format=%20%20%l:%20%C+%t') content] selector: #value)\n\tstepTime: 60000;\n\tuseStringFormat;\n\tyourself.\ndockingBar := World mainDockingBars first.\ndockingBar addMorph: wttr after: (dockingBar findA: ClockMorph).\n```\n\n![wttr.in integration in the Squeak world main docking bar](https://github.com/user-attachments/assets/4c2762b0-77ae-41a8-98db-3eb310d073bd)\n\n## Data-rich output format (v2)\n\nIn the experimental data-rich output format, that is available under the view code `v2`,\na lot of additional weather and astronomical information is available:\n\n* Temperature, and precipitation changes forecast throughout the days;\n* Moonphase for today and the next three days;\n* The current weather condition, temperature, humidity, wind speed and direction, pressure;\n* Timezone;\n* Dawn, sunrise, noon, sunset, dusk time for he selected location;\n* Precise geographical coordinates for the selected location.\n\n```\n  $ curl v2.wttr.in/München\n```\n\nor\n\n```\n  $ curl wttr.in/München?format=v2\n```\n\nor, if you prefer Nerd Fonts instead of Emoji, `v2d` (day) or `v2n` (night):\n\n```\n  $ curl v2d.wttr.in/München\n```\n\n\n![data-rich output format](https://wttr.in/files/example-wttr-v2.png)\n\n(The mode is experimental, and it has several limitations currently:\n\n* It works only in terminal;\n* Only English is supported).\n\nCurrently, you need some tweaks for some terminals, to get the best possible visualization.\n\n### URXVT\n\nDepending on your configuration you might be taking all steps, or only a few. URXVT currently doesn't support emoji related fonts, but we can get almost the same effect using *Font-Symbola*. So add to your `.Xresources` file the following line:\n```\n    xft:symbola:size=10:minspace=False\n```\nYou can add it _after_ your preferred font and it will only show up when required.\nThen, if you see or feel like you're having spacing issues, add this: `URxvt.letterSpace: 0`\nFor some reason URXVT sometimes stops deciding right the word spacing and we need to force it this way.\n\nThe result, should look like:\n\n![URXVT Emoji line](https://user-images.githubusercontent.com/24360204/63842949-1d36d480-c975-11e9-81dd-998d1329bd8a.png)\n\n## Map view (v3)\n\nIn the experimental map view, that is available under the view code `v3`,\nweather information about a geographical region is available:\n\n```\n    $ curl v3.wttr.in/Bayern.sxl\n```\n\n![v3.wttr.in/Bayern](https://v3.wttr.in/Bayern.png)\n\nor directly in browser:\n\n*   https://v3.wttr.in/Bayern\n\nThe map view currently supports three formats:\n\n* PNG (for browser and messengers);\n* Sixel (terminal inline images support);\n* IIP (terminal with iterm2 inline images protocol support).\n\nTerminal with inline images protocols support:\n\n⟶ *Detailed article: [Images in terminal](doc/terminal-images.md)*\n\n| Terminal              | Environment    | Images support | Protocol |\n| --------------------- | --------- | ------------- | --------- |\n| uxterm                |   X11     |   yes         |   Sixel   |\n| mlterm                |   X11     |   yes         |   Sixel   |\n| kitty                 |   X11     |   yes         |   Kitty   |\n| wezterm               |   X11     |   yes         |   IIP     |\n| Darktile              |   X11     |   yes         |   Sixel   |\n| Jexer                 |   X11     |   yes         |   Sixel   |\n| GNOME Terminal        |   X11     |   [in-progress](https://gitlab.gnome.org/GNOME/vte/-/issues/253) |   Sixel   |\n| alacritty             |   X11     |   [in-progress](https://github.com/alacritty/alacritty/issues/910) |  Sixel   |\n| foot                  |  Wayland  |   yes         |   Sixel   |\n| DomTerm               |   Web     |   yes         |   Sixel   |\n| Yaft                  |   FB      |   yes         |   Sixel   |\n| iTerm2                |   Mac OS X|   yes         |   IIP     |\n| mintty                | Windows   |   yes         |   Sixel   |\n| Windows Terminal  |   Windows     |   [in-progress](https://github.com/microsoft/terminal/issues/448) |   Sixel   |\n| [RLogin](http://nanno.dip.jp/softlib/man/rlogin/) | Windows | yes         |   Sixel   |   |\n\n\n## Different output formats\n\n### JSON output\n\nThe JSON format is a feature providing access to *wttr.in* data through an easy-to-parse format, without requiring the user to create a complex script to reinterpret wttr.in's graphical output.\n\nTo fetch information in JSON format, use the following syntax:\n\n    $ curl wttr.in/Detroit?format=j1\n\nThis will fetch information on the Detroit region in JSON format. The j1 format code is used to allow for the use of other layouts for the JSON output.\n\nThe result will look something like the following:\n```json\n{\n\t\"current_condition\": [\n\t\t{\n\t\t    \"FeelsLikeC\": \"25\",\n\t\t    \"FeelsLikeF\": \"76\",\n\t\t    \"cloudcover\": \"100\",\n\t\t    \"humidity\": \"76\",\n\t\t    \"observation_time\": \"04:08 PM\",\n\t\t    \"precipMM\": \"0.2\",\n\t\t    \"pressure\": \"1019\",\n\t\t    \"temp_C\": \"22\",\n\t\t    \"temp_F\": \"72\",\n\t\t    \"uvIndex\": 5,\n\t\t    \"visibility\": \"16\",\n\t\t    \"weatherCode\": \"122\",\n\t\t    \"weatherDesc\": [\n\t\t\t{\n\t\t\t    \"value\": \"Overcast\"\n\t\t\t}\n\t\t    ],\n\t\t    \"weatherIconUrl\": [\n\t\t\t{\n\t\t\t    \"value\": \"\"\n\t\t\t}\n\t\t    ],\n\t\t    \"winddir16Point\": \"NNE\",\n\t\t    \"winddirDegree\": \"20\",\n\t\t    \"windspeedKmph\": \"7\",\n\t\t    \"windspeedMiles\": \"4\"\n\t\t}\n\t],\n...\n```\n\nMost of these values are self-explanatory, aside from `weatherCode`. The `weatherCode` is an enumeration which you can find at either [the WorldWeatherOnline website](https://www.worldweatheronline.com/developer/api/docs/weather-icons.aspx) or [in the wttr.in source code](https://github.com/chubin/wttr.in/blob/master/lib/constants.py).\n\nA smaller version `format=j2` without hourly data is also availble. Can work well for microcontrollers with limited memory.\n\n### Prometheus Metrics Output\n\nThe [Prometheus](https://github.com/prometheus/prometheus) Metrics format is a feature providing access to *wttr.in* data through an easy-to-parse format for monitoring systems, without requiring the user to create a complex script to reinterpret wttr.in's graphical output.\n\nTo fetch information in Prometheus format, use the following syntax:\n\n    $ curl wttr.in/Detroit?format=p1\n\nThis will fetch information on the Detroit region in Prometheus Metrics format. The `p1` format code is used to allow for the use of other layouts for the Prometheus Metrics output.\n\nA possible configuration for Prometheus could look like this:\n\n```yaml\n    - job_name: 'wttr_in_detroit'\n        static_configs:\n            - targets: ['wttr.in']\n        metrics_path: '/Detroit'\n        params:\n            format: ['p1']\n```\n\nThe result will look something like the following:\n\n\n    # HELP temperature_feels_like_celsius Feels Like Temperature in Celsius\n    temperature_feels_like_celsius{forecast=\"current\"} 7\n    # HELP temperature_feels_like_fahrenheit Feels Like Temperature in Fahrenheit\n    temperature_feels_like_fahrenheit{forecast=\"current\"} 45\n    [truncated]\n...\n\n\n## Moon phases\n\nwttr.in can also be used to check the phase of the Moon. This example shows how to see the current Moon phase\nin the full-output mode:\n\n    $ curl wttr.in/Moon\n\nGet the moon phase for a particular date by adding `@YYYY-MM-DD`:\n\n    $ curl wttr.in/Moon@2016-12-25\n\nThe moon phase information uses [pyphoon](https://github.com/chubin/pyphoon) as its backend.\n\nTo get the moon phase information in the online mode, use `%m`:\n\n    $ curl wttr.in/London?format=%m\n    🌖\n\nKeep in mind that the Unicode representation of moon phases suffers 2 caveats:\n\n- With some fonts, the representation `🌘` is ambiguous, for it either seem\n  almost-shadowed or almost-lit, depending on whether your terminal is in\n  light mode or dark mode. Relying on colored fonts like `noto-fonts` works\n  around this problem.\n\n- The representation `🌘` is also ambiguous, for it means \"last quarter\" in\n  northern hemisphere, but \"first quarter\" in souther hemisphere. It also means\n  nothing in tropical zones. This is a limitation that\n  [Unicode](https://www.unicode.org/L2/L2017/17304-moon-var.pdf) is aware about.\n  But it has not been worked around at `wttr.in` yet.\n\nSee #247, #364 for the corresponding tracking issues,\nand [pyphoon#1](https://github.com/chubin/pyphoon/issues/1) for pyphoon. Any help is welcome.\n\n## Internationalization and localization\n\nwttr.in supports multilingual locations names that can be specified in any language in the world\n(it may be surprising, but many locations in the world don't have an English name).\n\nThe query string should be specified in Unicode (hex-encoded or not). Spaces in the query string\nmust be replaced with `+`:\n\n    $ curl wttr.in/станция+Восток\n    Weather report: станция Восток\n\n                   Overcast\n          .--.     -65 – -47 °C\n       .-(    ).   ↑ 23 km/h\n      (___.__)__)  15 km\n                   0.0 mm\n\nThe language used for the output (except the location name) does not depend on the input language\nand it is either English (by default) or the preferred language of the browser (if the query\nwas issued from a browser) that is specified in the query headers (`Accept-Language`).\n\nThe language can be set explicitly when using console clients by using command-line options like this:\n\n    curl -H \"Accept-Language: fr\" wttr.in\n    http GET wttr.in Accept-Language:ru\n\nThe preferred language can be forced using the `lang` option:\n\n    $ curl wttr.in/Berlin?lang=de\n\nThe third option is to choose the language using the DNS name used in the query:\n\n    $ curl de.wttr.in/Berlin\n\nwttr.in is currently translated into 54 languages, and the number of supported languages is constantly growing.\n\nSee [/:translation](https://wttr.in/:translation) to learn more about the translation process,\nto see the list of supported languages and contributors, or to know how you can help to translate wttr.in\nin your language.\n\n![Queries to wttr.in in various languages](https://pbs.twimg.com/media/C7hShiDXQAES6z1.jpg)\n\n## Installation\n\nTo install the application:\n\n1. Install external dependencies\n2. Install Python dependencies used by the service\n3. Configure IP2Location (optional)\n4. Get a WorldWeatherOnline API and configure wego\n5. Configure wttr.in\n6. Configure the HTTP-frontend service\n\n### Install external dependencies\n\nwttr.in has the following external dependencies:\n\n* [golang](https://golang.org/doc/install), wego dependency\n* [wego](https://github.com/schachmat/wego), weather client for terminal\n\nAfter you install [golang](https://golang.org/doc/install), install `wego`:\n```bash\ngo install github.com/schachmat/wego@latest\n```\n\n### Install Python dependencies\n\nPython requirements:\n\n* Flask\n* geoip2\n* geopy\n* requests\n* gevent\n\nIf you want to get weather reports as PNG files, you'll also need to install:\n\n* PIL\n* pyte (>=0.6)\n* necessary fonts\n\nYou can install most of them using `pip`.\n\nSome python package use LLVM, so install it first:\n\n```bash\napt-get install llvm-7 llvm-7-dev\n```\nIf `virtualenv` is used:\n```bash\nvirtualenv -p python3 ve\nve/bin/pip3 install -r requirements.txt\nve/bin/python3 bin/srv.py\n```\n\nAlso, you need to install the geoip2 database.\nYou can use a free database GeoLite2 that can be downloaded from (http://dev.maxmind.com/geoip/geoip2/geolite2/).\n\n### Configure IP2Location (optional)\n\nIf you want to use the IP2location service for IP-addresses that are not covered by GeoLite2,\nyou have to obtain a API key of that service, and after that save into the `~/.ip2location.key` file:\n\n```\n$ echo 'YOUR_IP2LOCATION_KEY' > ~/.ip2location.key\n```\n\nIf you don't have this file, the service will be silently skipped (it is not a big problem,\nbecause the MaxMind database is pretty good).\n\n### Installation with Docker\n\n* Install Docker\n* Build Docker Image\n* These files should be mounted by the user at runtime:\n\n```\n/root/.wegorc\n/root/.ip2location.key (optional)\n/app/airports.dat\n/app/GeoLite2-City.mmdb\n```\n\n### Get a WorldWeatherOnline key and configure wego\n\nTo get a WorldWeatherOnline API key, you must register here:\n\n    https://developer.worldweatheronline.com/auth/register\n\nAfter you have a WorldWeatherOnline key, you can save it into the\nWWO key file: `~/.wwo.key`\n\nAlso, you have to specify the key in the `wego` configuration:\n\n```json\n$ cat ~/.wegorc\n{\n\t\"APIKey\": \"00XXXXXXXXXXXXXXXXXXXXXXXXXXX\",\n\t\"City\": \"London\",\n\t\"Numdays\": 3,\n\t\"Imperial\": false,\n\t\"Lang\": \"en\"\n}\n```\n\nThe `City` parameter in `~/.wegorc` is ignored.\n\n### Configure wttr.in\n\nConfigure the following environment variables that define the path to the local `wttr.in`\ninstallation, to the GeoLite database, and to the `wego` installation. For example:\n\n```bash\nexport WTTR_MYDIR=\"/home/igor/wttr.in\"\nexport WTTR_GEOLITE=\"/home/igor/wttr.in/GeoLite2-City.mmdb\"\nexport WTTR_WEGO=\"/home/igor/go/bin/wego\"\nexport WTTR_LISTEN_HOST=\"0.0.0.0\"\nexport WTTR_LISTEN_PORT=\"8002\"\n```\n\n\n### Configure the HTTP-frontend service\n\nIt's recommended that you also configure the web server that will be used to access the service:\n\n```nginx\nserver {\n\tlisten [::]:80;\n\tserver_name  wttr.in *.wttr.in;\n\taccess_log  /var/log/nginx/wttr.in-access.log  main;\n\terror_log  /var/log/nginx/wttr.in-error.log;\n\n\tlocation / {\n\t    proxy_pass         http://127.0.0.1:8002;\n\n\t    proxy_set_header   Host             $host;\n\t    proxy_set_header   X-Real-IP        $remote_addr;\n\t    proxy_set_header   X-Forwarded-For  $remote_addr;\n\n\t    client_max_body_size       10m;\n\t    client_body_buffer_size    128k;\n\n\t    proxy_connect_timeout      90;\n\t    proxy_send_timeout         90;\n\t    proxy_read_timeout         90;\n\n\t    proxy_buffer_size          4k;\n\t    proxy_buffers              4 32k;\n\t    proxy_busy_buffers_size    64k;\n\t    proxy_temp_file_write_size 64k;\n\n\t    expires                    off;\n\t}\n}\n```\n\n## wttr.in usage stats\n\nAs of March 2026, *wttr.in* handles 22-27 million queries per day from 300,000 to 320,000 users, according to the access logs.\n\n![wttr.in usage stats](share/stats/stats.png)\n"
  },
  {
    "path": "bin/geo-proxy.py",
    "content": "import gevent\nfrom gevent.pywsgi import WSGIServer\nfrom gevent.queue import Queue\nfrom gevent.monkey import patch_all\nfrom gevent.subprocess import Popen, PIPE, STDOUT\n\npatch_all()\n\nimport sys\nimport os\nimport json\n\nfrom flask import (\n    Flask,\n    request,\n    render_template,\n    send_from_directory,\n    send_file,\n    make_response,\n    jsonify,\n    Response,\n)\n\napp = Flask(__name__)\n\nMYDIR = os.path.abspath(os.path.dirname(\"__file__\"))\nsys.path.append(os.path.join(MYDIR, \"lib\"))\n\nCACHEDIR = os.path.join(MYDIR, \"cache\")\n\nfrom geopy.geocoders import Nominatim  # , Mapzen\n\n# geomapzen = Mapzen(\"mapzen-RBNbmcZ\") # Nominatim()\ngeoosm = Nominatim(timeout=7, user_agent=\"wttrin-geo/0.0.2\")\n\nimport airports\n\n# from tzwhere import tzwhere\nimport timezonefinder\n\ntf = timezonefinder.TimezoneFinder()\n\n\ndef load_cache(location_string):\n    try:\n        location_string = location_string.replace(\"/\", \"_\")\n        cachefile = os.path.join(CACHEDIR, location_string)\n\n        return json.loads(open(cachefile, \"r\").read())\n    except Exception:\n        return None\n\n\ndef shorten_full_address(address):\n    parts = address.split(\",\")\n    if len(parts) > 6:\n        parts = parts[:2] + [x for x in parts[-4:] if len(x) < 20]\n        return \",\".join(parts)\n    return address\n\n\ndef save_cache(location_string, answer):\n    location_string = location_string.replace(\"/\", \"_\")\n    cachefile = os.path.join(CACHEDIR, location_string)\n    open(cachefile, \"w\").write(json.dumps(answer))\n\n\ndef query_osm(location_string):\n    try:\n        location = geoosm.geocode(location_string)\n        return {\n            \"address\": location.address,\n            \"latitude\": location.latitude,\n            \"longitude\": location.longitude,\n        }\n\n    except Exception as e:\n        print(e)\n        return None\n\n\ndef add_timezone_information(geo_data):\n    # tzwhere_ = tzwhere.tzwhere()\n    # timezone_str = tzwhere_.tzNameAt(geo_data[\"latitude\"], geo_data[\"longitude\"])\n    timezone_str = tf.certain_timezone_at(\n        lat=geo_data[\"latitude\"], lng=geo_data[\"longitude\"]\n    )\n\n    answer = geo_data.copy()\n    answer[\"timezone\"] = timezone_str\n\n    return answer\n\n\n@app.route(\"/<string:location>\")\ndef find_location(location):\n\n    airport_gps_location = airports.get_airport_gps_location(\n        location.upper().lstrip(\"~\")\n    )\n    is_airport = False\n    if airport_gps_location is not None:\n        location = airport_gps_location\n        is_airport = True\n\n    location = location.replace(\"+\", \" \")\n    answer = load_cache(location)\n    loaded_answer = None\n\n    if answer is not None:\n        loaded_answer = answer.copy()\n        print(\"cache found: %s\" % location)\n\n    if answer is None:\n        answer = query_osm(location)\n\n    if is_airport:\n        answer[\"address\"] = shorten_full_address(answer[\"address\"])\n\n    if \"timezone\" not in answer:\n        answer = add_timezone_information(answer)\n\n    if answer is not None and loaded_answer != answer:\n        save_cache(location, answer)\n\n    if answer is None:\n        return \"\"\n    else:\n        r = Response(json.dumps(answer))\n        r.headers[\"Content-Type\"] = \"text/json; charset=utf-8\"\n        return r\n\n\napp.config[\"JSON_AS_ASCII\"] = False\nserver = WSGIServer((\"127.0.0.1\", 8004), app)\nserver.serve_forever()\n"
  },
  {
    "path": "bin/proxy.py",
    "content": "# vim: fileencoding=utf-8\n\n\"\"\"\n\nThe proxy server acts as a backend for the wttr.in service.\n\nIt caches the answers and handles various data sources transforming their\nanswers into format supported by the wttr.in service.\n\nIf WTTRIN_TEST is specified, it works in a special test mode:\nit does not fetch and does not store the data in the cache,\nbut is using the fake data from \"test/proxy-data\".\n\n\"\"\"\nfrom __future__ import print_function\n\nfrom gevent.pywsgi import WSGIServer\nfrom gevent.monkey import patch_all\n\npatch_all()\n\n# pylint: disable=wrong-import-position,wrong-import-order\nimport sys\nimport os\nimport time\nimport json\nimport hashlib\nimport re\nimport logging\n\n\nimport requests\nimport cyrtranslit\n\nfrom flask import Flask, request\n\nAPP = Flask(__name__)\n\n\nMYDIR = os.path.abspath(os.path.dirname(os.path.dirname(\"__file__\")))\nsys.path.append(\"%s/lib/\" % MYDIR)\n\nimport proxy_log\nimport globals\nfrom globals import (\n    PROXY_CACHEDIR,\n    PROXY_PORT,\n    USE_METNO,\n    USER_AGENT,\n    MISSING_TRANSLATION_LOG,\n)\nfrom metno import create_standard_json_from_metno, metno_request\nfrom translations import PROXY_LANGS\n\n# pylint: enable=wrong-import-position\n\nproxy_logger = proxy_log.LoggerWWO(globals.PROXY_LOG_ACCESS, globals.PROXY_LOG_ERRORS)\n\n\ndef is_testmode():\n    \"\"\"Server is running in the wttr.in test mode\"\"\"\n\n    return \"WTTRIN_TEST\" in os.environ\n\n\ndef load_translations():\n    \"\"\"\n    load all translations\n    \"\"\"\n    translations = {}\n\n    for f_name in PROXY_LANGS:\n        f_name = \"share/translations/%s.txt\" % f_name\n        translation = {}\n        lang = f_name.split(\"/\")[-1].split(\".\", 1)[0]\n        with open(f_name, \"r\") as f_file:\n            for line in f_file:\n                if \":\" not in line:\n                    continue\n                if line.count(\":\") == 3:\n                    _, trans, orig, _ = line.strip().split(\":\", 4)\n                else:\n                    _, trans, orig = line.strip().split(\":\", 3)\n                trans = trans.strip()\n                orig = orig.strip()\n\n                translation[orig.lower()] = trans\n        translations[lang] = translation\n    return translations\n\n\nTRANSLATIONS = load_translations()\n\n\ndef _is_metno():\n    return USE_METNO\n\n\ndef _find_srv_for_query(path, query):  # pylint: disable=unused-argument\n    if _is_metno():\n        return \"https://api.met.no\"\n    return \"http://api.worldweatheronline.com\"\n\n\ndef _cache_file(path, query):\n    \"\"\"Return cache file name for specified `path` and `query`\n    and for the current time.\n\n    Do smooth load on the server, expiration time\n    is slightly varied basing on the path+query sha1 hash digest.\n    \"\"\"\n\n    digest = hashlib.sha1((\"%s %s\" % (path, query)).encode(\"utf-8\")).hexdigest()\n    digest_number = ord(digest[0].upper())\n    penalty = 0\n    expiry_interval = 60 * (digest_number + penalty)\n\n    timestamp = \"%010d\" % (int(time.time()) // expiry_interval * expiry_interval)\n    filename = os.path.join(PROXY_CACHEDIR, timestamp, path, query)\n\n    return filename\n\n\ndef _load_content_and_headers(path, query):\n    if is_testmode():\n        cache_file = \"test/proxy-data/data1\"\n    else:\n        cache_file = _cache_file(path, query)\n    try:\n        return (\n            open(cache_file, \"r\").read(),\n            json.loads(open(cache_file + \".headers\", \"r\").read()),\n        )\n    except IOError:\n        return None, None\n\n\ndef _touch_empty_file(path, query):\n    cache_file = _cache_file(path, query)\n    cache_dir = os.path.dirname(cache_file)\n    if not os.path.exists(cache_dir):\n        os.makedirs(cache_dir)\n    open(cache_file, \"w\").write(\"\")\n\n\ndef _save_content_and_headers(path, query, content, headers):\n    cache_file = _cache_file(path, query)\n    cache_dir = os.path.dirname(cache_file)\n    if not os.path.exists(cache_dir):\n        os.makedirs(cache_dir)\n    open(cache_file + \".headers\", \"w\").write(json.dumps(headers))\n    open(cache_file, \"wb\").write(content)\n\n\ndef translate(text, lang):\n    \"\"\"\n    Translate `text` into `lang`.\n    If `text` is comma-separated, translate each term independently.\n    If no translation found, leave it untouched.\n    \"\"\"\n\n    def _log_unknown_translation(lang, text):\n        with open(MISSING_TRANSLATION_LOG % lang, \"a\") as f_missing_translation:\n            f_missing_translation.write(text + \"\\n\")\n\n    if \",\" in text:\n        terms = text.split(\",\")\n        translated_terms = [translate(term.strip(), lang) for term in terms]\n        return \", \".join(translated_terms)\n\n    if lang not in TRANSLATIONS:\n        _log_unknown_translation(lang, \"UNKNOWN_LANGUAGE\")\n        return text\n\n    if text.lower() not in TRANSLATIONS.get(lang, {}):\n        _log_unknown_translation(lang, text)\n        return text\n\n    translated = TRANSLATIONS.get(lang, {}).get(text.lower(), text)\n    return translated\n\n\ndef cyr(to_translate):\n    \"\"\"\n    Transliterate `to_translate` from latin into cyrillic\n    \"\"\"\n    return cyrtranslit.to_cyrillic(to_translate)\n\n\ndef _patch_greek(original):\n    return original.replace(\"Ηλιόλουστη/ο\", \"Ηλιόλουστη\")\n\n\ndef add_translations(content, lang):\n    \"\"\"\n    Add `lang` translation to `content` (JSON)\n    returned by the data source\n    \"\"\"\n\n    if content == \"{}\":\n        return {}\n\n    languages_to_translate = TRANSLATIONS.keys()\n    try:\n        d = json.loads(content)  # pylint: disable=invalid-name\n    except (ValueError, TypeError) as exception:\n        print(\"---\")\n        print(exception)\n        print(\"---\")\n        return {}\n\n    if \"current_condition\" not in d[\"data\"]:\n        return content\n\n    try:\n        weather_condition = (\n            d[\"data\"][\"current_condition\"][0][\"weatherDesc\"][0][\"value\"]\n            .capitalize()\n            .strip()\n        )\n        d[\"data\"][\"current_condition\"][0][\"weatherDesc\"][0][\"value\"] = weather_condition\n        if lang in languages_to_translate:\n            d[\"data\"][\"current_condition\"][0][\"lang_%s\" % lang] = [\n                {\"value\": translate(weather_condition, lang)}\n            ]\n        elif lang == \"sr\":\n            d[\"data\"][\"current_condition\"][0][\"lang_%s\" % lang] = [\n                {\n                    \"value\": cyr(\n                        d[\"data\"][\"current_condition\"][0][\"lang_%s\" % lang][0][\"value\"]\n                    )\n                }\n            ]\n        elif lang == \"el\":\n            d[\"data\"][\"current_condition\"][0][\"lang_%s\" % lang] = [\n                {\n                    \"value\": _patch_greek(\n                        d[\"data\"][\"current_condition\"][0][\"lang_%s\" % lang][0][\"value\"]\n                    )\n                }\n            ]\n        elif lang == \"sr-lat\":\n            d[\"data\"][\"current_condition\"][0][\"lang_%s\" % lang] = [\n                {\"value\": d[\"data\"][\"current_condition\"][0][\"lang_sr\"][0][\"value\"]}\n            ]\n\n        fixed_weather = []\n        for w in d[\"data\"][\"weather\"]:  # pylint: disable=invalid-name\n            fixed_hourly = []\n            for h in w[\"hourly\"]:  # pylint: disable=invalid-name\n                weather_condition = h[\"weatherDesc\"][0][\"value\"].strip()\n                if lang in languages_to_translate:\n                    h[\"lang_%s\" % lang] = [\n                        {\"value\": translate(weather_condition, lang)}\n                    ]\n                elif lang == \"sr\":\n                    h[\"lang_%s\" % lang] = [\n                        {\"value\": cyr(h[\"lang_%s\" % lang][0][\"value\"])}\n                    ]\n                elif lang == \"el\":\n                    h[\"lang_%s\" % lang] = [\n                        {\"value\": _patch_greek(h[\"lang_%s\" % lang][0][\"value\"])}\n                    ]\n                elif lang == \"sr-lat\":\n                    h[\"lang_%s\" % lang] = [{\"value\": h[\"lang_sr\"][0][\"value\"]}]\n                fixed_hourly.append(h)\n            w[\"hourly\"] = fixed_hourly\n            fixed_weather.append(w)\n        d[\"data\"][\"weather\"] = fixed_weather\n\n        content = json.dumps(d)\n    except (IndexError, ValueError) as exception:\n        print(exception)\n    return content\n\n\ndef _fetch_content_and_headers(path, query_string, **kwargs):\n    content, headers = _load_content_and_headers(path, query_string)\n\n    if content is None:\n        srv = _find_srv_for_query(path, query_string)\n        url = \"%s/%s?%s\" % (srv, path, query_string)\n\n        attempts = 10\n        response = None\n        error = \"\"\n        while attempts:\n            try:\n                response = requests.get(url, timeout=2, **kwargs)\n            except requests.ReadTimeout:\n                attempts -= 1\n                continue\n            try:\n                data = json.loads(response.content)\n                error = data.get(\"data\", {}).get(\"error\", \"\")\n                if error:\n                    try:\n                        error = error[0][\"msg\"]\n                    except (ValueError, IndexError):\n                        error = \"invalid error format: %s\" % error\n                break\n            except ValueError:\n                attempts -= 1\n                error = \"invalid response\"\n\n        proxy_logger.log(query_string, error)\n        _touch_empty_file(path, query_string)\n        if response:\n            headers = {}\n            headers[\"Content-Type\"] = response.headers[\"content-type\"]\n            _save_content_and_headers(path, query_string, response.content, headers)\n            content = response.content\n        else:\n            content = \"{}\"\n    return content, headers\n\n\ndef _make_query(path, query_string):\n    if _is_metno():\n        path, query, days = metno_request(path, query_string)\n        if USER_AGENT == \"\":\n            raise ValueError(\n                \"User agent must be set to adhere to metno ToS: https://api.met.no/doc/TermsOfService\"\n            )\n        content, headers = _fetch_content_and_headers(\n            path, query, headers={\"User-Agent\": USER_AGENT}\n        )\n        content = create_standard_json_from_metno(content, days)\n    else:\n        # WWO tweaks\n        query_string += \"&extra=localObsTime\"\n        query_string += \"&includelocation=yes\"\n        content, headers = _fetch_content_and_headers(path, query_string)\n\n    return content, headers\n\n\ndef _normalize_query_string(query_string):\n    # Normalized query string has the following fixes:\n    # 1. Uses , for the coordinates separation\n    # 2. Limits number of digits after .\n\n    coord_match = re.search(r\"q=[^&]*\", query_string)\n    coords_str = coord_match.group(0)\n    coords = re.findall(r\"[-0-9.]+\", coords_str)\n    if len(coords) != 2:\n        return query_string\n\n    lat = str(round(float(coords[0]), 2))\n    lng = str(round(float(coords[1]), 2))\n    query_string = re.sub(r\"q=[^&]*\", \"q=\" + lat + \",\" + lng, query_string)\n    # print(query_string)\n\n    # nqs = query_string.replace(\"%2C\", \",\")\n    # lat, lng = nqs.split(\",\", 1)\n    # nqs = f\"{lat:.2f},{lng:.2f}\"\n\n    return query_string\n\n\n@APP.route(\"/<path:path>\")\ndef proxy(path):\n    \"\"\"\n    Main proxy function. Handles incoming HTTP queries.\n    \"\"\"\n\n    lang = request.args.get(\"lang\", \"en\")\n    query_string = request.query_string.decode(\"utf-8\")\n    query_string = _normalize_query_string(query_string)\n    query_string = query_string.replace(\"sr-lat\", \"sr\")\n    query_string = query_string.replace(\"lang=None\", \"lang=en\")\n    content = \"\"\n    headers = \"\"\n\n    content, headers = _make_query(path, query_string)\n\n    # _log_query(path, query_string, error)\n\n    content = add_translations(content, lang)\n    if \"Unable to find any\" in content:\n        print(query_string)\n\n    return content, 200, headers\n\n\nif __name__ == \"__main__\":\n    # app.run(host='0.0.0.0', port=5001, debug=False)\n    # app.debug = True\n    if len(sys.argv) == 1:\n        bind_addr = \"0.0.0.0\"\n        logging.getLogger('werkzeug').setLevel(logging.ERROR)  # Suppress Werkzeug logs\n        SERVER = WSGIServer((bind_addr, PROXY_PORT), APP, log=None)\n        SERVER.serve_forever()\n    else:\n        print(\"running single request from command line arg\")\n        APP.testing = True\n        with APP.test_client() as c:\n            resp = c.get(sys.argv[1])\n            print(\"Status: \" + resp.status)\n            # print('Headers: ' + dumps(resp.headers))\n            print(resp.data.decode(\"utf-8\"))\n"
  },
  {
    "path": "bin/srv.py",
    "content": "#!/usr/bin/env python\n# vim: set encoding=utf-8\n\nfrom gevent.pywsgi import WSGIServer\nfrom gevent.monkey import patch_all\n\npatch_all()\n\n# pylint: disable=wrong-import-position,wrong-import-order\nimport sys\nimport os\nimport jinja2\n\nfrom flask import Flask, request, send_from_directory, send_file\n\nAPP = Flask(__name__)\n\nMYDIR = os.path.abspath(os.path.dirname(os.path.dirname(\"__file__\")))\nsys.path.append(\"%s/lib/\" % MYDIR)\n\nimport wttr_srv\nfrom globals import TEMPLATES, STATIC, LISTEN_HOST, LISTEN_PORT\n\n# pylint: enable=wrong-import-position,wrong-import-order\n\n# from view.v3 import v3_file\n\nMY_LOADER = jinja2.ChoiceLoader(\n    [\n        APP.jinja_loader,\n        jinja2.FileSystemLoader(TEMPLATES),\n    ]\n)\n\nAPP.jinja_loader = MY_LOADER\n\n\n# @APP.route(\"/v3/<string:location>\")\n# def send_v3(location):\n#     filepath = v3_file(location)\n#     if filepath.startswith(\"ERROR\"):\n#         return filepath.rstrip(\"\\n\") + \"\\n\"\n#     return send_file(filepath)\n\n\n@APP.route(\"/files/<path:path>\")\ndef send_static(path):\n    \"Send any static file located in /files/\"\n    return send_from_directory(STATIC, path)\n\n\n@APP.route(\"/favicon.ico\")\ndef send_favicon():\n    \"Send static file favicon.ico\"\n    return send_from_directory(STATIC, \"favicon.ico\")\n\n\n@APP.route(\"/malformed-response.html\")\ndef send_malformed():\n    \"Send static file malformed-response.html\"\n    return send_from_directory(STATIC, \"malformed-response.html\")\n\n\n@APP.route(\"/\")\n@APP.route(\"/<string:location>\")\ndef wttr(location=None):\n    \"Main function wrapper\"\n    return wttr_srv.wttr(location, request)\n\n\nSERVER = WSGIServer(\n    (LISTEN_HOST, int(os.environ.get(\"WTTRIN_SRV_PORT\", LISTEN_PORT))), APP\n)\nSERVER.serve_forever()\n"
  },
  {
    "path": "config/services/services.yaml",
    "content": "services:\n  - name: \"main server\"\n    command: \"while true; do sudo /wttr.in/bin/srv big-cache.yaml ; sleep 5; done\"\n    workdir: \"$HOME\"\n    port: ...\n\n  - name: \"geo server\"\n    command: \"while true; do /wttr.in/bin/srv geo.yaml; sleep 5; done\"\n    workdir: \"$HOME\"\n    env:\n      - NOMINATIM_OPENCAGE\n    port: 8085\n\n  - name: \"proxy\"\n    command: ve/bin/python3 bin/proxy.py\n    workdir: \"/wttr.in/wttr.in-v2-v2\"\n    port: 5001\n\n  - name: \"format=j1\"\n    command: \"WTTRIN_SRV_PORT=9003 ve/bin/python3 bin/srv.py\"\n    workdir: \"/wttr.in/wttr.in-v2-v2\"\n    port: 9003\n\n  - name: \"format=line\"\n    command: \"WTTRIN_SRV_PORT=9004 ve/bin/python3 bin/srv.py\"\n    workdir: \"/wttr.in/wttr.in-v2-v2\"\n    port: 9004\n\n  - name: \"format=v1\"\n    command: \"WTTRIN_SRV_PORT=9005 ve/bin/python3 bin/srv.py\"\n    workdir: \"/wttr.in/wttr.in-v2-v2\"\n    port: 9005\n\n  - name: \"filetype=png\"\n    command: \"WTTRIN_SRV_PORT=9006 ve/bin/python3 bin/srv.py\"\n    workdir: \"/wttr.in/wttr.in-v2-v2\"\n    port: 9006\n"
  },
  {
    "path": "doc/integrations.md",
    "content": "## Integrations\n\nThanks to the ease of integrating *wttr.in* into any program, there are a\nplethora of popular integrations across various libraries, programming\nlanguages, and systems.\n\n*wttr.in* is compatible with:\n\n* terminal managers,\n* window managers,\n* editors,\n* chat clients,\n\nand more, these integrations enhance workflow efficiency by embedding weather information directly into user interfaces.\n\nBelow, we've compiled a list of some of these integrations. While not\nexhaustive, it serves as a guide to help you use *wttr.in* within your favorite\napplication or add integration to a new one.\n\n\n| Integration For                                    | Short Description                                                                                                | Repository                                                                                         |\n|----------------------------------------------------|------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------|\n| **Terminal Managers**                              |                                                                                                                  |                                                                                                    |\n| [tmux](#tmux)                                      | Allows embedding weather data in the tmux status bar with customizable update intervals.                         | -                                                                                                  |\n| **Window Managers Statusbars**                     |                                                                                                                  |                                                                                                    |\n| [Waybar](#Waybar)                                  | A custom module in Rust for displaying weather in Waybar, with support for custom indicators and error handling. | [wttrbar](https://github.com/bjesus/wttrbar)                                                       |\n| [Xmobar](#Xmobar)                                  | A Python script for integrating weather data into Xmobar.                                                        | [weather-xmobar-wttr.in](https://github.com/alexeygumirov/weather-xmobar-wttr.in)                  |\n| [AwesomeWM](#AwesomeWM)                            | Displays weather in AwesomeWM with a focus on clean UI and tooltips.                                             | [wttr-widget](https://github.com/pivaldi/wttr-widget)                                              |\n| **Editors**                                        |                                                                                                                  |                                                                                                    |\n| [Emacs](#Emacs)                                    | An Emacs frontend for showing weather forecasts directly within Emacs.                                           | [emacs-wttrin](https://github.com/cjennings/emacs-wttrin)                                            |\n| [Emacs](#Emacs)                                    | Displays weather in the Emacs mode line with emoji support, configurable for updates.                            | [display-wttr](https://git.sr.ht/~josegpt/display-wttr)                                            |\n| **Chats**                                          |                                                                                                                  |                                                                                                    |\n| [Conky](#Conky)                                    | Example script for displaying weather in Conky using transparent images.                                         | -                                                                                                  |\n| [WeeChat](#WeeChat)                                | Script for embedding weather in the WeeChat IRC client's status bar.                                             | -                                                                                                  |\n| [IRC](#IRC)                                        | Uses Qt-based mirc bot to show weather updates.                                                                  | [IRC integration](https://github.com/OpenSourceTreasure/Mirc-ASCII-weather-translate-pixel-editor) |\n| **Other**                                          |                                                                                                                  |                                                                                                    |\n| [ObsidianMD](#ObsidianMD)                          | Script for embedding weather in Squeak's world main docking bar.                                                 | -                                                                                                  |\n| [RainMeter](#Rainmeter)                            |                                                                                                                  | -                                                                                                  |\n| [Squeak](#Squeak)                                  |                                                                                                                  | -                                                                                                  |\n| [Twitch](#Twitch)                                  |                                                                                                                  | -                                                                                                  |\n| [GoogleSheets/Excel365](#google-sheets--excel-365) | Direct wttr.in access from Google Sheets / Excel 365                                                             | -                                                                                                  |\n| [Raycast](#Raycast)                                | Weather extension for Raycast                                                                                    | -                                                                                                  |\n\n\n## Terminal Managers\n\n### tmux\n\nWhen using in `tmux.conf`, you have to escape `%` with `%`, i.e. write there `%%` instead of `%`.\n\nThe output does not contain new line by default, when the %-notation is used, but it does contain it when preconfigured format (`1`,`2`,`3` etc.)\nare used. To have the new line in the output when the %-notation is used, use '\\n' and single quotes when doing a query from the shell.\n\nIn programs, that are querying the service automatically (such as tmux), it is better to use some reasonable update interval. In tmux, you can configure it with `status-interval`.\n\nIf several, `:` separated locations, are specified in the query, specify update period\nas an additional query parameter `period=`:\n\n```\nset -g status-interval 60\nWEATHER='#(curl -s wttr.in/London:Stockholm:Moscow\\?format\\=\"%%l:+%%c%%20%%t%%60%%w&period=60\")'\nset -g status-right \"$WEATHER ...\"\n```\n\n![wttr.in in tmux status bar](https://wttr.in/files/example-tmux-status-line.png)\n\n\n## Window Managers Statusbars\n\n### Waybar\n\n[wttrbar](https://github.com/bjesus/wttrbar) by *bjesus*\n\nA custom module for displaying weather in Waybar using wttr.in. It’s written in\nRust for reliability and supports features like custom indicators (e.g.,\ntemperature in Celsius or Fahrenheit), location specification, and date\nformatting.\n\nExample configuration:\n\n```json\n    \"custom/weather\": {\n      \"format\": \"{}°\",\n      \"tooltip\": true,\n      \"interval\": 3600,\n      \"exec\": \"wttrbar --location=Paris --main-indicator=FeelsLikeC --date-format=%d.%m.%Y\",\n      \"return-type\": \"json\"\n    }\n```\n\nInstallation:\n\nCompile using cargo build --release or download pre-built binaries. Requires a font supporting emojis (e.g., Noto Emoji) for weather icons.\n\nFeatures: Supports custom styling based on weather conditions (e.g., sunny), handles wttr.in errors gracefully, and allows wind direction display with Unicode arrows.\n\n<img src=\"https://user-images.githubusercontent.com/55081/232401699-b8345fe0-ffce-4353-b51b-615389153448.png\" alt=\"wttrbar\" width=\"300px\">\n\n### Xmobar\n\n[weather-xmobar-wttr.in](https://github.com/alexeygumirov/weather-xmobar-wttr.in) by *alexeygumirov*\n\nA Python-based script for displaying weather status in Xmobar, leveraging\nwttr.in. It provides a lightweight solution for integrating weather data into\nthe Xmobar status bar.\n\n![wttr-in-Xmodbar](https://raw.githubusercontent.com/alexeygumirov/weather-xmobar-wttr.in/refs/heads/main/screenshot/screenshot_day.png)\n\n(displays weather conditions in a compact format suitable for Xmobar).\n\n### AwesomeWM\n\n[wttr-widget](https://github.com/pivaldi/wttr-widget) by *pivaldi*\n\nA weather widget for AwesomeWM that uses wttr.in to display weather information. It’s designed to integrate seamlessly with the Awesome window manager, providing a tooltip with detailed weather data.\n\nDisplays weather conditions with a focus on a clean, customizable UI. The screenshot shows a tooltip with weather details like temperature and conditions.\n\n![wttr-in-awesome](https://raw.githubusercontent.com/pivaldi/wttr-widget/refs/heads/master/screenshots/tooltip1.png)\n\n(shows a tooltip with weather data integrated into AwesomeWM)\n\n## Editors\n\n### Emacs\n\n#### emacs-wttrin by bcbcarl\n\n[emacs-wttrin](https://github.com/bcbcarl/emacs-wttrin) by *bcbcarl*\n\nAn Emacs frontend for wttr.in, allowing users to view weather forecasts directly within Emacs. It’s designed for simplicity and integration into the Emacs workflow.\n\nUsers can configure it to fetch weather for specific locations and display it in a buffer.\n\n#### display-wttr by josegpt\n\n[display-wttr](https://git.sr.ht/~josegpt/display-wttr) by *josegpt*\n    \nDisplays wttr.in weather data in the Emacs mode line with emoji support (requires Emacs 28 or later). It’s lightweight and configurable for periodic updates.\n\nConfiguration Example:\n\n```elisp\n(use-package display-wttr\n  :config\n  (display-wttr-mode))\n```\n\nSupports custom locations, update intervals, and emoji-based weather display. The repository has moved to https://git.sr.ht/~josegpt/display-wttr.\n\nScreenshot: \n\n![display-wttr](https://raw.githubusercontent.com/josegpt/display-wttr/main/emoji-display-wttr.png)\n\n(shows weather with emojis in the Emacs mode line).\n\n## Chats\n\n### conky\n\nConky usage example:\n\n```\n${texeci 1800 curl wttr.in/kyiv_0pq_lang=uk.png\n  | convert - -transparent black $HOME/.config/conky/out.png}\n${image $HOME/.config/conky/out.png -p 0,0}\n```\n\n![wttr.in in conky](https://user-images.githubusercontent.com/3875145/172178453-9e9ed9e3-9815-426a-9a21-afdd6e279fc8.png)\n\n### WeeChat\n\nTo embed in to an IRC ([WeeChat](https://github.com/weechat/weechat)) client's existing status bar:\n\n```\n/alias add wttr /exec -pipe \"/mute /set plugins.var.wttr\" url:wttr.in/Montreal?format=%l:+%c+%f+%h+%p+%P+%m+%w+%S+%s;/wait 3 /item refresh wttr\n/trigger add wttr timer 60000;0;0 \"\" \"\" \"/wttr\"\n/item add wttr \"\" \"${plugins.var.wttr}\"\n/eval /set weechat.bar.status.items ${weechat.bar.status.items},spacer,wttr\n/eval /set weechat.startup.command_after_plugins ${weechat.startup.command_after_plugins};/wttr\n/wttr\n```\n\n![wttr.in in WeeChat status bar](https://i.imgur.com/XkYiRU7.png)\n\n### IRC\n\n[IRC integration](https://github.com/OpenSourceTreasure/Mirc-ASCII-weather-translate-pixel-editor)\n\n![wttr-in-irc](https://raw.githubusercontent.com/OpenSourceTreasure/Mirc-ASCII-weather-translate-pixel-editor/main/mirc-bot.png)\n\n## Other\n\n### ObsidianMD Integration\n\nA script for ObsidianMD (a note-taking app) integrates wttr.in to embed weather data in daily notes using the Templater plugin. It fetches and displays weather details for a specified location only for the current day’s note.\n\n*Usage:* Add a script to the Templater plugin to check if the note’s date matches today and fetch weather data. Example script:\n\n```javascript\n<%* if (tp.file.title === tp.date.now()) { %>\n  <%* const weather = await requestUrl('https://wttr.in/Berlin?format=%l:+%c+%C+%t+feels+like+%f\\nTime:+++++%T\\nSunrise:++%S\\nSunset:+++%s\\nMoon:+++++%m\\nWind:+++++%w\\nRainfall:+%p\\nHumidity:+%h') %>\n  <%* tR += weather.text %>\n<%* } else { %>\n  Update the weather report!\n<%* } %>\n```\n\nThis displays weather details like temperature, sunrise/sunset, moon phase, wind, rainfall, and humidity in the note body.\n\n*Features:* Updates only for the current day’s note, supports custom formats, and can be triggered manually via a hotkey.\n\n\n### Rainmeter\n\nRainmeter, a desktop customization tool for Windows, can use wttr.in to display\nweather data by parsing its JSON output. This is particularly useful for\ncreating custom desktop widgets.\n\nUse a URL like `https://wttr.in/Alexandria,Virginia?format=j1` to fetch\nJSON data, which includes detailed weather metrics (e.g., temperature,\nhumidity, wind speed, weather code). A Lua script can map weather codes to\nlocal icons for visualization.\n\nParses JSON for detailed weather data, supports integration with\ncustom icons (referencing WorldWeatherOnline’s weather codes), and allows for\nflexible widget design.\n\n### Squeak\n\nTo embed into the world main docking bar:\n\n```smalltalk\nwttr := (UpdatingStringMorph on: [(WebClient httpGet: 'https://wttr.in/?format=%20%20%l:%20%C+%t') content] selector: #value)\n\tstepTime: 60000;\n\tuseStringFormat;\n\tyourself.\ndockingBar := World mainDockingBars first.\ndockingBar addMorph: wttr after: (dockingBar findA: ClockMorph).\n```\n\n![wttr.in integration in the Squeak world main docking bar](https://github.com/user-attachments/assets/4c2762b0-77ae-41a8-98db-3eb310d073bd)\n\n### Twitch\n\nwttr.in is used to create a custom `!weather` command for Twitch streams, allowing viewers to query weather for a specific location (e.g., `!weather Toronto`).\nThe command formats wttr.in output for display in chat.\n\n```bash\ncurl \"https://wttr.in/Toronto?format=:+%c+%l+is+currently+%C+with+a+temperature+of+%t+(+%f).+The+wind+is+blowing+from+%w.+The+Humidity+is+currently+%h&u\"\n```\n\nThis outputs, e.g., : ⛅️ Toronto is currently Partly Cloudy with a temperature\nof +7°C (+45°F). The wind is blowing from NE. The humidity is currently 65%. To\ndisplay Fahrenheit in parentheses, add `?u` to the URL for USCS units.\n\nFeatures: Customizable output for Twitch chat, supports both Celsius and\nFahrenheit, and handles location-based queries dynamically.\n\nDetails: [wttr.in-on-twitch](https://www.reddit.com/r/commandline/comments/1eqoa0w/creating_a_weather_command_using_wttrin_service/)\n\n\n### Google Sheets / Excel 365\n\nIt is possible to show the live weather in Google Sheets.\n\nAssume you want the weather image for a specific location, and the location is either hardcoded or stored in a cell.\nExample 1: Hardcoded Location (London):\nIn a cell (e.g., A1), enter:\nexcel\n\n```\n=IMAGE(\"https://wttr.in/London_0pq.png\", 1)\n```\n\nThis inserts a weather image for London, resized to fit the cell while maintaining the aspect ratio.\nExample 2: Dynamic Location (from a cell):\nIf cell B1 contains the location (e.g., London), use:\n\n```excel\n=IMAGE(\"https://wttr.in/\"&B1&\"_0pq.png\", 4, 100, 200)\n```\n\nThis inserts the image with a custom size (100px height, 200px width). Adjust height and width as needed.\n\nCustomize the wttr.in URL (Optional):\n\n* `_0pq`: Simple weather image (current conditions, no background).\n* `_m`: Metric units (e.g., Celsius).\n* `_u`: USCS units (e.g., Fahrenheit).\n* `_t`: Transparent background.\n\nExample with metric units and transparency:\n\n```\n=IMAGE(\"https://wttr.in/\"&B1&\"_0pqt_m.png\", 1)\n```\n\n![Google Sheets Example](google-sheets.png)\n\n### Raycast\n\n* Raycast Store: https://www.raycast.com/tonka3000/weather\n* Source code: [Github](https://github.com/raycast/extensions/tree/542ed079c2eb5a95df0835d83ab1f1c2b1970e44/extensions/weather/)\n* Author: [tonka3000](https://github.com/tonka3000)\n\nRaycast is a handy tool for Mac users that helps them work faster and more\nefficiently.  It's popular among developers, designers, and tech enthusiasts who\nwant to streamline their workflows.\nWith Raycast, you can quickly launch apps,\nsearch for files, and perform everyday tasks all from one central place,\nboosting productivity and saving time.\n\nWith the \"Weather\" extension, you can quickly check information about the current weather.\n\n![wttr.in in raycast](raycast.png)\n"
  },
  {
    "path": "doc/terminal-images.md",
    "content": "\n## Map view (v3)\n\nIn the experimental map view, that is available under the view code `v3`,\nweather information about a geographical region is available:\n\n```\n    $ curl v3.wttr.in/Bayern.sxl\n```\n\n![v3.wttr.in/Bayern](https://v3.wttr.in/Bayern.png)\n\nor directly in browser:\n\n*   https://v3.wttr.in/Bayern\n\nThe map view currently supports three formats:\n\n* PNG (for browser and messangers);\n* Sixel (terminal inline images support);\n* IIP (terminal with iterm2 inline images protocol support).\n\n## Terminal with images support\n\n\n| Terminal              | Environment    | Images support | Protocol |\n| --------------------- | --------- | ------------- | --------- |\n| uxterm                |   X11     |   yes         |   Sixel   |\n| mlterm                |   X11     |   yes         |   Sixel   |\n| kitty                 |   X11     |   yes         |   Kitty   |\n| wezterm               |   X11     |   yes         |   IIP     |\n| Darktile              |   X11     |   yes         |   Sixel   |\n| Jexer                 |   X11     |   yes         |   Sixel   |\n| GNOME Terminal        |   X11     |   [in-progress](https://gitlab.gnome.org/GNOME/vte/-/issues/253) |   Sixel   |\n| alacritty             |   X11     |   [in-progress](https://github.com/alacritty/alacritty/issues/910) |  Sixel   |\n| st                    |   X11     | [stixel](https://github.com/vizs/stixel) or [st-sixel](https://github.com/galatolofederico/st-sixel)     |   Sixel   |\n| Konsole               |   X11     |   yes         |   Sixel   |\n| DomTerm               |   Web     |   yes         |   Sixel   |\n| Yaft                  |   FB      |   yes         |   Sixel   |\n| iTerm2                |   Mac OS X|   yes         |   IIP     |\n| mintty                | Windows   |   yes         |   Sixel   |\n| Windows Terminal  |   Windows     |   [in-progress](https://github.com/microsoft/terminal/issues/448) |   Sixel   |\n| [RLogin](http://nanno.dip.jp/softlib/man/rlogin/) | Windows | yes         |   Sixel   |   |\n\nSupport in all VTE-based terminals: termite, terminator, etc is more or less the same as in the GNOME Terminal\n\n## Notes\n\n### xterm/uxterm\n\nTo start xterm/uxterm with Sixel support:\n\n```\nuxterm -ti vt340\n```\n\n### Kitty\n\nTo view images in kitty:\n\n```\ncurl -s v3.wttr.in/Tabasco.png | kitty icat --align=left\n```\n\nor even without `curl` at  all, because `icat` knows how to handle URLs:\n\n```\nkitty icat --align=left https://v3.wttr.in/Tabasco.png\n```\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/chubin/wttr.in\n\ngo 1.16\n\nrequire (\n\tgithub.com/alecthomas/kong v1.7.0\n\tgithub.com/denisenkom/go-mssqldb v0.0.0-20200910202707-1e08a3fab204 // indirect\n\tgithub.com/go-sql-driver/mysql v1.5.0 // indirect\n\tgithub.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect\n\tgithub.com/hashicorp/golang-lru v1.0.2\n\tgithub.com/itchyny/gojq v0.12.11 // indirect\n\tgithub.com/klauspost/lctime v0.1.0\n\tgithub.com/lib/pq v1.8.0 // indirect\n\tgithub.com/mattn/go-colorable v0.1.14\n\tgithub.com/mattn/go-runewidth v0.0.16\n\tgithub.com/mattn/go-sqlite3 v1.14.24 // indirect\n\tgithub.com/rivo/uniseg v0.4.7 // indirect\n\tgithub.com/robfig/cron v1.2.0\n\tgithub.com/samonzeweb/godb v1.0.13\n\tgithub.com/sirupsen/logrus v1.9.3\n\tgithub.com/smartystreets/assertions v1.2.0 // indirect\n\tgithub.com/smartystreets/goconvey v1.6.4 // indirect\n\tgithub.com/stretchr/testify v1.8.1 // indirect\n\tgithub.com/zsefvlol/timezonemapper v1.0.0\n\tgolang.org/x/crypto v0.17.0 // indirect\n\tgolang.org/x/sys v0.30.0 // indirect\n\tgoogle.golang.org/appengine v1.6.3 // indirect\n\tgopkg.in/yaml.v3 v3.0.1\n)\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/alecthomas/assert/v2 v2.1.0/go.mod h1:b/+1DI2Q6NckYi+3mXyH3wFb8qG37K/DuK80n7WefXA=\ngithub.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=\ngithub.com/alecthomas/kong v0.7.1 h1:azoTh0IOfwlAX3qN9sHWTxACE2oV8Bg2gAwBsMwDQY4=\ngithub.com/alecthomas/kong v0.7.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U=\ngithub.com/alecthomas/kong v1.7.0 h1:MnT8+5JxFDCvISeI6vgd/mFbAJwueJ/pqQNzZMsiqZE=\ngithub.com/alecthomas/kong v1.7.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=\ngithub.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=\ngithub.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/denisenkom/go-mssqldb v0.0.0-20190920000552-128d9f4ae1cd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=\ngithub.com/denisenkom/go-mssqldb v0.0.0-20200910202707-1e08a3fab204/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=\ngithub.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=\ngithub.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=\ngithub.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=\ngithub.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=\ngithub.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=\ngithub.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4=\ngithub.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=\ngithub.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=\ngithub.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=\ngithub.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=\ngithub.com/itchyny/gojq v0.12.11 h1:YhLueoHhHiN4mkfM+3AyJV6EPcCxKZsOnYf+aVSwaQw=\ngithub.com/itchyny/gojq v0.12.11/go.mod h1:o3FT8Gkbg/geT4pLI0tF3hvip5F3Y/uskjRz9OYa38g=\ngithub.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=\ngithub.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=\ngithub.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=\ngithub.com/klauspost/lctime v0.1.0 h1:nINsuFc860M9cyYhT6vfg6U1USh7kiVBj/s/2b04U70=\ngithub.com/klauspost/lctime v0.1.0/go.mod h1:OwdMhr8tbQvusAsnilqkkgDQqivWlqyg0w5cfXkLiDk=\ngithub.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=\ngithub.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=\ngithub.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=\ngithub.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=\ngithub.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=\ngithub.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=\ngithub.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=\ngithub.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=\ngithub.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=\ngithub.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=\ngithub.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=\ngithub.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=\ngithub.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=\ngithub.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=\ngithub.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=\ngithub.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=\ngithub.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=\ngithub.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=\ngithub.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=\ngithub.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=\ngithub.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=\ngithub.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=\ngithub.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=\ngithub.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=\ngithub.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=\ngithub.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=\ngithub.com/samonzeweb/godb v1.0.8 h1:WRn6nq0FChYOzh+w8SgpXHUkEhL7W6ZqkCf5Ninx7Uc=\ngithub.com/samonzeweb/godb v1.0.8/go.mod h1:LNDt3CakfBwpRY4AD0y/QPTbj+jB6O17tSxQES0p47o=\ngithub.com/samonzeweb/godb v1.0.13 h1:dEWijZGizhSN7oOLFYq0+NquG54DCJ9WG55bEcH7GOA=\ngithub.com/samonzeweb/godb v1.0.13/go.mod h1:Dcm9f9+aO6bQin4Ce4X3oOM2gvhGMt2naLIDLPQSaWQ=\ngithub.com/samonzeweb/godb v1.0.15 h1:HyNb8o1w109as9KWE8ih1YIBe8jC4luJ22f1XNacW38=\ngithub.com/samonzeweb/godb v1.0.15/go.mod h1:SxCHqyireDXNrZApknS9lGUEutA43x9eJF632ecbK5Q=\ngithub.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=\ngithub.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=\ngithub.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=\ngithub.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=\ngithub.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=\ngithub.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=\ngithub.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=\ngithub.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=\ngithub.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=\ngithub.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=\ngithub.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=\ngithub.com/zsefvlol/timezonemapper v1.0.0 h1:HXqkOzf01gXYh2nDQcDSROikFgMaximnhE8BY9SyF6E=\ngithub.com/zsefvlol/timezonemapper v1.0.0/go.mod h1:cVUCOLEmc/VvOMusEhpd2G/UBtadL26ZVz2syODXDoQ=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=\ngolang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=\ngolang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=\ngolang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=\ngolang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=\ngolang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=\ngolang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=\ngolang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=\ngolang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=\ngolang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=\ngolang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=\ngolang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=\ngolang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=\ngolang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=\ngolang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=\ngolang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=\ngolang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=\ngolang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=\ngolang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngoogle.golang.org/appengine v1.6.3/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\n"
  },
  {
    "path": "internal/config/config.go",
    "content": "package config\n\nimport (\n\t\"log\"\n\t\"os\"\n\n\t\"gopkg.in/yaml.v3\"\n\n\t\"github.com/chubin/wttr.in/internal/types\"\n\t\"github.com/chubin/wttr.in/internal/util\"\n)\n\n// Config of the program.\ntype Config struct {\n\tCache\n\tGeo\n\tLogging\n\tServer\n\tUplink\n}\n\n// Logging configuration.\ntype Logging struct {\n\t// AccessLog path.\n\tAccessLog string `yaml:\"accessLog,omitempty\"`\n\n\t// ErrorsLog path.\n\tErrorsLog string `yaml:\"errorsLog,omitempty\"`\n\n\t// Interval between access log flushes, in seconds.\n\tInterval int `yaml:\"interval,omitempty\"`\n}\n\n// Server configuration.\ntype Server struct {\n\t// PortHTTP is port where HTTP server must listen.\n\t// If 0, HTTP is disabled.\n\tPortHTTP int `yaml:\"portHttp,omitempty\"`\n\n\t// PortHTTP is port where the HTTPS server must listen.\n\t// If 0, HTTPS is disabled.\n\tPortHTTPS int `yaml:\"portHttps,omitempty\"`\n\n\t// TLSCertFile contains path to cert file for TLS Server.\n\tTLSCertFile string `yaml:\"tlsCertFile,omitempty\"`\n\n\t// TLSCertFile contains path to key file for TLS Server.\n\tTLSKeyFile string `yaml:\"tlsKeyFile,omitempty\"`\n}\n\n// Uplink configuration.\ntype Uplink struct {\n\t// Address1 contains address of the uplink server in form IP:PORT\n\t// for format=j1 queries.\n\tAddress1 string `yaml:\"address1,omitempty\"`\n\n\t// Address2 contains address of the uplink server in form IP:PORT\n\t// for format=* queries.\n\tAddress2 string `yaml:\"address2,omitempty\"`\n\n\t// Address3 contains address of the uplink server in form IP:PORT\n\t// for all other queries.\n\tAddress3 string `yaml:\"address3,omitempty\"`\n\n\t// Address4 contains address of the uplink server in form IP:PORT\n\t// for PNG queries.\n\tAddress4 string `yaml:\"address4,omitempty\"`\n\n\t// Timeout for upstream queries.\n\tTimeout int `yaml:\"timeout,omitempty\"`\n\n\t// PrefetchInterval contains time (in milliseconds) indicating,\n\t// how long the prefetch procedure should take.\n\tPrefetchInterval int `yaml:\"prefetchInterval,omitempty\"`\n}\n\n// Cache configuration.\ntype Cache struct {\n\t// Size of the main cache.\n\tSize int `yaml:\"size,omitempty\"`\n}\n\n// Geo contains geolocation configuration.\ntype Geo struct {\n\t// IPCache contains the path to the IP Geodata cache.\n\tIPCache string `yaml:\"ipCache,omitempty\"`\n\n\t// IPCacheDB contains the path to the SQLite DB with the IP Geodata cache.\n\tIPCacheDB string `yaml:\"ipCacheDb,omitempty\"`\n\n\tIPCacheType types.CacheType `yaml:\"ipCacheType,omitempty\"`\n\n\t// LocationCache contains the path to the Location Geodata cache.\n\tLocationCache string `yaml:\"locationCache,omitempty\"`\n\n\t// LocationCacheDB contains the path to the SQLite DB with the Location Geodata cache.\n\tLocationCacheDB string `yaml:\"locationCacheDb,omitempty\"`\n\n\tLocationCacheType types.CacheType `yaml:\"locationCacheType,omitempty\"`\n\n\tNominatim []Nominatim `yaml:\"nominatim\"`\n}\n\ntype Nominatim struct {\n\tName string\n\n\t// Type describes the type of the location service.\n\t// Supported types: iq.\n\tType string\n\n\tURL string\n\n\tToken string\n}\n\n// Default contains the default configuration.\nfunc Default() *Config {\n\treturn &Config{\n\t\tCache{\n\t\t\tSize: 12800,\n\t\t},\n\t\tGeo{\n\t\t\tIPCache:           \"/wttr.in/cache/ip2l\",\n\t\t\tIPCacheDB:         \"/wttr.in/cache/geoip.db\",\n\t\t\tIPCacheType:       types.CacheTypeDB,\n\t\t\tLocationCache:     \"/wttr.in/cache/loc\",\n\t\t\tLocationCacheDB:   \"/wttr.in/cache/geoloc.db\",\n\t\t\tLocationCacheType: types.CacheTypeDB,\n\t\t\tNominatim: []Nominatim{\n\t\t\t\t{\n\t\t\t\t\tName:  \"locationiq\",\n\t\t\t\t\tType:  \"iq\",\n\t\t\t\t\tURL:   \"https://eu1.locationiq.com/v1/search\",\n\t\t\t\t\tToken: os.Getenv(\"NOMINATIM_LOCATIONIQ\"),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName:  \"opencage\",\n\t\t\t\t\tType:  \"opencage\",\n\t\t\t\t\tURL:   \"https://api.opencagedata.com/geocode/v1/json\",\n\t\t\t\t\tToken: os.Getenv(\"NOMINATIM_OPENCAGE\"),\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tLogging{\n\t\t\tAccessLog: \"/wttr.in/log/access.log\",\n\t\t\tErrorsLog: \"/wttr.in/log/errors.log\",\n\t\t\tInterval:  300,\n\t\t},\n\t\tServer{\n\t\t\tPortHTTP:    8083,\n\t\t\tPortHTTPS:   8084,\n\t\t\tTLSCertFile: \"/wttr.in/etc/fullchain.pem\",\n\t\t\tTLSKeyFile:  \"/wttr.in/etc/privkey.pem\",\n\t\t},\n\t\tUplink{\n\t\t\tAddress1:         \"127.0.0.1:9002\",\n\t\t\tAddress2:         \"127.0.0.1:9002\",\n\t\t\tAddress3:         \"127.0.0.1:9002\",\n\t\t\tAddress4:         \"127.0.0.1:9002\",\n\t\t\tTimeout:          30,\n\t\t\tPrefetchInterval: 300,\n\t\t},\n\t}\n}\n\n// Load config from file.\nfunc Load(filename string) (*Config, error) {\n\tvar (\n\t\tconfig Config\n\t\tdata   []byte\n\t\terr    error\n\t)\n\n\tdata, err = os.ReadFile(filename)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\terr = util.YamlUnmarshalStrict(data, &config)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &config, nil\n}\n\nfunc (c *Config) Dump() []byte {\n\tdata, err := yaml.Marshal(c)\n\tif err != nil {\n\t\t// should never happen.\n\t\tlog.Fatalln(\"config.Dump():\", err)\n\t}\n\n\treturn data\n}\n"
  },
  {
    "path": "internal/fmt/png/colors.go",
    "content": "package main\n\n// Source: https://www.ditig.com/downloads/256-colors.json\n\nvar ansiColorsDB = [][3]float64{\n\t{\n\t\t0, 0, 0,\n\t},\n\t{\n\t\t128, 0, 0,\n\t},\n\t{\n\t\t0, 128, 0,\n\t},\n\t{\n\t\t128, 128, 0,\n\t},\n\t{\n\t\t0, 0, 128,\n\t},\n\t{\n\t\t128, 0, 128,\n\t},\n\t{\n\t\t0, 128, 128,\n\t},\n\t{\n\t\t192, 192, 192,\n\t},\n\t{\n\t\t128, 128, 128,\n\t},\n\t{\n\t\t255, 0, 0,\n\t},\n\t{\n\t\t0, 255, 0,\n\t},\n\t{\n\t\t255, 255, 0,\n\t},\n\t{\n\t\t0, 0, 255,\n\t},\n\t{\n\t\t255, 0, 255,\n\t},\n\t{\n\t\t0, 255, 255,\n\t},\n\t{\n\t\t255, 255, 255,\n\t},\n\t{\n\t\t0, 0, 0,\n\t},\n\t{\n\t\t0, 0, 95,\n\t},\n\t{\n\t\t0, 0, 135,\n\t},\n\t{\n\t\t0, 0, 175,\n\t},\n\t{\n\t\t0, 0, 215,\n\t},\n\t{\n\t\t0, 0, 255,\n\t},\n\t{\n\t\t0, 95, 0,\n\t},\n\t{\n\t\t0, 95, 95,\n\t},\n\t{\n\t\t0, 95, 135,\n\t},\n\t{\n\t\t0, 95, 175,\n\t},\n\t{\n\t\t0, 95, 215,\n\t},\n\t{\n\t\t0, 95, 255,\n\t},\n\t{\n\t\t0, 135, 0,\n\t},\n\t{\n\t\t0, 135, 95,\n\t},\n\t{\n\t\t0, 135, 135,\n\t},\n\t{\n\t\t0, 135, 175,\n\t},\n\t{\n\t\t0, 135, 215,\n\t},\n\t{\n\t\t0, 135, 255,\n\t},\n\t{\n\t\t0, 175, 0,\n\t},\n\t{\n\t\t0, 175, 95,\n\t},\n\t{\n\t\t0, 175, 135,\n\t},\n\t{\n\t\t0, 175, 175,\n\t},\n\t{\n\t\t0, 175, 215,\n\t},\n\t{\n\t\t0, 175, 255,\n\t},\n\t{\n\t\t0, 215, 0,\n\t},\n\t{\n\t\t0, 215, 95,\n\t},\n\t{\n\t\t0, 215, 135,\n\t},\n\t{\n\t\t0, 215, 175,\n\t},\n\t{\n\t\t0, 215, 215,\n\t},\n\t{\n\t\t0, 215, 255,\n\t},\n\t{\n\t\t0, 255, 0,\n\t},\n\t{\n\t\t0, 255, 95,\n\t},\n\t{\n\t\t0, 255, 135,\n\t},\n\t{\n\t\t0, 255, 175,\n\t},\n\t{\n\t\t0, 255, 215,\n\t},\n\t{\n\t\t0, 255, 255,\n\t},\n\t{\n\t\t95, 0, 0,\n\t},\n\t{\n\t\t95, 0, 95,\n\t},\n\t{\n\t\t95, 0, 135,\n\t},\n\t{\n\t\t95, 0, 175,\n\t},\n\t{\n\t\t95, 0, 215,\n\t},\n\t{\n\t\t95, 0, 255,\n\t},\n\t{\n\t\t95, 95, 0,\n\t},\n\t{\n\t\t95, 95, 95,\n\t},\n\t{\n\t\t95, 95, 135,\n\t},\n\t{\n\t\t95, 95, 175,\n\t},\n\t{\n\t\t95, 95, 215,\n\t},\n\t{\n\t\t95, 95, 255,\n\t},\n\t{\n\t\t95, 135, 0,\n\t},\n\t{\n\t\t95, 135, 95,\n\t},\n\t{\n\t\t95, 135, 135,\n\t},\n\t{\n\t\t95, 135, 175,\n\t},\n\t{\n\t\t95, 135, 215,\n\t},\n\t{\n\t\t95, 135, 255,\n\t},\n\t{\n\t\t95, 175, 0,\n\t},\n\t{\n\t\t95, 175, 95,\n\t},\n\t{\n\t\t95, 175, 135,\n\t},\n\t{\n\t\t95, 175, 175,\n\t},\n\t{\n\t\t95, 175, 215,\n\t},\n\t{\n\t\t95, 175, 255,\n\t},\n\t{\n\t\t95, 215, 0,\n\t},\n\t{\n\t\t95, 215, 95,\n\t},\n\t{\n\t\t95, 215, 135,\n\t},\n\t{\n\t\t95, 215, 175,\n\t},\n\t{\n\t\t95, 215, 215,\n\t},\n\t{\n\t\t95, 215, 255,\n\t},\n\t{\n\t\t95, 255, 0,\n\t},\n\t{\n\t\t95, 255, 95,\n\t},\n\t{\n\t\t95, 255, 135,\n\t},\n\t{\n\t\t95, 255, 175,\n\t},\n\t{\n\t\t95, 255, 215,\n\t},\n\t{\n\t\t95, 255, 255,\n\t},\n\t{\n\t\t135, 0, 0,\n\t},\n\t{\n\t\t135, 0, 95,\n\t},\n\t{\n\t\t135, 0, 135,\n\t},\n\t{\n\t\t135, 0, 175,\n\t},\n\t{\n\t\t135, 0, 215,\n\t},\n\t{\n\t\t135, 0, 255,\n\t},\n\t{\n\t\t135, 95, 0,\n\t},\n\t{\n\t\t135, 95, 95,\n\t},\n\t{\n\t\t135, 95, 135,\n\t},\n\t{\n\t\t135, 95, 175,\n\t},\n\t{\n\t\t135, 95, 215,\n\t},\n\t{\n\t\t135, 95, 255,\n\t},\n\t{\n\t\t135, 135, 0,\n\t},\n\t{\n\t\t135, 135, 95,\n\t},\n\t{\n\t\t135, 135, 135,\n\t},\n\t{\n\t\t135, 135, 175,\n\t},\n\t{\n\t\t135, 135, 215,\n\t},\n\t{\n\t\t135, 135, 255,\n\t},\n\t{\n\t\t135, 175, 0,\n\t},\n\t{\n\t\t135, 175, 95,\n\t},\n\t{\n\t\t135, 175, 135,\n\t},\n\t{\n\t\t135, 175, 175,\n\t},\n\t{\n\t\t135, 175, 215,\n\t},\n\t{\n\t\t135, 175, 255,\n\t},\n\t{\n\t\t135, 215, 0,\n\t},\n\t{\n\t\t135, 215, 95,\n\t},\n\t{\n\t\t135, 215, 135,\n\t},\n\t{\n\t\t135, 215, 175,\n\t},\n\t{\n\t\t135, 215, 215,\n\t},\n\t{\n\t\t135, 215, 255,\n\t},\n\t{\n\t\t135, 255, 0,\n\t},\n\t{\n\t\t135, 255, 95,\n\t},\n\t{\n\t\t135, 255, 135,\n\t},\n\t{\n\t\t135, 255, 175,\n\t},\n\t{\n\t\t135, 255, 215,\n\t},\n\t{\n\t\t135, 255, 255,\n\t},\n\t{\n\t\t175, 0, 0,\n\t},\n\t{\n\t\t175, 0, 95,\n\t},\n\t{\n\t\t175, 0, 135,\n\t},\n\t{\n\t\t175, 0, 175,\n\t},\n\t{\n\t\t175, 0, 215,\n\t},\n\t{\n\t\t175, 0, 255,\n\t},\n\t{\n\t\t175, 95, 0,\n\t},\n\t{\n\t\t175, 95, 95,\n\t},\n\t{\n\t\t175, 95, 135,\n\t},\n\t{\n\t\t175, 95, 175,\n\t},\n\t{\n\t\t175, 95, 215,\n\t},\n\t{\n\t\t175, 95, 255,\n\t},\n\t{\n\t\t175, 135, 0,\n\t},\n\t{\n\t\t175, 135, 95,\n\t},\n\t{\n\t\t175, 135, 135,\n\t},\n\t{\n\t\t175, 135, 175,\n\t},\n\t{\n\t\t175, 135, 215,\n\t},\n\t{\n\t\t175, 135, 255,\n\t},\n\t{\n\t\t175, 175, 0,\n\t},\n\t{\n\t\t175, 175, 95,\n\t},\n\t{\n\t\t175, 175, 135,\n\t},\n\t{\n\t\t175, 175, 175,\n\t},\n\t{\n\t\t175, 175, 215,\n\t},\n\t{\n\t\t175, 175, 255,\n\t},\n\t{\n\t\t175, 215, 0,\n\t},\n\t{\n\t\t175, 215, 95,\n\t},\n\t{\n\t\t175, 215, 135,\n\t},\n\t{\n\t\t175, 215, 175,\n\t},\n\t{\n\t\t175, 215, 215,\n\t},\n\t{\n\t\t175, 215, 255,\n\t},\n\t{\n\t\t175, 255, 0,\n\t},\n\t{\n\t\t175, 255, 95,\n\t},\n\t{\n\t\t175, 255, 135,\n\t},\n\t{\n\t\t175, 255, 175,\n\t},\n\t{\n\t\t175, 255, 215,\n\t},\n\t{\n\t\t175, 255, 255,\n\t},\n\t{\n\t\t215, 0, 0,\n\t},\n\t{\n\t\t215, 0, 95,\n\t},\n\t{\n\t\t215, 0, 135,\n\t},\n\t{\n\t\t215, 0, 175,\n\t},\n\t{\n\t\t215, 0, 215,\n\t},\n\t{\n\t\t215, 0, 255,\n\t},\n\t{\n\t\t215, 95, 0,\n\t},\n\t{\n\t\t215, 95, 95,\n\t},\n\t{\n\t\t215, 95, 135,\n\t},\n\t{\n\t\t215, 95, 175,\n\t},\n\t{\n\t\t215, 95, 215,\n\t},\n\t{\n\t\t215, 95, 255,\n\t},\n\t{\n\t\t215, 135, 0,\n\t},\n\t{\n\t\t215, 135, 95,\n\t},\n\t{\n\t\t215, 135, 135,\n\t},\n\t{\n\t\t215, 135, 175,\n\t},\n\t{\n\t\t215, 135, 215,\n\t},\n\t{\n\t\t215, 135, 255,\n\t},\n\t{\n\t\t215, 175, 0,\n\t},\n\t{\n\t\t215, 175, 95,\n\t},\n\t{\n\t\t215, 175, 135,\n\t},\n\t{\n\t\t215, 175, 175,\n\t},\n\t{\n\t\t215, 175, 215,\n\t},\n\t{\n\t\t215, 175, 255,\n\t},\n\t{\n\t\t215, 215, 0,\n\t},\n\t{\n\t\t215, 215, 95,\n\t},\n\t{\n\t\t215, 215, 135,\n\t},\n\t{\n\t\t215, 215, 175,\n\t},\n\t{\n\t\t215, 215, 215,\n\t},\n\t{\n\t\t215, 215, 255,\n\t},\n\t{\n\t\t215, 255, 0,\n\t},\n\t{\n\t\t215, 255, 95,\n\t},\n\t{\n\t\t215, 255, 135,\n\t},\n\t{\n\t\t215, 255, 175,\n\t},\n\t{\n\t\t215, 255, 215,\n\t},\n\t{\n\t\t215, 255, 255,\n\t},\n\t{\n\t\t255, 0, 0,\n\t},\n\t{\n\t\t255, 0, 95,\n\t},\n\t{\n\t\t255, 0, 135,\n\t},\n\t{\n\t\t255, 0, 175,\n\t},\n\t{\n\t\t255, 0, 215,\n\t},\n\t{\n\t\t255, 0, 255,\n\t},\n\t{\n\t\t255, 95, 0,\n\t},\n\t{\n\t\t255, 95, 95,\n\t},\n\t{\n\t\t255, 95, 135,\n\t},\n\t{\n\t\t255, 95, 175,\n\t},\n\t{\n\t\t255, 95, 215,\n\t},\n\t{\n\t\t255, 95, 255,\n\t},\n\t{\n\t\t255, 135, 0,\n\t},\n\t{\n\t\t255, 135, 95,\n\t},\n\t{\n\t\t255, 135, 135,\n\t},\n\t{\n\t\t255, 135, 175,\n\t},\n\t{\n\t\t255, 135, 215,\n\t},\n\t{\n\t\t255, 135, 255,\n\t},\n\t{\n\t\t255, 175, 0,\n\t},\n\t{\n\t\t255, 175, 95,\n\t},\n\t{\n\t\t255, 175, 135,\n\t},\n\t{\n\t\t255, 175, 175,\n\t},\n\t{\n\t\t255, 175, 215,\n\t},\n\t{\n\t\t255, 175, 255,\n\t},\n\t{\n\t\t255, 215, 0,\n\t},\n\t{\n\t\t255, 215, 95,\n\t},\n\t{\n\t\t255, 215, 135,\n\t},\n\t{\n\t\t255, 215, 175,\n\t},\n\t{\n\t\t255, 215, 215,\n\t},\n\t{\n\t\t255, 215, 255,\n\t},\n\t{\n\t\t255, 255, 0,\n\t},\n\t{\n\t\t255, 255, 95,\n\t},\n\t{\n\t\t255, 255, 135,\n\t},\n\t{\n\t\t255, 255, 175,\n\t},\n\t{\n\t\t255, 255, 215,\n\t},\n\t{\n\t\t255, 255, 255,\n\t},\n\t{\n\t\t8, 8, 8,\n\t},\n\t{\n\t\t18, 18, 18,\n\t},\n\t{\n\t\t28, 28, 28,\n\t},\n\t{\n\t\t38, 38, 38,\n\t},\n\t{\n\t\t48, 48, 48,\n\t},\n\t{\n\t\t58, 58, 58,\n\t},\n\t{\n\t\t68, 68, 68,\n\t},\n\t{\n\t\t78, 78, 78,\n\t},\n\t{\n\t\t88, 88, 88,\n\t},\n\t{\n\t\t98, 98, 98,\n\t},\n\t{\n\t\t108, 108, 108,\n\t},\n\t{\n\t\t118, 118, 118,\n\t},\n\t{\n\t\t128, 128, 128,\n\t},\n\t{\n\t\t138, 138, 138,\n\t},\n\t{\n\t\t148, 148, 148,\n\t},\n\t{\n\t\t158, 158, 158,\n\t},\n\t{\n\t\t168, 168, 168,\n\t},\n\t{\n\t\t178, 178, 178,\n\t},\n\t{\n\t\t188, 188, 188,\n\t},\n\t{\n\t\t198, 198, 198,\n\t},\n\t{\n\t\t208, 208, 208,\n\t},\n\t{\n\t\t218, 218, 218,\n\t},\n\t{\n\t\t228, 228, 228,\n\t},\n\t{\n\t\t238, 238, 238,\n\t},\n}\n"
  },
  {
    "path": "internal/fmt/png/go.mod",
    "content": "module example.com/m/v2\n\ngo 1.20\n\nrequire (\n\tgithub.com/chubin/vt10x v0.0.0-20231112153020-ef4f56837bf1 // indirect\n\tgithub.com/fogleman/gg v1.3.0 // indirect\n\tgithub.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect\n\tgolang.org/x/image v0.14.0 // indirect\n)\n"
  },
  {
    "path": "internal/fmt/png/go.sum",
    "content": "github.com/chubin/vt10x v0.0.0-20231112153020-ef4f56837bf1 h1:CHg5BTAJZmCjBaAAQrD92s248JHH3JTsLlaC6QBJo/Y=\ngithub.com/chubin/vt10x v0.0.0-20231112153020-ef4f56837bf1/go.mod h1:mQssL2gI1LTqWgbffl6DESqe6QkAF67ujBdzSe4bWkU=\ngithub.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=\ngithub.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=\ngithub.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=\ngithub.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=\ngolang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=\ngolang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=\n"
  },
  {
    "path": "internal/fmt/png/png.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/chubin/vt10x\"\n\t\"github.com/fogleman/gg\"\n)\n\nfunc StringSliceToRuneSlice(s string) [][]rune {\n\tstrings := strings.Split(s, \"\\n\")\n\tresult := make([][]rune, len(strings))\n\n\ti := 0\n\tfor _, str := range strings {\n\t\tif len(str) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tresult[i] = []rune(str)\n\t\ti++\n\t}\n\n\treturn result\n}\n\nfunc maxRowLength(rows [][]rune) int {\n\tmaxLen := 0\n\tfor _, row := range rows {\n\t\tif len(row) > maxLen {\n\t\t\tmaxLen = len(row)\n\t\t}\n\t}\n\treturn maxLen\n}\n\nfunc GeneratePng() {\n\trunes := StringSliceToRuneSlice(`\nWeather report: Hochstadt an der Aisch, Germany\n\n     \\  /       Partly cloudy\n   _ /\"\".-.     +5(2) °C\n     \\_(   ).   ↗ 9 km/h\n     /(___(__)  10 km\n                0.0 mm\n                        ┌─────────────┐\n┌───────────────────────┤  Sat 11 Nov ├───────────────────────┐\n│             Noon      └──────┬──────┘      Night            │\n├──────────────────────────────┼──────────────────────────────┤\n│  _'/\"\".-.     Patchy rain po…│  _'/\"\".-.     Patchy rain po…│\n│   ,\\_(   ).   +6(3) °C       │   ,\\_(   ).   +5(2) °C       │\n│    /(___(__)  → 22-29 km/h   │    /(___(__)  ↗ 14-20 km/h   │\n│      ‘ ‘ ‘ ‘  10 km          │      ‘ ‘ ‘ ‘  10 km          │\n│     ‘ ‘ ‘ ‘   0.1 mm | 86%   │     ‘ ‘ ‘ ‘   0.0 mm | 89%   │\n└──────────────────────────────┴──────────────────────────────┘\n                        ┌─────────────┐\n┌───────────────────────┤  Sun 12 Nov ├───────────────────────┐\n│             Noon      └──────┬──────┘      Night            │\n├──────────────────────────────┼──────────────────────────────┤\n│    \\  /       Partly cloudy  │      .-.      Light drizzle  │\n│  _ /\"\".-.     +8(7) °C       │     (   ).    +5(2) °C       │\n│    \\_(   ).   ↑ 7-8 km/h     │    (___(__)   ↑ 13-18 km/h   │\n│    /(___(__)  10 km          │     ‘ ‘ ‘ ‘   2 km           │\n│               0.0 mm | 0%    │    ‘ ‘ ‘ ‘    0.3 mm | 76%   │\n└──────────────────────────────┴──────────────────────────────┘\n`)\n\n\t// Dimensions of each rune in pixels\n\truneWidth := 8\n\truneHeight := 14\n\n\t// Compute the width and height of the final image\n\timageWidth := runeWidth * maxRowLength(runes)\n\timageHeight := runeHeight * len(runes)\n\n\t// Create a new context with the computed dimensions\n\tdc := gg.NewContext(imageWidth, imageHeight)\n\n\t// fontPath := \"/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf\"\n\t// fontPath := \"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc\"\n\tfontPath := \"/usr/share/fonts/truetype/lexi/LexiGulim.ttf\"\n\n\terr := dc.LoadFontFace(fontPath, 13)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Loop through each rune in the array and draw it on the context\n\tfor i, row := range runes {\n\t\tfor j, char := range row {\n\t\t\t// Compute the x and y coordinates for drawing the current rune\n\t\t\tx := float64(j*runeWidth + runeWidth/2)\n\t\t\ty := float64(i*runeHeight + runeHeight/2)\n\n\t\t\t// Set the appropriate color for the current rune\n\t\t\tif char == '#' {\n\t\t\t\tdc.SetRGB(0, 0, 0) // Black\n\t\t\t} else if char == '@' {\n\t\t\t\tdc.SetRGB(1, 0, 0) // Red\n\t\t\t} else {\n\t\t\t\tdc.SetRGB(1, 1, 1) // White\n\t\t\t}\n\n\t\t\tcharacter := string(char)\n\t\t\t// if char == ' ' {\n\t\t\t// \tcharacter = fmt.Sprint(j % 10)\n\t\t\t// }\n\t\t\tdc.DrawRectangle(x, y, x+float64(runeWidth), y+float64(runeHeight))\n\t\t\tdc.Fill()\n\n\t\t\t// Draw a rectangle with the rune's dimensions and color\n\t\t\tdc.DrawString(character, x, y) // Draw the character centered on the canvas\n\t\t\t// dc.DrawStringAnchored(character, x, y, 0.5, 0.5) // Draw the character centered on the canvas\n\t\t}\n\t}\n\n\t// Save the image to a PNG file\n\terr = dc.SavePNG(\"output.png\")\n\tif err != nil {\n\t\tfmt.Println(\"Error saving PNG:\", err)\n\t\treturn\n\t}\n\n\tfmt.Println(\"PNG generated successfully\")\n}\n\nfunc GeneratePngFromANSI(input []byte, outputFile string) error {\n\t// Dimensions of each rune in pixels\n\truneWidth := 8\n\truneHeight := 14\n\tfontSize := 13.0\n\t// fontPath := \"/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf\"\n\tfontPath := \"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc\"\n\n\timageCols := 80\n\timageRows := 25\n\n\t// Compute the width and height of the final image\n\timageWidth := runeWidth * imageCols\n\timageHeight := runeHeight * imageRows\n\n\t// Create terminal and feed it with input.\n\tterm := vt10x.New(vt10x.WithSize(imageCols, imageRows))\n\t_, err := term.Write([]byte(\"\\033[20h\"))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"virtual terminal write error: %w\", err)\n\t}\n\n\t_, err = term.Write(input)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"virtual terminal write error: %w\", err)\n\t}\n\n\t// Create a new context with the computed dimensions\n\tdc := gg.NewContext(imageWidth, imageHeight)\n\n\terr = dc.LoadFontFace(fontPath, fontSize) // Set font size to 96\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error loading font: %w\", err)\n\t}\n\n\t// Loop through each rune in the array and draw it on the context\n\tfor i := 0; i < imageRows; i++ {\n\t\tfor j := 0; j < imageCols; j++ {\n\t\t\t// Compute the x and y coordinates for drawing the current rune\n\t\t\tx := float64(j * runeWidth)\n\t\t\ty := float64(i * runeHeight)\n\n\t\t\tcell := term.Cell(j, i)\n\t\t\tcharacter := string(cell.Char)\n\n\t\t\tdc.DrawRectangle(x, y, float64(runeWidth), float64(runeHeight))\n\t\t\tbg := colorANSItoRGB(cell.BG)\n\t\t\tdc.SetRGB(bg[0], bg[1], bg[2])\n\t\t\tdc.Fill()\n\n\t\t\tfg := colorANSItoRGB(cell.FG)\n\t\t\tdc.SetRGB(fg[0], fg[1], fg[2])\n\n\t\t\t// Draw a rectangle with the rune's dimensions and color\n\t\t\tdc.DrawString(character, x, y+float64(runeHeight)-3) // Draw the character centered on the canvas\n\t\t\t// dc.DrawStringAnchored(character, x, y, 0.5, 0.5) // Draw the character centered on the canvas\n\t\t}\n\t}\n\n\t// Save the image to a PNG file\n\terr = dc.SavePNG(outputFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error saving png: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc colorANSItoRGB(colorANSI vt10x.Color) [3]float64 {\n\tdefaultBG := vt10x.Color(0)\n\tdefaultFG := vt10x.Color(8)\n\n\tif colorANSI == vt10x.DefaultFG {\n\t\tcolorANSI = defaultFG\n\t}\n\tif colorANSI == vt10x.DefaultBG {\n\t\tcolorANSI = defaultBG\n\t}\n\n\tif colorANSI > 255 {\n\t\treturn [3]float64{127, 127, 127}\n\t}\n\treturn ansiColorsDB[colorANSI]\n}\n\nfunc main() {\n\tdata, err := os.ReadFile(\"zh-text.txt\")\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\terr = GeneratePngFromANSI(data, \"output.png\")\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n}\n"
  },
  {
    "path": "internal/geo/ip/convert.go",
    "content": "package ip\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"path/filepath\"\n\n\t\"github.com/samonzeweb/godb\"\n\t\"github.com/samonzeweb/godb/adapters/sqlite\"\n\n\t\"github.com/chubin/wttr.in/internal/util\"\n)\n\n//nolint:cyclop\nfunc (c *Cache) ConvertCache() error {\n\tdbfile := c.config.Geo.IPCacheDB\n\n\terr := util.RemoveFileIfExists(dbfile)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdb, err := godb.Open(sqlite.Adapter, dbfile)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = createTable(db, \"Address\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlog.Println(\"listing cache entries...\")\n\tfiles, err := filepath.Glob(filepath.Join(c.config.Geo.IPCache, \"*\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlog.Printf(\"going to convert %d entries\\n\", len(files))\n\n\tblock := []Address{}\n\tfor i, file := range files {\n\t\tip := filepath.Base(file)\n\t\tloc, err := c.Read(ip)\n\t\tif err != nil {\n\t\t\tlog.Println(\"invalid entry for\", ip)\n\n\t\t\tcontinue\n\t\t}\n\n\t\tblock = append(block, *loc)\n\n\t\tif i%1000 != 0 || i == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\terr = db.BulkInsert(&block).Do()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tblock = []Address{}\n\t\tlog.Println(\"converted\", i+1, \"entries\")\n\t}\n\n\t// inserting the rest.\n\terr = db.BulkInsert(&block).Do()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlog.Println(\"converted\", len(files), \"entries\")\n\n\treturn nil\n}\n\nfunc createTable(db *godb.DB, tableName string) error {\n\tcreateTable := fmt.Sprintf(\n\t\t`create table %s (\n\t    name           text not null primary key,\n        fullName       text not null,\n        lat            text not null,\n        long           text not null);\n\t`, tableName)\n\n\t_, err := db.CurrentDB().Exec(createTable)\n\n\treturn err\n}\n"
  },
  {
    "path": "internal/geo/ip/ip.go",
    "content": "package ip\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"path\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/samonzeweb/godb\"\n\t\"github.com/samonzeweb/godb/adapters/sqlite\"\n\n\t\"github.com/chubin/wttr.in/internal/config\"\n\t\"github.com/chubin/wttr.in/internal/routing\"\n\t\"github.com/chubin/wttr.in/internal/types\"\n\t\"github.com/chubin/wttr.in/internal/util\"\n)\n\n// Address information.\ntype Address struct {\n\tIP          string  `db:\"ip,key\"`\n\tCountryCode string  `db:\"countryCode\"`\n\tCountry     string  `db:\"country\"`\n\tRegion      string  `db:\"region\"`\n\tCity        string  `db:\"city\"`\n\tLatitude    float64 `db:\"latitude\"`\n\tLongitude   float64 `db:\"longitude\"`\n}\n\nfunc (l *Address) String() string {\n\tif l.Latitude == -1000 {\n\t\treturn fmt.Sprintf(\n\t\t\t\"%s;%s;%s;%s\",\n\t\t\tl.CountryCode, l.Country, l.Region, l.City)\n\t}\n\n\treturn fmt.Sprintf(\n\t\t\"%s;%s;%s;%s;%v;%v\",\n\t\tl.CountryCode, l.Country, l.Region, l.City, l.Latitude, l.Longitude)\n}\n\n// Cache provides access to the IP Geodata cache.\ntype Cache struct {\n\tconfig *config.Config\n\tdb     *godb.DB\n}\n\n// NewCache returns new cache reader for the specified config.\nfunc NewCache(config *config.Config) (*Cache, error) {\n\tdb, err := godb.Open(sqlite.Adapter, config.Geo.IPCacheDB)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Needed for \"upsert\" implementation in Put()\n\tdb.UseErrorParser()\n\n\treturn &Cache{\n\t\tconfig: config,\n\t\tdb:     db,\n\t}, nil\n}\n\n// Read returns location information from the cache, if found,\n// or types.ErrNotFound if not found. If the entry is found, but its format\n// is invalid, types.ErrInvalidCacheEntry is returned.\n//\n// Format:\n//\n//  [CountryCode];Country;Region;City;[Latitude];[Longitude]\n//\n// Example:\n//\n//  DE;Germany;Free and Hanseatic City of Hamburg;Hamburg;53.5736;9.9782\n//\n\nfunc (c *Cache) Read(addr string) (*Address, error) {\n\tif c.config.Geo.IPCacheType == types.CacheTypeDB {\n\t\treturn c.readFromCacheDB(addr)\n\t}\n\n\treturn c.readFromCacheFile(addr)\n}\n\nfunc (c *Cache) readFromCacheFile(addr string) (*Address, error) {\n\tbytes, err := os.ReadFile(c.cacheFile(addr))\n\tif err != nil {\n\t\treturn nil, types.ErrNotFound\n\t}\n\n\treturn NewAddressFromString(addr, string(bytes))\n}\n\nfunc (c *Cache) readFromCacheDB(addr string) (*Address, error) {\n\tresult := Address{}\n\terr := c.db.Select(&result).\n\t\tWhere(\"IP = ?\", addr).\n\t\tDo()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &result, nil\n}\n\nfunc (c *Cache) Put(addr string, loc *Address) error {\n\tif c.config.Geo.IPCacheType == types.CacheTypeDB {\n\t\treturn c.putToCacheDB(loc)\n\t}\n\n\treturn c.putToCacheFile(addr, loc)\n}\n\nfunc (c *Cache) putToCacheDB(loc *Address) error {\n\terr := c.db.Insert(loc).Do()\n\t// it should work like this:\n\t//\n\t//   target := dberror.UniqueConstraint{}\n\t//   if errors.As(err, &target) {\n\t//\n\t// See: https://github.com/samonzeweb/godb/pull/23\n\t//\n\t// But for some reason it does not work,\n\t// so the dirty hack is used:\n\tif strings.Contains(fmt.Sprint(err), \"UNIQUE constraint failed\") {\n\t\treturn c.db.Update(loc).Do()\n\t}\n\n\treturn err\n}\n\nfunc (c *Cache) putToCacheFile(addr string, loc fmt.Stringer) error {\n\treturn os.WriteFile(c.cacheFile(addr), []byte(loc.String()), 0o600)\n}\n\n// cacheFile returns path to the cache entry for addr.\nfunc (c *Cache) cacheFile(addr string) string {\n\treturn path.Join(c.config.Geo.IPCache, addr)\n}\n\n// NewAddressFromString parses the location cache entry s,\n// and return location, or error, if the cache entry is invalid.\nfunc NewAddressFromString(addr, s string) (*Address, error) {\n\tvar (\n\t\tlat  float64 = -1000\n\t\tlong float64 = -1000\n\t\terr  error\n\t)\n\n\tparts := strings.Split(s, \";\")\n\tif len(parts) < 4 {\n\t\treturn nil, types.ErrInvalidCacheEntry\n\t}\n\n\tif len(parts) >= 6 {\n\t\tlat, err = strconv.ParseFloat(parts[4], 64)\n\t\tif err != nil {\n\t\t\treturn nil, types.ErrInvalidCacheEntry\n\t\t}\n\n\t\tlong, err = strconv.ParseFloat(parts[5], 64)\n\t\tif err != nil {\n\t\t\treturn nil, types.ErrInvalidCacheEntry\n\t\t}\n\t}\n\n\treturn &Address{\n\t\tIP:          addr,\n\t\tCountryCode: parts[0],\n\t\tCountry:     parts[1],\n\t\tRegion:      parts[2],\n\t\tCity:        parts[3],\n\t\tLatitude:    lat,\n\t\tLongitude:   long,\n\t}, nil\n}\n\n// Response provides routing interface to the geo cache.\n//\n// Temporary workaround to switch IP addresses handling to the Go server.\n// Handles two queries:\n//\n// - /:geo-ip-put?ip=IP&value=VALUE\n// - /:geo-ip-get?ip=IP\n//\n//nolint:cyclop\nfunc (c *Cache) Response(r *http.Request) *routing.Cadre {\n\tvar (\n\t\trespERR = &routing.Cadre{Body: []byte(\"ERR\")}\n\t\trespOK  = &routing.Cadre{Body: []byte(\"OK\")}\n\t)\n\n\tif ip := util.ReadUserIP(r); ip != \"127.0.0.1\" {\n\t\tlog.Printf(\"geoIP access from %s rejected\\n\", ip)\n\n\t\treturn nil\n\t}\n\n\tif r.URL.Path == \"/:geo-ip-put\" {\n\t\tip := r.URL.Query().Get(\"ip\")\n\t\tvalue := r.URL.Query().Get(\"value\")\n\t\tif !validIP4(ip) || value == \"\" {\n\t\t\tlog.Printf(\"invalid geoIP put query: ip='%s' value='%s'\\n\", ip, value)\n\n\t\t\treturn respERR\n\t\t}\n\n\t\tlocation, err := NewAddressFromString(ip, value)\n\t\tif err != nil {\n\t\t\treturn respERR\n\t\t}\n\n\t\terr = c.Put(ip, location)\n\t\tif err != nil {\n\t\t\treturn respERR\n\t\t}\n\n\t\treturn respOK\n\t}\n\tif r.URL.Path == \"/:geo-ip-get\" {\n\t\tip := r.URL.Query().Get(\"ip\")\n\t\tif !validIP4(ip) {\n\t\t\treturn respERR\n\t\t}\n\n\t\tresult, err := c.Read(ip)\n\t\tif result == nil || err != nil {\n\t\t\treturn respERR\n\t\t}\n\n\t\treturn &routing.Cadre{Body: []byte(result.String())}\n\t}\n\n\treturn nil\n}\n\nfunc validIP4(ipAddress string) bool {\n\tre := regexp.MustCompile(\n\t\t`^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$`)\n\n\treturn re.MatchString(strings.Trim(ipAddress, \" \"))\n}\n"
  },
  {
    "path": "internal/geo/ip/ip_test.go",
    "content": "package ip_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n\n\t. \"github.com/chubin/wttr.in/internal/geo/ip\"\n\t\"github.com/chubin/wttr.in/internal/types\"\n)\n\n//nolint:funlen\nfunc TestParseCacheEntry(t *testing.T) {\n\tt.Parallel()\n\ttests := []struct {\n\t\taddr     string\n\t\tinput    string\n\t\texpected Address\n\t\terr      error\n\t}{\n\t\t{\n\t\t\t\"1.2.3.4\",\n\t\t\t\"DE;Germany;Free and Hanseatic City of Hamburg;Hamburg;53.5736;9.9782\",\n\t\t\tAddress{\n\t\t\t\tIP:          \"1.2.3.4\",\n\t\t\t\tCountryCode: \"DE\",\n\t\t\t\tCountry:     \"Germany\",\n\t\t\t\tRegion:      \"Free and Hanseatic City of Hamburg\",\n\t\t\t\tCity:        \"Hamburg\",\n\t\t\t\tLatitude:    53.5736,\n\t\t\t\tLongitude:   9.9782,\n\t\t\t},\n\t\t\tnil,\n\t\t},\n\n\t\t{\n\t\t\t\"1.2.3.4\",\n\t\t\t\"ES;Spain;Madrid, Comunidad de;Madrid;40.4165;-3.70256;28223;Orange Espagne SA;orange.es\",\n\t\t\tAddress{\n\t\t\t\tIP:          \"1.2.3.4\",\n\t\t\t\tCountryCode: \"ES\",\n\t\t\t\tCountry:     \"Spain\",\n\t\t\t\tRegion:      \"Madrid, Comunidad de\",\n\t\t\t\tCity:        \"Madrid\",\n\t\t\t\tLatitude:    40.4165,\n\t\t\t\tLongitude:   -3.70256,\n\t\t\t},\n\t\t\tnil,\n\t\t},\n\n\t\t{\n\t\t\t\"1.2.3.4\",\n\t\t\t\"US;United States of America;California;Mountain View\",\n\t\t\tAddress{\n\t\t\t\tIP:          \"1.2.3.4\",\n\t\t\t\tCountryCode: \"US\",\n\t\t\t\tCountry:     \"United States of America\",\n\t\t\t\tRegion:      \"California\",\n\t\t\t\tCity:        \"Mountain View\",\n\t\t\t\tLatitude:    -1000,\n\t\t\t\tLongitude:   -1000,\n\t\t\t},\n\t\t\tnil,\n\t\t},\n\n\t\t// Invalid entries\n\t\t{\n\t\t\t\"1.2.3.4\",\n\t\t\t\"DE;Germany;Free and Hanseatic City of Hamburg;Hamburg;53.5736;XXX\",\n\t\t\tAddress{},\n\t\t\ttypes.ErrInvalidCacheEntry,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tresult, err := NewAddressFromString(tt.addr, tt.input)\n\t\tif tt.err == nil {\n\t\t\trequire.NoError(t, err)\n\t\t\trequire.Equal(t, *result, tt.expected)\n\t\t} else {\n\t\t\trequire.ErrorIs(t, err, tt.err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/geo/location/cache.go",
    "content": "package location\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/samonzeweb/godb\"\n\t\"github.com/samonzeweb/godb/adapters/sqlite\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/zsefvlol/timezonemapper\"\n\n\t\"github.com/chubin/wttr.in/internal/config\"\n\t\"github.com/chubin/wttr.in/internal/types\"\n)\n\n// Cache is an implemenation of DB/file-based cache.\n//\n// At the moment, it is an implementation for the location cache,\n// but it should be generalized to cache everything.\ntype Cache struct {\n\tconfig        *config.Config\n\tdb            *godb.DB\n\tsearcher      *Searcher\n\tindexField    string\n\tfilesCacheDir string\n}\n\n// NewCache returns new cache reader for the specified config.\nfunc NewCache(config *config.Config) (*Cache, error) {\n\tvar (\n\t\tdb  *godb.DB\n\t\terr error\n\t)\n\n\tif config.Geo.LocationCacheType == types.CacheTypeDB {\n\t\tlog.Debugln(\"using db for location cache\")\n\t\tdb, err = godb.Open(sqlite.Adapter, config.Geo.LocationCacheDB)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tlog.Debugln(\"db file:\", config.Geo.LocationCacheDB)\n\n\t\t// Needed for \"upsert\" implementation in Put()\n\t\tdb.UseErrorParser()\n\t}\n\n\treturn &Cache{\n\t\tconfig:        config,\n\t\tdb:            db,\n\t\tindexField:    \"name\",\n\t\tfilesCacheDir: config.Geo.LocationCache,\n\t\tsearcher:      NewSearcher(config),\n\t}, nil\n}\n\n// Resolve returns location information for specified location.\n// If the information is found in the cache, it is returned.\n// If it is not found, the external service is queried,\n// and the result is stored in the cache.\nfunc (c *Cache) Resolve(location string) (*Location, error) {\n\tlocation = normalizeLocationName(location)\n\n\tloc, err := c.Read(location)\n\tif !errors.Is(err, types.ErrNotFound) {\n\t\treturn loc, err\n\t}\n\n\tlog.Debugln(\"geo/location: not found in cache:\", location)\n\tloc, err = c.searcher.Search(location)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tloc.Name = location\n\tloc.Timezone = latLngToTimezoneString(loc.Lat, loc.Lon)\n\n\terr = c.Put(location, loc)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn loc, nil\n}\n\n// Read returns location information from the cache, if found,\n// or types.ErrNotFound if not found. If the entry is found, but its format\n// is invalid, types.ErrInvalidCacheEntry is returned.\nfunc (c *Cache) Read(addr string) (*Location, error) {\n\tif c.config.Geo.LocationCacheType == types.CacheTypeFiles {\n\t\treturn c.readFromCacheFile(addr)\n\t}\n\n\treturn c.readFromCacheDB(addr)\n}\n\nfunc (c *Cache) readFromCacheFile(name string) (*Location, error) {\n\tvar (\n\t\tfileLoc = struct {\n\t\t\tLatitude  float64 `json:\"latitude\"`\n\t\t\tLongitude float64 `json:\"longitude\"`\n\t\t\tTimezone  string  `json:\"timezone\"`\n\t\t\tAddress   string  `json:\"address\"`\n\t\t}{}\n\t\tlocation Location\n\t)\n\n\tbytes, err := os.ReadFile(c.cacheFile(name))\n\tif err != nil {\n\t\treturn nil, types.ErrNotFound\n\t}\n\terr = json.Unmarshal(bytes, &fileLoc)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// normalize name\n\tname = strings.TrimSpace(\n\t\tstrings.TrimRight(\n\t\t\tstrings.TrimLeft(name, `\"`), `\"`))\n\n\ttimezone := fileLoc.Timezone\n\tif timezone == \"\" {\n\t\ttimezone = timezonemapper.LatLngToTimezoneString(fileLoc.Latitude, fileLoc.Longitude)\n\t}\n\n\tlocation = Location{\n\t\tName:     name,\n\t\tLat:      fmt.Sprint(fileLoc.Latitude),\n\t\tLon:      fmt.Sprint(fileLoc.Longitude),\n\t\tTimezone: timezone,\n\t\tFullname: fileLoc.Address,\n\t}\n\n\treturn &location, nil\n}\n\nfunc (c *Cache) readFromCacheDB(addr string) (*Location, error) {\n\tresult := Location{}\n\terr := c.db.Select(&result).\n\t\tWhere(c.indexField+\" = ?\", addr).\n\t\tDo()\n\n\tif strings.Contains(fmt.Sprint(err), \"no rows in result set\") {\n\t\treturn nil, types.ErrNotFound\n\t}\n\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"readFromCacheDB: %w\", err)\n\t}\n\n\treturn &result, nil\n}\n\nfunc (c *Cache) Put(addr string, loc *Location) error {\n\tlog.Infoln(\"geo/location: storing in cache:\", loc)\n\tif c.config.Geo.IPCacheType == types.CacheTypeDB {\n\t\treturn c.putToCacheDB(loc)\n\t}\n\n\treturn c.putToCacheFile(addr, loc)\n}\n\nfunc (c *Cache) putToCacheDB(loc *Location) error {\n\terr := c.db.Insert(loc).Do()\n\tif strings.Contains(fmt.Sprint(err), \"UNIQUE constraint failed\") {\n\t\treturn c.db.Update(loc).Do()\n\t}\n\n\treturn err\n}\n\nfunc (c *Cache) putToCacheFile(addr string, loc fmt.Stringer) error {\n\treturn os.WriteFile(c.cacheFile(addr), []byte(loc.String()), 0o600)\n}\n\n// cacheFile returns path to the cache entry for addr.\nfunc (c *Cache) cacheFile(item string) string {\n\treturn path.Join(c.filesCacheDir, item)\n}\n\n// normalizeLocationName converts name into the standard location form\n// with the following steps:\n// - remove excessive spaces,\n// - remove quotes,\n// - convert to lover case.\nfunc normalizeLocationName(name string) string {\n\tname = strings.ReplaceAll(name, `\"`, \" \")\n\tname = strings.ReplaceAll(name, `'`, \" \")\n\tname = strings.TrimSpace(name)\n\tname = strings.Join(strings.Fields(name), \" \")\n\n\treturn strings.ToLower(name)\n}\n\n// latLngToTimezoneString returns timezone for lat, lon,\n// or an empty string if they are invalid.\nfunc latLngToTimezoneString(lat, lon string) string {\n\tlatFloat, err := strconv.ParseFloat(lat, 64)\n\tif err != nil {\n\t\tlog.Errorln(\"geoloc: latLngToTimezoneString:\", err)\n\n\t\treturn \"\"\n\t}\n\tlonFloat, err := strconv.ParseFloat(lon, 64)\n\tif err != nil {\n\t\tlog.Errorln(\"geoloc: latLngToTimezoneString:\", err)\n\n\t\treturn \"\"\n\t}\n\n\treturn timezonemapper.LatLngToTimezoneString(latFloat, lonFloat)\n}\n"
  },
  {
    "path": "internal/geo/location/convert.go",
    "content": "package location\n\nimport (\n\t\"database/sql\"\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/samonzeweb/godb\"\n\t\"github.com/samonzeweb/godb/adapters/sqlite\"\n)\n\n// ConvertCache converts files-based cache into the DB-based cache.\n// If reset is true, the DB cache is created from scratch.\n//\n//nolint:funlen,cyclop\nfunc (c *Cache) ConvertCache(reset bool) error {\n\tvar (\n\t\tdbfile     = c.config.Geo.LocationCacheDB\n\t\ttableName  = \"Location\"\n\t\tcacheFiles = c.filesCacheDir\n\t\tknown      = map[string]bool{}\n\t)\n\n\tif reset {\n\t\terr := removeDBIfExists(dbfile)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tdb, err := godb.Open(sqlite.Adapter, dbfile)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif reset {\n\t\terr = createTable(db, tableName)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tlog.Println(\"listing cache entries...\")\n\tfiles, err := filepath.Glob(filepath.Join(cacheFiles, \"*\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlog.Printf(\"going to convert %d entries\\n\", len(files))\n\n\tblock := []Location{}\n\tfor i, file := range files {\n\t\tip := filepath.Base(file)\n\t\tloc, err := c.Read(ip)\n\t\tif err != nil {\n\t\t\tlog.Println(\"invalid entry for\", ip)\n\n\t\t\tcontinue\n\t\t}\n\n\t\t// Skip too long location names.\n\t\tif len(loc.Name) > 25 {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Skip duplicates.\n\t\tif known[loc.Name] {\n\t\t\tlog.Println(\"skipping\", loc.Name)\n\n\t\t\tcontinue\n\t\t}\n\n\t\tsingleLocation := Location{}\n\t\terr = db.Select(&singleLocation).\n\t\t\tWhere(\"name = ?\", loc.Name).\n\t\t\tDo()\n\t\tif !errors.Is(err, sql.ErrNoRows) {\n\t\t\tlog.Println(\"found in db:\", loc.Name)\n\n\t\t\tcontinue\n\t\t}\n\n\t\tknown[loc.Name] = true\n\n\t\t// Skip some invalid names.\n\t\tif strings.Contains(loc.Name, \"\\n\") {\n\t\t\tcontinue\n\t\t}\n\n\t\tblock = append(block, *loc)\n\t\tif i%1000 != 0 || i == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tlog.Println(\"going to insert new entries\")\n\t\terr = db.BulkInsert(&block).Do()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tblock = []Location{}\n\t\tlog.Println(\"converted\", i+1, \"entries\")\n\t}\n\n\t// inserting the rest.\n\terr = db.BulkInsert(&block).Do()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlog.Println(\"converted\", len(files), \"entries\")\n\n\treturn nil\n}\n\nfunc createTable(db *godb.DB, tableName string) error {\n\tcreateTable := fmt.Sprintf(\n\t\t`create table %s (\n\t    name           text not null primary key,\n        displayName    text not null,\n        lat            text not null,\n        lon            text not null,\n\t\ttimezone       text not null);\n\t`, tableName)\n\n\t_, err := db.CurrentDB().Exec(createTable)\n\n\treturn err\n}\n\nfunc removeDBIfExists(filename string) error {\n\t_, err := os.Stat(filename)\n\tif err != nil {\n\t\tif !os.IsNotExist(err) {\n\t\t\treturn err\n\t\t}\n\t\t// no db file\n\t\treturn nil\n\t}\n\n\treturn os.Remove(filename)\n}\n"
  },
  {
    "path": "internal/geo/location/location.go",
    "content": "package location\n\nimport (\n\t\"encoding/json\"\n\t\"log\"\n)\n\ntype Location struct {\n\tName     string `db:\"name,key\" json:\"name\"`\n\tLat      string `db:\"lat\" json:\"latitude\"`\n\tLon      string `db:\"lon\" json:\"longitude\"`\n\tTimezone string `db:\"timezone\" json:\"timezone\"`\n\tFullname string `db:\"displayName\" json:\"address\"`\n}\n\n// String returns string representation of location.\nfunc (l *Location) String() string {\n\tbytes, err := json.Marshal(l)\n\tif err != nil {\n\t\t// should never happen\n\t\tlog.Fatalln(err)\n\t}\n\n\treturn string(bytes)\n}\n"
  },
  {
    "path": "internal/geo/location/nominatim.go",
    "content": "package location\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\n\t\"github.com/chubin/wttr.in/internal/types\"\n\tlog \"github.com/sirupsen/logrus\"\n)\n\ntype Nominatim struct {\n\tname  string\n\turl   string\n\ttoken string\n\ttyp   string\n}\n\ntype locationQuerier interface {\n\tQuery(*Nominatim, string) (*Location, error)\n}\n\nfunc NewNominatim(name, typ, url, token string) *Nominatim {\n\treturn &Nominatim{\n\t\tname:  name,\n\t\turl:   url,\n\t\ttoken: token,\n\t\ttyp:   typ,\n\t}\n}\n\nfunc (n *Nominatim) Query(location string) (*Location, error) {\n\tvar data locationQuerier\n\n\tswitch n.typ {\n\tcase \"iq\":\n\t\tdata = &locationIQ{}\n\tcase \"opencage\":\n\t\tdata = &locationOpenCage{}\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"%s: %w\", n.name, types.ErrUnknownLocationService)\n\t}\n\n\treturn data.Query(n, location)\n}\n\nfunc makeQuery(url string, result interface{}) error {\n\tvar errResponse struct {\n\t\tError string\n\t}\n\n\tlog.Debugln(\"nominatim:\", url)\n\tresp, err := http.Get(url)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\n\tbody, err := ioutil.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = json.Unmarshal(body, &errResponse)\n\tif err == nil && errResponse.Error != \"\" {\n\t\treturn fmt.Errorf(\"%w: %s\", types.ErrUpstream, errResponse.Error)\n\t}\n\n\tlog.Debugln(\"nominatim: response: \", string(body))\n\terr = json.Unmarshal(body, &result)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/geo/location/nominatim_locationiq.go",
    "content": "package location\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\n\t\"github.com/chubin/wttr.in/internal/types\"\n)\n\ntype locationIQ []struct {\n\tName string `db:\"name,key\"`\n\tLat  string `db:\"lat\"`\n\tLon  string `db:\"lon\"`\n\t//nolint:tagliatelle\n\tFullname string `db:\"displayName\" json:\"display_name\"`\n}\n\nfunc (data *locationIQ) Query(n *Nominatim, location string) (*Location, error) {\n\turl := fmt.Sprintf(\n\t\t\"%s?q=%s&format=json&language=native&limit=1&key=%s\",\n\t\tn.url, url.QueryEscape(location), n.token)\n\n\terr := makeQuery(url, data)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%s: %w\", n.name, err)\n\t}\n\n\tif len(*data) != 1 {\n\t\treturn nil, fmt.Errorf(\"%w: %s: invalid response\", types.ErrUpstream, n.name)\n\t}\n\n\tnl := &(*data)[0]\n\n\treturn &Location{\n\t\tLat:      nl.Lat,\n\t\tLon:      nl.Lon,\n\t\tFullname: nl.Fullname,\n\t}, nil\n}\n"
  },
  {
    "path": "internal/geo/location/nominatim_opencage.go",
    "content": "package location\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\n\t\"github.com/chubin/wttr.in/internal/types\"\n)\n\ntype locationOpenCage struct {\n\tResults []struct {\n\t\tName     string `db:\"name,key\"`\n\t\tGeometry struct {\n\t\t\tLat float64 `db:\"lat\"`\n\t\t\tLng float64 `db:\"lng\"`\n\t\t}\n\t\tFullname string `json:\"formatted\"`\n\t} `json:\"results\"`\n}\n\nfunc (data *locationOpenCage) Query(n *Nominatim, location string) (*Location, error) {\n\turl := fmt.Sprintf(\n\t\t\"%s?q=%s&language=native&limit=1&key=%s\",\n\t\tn.url, url.QueryEscape(location), n.token)\n\n\terr := makeQuery(url, data)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%s: %w\", n.name, err)\n\t}\n\n\tif len(data.Results) != 1 {\n\t\treturn nil, fmt.Errorf(\"%w: %s: invalid response\", types.ErrUpstream, n.name)\n\t}\n\n\tnl := data.Results[0]\n\n\treturn &Location{\n\t\tLat:      fmt.Sprint(nl.Geometry.Lat),\n\t\tLon:      fmt.Sprint(nl.Geometry.Lng),\n\t\tFullname: nl.Fullname,\n\t}, nil\n}\n"
  },
  {
    "path": "internal/geo/location/response.go",
    "content": "package location\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/chubin/wttr.in/internal/routing\"\n)\n\n// Response provides routing interface to the geo cache.\nfunc (c *Cache) Response(r *http.Request) *routing.Cadre {\n\tvar (\n\t\tlocationName = r.URL.Query().Get(\"location\")\n\t\tloc          *Location\n\t\tbytes        []byte\n\t\terr          error\n\t)\n\n\tif locationName == \"\" {\n\t\treturn errorResponse(\"location is not specified\")\n\t}\n\n\tif strings.Contains(locationName, \".html\") || strings.Contains(locationName, \".txt\") {\n\t\treturn errorResponse(\"invalid location\")\n\t}\n\n\tloc, err = c.Resolve(locationName)\n\tif err != nil {\n\t\tlog.Println(\"geo/location error:\", locationName, r.RemoteAddr)\n\n\t\treturn errorResponse(fmt.Sprint(err))\n\t}\n\n\tbytes, err = json.Marshal(loc)\n\tif err != nil {\n\t\treturn errorResponse(fmt.Sprint(err))\n\t}\n\n\treturn &routing.Cadre{Body: bytes}\n}\n\nfunc errorResponse(s string) *routing.Cadre {\n\treturn &routing.Cadre{Body: []byte(\n\t\tfmt.Sprintf(`{\"error\": %q}`, s),\n\t)}\n}\n"
  },
  {
    "path": "internal/geo/location/search.go",
    "content": "package location\n\nimport \"github.com/chubin/wttr.in/internal/config\"\n\ntype Provider interface {\n\tQuery(location string) (*Location, error)\n}\n\ntype Searcher struct {\n\tproviders []Provider\n}\n\n// NewSearcher returns a new Searcher for the specified config.\nfunc NewSearcher(config *config.Config) *Searcher {\n\tproviders := []Provider{}\n\tfor _, p := range config.Geo.Nominatim {\n\t\tproviders = append(providers, NewNominatim(p.Name, p.Type, p.URL, p.Token))\n\t}\n\n\treturn &Searcher{\n\t\tproviders: providers,\n\t}\n}\n\n// Search makes queries through all known providers,\n// and returns response, as soon as it is not nil.\n// If all responses were nil, the last response is returned.\nfunc (s *Searcher) Search(location string) (*Location, error) {\n\tvar (\n\t\terr    error\n\t\tresult *Location\n\t)\n\n\tfor _, p := range s.providers {\n\t\tresult, err = p.Query(location)\n\t\tif result != nil && err == nil {\n\t\t\treturn result, nil\n\t\t}\n\t}\n\n\treturn result, err\n}\n"
  },
  {
    "path": "internal/logging/logging.go",
    "content": "package logging\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/chubin/wttr.in/internal/util\"\n)\n\n// Logging request.\n//\n\n// RequestLogger logs all incoming HTTP requests.\ntype RequestLogger struct {\n\tbuf      map[logEntry]int\n\tfilename string\n\tm        sync.Mutex\n\n\tperiod    time.Duration\n\tlastFlush time.Time\n}\n\ntype logEntry struct {\n\tProto     string\n\tIP        string\n\tURI       string\n\tUserAgent string\n}\n\n// NewRequestLogger returns a new RequestLogger for the specified log file.\n// Flush logging entries after period of time.\n//\n// If filename is empty, no log will be written, and all logging entries\n// will be silently dropped.\nfunc NewRequestLogger(filename string, period time.Duration) *RequestLogger {\n\treturn &RequestLogger{\n\t\tbuf:      map[logEntry]int{},\n\t\tfilename: filename,\n\t\tm:        sync.Mutex{},\n\t\tperiod:   period,\n\t}\n}\n\n// Log logs information about a HTTP request.\nfunc (rl *RequestLogger) Log(r *http.Request) error {\n\tle := logEntry{\n\t\tProto:     \"http\",\n\t\tIP:        util.ReadUserIP(r),\n\t\tURI:       r.RequestURI,\n\t\tUserAgent: r.Header.Get(\"User-Agent\"),\n\t}\n\tif r.TLS != nil {\n\t\tle.Proto = \"https\"\n\t}\n\n\t// Do not log 127.0.0.1 connections\n\tif le.IP == \"127.0.0.1\" {\n\t\treturn nil\n\t}\n\n\trl.m.Lock()\n\trl.buf[le]++\n\trl.m.Unlock()\n\n\tif time.Since(rl.lastFlush) > rl.period {\n\t\treturn rl.flush()\n\t}\n\n\treturn nil\n}\n\n// flush stores log data to disk, and flushes the buffer.\nfunc (rl *RequestLogger) flush() error {\n\trl.m.Lock()\n\tdefer rl.m.Unlock()\n\n\t// It is possible, that while waiting the mutex,\n\t// the buffer was already flushed.\n\tif time.Since(rl.lastFlush) <= rl.period {\n\t\treturn nil\n\t}\n\n\tif rl.filename != \"\" {\n\t\t// Generate log output.\n\t\toutput := \"\"\n\t\tfor k, hitsNumber := range rl.buf {\n\t\t\toutput += fmt.Sprintf(\"%s %3d %s\\n\", time.Now().Format(time.RFC3339), hitsNumber, k.String())\n\t\t}\n\n\t\t// Open log file.\n\t\t//nolint:nosnakecase\n\t\tf, err := os.OpenFile(rl.filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o600)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer f.Close()\n\n\t\t// Save output to log file.\n\t\t_, err = f.Write([]byte(output))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Flush buffer.\n\trl.buf = map[logEntry]int{}\n\trl.lastFlush = time.Now()\n\n\treturn nil\n}\n\n// String returns string representation of logEntry.\nfunc (e *logEntry) String() string {\n\treturn fmt.Sprintf(\n\t\t\"%s %s %s %s\",\n\t\te.Proto,\n\t\te.IP,\n\t\te.URI,\n\t\te.UserAgent,\n\t)\n}\n"
  },
  {
    "path": "internal/logging/suppress.go",
    "content": "package logging\n\nimport (\n\t\"os\"\n\t\"strings\"\n\t\"sync\"\n)\n\n// LogSuppressor provides io.Writer interface for logging\n// with lines suppression. For usage with log.Logger.\ntype LogSuppressor struct {\n\tfilename   string\n\tsuppress   []string\n\tlinePrefix string\n\n\tlogFile *os.File\n\tm       sync.Mutex\n}\n\n// NewLogSuppressor creates a new LogSuppressor for specified\n// filename and lines to be suppressed.\n//\n// If filename is empty, log entries will be printed to stderr.\nfunc NewLogSuppressor(filename string, suppress []string, linePrefix string) *LogSuppressor {\n\treturn &LogSuppressor{\n\t\tfilename:   filename,\n\t\tsuppress:   suppress,\n\t\tlinePrefix: linePrefix,\n\t}\n}\n\n// Open opens log file.\nfunc (ls *LogSuppressor) Open() error {\n\tvar err error\n\n\tif ls.filename == \"\" {\n\t\treturn nil\n\t}\n\n\t//nolint:nosnakecase\n\tls.logFile, err = os.OpenFile(ls.filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o600)\n\n\treturn err\n}\n\n// Close closes log file.\nfunc (ls *LogSuppressor) Close() error {\n\tif ls.filename == \"\" {\n\t\treturn nil\n\t}\n\n\treturn ls.logFile.Close()\n}\n\n// Write writes p to log, and returns number f bytes written.\n// Implements io.Writer interface.\nfunc (ls *LogSuppressor) Write(p []byte) (int, error) {\n\tvar output string\n\n\tif ls.filename == \"\" {\n\t\treturn os.Stdin.Write(p)\n\t}\n\n\tls.m.Lock()\n\tdefer ls.m.Unlock()\n\n\tlines := strings.Split(string(p), ls.linePrefix)\n\tfor _, line := range lines {\n\t\tif (func(line string) bool {\n\t\t\tfor _, suppress := range ls.suppress {\n\t\t\t\tif strings.Contains(line, suppress) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false\n\t\t})(line) {\n\t\t\tcontinue\n\t\t}\n\t\toutput += line\n\t}\n\n\treturn ls.logFile.Write([]byte(output))\n}\n"
  },
  {
    "path": "internal/options/options.go",
    "content": "package options\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\n\t\"gopkg.in/yaml.v3\"\n)\n\n// WttrInOptions represents the configuration for wttr.in query options and format specifiers.\ntype WttrInOptions struct {\n\tQueryOptions     []QueryOption     `yaml:\"query_options\"`\n\tFormatSpecifiers []FormatSpecifier `yaml:\"format_specifiers\"`\n}\n\n// QueryOption defines a single query option for wttr.in, such as `lang` or `format`.\ntype QueryOption struct {\n\t// Name is the long name of the option (e.g., \"lang\", \"current_only\").\n\tName string `yaml:\"name\"`\n\n\t// Short is the short name of the option (e.g., \"m\"), omitted if not present.\n\tShort string `yaml:\"short,omitempty\"`\n\n\t// Description of the option's purpose (e.g., \"Specify output language\").\n\tDescription string `yaml:\"description\"`\n\n\t// Type is the data type of the option (e.g., \"boolean\", \"string\", \"integer\").\n\tType string `yaml:\"type\"`\n\n\t// ValuesMap is the map of possible values to their descriptions (e.g., for `lang`, `format`).\n\tValuesMap map[string]string `yaml:\"values_map,omitempty\"`\n\n\t// Values is the list of supported values (e.g., [\"true\", \"false\"] for booleans).\n\tValues []string `yaml:\"values,omitempty\"`\n\n\t// Range is the numeric range for integer options (e.g., min and max for `transparency`).\n\tRange *Range `yaml:\"range,omitempty\"`\n\n\t// Default is the default value of the option (e.g., \"en\" for `lang`, null for `background`).\n\tDefault interface{} `yaml:\"default\"`\n\n\t// Validate contains validation conditions in function call style (e.g., \"length 6\" for `background`).\n\tValidate []string `yaml:\"validate,omitempty\"`\n\n\t// Active indicates if the option is implemented (true) or proposed (false).\n\tActive bool `yaml:\"active\"`\n\n\t// Note includes additional notes or caveats (e.g., \"Proposed but not officially supported\").\n\tNote string `yaml:\"note,omitempty\"`\n}\n\n// Range defines a numeric range for integer-type query options.\ntype Range struct {\n\t// Min is the minimum value of the range (e.g., 0 for `transparency`).\n\tMin int `yaml:\"min\"`\n\n\t// Max is the maximum value of the range, nullable for unbounded (e.g., null for `date`).\n\tMax *int `yaml:\"max\"`\n}\n\n// FormatSpecifier defines a format specifier for the `format` option (e.g., %c, %t).\ntype FormatSpecifier struct {\n\t// Specifier is the format specifier (e.g., \"%c\").\n\tSpecifier string `yaml:\"specifier\"`\n\n\t// Description provides the output description of the specifier (e.g., \"Weather condition\").\n\tDescription string `yaml:\"description\"`\n\n\t// Active indicates if the specifier is implemented (true) or proposed (false).\n\tActive bool `yaml:\"active\"`\n\n\t// Note contains additional notes, if any (e.g., \"Proposed in issue #585\").\n\tNote string `yaml:\"note,omitempty\"`\n}\n\n// NewFromFile reads a QueryOption from a YAML file and returns a pointer to it.\nfunc NewFromFile(filename string) (*WttrInOptions, error) {\n\t// Read the YAML file\n\tdata, err := ioutil.ReadFile(filename)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read file: %w\", err)\n\t}\n\n\t// Unmarshal the YAML content into a QueryOption struct\n\tvar option WttrInOptions\n\tif err := yaml.Unmarshal(data, &option); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to unmarshal YAML: %w\", err)\n\t}\n\n\treturn &option, nil\n}\n"
  },
  {
    "path": "internal/options/parse.go",
    "content": "package options\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/url\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// Errors for query parsing and validation\nvar (\n\tErrInvalidQueryString      = errors.New(\"ERR001: failed to parse query string\")\n\tErrMultipleValues          = errors.New(\"ERR002: option has multiple values\")\n\tErrUnknownOption           = errors.New(\"ERR003: unknown option\")\n\tErrOptionNotImplemented    = errors.New(\"ERR004: option is not implemented\")\n\tErrBooleanValueRequired    = errors.New(\"ERR005: option requires boolean value (true/false)\")\n\tErrInvalidBooleanValue     = errors.New(\"ERR006: invalid boolean value\")\n\tErrValueRequired           = errors.New(\"ERR007: option requires a value\")\n\tErrInvalidStringValue      = errors.New(\"ERR008: invalid string value\")\n\tErrInvalidValidationRule   = errors.New(\"ERR009: invalid validation rule\")\n\tErrInvalidLengthRule       = errors.New(\"ERR010: invalid length rule\")\n\tErrInvalidLength           = errors.New(\"ERR011: invalid length\")\n\tErrInvalidRegexpRule       = errors.New(\"ERR012: invalid regexp rule\")\n\tErrInvalidRegexp           = errors.New(\"ERR013: invalid regexp match\")\n\tErrUnsupportedRule         = errors.New(\"ERR014: unsupported validation rule\")\n\tErrInvalidInteger          = errors.New(\"ERR015: option requires an integer\")\n\tErrBelowMinimum            = errors.New(\"ERR016: value below minimum\")\n\tErrAboveMaximum            = errors.New(\"ERR017: value exceeds maximum\")\n\tErrUnsupportedType         = errors.New(\"ERR018: unsupported option type\")\n\tErrInactiveFormatSpecifier = errors.New(\"ERR019: format specifier is not implemented\")\n)\n\n// ParseQueryString parses a wttr.in query string into a map of option names to values.\n// It validates option names, types, content, and values based on the provided WttrInOptions.\n// Returns the parsed map or an error if parsing or validation fails.\nfunc ParseQueryString(query string, config *WttrInOptions) (map[string]string, error) {\n\t// Initialize result map and lookup tables\n\tresult := make(map[string]string)\n\tshortToName, nameToOption := buildOptionLookups(config.QueryOptions)\n\n\t// Parse query string\n\tquery = strings.ReplaceAll(\n\t\tstrings.ReplaceAll(query, \"%25\", \"%\"),\n\t\t\"%\", \"%25\")\n\n\tparsed, err := url.ParseQuery(query)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: %v\", ErrInvalidQueryString, err)\n\t}\n\n\t// Process query parameters\n\tfor key, values := range parsed {\n\t\tif len(values) == 0 || (len(values) == 1 && values[0] == \"\") {\n\t\t\tif err := handleFlagOption(key, shortToName, nameToOption, result); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif len(values) > 1 {\n\t\t\treturn nil, fmt.Errorf(\"%w: %s: %v\", ErrMultipleValues, key, values)\n\t\t}\n\t\tif err := handleValueOption(key, values[0], shortToName, nameToOption, result); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// Validate format specifiers if format=custom\n\tif formatValue, exists := result[\"format\"]; exists && formatValue == \"custom\" {\n\t\tfor _, spec := range config.FormatSpecifiers {\n\t\t\tif !spec.Active {\n\t\t\t\treturn nil, fmt.Errorf(\"%w: %s\", ErrInactiveFormatSpecifier, spec.Specifier)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// buildOptionLookups creates lookup maps for short-to-long names and option details.\nfunc buildOptionLookups(options []QueryOption) (map[string]string, map[string]QueryOption) {\n\tshortToName := make(map[string]string)\n\tnameToOption := make(map[string]QueryOption)\n\tfor _, opt := range options {\n\t\tnameToOption[opt.Name] = opt\n\t\tif opt.Short != \"\" {\n\t\t\tshortToName[opt.Short] = opt.Name\n\t\t}\n\t}\n\treturn shortToName, nameToOption\n}\n\n// handleFlagOption processes flag options (e.g., \"0pq\" or \"m\") without values.\nfunc handleFlagOption(key string, shortToName map[string]string, nameToOption map[string]QueryOption, result map[string]string) error {\n\t// Handle bundled short options (e.g., \"0pq\")\n\tif len(key) > 1 && !strings.Contains(key, \"=\") {\n\t\tfor _, short := range strings.Split(key, \"\") {\n\t\t\tif err := validateAndSetFlag(short, shortToName, nameToOption, result); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\t// Handle single flag\n\treturn validateAndSetFlag(key, shortToName, nameToOption, result)\n}\n\n// validateAndSetFlag validates and sets a single flag option.\nfunc validateAndSetFlag(key string, shortToName map[string]string, nameToOption map[string]QueryOption, result map[string]string) error {\n\tname, exists := shortToName[key]\n\tif !exists {\n\t\tname = key // Try long name\n\t}\n\topt, exists := nameToOption[name]\n\tif !exists {\n\t\treturn fmt.Errorf(\"%w: %s\", ErrUnknownOption, key)\n\t}\n\tif !opt.Active {\n\t\treturn fmt.Errorf(\"%w: %s\", ErrOptionNotImplemented, name)\n\t}\n\tif opt.Type != \"boolean\" {\n\t\treturn fmt.Errorf(\"%w: %s\", ErrValueRequired, key)\n\t}\n\tresult[name] = \"true\"\n\treturn nil\n}\n\n// handleValueOption processes options with values (e.g., \"lang=fr\").\nfunc handleValueOption(key, value string, shortToName map[string]string, nameToOption map[string]QueryOption, result map[string]string) error {\n\t// Resolve option name\n\tname, exists := shortToName[key]\n\tif !exists {\n\t\tname = key // Assume long name\n\t}\n\topt, exists := nameToOption[name]\n\tif !exists {\n\t\treturn fmt.Errorf(\"%w: %s\", ErrUnknownOption, key)\n\t}\n\tif !opt.Active {\n\t\treturn fmt.Errorf(\"%w: %s\", ErrOptionNotImplemented, name)\n\t}\n\n\t// Validate based on type\n\tswitch opt.Type {\n\tcase \"boolean\":\n\t\treturn validateBooleanOption(name, value, opt, result)\n\tcase \"string\":\n\t\treturn validateStringOption(name, value, opt, result)\n\tcase \"integer\":\n\t\treturn validateIntegerOption(name, value, opt, result)\n\tdefault:\n\t\treturn fmt.Errorf(\"%w: %s: %s\", ErrUnsupportedType, name, opt.Type)\n\t}\n}\n\n// validateBooleanOption validates and sets boolean option values.\nfunc validateBooleanOption(name, value string, opt QueryOption, result map[string]string) error {\n\tif value != \"true\" && value != \"false\" {\n\t\treturn fmt.Errorf(\"%w: %s: %s\", ErrBooleanValueRequired, name, value)\n\t}\n\tif len(opt.Values) > 0 {\n\t\tfor _, v := range opt.Values {\n\t\t\tif v == value {\n\t\t\t\tresult[name] = value\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t\treturn fmt.Errorf(\"%w: %s: %s, expected one of %v\", ErrInvalidBooleanValue, name, value, opt.Values)\n\t}\n\tresult[name] = value\n\treturn nil\n}\n\n// validateStringOption validates and sets string option values, including background-specific rules.\nfunc validateStringOption(name, value string, opt QueryOption, result map[string]string) error {\n\tif len(opt.ValuesMap) > 0 {\n\t\tif _, valid := opt.ValuesMap[value]; !valid {\n\t\t\treturn fmt.Errorf(\"%w: %s: %s, expected one of %v\", ErrInvalidStringValue, name, value, getMapKeys(opt.ValuesMap))\n\t\t}\n\t}\n\tif len(opt.Values) > 0 {\n\t\tfor _, v := range opt.Values {\n\t\t\tif v == value {\n\t\t\t\tresult[name] = value\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t\treturn fmt.Errorf(\"%w: %s: %s, expected one of %v\", ErrInvalidStringValue, name, value, opt.Values)\n\t}\n\tif name == \"background\" && len(opt.Validate) > 0 {\n\t\tfor _, rule := range opt.Validate {\n\t\t\tif err := applyValidationRule(name, value, rule); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\tresult[name] = value\n\treturn nil\n}\n\n// applyValidationRule applies a single validation rule (e.g., \"length 6\", \"regexp [0-9a-fA-F]{6}\").\nfunc applyValidationRule(name, value, rule string) error {\n\tparts := strings.SplitN(rule, \" \", 2)\n\tif len(parts) < 2 {\n\t\treturn fmt.Errorf(\"%w: %s: %s\", ErrInvalidValidationRule, name, rule)\n\t}\n\tswitch parts[0] {\n\tcase \"length\":\n\t\tlength, err := strconv.Atoi(parts[1])\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"%w: %s: %s\", ErrInvalidLengthRule, name, rule)\n\t\t}\n\t\tif len(value) != length {\n\t\t\treturn fmt.Errorf(\"%w: %s: %s, expected length %d\", ErrInvalidLength, name, value, length)\n\t\t}\n\tcase \"regexp\":\n\t\tre, err := regexp.Compile(parts[1])\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"%w: %s: %s\", ErrInvalidRegexpRule, name, rule)\n\t\t}\n\t\tif !re.MatchString(value) {\n\t\t\treturn fmt.Errorf(\"%w: %s: %s, expected match for %s\", ErrInvalidRegexp, name, value, parts[1])\n\t\t}\n\tdefault:\n\t\treturn fmt.Errorf(\"%w: %s: %s\", ErrUnsupportedRule, name, rule)\n\t}\n\treturn nil\n}\n\n// validateIntegerOption validates and sets integer option values.\nfunc validateIntegerOption(name, value string, opt QueryOption, result map[string]string) error {\n\tnum, err := strconv.Atoi(value)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%w: %s: %s\", ErrInvalidInteger, name, value)\n\t}\n\tif opt.Range != nil {\n\t\tif num < opt.Range.Min {\n\t\t\treturn fmt.Errorf(\"%w: %s: %d, minimum is %d\", ErrBelowMinimum, name, num, opt.Range.Min)\n\t\t}\n\t\tif opt.Range.Max != nil && num > *opt.Range.Max {\n\t\t\treturn fmt.Errorf(\"%w: %s: %d, maximum is %d\", ErrAboveMaximum, name, num, *opt.Range.Max)\n\t\t}\n\t}\n\tresult[name] = value\n\treturn nil\n}\n\n// getMapKeys returns a sorted slice of keys from a map for error messages.\nfunc getMapKeys(m map[string]string) []string {\n\tkeys := make([]string, 0, len(m))\n\tfor k := range m {\n\t\tkeys = append(keys, k)\n\t}\n\t// Sort for consistent error messages\n\tfor i := 0; i < len(keys)-1; i++ {\n\t\tfor j := i + 1; j < len(keys); j++ {\n\t\t\tif keys[i] > keys[j] {\n\t\t\t\tkeys[i], keys[j] = keys[j], keys[i]\n\t\t\t}\n\t\t}\n\t}\n\treturn keys\n}\n"
  },
  {
    "path": "internal/options/processlog.go",
    "content": "package options\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n)\n\n// ProcessLogFile reads a wttr.in log file, parses queries, and writes invalid entries to an error file.\n// Each log line is expected in the format: \"timestamp request_id protocol ip query user_agent\".\n// Invalid queries and their error messages are written to errorFilePath.\nfunc ProcessLogFile(logFilePath, errorFilePath string, config *WttrInOptions) error {\n\tlogFile, err := openLogFile(logFilePath)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer logFile.Close()\n\n\terrorFile, writer, err := openErrorFile(errorFilePath)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer errorFile.Close()\n\tdefer writer.Flush()\n\n\treturn processLogLines(logFile, writer, config)\n}\n\n// openLogFile opens the log file for reading.\nfunc openLogFile(logFilePath string) (*os.File, error) {\n\tlogFile, err := os.Open(logFilePath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to open log file: %w\", err)\n\t}\n\treturn logFile, nil\n}\n\n// openErrorFile creates and opens the error file for writing.\nfunc openErrorFile(errorFilePath string) (*os.File, *bufio.Writer, error) {\n\terrorFile, err := os.Create(errorFilePath)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to create error file: %w\", err)\n\t}\n\twriter := bufio.NewWriter(errorFile)\n\treturn errorFile, writer, nil\n}\n\n// processLogLines reads and processes each line of the log file.\nfunc processLogLines(logFile *os.File, writer *bufio.Writer, config *WttrInOptions) error {\n\tscanner := bufio.NewScanner(logFile)\n\tlineNumber := 0\n\tfor scanner.Scan() {\n\t\tlineNumber++\n\t\tif err := processLogLine(scanner.Text(), lineNumber, writer, config); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif err := scanner.Err(); err != nil {\n\t\treturn fmt.Errorf(\"failed to read log file: %w\", err)\n\t}\n\treturn nil\n}\n\n// processLogLine processes a single log line and writes errors to the error file.\nfunc processLogLine(line string, lineNumber int, writer *bufio.Writer, config *WttrInOptions) error {\n\tquery, err := extractQueryFromLine(line, lineNumber, writer)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t_, err = ParseQueryString(query, config)\n\tif err != nil {\n\t\t_, writeErr := fmt.Fprintf(writer, \"Line %d: Query: %s, Error: %v\\n\", lineNumber, query, err)\n\t\tif writeErr != nil {\n\t\t\treturn fmt.Errorf(\"failed to write to error file at line %d: %w\", lineNumber, writeErr)\n\t\t}\n\t}\n\treturn nil\n}\n\n// extractQueryFromLine extracts the query from a log line and validates its format.\nfunc extractQueryFromLine(line string, lineNumber int, writer *bufio.Writer) (string, error) {\n\tfields := strings.Fields(line)\n\tif len(fields) < 5 {\n\t\t_, err := fmt.Fprintf(writer, \"Line %d: Invalid log format: %s\\n\", lineNumber, line)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed to write to error file at line %d: %w\", lineNumber, err)\n\t\t}\n\t\treturn \"\", nil\n\t}\n\n\tquery := fields[4]\n\tif strings.Contains(query, \"?\") {\n\t\tparts := strings.SplitN(query, \"?\", 2)\n\t\tif len(parts) == 2 {\n\t\t\treturn parts[1], nil\n\t\t}\n\t\treturn \"\", nil\n\t}\n\treturn \"\", nil\n}\n"
  },
  {
    "path": "internal/processor/j1.go",
    "content": "package processor\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"time\"\n)\n\nfunc getAny(req *http.Request, tr1, tr2, tr3, tr4 *http.Transport) (*ResponseWithHeader, error) {\n\turi := strings.ReplaceAll(req.URL.RequestURI(), \"%\", \"%25\")\n\n\tu, err := url.Parse(uri)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tformat := u.Query().Get(\"format\")\n\n\tif format == \"j1\" {\n\t\treturn getJ1(req, tr1)\n\t} else if format != \"\" {\n\t\treturn getFormat(req, tr2)\n\t}\n\n\t// log.Println(req.URL.Query())\n\t// log.Println()\n\n\tif checkURLForPNG(req) {\n\t\treturn getDefault(req, tr4)\n\t}\n\n\treturn getDefault(req, tr3)\n}\n\nfunc getJ1(req *http.Request, transport *http.Transport) (*ResponseWithHeader, error) {\n\treturn getUpstream(req, transport)\n}\n\nfunc getFormat(req *http.Request, transport *http.Transport) (*ResponseWithHeader, error) {\n\treturn getUpstream(req, transport)\n}\n\nfunc getDefault(req *http.Request, transport *http.Transport) (*ResponseWithHeader, error) {\n\treturn getUpstream(req, transport)\n}\n\nfunc getUpstream(req *http.Request, transport *http.Transport) (*ResponseWithHeader, error) {\n\tclient := &http.Client{\n\t\tTransport: transport,\n\t}\n\n\tqueryURL := fmt.Sprintf(\"http://%s%s\", req.Host, req.RequestURI)\n\n\tproxyReq, err := http.NewRequest(req.Method, queryURL, req.Body)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// proxyReq.Header.Set(\"Host\", req.Host)\n\t// proxyReq.Header.Set(\"X-Forwarded-For\", req.RemoteAddr)\n\n\tfor header, values := range req.Header {\n\t\tfor _, value := range values {\n\t\t\tproxyReq.Header.Add(header, value)\n\t\t}\n\t}\n\n\tif proxyReq.Header.Get(\"X-Forwarded-For\") == \"\" {\n\t\tproxyReq.Header.Set(\"X-Forwarded-For\", ipFromAddr(req.RemoteAddr))\n\t}\n\n\tres, err := client.Do(proxyReq)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer res.Body.Close()\n\n\tbody, err := ioutil.ReadAll(res.Body)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &ResponseWithHeader{\n\t\tInProgress: false,\n\t\tExpires:    time.Now().Add(time.Duration(randInt(1000, 1500)) * time.Second),\n\t\tBody:       body,\n\t\tHeader:     res.Header,\n\t\tStatusCode: res.StatusCode,\n\t}, nil\n}\n\nfunc checkURLForPNG(r *http.Request) bool {\n\turl := r.URL.String()\n\treturn strings.Contains(url, \".png\") && !strings.Contains(url, \"/files/\")\n}\n"
  },
  {
    "path": "internal/processor/peak.go",
    "content": "package processor\n\nimport (\n\t\"log\"\n\t\"net/http\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/robfig/cron\"\n)\n\nfunc (rp *RequestProcessor) startPeakHandling() error {\n\tvar err error\n\n\tc := cron.New()\n\t// cronTime := fmt.Sprintf(\"%d,%d * * * *\", 30-prefetchInterval/60, 60-prefetchInterval/60)\n\terr = c.AddFunc(\n\t\t\"24 * * * *\",\n\t\tfunc() { rp.prefetchPeakRequests(&rp.peakRequest30) },\n\t)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = c.AddFunc(\n\t\t\"54 * * * *\",\n\t\tfunc() { rp.prefetchPeakRequests(&rp.peakRequest60) },\n\t)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tc.Start()\n\n\treturn nil\n}\n\n// registerPeakRequest registers requests coming in the peak time.\n// Such requests can be prefetched afterwards just before the peak time comes.\nfunc (rp *RequestProcessor) savePeakRequest(cacheDigest string, r *http.Request) {\n\tif _, min, _ := time.Now().Clock(); min == 30 {\n\t\trp.peakRequest30.Store(cacheDigest, *r)\n\t} else if min == 0 {\n\t\trp.peakRequest60.Store(cacheDigest, *r)\n\t}\n}\n\nfunc (rp *RequestProcessor) prefetchRequest(r *http.Request) error {\n\t_, err := rp.ProcessRequest(r)\n\n\treturn err\n}\n\nfunc syncMapLen(sm *sync.Map) int {\n\tcount := 0\n\tf := func(key, value interface{}) bool {\n\t\t// Not really certain about this part, don't know for sure\n\t\t// if this is a good check for an entry's existence\n\t\tif key == \"\" {\n\t\t\treturn false\n\t\t}\n\t\tcount++\n\n\t\treturn true\n\t}\n\n\tsm.Range(f)\n\n\treturn count\n}\n\nfunc (rp *RequestProcessor) prefetchPeakRequests(peakRequestMap *sync.Map) {\n\tpeakRequestLen := syncMapLen(peakRequestMap)\n\tif peakRequestLen == 0 {\n\t\treturn\n\t}\n\tlog.Printf(\"PREFETCH: Prefetching %d requests\\n\", peakRequestLen)\n\tsleepBetweenRequests := time.Duration(rp.config.Uplink.PrefetchInterval*1000/peakRequestLen) * time.Millisecond\n\tpeakRequestMap.Range(func(key interface{}, value interface{}) bool {\n\t\treq, ok := value.(http.Request)\n\t\tif !ok {\n\t\t\tlog.Println(\"missing value for:\", key)\n\n\t\t\treturn true\n\t\t}\n\n\t\tgo func(r http.Request) {\n\t\t\terr := rp.prefetchRequest(&r)\n\t\t\tif err != nil {\n\t\t\t\tlog.Println(\"prefetch request:\", err)\n\t\t\t}\n\t\t}(req)\n\t\tpeakRequestMap.Delete(key)\n\t\ttime.Sleep(sleepBetweenRequests)\n\n\t\treturn true\n\t})\n}\n"
  },
  {
    "path": "internal/processor/processor.go",
    "content": "package processor\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"net\"\n\t\"net/http\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\tlru \"github.com/hashicorp/golang-lru\"\n\n\t\"github.com/chubin/wttr.in/internal/config\"\n\tgeoip \"github.com/chubin/wttr.in/internal/geo/ip\"\n\tgeoloc \"github.com/chubin/wttr.in/internal/geo/location\"\n\t\"github.com/chubin/wttr.in/internal/routing\"\n\t\"github.com/chubin/wttr.in/internal/stats\"\n\t\"github.com/chubin/wttr.in/internal/util\"\n)\n\n// plainTextAgents contains signatures of the plain-text agents.\nfunc plainTextAgents() []string {\n\treturn []string{\n\t\t\"curl\",\n\t\t\"httpie\",\n\t\t\"lwp-request\",\n\t\t\"wget\",\n\t\t\"python-httpx\",\n\t\t\"python-requests\",\n\t\t\"openbsd ftp\",\n\t\t\"powershell\",\n\t\t\"fetch\",\n\t\t\"aiohttp\",\n\t\t\"http_get\",\n\t\t\"xh\",\n\t\t\"nushell\",\n\t\t\"zig\",\n\t\t\"node\",\n\t}\n}\n\ntype ResponseWithHeader struct {\n\tInProgress bool      // true if the request is being processed\n\tExpires    time.Time // expiration time of the cache entry\n\n\tBody       []byte\n\tHeader     http.Header\n\tStatusCode int // e.g. 200\n}\n\n// RequestProcessor handles incoming requests.\ntype RequestProcessor struct {\n\tpeakRequest30      sync.Map\n\tpeakRequest60      sync.Map\n\tlruCache           *lru.Cache\n\tstats              *stats.Stats\n\trouter             routing.Router\n\tupstreamTransport1 *http.Transport\n\tupstreamTransport2 *http.Transport\n\tupstreamTransport3 *http.Transport\n\tupstreamTransport4 *http.Transport\n\tconfig             *config.Config\n\tgeoIPCache         *geoip.Cache\n\tgeoLocation        *geoloc.Cache\n}\n\n// NewRequestProcessor returns new RequestProcessor.\nfunc NewRequestProcessor(config *config.Config) (*RequestProcessor, error) {\n\tlruCache, err := lru.New(config.Cache.Size)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdialer := &net.Dialer{\n\t\tTimeout:   time.Duration(config.Uplink.Timeout) * time.Second,\n\t\tKeepAlive: time.Duration(config.Uplink.Timeout) * time.Second,\n\t\tDualStack: true,\n\t}\n\n\ttransport1 := &http.Transport{\n\t\tDialContext: func(ctx context.Context, network, _ string) (net.Conn, error) {\n\t\t\treturn dialer.DialContext(ctx, network, config.Uplink.Address1)\n\t\t},\n\t}\n\ttransport2 := &http.Transport{\n\t\tDialContext: func(ctx context.Context, network, _ string) (net.Conn, error) {\n\t\t\treturn dialer.DialContext(ctx, network, config.Uplink.Address2)\n\t\t},\n\t}\n\ttransport3 := &http.Transport{\n\t\tDialContext: func(ctx context.Context, network, _ string) (net.Conn, error) {\n\t\t\treturn dialer.DialContext(ctx, network, config.Uplink.Address3)\n\t\t},\n\t}\n\ttransport4 := &http.Transport{\n\t\tDialContext: func(ctx context.Context, network, _ string) (net.Conn, error) {\n\t\t\treturn dialer.DialContext(ctx, network, config.Uplink.Address4)\n\t\t},\n\t}\n\n\tgeoCache, err := geoip.NewCache(config)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tgeoLocation, err := geoloc.NewCache(config)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\trp := &RequestProcessor{\n\t\tlruCache:           lruCache,\n\t\tstats:              stats.New(),\n\t\tupstreamTransport1: transport1,\n\t\tupstreamTransport2: transport2,\n\t\tupstreamTransport3: transport3,\n\t\tupstreamTransport4: transport4,\n\t\tconfig:             config,\n\t\tgeoIPCache:         geoCache,\n\t\tgeoLocation:        geoLocation,\n\t}\n\n\t// Initialize routes.\n\trp.router.AddPath(\"/:stats\", rp.stats)\n\trp.router.AddPath(\"/:geo-ip-get\", rp.geoIPCache)\n\trp.router.AddPath(\"/:geo-ip-put\", rp.geoIPCache)\n\trp.router.AddPath(\"/:geo-location\", rp.geoLocation)\n\n\treturn rp, nil\n}\n\n// Start starts async request processor jobs, such as peak handling.\nfunc (rp *RequestProcessor) Start() error {\n\treturn rp.startPeakHandling()\n}\n\nfunc (rp *RequestProcessor) ProcessRequest(r *http.Request) (*ResponseWithHeader, error) {\n\tvar (\n\t\tresponse *ResponseWithHeader\n\t\tip       = util.ReadUserIP(r)\n\t)\n\n\tif ip != \"127.0.0.1\" {\n\t\trp.stats.Inc(\"total\")\n\t}\n\n\t// Main routing logic.\n\tif rh := rp.router.Route(r); rh != nil {\n\t\tresult := rh.Response(r)\n\t\tif result != nil {\n\t\t\treturn fromCadre(result), nil\n\t\t}\n\t}\n\n\tif resp, ok := redirectInsecure(r); ok {\n\t\trp.stats.Inc(\"redirects\")\n\n\t\treturn resp, nil\n\t}\n\n\tif dontCache(r) {\n\t\trp.stats.Inc(\"uncached\")\n\n\t\treturn getAny(r, rp.upstreamTransport1, rp.upstreamTransport2, rp.upstreamTransport3, rp.upstreamTransport4)\n\t}\n\n\t// processing cached request\n\tcacheDigest := getCacheDigest(r)\n\n\trp.savePeakRequest(cacheDigest, r)\n\n\tresponse = rp.processRequestFromCache(r)\n\tif response != nil {\n\t\treturn response, nil\n\t}\n\n\treturn rp.processUncachedRequest(r)\n}\n\n// processRequestFromCache processes requests using the cache.\n// If no entry in cache found, nil is returned.\nfunc (rp *RequestProcessor) processRequestFromCache(r *http.Request) *ResponseWithHeader {\n\tvar (\n\t\tcacheEntry  ResponseWithHeader\n\t\tcacheDigest = getCacheDigest(r)\n\t\tok          bool\n\t)\n\n\tcacheBody, _ := rp.lruCache.Get(cacheDigest)\n\tcacheEntry, ok = cacheBody.(ResponseWithHeader)\n\tif !ok {\n\t\treturn nil\n\t}\n\n\t// If after all attempts we still have no answer,\n\t// respond with an error message.\n\t// (WAS: we try to make the query on our own)\n\tfor attempts := 0; attempts < 300; attempts++ {\n\t\tif !ok || !cacheEntry.InProgress {\n\t\t\tbreak\n\t\t}\n\t\ttime.Sleep(30 * time.Millisecond)\n\t\tcacheBody, _ = rp.lruCache.Get(cacheDigest)\n\t\tv, ok := cacheBody.(ResponseWithHeader)\n\t\tif ok {\n\t\t\tcacheEntry = v\n\t\t}\n\t}\n\tif cacheEntry.InProgress {\n\t\t// log.Printf(\"TIMEOUT: %s\\n\", cacheDigest)\n\t\treturn &ResponseWithHeader{\n\t\t\tInProgress: false,\n\t\t\tExpires:    time.Now().Add(time.Duration(randInt(1000, 1500)) * time.Second),\n\t\t\tBody:       []byte(\"This query is already being processed\"),\n\t\t\tStatusCode: 200,\n\t\t}\n\t}\n\tif ok && !cacheEntry.InProgress && cacheEntry.Expires.After(time.Now()) {\n\t\trp.stats.Inc(\"cache1\")\n\n\t\treturn &cacheEntry\n\t}\n\n\treturn nil\n}\n\n// processUncachedRequest processes requests that were not found in the cache.\nfunc (rp *RequestProcessor) processUncachedRequest(r *http.Request) (*ResponseWithHeader, error) {\n\tvar (\n\t\tcacheDigest = getCacheDigest(r)\n\t\tip          = util.ReadUserIP(r)\n\t\tresponse    *ResponseWithHeader\n\t\terr         error\n\t)\n\n\t// Indicate, that the request is being handled.\n\trp.lruCache.Add(cacheDigest, ResponseWithHeader{InProgress: true})\n\n\t// Response was not found in cache.\n\t// Starting real handling.\n\tformat := r.URL.Query().Get(\"format\")\n\tif len(format) != 0 {\n\t\trp.stats.Inc(\"format\")\n\t\tif format == \"j1\" {\n\t\t\trp.stats.Inc(\"format=j1\")\n\t\t}\n\t}\n\n\t// Count, how many IP addresses are known.\n\t_, err = rp.geoIPCache.Read(ip)\n\tif err == nil {\n\t\trp.stats.Inc(\"geoip\")\n\t}\n\n\tresponse, err = getAny(r, rp.upstreamTransport1, rp.upstreamTransport2, rp.upstreamTransport3, rp.upstreamTransport4)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif response.StatusCode == 200 || response.StatusCode == 304 || response.StatusCode == 404 {\n\t\trp.lruCache.Add(cacheDigest, *response)\n\t} else {\n\t\tlog.Printf(\"REMOVE: %d response for %s from cache\\n\", response.StatusCode, cacheDigest)\n\t\trp.lruCache.Remove(cacheDigest)\n\t}\n\n\treturn response, nil\n}\n\n// getCacheDigest is an implementation of the cache.get_signature of original wttr.in.\nfunc getCacheDigest(req *http.Request) string {\n\tuserAgent := req.Header.Get(\"User-Agent\")\n\n\tqueryHost := req.Host\n\tqueryString := req.RequestURI\n\n\tclientIPAddress := util.ReadUserIP(req)\n\n\tlang := req.Header.Get(\"Accept-Language\")\n\n\treturn fmt.Sprintf(\"%s:%s%s:%s:%s\", userAgent, queryHost, queryString, clientIPAddress, lang)\n}\n\n// dontCache returns true if req should not be cached.\nfunc dontCache(req *http.Request) bool {\n\t// dont cache cyclic requests\n\tloc := strings.Split(req.RequestURI, \"?\")[0]\n\n\treturn strings.Contains(loc, \":\")\n}\n\n// redirectInsecure returns redirection response, and bool value, if redirection was needed,\n// if the query comes from a browser, and it is insecure.\n//\n// Insecure queries are marked by the frontend web server\n// with X-Forwarded-Proto header:\n// `proxy_set_header   X-Forwarded-Proto $scheme;`.\nfunc redirectInsecure(req *http.Request) (*ResponseWithHeader, bool) {\n\tif isPlainTextAgent(req.Header.Get(\"User-Agent\")) {\n\t\treturn nil, false\n\t}\n\n\tif req.TLS != nil || strings.ToLower(req.Header.Get(\"X-Forwarded-Proto\")) == \"https\" {\n\t\treturn nil, false\n\t}\n\n\ttarget := \"https://\" + req.Host + req.URL.Path\n\tif len(req.URL.RawQuery) > 0 {\n\t\ttarget += \"?\" + req.URL.RawQuery\n\t}\n\n\tbody := []byte(fmt.Sprintf(`<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<TITLE>301 Moved</TITLE></HEAD><BODY>\n<H1>301 Moved</H1>\nThe document has moved\n<A HREF=\"%s\">here</A>.\n</BODY></HTML>\n`, target))\n\n\treturn &ResponseWithHeader{\n\t\tInProgress: false,\n\t\tExpires:    time.Now().Add(time.Duration(randInt(1000, 1500)) * time.Second),\n\t\tBody:       body,\n\t\tHeader:     http.Header{\"Location\": []string{target}},\n\t\tStatusCode: 301,\n\t}, true\n}\n\n// isPlainTextAgent returns true if userAgent is a plain-text agent.\nfunc isPlainTextAgent(userAgent string) bool {\n\tuserAgentLower := strings.ToLower(userAgent)\n\tfor _, signature := range plainTextAgents() {\n\t\tif strings.Contains(userAgentLower, signature) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc randInt(min int, max int) int {\n\treturn min + rand.Intn(max-min)\n}\n\n// ipFromAddr returns IP address from a ADDR:PORT pair.\nfunc ipFromAddr(s string) string {\n\tpos := strings.LastIndex(s, \":\")\n\tif pos == -1 {\n\t\treturn s\n\t}\n\n\treturn s[:pos]\n}\n\n// fromCadre converts Cadre into a responseWithHeader.\nfunc fromCadre(cadre *routing.Cadre) *ResponseWithHeader {\n\treturn &ResponseWithHeader{\n\t\tBody:       cadre.Body,\n\t\tExpires:    cadre.Expires,\n\t\tStatusCode: 200,\n\t\tInProgress: false,\n\t}\n}\n"
  },
  {
    "path": "internal/routing/routing.go",
    "content": "package routing\n\nimport (\n\t\"net/http\"\n\t\"time\"\n)\n\n// CadreFormat specifies how the shot data is formatted.\ntype CadreFormat int\n\nconst (\n\t// CadreFormatANSI represents Terminal ANSI format.\n\tCadreFormatANSI = iota\n\n\t// CadreFormatHTML represents HTML.\n\tCadreFormatHTML\n\n\t// CadreFormatPNG represents PNG.\n\tCadreFormatPNG\n)\n\n// Cadre contains result of a query execution.\ntype Cadre struct {\n\t// Body contains the data of Cadre, formatted as Format.\n\tBody []byte\n\n\t// Format of the shot.\n\tFormat CadreFormat\n\n\t// Expires contains the time of the Cadre expiration,\n\t// or 0 if it does not expire.\n\tExpires time.Time\n}\n\n// Handler can handle queries and return views.\ntype Handler interface {\n\tResponse(*http.Request) *Cadre\n}\n\ntype routeFunc func(*http.Request) bool\n\ntype route struct {\n\trouteFunc\n\tHandler\n}\n\n// Router keeps a routing table, and finds queries handlers, based on its rules.\ntype Router struct {\n\trt []route\n}\n\n// Route returns a query handler based on its content.\nfunc (r *Router) Route(req *http.Request) Handler {\n\tfor _, re := range r.rt {\n\t\tif re.routeFunc(req) {\n\t\t\treturn re.Handler\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// AddPath adds route for a static path.\nfunc (r *Router) AddPath(path string, handler Handler) {\n\tr.rt = append(r.rt, route{routePath(path), handler})\n}\n\nfunc routePath(path string) routeFunc {\n\treturn routeFunc(func(req *http.Request) bool {\n\t\treturn req.URL.Path == path\n\t})\n}\n"
  },
  {
    "path": "internal/stats/stats.go",
    "content": "package stats\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/chubin/wttr.in/internal/routing\"\n)\n\n// Stats holds processed requests statistics.\ntype Stats struct {\n\tm         sync.Mutex\n\tv         map[string]int\n\tstartTime time.Time\n}\n\n// New returns new Stats.\nfunc New() *Stats {\n\treturn &Stats{\n\t\tv:         map[string]int{},\n\t\tstartTime: time.Now(),\n\t}\n}\n\n// Inc key by one.\nfunc (c *Stats) Inc(key string) {\n\tc.m.Lock()\n\tc.v[key]++\n\tc.m.Unlock()\n}\n\n// Get current key counter value.\nfunc (c *Stats) Get(key string) int {\n\tc.m.Lock()\n\tdefer c.m.Unlock()\n\n\treturn c.v[key]\n}\n\n// Reset key counter.\nfunc (c *Stats) Reset(key string) int {\n\tc.m.Lock()\n\tdefer c.m.Unlock()\n\tresult := c.v[key]\n\tc.v[key] = 0\n\n\treturn result\n}\n\n// Show returns current statistics formatted as []byte.\nfunc (c *Stats) Show() []byte {\n\tvar b bytes.Buffer\n\n\tc.m.Lock()\n\tdefer c.m.Unlock()\n\n\tuptime := time.Since(c.startTime) / time.Second\n\n\tfmt.Fprintf(&b, \"%-20s: %v\\n\", \"Running since\", c.startTime.Format(time.RFC3339))\n\tfmt.Fprintf(&b, \"%-20s: %d\\n\", \"Uptime (min)\", uptime/60)\n\n\tfmt.Fprintf(&b, \"%-20s: %d\\n\", \"Total queries\", c.v[\"total\"])\n\n\tif uptime != 0 {\n\t\tfmt.Fprintf(&b, \"%-20s: %d\\n\", \"Throughput (QpM)\", c.v[\"total\"]*60/int(uptime))\n\t}\n\n\tfmt.Fprintf(&b, \"%-20s: %d\\n\", \"Cache L1 queries\", c.v[\"cache1\"])\n\n\tif c.v[\"total\"] != 0 {\n\t\tfmt.Fprintf(&b, \"%-20s: %d\\n\", \"Cache L1 queries (%)\", (100*c.v[\"cache1\"])/c.v[\"total\"])\n\t}\n\n\tfmt.Fprintf(&b, \"%-20s: %d\\n\", \"Upstream queries\", c.v[\"total\"]-c.v[\"cache1\"])\n\tfmt.Fprintf(&b, \"%-20s: %d\\n\", \"Queries with format\", c.v[\"format\"])\n\tfmt.Fprintf(&b, \"%-20s: %d\\n\", \"Queries with format=j1\", c.v[\"format=j1\"])\n\tfmt.Fprintf(&b, \"%-20s: %d\\n\", \"Queries with known IP\", c.v[\"geoip\"])\n\n\treturn b.Bytes()\n}\n\nfunc (c *Stats) Response(*http.Request) *routing.Cadre {\n\treturn &routing.Cadre{\n\t\tBody: c.Show(),\n\t}\n}\n"
  },
  {
    "path": "internal/types/errors.go",
    "content": "package types\n\nimport \"errors\"\n\nvar (\n\tErrNotFound          = errors.New(\"cache entry not found\")\n\tErrInvalidCacheEntry = errors.New(\"invalid cache entry format\")\n\tErrUpstream          = errors.New(\"upstream error\")\n\n\t// ErrNoServersConfigured means that there are no servers to run.\n\tErrNoServersConfigured = errors.New(\"no servers configured\")\n\n\tErrUnknownLocationService = errors.New(\"unknown location service\")\n)\n"
  },
  {
    "path": "internal/types/types.go",
    "content": "package types\n\ntype CacheType string\n\nconst (\n\tCacheTypeDB    = \"db\"\n\tCacheTypeFiles = \"files\"\n)\n"
  },
  {
    "path": "internal/util/files.go",
    "content": "package util\n\nimport \"os\"\n\n// RemoveFileIfExists removes filename if exists, or does nothing if the file\n// is not there. Returns an error, if it occurred during deletion.\nfunc RemoveFileIfExists(filename string) error {\n\t_, err := os.Stat(filename)\n\tif err != nil {\n\t\tif !os.IsNotExist(err) {\n\t\t\treturn err\n\t\t}\n\t\t// no db file\n\t\treturn nil\n\t}\n\n\treturn os.Remove(filename)\n}\n"
  },
  {
    "path": "internal/util/http.go",
    "content": "package util\n\nimport (\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n)\n\n// ReadUserIP returns IP address of the client from http.Request,\n// taking into account the HTTP headers.\nfunc ReadUserIP(r *http.Request) string {\n\tIPAddress := r.Header.Get(\"X-Real-Ip\")\n\tif IPAddress == \"\" {\n\t\tIPAddress = r.Header.Get(\"X-Forwarded-For\")\n\t}\n\tif IPAddress == \"\" {\n\t\tIPAddress = r.RemoteAddr\n\t\tvar err error\n\t\tIPAddress, _, err = net.SplitHostPort(IPAddress)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"ERROR: userip: %q is not IP:port\\n\", IPAddress)\n\t\t}\n\t}\n\n\treturn IPAddress\n}\n"
  },
  {
    "path": "internal/util/yaml.go",
    "content": "package util\n\nimport (\n\t\"bytes\"\n\n\t\"gopkg.in/yaml.v3\"\n)\n\n// YamlUnmarshalStrict unmarshals YAML data with an error when unknown fields are present.\nfunc YamlUnmarshalStrict(in []byte, out interface{}) error {\n\tdec := yaml.NewDecoder(bytes.NewReader(in))\n\tdec.KnownFields(true)\n\n\treturn dec.Decode(out)\n}\n"
  },
  {
    "path": "internal/view/v1/api.go",
    "content": "//nolint:forbidigo,funlen,nestif,goerr113,gocognit,cyclop\npackage v1\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n//nolint:tagliatelle\ntype cond struct {\n\tChanceOfRain   string  `json:\"chanceofrain\"`\n\tFeelsLikeC     int     `json:\",string\"`\n\tPrecipMM       float32 `json:\"precipMM,string\"`\n\tTempC          int     `json:\"tempC,string\"`\n\tTempC2         int     `json:\"temp_C,string\"`\n\tTime           int     `json:\"time,string\"`\n\tVisibleDistKM  int     `json:\"visibility,string\"`\n\tWeatherCode    int     `json:\"weatherCode,string\"`\n\tWeatherDesc    []struct{ Value string }\n\tWindGustKmph   int `json:\",string\"`\n\tWinddir16Point string\n\tWindspeedKmph  int `json:\"windspeedKmph,string\"`\n}\n\ntype astro struct {\n\tMoonrise string\n\tMoonset  string\n\tSunrise  string\n\tSunset   string\n}\n\ntype weather struct {\n\tAstronomy []astro\n\tDate      string\n\tHourly    []cond\n\tMaxtempC  int `json:\"maxtempC,string\"`\n\tMintempC  int `json:\"mintempC,string\"`\n}\n\ntype loc struct {\n\tQuery string `json:\"query\"`\n\tType  string `json:\"type\"`\n}\n\n//nolint:tagliatelle\ntype resp struct {\n\tData struct {\n\t\tCur     []cond                 `json:\"current_condition\"`\n\t\tErr     []struct{ Msg string } `json:\"error\"`\n\t\tReq     []loc                  `json:\"request\"`\n\t\tWeather []weather              `json:\"weather\"`\n\t} `json:\"data\"`\n}\n\nfunc (g *global) getDataFromAPI() (*resp, error) {\n\tvar (\n\t\tret    resp\n\t\tparams []string\n\t)\n\n\tif len(g.config.APIKey) == 0 {\n\t\treturn nil, fmt.Errorf(\"no API key specified. Setup instructions are in the README\")\n\t}\n\tparams = append(params, \"key=\"+g.config.APIKey)\n\n\t// non-flag shortcut arguments will overwrite possible flag arguments\n\tfor _, arg := range flag.Args() {\n\t\tif v, err := strconv.Atoi(arg); err == nil && len(arg) == 1 {\n\t\t\tg.config.Numdays = v\n\t\t} else {\n\t\t\tg.config.City = arg\n\t\t}\n\t}\n\n\tif len(g.config.City) > 0 {\n\t\tparams = append(params, \"q=\"+url.QueryEscape(g.config.City))\n\t}\n\tparams = append(params, \"format=json\", \"num_of_days=\"+strconv.Itoa(g.config.Numdays), \"tp=3\")\n\tif g.config.Lang != \"\" {\n\t\tparams = append(params, \"lang=\"+g.config.Lang)\n\t}\n\n\tif g.debug {\n\t\tfmt.Fprintln(os.Stderr, params)\n\t}\n\n\tres, err := http.Get(wuri + strings.Join(params, \"&\"))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer res.Body.Close()\n\tbody, err := ioutil.ReadAll(res.Body)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif g.debug {\n\t\tvar out bytes.Buffer\n\n\t\terr := json.Indent(&out, body, \"\", \"  \")\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t_, err = out.WriteTo(os.Stderr)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tfmt.Print(\"\\n\\n\")\n\t}\n\n\tif g.config.Lang == \"\" {\n\t\tif err = json.Unmarshal(body, &ret); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t} else {\n\t\tif err = g.unmarshalLang(body, &ret); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn &ret, nil\n}\n\nfunc (g *global) unmarshalLang(body []byte, r *resp) error {\n\tvar rv map[string]interface{}\n\tif err := json.Unmarshal(body, &rv); err != nil {\n\t\treturn err\n\t}\n\tif data, ok := rv[\"data\"].(map[string]interface{}); ok {\n\t\tif ccs, ok := data[\"current_condition\"].([]interface{}); ok {\n\t\t\tfor _, cci := range ccs {\n\t\t\t\tcc, ok := cci.(map[string]interface{})\n\t\t\t\tif !ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tlangs, ok := cc[\"lang_\"+g.config.Lang].([]interface{})\n\t\t\t\tif !ok || len(langs) == 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tweatherDesc, ok := cc[\"weatherDesc\"].([]interface{})\n\t\t\t\tif !ok || len(weatherDesc) == 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tweatherDesc[0] = langs[0]\n\t\t\t}\n\t\t}\n\t\tif ws, ok := data[\"weather\"].([]interface{}); ok {\n\t\t\tfor _, wi := range ws {\n\t\t\t\tw, ok := wi.(map[string]interface{})\n\t\t\t\tif !ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif hs, ok := w[\"hourly\"].([]interface{}); ok {\n\t\t\t\t\tfor _, hi := range hs {\n\t\t\t\t\t\th, ok := hi.(map[string]interface{})\n\t\t\t\t\t\tif !ok {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlangs, ok := h[\"lang_\"+g.config.Lang].([]interface{})\n\t\t\t\t\t\tif !ok || len(langs) == 0 {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tweatherDesc, ok := h[\"weatherDesc\"].([]interface{})\n\t\t\t\t\t\tif !ok || len(weatherDesc) == 0 {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tweatherDesc[0] = langs[0]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tvar buf bytes.Buffer\n\tif err := json.NewEncoder(&buf).Encode(rv); err != nil {\n\t\treturn err\n\t}\n\tif err := json.NewDecoder(&buf).Decode(r); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/view/v1/cmd.go",
    "content": "// This code represents wttr.in view v1.\n// It is based on wego (github.com/schachmat/wego) from which it diverged back in 2016.\n\n//nolint:forbidigo,funlen,gocognit,cyclop\npackage v1\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n\t\"os/user\"\n\t\"path\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/mattn/go-colorable\"\n\t\"github.com/mattn/go-runewidth\"\n)\n\ntype Configuration struct {\n\tAPIKey       string\n\tCity         string\n\tNumdays      int\n\tImperial     bool\n\tWindUnit     bool\n\tInverse      bool\n\tLang         string\n\tNarrow       bool\n\tLocationName string\n\tWindMS       bool\n\tRightToLeft  bool\n}\n\ntype global struct {\n\tansiEsc    *regexp.Regexp\n\tconfig     Configuration\n\tconfigpath string\n\tdebug      bool\n}\n\nconst (\n\twuri      = \"http://127.0.0.1:5001/premium/v1/weather.ashx?\"\n\tsuri      = \"http://127.0.0.1:5001/premium/v1/search.ashx?\"\n\tslotcount = 4\n)\n\nfunc (g *global) configload() error {\n\tb, err := ioutil.ReadFile(g.configpath)\n\tif err == nil {\n\t\treturn json.Unmarshal(b, &g.config)\n\t}\n\n\treturn err\n}\n\nfunc (g *global) configsave() error {\n\tj, err := json.MarshalIndent(g.config, \"\", \"\\t\")\n\tif err == nil {\n\t\treturn ioutil.WriteFile(g.configpath, j, 0o600)\n\t}\n\n\treturn err\n}\n\nfunc (g *global) init() {\n\tflag.IntVar(&g.config.Numdays, \"days\", 3, \"Number of days of weather forecast to be displayed\")\n\tflag.StringVar(&g.config.Lang, \"lang\", \"en\", \"Language of the report\")\n\tflag.StringVar(&g.config.City, \"city\", \"New York\", \"City to be queried\")\n\tflag.BoolVar(&g.debug, \"debug\", false, \"Print out raw json response for debugging purposes\")\n\tflag.BoolVar(&g.config.Imperial, \"imperial\", false, \"Use imperial units\")\n\tflag.BoolVar(&g.config.Inverse, \"inverse\", false, \"Use inverted colors\")\n\tflag.BoolVar(&g.config.Narrow, \"narrow\", false, \"Narrow output (two columns)\")\n\tflag.StringVar(&g.config.LocationName, \"location_name\", \"\", \"Location name (used in the caption)\")\n\tflag.BoolVar(&g.config.WindMS, \"wind_in_ms\", false, \"Show wind speed in m/s\")\n\tflag.BoolVar(&g.config.RightToLeft, \"right_to_left\", false, \"Right to left script\")\n\tg.configpath = os.Getenv(\"WEGORC\")\n\tif g.configpath == \"\" {\n\t\tusr, err := user.Current()\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"%v\\nYou can set the environment variable WEGORC to point to your config file as a workaround.\", err)\n\t\t}\n\t\tg.configpath = path.Join(usr.HomeDir, \".wegorc\")\n\t}\n\tg.config.APIKey = \"\"\n\tg.config.Imperial = false\n\tg.config.Lang = \"en\"\n\terr := g.configload()\n\tvar pathError *os.PathError\n\tif errors.Is(err, pathError) {\n\t\tlog.Printf(\"No config file found. Creating %s ...\", g.configpath)\n\t\tif err2 := g.configsave(); err2 != nil {\n\t\t\tlog.Fatal(err2)\n\t\t}\n\t} else if err != nil {\n\t\tlog.Fatalf(\"could not parse %v: %v\", g.configpath, err)\n\t}\n\n\tg.ansiEsc = regexp.MustCompile(\"\\033.*?m\")\n}\n\nfunc Cmd() error {\n\tg := global{}\n\tg.init()\n\n\tflag.Parse()\n\n\tr, err := g.getDataFromAPI()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif r.Data.Req == nil || len(r.Data.Req) < 1 {\n\t\tif r.Data.Err != nil && len(r.Data.Err) >= 1 {\n\t\t\tlog.Fatal(r.Data.Err[0].Msg)\n\t\t}\n\t\tlog.Fatal(\"Malformed response.\")\n\t}\n\tlocationName := r.Data.Req[0].Query\n\tif g.config.LocationName != \"\" {\n\t\tlocationName = g.config.LocationName\n\t}\n\tif g.config.Lang == \"he\" || g.config.Lang == \"ar\" || g.config.Lang == \"fa\" {\n\t\tg.config.RightToLeft = true\n\t}\n\tif caption, ok := localizedCaption()[g.config.Lang]; !ok {\n\t\tfmt.Printf(\"Weather report: %s\\n\\n\", locationName)\n\t} else {\n\t\tif g.config.RightToLeft {\n\t\t\tcaption = locationName + \" \" + caption\n\t\t\tspace := strings.Repeat(\" \", 125-runewidth.StringWidth(caption))\n\t\t\tfmt.Printf(\"%s%s\\n\\n\", space, caption)\n\t\t} else {\n\t\t\tfmt.Printf(\"%s %s\\n\\n\", caption, locationName)\n\t\t}\n\t}\n\tstdout := colorable.NewColorableStdout()\n\n\tif r.Data.Cur == nil || len(r.Data.Cur) < 1 {\n\t\tlog.Fatal(\"No weather data available.\")\n\t}\n\tout := g.formatCond(make([]string, 5), r.Data.Cur[0], true)\n\tfor _, val := range out {\n\t\tif g.config.RightToLeft {\n\t\t\tfmt.Fprint(stdout, strings.Repeat(\" \", 94))\n\t\t} else {\n\t\t\tfmt.Fprint(stdout, \" \")\n\t\t}\n\t\tfmt.Fprintln(stdout, val)\n\t}\n\n\tif g.config.Numdays == 0 {\n\t\treturn nil\n\t}\n\tif r.Data.Weather == nil {\n\t\tlog.Fatal(\"No detailed weather forecast available.\")\n\t}\n\tfor _, d := range r.Data.Weather {\n\t\tlines, err := g.printDay(d)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, val := range lines {\n\t\t\tfmt.Fprintln(stdout, val)\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/view/v1/format.go",
    "content": "//nolint:funlen,nestif,cyclop,gocognit,gocyclo\npackage v1\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"unicode/utf8\"\n\n\t\"github.com/mattn/go-runewidth\"\n)\n\nfunc windDir() map[string]string {\n\treturn map[string]string{\n\t\t\"N\":   \"\\033[1m↓\\033[0m\",\n\t\t\"NNE\": \"\\033[1m↓\\033[0m\",\n\t\t\"NE\":  \"\\033[1m↙\\033[0m\",\n\t\t\"ENE\": \"\\033[1m↙\\033[0m\",\n\t\t\"E\":   \"\\033[1m←\\033[0m\",\n\t\t\"ESE\": \"\\033[1m←\\033[0m\",\n\t\t\"SE\":  \"\\033[1m↖\\033[0m\",\n\t\t\"SSE\": \"\\033[1m↖\\033[0m\",\n\t\t\"S\":   \"\\033[1m↑\\033[0m\",\n\t\t\"SSW\": \"\\033[1m↑\\033[0m\",\n\t\t\"SW\":  \"\\033[1m↗\\033[0m\",\n\t\t\"WSW\": \"\\033[1m↗\\033[0m\",\n\t\t\"W\":   \"\\033[1m→\\033[0m\",\n\t\t\"WNW\": \"\\033[1m→\\033[0m\",\n\t\t\"NW\":  \"\\033[1m↘\\033[0m\",\n\t\t\"NNW\": \"\\033[1m↘\\033[0m\",\n\t}\n}\n\nfunc (g *global) formatTemp(c cond) string {\n\tcolor := func(temp int, explicitPlus bool) string {\n\t\tvar col int\n\t\t//nolint:dupl\n\t\tif !g.config.Inverse {\n\t\t\t// Extremely cold temperature must be shown with violet\n\t\t\t// because dark blue is too dark\n\t\t\tcol = 165\n\t\t\tswitch temp {\n\t\t\tcase -15, -14, -13:\n\t\t\t\tcol = 171\n\t\t\tcase -12, -11, -10:\n\t\t\t\tcol = 33\n\t\t\tcase -9, -8, -7:\n\t\t\t\tcol = 39\n\t\t\tcase -6, -5, -4:\n\t\t\t\tcol = 45\n\t\t\tcase -3, -2, -1:\n\t\t\t\tcol = 51\n\t\t\tcase 0, 1:\n\t\t\t\tcol = 50\n\t\t\tcase 2, 3:\n\t\t\t\tcol = 49\n\t\t\tcase 4, 5:\n\t\t\t\tcol = 48\n\t\t\tcase 6, 7:\n\t\t\t\tcol = 47\n\t\t\tcase 8, 9:\n\t\t\t\tcol = 46\n\t\t\tcase 10, 11, 12:\n\t\t\t\tcol = 82\n\t\t\tcase 13, 14, 15:\n\t\t\t\tcol = 118\n\t\t\tcase 16, 17, 18:\n\t\t\t\tcol = 154\n\t\t\tcase 19, 20, 21:\n\t\t\t\tcol = 190\n\t\t\tcase 22, 23, 24:\n\t\t\t\tcol = 226\n\t\t\tcase 25, 26, 27:\n\t\t\t\tcol = 220\n\t\t\tcase 28, 29, 30:\n\t\t\t\tcol = 214\n\t\t\tcase 31, 32, 33:\n\t\t\t\tcol = 208\n\t\t\tcase 34, 35, 36:\n\t\t\t\tcol = 202\n\t\t\tdefault:\n\t\t\t\tif temp > 0 {\n\t\t\t\t\tcol = 196\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tcol = 16\n\t\t\tswitch temp {\n\t\t\tcase -15, -14, -13:\n\t\t\t\tcol = 17\n\t\t\tcase -12, -11, -10:\n\t\t\t\tcol = 18\n\t\t\tcase -9, -8, -7:\n\t\t\t\tcol = 19\n\t\t\tcase -6, -5, -4:\n\t\t\t\tcol = 20\n\t\t\tcase -3, -2, -1:\n\t\t\t\tcol = 21\n\t\t\tcase 0, 1:\n\t\t\t\tcol = 30\n\t\t\tcase 2, 3:\n\t\t\t\tcol = 28\n\t\t\tcase 4, 5:\n\t\t\t\tcol = 29\n\t\t\tcase 6, 7:\n\t\t\t\tcol = 30\n\t\t\tcase 8, 9:\n\t\t\t\tcol = 34\n\t\t\tcase 10, 11, 12:\n\t\t\t\tcol = 35\n\t\t\tcase 13, 14, 15:\n\t\t\t\tcol = 36\n\t\t\tcase 16, 17, 18:\n\t\t\t\tcol = 40\n\t\t\tcase 19, 20, 21:\n\t\t\t\tcol = 59\n\t\t\tcase 22, 23, 24:\n\t\t\t\tcol = 100\n\t\t\tcase 25, 26, 27:\n\t\t\t\tcol = 101\n\t\t\tcase 28, 29, 30:\n\t\t\t\tcol = 94\n\t\t\tcase 31, 32, 33:\n\t\t\t\tcol = 166\n\t\t\tcase 34, 35, 36:\n\t\t\t\tcol = 52\n\t\t\tdefault:\n\t\t\t\tif temp > 0 {\n\t\t\t\t\tcol = 196\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif g.config.Imperial {\n\t\t\ttemp = (temp*18 + 320) / 10\n\t\t}\n\t\tif explicitPlus {\n\t\t\treturn fmt.Sprintf(\"\\033[38;5;%03dm+%d\\033[0m\", col, temp)\n\t\t}\n\n\t\treturn fmt.Sprintf(\"\\033[38;5;%03dm%d\\033[0m\", col, temp)\n\t}\n\tt := c.TempC\n\tif t == 0 {\n\t\tt = c.TempC2\n\t}\n\n\t// hyphen := \" - \"\n\n\t// if (config.Lang == \"sl\") {\n\t//     hyphen = \"-\"\n\t// }\n\n\t// hyphen = \"..\"\n\n\texplicitPlus1 := false\n\texplicitPlus2 := false\n\tif c.FeelsLikeC != t {\n\t\tif t > 0 {\n\t\t\texplicitPlus1 = true\n\t\t}\n\t\tif c.FeelsLikeC > 0 {\n\t\t\texplicitPlus2 = true\n\t\t}\n\t\tif explicitPlus1 {\n\t\t\texplicitPlus2 = false\n\t\t}\n\n\t\treturn g.pad(\n\t\t\tfmt.Sprintf(\"%s(%s) °%s\",\n\t\t\t\tcolor(t, explicitPlus1),\n\t\t\t\tcolor(c.FeelsLikeC, explicitPlus2),\n\t\t\t\tunitTemp()[g.config.Imperial]),\n\t\t\t15)\n\t}\n\n\treturn g.pad(fmt.Sprintf(\"%s °%s\", color(c.FeelsLikeC, false), unitTemp()[g.config.Imperial]), 15)\n}\n\nfunc (g *global) formatWind(c cond) string {\n\tunitWindString := unitWind(0, g.config.Lang)\n\tif g.config.WindMS {\n\t\tunitWindString = unitWind(2, g.config.Lang)\n\t} else if g.config.Imperial {\n\t\tunitWindString = unitWind(1, g.config.Lang)\n\t}\n\n\thyphen := \"-\"\n\n\tcWindGustKmph := speedToColor(c.WindGustKmph, windInRightUnits(c.WindGustKmph, g.config.WindMS, g.config.Imperial))\n\tcWindspeedKmph := speedToColor(c.WindspeedKmph, windInRightUnits(c.WindspeedKmph, g.config.WindMS, g.config.Imperial))\n\tif windInRightUnits(c.WindGustKmph, g.config.WindMS, g.config.Imperial) >\n\t\twindInRightUnits(c.WindspeedKmph, g.config.WindMS, g.config.Imperial) {\n\t\treturn g.pad(\n\t\t\tfmt.Sprintf(\"%s %s%s%s %s\", windDir()[c.Winddir16Point], cWindspeedKmph, hyphen, cWindGustKmph, unitWindString),\n\t\t\t15)\n\t}\n\n\treturn g.pad(fmt.Sprintf(\"%s %s %s\", windDir()[c.Winddir16Point], cWindspeedKmph, unitWindString), 15)\n}\n\nfunc windInRightUnits(spd int, windMS, imperial bool) int {\n\tif windMS {\n\t\tspd = (spd * 1000) / 3600\n\t} else if imperial {\n\t\tspd = (spd * 1000) / 1609\n\t}\n\n\treturn spd\n}\n\nfunc speedToColor(spd, spdConverted int) string {\n\tcol := 46\n\tswitch spd {\n\tcase 1, 2, 3:\n\t\tcol = 82\n\tcase 4, 5, 6:\n\t\tcol = 118\n\tcase 7, 8, 9:\n\t\tcol = 154\n\tcase 10, 11, 12:\n\t\tcol = 190\n\tcase 13, 14, 15:\n\t\tcol = 226\n\tcase 16, 17, 18, 19:\n\t\tcol = 220\n\tcase 20, 21, 22, 23:\n\t\tcol = 214\n\tcase 24, 25, 26, 27:\n\t\tcol = 208\n\tcase 28, 29, 30, 31:\n\t\tcol = 202\n\tdefault:\n\t\tif spd > 0 {\n\t\t\tcol = 196\n\t\t}\n\t}\n\n\treturn fmt.Sprintf(\"\\033[38;5;%03dm%d\\033[0m\", col, spdConverted)\n}\n\nfunc (g *global) formatVisibility(c cond) string {\n\tif g.config.Imperial {\n\t\tc.VisibleDistKM = (c.VisibleDistKM * 621) / 1000\n\t}\n\n\treturn g.pad(fmt.Sprintf(\"%d %s\", c.VisibleDistKM, unitVis(g.config.Imperial, g.config.Lang)), 15)\n}\n\nfunc (g *global) formatRain(c cond) string {\n\trainUnit := c.PrecipMM\n\tif g.config.Imperial {\n\t\trainUnit = c.PrecipMM * 0.039\n\t}\n\tif c.ChanceOfRain != \"\" {\n\t\treturn g.pad(fmt.Sprintf(\n\t\t\t\"%.1f %s | %s%%\",\n\t\t\trainUnit,\n\t\t\tunitRain(g.config.Imperial, g.config.Lang),\n\t\t\tc.ChanceOfRain), 15)\n\t}\n\n\treturn g.pad(fmt.Sprintf(\"%.1f %s\", rainUnit, unitRain(g.config.Imperial, g.config.Lang)), 15)\n}\n\nfunc (g *global) formatCond(cur []string, c cond, current bool) []string {\n\tvar (\n\t\tret  []string\n\t\ticon []string\n\t)\n\n\tif i, ok := codes()[c.WeatherCode]; !ok {\n\t\ticon = getIcon(\"iconUnknown\")\n\t} else {\n\t\ticon = i\n\t}\n\tif g.config.Inverse {\n\t\t// inverting colors\n\t\tfor i := range icon {\n\t\t\ticon[i] = strings.ReplaceAll(icon[i], \"38;5;226\", \"38;5;94\")\n\t\t\ticon[i] = strings.ReplaceAll(icon[i], \"38;5;250\", \"38;5;243\")\n\t\t\ticon[i] = strings.ReplaceAll(icon[i], \"38;5;21\", \"38;5;18\")\n\t\t\ticon[i] = strings.ReplaceAll(icon[i], \"38;5;255\", \"38;5;245\")\n\t\t\ticon[i] = strings.ReplaceAll(icon[i], \"38;5;111\", \"38;5;63\")\n\t\t\ticon[i] = strings.ReplaceAll(icon[i], \"38;5;251\", \"38;5;238\")\n\t\t}\n\t}\n\t// desc := fmt.Sprintf(\"%-15.15v\", c.WeatherDesc[0].Value)\n\tdesc := c.WeatherDesc[0].Value\n\tif g.config.RightToLeft {\n\t\tfor runewidth.StringWidth(desc) < 15 {\n\t\t\tdesc = \" \" + desc\n\t\t}\n\t\tfor runewidth.StringWidth(desc) > 15 {\n\t\t\t_, size := utf8.DecodeLastRuneInString(desc)\n\t\t\tdesc = desc[size:]\n\t\t}\n\t} else {\n\t\tfor runewidth.StringWidth(desc) < 15 {\n\t\t\tdesc += \" \"\n\t\t}\n\t\tfor runewidth.StringWidth(desc) > 15 {\n\t\t\t_, size := utf8.DecodeLastRuneInString(desc)\n\t\t\tdesc = desc[:len(desc)-size]\n\t\t}\n\t}\n\tif current {\n\t\tif g.config.RightToLeft {\n\t\t\tdesc = c.WeatherDesc[0].Value\n\t\t\tif runewidth.StringWidth(desc) < 15 {\n\t\t\t\tdesc = strings.Repeat(\" \", 15-runewidth.StringWidth(desc)) + desc\n\t\t\t}\n\t\t} else {\n\t\t\tdesc = c.WeatherDesc[0].Value\n\t\t}\n\t} else {\n\t\tif g.config.RightToLeft {\n\t\t\tif frstRune, size := utf8.DecodeRuneInString(desc); frstRune != ' ' {\n\t\t\t\tdesc = \"…\" + desc[size:]\n\t\t\t\tfor runewidth.StringWidth(desc) < 15 {\n\t\t\t\t\tdesc = \" \" + desc\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif lastRune, size := utf8.DecodeLastRuneInString(desc); lastRune != ' ' {\n\t\t\t\tdesc = desc[:len(desc)-size] + \"…\"\n\t\t\t\t// for numberOfSpaces < runewidth.StringWidth(fmt.Sprintf(\"%c\", lastRune)) - 1 {\n\t\t\t\tfor runewidth.StringWidth(desc) < 15 {\n\t\t\t\t\tdesc += \" \"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif g.config.RightToLeft {\n\t\tret = append(\n\t\t\tret,\n\t\t\tfmt.Sprintf(\"%v %v %v\", cur[0], desc, icon[0]),\n\t\t\tfmt.Sprintf(\"%v %v %v\", cur[1], g.formatTemp(c), icon[1]),\n\t\t\tfmt.Sprintf(\"%v %v %v\", cur[2], g.formatWind(c), icon[2]),\n\t\t\tfmt.Sprintf(\"%v %v %v\", cur[3], g.formatVisibility(c), icon[3]),\n\t\t\tfmt.Sprintf(\"%v %v %v\", cur[4], g.formatRain(c), icon[4]))\n\t} else {\n\t\tret = append(\n\t\t\tret,\n\t\t\tfmt.Sprintf(\"%v %v %v\", cur[0], icon[0], desc),\n\t\t\tfmt.Sprintf(\"%v %v %v\", cur[1], icon[1], g.formatTemp(c)),\n\t\t\tfmt.Sprintf(\"%v %v %v\", cur[2], icon[2], g.formatWind(c)),\n\t\t\tfmt.Sprintf(\"%v %v %v\", cur[3], icon[3], g.formatVisibility(c)),\n\t\t\tfmt.Sprintf(\"%v %v %v\", cur[4], icon[4], g.formatRain(c)))\n\t}\n\n\treturn ret\n}\n\nfunc justifyCenter(s string, width int) string {\n\tappendSide := 0\n\tfor runewidth.StringWidth(s) <= width {\n\t\tif appendSide == 1 {\n\t\t\ts += \" \"\n\t\t\tappendSide = 0\n\t\t} else {\n\t\t\ts = \" \" + s\n\t\t\tappendSide = 1\n\t\t}\n\t}\n\n\treturn s\n}\n\nfunc reverse(s string) string {\n\tr := []rune(s)\n\tfor i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {\n\t\tr[i], r[j] = r[j], r[i]\n\t}\n\n\treturn string(r)\n}\n\nfunc (g *global) pad(s string, mustLen int) string {\n\tvar ret string\n\tret = s\n\trealLen := utf8.RuneCountInString(g.ansiEsc.ReplaceAllLiteralString(s, \"\"))\n\tdelta := mustLen - realLen\n\tif delta > 0 {\n\t\tif g.config.RightToLeft {\n\t\t\tret = strings.Repeat(\" \", delta) + ret + \"\\033[0m\"\n\t\t} else {\n\t\t\tret += \"\\033[0m\" + strings.Repeat(\" \", delta)\n\t\t}\n\t} else if delta < 0 {\n\t\ttoks := g.ansiEsc.Split(s, 2)\n\t\ttokLen := utf8.RuneCountInString(toks[0])\n\t\tesc := g.ansiEsc.FindString(s)\n\t\tif tokLen > mustLen {\n\t\t\tret = fmt.Sprintf(\"%.*s\\033[0m\", mustLen, toks[0])\n\t\t} else {\n\t\t\tret = fmt.Sprintf(\"%s%s%s\", toks[0], esc, g.pad(toks[1], mustLen-tokLen))\n\t\t}\n\t}\n\n\treturn ret\n}\n"
  },
  {
    "path": "internal/view/v1/icons.go",
    "content": "package v1\n\n//nolint:funlen\nfunc getIcon(name string) []string {\n\ticon := map[string][]string{\n\t\t\"iconUnknown\": {\n\t\t\t\"    .-.      \",\n\t\t\t\"     __)     \",\n\t\t\t\"    (        \",\n\t\t\t\"     `-’     \",\n\t\t\t\"      •      \",\n\t\t},\n\n\t\t\"iconSunny\": {\n\t\t\t\"\\033[38;5;226m    \\\\   /    \\033[0m\",\n\t\t\t\"\\033[38;5;226m     .-.     \\033[0m\",\n\t\t\t\"\\033[38;5;226m  ― (   ) ―  \\033[0m\",\n\t\t\t\"\\033[38;5;226m     `-’     \\033[0m\",\n\t\t\t\"\\033[38;5;226m    /   \\\\    \\033[0m\",\n\t\t},\n\n\t\t\"iconPartlyCloudy\": {\n\t\t\t\"\\033[38;5;226m   \\\\  /\\033[0m      \",\n\t\t\t\"\\033[38;5;226m _ /\\\"\\\"\\033[38;5;250m.-.    \\033[0m\",\n\t\t\t\"\\033[38;5;226m   \\\\_\\033[38;5;250m(   ).  \\033[0m\",\n\t\t\t\"\\033[38;5;226m   /\\033[38;5;250m(___(__) \\033[0m\",\n\t\t\t\"             \",\n\t\t},\n\n\t\t\"iconCloudy\": {\n\t\t\t\"             \",\n\t\t\t\"\\033[38;5;250m     .--.    \\033[0m\",\n\t\t\t\"\\033[38;5;250m  .-(    ).  \\033[0m\",\n\t\t\t\"\\033[38;5;250m (___.__)__) \\033[0m\",\n\t\t\t\"             \",\n\t\t},\n\n\t\t\"iconVeryCloudy\": {\n\t\t\t\"             \",\n\t\t\t\"\\033[38;5;240;1m     .--.    \\033[0m\",\n\t\t\t\"\\033[38;5;240;1m  .-(    ).  \\033[0m\",\n\t\t\t\"\\033[38;5;240;1m (___.__)__) \\033[0m\",\n\t\t\t\"             \",\n\t\t},\n\n\t\t\"iconLightShowers\": {\n\t\t\t\"\\033[38;5;226m _`/\\\"\\\"\\033[38;5;250m.-.    \\033[0m\",\n\t\t\t\"\\033[38;5;226m  ,\\\\_\\033[38;5;250m(   ).  \\033[0m\",\n\t\t\t\"\\033[38;5;226m   /\\033[38;5;250m(___(__) \\033[0m\",\n\t\t\t\"\\033[38;5;111m     ‘ ‘ ‘ ‘ \\033[0m\",\n\t\t\t\"\\033[38;5;111m    ‘ ‘ ‘ ‘  \\033[0m\",\n\t\t},\n\n\t\t\"iconHeavyShowers\": {\n\t\t\t\"\\033[38;5;226m _`/\\\"\\\"\\033[38;5;240;1m.-.    \\033[0m\",\n\t\t\t\"\\033[38;5;226m  ,\\\\_\\033[38;5;240;1m(   ).  \\033[0m\",\n\t\t\t\"\\033[38;5;226m   /\\033[38;5;240;1m(___(__) \\033[0m\",\n\t\t\t\"\\033[38;5;21;1m   ‚‘‚‘‚‘‚‘  \\033[0m\",\n\t\t\t\"\\033[38;5;21;1m   ‚’‚’‚’‚’  \\033[0m\",\n\t\t},\n\n\t\t\"iconLightSnowShowers\": {\n\t\t\t\"\\033[38;5;226m _`/\\\"\\\"\\033[38;5;250m.-.    \\033[0m\",\n\t\t\t\"\\033[38;5;226m  ,\\\\_\\033[38;5;250m(   ).  \\033[0m\",\n\t\t\t\"\\033[38;5;226m   /\\033[38;5;250m(___(__) \\033[0m\",\n\t\t\t\"\\033[38;5;255m     *  *  * \\033[0m\",\n\t\t\t\"\\033[38;5;255m    *  *  *  \\033[0m\",\n\t\t},\n\n\t\t\"iconHeavySnowShowers\": {\n\t\t\t\"\\033[38;5;226m _`/\\\"\\\"\\033[38;5;240;1m.-.    \\033[0m\",\n\t\t\t\"\\033[38;5;226m  ,\\\\_\\033[38;5;240;1m(   ).  \\033[0m\",\n\t\t\t\"\\033[38;5;226m   /\\033[38;5;240;1m(___(__) \\033[0m\",\n\t\t\t\"\\033[38;5;255;1m    * * * *  \\033[0m\",\n\t\t\t\"\\033[38;5;255;1m   * * * *   \\033[0m\",\n\t\t},\n\n\t\t\"iconLightSleetShowers\": {\n\t\t\t\"\\033[38;5;226m _`/\\\"\\\"\\033[38;5;250m.-.    \\033[0m\",\n\t\t\t\"\\033[38;5;226m  ,\\\\_\\033[38;5;250m(   ).  \\033[0m\",\n\t\t\t\"\\033[38;5;226m   /\\033[38;5;250m(___(__) \\033[0m\",\n\t\t\t\"\\033[38;5;111m     ‘ \\033[38;5;255m*\\033[38;5;111m ‘ \\033[38;5;255m* \\033[0m\",\n\t\t\t\"\\033[38;5;255m    *\\033[38;5;111m ‘ \\033[38;5;255m*\\033[38;5;111m ‘  \\033[0m\",\n\t\t},\n\n\t\t\"iconThunderyShowers\": {\n\t\t\t\"\\033[38;5;226m _`/\\\"\\\"\\033[38;5;250m.-.    \\033[0m\",\n\t\t\t\"\\033[38;5;226m  ,\\\\_\\033[38;5;250m(   ).  \\033[0m\",\n\t\t\t\"\\033[38;5;226m   /\\033[38;5;250m(___(__) \\033[0m\",\n\t\t\t\"\\033[38;5;228;5m    ⚡\\033[38;5;111;25m‘‘\\033[38;5;228;5m⚡\\033[38;5;111;25m‘‘ \\033[0m\",\n\t\t\t\"\\033[38;5;111m    ‘ ‘ ‘ ‘  \\033[0m\",\n\t\t},\n\n\t\t\"iconThunderyHeavyRain\": {\n\t\t\t\"\\033[38;5;240;1m     .-.     \\033[0m\",\n\t\t\t\"\\033[38;5;240;1m    (   ).   \\033[0m\",\n\t\t\t\"\\033[38;5;240;1m   (___(__)  \\033[0m\",\n\t\t\t\"\\033[38;5;21;1m  ‚‘\\033[38;5;228;5m⚡\\033[38;5;21;25m‘‚\\033[38;5;228;5m⚡\\033[38;5;21;25m‚‘ \\033[0m\",\n\t\t\t\"\\033[38;5;21;1m  ‚’‚’\\033[38;5;228;5m⚡\\033[38;5;21;25m’‚’  \\033[0m\",\n\t\t},\n\n\t\t\"iconThunderySnowShowers\": {\n\t\t\t\"\\033[38;5;226m _`/\\\"\\\"\\033[38;5;250m.-.    \\033[0m\",\n\t\t\t\"\\033[38;5;226m  ,\\\\_\\033[38;5;250m(   ).  \\033[0m\",\n\t\t\t\"\\033[38;5;226m   /\\033[38;5;250m(___(__) \\033[0m\",\n\t\t\t\"\\033[38;5;255m     *\\033[38;5;228;5m⚡\\033[38;5;255;25m*\\033[38;5;228;5m⚡\\033[38;5;255;25m* \\033[0m\",\n\t\t\t\"\\033[38;5;255m    *  *  *  \\033[0m\",\n\t\t},\n\n\t\t\"iconLightRain\": {\n\t\t\t\"\\033[38;5;250m     .-.     \\033[0m\",\n\t\t\t\"\\033[38;5;250m    (   ).   \\033[0m\",\n\t\t\t\"\\033[38;5;250m   (___(__)  \\033[0m\",\n\t\t\t\"\\033[38;5;111m    ‘ ‘ ‘ ‘  \\033[0m\",\n\t\t\t\"\\033[38;5;111m   ‘ ‘ ‘ ‘   \\033[0m\",\n\t\t},\n\n\t\t\"iconHeavyRain\": {\n\t\t\t\"\\033[38;5;240;1m     .-.     \\033[0m\",\n\t\t\t\"\\033[38;5;240;1m    (   ).   \\033[0m\",\n\t\t\t\"\\033[38;5;240;1m   (___(__)  \\033[0m\",\n\t\t\t\"\\033[38;5;21;1m  ‚‘‚‘‚‘‚‘   \\033[0m\",\n\t\t\t\"\\033[38;5;21;1m  ‚’‚’‚’‚’   \\033[0m\",\n\t\t},\n\n\t\t\"iconLightSnow\": {\n\t\t\t\"\\033[38;5;250m     .-.     \\033[0m\",\n\t\t\t\"\\033[38;5;250m    (   ).   \\033[0m\",\n\t\t\t\"\\033[38;5;250m   (___(__)  \\033[0m\",\n\t\t\t\"\\033[38;5;255m    *  *  *  \\033[0m\",\n\t\t\t\"\\033[38;5;255m   *  *  *   \\033[0m\",\n\t\t},\n\n\t\t\"iconHeavySnow\": {\n\t\t\t\"\\033[38;5;240;1m     .-.     \\033[0m\",\n\t\t\t\"\\033[38;5;240;1m    (   ).   \\033[0m\",\n\t\t\t\"\\033[38;5;240;1m   (___(__)  \\033[0m\",\n\t\t\t\"\\033[38;5;255;1m   * * * *   \\033[0m\",\n\t\t\t\"\\033[38;5;255;1m  * * * *    \\033[0m\",\n\t\t},\n\n\t\t\"iconLightSleet\": {\n\t\t\t\"\\033[38;5;250m     .-.     \\033[0m\",\n\t\t\t\"\\033[38;5;250m    (   ).   \\033[0m\",\n\t\t\t\"\\033[38;5;250m   (___(__)  \\033[0m\",\n\t\t\t\"\\033[38;5;111m    ‘ \\033[38;5;255m*\\033[38;5;111m ‘ \\033[38;5;255m*  \\033[0m\",\n\t\t\t\"\\033[38;5;255m   *\\033[38;5;111m ‘ \\033[38;5;255m*\\033[38;5;111m ‘   \\033[0m\",\n\t\t},\n\n\t\t\"iconFog\": {\n\t\t\t\"             \",\n\t\t\t\"\\033[38;5;251m _ - _ - _ - \\033[0m\",\n\t\t\t\"\\033[38;5;251m  _ - _ - _  \\033[0m\",\n\t\t\t\"\\033[38;5;251m _ - _ - _ - \\033[0m\",\n\t\t\t\"             \",\n\t\t},\n\t}\n\n\treturn icon[name]\n}\n\nfunc codes() map[int][]string {\n\treturn map[int][]string{\n\t\t113: getIcon(\"iconSunny\"),\n\t\t116: getIcon(\"iconPartlyCloudy\"),\n\t\t119: getIcon(\"iconCloudy\"),\n\t\t122: getIcon(\"iconVeryCloudy\"),\n\t\t143: getIcon(\"iconFog\"),\n\t\t176: getIcon(\"iconLightShowers\"),\n\t\t179: getIcon(\"iconLightSleetShowers\"),\n\t\t182: getIcon(\"iconLightSleet\"),\n\t\t185: getIcon(\"iconLightSleet\"),\n\t\t200: getIcon(\"iconThunderyShowers\"),\n\t\t227: getIcon(\"iconLightSnow\"),\n\t\t230: getIcon(\"iconHeavySnow\"),\n\t\t248: getIcon(\"iconFog\"),\n\t\t260: getIcon(\"iconFog\"),\n\t\t263: getIcon(\"iconLightShowers\"),\n\t\t266: getIcon(\"iconLightRain\"),\n\t\t281: getIcon(\"iconLightSleet\"),\n\t\t284: getIcon(\"iconLightSleet\"),\n\t\t293: getIcon(\"iconLightRain\"),\n\t\t296: getIcon(\"iconLightRain\"),\n\t\t299: getIcon(\"iconHeavyShowers\"),\n\t\t302: getIcon(\"iconHeavyRain\"),\n\t\t305: getIcon(\"iconHeavyShowers\"),\n\t\t308: getIcon(\"iconHeavyRain\"),\n\t\t311: getIcon(\"iconLightSleet\"),\n\t\t314: getIcon(\"iconLightSleet\"),\n\t\t317: getIcon(\"iconLightSleet\"),\n\t\t320: getIcon(\"iconLightSnow\"),\n\t\t323: getIcon(\"iconLightSnowShowers\"),\n\t\t326: getIcon(\"iconLightSnowShowers\"),\n\t\t329: getIcon(\"iconHeavySnow\"),\n\t\t332: getIcon(\"iconHeavySnow\"),\n\t\t335: getIcon(\"iconHeavySnowShowers\"),\n\t\t338: getIcon(\"iconHeavySnow\"),\n\t\t350: getIcon(\"iconLightSleet\"),\n\t\t353: getIcon(\"iconLightShowers\"),\n\t\t356: getIcon(\"iconHeavyShowers\"),\n\t\t359: getIcon(\"iconHeavyRain\"),\n\t\t362: getIcon(\"iconLightSleetShowers\"),\n\t\t365: getIcon(\"iconLightSleetShowers\"),\n\t\t368: getIcon(\"iconLightSnowShowers\"),\n\t\t371: getIcon(\"iconHeavySnowShowers\"),\n\t\t374: getIcon(\"iconLightSleetShowers\"),\n\t\t377: getIcon(\"iconLightSleet\"),\n\t\t386: getIcon(\"iconThunderyShowers\"),\n\t\t389: getIcon(\"iconThunderyHeavyRain\"),\n\t\t392: getIcon(\"iconThunderySnowShowers\"),\n\t\t395: getIcon(\"iconHeavySnowShowers\"),\n\t}\n}\n"
  },
  {
    "path": "internal/view/v1/locale.go",
    "content": "package v1\n\n//nolint:funlen\nfunc locale() map[string]string {\n\treturn map[string]string{\n\t\t\"af\":     \"af_ZA\",\n\t\t\"am\":     \"am_ET\",\n\t\t\"ar\":     \"ar_TN\",\n\t\t\"az\":     \"az_AZ\",\n\t\t\"be\":     \"be_BY\",\n\t\t\"bg\":     \"bg_BG\",\n\t\t\"bn\":     \"bn_IN\",\n\t\t\"bs\":     \"bs_BA\",\n\t\t\"ca\":     \"ca_ES\",\n\t\t\"cs\":     \"cs_CZ\",\n\t\t\"cy\":     \"cy_GB\",\n\t\t\"da\":     \"da_DK\",\n\t\t\"de\":     \"de_DE\",\n\t\t\"el\":     \"el_GR\",\n\t\t\"eo\":     \"eo\",\n\t\t\"es\":     \"es_ES\",\n\t\t\"et\":     \"et_EE\",\n\t\t\"eu\":     \"eu_ES\",\n\t\t\"fa\":     \"fa_IR\",\n\t\t\"fi\":     \"fi_FI\",\n\t\t\"fr\":     \"fr_FR\",\n\t\t\"fy\":     \"fy_NL\",\n\t\t\"ga\":     \"ga_IE\",\n\t\t\"gl\":     \"gl_ES\",\n\t\t\"he\":     \"he_IL\",\n\t\t\"hi\":     \"hi_IN\",\n\t\t\"hr\":     \"hr_HR\",\n\t\t\"hu\":     \"hu_HU\",\n\t\t\"hy\":     \"hy_AM\",\n\t\t\"ia\":     \"ia\",\n\t\t\"id\":     \"id_ID\",\n\t\t\"is\":     \"is_IS\",\n\t\t\"it\":     \"it_IT\",\n\t\t\"ja\":     \"ja_JP\",\n\t\t\"jv\":     \"en_US\",\n\t\t\"ka\":     \"ka_GE\",\n\t\t\"kk\":     \"kk_KZ\",\n\t\t\"ko\":     \"ko_KR\",\n\t\t\"ky\":     \"ky_KG\",\n\t\t\"lt\":     \"lt_LT\",\n\t\t\"lv\":     \"lv_LV\",\n\t\t\"mg\":     \"mg_MG\",\n\t\t\"mk\":     \"mk_MK\",\n\t\t\"ml\":     \"ml_IN\",\n\t\t\"mr\":     \"mr_IN\",\n\t\t\"nb\":     \"nb_NO\",\n\t\t\"nl\":     \"nl_NL\",\n\t\t\"nn\":     \"nn_NO\",\n\t\t\"oc\":     \"oc_FR\",\n\t\t\"pl\":     \"pl_PL\",\n\t\t\"pt-br\":  \"pt_BR\",\n\t\t\"pt\":     \"pt_PT\",\n\t\t\"ro\":     \"ro_RO\",\n\t\t\"ru\":     \"ru_RU\",\n\t\t\"sk\":     \"sk_SK\",\n\t\t\"sl\":     \"sl_SI\",\n\t\t\"sr-lat\": \"sr_RS@latin\",\n\t\t\"sr\":     \"sr_RS\",\n\t\t\"sv\":     \"sv_SE\",\n\t\t\"sw\":     \"sw_KE\",\n\t\t\"ta\":     \"ta_IN\",\n\t\t\"th\":     \"th_TH\",\n\t\t\"tr\":     \"tr_TR\",\n\t\t\"uk\":     \"uk_UA\",\n\t\t\"uz\":     \"uz_UZ\",\n\t\t\"vi\":     \"vi_VN\",\n\t\t\"zh-cn\":  \"zh_CN\",\n\t\t\"zh-tw\":  \"zh_TW\",\n\t\t\"zh\":     \"zh_CN\",\n\t\t\"zu\":     \"zu_ZA\",\n\t}\n}\n\n//nolint:funlen\nfunc localizedCaption() map[string]string {\n\treturn map[string]string{\n\t\t\"af\":     \"Weer verslag vir:\",\n\t\t\"am\":     \"የአየር ሁኔታ ዘገባ ለ ፥\",\n\t\t\"ar\":     \"تقرير حالة ألطقس\",\n\t\t\"az\":     \"Hava proqnozu:\",\n\t\t\"be\":     \"Прагноз надвор'я для:\",\n\t\t\"bg\":     \"Прогноза за времето в:\",\n\t\t\"bn\":     \"আবহাওয়া সঙ্ক্রান্ত তথ্য\",\n\t\t\"bs\":     \"Vremenske prognoze za:\",\n\t\t\"ca\":     \"Informe del temps per a:\",\n\t\t\"cs\":     \"Předpověď počasí pro:\",\n\t\t\"cy\":     \"Adroddiad tywydd ar gyfer:\",\n\t\t\"da\":     \"Vejret i:\",\n\t\t\"de\":     \"Wetterbericht für:\",\n\t\t\"el\":     \"Πρόγνωση καιρού για:\",\n\t\t\"eo\":     \"Veterprognozo por:\",\n\t\t\"es\":     \"El tiempo en:\",\n\t\t\"et\":     \"Ilmaprognoos:\",\n\t\t\"eu\":     \"Eguraldia:\",\n\t\t\"fa\":     \"اوه و بآ تیعضو شرازگ\",\n\t\t\"fi\":     \"Säätiedotus:\",\n\t\t\"fr\":     \"Prévisions météo pour:\",\n\t\t\"fy\":     \"Waarberjocht foar:\",\n\t\t\"ga\":     \"Réamhaisnéis na haimsire do:\",\n\t\t\"gl\":     \"Previsión do tempo en:\",\n\t\t\"he\":     \":ריוואה גזמ תיזחת\",\n\t\t\"hi\":     \"मौसम की जानकारी\",\n\t\t\"hr\":     \"Vremenska prognoza za:\",\n\t\t\"hu\":     \"Időjárás előrejelzés:\",\n\t\t\"hy\":     \"Եղանակի տեսություն:\",\n\t\t\"ia\":     \"Le tempore a:\",\n\t\t\"id\":     \"Prakiraan cuaca:\",\n\t\t\"it\":     \"Previsioni meteo:\",\n\t\t\"is\":     \"Veðurskýrsla fyrir:\",\n\t\t\"ja\":     \"天気予報：\",\n\t\t\"jv\":     \"Weather forecast for:\",\n\t\t\"ka\":     \"ამინდის პროგნოზი:\",\n\t\t\"kk\":     \"Ауа райы:\",\n\t\t\"ko\":     \"일기 예보：\",\n\t\t\"ky\":     \"Аба ырайы:\",\n\t\t\"lt\":     \"Orų prognozė:\",\n\t\t\"lv\":     \"Laika ziņas:\",\n\t\t\"mk\":     \"Прогноза за времето во:\",\n\t\t\"ml\":     \"കാലാവസ്ഥ റിപ്പോർട്ട്:\",\n\t\t\"mr\":     \"हवामानाचा अंदाज:\",\n\t\t\"nb\":     \"Værmelding for:\",\n\t\t\"nl\":     \"Weerbericht voor:\",\n\t\t\"nn\":     \"Vêrmelding for:\",\n\t\t\"oc\":     \"Previsions metèo per:\",\n\t\t\"pl\":     \"Pogoda w:\",\n\t\t\"pt\":     \"Previsão do tempo para:\",\n\t\t\"pt-br\":  \"Previsão do tempo para:\",\n\t\t\"ro\":     \"Prognoza meteo pentru:\",\n\t\t\"ru\":     \"Прогноз погоды:\",\n\t\t\"sk\":     \"Predpoveď počasia pre:\",\n\t\t\"sl\":     \"Vremenska napoved za\",\n\t\t\"sr\":     \"Временска прогноза за:\",\n\t\t\"sr-lat\": \"Vremenska prognoza za:\",\n\t\t\"sv\":     \"Väderleksprognos för:\",\n\t\t\"sw\":     \"Ripoti ya hali ya hewa, jiji la:\",\n\t\t\"ta\":     \"வானிலை அறிக்கை\",\n\t\t\"te\":     \"వాతావరణ సమాచారము:\",\n\t\t\"th\":     \"รายงานสภาพอากาศ:\",\n\t\t\"tr\":     \"Hava beklentisi:\",\n\t\t\"uk\":     \"Прогноз погоди для:\",\n\t\t\"uz\":     \"Ob-havo bashorati:\",\n\t\t\"vi\":     \"Báo cáo thời tiết:\",\n\t\t\"zu\":     \"Isimo sezulu:\",\n\t\t\"zh\":     \"天气预报：\",\n\t\t\"zh-cn\":  \"天气预报：\",\n\t\t\"zh-tw\":  \"天氣預報：\",\n\t\t\"mg\":     \"Vinavina toetr'andro hoan'ny:\",\n\t}\n}\n\n//nolint:misspell,funlen\nfunc daytimeTranslation() map[string][]string {\n\treturn map[string][]string{\n\t\t\"af\":     {\"Oggend\", \"Middag\", \"Vroegaand\", \"Laatnag\"},\n\t\t\"am\":     {\"ጠዋት\", \"ከሰዓት በኋላ\", \"ምሽት\", \"ሌሊት\"},\n\t\t\"ar\":     {\"ﺎﻠﻠﻴﻟ\", \"ﺎﻠﻤﺳﺍﺀ\", \"ﺎﻠﻈﻫﺭ\", \"ﺎﻠﺼﺑﺎﺣ\"},\n\t\t\"az\":     {\"Səhər\", \"Gün\", \"Axşam\", \"Gecə\"},\n\t\t\"be\":     {\"Раніца\", \"Дзень\", \"Вечар\", \"Ноч\"},\n\t\t\"bg\":     {\"Сутрин\", \"Обяд\", \"Вечер\", \"Нощ\"},\n\t\t\"bn\":     {\"সকাল\", \"দুপুর\", \"সন্ধ্যা\", \"রাত্রি\"},\n\t\t\"bs\":     {\"Ujutro\", \"Dan\", \"Večer\", \"Noć\"},\n\t\t\"cs\":     {\"Ráno\", \"Ve dne\", \"Večer\", \"V noci\"},\n\t\t\"ca\":     {\"Matí\", \"Dia\", \"Tarda\", \"Nit\"},\n\t\t\"cy\":     {\"Bore\", \"Dydd\", \"Hwyr\", \"Nos\"},\n\t\t\"da\":     {\"Morgen\", \"Middag\", \"Aften\", \"Nat\"},\n\t\t\"de\":     {\"Morgen\", \"Mittag\", \"Abend\", \"Nacht\"},\n\t\t\"el\":     {\"Πρωί\", \"Μεσημέρι\", \"Απόγευμα\", \"Βράδυ\"},\n\t\t\"en\":     {\"Morning\", \"Noon\", \"Evening\", \"Night\"},\n\t\t\"eo\":     {\"Mateno\", \"Tago\", \"Vespero\", \"Nokto\"},\n\t\t\"es\":     {\"Mañana\", \"Mediodía\", \"Tarde\", \"Noche\"},\n\t\t\"et\":     {\"Hommik\", \"Päev\", \"Õhtu\", \"Öösel\"},\n\t\t\"eu\":     {\"Goiza\", \"Eguerdia\", \"Arratsaldea\", \"Gaua\"},\n\t\t\"fa\":     {\"حبص\", \"رهظ\", \"رصع\", \"بش\"},\n\t\t\"fi\":     {\"Aamu\", \"Keskipäivä\", \"Ilta\", \"Yö\"},\n\t\t\"fr\":     {\"Matin\", \"Après-midi\", \"Soir\", \"Nuit\"},\n\t\t\"fy\":     {\"Moarns\", \"Middeis\", \"Jûns\", \"Nachts\"},\n\t\t\"ga\":     {\"Maidin\", \"Nóin\", \"Tráthnóna\", \"Oíche\"},\n\t\t\"gl\":     {\"Mañá\", \"Mediodía\", \"Tarde\", \"Noite\"},\n\t\t\"he\":     {\"רקוב\", \"םוֹיְ\", \"ברֶעֶ\", \"הלָיְלַ\"},\n\t\t\"hi\":     {\"प्रातःकाल\", \"दोपहर\", \"सायंकाल\", \"रात\"},\n\t\t\"hr\":     {\"Jutro\", \"Dan\", \"Večer\", \"Noć\"},\n\t\t\"hu\":     {\"Reggel\", \"Dél\", \"Este\", \"Éjszaka\"},\n\t\t\"hy\":     {\"Առավոտ\", \"Կեսօր\", \"Երեկո\", \"Գիշեր\"},\n\t\t\"ia\":     {\"Matino\", \"Mediedie\", \"Vespere\", \"Nocte\"},\n\t\t\"id\":     {\"Pagi\", \"Hari\", \"Petang\", \"Malam\"},\n\t\t\"it\":     {\"Mattina\", \"Pomeriggio\", \"Sera\", \"Notte\"},\n\t\t\"is\":     {\"Morgunn\", \"Dagur\", \"Kvöld\", \"Nótt\"},\n\t\t\"ja\":     {\"朝\", \"昼\", \"夕\", \"夜\"},\n\t\t\"jv\":     {\"Morning\", \"Noon\", \"Evening\", \"Night\"},\n\t\t\"ka\":     {\"დილა\", \"დღე\", \"საღამო\", \"ღამე\"},\n\t\t\"kk\":     {\"Таң\", \"Күндіз\", \"Кеш\", \"Түн\"},\n\t\t\"ko\":     {\"아침\", \"낮\", \"저녁\", \"밤\"},\n\t\t\"ky\":     {\"Эртең\", \"Күн\", \"Кеч\", \"Түн\"},\n\t\t\"lt\":     {\"Rytas\", \"Diena\", \"Vakaras\", \"Naktis\"},\n\t\t\"lv\":     {\"Rīts\", \"Diena\", \"Vakars\", \"Nakts\"},\n\t\t\"mk\":     {\"Утро\", \"Пладне\", \"Вечер\", \"Ноќ\"},\n\t\t\"ml\":     {\"രാവിലെ\", \"മധ്യാഹ്നം\", \"വൈകുന്നേരം\", \"രാത്രി\"},\n\t\t\"mr\":     {\"सकाळ\", \"दुपार\", \"संध्याकाळ\", \"रात्र\"},\n\t\t\"nl\":     {\"'s Ochtends\", \"'s Middags\", \"'s Avonds\", \"'s Nachts\"},\n\t\t\"nb\":     {\"Morgen\", \"Middag\", \"Kveld\", \"Natt\"},\n\t\t\"nn\":     {\"Morgon\", \"Middag\", \"Kveld\", \"Natt\"},\n\t\t\"oc\":     {\"Matin\", \"Jorn\", \"Vèspre\", \"Nuèch\"},\n\t\t\"pl\":     {\"Ranek\", \"Dzień\", \"Wieczór\", \"Noc\"},\n\t\t\"pt\":     {\"Manhã\", \"Meio-dia\", \"Tarde\", \"Noite\"},\n\t\t\"pt-br\":  {\"Manhã\", \"Meio-dia\", \"Tarde\", \"Noite\"},\n\t\t\"ro\":     {\"Dimineaţă\", \"Amiază\", \"Seară\", \"Noapte\"},\n\t\t\"ru\":     {\"Утро\", \"День\", \"Вечер\", \"Ночь\"},\n\t\t\"sk\":     {\"Ráno\", \"Cez deň\", \"Večer\", \"V noci\"},\n\t\t\"sl\":     {\"Jutro\", \"Dan\", \"Večer\", \"Noč\"},\n\t\t\"sr\":     {\"Јутро\", \"Подне\", \"Вече\", \"Ноћ\"},\n\t\t\"sr-lat\": {\"Jutro\", \"Podne\", \"Veče\", \"Noć\"},\n\t\t\"sv\":     {\"Morgon\", \"Eftermiddag\", \"Kväll\", \"Natt\"},\n\t\t\"sw\":     {\"Asubuhi\", \"Adhuhuri\", \"Jioni\", \"Usiku\"},\n\t\t\"ta\":     {\"காலை\", \"நண்பகல்\", \"சாயங்காலம்\", \"இரவு\"},\n\t\t\"te\":     {\"ఉదయం\", \"రోజు\", \"సాయంత్రం\", \"రాత్రి\"},\n\t\t\"th\":     {\"เช้า\", \"วัน\", \"เย็น\", \"คืน\"},\n\t\t\"tr\":     {\"Sabah\", \"Öğle\", \"Akşam\", \"Gece\"},\n\t\t\"uk\":     {\"Ранок\", \"День\", \"Вечір\", \"Ніч\"},\n\t\t\"uz\":     {\"Ertalab\", \"Kunduzi\", \"Kechqurun\", \"Kecha\"},\n\t\t\"vi\":     {\"Sáng\", \"Trưa\", \"Chiều\", \"Tối\"},\n\t\t\"zh\":     {\"早上\", \"中午\", \"傍晚\", \"夜间\"},\n\t\t\"zh-cn\":  {\"早上\", \"中午\", \"傍晚\", \"夜间\"},\n\t\t\"zh-tw\":  {\"早上\", \"中午\", \"傍晚\", \"夜間\"},\n\t\t\"zu\":     {\"Morning\", \"Noon\", \"Evening\", \"Night\"},\n\t\t\"mg\":     {\"Maraina\", \"Tolakandro\", \"Ariva\", \"Alina\"},\n\t}\n}\n\nfunc unitTemp() map[bool]string {\n\treturn map[bool]string{\n\t\tfalse: \"C\",\n\t\ttrue:  \"F\",\n\t}\n}\n\nfunc localizedRain() map[string]map[bool]string {\n\treturn map[string]map[bool]string{\n\t\t\"en\": {\n\t\t\tfalse: \"mm\",\n\t\t\ttrue:  \"in\",\n\t\t},\n\t\t\"be\": {\n\t\t\tfalse: \"мм\",\n\t\t\ttrue:  \"in\",\n\t\t},\n\t\t\"ru\": {\n\t\t\tfalse: \"мм\",\n\t\t\ttrue:  \"in\",\n\t\t},\n\t\t\"uk\": {\n\t\t\tfalse: \"мм\",\n\t\t\ttrue:  \"in\",\n\t\t},\n\t}\n}\n\nfunc localizedVis() map[string]map[bool]string {\n\treturn map[string]map[bool]string{\n\t\t\"en\": {\n\t\t\tfalse: \"km\",\n\t\t\ttrue:  \"mi\",\n\t\t},\n\t\t\"be\": {\n\t\t\tfalse: \"км\",\n\t\t\ttrue:  \"mi\",\n\t\t},\n\t\t\"ru\": {\n\t\t\tfalse: \"км\",\n\t\t\ttrue:  \"mi\",\n\t\t},\n\t\t\"uk\": {\n\t\t\tfalse: \"км\",\n\t\t\ttrue:  \"mi\",\n\t\t},\n\t}\n}\n\nfunc localizedWind() map[string]map[int]string {\n\treturn map[string]map[int]string{\n\t\t\"en\": {\n\t\t\t0: \"km/h\",\n\t\t\t1: \"mph\",\n\t\t\t2: \"m/s\",\n\t\t},\n\t\t\"be\": {\n\t\t\t0: \"км/г\",\n\t\t\t1: \"mph\",\n\t\t\t2: \"м/c\",\n\t\t},\n\t\t\"ru\": {\n\t\t\t0: \"км/ч\",\n\t\t\t1: \"mph\",\n\t\t\t2: \"м/c\",\n\t\t},\n\t\t\"tr\": {\n\t\t\t0: \"km/sa\",\n\t\t\t1: \"mph\",\n\t\t\t2: \"m/s\",\n\t\t},\n\t\t\"uk\": {\n\t\t\t0: \"км/год\",\n\t\t\t1: \"mph\",\n\t\t\t2: \"м/c\",\n\t\t},\n\t}\n}\n\nfunc unitWind(unit int, lang string) string {\n\ttranslation, ok := localizedWind()[lang]\n\tif !ok {\n\t\ttranslation = localizedWind()[\"en\"]\n\t}\n\n\treturn translation[unit]\n}\n\nfunc unitVis(unit bool, lang string) string {\n\ttranslation, ok := localizedVis()[lang]\n\tif !ok {\n\t\ttranslation = localizedVis()[\"en\"]\n\t}\n\n\treturn translation[unit]\n}\n\nfunc unitRain(unit bool, lang string) string {\n\ttranslation, ok := localizedRain()[lang]\n\tif !ok {\n\t\ttranslation = localizedRain()[\"en\"]\n\t}\n\n\treturn translation[unit]\n}\n"
  },
  {
    "path": "internal/view/v1/view1.go",
    "content": "package v1\n\nimport (\n\t\"math\"\n\t\"time\"\n\n\t\"github.com/klauspost/lctime\"\n)\n\nfunc slotTimes() []int {\n\treturn []int{9 * 60, 12 * 60, 18 * 60, 22 * 60}\n}\n\n//nolint:funlen,gocognit,cyclop\nfunc (g *global) printDay(w weather) ([]string, error) {\n\tvar (\n\t\tret      = []string{}\n\t\tdateName string\n\t\tnames    string\n\t)\n\n\thourly := w.Hourly\n\tfor i := range ret {\n\t\tret[i] = \"│\"\n\t}\n\n\t// find hourly data which fits the desired times of day best\n\tvar slots [slotcount]cond\n\tfor _, h := range hourly {\n\t\tc := int(math.Mod(float64(h.Time), 100)) + 60*(h.Time/100)\n\t\tfor i, s := range slots {\n\t\t\tif math.Abs(float64(c-slotTimes()[i])) < math.Abs(float64(s.Time-slotTimes()[i])) {\n\t\t\t\th.Time = c\n\t\t\t\tslots[i] = h\n\t\t\t}\n\t\t}\n\t}\n\n\tif g.config.RightToLeft {\n\t\tslots[0], slots[3] = slots[3], slots[0]\n\t\tslots[1], slots[2] = slots[2], slots[1]\n\t}\n\n\tfor i, s := range slots {\n\t\tif g.config.Narrow {\n\t\t\tif i == 0 || i == 2 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tret = g.formatCond(ret, s, false)\n\t\tfor i := range ret {\n\t\t\tret[i] += \"│\"\n\t\t}\n\t}\n\n\td, _ := time.Parse(\"2006-01-02\", w.Date)\n\t// dateFmt := \"┤ \" + d.Format(\"Mon 02. Jan\") + \" ├\"\n\n\tif val, ok := locale()[g.config.Lang]; ok {\n\t\terr := lctime.SetLocale(val)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t} else {\n\t\terr := lctime.SetLocale(\"en_US\")\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tif g.config.RightToLeft {\n\t\tdow := lctime.Strftime(\"%a\", d)\n\t\tday := lctime.Strftime(\"%d\", d)\n\t\tmonth := lctime.Strftime(\"%b\", d)\n\t\tdateName = reverse(month) + \" \" + day + \" \" + reverse(dow)\n\t} else {\n\t\tswitch g.config.Lang {\n\t\tcase \"ko\":\n\t\t\tdate_format = \"%b %d일 %a\"\n\t\tcase \"lv\":\n\t\t\tdate_format = \"%a., %d. %b.\"\n\t\tcase \"zh\", \"zh-cn\", \"zh-tw\":\n\t\t\tdate_format = \"%b%d日%A\"\n\t\tdefault:\n\t\t\tdate_format = \"%a %d %b\"\n\t\t}\n\t\tdateName = lctime.Strftime(date_format, d)\n\t}\n\n\tdateFmt := \"┤\" + justifyCenter(dateName, 12) + \"├\"\n\n\ttrans := daytimeTranslation()[\"en\"]\n\tif t, ok := daytimeTranslation()[g.config.Lang]; ok {\n\t\ttrans = t\n\t}\n\tif g.config.Narrow {\n\t\tnames := \"│      \" + justifyCenter(trans[1], 16) +\n\t\t\t\"└──────┬──────┘\" + justifyCenter(trans[3], 16) + \"      │\"\n\n\t\tret = append([]string{\n\t\t\t\"                        ┌─────────────┐                        \",\n\t\t\t\"┌───────────────────────\" + dateFmt + \"───────────────────────┐\",\n\t\t\tnames,\n\t\t\t\"├──────────────────────────────┼──────────────────────────────┤\",\n\t\t},\n\t\t\tret...)\n\n\t\treturn append(ret,\n\t\t\t\t\"└──────────────────────────────┴──────────────────────────────┘\"),\n\t\t\tnil\n\t}\n\n\tif g.config.RightToLeft {\n\t\tnames = \"│\" + justifyCenter(trans[3], 29) + \"│      \" + justifyCenter(trans[2], 16) +\n\t\t\t\"└──────┬──────┘\" + justifyCenter(trans[1], 16) + \"      │\" + justifyCenter(trans[0], 29) + \"│\"\n\t} else {\n\t\tnames = \"│\" + justifyCenter(trans[0], 29) + \"│      \" + justifyCenter(trans[1], 16) +\n\t\t\t\"└──────┬──────┘\" + justifyCenter(trans[2], 16) + \"      │\" + justifyCenter(trans[3], 29) + \"│\"\n\t}\n\n\t//nolint:lll\n\tret = append([]string{\n\t\t\"                                                       ┌─────────────┐                                                       \",\n\t\t\"┌──────────────────────────────┬───────────────────────\" + dateFmt + \"───────────────────────┬──────────────────────────────┐\",\n\t\tnames,\n\t\t\"├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤\",\n\t},\n\t\tret...)\n\n\t//nolint:lll\n\treturn append(ret,\n\t\t\t\"└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘\"),\n\t\tnil\n}\n"
  },
  {
    "path": "lib/airports.py",
    "content": "import csv\n\nAIRPORTS_DAT_FILE = \"/home/igor/wttrin-geo/share/airports.dat\"\n\n\ndef load_aiports_index():\n    file_ = open(AIRPORTS_DAT_FILE, \"r\")\n    reader = csv.reader(file_)\n    airport_index = {}\n\n    for line in reader:\n        airport_index[line[4]] = line\n\n    return airport_index\n\n\nAIRPORTS_INDEX = load_aiports_index()\n\n\ndef get_airport_gps_location(iata_code):\n    if iata_code in AIRPORTS_INDEX:\n        airport = AIRPORTS_INDEX[iata_code]\n        return \"%s,%s airport\" % (airport[6], airport[7])  # , airport[1])\n    return None\n"
  },
  {
    "path": "lib/buttons.py",
    "content": "TWITTER_BUTTON = \"\"\"\n<a href=\"https://twitter.com/igor_chubin?ref_src=twsrc%5Etfw\" class=\"twitter-follow-button\" data-show-count=\"false\">Follow @igor_chubin</a><script async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\n\"\"\"\n\nGITHUB_BUTTON = \"\"\"\n<a aria-label=\"Star chubin/wttr.in on GitHub\" data-count-aria-label=\"# stargazers on GitHub\" data-count-api=\"/repos/chubin/wttr.in#stargazers_count\" data-count-href=\"/chubin/wttr.in/stargazers\" data-show-count=\"true\" data-icon=\"octicon-star\" href=\"https://github.com/chubin/wttr.in\" class=\"github-button\">wttr.in</a>\n\"\"\"\n\nGITHUB_BUTTON_2 = \"\"\"\n<!-- Place this tag where you want the button to render. -->\n<a aria-label=\"Star schachmat/wego on GitHub\" data-count-aria-label=\"# stargazers on GitHub\" data-count-api=\"/repos/schachmat/wego#stargazers_count\" data-count-href=\"/schachmat/wego/stargazers\" data-show-count=\"true\" data-icon=\"octicon-star\" href=\"https://github.com/schachmat/wego\" class=\"github-button\">wego</a>\n\"\"\"\n\nGITHUB_BUTTON_3 = \"\"\"\n<!-- Place this tag where you want the button to render. -->\n<a aria-label=\"Star chubin/pyphoon on GitHub\" data-count-aria-label=\"# stargazers on GitHub\" data-count-api=\"/repos/chubin/pyphoon#stargazers_count\" data-count-href=\"/chubin/pyphoon/stargazers\" data-show-count=\"true\" data-icon=\"octicon-star\" href=\"https://github.com/chubin/pyphoon\" class=\"github-button\">pyphoon</a>\n\"\"\"\n\nGITHUB_BUTTON_FOOTER = \"\"\"\n<!-- Place this tag right after the last button or just before your close body tag. -->\n<script async defer id=\"github-bjs\" src=\"https://buttons.github.io/buttons.js\"></script>\n\"\"\"\n\n\ndef add_buttons(output):\n    \"\"\"\n    Add buttons to html output\n    \"\"\"\n\n    return output.replace(\n        \"</body>\",\n        (\n            TWITTER_BUTTON\n            + GITHUB_BUTTON\n            + GITHUB_BUTTON_3\n            + GITHUB_BUTTON_2\n            + GITHUB_BUTTON_FOOTER\n        )\n        + \"</body>\",\n    )\n"
  },
  {
    "path": "lib/cache.py",
    "content": "\"\"\"\nLRU-Cache implementation for formatted (`format=`) answers\n\"\"\"\n\nimport datetime\nimport re\nimport time\nimport os\nimport hashlib\nimport random\n\nimport pytz\nimport pylru\n\nfrom globals import LRU_CACHE\n\nCACHE_SIZE = 10000\nCACHE = pylru.lrucache(CACHE_SIZE)\n\n# strings longer than this are stored not in ram\n# but in the file cache\nMIN_SIZE_FOR_FILECACHE = 80\n\n\ndef _update_answer(answer):\n    def _now_in_tz(timezone):\n        return datetime.datetime.now(pytz.timezone(timezone)).strftime(\"%H:%M:%S%z\")\n\n    if isinstance(answer, str) and \"%{{NOW(\" in answer:\n        answer = re.sub(\n            r\"%{{NOW\\(([^}]*)\\)}}\", lambda x: _now_in_tz(x.group(1)), answer\n        )\n\n    return answer\n\n\ndef get_signature(user_agent, query_string, client_ip_address, lang):\n    \"\"\"\n    Get cache signature based on `user_agent`, `url_string`,\n    `lang`, and `client_ip_address`\n    Return `None` if query should not be cached.\n    \"\"\"\n\n    if \"?\" in query_string:\n        location = query_string.split(\"?\", 1)[0]\n    else:\n        location = query_string\n    if location.startswith(\"http://\"):\n        location = location[7:]\n    elif location.startswith(\"https://\"):\n        location = location[8:]\n    if \":\" in location:\n        return None\n\n    signature = \"%s:%s:%s:%s\" % (user_agent, query_string, client_ip_address, lang)\n    print(signature)\n    return signature\n\n\ndef get(signature):\n    \"\"\"\n    If `update_answer` is not True, return answer as it is\n    stored in the cache. Otherwise update it, using\n    the `_update_answer` function.\n    \"\"\"\n\n    if not signature:\n        return None\n\n    value_record = CACHE.get(signature)\n    if not value_record:\n        return None\n\n    value = value_record[\"val\"]\n    expiry = value_record[\"expiry\"]\n    if value and time.time() < expiry:\n        if value.startswith(\"file:\") or value.startswith(\"bfile:\"):\n            value = _read_from_file(signature, sighash=value)\n            if not value:\n                return None\n        return _update_answer(value)\n    return None\n\n\ndef _randint(minimum, maximum):\n    return random.randrange(maximum - minimum)\n\n\ndef store(signature, value):\n    \"\"\"\n    Store in cache `value` for `signature`\n    \"\"\"\n    if not signature:\n        return _update_answer(value)\n\n    if len(value) >= MIN_SIZE_FOR_FILECACHE:\n        value_to_store = _store_in_file(signature, value)\n    else:\n        value_to_store = value\n\n    value_record = {\n        \"val\": value_to_store,\n        \"expiry\": time.time() + _randint(1000, 2000),\n    }\n\n    CACHE[signature] = value_record\n\n    return _update_answer(value)\n\n\ndef _hash(signature):\n    return hashlib.md5(signature.encode(\"utf-8\")).hexdigest()\n\n\ndef _store_in_file(signature, value):\n    \"\"\"Store `value` for `signature` in cache file.\n    Return file name (signature_hash) as the result.\n    `value` can be string as well as bytes.\n    Returned filename is prefixed with \"file:\" (for text files)\n    or \"bfile:\" (for binary files).\n    \"\"\"\n\n    signature_hash = _hash(signature)\n    filename = os.path.join(LRU_CACHE, signature_hash)\n    if not os.path.exists(LRU_CACHE):\n        os.makedirs(LRU_CACHE)\n\n    if isinstance(value, bytes):\n        mode = \"wb\"\n        signature_hash = \"bfile:%s\" % signature_hash\n    else:\n        mode = \"w\"\n        signature_hash = \"file:%s\" % signature_hash\n\n    with open(filename, mode) as f_cache:\n        f_cache.write(value)\n    return signature_hash\n\n\ndef _read_from_file(signature, sighash=None):\n    \"\"\"Read value for `signature` from cache file,\n    or return None if file is not found.\n    If `sighash` is specified, do not calculate file name\n    from signature, but use `sighash` instead.\n\n    `sigash` can be prefixed with \"file:\" (for text files)\n    or \"bfile:\" (for binary files).\n    \"\"\"\n\n    mode = \"r\"\n    if sighash:\n        if sighash.startswith(\"file:\"):\n            sighash = sighash[5:]\n        elif sighash.startswith(\"bfile:\"):\n            sighash = sighash[6:]\n            mode = \"rb\"\n    else:\n        sighash = _hash(signature)\n\n    filename = os.path.join(LRU_CACHE, sighash)\n    if not os.path.exists(filename):\n        return None\n\n    with open(filename, mode) as f_cache:\n        return f_cache.read()\n"
  },
  {
    "path": "lib/constants.py",
    "content": "# vim: fileencoding=utf-8\n\nWWO_CODE = {\n    \"113\": \"Sunny\",\n    \"116\": \"PartlyCloudy\",\n    \"119\": \"Cloudy\",\n    \"122\": \"VeryCloudy\",\n    \"143\": \"Fog\",\n    \"176\": \"LightShowers\",\n    \"179\": \"LightSleetShowers\",\n    \"182\": \"LightSleet\",\n    \"185\": \"LightSleet\",\n    \"200\": \"ThunderyShowers\",\n    \"227\": \"LightSnow\",\n    \"230\": \"HeavySnow\",\n    \"248\": \"Fog\",\n    \"260\": \"Fog\",\n    \"263\": \"LightShowers\",\n    \"266\": \"LightRain\",\n    \"281\": \"LightSleet\",\n    \"284\": \"LightSleet\",\n    \"293\": \"LightRain\",\n    \"296\": \"LightRain\",\n    \"299\": \"HeavyShowers\",\n    \"302\": \"HeavyRain\",\n    \"305\": \"HeavyShowers\",\n    \"308\": \"HeavyRain\",\n    \"311\": \"LightSleet\",\n    \"314\": \"LightSleet\",\n    \"317\": \"LightSleet\",\n    \"320\": \"LightSnow\",\n    \"323\": \"LightSnowShowers\",\n    \"326\": \"LightSnowShowers\",\n    \"329\": \"HeavySnow\",\n    \"332\": \"HeavySnow\",\n    \"335\": \"HeavySnowShowers\",\n    \"338\": \"HeavySnow\",\n    \"350\": \"LightSleet\",\n    \"353\": \"LightShowers\",\n    \"356\": \"HeavyShowers\",\n    \"359\": \"HeavyRain\",\n    \"362\": \"LightSleetShowers\",\n    \"365\": \"LightSleetShowers\",\n    \"368\": \"LightSnowShowers\",\n    \"371\": \"HeavySnowShowers\",\n    \"374\": \"LightSleetShowers\",\n    \"377\": \"LightSleet\",\n    \"386\": \"ThunderyShowers\",\n    \"389\": \"ThunderyHeavyRain\",\n    \"392\": \"ThunderySnowShowers\",\n    \"395\": \"HeavySnowShowers\",\n}\n\nWEATHER_SYMBOL = {\n    \"Unknown\": \"✨\",\n    \"Cloudy\": \"☁️\",\n    \"Fog\": \"🌫\",\n    \"HeavyRain\": \"🌧\",\n    \"HeavyShowers\": \"🌧\",\n    \"HeavySnow\": \"❄️\",\n    \"HeavySnowShowers\": \"❄️\",\n    \"LightRain\": \"🌦\",\n    \"LightShowers\": \"🌦\",\n    \"LightSleet\": \"🌧\",\n    \"LightSleetShowers\": \"🌧\",\n    \"LightSnow\": \"🌨\",\n    \"LightSnowShowers\": \"🌨\",\n    \"PartlyCloudy\": \"⛅️\",\n    \"Sunny\": \"☀️\",\n    \"ThunderyHeavyRain\": \"🌩\",\n    \"ThunderyShowers\": \"⛈\",\n    \"ThunderySnowShowers\": \"⛈\",\n    \"VeryCloudy\": \"☁️\",\n}\n\nWEATHER_SYMBOL_WIDTH_VTE = {\n    \"✨\": 2,\n    \"☁️\": 1,\n    \"🌫\": 2,\n    \"🌧\": 2,\n    \"🌧\": 2,\n    \"❄️\": 1,\n    \"❄️\": 1,\n    \"🌦\": 1,\n    \"🌦\": 1,\n    \"🌧\": 1,\n    \"🌧\": 1,\n    \"🌨\": 2,\n    \"🌨\": 2,\n    \"⛅️\": 2,\n    \"☀️\": 1,\n    \"🌩\": 2,\n    \"⛈\": 1,\n    \"⛈\": 1,\n    \"☁️\": 1,\n}\n\nWIND_DIRECTION = [\n    \"↓\",\n    \"↙\",\n    \"←\",\n    \"↖\",\n    \"↑\",\n    \"↗\",\n    \"→\",\n    \"↘\",\n]\n\nMOON_PHASES = (\"🌑\", \"🌒\", \"🌓\", \"🌔\", \"🌕\", \"🌖\", \"🌗\", \"🌘\")\n\nWEATHER_SYMBOL_WI_DAY = {\n    \"Unknown\": \"\",\n    \"Cloudy\": \"\",\n    \"Fog\": \"\",\n    \"HeavyRain\": \"\",\n    \"HeavyShowers\": \"\",\n    \"HeavySnow\": \"\",\n    \"HeavySnowShowers\": \"\",\n    \"LightRain\": \"\",\n    \"LightShowers\": \"\",\n    \"LightSleet\": \"\",\n    \"LightSleetShowers\": \"\",\n    \"LightSnow\": \"\",\n    \"LightSnowShowers\": \"\",\n    \"PartlyCloudy\": \"\",\n    \"Sunny\": \"\",\n    \"ThunderyHeavyRain\": \"\",\n    \"ThunderyShowers\": \"\",\n    \"ThunderySnowShowers\": \"\",\n    \"VeryCloudy\": \"\",\n}\n\nWEATHER_SYMBOL_WI_NIGHT = {\n    \"Unknown\": \"\",\n    \"Cloudy\": \"\",\n    \"Fog\": \"\",\n    \"HeavyRain\": \"\",\n    \"HeavyShowers\": \"\",\n    \"HeavySnow\": \"\",\n    \"HeavySnowShowers\": \"\",\n    \"LightRain\": \"\",\n    \"LightShowers\": \"\",\n    \"LightSleet\": \"\",\n    \"LightSleetShowers\": \"\",\n    \"LightSnow\": \"\",\n    \"LightSnowShowers\": \"\",\n    \"PartlyCloudy\": \"\",\n    \"Sunny\": \"\",\n    \"ThunderyHeavyRain\": \"\",\n    \"ThunderyShowers\": \"\",\n    \"ThunderySnowShowers\": \"\",\n    \"VeryCloudy\": \"\",\n}\n\nWEATHER_SYMBOL_PLAIN = {\n    \"Unknown\": \"?\",\n    \"Cloudy\": \"mm\",\n    \"Fog\": \"=\",\n    \"HeavyRain\": \"///\",\n    \"HeavyShowers\": \"//\",\n    \"HeavySnow\": \"**\",\n    \"HeavySnowShowers\": \"*/*\",\n    \"LightRain\": \"/\",\n    \"LightShowers\": \".\",\n    \"LightSleet\": \"x\",\n    \"LightSleetShowers\": \"x/\",\n    \"LightSnow\": \"*\",\n    \"LightSnowShowers\": \"*/\",\n    \"PartlyCloudy\": \"m\",\n    \"Sunny\": \"o\",\n    \"ThunderyHeavyRain\": \"/!/\",\n    \"ThunderyShowers\": \"!/\",\n    \"ThunderySnowShowers\": \"*!*\",\n    \"VeryCloudy\": \"mmm\",\n}\n\nWEATHER_SYMBOL_WIDTH_VTE_WI = {}\n\nWIND_DIRECTION_WI = [\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n]\n\nWIND_SCALE_WI = [\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n]\n\nMOON_PHASES_WI = (\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n    \"\",\n)\n\nWEATHER_SYMBOL_WEGO = {\n    \"Unknown\": [\n        \"    .-.      \",\n        \"     __)     \",\n        \"    (        \",\n        \"     `-’     \",\n        \"      •      \",\n    ],\n    \"Sunny\": [\n        \"\\033[38;5;226m    \\\\   /    \\033[0m\",\n        \"\\033[38;5;226m     .-.     \\033[0m\",\n        \"\\033[38;5;226m  ― (   ) ―  \\033[0m\",\n        \"\\033[38;5;226m     `-’     \\033[0m\",\n        \"\\033[38;5;226m    /   \\\\    \\033[0m\",\n    ],\n    \"PartlyCloudy\": [\n        \"\\033[38;5;226m   \\\\  /\\033[0m      \",\n        '\\033[38;5;226m _ /\"\"\\033[38;5;250m.-.    \\033[0m',\n        \"\\033[38;5;226m   \\\\_\\033[38;5;250m(   ).  \\033[0m\",\n        \"\\033[38;5;226m   /\\033[38;5;250m(___(__) \\033[0m\",\n        \"             \",\n    ],\n    \"Cloudy\": [\n        \"             \",\n        \"\\033[38;5;250m     .--.    \\033[0m\",\n        \"\\033[38;5;250m  .-(    ).  \\033[0m\",\n        \"\\033[38;5;250m (___.__)__) \\033[0m\",\n        \"             \",\n    ],\n    \"VeryCloudy\": [\n        \"             \",\n        \"\\033[38;5;240;1m     .--.    \\033[0m\",\n        \"\\033[38;5;240;1m  .-(    ).  \\033[0m\",\n        \"\\033[38;5;240;1m (___.__)__) \\033[0m\",\n        \"             \",\n    ],\n    \"LightShowers\": [\n        '\\033[38;5;226m _`/\"\"\\033[38;5;250m.-.    \\033[0m',\n        \"\\033[38;5;226m  ,\\\\_\\033[38;5;250m(   ).  \\033[0m\",\n        \"\\033[38;5;226m   /\\033[38;5;250m(___(__) \\033[0m\",\n        \"\\033[38;5;111m     ‘ ‘ ‘ ‘ \\033[0m\",\n        \"\\033[38;5;111m    ‘ ‘ ‘ ‘  \\033[0m\",\n    ],\n    \"HeavyShowers\": [\n        '\\033[38;5;226m _`/\"\"\\033[38;5;240;1m.-.    \\033[0m',\n        \"\\033[38;5;226m  ,\\\\_\\033[38;5;240;1m(   ).  \\033[0m\",\n        \"\\033[38;5;226m   /\\033[38;5;240;1m(___(__) \\033[0m\",\n        \"\\033[38;5;21;1m   ‚‘‚‘‚‘‚‘  \\033[0m\",\n        \"\\033[38;5;21;1m   ‚’‚’‚’‚’  \\033[0m\",\n    ],\n    \"LightSnowShowers\": [\n        '\\033[38;5;226m _`/\"\"\\033[38;5;250m.-.    \\033[0m',\n        \"\\033[38;5;226m  ,\\\\_\\033[38;5;250m(   ).  \\033[0m\",\n        \"\\033[38;5;226m   /\\033[38;5;250m(___(__) \\033[0m\",\n        \"\\033[38;5;255m     *  *  * \\033[0m\",\n        \"\\033[38;5;255m    *  *  *  \\033[0m\",\n    ],\n    \"HeavySnowShowers\": [\n        '\\033[38;5;226m _`/\"\"\\033[38;5;240;1m.-.    \\033[0m',\n        \"\\033[38;5;226m  ,\\\\_\\033[38;5;240;1m(   ).  \\033[0m\",\n        \"\\033[38;5;226m   /\\033[38;5;240;1m(___(__) \\033[0m\",\n        \"\\033[38;5;255;1m    * * * *  \\033[0m\",\n        \"\\033[38;5;255;1m   * * * *   \\033[0m\",\n    ],\n    \"LightSleetShowers\": [\n        '\\033[38;5;226m _`/\"\"\\033[38;5;250m.-.    \\033[0m',\n        \"\\033[38;5;226m  ,\\\\_\\033[38;5;250m(   ).  \\033[0m\",\n        \"\\033[38;5;226m   /\\033[38;5;250m(___(__) \\033[0m\",\n        \"\\033[38;5;111m     ‘ \\033[38;5;255m*\\033[38;5;111m ‘ \\033[38;5;255m* \\033[0m\",\n        \"\\033[38;5;255m    *\\033[38;5;111m ‘ \\033[38;5;255m*\\033[38;5;111m ‘  \\033[0m\",\n    ],\n    \"ThunderyShowers\": [\n        '\\033[38;5;226m _`/\"\"\\033[38;5;250m.-.    \\033[0m',\n        \"\\033[38;5;226m  ,\\\\_\\033[38;5;250m(   ).  \\033[0m\",\n        \"\\033[38;5;226m   /\\033[38;5;250m(___(__) \\033[0m\",\n        \"\\033[38;5;228;5m    ⚡\\033[38;5;111;25m‘ ‘\\033[38;5;228;5m⚡\\033[38;5;111;25m‘ ‘ \\033[0m\",\n        \"\\033[38;5;111m    ‘ ‘ ‘ ‘  \\033[0m\",\n    ],\n    \"ThunderyHeavyRain\": [\n        \"\\033[38;5;240;1m     .-.     \\033[0m\",\n        \"\\033[38;5;240;1m    (   ).   \\033[0m\",\n        \"\\033[38;5;240;1m   (___(__)  \\033[0m\",\n        \"\\033[38;5;21;1m  ‚‘\\033[38;5;228;5m⚡\\033[38;5;21;25m‘‚\\033[38;5;228;5m⚡\\033[38;5;21;25m‚‘ \\033[0m\",\n        \"\\033[38;5;21;1m  ‚’‚’\\033[38;5;228;5m⚡\\033[38;5;21;25m’‚’  \\033[0m\",\n    ],\n    \"ThunderySnowShowers\": [\n        '\\033[38;5;226m _`/\"\"\\033[38;5;250m.-.    \\033[0m',\n        \"\\033[38;5;226m  ,\\\\_\\033[38;5;250m(   ).  \\033[0m\",\n        \"\\033[38;5;226m   /\\033[38;5;250m(___(__) \\033[0m\",\n        \"\\033[38;5;255m     *\\033[38;5;228;5m⚡\\033[38;5;255;25m*\\033[38;5;228;5m⚡\\033[38;5;255;25m* \\033[0m\",\n        \"\\033[38;5;255m    *  *  *  \\033[0m\",\n    ],\n    \"LightRain\": [\n        \"\\033[38;5;250m     .-.     \\033[0m\",\n        \"\\033[38;5;250m    (   ).   \\033[0m\",\n        \"\\033[38;5;250m   (___(__)  \\033[0m\",\n        \"\\033[38;5;111m    ‘ ‘ ‘ ‘  \\033[0m\",\n        \"\\033[38;5;111m   ‘ ‘ ‘ ‘   \\033[0m\",\n    ],\n    \"HeavyRain\": [\n        \"\\033[38;5;240;1m     .-.     \\033[0m\",\n        \"\\033[38;5;240;1m    (   ).   \\033[0m\",\n        \"\\033[38;5;240;1m   (___(__)  \\033[0m\",\n        \"\\033[38;5;21;1m  ‚‘‚‘‚‘‚‘   \\033[0m\",\n        \"\\033[38;5;21;1m  ‚’‚’‚’‚’   \\033[0m\",\n    ],\n    \"LightSnow\": [\n        \"\\033[38;5;250m     .-.     \\033[0m\",\n        \"\\033[38;5;250m    (   ).   \\033[0m\",\n        \"\\033[38;5;250m   (___(__)  \\033[0m\",\n        \"\\033[38;5;255m    *  *  *  \\033[0m\",\n        \"\\033[38;5;255m   *  *  *   \\033[0m\",\n    ],\n    \"HeavySnow\": [\n        \"\\033[38;5;240;1m     .-.     \\033[0m\",\n        \"\\033[38;5;240;1m    (   ).   \\033[0m\",\n        \"\\033[38;5;240;1m   (___(__)  \\033[0m\",\n        \"\\033[38;5;255;1m   * * * *   \\033[0m\",\n        \"\\033[38;5;255;1m  * * * *    \\033[0m\",\n    ],\n    \"LightSleet\": [\n        \"\\033[38;5;250m     .-.     \\033[0m\",\n        \"\\033[38;5;250m    (   ).   \\033[0m\",\n        \"\\033[38;5;250m   (___(__)  \\033[0m\",\n        \"\\033[38;5;111m    ‘ \\033[38;5;255m*\\033[38;5;111m ‘ \\033[38;5;255m*  \\033[0m\",\n        \"\\033[38;5;255m   *\\033[38;5;111m ‘ \\033[38;5;255m*\\033[38;5;111m ‘   \\033[0m\",\n    ],\n    \"Fog\": [\n        \"             \",\n        \"\\033[38;5;251m _ - _ - _ - \\033[0m\",\n        \"\\033[38;5;251m  _ - _ - _  \\033[0m\",\n        \"\\033[38;5;251m _ - _ - _ - \\033[0m\",\n        \"             \",\n    ],\n}\n\nLOCALE = {\n    \"af\": \"af_ZA\",\n    \"ar\": \"ar_TN\",\n    \"az\": \"az_AZ\",\n    \"be\": \"be_BY\",\n    \"bg\": \"bg_BG\",\n    \"bs\": \"bs_BA\",\n    \"ca\": \"ca_ES\",\n    \"cs\": \"cs_CZ\",\n    \"cy\": \"cy_GB\",\n    \"da\": \"da_DK\",\n    \"de\": \"de_DE\",\n    \"el\": \"el_GR\",\n    \"eo\": \"eo\",\n    \"es\": \"es_ES\",\n    \"et\": \"et_EE\",\n    \"fa\": \"fa_IR\",\n    \"fi\": \"fi_FI\",\n    \"fr\": \"fr_FR\",\n    \"fy\": \"fy_NL\",\n    \"ga\": \"ga_IE\",\n    \"he\": \"he_IL\",\n    \"hr\": \"hr_HR\",\n    \"hu\": \"hu_HU\",\n    \"hy\": \"hy_AM\",\n    \"ia\": \"ia\",\n    \"id\": \"id_ID\",\n    \"is\": \"is_IS\",\n    \"it\": \"it_IT\",\n    \"ja\": \"ja_JP\",\n    \"jv\": \"en_US\",\n    \"ka\": \"ka_GE\",\n    \"ko\": \"ko_KR\",\n    \"kk\": \"kk_KZ\",\n    \"ky\": \"ky_KG\",\n    \"lt\": \"lt_LT\",\n    \"lv\": \"lv_LV\",\n    \"mk\": \"mk_MK\",\n    \"ml\": \"ml_IN\",\n    \"nb\": \"nb_NO\",\n    \"nl\": \"nl_NL\",\n    \"nn\": \"nn_NO\",\n    \"pt\": \"pt_PT\",\n    \"pt-br\": \"pt_BR\",\n    \"pl\": \"pl_PL\",\n    \"ro\": \"ro_RO\",\n    \"ru\": \"ru_RU\",\n    \"sv\": \"sv_SE\",\n    \"sk\": \"sk_SK\",\n    \"sl\": \"sl_SI\",\n    \"sr\": \"sr_RS\",\n    \"sr-lat\": \"sr_RS@latin\",\n    \"sw\": \"sw_KE\",\n    \"th\": \"th_TH\",\n    \"tr\": \"tr_TR\",\n    \"uk\": \"uk_UA\",\n    \"uz\": \"uz_UZ\",\n    \"vi\": \"vi_VN\",\n    \"zh\": \"zh_TW\",\n    \"zu\": \"zu_ZA\",\n    \"mg\": \"mg_MG\",\n}\n"
  },
  {
    "path": "lib/datasource/README.md",
    "content": "\nCurrently wttr.in uses just one data source, but more data sources must be added.\nHaving more data sources will increase data quality, and make it possible\nto select data source basing on location, or on the user's preferences.\n\n## Possible data sources\n\n* [Open weather map](https://openweathermap.org/)\n* [Accu weather](https://www.accuweather.com/)\n* [Windy](https://www.windy.com/?26.953,75.711,5)\n* [Yr](https://www.yr.no/nb)\n* [BBC WeatherFeeds](https://support.bbc.co.uk/platform/feeds/WeatherFeeds.htm)\n* https://weather.gc.ca\n* [Bom](http://www.bom.gov.au)\n* [IMD](https://mausam.imd.gov.in/)\n* [darksky](https://darksky.net/forecast/40.7127,-74.0059/us12/en)\n* [weather bug](https://www.weatherbug.com/)\n* [weather underground](https://www.wunderground.com/)\n* [brightsky](https://brightsky.dev/)\n\n## Air Quality sources\n\n* http://aqicn.org/\n* https://docs.airnowapi.org/\n* https://www2.purpleair.com/community/faq#hc-access-the-json\n\n"
  },
  {
    "path": "lib/duplicate_translations.py",
    "content": "import os\n\n\ndef remove_colon_and_strip_from_str(line):\n    \"\"\"\n    Removes the colon from the line and strips the line.\n    \"\"\"\n    return line.replace(\":\", \"\").strip()\n\n\ndef print_result_for_file(file_path, file_name, duplicate_entries):\n    \"\"\"\n    Prints the result for a given file.\n    \"\"\"\n    print(\"-\" * 50)\n    print(f\"Processing file: {file_name} \\n\")\n    # keep entries with more than one occurence\n    if len(duplicate_entries) > 0:\n        for key, value in duplicate_entries.items():\n            # prints debug info for each duplicate found\n            print(\n                f\"{file_path}: \\\"{key}\\\" appears in lines {', '.join(map(str, value))}\"\n            )\n    else:\n        # prints debug info, if no duplicates found 🥳\n        print(f\"No duplicates found!\")\n\n\ndef find_duplicates(directory, debug=False):\n    \"\"\"\n    Reads all .txt files in a given directory and tries to detect duplicate entries.\n    \"\"\"\n    try:\n        language_lookup_table = {}\n        files = [f for f in os.listdir(directory) if f.endswith(\".txt\")]\n        files.sort()\n\n        if not files:\n            print(\"No .txt files found in the directory.\")\n            return\n\n        for file_name in files:\n            # if file_name contains \"-help\" skip it for now!\n            if \"-help\" in file_name:\n                continue\n\n            file_path = os.path.join(directory, file_name)\n            try:\n                with open(file_path, \"r\", encoding=\"utf-8\") as file:\n                    lookup_table = {}\n                    for line_number, line in enumerate(file, start=1):\n                        stripped_line = line.strip()\n                        stripped_keywords = stripped_line.split(\":\")\n                        stripped_keywords = list(\n                            map(remove_colon_and_strip_from_str, stripped_keywords)\n                        )\n                        trimmed_keywords = list(map(str.strip, stripped_keywords))\n\n                        for tk in trimmed_keywords:\n                            if tk == \"\" or tk.isdigit():\n                                continue\n                            if tk in lookup_table:\n                                lookup_table[tk].append(line_number)\n                            else:\n                                lookup_table[tk] = [line_number]\n                    duplicate_entries = {\n                        k: v for k, v in lookup_table.items() if len(v) > 1\n                    }\n                    print_result_for_file(file_path, file_name, duplicate_entries)\n                    language_lookup_table[file_name] = duplicate_entries\n            except Exception as e:\n                print(f\"An error occurred while processing the file: {e}\")\n\n        return language_lookup_table\n    except Exception as e:\n        print(f\"An error occurred: {e}\")\n        return None\n\n\n# Example usage from the root directory:\n#   python ./lib/duplicate_translations.py\nif __name__ == \"__main__\":\n    directory_path = \"share/translations/\"\n    find_duplicates(directory_path, debug=True)\n"
  },
  {
    "path": "lib/extract_emoji.py",
    "content": "#!/usr/bin/env python\n# vim: fileencoding=utf-8\n\n\"\"\"\n\nAt the moment, Pillow library does not support colorful emojis,\nthat is why emojis must be extracted to external files first,\nand then they must be handled as usual graphical objects\nand not as text.\n\nThe files are extracted using Imagemagick.\n\nUsage:\n\n    ve/bi/python lib/extract_emoji.py\n\"\"\"\n\nimport subprocess\n\nEMOJIS = [\n    \"✨\",\n    \"☁️\",\n    \"🌫\",\n    \"🌧\",\n    \"🌧\",\n    \"❄️\",\n    \"❄️\",\n    \"🌦\",\n    \"🌦\",\n    \"🌧\",\n    \"🌧\",\n    \"🌨\",\n    \"🌨\",\n    \"⛅️\",\n    \"☀️\",\n    \"🌩\",\n    \"⛈\",\n    \"⛈\",\n    \"☁️\",\n    \"🌑\",\n    \"🌒\",\n    \"🌓\",\n    \"🌔\",\n    \"🌕\",\n    \"🌖\",\n    \"🌗\",\n    \"🌘\",\n]\n\n\ndef extract_emojis_to_directory(dirname):\n    \"\"\"\n    Extract emoji from an emoji font, to separate files.\n    \"\"\"\n\n    emoji_font = \"Noto Color Emoji\"\n    emoji_size = 30\n\n    for emoji in EMOJIS:\n        filename = \"%s/%s.png\" % (dirname, emoji)\n        convert_string = [\n            \"convert\",\n            \"-background\",\n            \"black\",\n            \"-size\",\n            \"%sx%s\" % (emoji_size, emoji_size),\n            \"-set\",\n            \"colorspace\",\n            \"sRGB\",\n            'pango:<span font=\"%s\" size=\"20000\">%s</span>' % (emoji_font, emoji),\n            filename,\n        ]\n        subprocess.Popen(convert_string)\n\n\nif __name__ == \"__main__\":\n    extract_emojis_to_directory(\"share/emoji\")\n"
  },
  {
    "path": "lib/fields.py",
    "content": "\"\"\"\nHuman readable description of the available data fields\ndescribing current weather, weather forecast, and astronomical data\n\"\"\"\n\nDESCRIPTION = {\n    # current condition fields\n    \"FeelsLikeC\": (\n        \"Feels Like Temperature in Celsius\",\n        \"temperature_feels_like_celsius\",\n    ),\n    \"FeelsLikeF\": (\n        \"Feels Like Temperature in Fahrenheit\",\n        \"temperature_feels_like_fahrenheit\",\n    ),\n    \"cloudcover\": (\"Cloud Coverage in Percent\", \"cloudcover_percentage\"),\n    \"humidity\": (\"Humidity in Percent\", \"humidity_percentage\"),\n    \"precipMM\": (\"Precipitation (Rainfall) in mm\", \"precipitation_mm\"),\n    \"pressure\": (\"Air pressure in hPa\", \"pressure_hpa\"),\n    \"temp_C\": (\"Temperature in Celsius\", \"temperature_celsius\"),\n    \"temp_F\": (\"Temperature in Fahrenheit\", \"temperature_fahrenheit\"),\n    \"uvIndex\": (\"Ultraviolet Radiation Index\", \"uv_index\"),\n    \"visibility\": (\"Visible Distance in Kilometres\", \"visibility\"),\n    \"weatherCode\": (\"Code to describe Weather Condition\", \"weather_code\"),\n    \"winddirDegree\": (\"Wind Direction in Degree\", \"winddir_degree\"),\n    \"windspeedKmph\": (\"Wind Speed in Kilometres per Hour\", \"windspeed_kmph\"),\n    \"windspeedMiles\": (\"Wind Speed in Miles per Hour\", \"windspeed_mph\"),\n    \"observation_time\": (\n        \"Minutes since start of the day the observation happened\",\n        \"observation_time\",\n    ),\n    # fields with `description`\n    \"weatherDesc\": (\"Weather Description\", \"weather_desc\"),\n    \"winddir16Point\": (\"Wind Direction on a 16-wind compass rose\", \"winddir_16_point\"),\n    # forecast fields\n    \"maxtempC\": (\"Maximum Temperature in Celsius\", \"temperature_celsius_maximum\"),\n    \"maxtempF\": (\"Maximum Temperature in Fahrenheit\", \"temperature_fahrenheit_maximum\"),\n    \"mintempC\": (\"Minimum Temperature in Celsius\", \"temperature_celsius_minimum\"),\n    \"mintempF\": (\"Minimum Temperature in Fahrenheit\", \"temperature_fahrenheit_minimum\"),\n    \"sunHour\": (\"Hours of sunlight\", \"sun_hour\"),\n    \"totalSnow_cm\": (\"Total snowfall in cm\", \"snowfall_cm\"),\n    # astronomy fields\n    \"moon_illumination\": (\n        \"Percentage of the moon illuminated\",\n        \"astronomy_moon_illumination\",\n    ),\n    # astronomy fields with description\n    \"moon_phase\": (\"Phase of the moon\", \"astronomy_moon_phase\"),\n    # astronomy fields with time\n    \"moonrise\": (\n        \"Minutes since start of the day until the moon appears above the horizon\",\n        \"astronomy_moonrise_min\",\n    ),\n    \"moonset\": (\n        \"Minutes since start of the day until the moon disappears below the horizon\",\n        \"astronomy_moonset_min\",\n    ),\n    \"sunrise\": (\n        \"Minutes since start of the day until the sun appears above the horizon\",\n        \"astronomy_sunrise_min\",\n    ),\n    \"sunset\": (\n        \"Minutes since start of the day until the moon disappears below the horizon\",\n        \"astronomy_sunset_min\",\n    ),\n}\n"
  },
  {
    "path": "lib/fmt/__init__.py",
    "content": ""
  },
  {
    "path": "lib/fmt/png.py",
    "content": "#!/usr/bin/python\n# vim: encoding=utf-8\n# pylint: disable=wrong-import-position,wrong-import-order,redefined-builtin\n\n\"\"\"\nThis module is used to generate png-files for wttr.in queries.\nThe only exported function is:\n\n* render_ansi(png_file, text, options=None)\n\n`render_ansi` is the main function of the module,\nwhich does rendering of stream into a PNG-file.\n\nThe module uses PIL for graphical tasks, and pyte for rendering\nof ANSI stream into terminal representation.\n\"\"\"\n\nfrom __future__ import print_function\n\nimport sys\nimport io\nimport os\nimport glob\n\nfrom PIL import Image, ImageFont, ImageDraw\nimport pyte.screens\nimport emoji\nimport grapheme\n\nfrom . import unicodedata2\n\nsys.path.insert(0, \"..\")\nimport constants\nimport globals\n\nCOLS = 180\nROWS = 100\nCHAR_WIDTH = 8\nCHAR_HEIGHT = 14\nFONT_SIZE = 13\nFONT_CAT = {\n    \"default\": \"/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf\",\n    \"Cyrillic\": \"/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf\",\n    \"Greek\": \"/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf\",\n    \"Arabic\": \"/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf\",\n    \"Hebrew\": \"/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf\",\n    \"Han\": \"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc\",\n    \"Hiragana\": \"/usr/share/fonts/truetype/motoya-l-cedar/MTLc3m.ttf\",\n    \"Katakana\": \"/usr/share/fonts/truetype/motoya-l-cedar/MTLc3m.ttf\",\n    \"Hangul\": \"/usr/share/fonts/truetype/lexi/LexiGulim.ttf\",\n    \"Braille\": \"/usr/share/fonts/truetype/ancient-scripts/Symbola_hint.ttf\",\n    \"Emoji\": \"/usr/share/fonts/truetype/ancient-scripts/Symbola_hint.ttf\",\n}\n\n#\n# How to find font for non-standard scripts:\n#\n#   $ fc-list :lang=ja\n#\n# GNU/Debian packages, that the fonts come from:\n#\n#   * fonts-dejavu-core\n#   * fonts-wqy-zenhei (Han)\n#   * fonts-motoya-l-cedar (Hiragana/Katakana)\n#   * fonts-lexi-gulim (Hangul)\n#   * fonts-symbola (Braille/Emoji)\n#\n\n\ndef render_ansi(text, options=None):\n    \"\"\"Render `text` (terminal sequence) in a PNG file\n    paying attention to passed command line `options`.\n\n    Return: file content\n    \"\"\"\n\n    screen = pyte.screens.Screen(COLS, ROWS)\n    screen.set_mode(pyte.modes.LNM)\n    stream = pyte.Stream(screen)\n\n    text, graphemes = _fix_graphemes(text)\n    stream.feed(text)\n\n    buf = sorted(screen.buffer.items(), key=lambda x: x[0])\n    buf = [[x[1] for x in sorted(line[1].items(), key=lambda x: x[0])] for line in buf]\n\n    return _gen_term(buf, graphemes, options=options)\n\n\ndef _color_mapping(color, inverse=False):\n    \"\"\"Convert pyte color to PIL color\n\n    Return: tuple of color values (R,G,B)\n    \"\"\"\n\n    if color == \"default\":\n        if inverse:\n            return \"black\"\n        return \"lightgray\"\n\n    if color in [\"green\", \"black\", \"cyan\", \"blue\", \"brown\"]:\n        return color\n    try:\n        return (int(color[0:2], 16), int(color[2:4], 16), int(color[4:6], 16))\n    except (ValueError, IndexError):\n        # if we do not know this color and it can not be decoded as RGB,\n        # print it and return it as it is (will be displayed as black)\n        # print color\n        return color\n    return color\n\n\ndef _strip_buf(buf):\n    \"\"\"Strips empty spaces from behind and from the right side.\n    (from the right side is not yet implemented)\n    \"\"\"\n\n    def empty_line(line):\n        \"Returns True if the line consists from spaces\"\n        return all(x.data == \" \" for x in line)\n\n    def line_len(line):\n        \"Returns len of the line excluding spaces from the right\"\n\n        last_pos = len(line)\n        while last_pos > 0 and line[last_pos - 1].data == \" \":\n            last_pos -= 1\n        return last_pos\n\n    number_of_lines = 0\n    for line in buf[::-1]:\n        if not empty_line(line):\n            break\n        number_of_lines += 1\n\n    if number_of_lines:\n        buf = buf[:-number_of_lines]\n\n    max_len = max(line_len(x) for x in buf)\n    buf = [line[:max_len] for line in buf]\n\n    return buf\n\n\ndef _script_category(char):\n    \"\"\"Returns category of a Unicode character\n\n    Possible values:\n        default, Cyrillic, Greek, Han, Hiragana\n    \"\"\"\n\n    if emoji.is_emoji(char):\n        return \"Emoji\"\n\n    cat = unicodedata2.script_cat(char)[0]\n    if char == \"：\":\n        return \"Han\"\n    if cat in [\"Latin\", \"Common\"]:\n        return \"default\"\n    return cat\n\n\ndef _load_emojilib():\n    \"\"\"Load known emojis from a directory, and return dictionary\n    of PIL Image objects correspodent to the loaded emojis.\n    Each emoji is resized to the CHAR_HEIGHT size.\n    \"\"\"\n\n    emojilib = {}\n    for filename in glob.glob(\"share/emoji/*.png\"):\n        character = os.path.basename(filename)[:-3]\n        emojilib[character] = Image.open(filename).resize((CHAR_HEIGHT, CHAR_HEIGHT))\n    return emojilib\n\n\n# pylint: disable=too-many-locals,too-many-branches,too-many-statements\ndef _gen_term(buf, graphemes, options=None):\n    \"\"\"Renders rendered pyte buffer `buf` and list of workaround `graphemes`\n    to a PNG file, and return its content\n    \"\"\"\n\n    if not options:\n        options = {}\n\n    current_grapheme = 0\n\n    buf = _strip_buf(buf)\n    cols = max(len(x) for x in buf)\n    rows = len(buf)\n\n    bg_color = 0\n    if \"background\" in options:\n        bg_color = _color_mapping(options[\"background\"], options.get(\"inverted_colors\"))\n\n    image = Image.new(\"RGB\", (cols * CHAR_WIDTH, rows * CHAR_HEIGHT), color=bg_color)\n\n    buf = buf[-ROWS:]\n\n    draw = ImageDraw.Draw(image)\n    font = {}\n    for cat in FONT_CAT:\n        font[cat] = ImageFont.truetype(FONT_CAT[cat], FONT_SIZE)\n\n    emojilib = _load_emojilib()\n\n    x_pos = 0\n    y_pos = 0\n    for line in buf:\n        x_pos = 0\n        for char in line:\n            current_color = _color_mapping(char.fg, options.get(\"inverted_colors\"))\n            if char.bg != \"default\":\n                draw.rectangle(\n                    ((x_pos, y_pos), (x_pos + CHAR_WIDTH, y_pos + CHAR_HEIGHT)),\n                    fill=_color_mapping(char.bg, options.get(\"inverted_colors\")),\n                )\n\n            if char.data == \"!\":\n                try:\n                    data = graphemes[current_grapheme]\n                except IndexError:\n                    pass\n                current_grapheme += 1\n            else:\n                data = char.data\n\n            if data:\n                cat = _script_category(data[0])\n                if cat not in font:\n                    globals.log(\"Unknown font category: %s\" % cat)\n                if cat == \"Emoji\" and emojilib.get(data):\n                    image.paste(emojilib.get(data), (x_pos, y_pos))\n                else:\n                    draw.text(\n                        (x_pos, y_pos),\n                        data,\n                        font=font.get(cat, font.get(\"default\")),\n                        fill=current_color,\n                    )\n\n            x_pos += CHAR_WIDTH * constants.WEATHER_SYMBOL_WIDTH_VTE.get(data, 1)\n        y_pos += CHAR_HEIGHT\n\n    if \"transparency\" in options:\n        transparency = options.get(\"transparency\", \"255\")\n        try:\n            transparency = int(transparency)\n        except ValueError:\n            transparency = 255\n\n        if transparency < 0:\n            transparency = 0\n\n        if transparency > 255:\n            transparency = 255\n\n        image = image.convert(\"RGBA\")\n        datas = image.getdata()\n\n        new_data = []\n        for item in datas:\n            new_item = tuple(list(item[:3]) + [transparency])\n            new_data.append(new_item)\n\n        image.putdata(new_data)\n\n    img_bytes = io.BytesIO()\n    image.save(img_bytes, format=\"png\")\n    return img_bytes.getvalue()\n\n\ndef _fix_graphemes(text):\n    \"\"\"\n    Extract long graphemes sequences that can't be handled\n    by pyte correctly because of the bug pyte#131.\n    Graphemes are omited and replaced with placeholders,\n    and returned as a list.\n\n    Return:\n        text_without_graphemes, graphemes\n    \"\"\"\n\n    output = \"\"\n    graphemes = []\n\n    for gra in grapheme.graphemes(text):\n        if len(gra) > 1:\n            character = \"!\"\n            graphemes.append(gra)\n        else:\n            character = gra\n        output += character\n\n    return output, graphemes\n"
  },
  {
    "path": "lib/fmt/unicodedata2.py",
    "content": "# downloaded from https://gist.github.com/2204527\n# described/recommended here:\n#\n#   http://stackoverflow.com/questions/9868792/find-out-the-unicode-script-of-a-character\n#\n\nfrom __future__ import print_function\nfrom unicodedata import *\n\nscript_data = {\n    \"names\": [\n        \"Common\",\n        \"Latin\",\n        \"Greek\",\n        \"Cyrillic\",\n        \"Armenian\",\n        \"Hebrew\",\n        \"Arabic\",\n        \"Syriac\",\n        \"Thaana\",\n        \"Devanagari\",\n        \"Bengali\",\n        \"Gurmukhi\",\n        \"Gujarati\",\n        \"Oriya\",\n        \"Tamil\",\n        \"Telugu\",\n        \"Kannada\",\n        \"Malayalam\",\n        \"Sinhala\",\n        \"Thai\",\n        \"Lao\",\n        \"Tibetan\",\n        \"Myanmar\",\n        \"Georgian\",\n        \"Hangul\",\n        \"Ethiopic\",\n        \"Cherokee\",\n        \"Canadian_Aboriginal\",\n        \"Ogham\",\n        \"Runic\",\n        \"Khmer\",\n        \"Mongolian\",\n        \"Hiragana\",\n        \"Katakana\",\n        \"Bopomofo\",\n        \"Han\",\n        \"Yi\",\n        \"Old_Italic\",\n        \"Gothic\",\n        \"Deseret\",\n        \"Inherited\",\n        \"Tagalog\",\n        \"Hanunoo\",\n        \"Buhid\",\n        \"Tagbanwa\",\n        \"Limbu\",\n        \"Tai_Le\",\n        \"Linear_B\",\n        \"Ugaritic\",\n        \"Shavian\",\n        \"Osmanya\",\n        \"Cypriot\",\n        \"Braille\",\n        \"Buginese\",\n        \"Coptic\",\n        \"New_Tai_Lue\",\n        \"Glagolitic\",\n        \"Tifinagh\",\n        \"Syloti_Nagri\",\n        \"Old_Persian\",\n        \"Kharoshthi\",\n        \"Balinese\",\n        \"Cuneiform\",\n        \"Phoenician\",\n        \"Phags_Pa\",\n        \"Nko\",\n        \"Sundanese\",\n        \"Lepcha\",\n        \"Ol_Chiki\",\n        \"Vai\",\n        \"Saurashtra\",\n        \"Kayah_Li\",\n        \"Rejang\",\n        \"Lycian\",\n        \"Carian\",\n        \"Lydian\",\n        \"Cham\",\n        \"Tai_Tham\",\n        \"Tai_Viet\",\n        \"Avestan\",\n        \"Egyptian_Hieroglyphs\",\n        \"Samaritan\",\n        \"Lisu\",\n        \"Bamum\",\n        \"Javanese\",\n        \"Meetei_Mayek\",\n        \"Imperial_Aramaic\",\n        \"Old_South_Arabian\",\n        \"Inscriptional_Parthian\",\n        \"Inscriptional_Pahlavi\",\n        \"Old_Turkic\",\n        \"Kaithi\",\n        \"Batak\",\n        \"Brahmi\",\n        \"Mandaic\",\n        \"Chakma\",\n        \"Meroitic_Cursive\",\n        \"Meroitic_Hieroglyphs\",\n        \"Miao\",\n        \"Sharada\",\n        \"Sora_Sompeng\",\n        \"Takri\",\n    ],\n    \"cats\": [\n        \"Cc\",\n        \"Zs\",\n        \"Po\",\n        \"Sc\",\n        \"Ps\",\n        \"Pe\",\n        \"Sm\",\n        \"Pd\",\n        \"Nd\",\n        \"Sk\",\n        \"Pc\",\n        \"So\",\n        \"Pi\",\n        \"Cf\",\n        \"No\",\n        \"L\",\n        \"Pf\",\n        \"Lm\",\n        \"Mc\",\n        \"Lo\",\n        \"Zl\",\n        \"Zp\",\n        \"Nl\",\n        \"Mn\",\n        \"Me\",\n    ],\n    \"idx\": [\n        (0x0, 0x1F, 0, 0),\n        (0x20, 0x20, 0, 1),\n        (0x21, 0x23, 0, 2),\n        (0x24, 0x24, 0, 3),\n        (0x25, 0x27, 0, 2),\n        (0x28, 0x28, 0, 4),\n        (0x29, 0x29, 0, 5),\n        (0x2A, 0x2A, 0, 2),\n        (0x2B, 0x2B, 0, 6),\n        (0x2C, 0x2C, 0, 2),\n        (0x2D, 0x2D, 0, 7),\n        (0x2E, 0x2F, 0, 2),\n        (0x30, 0x39, 0, 8),\n        (0x3A, 0x3B, 0, 2),\n        (0x3C, 0x3E, 0, 6),\n        (0x3F, 0x40, 0, 2),\n        (0x41, 0x5A, 1, 15),\n        (0x5B, 0x5B, 0, 4),\n        (0x5C, 0x5C, 0, 2),\n        (0x5D, 0x5D, 0, 5),\n        (0x5E, 0x5E, 0, 9),\n        (0x5F, 0x5F, 0, 10),\n        (0x60, 0x60, 0, 9),\n        (0x61, 0x7A, 1, 15),\n        (0x7B, 0x7B, 0, 4),\n        (0x7C, 0x7C, 0, 6),\n        (0x7D, 0x7D, 0, 5),\n        (0x7E, 0x7E, 0, 6),\n        (0x7F, 0x9F, 0, 0),\n        (0xA0, 0xA0, 0, 1),\n        (0xA1, 0xA1, 0, 2),\n        (0xA2, 0xA5, 0, 3),\n        (0xA6, 0xA6, 0, 11),\n        (0xA7, 0xA7, 0, 2),\n        (0xA8, 0xA8, 0, 9),\n        (0xA9, 0xA9, 0, 11),\n        (0xAA, 0xAA, 1, 19),\n        (0xAB, 0xAB, 0, 12),\n        (0xAC, 0xAC, 0, 6),\n        (0xAD, 0xAD, 0, 13),\n        (0xAE, 0xAE, 0, 11),\n        (0xAF, 0xAF, 0, 9),\n        (0xB0, 0xB0, 0, 11),\n        (0xB1, 0xB1, 0, 6),\n        (0xB2, 0xB3, 0, 14),\n        (0xB4, 0xB4, 0, 9),\n        (0xB5, 0xB5, 0, 15),\n        (0xB6, 0xB7, 0, 2),\n        (0xB8, 0xB8, 0, 9),\n        (0xB9, 0xB9, 0, 14),\n        (0xBA, 0xBA, 1, 19),\n        (0xBB, 0xBB, 0, 16),\n        (0xBC, 0xBE, 0, 14),\n        (0xBF, 0xBF, 0, 2),\n        (0xC0, 0xD6, 1, 15),\n        (0xD7, 0xD7, 0, 6),\n        (0xD8, 0xF6, 1, 15),\n        (0xF7, 0xF7, 0, 6),\n        (0xF8, 0x1BA, 1, 15),\n        (0x1BB, 0x1BB, 1, 19),\n        (0x1BC, 0x1BF, 1, 15),\n        (0x1C0, 0x1C3, 1, 19),\n        (0x1C4, 0x293, 1, 15),\n        (0x294, 0x294, 1, 19),\n        (0x295, 0x2AF, 1, 15),\n        (0x2B0, 0x2B8, 1, 17),\n        (0x2B9, 0x2C1, 0, 17),\n        (0x2C2, 0x2C5, 0, 9),\n        (0x2C6, 0x2D1, 0, 17),\n        (0x2D2, 0x2DF, 0, 9),\n        (0x2E0, 0x2E4, 1, 17),\n        (0x2E5, 0x2E9, 0, 9),\n        (0x2EA, 0x2EB, 34, 9),\n        (0x2EC, 0x2EC, 0, 17),\n        (0x2ED, 0x2ED, 0, 9),\n        (0x2EE, 0x2EE, 0, 17),\n        (0x2EF, 0x2FF, 0, 9),\n        (0x300, 0x36F, 40, 23),\n        (0x370, 0x373, 2, 15),\n        (0x374, 0x374, 0, 17),\n        (0x375, 0x375, 2, 9),\n        (0x376, 0x377, 2, 15),\n        (0x37A, 0x37A, 2, 17),\n        (0x37B, 0x37D, 2, 15),\n        (0x37E, 0x37E, 0, 2),\n        (0x384, 0x384, 2, 9),\n        (0x385, 0x385, 0, 9),\n        (0x386, 0x386, 2, 15),\n        (0x387, 0x387, 0, 2),\n        (0x388, 0x38A, 2, 15),\n        (0x38C, 0x38C, 2, 15),\n        (0x38E, 0x3A1, 2, 15),\n        (0x3A3, 0x3E1, 2, 15),\n        (0x3E2, 0x3EF, 54, 15),\n        (0x3F0, 0x3F5, 2, 15),\n        (0x3F6, 0x3F6, 2, 6),\n        (0x3F7, 0x3FF, 2, 15),\n        (0x400, 0x481, 3, 15),\n        (0x482, 0x482, 3, 11),\n        (0x483, 0x484, 3, 23),\n        (0x485, 0x486, 40, 23),\n        (0x487, 0x487, 3, 23),\n        (0x488, 0x489, 3, 24),\n        (0x48A, 0x527, 3, 15),\n        (0x531, 0x556, 4, 15),\n        (0x559, 0x559, 4, 17),\n        (0x55A, 0x55F, 4, 2),\n        (0x561, 0x587, 4, 15),\n        (0x589, 0x589, 0, 2),\n        (0x58A, 0x58A, 4, 7),\n        (0x58F, 0x58F, 4, 3),\n        (0x591, 0x5BD, 5, 23),\n        (0x5BE, 0x5BE, 5, 7),\n        (0x5BF, 0x5BF, 5, 23),\n        (0x5C0, 0x5C0, 5, 2),\n        (0x5C1, 0x5C2, 5, 23),\n        (0x5C3, 0x5C3, 5, 2),\n        (0x5C4, 0x5C5, 5, 23),\n        (0x5C6, 0x5C6, 5, 2),\n        (0x5C7, 0x5C7, 5, 23),\n        (0x5D0, 0x5EA, 5, 19),\n        (0x5F0, 0x5F2, 5, 19),\n        (0x5F3, 0x5F4, 5, 2),\n        (0x600, 0x604, 6, 13),\n        (0x606, 0x608, 6, 6),\n        (0x609, 0x60A, 6, 2),\n        (0x60B, 0x60B, 6, 3),\n        (0x60C, 0x60C, 0, 2),\n        (0x60D, 0x60D, 6, 2),\n        (0x60E, 0x60F, 6, 11),\n        (0x610, 0x61A, 6, 23),\n        (0x61B, 0x61B, 0, 2),\n        (0x61E, 0x61E, 6, 2),\n        (0x61F, 0x61F, 0, 2),\n        (0x620, 0x63F, 6, 19),\n        (0x640, 0x640, 0, 17),\n        (0x641, 0x64A, 6, 19),\n        (0x64B, 0x655, 40, 23),\n        (0x656, 0x65E, 6, 23),\n        (0x65F, 0x65F, 40, 23),\n        (0x660, 0x669, 0, 8),\n        (0x66A, 0x66D, 6, 2),\n        (0x66E, 0x66F, 6, 19),\n        (0x670, 0x670, 40, 23),\n        (0x671, 0x6D3, 6, 19),\n        (0x6D4, 0x6D4, 6, 2),\n        (0x6D5, 0x6D5, 6, 19),\n        (0x6D6, 0x6DC, 6, 23),\n        (0x6DD, 0x6DD, 0, 13),\n        (0x6DE, 0x6DE, 6, 11),\n        (0x6DF, 0x6E4, 6, 23),\n        (0x6E5, 0x6E6, 6, 17),\n        (0x6E7, 0x6E8, 6, 23),\n        (0x6E9, 0x6E9, 6, 11),\n        (0x6EA, 0x6ED, 6, 23),\n        (0x6EE, 0x6EF, 6, 19),\n        (0x6F0, 0x6F9, 6, 8),\n        (0x6FA, 0x6FC, 6, 19),\n        (0x6FD, 0x6FE, 6, 11),\n        (0x6FF, 0x6FF, 6, 19),\n        (0x700, 0x70D, 7, 2),\n        (0x70F, 0x70F, 7, 13),\n        (0x710, 0x710, 7, 19),\n        (0x711, 0x711, 7, 23),\n        (0x712, 0x72F, 7, 19),\n        (0x730, 0x74A, 7, 23),\n        (0x74D, 0x74F, 7, 19),\n        (0x750, 0x77F, 6, 19),\n        (0x780, 0x7A5, 8, 19),\n        (0x7A6, 0x7B0, 8, 23),\n        (0x7B1, 0x7B1, 8, 19),\n        (0x7C0, 0x7C9, 65, 8),\n        (0x7CA, 0x7EA, 65, 19),\n        (0x7EB, 0x7F3, 65, 23),\n        (0x7F4, 0x7F5, 65, 17),\n        (0x7F6, 0x7F6, 65, 11),\n        (0x7F7, 0x7F9, 65, 2),\n        (0x7FA, 0x7FA, 65, 17),\n        (0x800, 0x815, 81, 19),\n        (0x816, 0x819, 81, 23),\n        (0x81A, 0x81A, 81, 17),\n        (0x81B, 0x823, 81, 23),\n        (0x824, 0x824, 81, 17),\n        (0x825, 0x827, 81, 23),\n        (0x828, 0x828, 81, 17),\n        (0x829, 0x82D, 81, 23),\n        (0x830, 0x83E, 81, 2),\n        (0x840, 0x858, 94, 19),\n        (0x859, 0x85B, 94, 23),\n        (0x85E, 0x85E, 94, 2),\n        (0x8A0, 0x8A0, 6, 19),\n        (0x8A2, 0x8AC, 6, 19),\n        (0x8E4, 0x8FE, 6, 23),\n        (0x900, 0x902, 9, 23),\n        (0x903, 0x903, 9, 18),\n        (0x904, 0x939, 9, 19),\n        (0x93A, 0x93A, 9, 23),\n        (0x93B, 0x93B, 9, 18),\n        (0x93C, 0x93C, 9, 23),\n        (0x93D, 0x93D, 9, 19),\n        (0x93E, 0x940, 9, 18),\n        (0x941, 0x948, 9, 23),\n        (0x949, 0x94C, 9, 18),\n        (0x94D, 0x94D, 9, 23),\n        (0x94E, 0x94F, 9, 18),\n        (0x950, 0x950, 9, 19),\n        (0x951, 0x952, 40, 23),\n        (0x953, 0x957, 9, 23),\n        (0x958, 0x961, 9, 19),\n        (0x962, 0x963, 9, 23),\n        (0x964, 0x965, 0, 2),\n        (0x966, 0x96F, 9, 8),\n        (0x970, 0x970, 9, 2),\n        (0x971, 0x971, 9, 17),\n        (0x972, 0x977, 9, 19),\n        (0x979, 0x97F, 9, 19),\n        (0x981, 0x981, 10, 23),\n        (0x982, 0x983, 10, 18),\n        (0x985, 0x98C, 10, 19),\n        (0x98F, 0x990, 10, 19),\n        (0x993, 0x9A8, 10, 19),\n        (0x9AA, 0x9B0, 10, 19),\n        (0x9B2, 0x9B2, 10, 19),\n        (0x9B6, 0x9B9, 10, 19),\n        (0x9BC, 0x9BC, 10, 23),\n        (0x9BD, 0x9BD, 10, 19),\n        (0x9BE, 0x9C0, 10, 18),\n        (0x9C1, 0x9C4, 10, 23),\n        (0x9C7, 0x9C8, 10, 18),\n        (0x9CB, 0x9CC, 10, 18),\n        (0x9CD, 0x9CD, 10, 23),\n        (0x9CE, 0x9CE, 10, 19),\n        (0x9D7, 0x9D7, 10, 18),\n        (0x9DC, 0x9DD, 10, 19),\n        (0x9DF, 0x9E1, 10, 19),\n        (0x9E2, 0x9E3, 10, 23),\n        (0x9E6, 0x9EF, 10, 8),\n        (0x9F0, 0x9F1, 10, 19),\n        (0x9F2, 0x9F3, 10, 3),\n        (0x9F4, 0x9F9, 10, 14),\n        (0x9FA, 0x9FA, 10, 11),\n        (0x9FB, 0x9FB, 10, 3),\n        (0xA01, 0xA02, 11, 23),\n        (0xA03, 0xA03, 11, 18),\n        (0xA05, 0xA0A, 11, 19),\n        (0xA0F, 0xA10, 11, 19),\n        (0xA13, 0xA28, 11, 19),\n        (0xA2A, 0xA30, 11, 19),\n        (0xA32, 0xA33, 11, 19),\n        (0xA35, 0xA36, 11, 19),\n        (0xA38, 0xA39, 11, 19),\n        (0xA3C, 0xA3C, 11, 23),\n        (0xA3E, 0xA40, 11, 18),\n        (0xA41, 0xA42, 11, 23),\n        (0xA47, 0xA48, 11, 23),\n        (0xA4B, 0xA4D, 11, 23),\n        (0xA51, 0xA51, 11, 23),\n        (0xA59, 0xA5C, 11, 19),\n        (0xA5E, 0xA5E, 11, 19),\n        (0xA66, 0xA6F, 11, 8),\n        (0xA70, 0xA71, 11, 23),\n        (0xA72, 0xA74, 11, 19),\n        (0xA75, 0xA75, 11, 23),\n        (0xA81, 0xA82, 12, 23),\n        (0xA83, 0xA83, 12, 18),\n        (0xA85, 0xA8D, 12, 19),\n        (0xA8F, 0xA91, 12, 19),\n        (0xA93, 0xAA8, 12, 19),\n        (0xAAA, 0xAB0, 12, 19),\n        (0xAB2, 0xAB3, 12, 19),\n        (0xAB5, 0xAB9, 12, 19),\n        (0xABC, 0xABC, 12, 23),\n        (0xABD, 0xABD, 12, 19),\n        (0xABE, 0xAC0, 12, 18),\n        (0xAC1, 0xAC5, 12, 23),\n        (0xAC7, 0xAC8, 12, 23),\n        (0xAC9, 0xAC9, 12, 18),\n        (0xACB, 0xACC, 12, 18),\n        (0xACD, 0xACD, 12, 23),\n        (0xAD0, 0xAD0, 12, 19),\n        (0xAE0, 0xAE1, 12, 19),\n        (0xAE2, 0xAE3, 12, 23),\n        (0xAE6, 0xAEF, 12, 8),\n        (0xAF0, 0xAF0, 12, 2),\n        (0xAF1, 0xAF1, 12, 3),\n        (0xB01, 0xB01, 13, 23),\n        (0xB02, 0xB03, 13, 18),\n        (0xB05, 0xB0C, 13, 19),\n        (0xB0F, 0xB10, 13, 19),\n        (0xB13, 0xB28, 13, 19),\n        (0xB2A, 0xB30, 13, 19),\n        (0xB32, 0xB33, 13, 19),\n        (0xB35, 0xB39, 13, 19),\n        (0xB3C, 0xB3C, 13, 23),\n        (0xB3D, 0xB3D, 13, 19),\n        (0xB3E, 0xB3E, 13, 18),\n        (0xB3F, 0xB3F, 13, 23),\n        (0xB40, 0xB40, 13, 18),\n        (0xB41, 0xB44, 13, 23),\n        (0xB47, 0xB48, 13, 18),\n        (0xB4B, 0xB4C, 13, 18),\n        (0xB4D, 0xB4D, 13, 23),\n        (0xB56, 0xB56, 13, 23),\n        (0xB57, 0xB57, 13, 18),\n        (0xB5C, 0xB5D, 13, 19),\n        (0xB5F, 0xB61, 13, 19),\n        (0xB62, 0xB63, 13, 23),\n        (0xB66, 0xB6F, 13, 8),\n        (0xB70, 0xB70, 13, 11),\n        (0xB71, 0xB71, 13, 19),\n        (0xB72, 0xB77, 13, 14),\n        (0xB82, 0xB82, 14, 23),\n        (0xB83, 0xB83, 14, 19),\n        (0xB85, 0xB8A, 14, 19),\n        (0xB8E, 0xB90, 14, 19),\n        (0xB92, 0xB95, 14, 19),\n        (0xB99, 0xB9A, 14, 19),\n        (0xB9C, 0xB9C, 14, 19),\n        (0xB9E, 0xB9F, 14, 19),\n        (0xBA3, 0xBA4, 14, 19),\n        (0xBA8, 0xBAA, 14, 19),\n        (0xBAE, 0xBB9, 14, 19),\n        (0xBBE, 0xBBF, 14, 18),\n        (0xBC0, 0xBC0, 14, 23),\n        (0xBC1, 0xBC2, 14, 18),\n        (0xBC6, 0xBC8, 14, 18),\n        (0xBCA, 0xBCC, 14, 18),\n        (0xBCD, 0xBCD, 14, 23),\n        (0xBD0, 0xBD0, 14, 19),\n        (0xBD7, 0xBD7, 14, 18),\n        (0xBE6, 0xBEF, 14, 8),\n        (0xBF0, 0xBF2, 14, 14),\n        (0xBF3, 0xBF8, 14, 11),\n        (0xBF9, 0xBF9, 14, 3),\n        (0xBFA, 0xBFA, 14, 11),\n        (0xC01, 0xC03, 15, 18),\n        (0xC05, 0xC0C, 15, 19),\n        (0xC0E, 0xC10, 15, 19),\n        (0xC12, 0xC28, 15, 19),\n        (0xC2A, 0xC33, 15, 19),\n        (0xC35, 0xC39, 15, 19),\n        (0xC3D, 0xC3D, 15, 19),\n        (0xC3E, 0xC40, 15, 23),\n        (0xC41, 0xC44, 15, 18),\n        (0xC46, 0xC48, 15, 23),\n        (0xC4A, 0xC4D, 15, 23),\n        (0xC55, 0xC56, 15, 23),\n        (0xC58, 0xC59, 15, 19),\n        (0xC60, 0xC61, 15, 19),\n        (0xC62, 0xC63, 15, 23),\n        (0xC66, 0xC6F, 15, 8),\n        (0xC78, 0xC7E, 15, 14),\n        (0xC7F, 0xC7F, 15, 11),\n        (0xC82, 0xC83, 16, 18),\n        (0xC85, 0xC8C, 16, 19),\n        (0xC8E, 0xC90, 16, 19),\n        (0xC92, 0xCA8, 16, 19),\n        (0xCAA, 0xCB3, 16, 19),\n        (0xCB5, 0xCB9, 16, 19),\n        (0xCBC, 0xCBC, 16, 23),\n        (0xCBD, 0xCBD, 16, 19),\n        (0xCBE, 0xCBE, 16, 18),\n        (0xCBF, 0xCBF, 16, 23),\n        (0xCC0, 0xCC4, 16, 18),\n        (0xCC6, 0xCC6, 16, 23),\n        (0xCC7, 0xCC8, 16, 18),\n        (0xCCA, 0xCCB, 16, 18),\n        (0xCCC, 0xCCD, 16, 23),\n        (0xCD5, 0xCD6, 16, 18),\n        (0xCDE, 0xCDE, 16, 19),\n        (0xCE0, 0xCE1, 16, 19),\n        (0xCE2, 0xCE3, 16, 23),\n        (0xCE6, 0xCEF, 16, 8),\n        (0xCF1, 0xCF2, 16, 19),\n        (0xD02, 0xD03, 17, 18),\n        (0xD05, 0xD0C, 17, 19),\n        (0xD0E, 0xD10, 17, 19),\n        (0xD12, 0xD3A, 17, 19),\n        (0xD3D, 0xD3D, 17, 19),\n        (0xD3E, 0xD40, 17, 18),\n        (0xD41, 0xD44, 17, 23),\n        (0xD46, 0xD48, 17, 18),\n        (0xD4A, 0xD4C, 17, 18),\n        (0xD4D, 0xD4D, 17, 23),\n        (0xD4E, 0xD4E, 17, 19),\n        (0xD57, 0xD57, 17, 18),\n        (0xD60, 0xD61, 17, 19),\n        (0xD62, 0xD63, 17, 23),\n        (0xD66, 0xD6F, 17, 8),\n        (0xD70, 0xD75, 17, 14),\n        (0xD79, 0xD79, 17, 11),\n        (0xD7A, 0xD7F, 17, 19),\n        (0xD82, 0xD83, 18, 18),\n        (0xD85, 0xD96, 18, 19),\n        (0xD9A, 0xDB1, 18, 19),\n        (0xDB3, 0xDBB, 18, 19),\n        (0xDBD, 0xDBD, 18, 19),\n        (0xDC0, 0xDC6, 18, 19),\n        (0xDCA, 0xDCA, 18, 23),\n        (0xDCF, 0xDD1, 18, 18),\n        (0xDD2, 0xDD4, 18, 23),\n        (0xDD6, 0xDD6, 18, 23),\n        (0xDD8, 0xDDF, 18, 18),\n        (0xDF2, 0xDF3, 18, 18),\n        (0xDF4, 0xDF4, 18, 2),\n        (0xE01, 0xE30, 19, 19),\n        (0xE31, 0xE31, 19, 23),\n        (0xE32, 0xE33, 19, 19),\n        (0xE34, 0xE3A, 19, 23),\n        (0xE3F, 0xE3F, 0, 3),\n        (0xE40, 0xE45, 19, 19),\n        (0xE46, 0xE46, 19, 17),\n        (0xE47, 0xE4E, 19, 23),\n        (0xE4F, 0xE4F, 19, 2),\n        (0xE50, 0xE59, 19, 8),\n        (0xE5A, 0xE5B, 19, 2),\n        (0xE81, 0xE82, 20, 19),\n        (0xE84, 0xE84, 20, 19),\n        (0xE87, 0xE88, 20, 19),\n        (0xE8A, 0xE8A, 20, 19),\n        (0xE8D, 0xE8D, 20, 19),\n        (0xE94, 0xE97, 20, 19),\n        (0xE99, 0xE9F, 20, 19),\n        (0xEA1, 0xEA3, 20, 19),\n        (0xEA5, 0xEA5, 20, 19),\n        (0xEA7, 0xEA7, 20, 19),\n        (0xEAA, 0xEAB, 20, 19),\n        (0xEAD, 0xEB0, 20, 19),\n        (0xEB1, 0xEB1, 20, 23),\n        (0xEB2, 0xEB3, 20, 19),\n        (0xEB4, 0xEB9, 20, 23),\n        (0xEBB, 0xEBC, 20, 23),\n        (0xEBD, 0xEBD, 20, 19),\n        (0xEC0, 0xEC4, 20, 19),\n        (0xEC6, 0xEC6, 20, 17),\n        (0xEC8, 0xECD, 20, 23),\n        (0xED0, 0xED9, 20, 8),\n        (0xEDC, 0xEDF, 20, 19),\n        (0xF00, 0xF00, 21, 19),\n        (0xF01, 0xF03, 21, 11),\n        (0xF04, 0xF12, 21, 2),\n        (0xF13, 0xF13, 21, 11),\n        (0xF14, 0xF14, 21, 2),\n        (0xF15, 0xF17, 21, 11),\n        (0xF18, 0xF19, 21, 23),\n        (0xF1A, 0xF1F, 21, 11),\n        (0xF20, 0xF29, 21, 8),\n        (0xF2A, 0xF33, 21, 14),\n        (0xF34, 0xF34, 21, 11),\n        (0xF35, 0xF35, 21, 23),\n        (0xF36, 0xF36, 21, 11),\n        (0xF37, 0xF37, 21, 23),\n        (0xF38, 0xF38, 21, 11),\n        (0xF39, 0xF39, 21, 23),\n        (0xF3A, 0xF3A, 21, 4),\n        (0xF3B, 0xF3B, 21, 5),\n        (0xF3C, 0xF3C, 21, 4),\n        (0xF3D, 0xF3D, 21, 5),\n        (0xF3E, 0xF3F, 21, 18),\n        (0xF40, 0xF47, 21, 19),\n        (0xF49, 0xF6C, 21, 19),\n        (0xF71, 0xF7E, 21, 23),\n        (0xF7F, 0xF7F, 21, 18),\n        (0xF80, 0xF84, 21, 23),\n        (0xF85, 0xF85, 21, 2),\n        (0xF86, 0xF87, 21, 23),\n        (0xF88, 0xF8C, 21, 19),\n        (0xF8D, 0xF97, 21, 23),\n        (0xF99, 0xFBC, 21, 23),\n        (0xFBE, 0xFC5, 21, 11),\n        (0xFC6, 0xFC6, 21, 23),\n        (0xFC7, 0xFCC, 21, 11),\n        (0xFCE, 0xFCF, 21, 11),\n        (0xFD0, 0xFD4, 21, 2),\n        (0xFD5, 0xFD8, 0, 11),\n        (0xFD9, 0xFDA, 21, 2),\n        (0x1000, 0x102A, 22, 19),\n        (0x102B, 0x102C, 22, 18),\n        (0x102D, 0x1030, 22, 23),\n        (0x1031, 0x1031, 22, 18),\n        (0x1032, 0x1037, 22, 23),\n        (0x1038, 0x1038, 22, 18),\n        (0x1039, 0x103A, 22, 23),\n        (0x103B, 0x103C, 22, 18),\n        (0x103D, 0x103E, 22, 23),\n        (0x103F, 0x103F, 22, 19),\n        (0x1040, 0x1049, 22, 8),\n        (0x104A, 0x104F, 22, 2),\n        (0x1050, 0x1055, 22, 19),\n        (0x1056, 0x1057, 22, 18),\n        (0x1058, 0x1059, 22, 23),\n        (0x105A, 0x105D, 22, 19),\n        (0x105E, 0x1060, 22, 23),\n        (0x1061, 0x1061, 22, 19),\n        (0x1062, 0x1064, 22, 18),\n        (0x1065, 0x1066, 22, 19),\n        (0x1067, 0x106D, 22, 18),\n        (0x106E, 0x1070, 22, 19),\n        (0x1071, 0x1074, 22, 23),\n        (0x1075, 0x1081, 22, 19),\n        (0x1082, 0x1082, 22, 23),\n        (0x1083, 0x1084, 22, 18),\n        (0x1085, 0x1086, 22, 23),\n        (0x1087, 0x108C, 22, 18),\n        (0x108D, 0x108D, 22, 23),\n        (0x108E, 0x108E, 22, 19),\n        (0x108F, 0x108F, 22, 18),\n        (0x1090, 0x1099, 22, 8),\n        (0x109A, 0x109C, 22, 18),\n        (0x109D, 0x109D, 22, 23),\n        (0x109E, 0x109F, 22, 11),\n        (0x10A0, 0x10C5, 23, 15),\n        (0x10C7, 0x10C7, 23, 15),\n        (0x10CD, 0x10CD, 23, 15),\n        (0x10D0, 0x10FA, 23, 19),\n        (0x10FB, 0x10FB, 0, 2),\n        (0x10FC, 0x10FC, 23, 17),\n        (0x10FD, 0x10FF, 23, 19),\n        (0x1100, 0x11FF, 24, 19),\n        (0x1200, 0x1248, 25, 19),\n        (0x124A, 0x124D, 25, 19),\n        (0x1250, 0x1256, 25, 19),\n        (0x1258, 0x1258, 25, 19),\n        (0x125A, 0x125D, 25, 19),\n        (0x1260, 0x1288, 25, 19),\n        (0x128A, 0x128D, 25, 19),\n        (0x1290, 0x12B0, 25, 19),\n        (0x12B2, 0x12B5, 25, 19),\n        (0x12B8, 0x12BE, 25, 19),\n        (0x12C0, 0x12C0, 25, 19),\n        (0x12C2, 0x12C5, 25, 19),\n        (0x12C8, 0x12D6, 25, 19),\n        (0x12D8, 0x1310, 25, 19),\n        (0x1312, 0x1315, 25, 19),\n        (0x1318, 0x135A, 25, 19),\n        (0x135D, 0x135F, 25, 23),\n        (0x1360, 0x1368, 25, 2),\n        (0x1369, 0x137C, 25, 14),\n        (0x1380, 0x138F, 25, 19),\n        (0x1390, 0x1399, 25, 11),\n        (0x13A0, 0x13F4, 26, 19),\n        (0x1400, 0x1400, 27, 7),\n        (0x1401, 0x166C, 27, 19),\n        (0x166D, 0x166E, 27, 2),\n        (0x166F, 0x167F, 27, 19),\n        (0x1680, 0x1680, 28, 1),\n        (0x1681, 0x169A, 28, 19),\n        (0x169B, 0x169B, 28, 4),\n        (0x169C, 0x169C, 28, 5),\n        (0x16A0, 0x16EA, 29, 19),\n        (0x16EB, 0x16ED, 0, 2),\n        (0x16EE, 0x16F0, 29, 22),\n        (0x1700, 0x170C, 41, 19),\n        (0x170E, 0x1711, 41, 19),\n        (0x1712, 0x1714, 41, 23),\n        (0x1720, 0x1731, 42, 19),\n        (0x1732, 0x1734, 42, 23),\n        (0x1735, 0x1736, 0, 2),\n        (0x1740, 0x1751, 43, 19),\n        (0x1752, 0x1753, 43, 23),\n        (0x1760, 0x176C, 44, 19),\n        (0x176E, 0x1770, 44, 19),\n        (0x1772, 0x1773, 44, 23),\n        (0x1780, 0x17B3, 30, 19),\n        (0x17B4, 0x17B5, 30, 23),\n        (0x17B6, 0x17B6, 30, 18),\n        (0x17B7, 0x17BD, 30, 23),\n        (0x17BE, 0x17C5, 30, 18),\n        (0x17C6, 0x17C6, 30, 23),\n        (0x17C7, 0x17C8, 30, 18),\n        (0x17C9, 0x17D3, 30, 23),\n        (0x17D4, 0x17D6, 30, 2),\n        (0x17D7, 0x17D7, 30, 17),\n        (0x17D8, 0x17DA, 30, 2),\n        (0x17DB, 0x17DB, 30, 3),\n        (0x17DC, 0x17DC, 30, 19),\n        (0x17DD, 0x17DD, 30, 23),\n        (0x17E0, 0x17E9, 30, 8),\n        (0x17F0, 0x17F9, 30, 14),\n        (0x1800, 0x1801, 31, 2),\n        (0x1802, 0x1803, 0, 2),\n        (0x1804, 0x1804, 31, 2),\n        (0x1805, 0x1805, 0, 2),\n        (0x1806, 0x1806, 31, 7),\n        (0x1807, 0x180A, 31, 2),\n        (0x180B, 0x180D, 31, 23),\n        (0x180E, 0x180E, 31, 1),\n        (0x1810, 0x1819, 31, 8),\n        (0x1820, 0x1842, 31, 19),\n        (0x1843, 0x1843, 31, 17),\n        (0x1844, 0x1877, 31, 19),\n        (0x1880, 0x18A8, 31, 19),\n        (0x18A9, 0x18A9, 31, 23),\n        (0x18AA, 0x18AA, 31, 19),\n        (0x18B0, 0x18F5, 27, 19),\n        (0x1900, 0x191C, 45, 19),\n        (0x1920, 0x1922, 45, 23),\n        (0x1923, 0x1926, 45, 18),\n        (0x1927, 0x1928, 45, 23),\n        (0x1929, 0x192B, 45, 18),\n        (0x1930, 0x1931, 45, 18),\n        (0x1932, 0x1932, 45, 23),\n        (0x1933, 0x1938, 45, 18),\n        (0x1939, 0x193B, 45, 23),\n        (0x1940, 0x1940, 45, 11),\n        (0x1944, 0x1945, 45, 2),\n        (0x1946, 0x194F, 45, 8),\n        (0x1950, 0x196D, 46, 19),\n        (0x1970, 0x1974, 46, 19),\n        (0x1980, 0x19AB, 55, 19),\n        (0x19B0, 0x19C0, 55, 18),\n        (0x19C1, 0x19C7, 55, 19),\n        (0x19C8, 0x19C9, 55, 18),\n        (0x19D0, 0x19D9, 55, 8),\n        (0x19DA, 0x19DA, 55, 14),\n        (0x19DE, 0x19DF, 55, 11),\n        (0x19E0, 0x19FF, 30, 11),\n        (0x1A00, 0x1A16, 53, 19),\n        (0x1A17, 0x1A18, 53, 23),\n        (0x1A19, 0x1A1B, 53, 18),\n        (0x1A1E, 0x1A1F, 53, 2),\n        (0x1A20, 0x1A54, 77, 19),\n        (0x1A55, 0x1A55, 77, 18),\n        (0x1A56, 0x1A56, 77, 23),\n        (0x1A57, 0x1A57, 77, 18),\n        (0x1A58, 0x1A5E, 77, 23),\n        (0x1A60, 0x1A60, 77, 23),\n        (0x1A61, 0x1A61, 77, 18),\n        (0x1A62, 0x1A62, 77, 23),\n        (0x1A63, 0x1A64, 77, 18),\n        (0x1A65, 0x1A6C, 77, 23),\n        (0x1A6D, 0x1A72, 77, 18),\n        (0x1A73, 0x1A7C, 77, 23),\n        (0x1A7F, 0x1A7F, 77, 23),\n        (0x1A80, 0x1A89, 77, 8),\n        (0x1A90, 0x1A99, 77, 8),\n        (0x1AA0, 0x1AA6, 77, 2),\n        (0x1AA7, 0x1AA7, 77, 17),\n        (0x1AA8, 0x1AAD, 77, 2),\n        (0x1B00, 0x1B03, 61, 23),\n        (0x1B04, 0x1B04, 61, 18),\n        (0x1B05, 0x1B33, 61, 19),\n        (0x1B34, 0x1B34, 61, 23),\n        (0x1B35, 0x1B35, 61, 18),\n        (0x1B36, 0x1B3A, 61, 23),\n        (0x1B3B, 0x1B3B, 61, 18),\n        (0x1B3C, 0x1B3C, 61, 23),\n        (0x1B3D, 0x1B41, 61, 18),\n        (0x1B42, 0x1B42, 61, 23),\n        (0x1B43, 0x1B44, 61, 18),\n        (0x1B45, 0x1B4B, 61, 19),\n        (0x1B50, 0x1B59, 61, 8),\n        (0x1B5A, 0x1B60, 61, 2),\n        (0x1B61, 0x1B6A, 61, 11),\n        (0x1B6B, 0x1B73, 61, 23),\n        (0x1B74, 0x1B7C, 61, 11),\n        (0x1B80, 0x1B81, 66, 23),\n        (0x1B82, 0x1B82, 66, 18),\n        (0x1B83, 0x1BA0, 66, 19),\n        (0x1BA1, 0x1BA1, 66, 18),\n        (0x1BA2, 0x1BA5, 66, 23),\n        (0x1BA6, 0x1BA7, 66, 18),\n        (0x1BA8, 0x1BA9, 66, 23),\n        (0x1BAA, 0x1BAA, 66, 18),\n        (0x1BAB, 0x1BAB, 66, 23),\n        (0x1BAC, 0x1BAD, 66, 18),\n        (0x1BAE, 0x1BAF, 66, 19),\n        (0x1BB0, 0x1BB9, 66, 8),\n        (0x1BBA, 0x1BBF, 66, 19),\n        (0x1BC0, 0x1BE5, 92, 19),\n        (0x1BE6, 0x1BE6, 92, 23),\n        (0x1BE7, 0x1BE7, 92, 18),\n        (0x1BE8, 0x1BE9, 92, 23),\n        (0x1BEA, 0x1BEC, 92, 18),\n        (0x1BED, 0x1BED, 92, 23),\n        (0x1BEE, 0x1BEE, 92, 18),\n        (0x1BEF, 0x1BF1, 92, 23),\n        (0x1BF2, 0x1BF3, 92, 18),\n        (0x1BFC, 0x1BFF, 92, 2),\n        (0x1C00, 0x1C23, 67, 19),\n        (0x1C24, 0x1C2B, 67, 18),\n        (0x1C2C, 0x1C33, 67, 23),\n        (0x1C34, 0x1C35, 67, 18),\n        (0x1C36, 0x1C37, 67, 23),\n        (0x1C3B, 0x1C3F, 67, 2),\n        (0x1C40, 0x1C49, 67, 8),\n        (0x1C4D, 0x1C4F, 67, 19),\n        (0x1C50, 0x1C59, 68, 8),\n        (0x1C5A, 0x1C77, 68, 19),\n        (0x1C78, 0x1C7D, 68, 17),\n        (0x1C7E, 0x1C7F, 68, 2),\n        (0x1CC0, 0x1CC7, 66, 2),\n        (0x1CD0, 0x1CD2, 40, 23),\n        (0x1CD3, 0x1CD3, 0, 2),\n        (0x1CD4, 0x1CE0, 40, 23),\n        (0x1CE1, 0x1CE1, 0, 18),\n        (0x1CE2, 0x1CE8, 40, 23),\n        (0x1CE9, 0x1CEC, 0, 19),\n        (0x1CED, 0x1CED, 40, 23),\n        (0x1CEE, 0x1CF1, 0, 19),\n        (0x1CF2, 0x1CF3, 0, 18),\n        (0x1CF4, 0x1CF4, 40, 23),\n        (0x1CF5, 0x1CF6, 0, 19),\n        (0x1D00, 0x1D25, 1, 15),\n        (0x1D26, 0x1D2A, 2, 15),\n        (0x1D2B, 0x1D2B, 3, 15),\n        (0x1D2C, 0x1D5C, 1, 17),\n        (0x1D5D, 0x1D61, 2, 17),\n        (0x1D62, 0x1D65, 1, 17),\n        (0x1D66, 0x1D6A, 2, 17),\n        (0x1D6B, 0x1D77, 1, 15),\n        (0x1D78, 0x1D78, 3, 17),\n        (0x1D79, 0x1D9A, 1, 15),\n        (0x1D9B, 0x1DBE, 1, 17),\n        (0x1DBF, 0x1DBF, 2, 17),\n        (0x1DC0, 0x1DE6, 40, 23),\n        (0x1DFC, 0x1DFF, 40, 23),\n        (0x1E00, 0x1EFF, 1, 15),\n        (0x1F00, 0x1F15, 2, 15),\n        (0x1F18, 0x1F1D, 2, 15),\n        (0x1F20, 0x1F45, 2, 15),\n        (0x1F48, 0x1F4D, 2, 15),\n        (0x1F50, 0x1F57, 2, 15),\n        (0x1F59, 0x1F59, 2, 15),\n        (0x1F5B, 0x1F5B, 2, 15),\n        (0x1F5D, 0x1F5D, 2, 15),\n        (0x1F5F, 0x1F7D, 2, 15),\n        (0x1F80, 0x1FB4, 2, 15),\n        (0x1FB6, 0x1FBC, 2, 15),\n        (0x1FBD, 0x1FBD, 2, 9),\n        (0x1FBE, 0x1FBE, 2, 15),\n        (0x1FBF, 0x1FC1, 2, 9),\n        (0x1FC2, 0x1FC4, 2, 15),\n        (0x1FC6, 0x1FCC, 2, 15),\n        (0x1FCD, 0x1FCF, 2, 9),\n        (0x1FD0, 0x1FD3, 2, 15),\n        (0x1FD6, 0x1FDB, 2, 15),\n        (0x1FDD, 0x1FDF, 2, 9),\n        (0x1FE0, 0x1FEC, 2, 15),\n        (0x1FED, 0x1FEF, 2, 9),\n        (0x1FF2, 0x1FF4, 2, 15),\n        (0x1FF6, 0x1FFC, 2, 15),\n        (0x1FFD, 0x1FFE, 2, 9),\n        (0x2000, 0x200A, 0, 1),\n        (0x200B, 0x200B, 0, 13),\n        (0x200C, 0x200D, 40, 13),\n        (0x200E, 0x200F, 0, 13),\n        (0x2010, 0x2015, 0, 7),\n        (0x2016, 0x2017, 0, 2),\n        (0x2018, 0x2018, 0, 12),\n        (0x2019, 0x2019, 0, 16),\n        (0x201A, 0x201A, 0, 4),\n        (0x201B, 0x201C, 0, 12),\n        (0x201D, 0x201D, 0, 16),\n        (0x201E, 0x201E, 0, 4),\n        (0x201F, 0x201F, 0, 12),\n        (0x2020, 0x2027, 0, 2),\n        (0x2028, 0x2028, 0, 20),\n        (0x2029, 0x2029, 0, 21),\n        (0x202A, 0x202E, 0, 13),\n        (0x202F, 0x202F, 0, 1),\n        (0x2030, 0x2038, 0, 2),\n        (0x2039, 0x2039, 0, 12),\n        (0x203A, 0x203A, 0, 16),\n        (0x203B, 0x203E, 0, 2),\n        (0x203F, 0x2040, 0, 10),\n        (0x2041, 0x2043, 0, 2),\n        (0x2044, 0x2044, 0, 6),\n        (0x2045, 0x2045, 0, 4),\n        (0x2046, 0x2046, 0, 5),\n        (0x2047, 0x2051, 0, 2),\n        (0x2052, 0x2052, 0, 6),\n        (0x2053, 0x2053, 0, 2),\n        (0x2054, 0x2054, 0, 10),\n        (0x2055, 0x205E, 0, 2),\n        (0x205F, 0x205F, 0, 1),\n        (0x2060, 0x2064, 0, 13),\n        (0x206A, 0x206F, 0, 13),\n        (0x2070, 0x2070, 0, 14),\n        (0x2071, 0x2071, 1, 17),\n        (0x2074, 0x2079, 0, 14),\n        (0x207A, 0x207C, 0, 6),\n        (0x207D, 0x207D, 0, 4),\n        (0x207E, 0x207E, 0, 5),\n        (0x207F, 0x207F, 1, 17),\n        (0x2080, 0x2089, 0, 14),\n        (0x208A, 0x208C, 0, 6),\n        (0x208D, 0x208D, 0, 4),\n        (0x208E, 0x208E, 0, 5),\n        (0x2090, 0x209C, 1, 17),\n        (0x20A0, 0x20B9, 0, 3),\n        (0x20D0, 0x20DC, 40, 23),\n        (0x20DD, 0x20E0, 40, 24),\n        (0x20E1, 0x20E1, 40, 23),\n        (0x20E2, 0x20E4, 40, 24),\n        (0x20E5, 0x20F0, 40, 23),\n        (0x2100, 0x2101, 0, 11),\n        (0x2102, 0x2102, 0, 15),\n        (0x2103, 0x2106, 0, 11),\n        (0x2107, 0x2107, 0, 15),\n        (0x2108, 0x2109, 0, 11),\n        (0x210A, 0x2113, 0, 15),\n        (0x2114, 0x2114, 0, 11),\n        (0x2115, 0x2115, 0, 15),\n        (0x2116, 0x2117, 0, 11),\n        (0x2118, 0x2118, 0, 6),\n        (0x2119, 0x211D, 0, 15),\n        (0x211E, 0x2123, 0, 11),\n        (0x2124, 0x2124, 0, 15),\n        (0x2125, 0x2125, 0, 11),\n        (0x2126, 0x2126, 2, 15),\n        (0x2127, 0x2127, 0, 11),\n        (0x2128, 0x2128, 0, 15),\n        (0x2129, 0x2129, 0, 11),\n        (0x212A, 0x212B, 1, 15),\n        (0x212C, 0x212D, 0, 15),\n        (0x212E, 0x212E, 0, 11),\n        (0x212F, 0x2131, 0, 15),\n        (0x2132, 0x2132, 1, 15),\n        (0x2133, 0x2134, 0, 15),\n        (0x2135, 0x2138, 0, 19),\n        (0x2139, 0x2139, 0, 15),\n        (0x213A, 0x213B, 0, 11),\n        (0x213C, 0x213F, 0, 15),\n        (0x2140, 0x2144, 0, 6),\n        (0x2145, 0x2149, 0, 15),\n        (0x214A, 0x214A, 0, 11),\n        (0x214B, 0x214B, 0, 6),\n        (0x214C, 0x214D, 0, 11),\n        (0x214E, 0x214E, 1, 15),\n        (0x214F, 0x214F, 0, 11),\n        (0x2150, 0x215F, 0, 14),\n        (0x2160, 0x2182, 1, 22),\n        (0x2183, 0x2184, 1, 15),\n        (0x2185, 0x2188, 1, 22),\n        (0x2189, 0x2189, 0, 14),\n        (0x2190, 0x2194, 0, 6),\n        (0x2195, 0x2199, 0, 11),\n        (0x219A, 0x219B, 0, 6),\n        (0x219C, 0x219F, 0, 11),\n        (0x21A0, 0x21A0, 0, 6),\n        (0x21A1, 0x21A2, 0, 11),\n        (0x21A3, 0x21A3, 0, 6),\n        (0x21A4, 0x21A5, 0, 11),\n        (0x21A6, 0x21A6, 0, 6),\n        (0x21A7, 0x21AD, 0, 11),\n        (0x21AE, 0x21AE, 0, 6),\n        (0x21AF, 0x21CD, 0, 11),\n        (0x21CE, 0x21CF, 0, 6),\n        (0x21D0, 0x21D1, 0, 11),\n        (0x21D2, 0x21D2, 0, 6),\n        (0x21D3, 0x21D3, 0, 11),\n        (0x21D4, 0x21D4, 0, 6),\n        (0x21D5, 0x21F3, 0, 11),\n        (0x21F4, 0x22FF, 0, 6),\n        (0x2300, 0x2307, 0, 11),\n        (0x2308, 0x230B, 0, 6),\n        (0x230C, 0x231F, 0, 11),\n        (0x2320, 0x2321, 0, 6),\n        (0x2322, 0x2328, 0, 11),\n        (0x2329, 0x2329, 0, 4),\n        (0x232A, 0x232A, 0, 5),\n        (0x232B, 0x237B, 0, 11),\n        (0x237C, 0x237C, 0, 6),\n        (0x237D, 0x239A, 0, 11),\n        (0x239B, 0x23B3, 0, 6),\n        (0x23B4, 0x23DB, 0, 11),\n        (0x23DC, 0x23E1, 0, 6),\n        (0x23E2, 0x23F3, 0, 11),\n        (0x2400, 0x2426, 0, 11),\n        (0x2440, 0x244A, 0, 11),\n        (0x2460, 0x249B, 0, 14),\n        (0x249C, 0x24E9, 0, 11),\n        (0x24EA, 0x24FF, 0, 14),\n        (0x2500, 0x25B6, 0, 11),\n        (0x25B7, 0x25B7, 0, 6),\n        (0x25B8, 0x25C0, 0, 11),\n        (0x25C1, 0x25C1, 0, 6),\n        (0x25C2, 0x25F7, 0, 11),\n        (0x25F8, 0x25FF, 0, 6),\n        (0x2600, 0x266E, 0, 11),\n        (0x266F, 0x266F, 0, 6),\n        (0x2670, 0x26FF, 0, 11),\n        (0x2701, 0x2767, 0, 11),\n        (0x2768, 0x2768, 0, 4),\n        (0x2769, 0x2769, 0, 5),\n        (0x276A, 0x276A, 0, 4),\n        (0x276B, 0x276B, 0, 5),\n        (0x276C, 0x276C, 0, 4),\n        (0x276D, 0x276D, 0, 5),\n        (0x276E, 0x276E, 0, 4),\n        (0x276F, 0x276F, 0, 5),\n        (0x2770, 0x2770, 0, 4),\n        (0x2771, 0x2771, 0, 5),\n        (0x2772, 0x2772, 0, 4),\n        (0x2773, 0x2773, 0, 5),\n        (0x2774, 0x2774, 0, 4),\n        (0x2775, 0x2775, 0, 5),\n        (0x2776, 0x2793, 0, 14),\n        (0x2794, 0x27BF, 0, 11),\n        (0x27C0, 0x27C4, 0, 6),\n        (0x27C5, 0x27C5, 0, 4),\n        (0x27C6, 0x27C6, 0, 5),\n        (0x27C7, 0x27E5, 0, 6),\n        (0x27E6, 0x27E6, 0, 4),\n        (0x27E7, 0x27E7, 0, 5),\n        (0x27E8, 0x27E8, 0, 4),\n        (0x27E9, 0x27E9, 0, 5),\n        (0x27EA, 0x27EA, 0, 4),\n        (0x27EB, 0x27EB, 0, 5),\n        (0x27EC, 0x27EC, 0, 4),\n        (0x27ED, 0x27ED, 0, 5),\n        (0x27EE, 0x27EE, 0, 4),\n        (0x27EF, 0x27EF, 0, 5),\n        (0x27F0, 0x27FF, 0, 6),\n        (0x2800, 0x28FF, 52, 11),\n        (0x2900, 0x2982, 0, 6),\n        (0x2983, 0x2983, 0, 4),\n        (0x2984, 0x2984, 0, 5),\n        (0x2985, 0x2985, 0, 4),\n        (0x2986, 0x2986, 0, 5),\n        (0x2987, 0x2987, 0, 4),\n        (0x2988, 0x2988, 0, 5),\n        (0x2989, 0x2989, 0, 4),\n        (0x298A, 0x298A, 0, 5),\n        (0x298B, 0x298B, 0, 4),\n        (0x298C, 0x298C, 0, 5),\n        (0x298D, 0x298D, 0, 4),\n        (0x298E, 0x298E, 0, 5),\n        (0x298F, 0x298F, 0, 4),\n        (0x2990, 0x2990, 0, 5),\n        (0x2991, 0x2991, 0, 4),\n        (0x2992, 0x2992, 0, 5),\n        (0x2993, 0x2993, 0, 4),\n        (0x2994, 0x2994, 0, 5),\n        (0x2995, 0x2995, 0, 4),\n        (0x2996, 0x2996, 0, 5),\n        (0x2997, 0x2997, 0, 4),\n        (0x2998, 0x2998, 0, 5),\n        (0x2999, 0x29D7, 0, 6),\n        (0x29D8, 0x29D8, 0, 4),\n        (0x29D9, 0x29D9, 0, 5),\n        (0x29DA, 0x29DA, 0, 4),\n        (0x29DB, 0x29DB, 0, 5),\n        (0x29DC, 0x29FB, 0, 6),\n        (0x29FC, 0x29FC, 0, 4),\n        (0x29FD, 0x29FD, 0, 5),\n        (0x29FE, 0x2AFF, 0, 6),\n        (0x2B00, 0x2B2F, 0, 11),\n        (0x2B30, 0x2B44, 0, 6),\n        (0x2B45, 0x2B46, 0, 11),\n        (0x2B47, 0x2B4C, 0, 6),\n        (0x2B50, 0x2B59, 0, 11),\n        (0x2C00, 0x2C2E, 56, 15),\n        (0x2C30, 0x2C5E, 56, 15),\n        (0x2C60, 0x2C7B, 1, 15),\n        (0x2C7C, 0x2C7D, 1, 17),\n        (0x2C7E, 0x2C7F, 1, 15),\n        (0x2C80, 0x2CE4, 54, 15),\n        (0x2CE5, 0x2CEA, 54, 11),\n        (0x2CEB, 0x2CEE, 54, 15),\n        (0x2CEF, 0x2CF1, 54, 23),\n        (0x2CF2, 0x2CF3, 54, 15),\n        (0x2CF9, 0x2CFC, 54, 2),\n        (0x2CFD, 0x2CFD, 54, 14),\n        (0x2CFE, 0x2CFF, 54, 2),\n        (0x2D00, 0x2D25, 23, 15),\n        (0x2D27, 0x2D27, 23, 15),\n        (0x2D2D, 0x2D2D, 23, 15),\n        (0x2D30, 0x2D67, 57, 19),\n        (0x2D6F, 0x2D6F, 57, 17),\n        (0x2D70, 0x2D70, 57, 2),\n        (0x2D7F, 0x2D7F, 57, 23),\n        (0x2D80, 0x2D96, 25, 19),\n        (0x2DA0, 0x2DA6, 25, 19),\n        (0x2DA8, 0x2DAE, 25, 19),\n        (0x2DB0, 0x2DB6, 25, 19),\n        (0x2DB8, 0x2DBE, 25, 19),\n        (0x2DC0, 0x2DC6, 25, 19),\n        (0x2DC8, 0x2DCE, 25, 19),\n        (0x2DD0, 0x2DD6, 25, 19),\n        (0x2DD8, 0x2DDE, 25, 19),\n        (0x2DE0, 0x2DFF, 3, 23),\n        (0x2E00, 0x2E01, 0, 2),\n        (0x2E02, 0x2E02, 0, 12),\n        (0x2E03, 0x2E03, 0, 16),\n        (0x2E04, 0x2E04, 0, 12),\n        (0x2E05, 0x2E05, 0, 16),\n        (0x2E06, 0x2E08, 0, 2),\n        (0x2E09, 0x2E09, 0, 12),\n        (0x2E0A, 0x2E0A, 0, 16),\n        (0x2E0B, 0x2E0B, 0, 2),\n        (0x2E0C, 0x2E0C, 0, 12),\n        (0x2E0D, 0x2E0D, 0, 16),\n        (0x2E0E, 0x2E16, 0, 2),\n        (0x2E17, 0x2E17, 0, 7),\n        (0x2E18, 0x2E19, 0, 2),\n        (0x2E1A, 0x2E1A, 0, 7),\n        (0x2E1B, 0x2E1B, 0, 2),\n        (0x2E1C, 0x2E1C, 0, 12),\n        (0x2E1D, 0x2E1D, 0, 16),\n        (0x2E1E, 0x2E1F, 0, 2),\n        (0x2E20, 0x2E20, 0, 12),\n        (0x2E21, 0x2E21, 0, 16),\n        (0x2E22, 0x2E22, 0, 4),\n        (0x2E23, 0x2E23, 0, 5),\n        (0x2E24, 0x2E24, 0, 4),\n        (0x2E25, 0x2E25, 0, 5),\n        (0x2E26, 0x2E26, 0, 4),\n        (0x2E27, 0x2E27, 0, 5),\n        (0x2E28, 0x2E28, 0, 4),\n        (0x2E29, 0x2E29, 0, 5),\n        (0x2E2A, 0x2E2E, 0, 2),\n        (0x2E2F, 0x2E2F, 0, 17),\n        (0x2E30, 0x2E39, 0, 2),\n        (0x2E3A, 0x2E3B, 0, 7),\n        (0x2E80, 0x2E99, 35, 11),\n        (0x2E9B, 0x2EF3, 35, 11),\n        (0x2F00, 0x2FD5, 35, 11),\n        (0x2FF0, 0x2FFB, 0, 11),\n        (0x3000, 0x3000, 0, 1),\n        (0x3001, 0x3003, 0, 2),\n        (0x3004, 0x3004, 0, 11),\n        (0x3005, 0x3005, 35, 17),\n        (0x3006, 0x3006, 0, 19),\n        (0x3007, 0x3007, 35, 22),\n        (0x3008, 0x3008, 0, 4),\n        (0x3009, 0x3009, 0, 5),\n        (0x300A, 0x300A, 0, 4),\n        (0x300B, 0x300B, 0, 5),\n        (0x300C, 0x300C, 0, 4),\n        (0x300D, 0x300D, 0, 5),\n        (0x300E, 0x300E, 0, 4),\n        (0x300F, 0x300F, 0, 5),\n        (0x3010, 0x3010, 0, 4),\n        (0x3011, 0x3011, 0, 5),\n        (0x3012, 0x3013, 0, 11),\n        (0x3014, 0x3014, 0, 4),\n        (0x3015, 0x3015, 0, 5),\n        (0x3016, 0x3016, 0, 4),\n        (0x3017, 0x3017, 0, 5),\n        (0x3018, 0x3018, 0, 4),\n        (0x3019, 0x3019, 0, 5),\n        (0x301A, 0x301A, 0, 4),\n        (0x301B, 0x301B, 0, 5),\n        (0x301C, 0x301C, 0, 7),\n        (0x301D, 0x301D, 0, 4),\n        (0x301E, 0x301F, 0, 5),\n        (0x3020, 0x3020, 0, 11),\n        (0x3021, 0x3029, 35, 22),\n        (0x302A, 0x302D, 40, 23),\n        (0x302E, 0x302F, 24, 18),\n        (0x3030, 0x3030, 0, 7),\n        (0x3031, 0x3035, 0, 17),\n        (0x3036, 0x3037, 0, 11),\n        (0x3038, 0x303A, 35, 22),\n        (0x303B, 0x303B, 35, 17),\n        (0x303C, 0x303C, 0, 19),\n        (0x303D, 0x303D, 0, 2),\n        (0x303E, 0x303F, 0, 11),\n        (0x3041, 0x3096, 32, 19),\n        (0x3099, 0x309A, 40, 23),\n        (0x309B, 0x309C, 0, 9),\n        (0x309D, 0x309E, 32, 17),\n        (0x309F, 0x309F, 32, 19),\n        (0x30A0, 0x30A0, 0, 7),\n        (0x30A1, 0x30FA, 33, 19),\n        (0x30FB, 0x30FB, 0, 2),\n        (0x30FC, 0x30FC, 0, 17),\n        (0x30FD, 0x30FE, 33, 17),\n        (0x30FF, 0x30FF, 33, 19),\n        (0x3105, 0x312D, 34, 19),\n        (0x3131, 0x318E, 24, 19),\n        (0x3190, 0x3191, 0, 11),\n        (0x3192, 0x3195, 0, 14),\n        (0x3196, 0x319F, 0, 11),\n        (0x31A0, 0x31BA, 34, 19),\n        (0x31C0, 0x31E3, 0, 11),\n        (0x31F0, 0x31FF, 33, 19),\n        (0x3200, 0x321E, 24, 11),\n        (0x3220, 0x3229, 0, 14),\n        (0x322A, 0x3247, 0, 11),\n        (0x3248, 0x324F, 0, 14),\n        (0x3250, 0x3250, 0, 11),\n        (0x3251, 0x325F, 0, 14),\n        (0x3260, 0x327E, 24, 11),\n        (0x327F, 0x327F, 0, 11),\n        (0x3280, 0x3289, 0, 14),\n        (0x328A, 0x32B0, 0, 11),\n        (0x32B1, 0x32BF, 0, 14),\n        (0x32C0, 0x32CF, 0, 11),\n        (0x32D0, 0x32FE, 33, 11),\n        (0x3300, 0x3357, 33, 11),\n        (0x3358, 0x33FF, 0, 11),\n        (0x3400, 0x4DB5, 35, 19),\n        (0x4DC0, 0x4DFF, 0, 11),\n        (0x4E00, 0x9FCC, 35, 19),\n        (0xA000, 0xA014, 36, 19),\n        (0xA015, 0xA015, 36, 17),\n        (0xA016, 0xA48C, 36, 19),\n        (0xA490, 0xA4C6, 36, 11),\n        (0xA4D0, 0xA4F7, 82, 19),\n        (0xA4F8, 0xA4FD, 82, 17),\n        (0xA4FE, 0xA4FF, 82, 2),\n        (0xA500, 0xA60B, 69, 19),\n        (0xA60C, 0xA60C, 69, 17),\n        (0xA60D, 0xA60F, 69, 2),\n        (0xA610, 0xA61F, 69, 19),\n        (0xA620, 0xA629, 69, 8),\n        (0xA62A, 0xA62B, 69, 19),\n        (0xA640, 0xA66D, 3, 15),\n        (0xA66E, 0xA66E, 3, 19),\n        (0xA66F, 0xA66F, 3, 23),\n        (0xA670, 0xA672, 3, 24),\n        (0xA673, 0xA673, 3, 2),\n        (0xA674, 0xA67D, 3, 23),\n        (0xA67E, 0xA67E, 3, 2),\n        (0xA67F, 0xA67F, 3, 17),\n        (0xA680, 0xA697, 3, 15),\n        (0xA69F, 0xA69F, 3, 23),\n        (0xA6A0, 0xA6E5, 83, 19),\n        (0xA6E6, 0xA6EF, 83, 22),\n        (0xA6F0, 0xA6F1, 83, 23),\n        (0xA6F2, 0xA6F7, 83, 2),\n        (0xA700, 0xA716, 0, 9),\n        (0xA717, 0xA71F, 0, 17),\n        (0xA720, 0xA721, 0, 9),\n        (0xA722, 0xA76F, 1, 15),\n        (0xA770, 0xA770, 1, 17),\n        (0xA771, 0xA787, 1, 15),\n        (0xA788, 0xA788, 0, 17),\n        (0xA789, 0xA78A, 0, 9),\n        (0xA78B, 0xA78E, 1, 15),\n        (0xA790, 0xA793, 1, 15),\n        (0xA7A0, 0xA7AA, 1, 15),\n        (0xA7F8, 0xA7F9, 1, 17),\n        (0xA7FA, 0xA7FA, 1, 15),\n        (0xA7FB, 0xA7FF, 1, 19),\n        (0xA800, 0xA801, 58, 19),\n        (0xA802, 0xA802, 58, 23),\n        (0xA803, 0xA805, 58, 19),\n        (0xA806, 0xA806, 58, 23),\n        (0xA807, 0xA80A, 58, 19),\n        (0xA80B, 0xA80B, 58, 23),\n        (0xA80C, 0xA822, 58, 19),\n        (0xA823, 0xA824, 58, 18),\n        (0xA825, 0xA826, 58, 23),\n        (0xA827, 0xA827, 58, 18),\n        (0xA828, 0xA82B, 58, 11),\n        (0xA830, 0xA835, 0, 14),\n        (0xA836, 0xA837, 0, 11),\n        (0xA838, 0xA838, 0, 3),\n        (0xA839, 0xA839, 0, 11),\n        (0xA840, 0xA873, 64, 19),\n        (0xA874, 0xA877, 64, 2),\n        (0xA880, 0xA881, 70, 18),\n        (0xA882, 0xA8B3, 70, 19),\n        (0xA8B4, 0xA8C3, 70, 18),\n        (0xA8C4, 0xA8C4, 70, 23),\n        (0xA8CE, 0xA8CF, 70, 2),\n        (0xA8D0, 0xA8D9, 70, 8),\n        (0xA8E0, 0xA8F1, 9, 23),\n        (0xA8F2, 0xA8F7, 9, 19),\n        (0xA8F8, 0xA8FA, 9, 2),\n        (0xA8FB, 0xA8FB, 9, 19),\n        (0xA900, 0xA909, 71, 8),\n        (0xA90A, 0xA925, 71, 19),\n        (0xA926, 0xA92D, 71, 23),\n        (0xA92E, 0xA92F, 71, 2),\n        (0xA930, 0xA946, 72, 19),\n        (0xA947, 0xA951, 72, 23),\n        (0xA952, 0xA953, 72, 18),\n        (0xA95F, 0xA95F, 72, 2),\n        (0xA960, 0xA97C, 24, 19),\n        (0xA980, 0xA982, 84, 23),\n        (0xA983, 0xA983, 84, 18),\n        (0xA984, 0xA9B2, 84, 19),\n        (0xA9B3, 0xA9B3, 84, 23),\n        (0xA9B4, 0xA9B5, 84, 18),\n        (0xA9B6, 0xA9B9, 84, 23),\n        (0xA9BA, 0xA9BB, 84, 18),\n        (0xA9BC, 0xA9BC, 84, 23),\n        (0xA9BD, 0xA9C0, 84, 18),\n        (0xA9C1, 0xA9CD, 84, 2),\n        (0xA9CF, 0xA9CF, 84, 17),\n        (0xA9D0, 0xA9D9, 84, 8),\n        (0xA9DE, 0xA9DF, 84, 2),\n        (0xAA00, 0xAA28, 76, 19),\n        (0xAA29, 0xAA2E, 76, 23),\n        (0xAA2F, 0xAA30, 76, 18),\n        (0xAA31, 0xAA32, 76, 23),\n        (0xAA33, 0xAA34, 76, 18),\n        (0xAA35, 0xAA36, 76, 23),\n        (0xAA40, 0xAA42, 76, 19),\n        (0xAA43, 0xAA43, 76, 23),\n        (0xAA44, 0xAA4B, 76, 19),\n        (0xAA4C, 0xAA4C, 76, 23),\n        (0xAA4D, 0xAA4D, 76, 18),\n        (0xAA50, 0xAA59, 76, 8),\n        (0xAA5C, 0xAA5F, 76, 2),\n        (0xAA60, 0xAA6F, 22, 19),\n        (0xAA70, 0xAA70, 22, 17),\n        (0xAA71, 0xAA76, 22, 19),\n        (0xAA77, 0xAA79, 22, 11),\n        (0xAA7A, 0xAA7A, 22, 19),\n        (0xAA7B, 0xAA7B, 22, 18),\n        (0xAA80, 0xAAAF, 78, 19),\n        (0xAAB0, 0xAAB0, 78, 23),\n        (0xAAB1, 0xAAB1, 78, 19),\n        (0xAAB2, 0xAAB4, 78, 23),\n        (0xAAB5, 0xAAB6, 78, 19),\n        (0xAAB7, 0xAAB8, 78, 23),\n        (0xAAB9, 0xAABD, 78, 19),\n        (0xAABE, 0xAABF, 78, 23),\n        (0xAAC0, 0xAAC0, 78, 19),\n        (0xAAC1, 0xAAC1, 78, 23),\n        (0xAAC2, 0xAAC2, 78, 19),\n        (0xAADB, 0xAADC, 78, 19),\n        (0xAADD, 0xAADD, 78, 17),\n        (0xAADE, 0xAADF, 78, 2),\n        (0xAAE0, 0xAAEA, 85, 19),\n        (0xAAEB, 0xAAEB, 85, 18),\n        (0xAAEC, 0xAAED, 85, 23),\n        (0xAAEE, 0xAAEF, 85, 18),\n        (0xAAF0, 0xAAF1, 85, 2),\n        (0xAAF2, 0xAAF2, 85, 19),\n        (0xAAF3, 0xAAF4, 85, 17),\n        (0xAAF5, 0xAAF5, 85, 18),\n        (0xAAF6, 0xAAF6, 85, 23),\n        (0xAB01, 0xAB06, 25, 19),\n        (0xAB09, 0xAB0E, 25, 19),\n        (0xAB11, 0xAB16, 25, 19),\n        (0xAB20, 0xAB26, 25, 19),\n        (0xAB28, 0xAB2E, 25, 19),\n        (0xABC0, 0xABE2, 85, 19),\n        (0xABE3, 0xABE4, 85, 18),\n        (0xABE5, 0xABE5, 85, 23),\n        (0xABE6, 0xABE7, 85, 18),\n        (0xABE8, 0xABE8, 85, 23),\n        (0xABE9, 0xABEA, 85, 18),\n        (0xABEB, 0xABEB, 85, 2),\n        (0xABEC, 0xABEC, 85, 18),\n        (0xABED, 0xABED, 85, 23),\n        (0xABF0, 0xABF9, 85, 8),\n        (0xAC00, 0xD7A3, 24, 19),\n        (0xD7B0, 0xD7C6, 24, 19),\n        (0xD7CB, 0xD7FB, 24, 19),\n        (0xF900, 0xFA6D, 35, 19),\n        (0xFA70, 0xFAD9, 35, 19),\n        (0xFB00, 0xFB06, 1, 15),\n        (0xFB13, 0xFB17, 4, 15),\n        (0xFB1D, 0xFB1D, 5, 19),\n        (0xFB1E, 0xFB1E, 5, 23),\n        (0xFB1F, 0xFB28, 5, 19),\n        (0xFB29, 0xFB29, 5, 6),\n        (0xFB2A, 0xFB36, 5, 19),\n        (0xFB38, 0xFB3C, 5, 19),\n        (0xFB3E, 0xFB3E, 5, 19),\n        (0xFB40, 0xFB41, 5, 19),\n        (0xFB43, 0xFB44, 5, 19),\n        (0xFB46, 0xFB4F, 5, 19),\n        (0xFB50, 0xFBB1, 6, 19),\n        (0xFBB2, 0xFBC1, 6, 9),\n        (0xFBD3, 0xFD3D, 6, 19),\n        (0xFD3E, 0xFD3E, 0, 4),\n        (0xFD3F, 0xFD3F, 0, 5),\n        (0xFD50, 0xFD8F, 6, 19),\n        (0xFD92, 0xFDC7, 6, 19),\n        (0xFDF0, 0xFDFB, 6, 19),\n        (0xFDFC, 0xFDFC, 6, 3),\n        (0xFDFD, 0xFDFD, 0, 11),\n        (0xFE00, 0xFE0F, 40, 23),\n        (0xFE10, 0xFE16, 0, 2),\n        (0xFE17, 0xFE17, 0, 4),\n        (0xFE18, 0xFE18, 0, 5),\n        (0xFE19, 0xFE19, 0, 2),\n        (0xFE20, 0xFE26, 40, 23),\n        (0xFE30, 0xFE30, 0, 2),\n        (0xFE31, 0xFE32, 0, 7),\n        (0xFE33, 0xFE34, 0, 10),\n        (0xFE35, 0xFE35, 0, 4),\n        (0xFE36, 0xFE36, 0, 5),\n        (0xFE37, 0xFE37, 0, 4),\n        (0xFE38, 0xFE38, 0, 5),\n        (0xFE39, 0xFE39, 0, 4),\n        (0xFE3A, 0xFE3A, 0, 5),\n        (0xFE3B, 0xFE3B, 0, 4),\n        (0xFE3C, 0xFE3C, 0, 5),\n        (0xFE3D, 0xFE3D, 0, 4),\n        (0xFE3E, 0xFE3E, 0, 5),\n        (0xFE3F, 0xFE3F, 0, 4),\n        (0xFE40, 0xFE40, 0, 5),\n        (0xFE41, 0xFE41, 0, 4),\n        (0xFE42, 0xFE42, 0, 5),\n        (0xFE43, 0xFE43, 0, 4),\n        (0xFE44, 0xFE44, 0, 5),\n        (0xFE45, 0xFE46, 0, 2),\n        (0xFE47, 0xFE47, 0, 4),\n        (0xFE48, 0xFE48, 0, 5),\n        (0xFE49, 0xFE4C, 0, 2),\n        (0xFE4D, 0xFE4F, 0, 10),\n        (0xFE50, 0xFE52, 0, 2),\n        (0xFE54, 0xFE57, 0, 2),\n        (0xFE58, 0xFE58, 0, 7),\n        (0xFE59, 0xFE59, 0, 4),\n        (0xFE5A, 0xFE5A, 0, 5),\n        (0xFE5B, 0xFE5B, 0, 4),\n        (0xFE5C, 0xFE5C, 0, 5),\n        (0xFE5D, 0xFE5D, 0, 4),\n        (0xFE5E, 0xFE5E, 0, 5),\n        (0xFE5F, 0xFE61, 0, 2),\n        (0xFE62, 0xFE62, 0, 6),\n        (0xFE63, 0xFE63, 0, 7),\n        (0xFE64, 0xFE66, 0, 6),\n        (0xFE68, 0xFE68, 0, 2),\n        (0xFE69, 0xFE69, 0, 3),\n        (0xFE6A, 0xFE6B, 0, 2),\n        (0xFE70, 0xFE74, 6, 19),\n        (0xFE76, 0xFEFC, 6, 19),\n        (0xFEFF, 0xFEFF, 0, 13),\n        (0xFF01, 0xFF03, 0, 2),\n        (0xFF04, 0xFF04, 0, 3),\n        (0xFF05, 0xFF07, 0, 2),\n        (0xFF08, 0xFF08, 0, 4),\n        (0xFF09, 0xFF09, 0, 5),\n        (0xFF0A, 0xFF0A, 0, 2),\n        (0xFF0B, 0xFF0B, 0, 6),\n        (0xFF0C, 0xFF0C, 0, 2),\n        (0xFF0D, 0xFF0D, 0, 7),\n        (0xFF0E, 0xFF0F, 0, 2),\n        (0xFF10, 0xFF19, 0, 8),\n        (0xFF1A, 0xFF1B, 0, 2),\n        (0xFF1C, 0xFF1E, 0, 6),\n        (0xFF1F, 0xFF20, 0, 2),\n        (0xFF21, 0xFF3A, 1, 15),\n        (0xFF3B, 0xFF3B, 0, 4),\n        (0xFF3C, 0xFF3C, 0, 2),\n        (0xFF3D, 0xFF3D, 0, 5),\n        (0xFF3E, 0xFF3E, 0, 9),\n        (0xFF3F, 0xFF3F, 0, 10),\n        (0xFF40, 0xFF40, 0, 9),\n        (0xFF41, 0xFF5A, 1, 15),\n        (0xFF5B, 0xFF5B, 0, 4),\n        (0xFF5C, 0xFF5C, 0, 6),\n        (0xFF5D, 0xFF5D, 0, 5),\n        (0xFF5E, 0xFF5E, 0, 6),\n        (0xFF5F, 0xFF5F, 0, 4),\n        (0xFF60, 0xFF60, 0, 5),\n        (0xFF61, 0xFF61, 0, 2),\n        (0xFF62, 0xFF62, 0, 4),\n        (0xFF63, 0xFF63, 0, 5),\n        (0xFF64, 0xFF65, 0, 2),\n        (0xFF66, 0xFF6F, 33, 19),\n        (0xFF70, 0xFF70, 0, 17),\n        (0xFF71, 0xFF9D, 33, 19),\n        (0xFF9E, 0xFF9F, 0, 17),\n        (0xFFA0, 0xFFBE, 24, 19),\n        (0xFFC2, 0xFFC7, 24, 19),\n        (0xFFCA, 0xFFCF, 24, 19),\n        (0xFFD2, 0xFFD7, 24, 19),\n        (0xFFDA, 0xFFDC, 24, 19),\n        (0xFFE0, 0xFFE1, 0, 3),\n        (0xFFE2, 0xFFE2, 0, 6),\n        (0xFFE3, 0xFFE3, 0, 9),\n        (0xFFE4, 0xFFE4, 0, 11),\n        (0xFFE5, 0xFFE6, 0, 3),\n        (0xFFE8, 0xFFE8, 0, 11),\n        (0xFFE9, 0xFFEC, 0, 6),\n        (0xFFED, 0xFFEE, 0, 11),\n        (0xFFF9, 0xFFFB, 0, 13),\n        (0xFFFC, 0xFFFD, 0, 11),\n        (0x10000, 0x1000B, 47, 19),\n        (0x1000D, 0x10026, 47, 19),\n        (0x10028, 0x1003A, 47, 19),\n        (0x1003C, 0x1003D, 47, 19),\n        (0x1003F, 0x1004D, 47, 19),\n        (0x10050, 0x1005D, 47, 19),\n        (0x10080, 0x100FA, 47, 19),\n        (0x10100, 0x10102, 0, 2),\n        (0x10107, 0x10133, 0, 14),\n        (0x10137, 0x1013F, 0, 11),\n        (0x10140, 0x10174, 2, 22),\n        (0x10175, 0x10178, 2, 14),\n        (0x10179, 0x10189, 2, 11),\n        (0x1018A, 0x1018A, 2, 14),\n        (0x10190, 0x1019B, 0, 11),\n        (0x101D0, 0x101FC, 0, 11),\n        (0x101FD, 0x101FD, 40, 23),\n        (0x10280, 0x1029C, 73, 19),\n        (0x102A0, 0x102D0, 74, 19),\n        (0x10300, 0x1031E, 37, 19),\n        (0x10320, 0x10323, 37, 14),\n        (0x10330, 0x10340, 38, 19),\n        (0x10341, 0x10341, 38, 22),\n        (0x10342, 0x10349, 38, 19),\n        (0x1034A, 0x1034A, 38, 22),\n        (0x10380, 0x1039D, 48, 19),\n        (0x1039F, 0x1039F, 48, 2),\n        (0x103A0, 0x103C3, 59, 19),\n        (0x103C8, 0x103CF, 59, 19),\n        (0x103D0, 0x103D0, 59, 2),\n        (0x103D1, 0x103D5, 59, 22),\n        (0x10400, 0x1044F, 39, 15),\n        (0x10450, 0x1047F, 49, 19),\n        (0x10480, 0x1049D, 50, 19),\n        (0x104A0, 0x104A9, 50, 8),\n        (0x10800, 0x10805, 51, 19),\n        (0x10808, 0x10808, 51, 19),\n        (0x1080A, 0x10835, 51, 19),\n        (0x10837, 0x10838, 51, 19),\n        (0x1083C, 0x1083C, 51, 19),\n        (0x1083F, 0x1083F, 51, 19),\n        (0x10840, 0x10855, 86, 19),\n        (0x10857, 0x10857, 86, 2),\n        (0x10858, 0x1085F, 86, 14),\n        (0x10900, 0x10915, 63, 19),\n        (0x10916, 0x1091B, 63, 14),\n        (0x1091F, 0x1091F, 63, 2),\n        (0x10920, 0x10939, 75, 19),\n        (0x1093F, 0x1093F, 75, 2),\n        (0x10980, 0x1099F, 97, 19),\n        (0x109A0, 0x109B7, 96, 19),\n        (0x109BE, 0x109BF, 96, 19),\n        (0x10A00, 0x10A00, 60, 19),\n        (0x10A01, 0x10A03, 60, 23),\n        (0x10A05, 0x10A06, 60, 23),\n        (0x10A0C, 0x10A0F, 60, 23),\n        (0x10A10, 0x10A13, 60, 19),\n        (0x10A15, 0x10A17, 60, 19),\n        (0x10A19, 0x10A33, 60, 19),\n        (0x10A38, 0x10A3A, 60, 23),\n        (0x10A3F, 0x10A3F, 60, 23),\n        (0x10A40, 0x10A47, 60, 14),\n        (0x10A50, 0x10A58, 60, 2),\n        (0x10A60, 0x10A7C, 87, 19),\n        (0x10A7D, 0x10A7E, 87, 14),\n        (0x10A7F, 0x10A7F, 87, 2),\n        (0x10B00, 0x10B35, 79, 19),\n        (0x10B39, 0x10B3F, 79, 2),\n        (0x10B40, 0x10B55, 88, 19),\n        (0x10B58, 0x10B5F, 88, 14),\n        (0x10B60, 0x10B72, 89, 19),\n        (0x10B78, 0x10B7F, 89, 14),\n        (0x10C00, 0x10C48, 90, 19),\n        (0x10E60, 0x10E7E, 6, 14),\n        (0x11000, 0x11000, 93, 18),\n        (0x11001, 0x11001, 93, 23),\n        (0x11002, 0x11002, 93, 18),\n        (0x11003, 0x11037, 93, 19),\n        (0x11038, 0x11046, 93, 23),\n        (0x11047, 0x1104D, 93, 2),\n        (0x11052, 0x11065, 93, 14),\n        (0x11066, 0x1106F, 93, 8),\n        (0x11080, 0x11081, 91, 23),\n        (0x11082, 0x11082, 91, 18),\n        (0x11083, 0x110AF, 91, 19),\n        (0x110B0, 0x110B2, 91, 18),\n        (0x110B3, 0x110B6, 91, 23),\n        (0x110B7, 0x110B8, 91, 18),\n        (0x110B9, 0x110BA, 91, 23),\n        (0x110BB, 0x110BC, 91, 2),\n        (0x110BD, 0x110BD, 91, 13),\n        (0x110BE, 0x110C1, 91, 2),\n        (0x110D0, 0x110E8, 100, 19),\n        (0x110F0, 0x110F9, 100, 8),\n        (0x11100, 0x11102, 95, 23),\n        (0x11103, 0x11126, 95, 19),\n        (0x11127, 0x1112B, 95, 23),\n        (0x1112C, 0x1112C, 95, 18),\n        (0x1112D, 0x11134, 95, 23),\n        (0x11136, 0x1113F, 95, 8),\n        (0x11140, 0x11143, 95, 2),\n        (0x11180, 0x11181, 99, 23),\n        (0x11182, 0x11182, 99, 18),\n        (0x11183, 0x111B2, 99, 19),\n        (0x111B3, 0x111B5, 99, 18),\n        (0x111B6, 0x111BE, 99, 23),\n        (0x111BF, 0x111C0, 99, 18),\n        (0x111C1, 0x111C4, 99, 19),\n        (0x111C5, 0x111C8, 99, 2),\n        (0x111D0, 0x111D9, 99, 8),\n        (0x11680, 0x116AA, 101, 19),\n        (0x116AB, 0x116AB, 101, 23),\n        (0x116AC, 0x116AC, 101, 18),\n        (0x116AD, 0x116AD, 101, 23),\n        (0x116AE, 0x116AF, 101, 18),\n        (0x116B0, 0x116B5, 101, 23),\n        (0x116B6, 0x116B6, 101, 18),\n        (0x116B7, 0x116B7, 101, 23),\n        (0x116C0, 0x116C9, 101, 8),\n        (0x12000, 0x1236E, 62, 19),\n        (0x12400, 0x12462, 62, 22),\n        (0x12470, 0x12473, 62, 2),\n        (0x13000, 0x1342E, 80, 19),\n        (0x16800, 0x16A38, 83, 19),\n        (0x16F00, 0x16F44, 98, 19),\n        (0x16F50, 0x16F50, 98, 19),\n        (0x16F51, 0x16F7E, 98, 18),\n        (0x16F8F, 0x16F92, 98, 23),\n        (0x16F93, 0x16F9F, 98, 17),\n        (0x1B000, 0x1B000, 33, 19),\n        (0x1B001, 0x1B001, 32, 19),\n        (0x1D000, 0x1D0F5, 0, 11),\n        (0x1D100, 0x1D126, 0, 11),\n        (0x1D129, 0x1D164, 0, 11),\n        (0x1D165, 0x1D166, 0, 18),\n        (0x1D167, 0x1D169, 40, 23),\n        (0x1D16A, 0x1D16C, 0, 11),\n        (0x1D16D, 0x1D172, 0, 18),\n        (0x1D173, 0x1D17A, 0, 13),\n        (0x1D17B, 0x1D182, 40, 23),\n        (0x1D183, 0x1D184, 0, 11),\n        (0x1D185, 0x1D18B, 40, 23),\n        (0x1D18C, 0x1D1A9, 0, 11),\n        (0x1D1AA, 0x1D1AD, 40, 23),\n        (0x1D1AE, 0x1D1DD, 0, 11),\n        (0x1D200, 0x1D241, 2, 11),\n        (0x1D242, 0x1D244, 2, 23),\n        (0x1D245, 0x1D245, 2, 11),\n        (0x1D300, 0x1D356, 0, 11),\n        (0x1D360, 0x1D371, 0, 14),\n        (0x1D400, 0x1D454, 0, 15),\n        (0x1D456, 0x1D49C, 0, 15),\n        (0x1D49E, 0x1D49F, 0, 15),\n        (0x1D4A2, 0x1D4A2, 0, 15),\n        (0x1D4A5, 0x1D4A6, 0, 15),\n        (0x1D4A9, 0x1D4AC, 0, 15),\n        (0x1D4AE, 0x1D4B9, 0, 15),\n        (0x1D4BB, 0x1D4BB, 0, 15),\n        (0x1D4BD, 0x1D4C3, 0, 15),\n        (0x1D4C5, 0x1D505, 0, 15),\n        (0x1D507, 0x1D50A, 0, 15),\n        (0x1D50D, 0x1D514, 0, 15),\n        (0x1D516, 0x1D51C, 0, 15),\n        (0x1D51E, 0x1D539, 0, 15),\n        (0x1D53B, 0x1D53E, 0, 15),\n        (0x1D540, 0x1D544, 0, 15),\n        (0x1D546, 0x1D546, 0, 15),\n        (0x1D54A, 0x1D550, 0, 15),\n        (0x1D552, 0x1D6A5, 0, 15),\n        (0x1D6A8, 0x1D6C0, 0, 15),\n        (0x1D6C1, 0x1D6C1, 0, 6),\n        (0x1D6C2, 0x1D6DA, 0, 15),\n        (0x1D6DB, 0x1D6DB, 0, 6),\n        (0x1D6DC, 0x1D6FA, 0, 15),\n        (0x1D6FB, 0x1D6FB, 0, 6),\n        (0x1D6FC, 0x1D714, 0, 15),\n        (0x1D715, 0x1D715, 0, 6),\n        (0x1D716, 0x1D734, 0, 15),\n        (0x1D735, 0x1D735, 0, 6),\n        (0x1D736, 0x1D74E, 0, 15),\n        (0x1D74F, 0x1D74F, 0, 6),\n        (0x1D750, 0x1D76E, 0, 15),\n        (0x1D76F, 0x1D76F, 0, 6),\n        (0x1D770, 0x1D788, 0, 15),\n        (0x1D789, 0x1D789, 0, 6),\n        (0x1D78A, 0x1D7A8, 0, 15),\n        (0x1D7A9, 0x1D7A9, 0, 6),\n        (0x1D7AA, 0x1D7C2, 0, 15),\n        (0x1D7C3, 0x1D7C3, 0, 6),\n        (0x1D7C4, 0x1D7CB, 0, 15),\n        (0x1D7CE, 0x1D7FF, 0, 8),\n        (0x1EE00, 0x1EE03, 6, 19),\n        (0x1EE05, 0x1EE1F, 6, 19),\n        (0x1EE21, 0x1EE22, 6, 19),\n        (0x1EE24, 0x1EE24, 6, 19),\n        (0x1EE27, 0x1EE27, 6, 19),\n        (0x1EE29, 0x1EE32, 6, 19),\n        (0x1EE34, 0x1EE37, 6, 19),\n        (0x1EE39, 0x1EE39, 6, 19),\n        (0x1EE3B, 0x1EE3B, 6, 19),\n        (0x1EE42, 0x1EE42, 6, 19),\n        (0x1EE47, 0x1EE47, 6, 19),\n        (0x1EE49, 0x1EE49, 6, 19),\n        (0x1EE4B, 0x1EE4B, 6, 19),\n        (0x1EE4D, 0x1EE4F, 6, 19),\n        (0x1EE51, 0x1EE52, 6, 19),\n        (0x1EE54, 0x1EE54, 6, 19),\n        (0x1EE57, 0x1EE57, 6, 19),\n        (0x1EE59, 0x1EE59, 6, 19),\n        (0x1EE5B, 0x1EE5B, 6, 19),\n        (0x1EE5D, 0x1EE5D, 6, 19),\n        (0x1EE5F, 0x1EE5F, 6, 19),\n        (0x1EE61, 0x1EE62, 6, 19),\n        (0x1EE64, 0x1EE64, 6, 19),\n        (0x1EE67, 0x1EE6A, 6, 19),\n        (0x1EE6C, 0x1EE72, 6, 19),\n        (0x1EE74, 0x1EE77, 6, 19),\n        (0x1EE79, 0x1EE7C, 6, 19),\n        (0x1EE7E, 0x1EE7E, 6, 19),\n        (0x1EE80, 0x1EE89, 6, 19),\n        (0x1EE8B, 0x1EE9B, 6, 19),\n        (0x1EEA1, 0x1EEA3, 6, 19),\n        (0x1EEA5, 0x1EEA9, 6, 19),\n        (0x1EEAB, 0x1EEBB, 6, 19),\n        (0x1EEF0, 0x1EEF1, 6, 6),\n        (0x1F000, 0x1F02B, 0, 11),\n        (0x1F030, 0x1F093, 0, 11),\n        (0x1F0A0, 0x1F0AE, 0, 11),\n        (0x1F0B1, 0x1F0BE, 0, 11),\n        (0x1F0C1, 0x1F0CF, 0, 11),\n        (0x1F0D1, 0x1F0DF, 0, 11),\n        (0x1F100, 0x1F10A, 0, 14),\n        (0x1F110, 0x1F12E, 0, 11),\n        (0x1F130, 0x1F16B, 0, 11),\n        (0x1F170, 0x1F19A, 0, 11),\n        (0x1F1E6, 0x1F1FF, 0, 11),\n        (0x1F200, 0x1F200, 32, 11),\n        (0x1F201, 0x1F202, 0, 11),\n        (0x1F210, 0x1F23A, 0, 11),\n        (0x1F240, 0x1F248, 0, 11),\n        (0x1F250, 0x1F251, 0, 11),\n        (0x1F300, 0x1F320, 0, 11),\n        (0x1F330, 0x1F335, 0, 11),\n        (0x1F337, 0x1F37C, 0, 11),\n        (0x1F380, 0x1F393, 0, 11),\n        (0x1F3A0, 0x1F3C4, 0, 11),\n        (0x1F3C6, 0x1F3CA, 0, 11),\n        (0x1F3E0, 0x1F3F0, 0, 11),\n        (0x1F400, 0x1F43E, 0, 11),\n        (0x1F440, 0x1F440, 0, 11),\n        (0x1F442, 0x1F4F7, 0, 11),\n        (0x1F4F9, 0x1F4FC, 0, 11),\n        (0x1F500, 0x1F53D, 0, 11),\n        (0x1F540, 0x1F543, 0, 11),\n        (0x1F550, 0x1F567, 0, 11),\n        (0x1F5FB, 0x1F640, 0, 11),\n        (0x1F645, 0x1F64F, 0, 11),\n        (0x1F680, 0x1F6C5, 0, 11),\n        (0x1F700, 0x1F773, 0, 11),\n        (0x20000, 0x2A6D6, 35, 19),\n        (0x2A700, 0x2B734, 35, 19),\n        (0x2B740, 0x2B81D, 35, 19),\n        (0x2F800, 0x2FA1D, 35, 19),\n        (0xE0001, 0xE0001, 0, 13),\n        (0xE0020, 0xE007F, 0, 13),\n        (0xE0100, 0xE01EF, 40, 23),\n    ],\n}\n\n\ndef script_cat(chr):\n    \"\"\"For the unicode character chr return a tuple (Scriptname, Category).\"\"\"\n    l = 0\n    r = len(script_data[\"idx\"]) - 1\n    c = ord(chr)\n    while r >= l:\n        m = (l + r) >> 1\n        if c < script_data[\"idx\"][m][0]:\n            r = m - 1\n        elif c > script_data[\"idx\"][m][1]:\n            l = m + 1\n        else:\n            return (\n                script_data[\"names\"][script_data[\"idx\"][m][2]],\n                script_data[\"cats\"][script_data[\"idx\"][m][3]],\n            )\n    return \"Unknown\", \"Zzzz\"\n\n\ndef script(chr):\n    a, _ = script_cat(chr)\n    return a\n\n\ndef category(chr):\n    _, a = script_cat(chr)\n    return a\n\n\ndef _compile_scripts_txt():\n    # build indexes from 'scripts.txt'\n\n    idx = []\n    names = []\n    cats = []\n\n    import urllib2, re, textwrap\n\n    url = \"http://www.unicode.org/Public/UNIDATA/Scripts.txt\"\n    f = urllib2.urlopen(url)\n    for ln in f:\n        p = re.findall(r\"([0-9A-F]+)(?:\\.\\.([0-9A-F]+))?\\W+(\\w+)\\s*#\\s*(\\w+)\", ln)\n        if p:\n            a, b, name, cat = p[0]\n            if name not in names:\n                names.append(name)\n            if cat not in cats:\n                cats.append(cat)\n            idx.append(\n                (int(a, 16), int(b or a, 16), names.index(name), cats.index(cat))\n            )\n    idx.sort()\n\n    print(\n        'script_data = {\\n\"names\":%s,\\n\"cats\":%s,\\n\"idx\":[\\n%s\\n]}'\n        % (\n            \"\\n\".join(textwrap.wrap(repr(names), 80)),\n            \"\\n\".join(textwrap.wrap(repr(cats), 80)),\n            \"\\n\".join(\n                textwrap.wrap(\", \".join(\"(0x%x,0x%x,%d,%d)\" % c for c in idx), 80)\n            ),\n        )\n    )\n"
  },
  {
    "path": "lib/globals.py",
    "content": "\"\"\"\nglobal configuration of the project\n\nExternal environment variables:\n\n    WTTR_MYDIR\n    WTTR_GEOLITE\n    WTTR_WEGO\n    WTTR_LISTEN_HOST\n    WTTR_LISTEN_PORT\n    WTTR_USER_AGENT\n\n\"\"\"\nfrom __future__ import print_function\n\nimport logging\nimport os\nimport re\n\nMYDIR = os.path.abspath(os.path.dirname(os.path.dirname(\"__file__\")))\n\nif \"WTTR_GEOLITE\" in os.environ:\n    GEOLITE = os.environ[\"WTTR_GEOLITE\"]\nelse:\n    GEOLITE = os.path.join(MYDIR, \"data\", \"GeoLite2-City.mmdb\")\n\nWEGO = os.environ.get(\"WTTR_WEGO\", \"/home/igor/go/bin/we-lang\")\nPYPHOON = \"/home/igor/src/pyphoon/ve/bin/pyphoon-lolcat\" # \"pyphoon-lolcat\"\n\n_DATADIR = \"/wttr.in\"\n_LOGDIR = \"/wttr.in/log\"\n\nIP2LCACHE = os.path.join(_DATADIR, \"cache/ip2l/\")\nPNG_CACHE = os.path.join(_DATADIR, \"cache/png\")\nLRU_CACHE = os.path.join(_DATADIR, \"cache/lru\")\n\nLOG_FILE = os.path.join(_LOGDIR, \"main.log\")\n\nPROXY_LOG_ACCESS = os.path.join(_LOGDIR, \"proxy-access.log\")\nPROXY_LOG_ERRORS = os.path.join(_LOGDIR, \"proxy-errors.log\")\n\nMISSING_TRANSLATION_LOG = os.path.join(_LOGDIR, \"missing-translation/%s.log\")\n\nALIASES = os.path.join(MYDIR, \"share/aliases\")\nANSI2HTML = os.path.join(MYDIR, \"share/ansi2html.sh\")\nBLACKLIST = os.path.join(MYDIR, \"share/blacklist\")\n\nHELP_FILE = os.path.join(MYDIR, \"share/help.txt\")\nBASH_FUNCTION_FILE = os.path.join(MYDIR, \"share/bash-function.txt\")\nTRANSLATION_FILE = os.path.join(MYDIR, \"share/translation.txt\")\n\nIATA_CODES_FILE = os.path.join(MYDIR, \"share/list-of-iata-codes.txt\")\n\nTEMPLATES = os.path.join(MYDIR, \"share/templates\")\nSTATIC = os.path.join(MYDIR, \"share/static\")\n\nNOT_FOUND_LOCATION = \"not found\"\nDEFAULT_LOCATION = \"oymyakon\"\n\nMALFORMED_RESPONSE_HTML_PAGE = open(\n    os.path.join(STATIC, \"malformed-response.html\")\n).read()\n\nGEOLOCATOR_SERVICE = \"http://localhost:8004\"\n\n# number of queries from the same IP address is limited\n# (minute, hour, day) limitations:\nQUERY_LIMITS = (300, 3600, 24 * 3600)\n\nLISTEN_HOST = os.environ.get(\"WTTR_LISTEN_HOST\", \"\")\ntry:\n    LISTEN_PORT = int(os.environ.get(\"WTTR_LISTEN_PORT\"))\nexcept (TypeError, ValueError):\n    LISTEN_PORT = 8002\n\nPROXY_HOST = \"127.0.0.1\"\nPROXY_PORT = 5001\nPROXY_CACHEDIR = os.path.join(_DATADIR, \"cache/proxy-wwo/\")\n\nMY_EXTERNAL_IP = \"5.9.243.187\"\n\nPLAIN_TEXT_AGENTS = [\n    \"curl\",\n    \"httpie\",\n    \"lwp-request\",\n    \"wget\",\n    \"python-requests\",\n    \"python-httpx\",\n    \"openbsd ftp\",\n    \"powershell\",\n    \"fetch\",\n    \"aiohttp\",\n    \"http_get\",\n    \"xh\",\n    \"nushell\",\n    \"zig\",\n]\n\nPLAIN_TEXT_PAGES = [\":help\", \":bash.function\", \":translation\", \":iterm2\"]\n\nTRANSLATION_TABLE = str.maketrans(\n    {\n        \"\\u2196\": \"\\u256E\",  # '↖' -> '╮'\n        \"\\u2197\": \"\\u256D\",  # '↗' -> '╭'\n        \"\\u2198\": \"\\u2570\",  # '↘' -> '╰'\n        \"\\u2199\": \"\\u256F\",  # '↙' -> '╯'\n        \"\\u26A1\": \"\\u250C\\u2518\",\n    }\n)\n\n_IPLOCATION_ORDER = os.environ.get(\"WTTR_IPLOCATION_ORDER\", \"geoip,ip2location,ipinfo\")\nIPLOCATION_ORDER = _IPLOCATION_ORDER.split(\",\")\n\n_IP2LOCATION_KEY_FILE = os.environ.get(\n    \"WTTR_IP2LOCATION_KEY_FILE\", os.environ[\"HOME\"] + \"/.ip2location.key\"\n)\nIP2LOCATION_KEY = None\nif os.path.exists(_IP2LOCATION_KEY_FILE):\n    IP2LOCATION_KEY = open(_IP2LOCATION_KEY_FILE, \"r\").read().strip()\n\n_IPINFO_KEY_FILE = os.environ.get(\n    \"WTTR_IPINFO_KEY_FILE\", os.environ[\"HOME\"] + \"/.ipinfo.key\"\n)\nIPINFO_TOKEN = None\nif os.path.exists(_IPINFO_KEY_FILE):\n    IPINFO_TOKEN = open(_IPINFO_KEY_FILE, \"r\").read().strip()\n\n_WWO_KEY_FILE = os.environ.get(\"WTTR_WWO_KEY_FILE\", os.environ[\"HOME\"] + \"/.wwo.key\")\nWWO_KEY = \"key-is-not-specified\"\nUSE_METNO = True\nUSER_AGENT = os.environ.get(\"WTTR_USER_AGENT\", \"\")\nif os.path.exists(_WWO_KEY_FILE):\n    WWO_KEY = open(_WWO_KEY_FILE, \"r\").read().strip()\n    USE_METNO = False\n\n\ndef error(text):\n    \"log error `text` and raise a RuntimeError exception\"\n\n    if not text.startswith(\"Too many queries\"):\n        print(text)\n    logging.error(\"ERROR %s\", text)\n    raise RuntimeError(text)\n\n\ndef log(text):\n    \"log error `text` and do not raise any exceptions\"\n\n    if not text.startswith(\"Too many queries\"):\n        print(text)\n        logging.info(text)\n\n\ndef debug_log(text):\n    \"\"\"\n    Write `text` to the debug log\n    \"\"\"\n\n    with open(\"/tmp/wttr.in-debug.log\", \"a\") as f_debug:\n        f_debug.write(text + \"\\n\")\n\n\ndef get_help_file(lang):\n    \"Return help file for `lang`\"\n\n    help_file = os.path.join(MYDIR, \"share/translations/%s-help.txt\" % lang)\n    if os.path.exists(help_file):\n        return help_file\n    return HELP_FILE\n\n\ndef remove_ansi(sometext):\n    ansi_escape = re.compile(r\"(\\x9B|\\x1B\\[)[0-?]*[ -\\/]*[@-~]\")\n    return ansi_escape.sub(\"\", sometext)\n"
  },
  {
    "path": "lib/limits.py",
    "content": "\"\"\"\nConnection limitation.\n\nNumber of connections from one IP is limited.\nWe have nothing against scripting and automated queries.\nEven the opposite, we encourage them. But there are some\nconnection limits that even we can't handle.\nCurrently the limits are quite restrictive, but they will be relaxed\nin the future.\n\nUsage:\n\n        limits = Limits()\n        not_allowed = limits.check_ip(ip_address)\n        if not_allowed:\n            return \"ERROR: %s\" % not_allowed\n\n[Taken from github.com/chubin/cheat.sh]\n\"\"\"\n\nimport time\nfrom globals import log\n\n\ndef _time_caps(minutes, hours, days):\n    return {\n        \"min\": minutes,\n        \"hour\": hours,\n        \"day\": days,\n    }\n\n\nclass Limits(object):\n    \"\"\"\n    Queries limitation (by IP).\n\n    Exports:\n\n        check_ip(ip_address)\n    \"\"\"\n\n    def __init__(self, whitelist=None, limits=None):\n        self.intervals = [\"min\", \"hour\", \"day\"]\n\n        self.divisor = _time_caps(60, 3600, 86400)\n        self.last_update = _time_caps(0, 0, 0)\n\n        if limits:\n            self.limit = _time_caps(*limits)\n        else:\n            self.limit = _time_caps(30, 600, 1000)\n\n        if whitelist:\n            self.whitelist = whitelist[:]\n        else:\n            self.whitelist = []\n\n        self.counter = {\n            \"min\": {},\n            \"hour\": {},\n            \"day\": {},\n        }\n\n        self._clear_counters_if_needed()\n\n    def _log_visit(self, interval, ip_address):\n        if ip_address not in self.counter[interval]:\n            self.counter[interval][ip_address] = 0\n        self.counter[interval][ip_address] += 1\n\n    def _limit_exceeded(self, interval, ip_address):\n        visits = self.counter[interval][ip_address]\n        limit = self._get_limit(interval)\n        return visits > limit\n\n    def _get_limit(self, interval):\n        return self.limit[interval]\n\n    def _report_excessive_visits(self, interval, ip_address):\n        log(\n            \"%s LIMITED [%s for %s]\" % (ip_address, self._get_limit(interval), interval)\n        )\n\n    def check_ip(self, ip_address):\n        \"\"\"\n        Check if `ip_address` is allowed, and if not raise an RuntimeError exception.\n        Return True otherwise\n        \"\"\"\n        if ip_address in self.whitelist:\n            return None\n        self._clear_counters_if_needed()\n        for interval in self.intervals:\n            self._log_visit(interval, ip_address)\n            if self._limit_exceeded(interval, ip_address):\n                self._report_excessive_visits(interval, ip_address)\n                return \"Not so fast! Number of queries per %s is limited to %s\" % (\n                    interval,\n                    self._get_limit(interval),\n                )\n        return None\n\n    def reset(self):\n        \"\"\"\n        Reset all counters for all IPs\n        \"\"\"\n        for interval in self.intervals:\n            self.counter[interval] = {}\n\n    def _clear_counters_if_needed(self):\n        current_time = int(time.time())\n        for interval in self.intervals:\n            if current_time // self.divisor[interval] != self.last_update[interval]:\n                self.counter[interval] = {}\n                self.last_update[interval] = current_time / self.divisor[interval]\n"
  },
  {
    "path": "lib/location.py",
    "content": "\"\"\"\nAll location related functions and converters.\n\nThe main entry point is `location_processing` which gets `location` and\n`source_ip_address` and basing on this information generates precise location\ndescription.\n\n     [query]      -->   [location]      -->  [(lat,long)] -->\n                            ^\n                            |\n     [ip-address] --> _get_location()\n\nTo resolve IP address into location, the module uses function `_get_location()`,\nwhich subsequenlty utilizes one of the three methods:\n\n* `_geoip2()` (local sqlite database);\n* `_ip2location()` (an external paid service);\n* `_ipinfo()` (an external free service).\n\nIP-address resolution data is saved in cache (_ipcachewrite, _ipcache).\nCache entry format:\n\n    COUNTRY_CODE;COUNTRY;REGION;CITY[;REST]\n\nTo resolve location name into a (lat,long) pair,\nan external service is used, which is wrapped\nwith a function `_geolocator()`.\n\nExports:\n\n    location_processing\n    is_location_blocked\n\"\"\"\n\n\nfrom __future__ import print_function\n\nimport datetime\nimport json\nimport os\nimport socket\nimport sys\nimport random\n\nimport geoip2.database\nimport pycountry\nimport requests\n\nfrom globals import (\n    GEOLITE,\n    GEOLOCATOR_SERVICE,\n    IP2LCACHE,\n    IP2LOCATION_KEY,\n    NOT_FOUND_LOCATION,\n    ALIASES,\n    BLACKLIST,\n    IATA_CODES_FILE,\n    IPLOCATION_ORDER,\n    IPINFO_TOKEN,\n)\n\nGEOIP_READER = geoip2.database.Reader(GEOLITE)\nCOUNTRY_MAP = {\"Russian Federation\": \"Russia\"}\n\n\ndef _debug_log(s):\n    if os.environ.get(\"WTTR_DEBUG_LOCATION\"):\n        with open(\"/tmp/location-debug.log\", \"a\") as f:\n            f.write(\"%s %s\\n\" % (datetime.datetime.now(), s))\n\n\ndef _is_ip(ip_addr):\n    \"\"\"\n    Check if `ip_addr` looks like an IP Address\n    \"\"\"\n\n    if sys.version_info[0] < 3:\n        ip_addr = ip_addr.encode(\"utf-8\")\n\n    try:\n        socket.inet_pton(socket.AF_INET, ip_addr)\n        return True\n    except socket.error:\n        try:\n            socket.inet_pton(socket.AF_INET6, ip_addr)\n            return True\n        except socket.error:\n            return False\n\n\ndef _location_normalize(location):\n    \"\"\"\n    Normalize location name `location`\n    \"\"\"\n    # translation_table = dict.fromkeys(map(ord, '!@#$*;'), None)\n    def _remove_chars(chars, string):\n        return \"\".join(x for x in string if x not in chars)\n\n    location = location.lower().replace(\"_\", \" \").replace(\"+\", \" \").strip()\n    if not location.startswith(\"moon@\"):\n        location = _remove_chars(r\"!@#$*;:\\\\\", location)\n    return location\n\n\ndef _geolocator(location):\n    \"\"\"\n    Return a GPS pair for specified `location` or None\n    if nothing can be found\n    \"\"\"\n\n    try:\n        if random.random() < 0:\n            geo = requests.get(\"%s/%s\" % (GEOLOCATOR_SERVICE, location)).text\n        else:\n            geo = requests.get(\n                \"http://127.0.0.1:8085/:geo-location?location=%s\" % location\n            ).text\n    except requests.exceptions.ConnectionError as exception:\n        print(\"ERROR: %s\" % exception)\n        return None\n\n    if geo == \"\":\n        return None\n\n    try:\n        answer = json.loads(geo.encode(\"utf-8\"))\n        if \"error\" in answer:\n            return None\n        return answer\n    except ValueError as exception:\n        print(\"ERROR: %s\" % exception)\n        return None\n\n    return None\n\n\ndef _ipcachewrite(ip_addr, location):\n    \"\"\"Write a retrieved ip+location into cache\n    Can stress some filesystems after long term use, see\n    https://stackoverflow.com/questions/466521/how-many-files-can-i-put-in-a-directory\n\n    Expects a location of the form:\n        `(city, region, country, country_code, <lat>, <long>)`\n    Writes a cache entry of the form:\n        `country_code;country;region;city;<lat>;<long>`\n\n    The latitude and longitude are optional elements.\n    \"\"\"\n    return\n    cachefile = os.path.join(IP2LCACHE, ip_addr)\n    if not os.path.exists(IP2LCACHE):\n        os.makedirs(IP2LCACHE)\n    with open(cachefile, \"w\") as file:\n        # like ip2location format\n        file.write(\n            location[3] + \";\" + location[2] + \";\" + location[1] + \";\" + location[0]\n        )\n        if len(location) > 4:\n            file.write(\";\" + \";\".join(map(str, location[4:])))\n\n\ndef _ipcache(ip_addr):\n    \"\"\"Retrieve a location from cache by ip addr\n    Returns a triple of (CITY, REGION, COUNTRY) or None\n    TODO: When cache becomes more robust, transition to using latlong\n    \"\"\"\n\n    ## Use Geo IP service when available\n    r = requests.get(\"http://127.0.0.1:8085/:geo-ip-get?ip=%s\" % ip_addr)\n    if r.status_code == 200 and \";\" in r.text:\n        _, country, region, city, *_ = r.text.split(\";\")\n        return city, region, country\n\n    return None\n\n    # cachefile = os.path.join(IP2LCACHE, ip_addr)\n    #\n    # if os.path.exists(cachefile):\n    #     try:\n    #         _, country, region, city, *_ = open(cachefile, 'r').read().split(';')\n    #         return city, region, country\n    #     except ValueError:\n    #         # cache entry is malformed: should be\n    #         # [ccode];country;region;city;[lat];[long];...\n    #         return None\n    # else:\n    #     _debug_log(\"[_ipcache] %s not found\" % ip_addr)\n    # return None\n\n\ndef _ip2location(ip_addr):\n    \"\"\"Convert IP address `ip_addr` to a location name using ip2location.\n    Return list of location data fields:\n\n        [ccode, country, region, city, rest...]\n\n    Return `None` if an error occured.\n    \"\"\"\n\n    # if IP2LOCATION_KEY is not set, do not query,\n    # because the query wont be processed anyway\n    if not IP2LOCATION_KEY:\n        return None\n    try:\n        _debug_log(\"[_ip2location] %s search\" % ip_addr)\n        r = requests.get(\n            \"http://api.ip2location.com/?ip=%s&key=%s&package=WS3\"  # WS5 provides latlong\n            % (ip_addr, IP2LOCATION_KEY)\n        )\n        r.raise_for_status()\n        location = r.text\n\n        parts = location.split(\";\")\n        if len(parts) >= 4:\n            #       ccode,    country,  region,   city,       (rest)\n            _debug_log(\"[_ip2location] %s found\" % ip_addr)\n            return [parts[3], parts[2], parts[1], parts[0]] + parts[4:]\n        return None\n    except requests.exceptions.RequestException:\n        return None\n\n\ndef _ipinfo(ip_addr):\n    if not IPINFO_TOKEN:\n        return None\n    try:\n        r = requests.get(\"https://ipinfo.io/%s/json?token=%s\" % (ip_addr, IPINFO_TOKEN))\n        r.raise_for_status()\n        r_json = r.json()\n        # can't do two unpackings on one line\n        city, region, country, ccode = (\n            r_json[\"city\"],\n            r_json[\"region\"],\n            \"\",\n            r_json[\"country\"],\n        )\n        lat, long = r_json[\"loc\"].split(\",\")\n        # NOTE: ipinfo only provides ISO codes for countries\n        country = pycountry.countries.get(alpha_2=ccode).name\n    except (requests.exceptions.RequestException, ValueError):\n        # latter is thrown by failure to parse json in reponse\n        return None\n    return [city, region, country, ccode, lat, long]\n\n\ndef _geoip(ip_addr):\n    try:\n        _debug_log(\"[_geoip] %s search\" % ip_addr)\n        response = GEOIP_READER.city(ip_addr)\n        # print(response.subdivisions)\n        city, region, country, ccode, lat, long = (\n            response.city.name,\n            response.subdivisions[0].names[\"en\"],\n            response.country.name,\n            response.country.iso_code,\n            response.location.latitude,\n            response.location.longitude,\n        )\n        _debug_log(\"[_geoip] %s found\" % ip_addr)\n    except IndexError:\n        # Tuple error\n        try:\n            city, region, country, ccode, lat, long = (\n                response.city.name,\n                None,\n                response.country.name,\n                response.country.iso_code,\n                response.location.latitude,\n                response.location.longitude,\n            )\n        except IndexError:\n            return None\n    except (geoip2.errors.AddressNotFoundError):\n        return None\n    return [city, region, country, ccode, lat, long]\n\n\ndef _country_name_workaround(country):\n    # workaround for strange bug with the country name\n    # maybe some other countries has this problem too\n    country = COUNTRY_MAP.get(country) or country\n    return country\n\n\ndef _get_location(ip_addr):\n    \"\"\"\n    Return location triple (CITY, REGION, COUNTRY) for `ip_addr`\n    \"\"\"\n    location = _ipcache(ip_addr)\n    if location:\n        return location\n\n    # location from iplocators have the following order:\n    # (CITY, REGION, COUNTRY, CCODE, LAT, LONG)\n    for method in IPLOCATION_ORDER:\n        if method == \"geoip\":\n            location = _geoip(ip_addr)\n        elif method == \"ip2location\":\n            location = _ip2location(ip_addr)\n        elif method == \"ipinfo\":\n            location = _ipinfo(ip_addr)\n        else:\n            print(\"ERROR: invalid iplocation method specified: %s\" % method)\n        if location is not None:\n            break\n\n    if location is not None and all(location):\n        _ipcachewrite(ip_addr, location)\n        # cache write used to happen before workaround, preserve that\n        location[2] = _country_name_workaround(location[2])\n        return location[:3]  # city, region, country\n        # ccode is cached but not needed for location\n\n    # temporary disabled it because of geoip services capcacity\n    #\n    # if city is None and response.location:\n    #    coord = \"%s, %s\" % (response.location.latitude, response.location.longitude)\n    #    try:\n    #        location = geolocator.reverse(coord, language='en')\n    #        city = location.raw.get('address', {}).get('city')\n    #    except Exception:\n    #        pass\n\n    # No methods resulted in a location - return default\n    return NOT_FOUND_LOCATION, None, None\n\n\ndef _location_canonical_name(location):\n    \"Find canonical name for `location`\"\n\n    location = _location_normalize(location)\n    if location.lower() in LOCATION_ALIAS:\n        return LOCATION_ALIAS[location.lower()]\n    return location\n\n\ndef _load_aliases(aliases_filename):\n    \"\"\"\n    Load aliases from the aliases file\n    \"\"\"\n    aliases_db = {}\n    with open(aliases_filename, \"r\") as f_aliases:\n        for line in f_aliases.readlines():\n            try:\n                from_, to_ = line.decode(\"utf-8\").split(\":\", 1)\n            except AttributeError:\n                from_, to_ = line.split(\":\", 1)\n\n            aliases_db[_location_normalize(from_)] = _location_normalize(to_)\n    return aliases_db\n\n\ndef _load_iata_codes(iata_codes_filename):\n    \"\"\"\n    Load IATA codes from the IATA codes file\n    \"\"\"\n    with open(iata_codes_filename, \"r\") as f_iata_codes:\n        result = []\n        for line in f_iata_codes.readlines():\n            result.append(line.strip())\n    return set(result)\n\n\nLOCATION_ALIAS = _load_aliases(ALIASES)\nLOCATION_BLACK_LIST = [x.strip() for x in open(BLACKLIST, \"r\").readlines()]\nIATA_CODES = _load_iata_codes(IATA_CODES_FILE)\n\n\ndef is_location_blocked(location):\n    \"\"\"\n    Return True if this location is blocked\n    or False if it is allowed\n    \"\"\"\n    return location is not None and location.lower() in LOCATION_BLACK_LIST\n\n\ndef _get_hemisphere(location):\n    \"\"\"\n    Return hemisphere of the location (True = North, False = South).\n    Assume North and return True if location can't be found.\n    \"\"\"\n    if all(location):\n        location_string = \", \".join(location)\n    else:\n        return True\n\n    geolocation = _geolocator(location_string)\n    if geolocation is None:\n        return True\n    return float(geolocation[\"latitude\"]) > 0\n\n\ndef _fully_qualified_location(location, region, country):\n    \"\"\"Return fully qualified location name with `region` and `country`,\n    as a string.\n    \"\"\"\n\n    # If country is not specified, location stays as is\n    if not country:\n        return location\n\n    # Canonify/shorten country name\n    if country == \"United Kingdom of Great Britain and Northern Ireland\":\n        country = \"United Kingdom\"\n    elif country == \"Russian Federation\":\n        country = \"Russia\"\n    elif country == \"United States of America\":\n        country = \"United States\"\n\n    # In United States region is important, because there are a lot of\n    # locations with the same name in different regions.\n    # In the rest of the world, usage of region name may decrease chances\n    # or correct name resolution, so for the moment `region` is used\n    # only for the United States\n    if country == \"United States\" and region:\n        location += \", %s, %s\" % (region, country)\n    else:\n        location += \", %s\" % country\n    return location\n\n\ndef location_processing(location, ip_addr):\n    \"\"\" \"\"\"\n\n    # if location is starting with ~\n    # or has non ascii symbols\n    # it should be handled like a search term (for geolocator)\n    override_location_name = None\n    full_address = None\n    hide_full_address = False\n    force_show_full_address = location is not None and location.startswith(\"~\")\n\n    # location ~ means that it should be detected automatically,\n    # and shown in the location line below the report\n    if location == \"~\":\n        location = None\n\n    if location and location.lstrip(\"~ \").startswith(\"@\"):\n        try:\n            if location.lstrip(\"~ \")[1:] == \"\":\n                location, region, country = NOT_FOUND_LOCATION, None, None\n\n            else:\n                location, region, country = _get_location(\n                    socket.gethostbyname(location.lstrip(\"~ \")[1:])\n                )\n                location = \"~\" + location\n                location = _fully_qualified_location(location, region, country)\n                hide_full_address = not force_show_full_address\n\n        except Exception:\n            location, region, country = NOT_FOUND_LOCATION, None, None\n\n    query_source_location = _get_location(ip_addr)\n\n    # For moon queries, hemisphere must be found\n    # True for North, False for South\n    hemisphere = False\n    if location is not None and (location.lower() + \"@\").startswith(\"moon@\"):\n        hemisphere = _get_hemisphere(query_source_location)\n\n    country = None\n    if not location or location == \"MyLocation\":\n        location = ip_addr\n\n    if _is_ip(location):\n        location, region, country = _get_location(location)\n        # location is just city here\n\n        # here too\n        if location:\n            location = \"~\" + location\n            location = _fully_qualified_location(location, region, country)\n            hide_full_address = not force_show_full_address\n\n    if location and not location.startswith(\"~\"):\n        tmp_location = _location_canonical_name(location)\n        if tmp_location != location:\n            override_location_name = location\n            location = tmp_location\n\n    # up to this point it is possible that the name\n    # contains some unicode symbols\n    # here we resolve them\n    if location is not None and location != NOT_FOUND_LOCATION:\n        location = \"~\" + location.lstrip(\"~ \")\n        if not override_location_name:\n            override_location_name = location.lstrip(\"~\")\n\n    # if location is not None and location.upper() in IATA_CODES:\n    #     location = '~%s' % location\n\n    if (\n        location is not None\n        and not location.startswith(\"~-,\")\n        and location.startswith(\"~\")\n    ):\n        geolocation = _geolocator(_location_canonical_name(location[1:]))\n        if geolocation is not None:\n            if not override_location_name:\n                override_location_name = location[1:].replace(\"+\", \" \")\n            location = \"%s,%s\" % (geolocation[\"latitude\"], geolocation[\"longitude\"])\n            country = None\n            if not hide_full_address:\n                full_address = geolocation[\"address\"]\n            else:\n                full_address = None\n        else:\n            location = NOT_FOUND_LOCATION  # location[1:]\n\n    return (\n        location,\n        override_location_name,\n        full_address,\n        country,\n        query_source_location,\n        hemisphere,\n    )\n\n\ndef _main_():\n    \"\"\"Validate cache entries. Print names of invalid cache entries\n    and move it to the \"broken-entries\" directory.\"\"\"\n\n    import glob\n    import shutil\n\n    for filename in glob.glob(os.path.join(IP2LCACHE, \"*\")):\n        ip_address = os.path.basename(filename)\n        data = _ipcache(ip_address)\n        if data:\n            city, region, country = data\n            if any(x in city for x in \"0123456789\"):\n                print(city)\n                shutil.move(\n                    filename,\n                    os.path.join(\"/wttr.in/cache/ip2l-broken-format\", ip_address),\n                )\n\n\ndef _trace_ip():\n\n    print(_geoip(\"108.5.186.108\"))\n    print(_get_location(\"108.5.186.108\"))\n    print(location_processing(\"\", \"108.5.186.108\"))\n\n\nif __name__ == \"__main__\":\n    _trace_ip()\n    # _main_()\n    # print(_geoip(\"173.216.90.56\"))\n"
  },
  {
    "path": "lib/metno.py",
    "content": "#!/bin/env python\n# vim: fileencoding=utf-8\nfrom datetime import datetime, timedelta\nimport json\nimport logging\nimport os\nimport re\nimport sys\n\nimport timezonefinder\nfrom pytz import timezone\n\nfrom constants import WWO_CODE\n\nlogging.basicConfig(level=os.environ.get(\"LOGLEVEL\", \"INFO\"))\nlogger = logging.getLogger(__name__)\n\n\ndef metno_request(path, query_string):\n    # We'll need to sanitize the inbound request - ideally the\n    # premium/v1/weather.ashx portion would have always been here, though\n    # it seems as though the proxy was built after the majority of the app\n    # and not refactored. For WAPI we'll strip this and the API key out,\n    # then manage it on our own.\n    logger.debug(\"Original path: \" + path)\n    logger.debug(\"Original query: \" + query_string)\n\n    path = path.replace(\n        \"premium/v1/weather.ashx\", \"weatherapi/locationforecast/2.0/complete\"\n    )\n    query_string = re.sub(r\"key=[^&]*&\", \"\", query_string)\n    query_string = re.sub(r\"format=[^&]*&\", \"\", query_string)\n    days = int(re.search(r\"num_of_days=([0-9]+)&\", query_string).group(1))\n    query_string = re.sub(r\"num_of_days=[0-9]+&\", \"\", query_string)\n    # query_string = query_string.replace('key=', '?key=' + WAPI_KEY)\n    # TP is for hourly forecasting, which isn't available in the free api.\n    query_string = re.sub(r\"tp=[0-9]*&\", \"\", query_string)\n    # This assumes lang=... is at the end. Also note that the API doesn't\n    # localize, and we're not either. TODO: add language support\n    query_string = re.sub(r\"lang=[^&]*$\", \"\", query_string)\n    query_string = re.sub(r\"&$\", \"\", query_string)\n\n    logger.debug(\"qs: \" + query_string)\n    # Deal with coordinates. Need to be rounded to 4 decimals for metno ToC\n    # and in a different query string format\n    coord_match = re.search(r\"q=[^&]*\", query_string)\n    coords_str = coord_match.group(0)\n    coords = re.findall(r\"[-0-9.]+\", coords_str)\n    lat = str(round(float(coords[0]), 4))\n    lng = str(round(float(coords[1]), 4))\n    logger.debug(\"lat: \" + lat)\n    logger.debug(\"lng: \" + lng)\n    query_string = re.sub(r\"q=[^&]*\", \"lat=\" + lat + \"&lon=\" + lng + \"&\", query_string)\n    logger.debug(\"Return path: \" + path)\n    logger.debug(\"Return query: \" + query_string)\n\n    return path, query_string, days\n\n\ndef celsius_to_f(celsius):\n    return round((1.8 * celsius) + 32, 1)\n\n\ndef to_weather_code(symbol_code):\n    logger.debug(symbol_code)\n    code = re.sub(r\"_.*\", \"\", symbol_code)\n    logger.debug(code)\n    # symbol codes: https://api.met.no/weatherapi/weathericon/2.0/documentation\n    # they also have _day, _night and _polartwilight variants\n    # See json from https://api.met.no/weatherapi/weathericon/2.0/legends\n    # WWO codes: https://github.com/chubin/wttr.in/blob/master/lib/constants.py\n    #            http://www.worldweatheronline.com/feed/wwoConditionCodes.txt\n    weather_code_map = {\n        \"clearsky\": 113,\n        \"cloudy\": 119,\n        \"fair\": 116,\n        \"fog\": 143,\n        \"heavyrain\": 302,\n        \"heavyrainandthunder\": 389,\n        \"heavyrainshowers\": 305,\n        \"heavyrainshowersandthunder\": 386,\n        \"heavysleet\": 314,  # There's a ton of 'LightSleet' in WWO_CODE...\n        \"heavysleetandthunder\": 377,\n        \"heavysleetshowers\": 362,\n        \"heavysleetshowersandthunder\": 374,\n        \"heavysnow\": 230,\n        \"heavysnowandthunder\": 392,\n        \"heavysnowshowers\": 371,\n        \"heavysnowshowersandthunder\": 392,\n        \"lightrain\": 266,\n        \"lightrainandthunder\": 200,\n        \"lightrainshowers\": 176,\n        \"lightrainshowersandthunder\": 386,\n        \"lightsleet\": 281,\n        \"lightsleetandthunder\": 377,\n        \"lightsleetshowers\": 284,\n        \"lightsnow\": 320,\n        \"lightsnowandthunder\": 392,\n        \"lightsnowshowers\": 368,\n        \"lightssleetshowersandthunder\": 365,\n        \"lightssnowshowersandthunder\": 392,\n        \"partlycloudy\": 116,\n        \"rain\": 293,\n        \"rainandthunder\": 389,\n        \"rainshowers\": 299,\n        \"rainshowersandthunder\": 386,\n        \"sleet\": 185,\n        \"sleetandthunder\": 392,\n        \"sleetshowers\": 263,\n        \"sleetshowersandthunder\": 392,\n        \"snow\": 329,\n        \"snowandthunder\": 392,\n        \"snowshowers\": 230,\n        \"snowshowersandthunder\": 392,\n    }\n    if code not in weather_code_map:\n        logger.debug(\"not found\")\n        return -1  # not found\n    logger.debug(weather_code_map[code])\n    return weather_code_map[code]\n\n\ndef to_description(symbol_code):\n    desc = WWO_CODE[str(to_weather_code(symbol_code))]\n    logger.debug(desc)\n    return desc\n\n\ndef to_16_point(degrees):\n    # 360 degrees / 16 = 22.5 degrees of arc or 11.25 degrees around the point\n    if degrees > (360 - 11.25) or degrees <= 11.25:\n        return \"N\"\n    if degrees > 11.25 and degrees <= (11.25 + 22.5):\n        return \"NNE\"\n    if degrees > (11.25 + (22.5 * 1)) and degrees <= (11.25 + (22.5 * 2)):\n        return \"NE\"\n    if degrees > (11.25 + (22.5 * 2)) and degrees <= (11.25 + (22.5 * 3)):\n        return \"ENE\"\n    if degrees > (11.25 + (22.5 * 3)) and degrees <= (11.25 + (22.5 * 4)):\n        return \"E\"\n    if degrees > (11.25 + (22.5 * 4)) and degrees <= (11.25 + (22.5 * 5)):\n        return \"ESE\"\n    if degrees > (11.25 + (22.5 * 5)) and degrees <= (11.25 + (22.5 * 6)):\n        return \"SE\"\n    if degrees > (11.25 + (22.5 * 6)) and degrees <= (11.25 + (22.5 * 7)):\n        return \"SSE\"\n    if degrees > (11.25 + (22.5 * 7)) and degrees <= (11.25 + (22.5 * 8)):\n        return \"S\"\n    if degrees > (11.25 + (22.5 * 8)) and degrees <= (11.25 + (22.5 * 9)):\n        return \"SSW\"\n    if degrees > (11.25 + (22.5 * 9)) and degrees <= (11.25 + (22.5 * 10)):\n        return \"SW\"\n    if degrees > (11.25 + (22.5 * 10)) and degrees <= (11.25 + (22.5 * 11)):\n        return \"WSW\"\n    if degrees > (11.25 + (22.5 * 11)) and degrees <= (11.25 + (22.5 * 12)):\n        return \"W\"\n    if degrees > (11.25 + (22.5 * 12)) and degrees <= (11.25 + (22.5 * 13)):\n        return \"WNW\"\n    if degrees > (11.25 + (22.5 * 13)) and degrees <= (11.25 + (22.5 * 14)):\n        return \"NW\"\n    if degrees > (11.25 + (22.5 * 14)) and degrees <= (11.25 + (22.5 * 15)):\n        return \"NNW\"\n\n\ndef meters_to_miles(meters):\n    return round(meters * 0.00062137, 2)\n\n\ndef mm_to_inches(mm):\n    return round(mm / 25.4, 2)\n\n\ndef hpa_to_mb(hpa):\n    return hpa\n\n\ndef hpa_to_in(hpa):\n    return round(hpa * 0.02953, 2)\n\n\ndef hpa_to_mmHg(hpa):\n    return round(hpa * 0.75006157584566, 3)\n\n\ndef group_hours_to_days(lat, lng, hourlies, days_to_return):\n    tf = timezonefinder.TimezoneFinder()\n    timezone_str = tf.certain_timezone_at(lat=lat, lng=lng)\n    logger.debug(\"got TZ: \" + timezone_str)\n    tz = timezone(timezone_str)\n    start_day_gmt = datetime.fromisoformat(hourlies[0][\"time\"].replace(\"Z\", \"+00:00\"))\n    start_day_local = start_day_gmt.astimezone(tz)\n    end_day_local = (start_day_local + timedelta(days=days_to_return - 1)).date()\n    logger.debug(\"series starts at gmt time: \" + str(start_day_gmt))\n    logger.debug(\"series starts at local time: \" + str(start_day_local))\n    logger.debug(\"series ends on day: \" + str(end_day_local))\n    days = {}\n\n    for hour in hourlies:\n        current_day_gmt = datetime.fromisoformat(hour[\"time\"].replace(\"Z\", \"+00:00\"))\n        current_local = current_day_gmt.astimezone(tz)\n        current_day_local = current_local.date()\n        if current_day_local > end_day_local:\n            continue\n        if current_day_local not in days:\n            days[current_day_local] = {\"hourly\": []}\n        hour[\"localtime\"] = current_local.time()\n        days[current_day_local][\"hourly\"].append(hour)\n\n    # Need a second pass to build the min/max/avg data\n    for date, day in days.items():\n        minTempC = -999\n        maxTempC = 1000\n        avgTempC = None\n        n = 0\n        maxUvIndex = 0\n        for hour in day[\"hourly\"]:\n            temp = hour[\"data\"][\"instant\"][\"details\"][\"air_temperature\"]\n            if temp > minTempC:\n                minTempC = temp\n            if temp < maxTempC:\n                maxTempC = temp\n            if avgTempC is None:\n                avgTempC = temp\n                n = 1\n            else:\n                avgTempC = ((avgTempC * n) + temp) / (n + 1)\n                n = n + 1\n\n            uv = hour[\"data\"][\"instant\"][\"details\"]\n            if \"ultraviolet_index_clear_sky\" in uv:\n                if uv[\"ultraviolet_index_clear_sky\"] > maxUvIndex:\n                    maxUvIndex = uv[\"ultraviolet_index_clear_sky\"]\n        day[\"maxtempC\"] = str(maxTempC)\n        day[\"maxtempF\"] = str(celsius_to_f(maxTempC))\n        day[\"mintempC\"] = str(minTempC)\n        day[\"mintempF\"] = str(celsius_to_f(minTempC))\n        day[\"avgtempC\"] = str(round(avgTempC, 1))\n        day[\"avgtempF\"] = str(celsius_to_f(avgTempC))\n        # day[\"totalSnow_cm\": \"not implemented\",\n        # day[\"sunHour\": \"12\",  # This would come from astonomy data\n        day[\"uvIndex\"] = str(maxUvIndex)\n\n    return days\n\n\ndef _convert_hour(hour):\n    # Whatever is upstream is expecting data in the shape of WWO. This method will\n    # morph from metno to hourly WWO response format.\n    # Note that WWO is providing data every 3 hours. Metno provides every hour\n    #   {\n    # \"time\": \"0\",\n    # \"tempC\": \"19\",\n    # \"tempF\": \"66\",\n    # \"windspeedMiles\": \"6\",\n    # \"windspeedKmph\": \"9\",\n    # \"winddirDegree\": \"276\",\n    # \"winddir16Point\": \"W\",\n    # \"weatherCode\": \"119\",\n    # \"weatherIconUrl\": [\n    #   {\n    #     \"value\": \"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0003_white_cloud.png\"\n    #   }\n    # ],\n    # \"weatherDesc\": [\n    #   {\n    #     \"value\": \"Cloudy\"\n    #   }\n    # ],\n    # \"precipMM\": \"0.0\",\n    # \"precipInches\": \"0.0\",\n    # \"humidity\": \"62\",\n    # \"visibility\": \"10\",\n    # \"visibilityMiles\": \"6\",\n    # \"pressure\": \"1017\",\n    # \"pressureInches\": \"31\",\n    # \"cloudcover\": \"66\",\n    # \"HeatIndexC\": \"19\",\n    # \"HeatIndexF\": \"66\",\n    # \"DewPointC\": \"12\",\n    # \"DewPointF\": \"53\",\n    # \"WindChillC\": \"19\",\n    # \"WindChillF\": \"66\",\n    # \"WindGustMiles\": \"8\",\n    # \"WindGustKmph\": \"13\",\n    # \"FeelsLikeC\": \"19\",\n    # \"FeelsLikeF\": \"66\",\n    # \"chanceofrain\": \"0\",\n    # \"chanceofremdry\": \"93\",\n    # \"chanceofwindy\": \"0\",\n    # \"chanceofovercast\": \"89\",\n    # \"chanceofsunshine\": \"18\",\n    # \"chanceoffrost\": \"0\",\n    # \"chanceofhightemp\": \"0\",\n    # \"chanceoffog\": \"0\",\n    # \"chanceofsnow\": \"0\",\n    # \"chanceofthunder\": \"0\",\n    # \"uvIndex\": \"1\"\n    details = hour[\"data\"][\"instant\"][\"details\"]\n    if \"next_1_hours\" in hour[\"data\"]:\n        next_hour = hour[\"data\"][\"next_1_hours\"]\n    elif \"next_6_hours\" in hour[\"data\"]:\n        next_hour = hour[\"data\"][\"next_6_hours\"]\n    elif \"next_12_hours\" in hour[\"data\"]:\n        next_hour = hour[\"data\"][\"next_12_hours\"]\n    else:\n        next_hour = {}\n\n    # Need to dig out symbol_code and precipitation_amount\n    symbol_code = \"clearsky_day\"  # Default to sunny\n    if \"summary\" in next_hour and \"symbol_code\" in next_hour[\"summary\"]:\n        symbol_code = next_hour[\"summary\"][\"symbol_code\"]\n    precipitation_amount = 0  # Default to no rain\n    if \"details\" in next_hour and \"precipitation_amount\" in next_hour[\"details\"]:\n        precipitation_amount = next_hour[\"details\"][\"precipitation_amount\"]\n\n    uvIndex = 0  # default to 0 index\n    if \"ultraviolet_index_clear_sky\" in details:\n        uvIndex = details[\"ultraviolet_index_clear_sky\"]\n    localtime = \"\"\n    if \"localtime\" in hour:\n        localtime = \"{h:02.0f}\".format(h=hour[\"localtime\"].hour) + \"{m:02.0f}\".format(\n            m=hour[\"localtime\"].minute\n        )\n        logger.debug(str(hour[\"localtime\"]))\n    # time property is local time, 4 digit 24 hour, with no :, e.g. 2100\n    return {\n        \"time\": localtime,\n        \"observation_time\": hour[\"time\"],  # Need to figure out WWO TZ\n        # temp_C is used in we-lang.go calcs in such a way\n        # as to expect a whole number\n        \"temp_C\": str(int(round(details[\"air_temperature\"], 0))),\n        # temp_F can be more precise - not used in we-lang.go calcs\n        \"temp_F\": str(celsius_to_f(details[\"air_temperature\"])),\n        \"weatherCode\": str(to_weather_code(symbol_code)),\n        \"weatherIconUrl\": [\n            {\n                \"value\": \"not yet implemented\",\n            }\n        ],\n        \"weatherDesc\": [\n            {\n                \"value\": to_description(symbol_code),\n            }\n        ],\n        # similiarly, windspeedMiles is not used by we-lang.go, but kmph is\n        \"windspeedMiles\": str(meters_to_miles(details[\"wind_speed\"])),\n        \"windspeedKmph\": str(int(round(details[\"wind_speed\"], 0))),\n        \"winddirDegree\": str(details[\"wind_from_direction\"]),\n        \"winddir16Point\": to_16_point(details[\"wind_from_direction\"]),\n        \"precipMM\": str(precipitation_amount),\n        \"precipInches\": str(mm_to_inches(precipitation_amount)),\n        \"humidity\": str(details[\"relative_humidity\"]),\n        \"visibility\": \"not yet implemented\",  # str(details['vis_km']),\n        \"visibilityMiles\": \"not yet implemented\",  # str(details['vis_miles']),\n        \"pressure\": str(hpa_to_mb(details[\"air_pressure_at_sea_level\"])),\n        \"pressure_mmHg\": str(hpa_to_mmHg(details[\"air_pressure_at_sea_level\"])),\n        \"pressureInches\": str(hpa_to_in(details[\"air_pressure_at_sea_level\"])),\n        \"cloudcover\": \"not yet implemented\",  # Convert from cloud_area_fraction?? str(details['cloud']),\n        # metno doesn't have FeelsLikeC, but we-lang.go is using it in calcs,\n        # so we shall set it to temp_C\n        \"FeelsLikeC\": str(int(round(details[\"air_temperature\"], 0))),\n        \"FeelsLikeF\": \"not yet implemented\",  # str(details['feelslike_f']),\n        \"uvIndex\": str(uvIndex),\n    }\n\n\ndef _convert_hourly(hours):\n    converted_hours = []\n    for hour in hours:\n        converted_hours.append(_convert_hour(hour))\n    return converted_hours\n\n\n# Whatever is upstream is expecting data in the shape of WWO. This method will\n# morph from metno to WWO response format.\ndef create_standard_json_from_metno(content, days_to_return):\n    try:\n        forecast = json.loads(content)  # pylint: disable=invalid-name\n    except (ValueError, TypeError) as exception:\n        logger.error(\"---\")\n        logger.error(exception)\n        logger.error(\"---\")\n        return {}, \"\"\n    hourlies = forecast[\"properties\"][\"timeseries\"]\n    current = hourlies[0]\n    # We are assuming these units:\n    # \"units\": {\n    #   \"air_pressure_at_sea_level\": \"hPa\",\n    #   \"air_temperature\": \"celsius\",\n    #   \"air_temperature_max\": \"celsius\",\n    #   \"air_temperature_min\": \"celsius\",\n    #   \"cloud_area_fraction\": \"%\",\n    #   \"cloud_area_fraction_high\": \"%\",\n    #   \"cloud_area_fraction_low\": \"%\",\n    #   \"cloud_area_fraction_medium\": \"%\",\n    #   \"dew_point_temperature\": \"celsius\",\n    #   \"fog_area_fraction\": \"%\",\n    #   \"precipitation_amount\": \"mm\",\n    #   \"relative_humidity\": \"%\",\n    #   \"ultraviolet_index_clear_sky\": \"1\",\n    #   \"wind_from_direction\": \"degrees\",\n    #   \"wind_speed\": \"m/s\"\n    # }\n    content = {\n        \"data\": {\n            \"request\": [\n                {\n                    \"type\": \"feature\",\n                    \"query\": str(forecast[\"geometry\"][\"coordinates\"][1])\n                    + \",\"\n                    + str(forecast[\"geometry\"][\"coordinates\"][0]),\n                }\n            ],\n            \"current_condition\": [_convert_hour(current)],\n            \"weather\": [],\n        }\n    }\n\n    days = group_hours_to_days(\n        forecast[\"geometry\"][\"coordinates\"][1],\n        forecast[\"geometry\"][\"coordinates\"][0],\n        hourlies,\n        days_to_return,\n    )\n\n    # TODO: Astronomy needs to come from this:\n    # https://api.met.no/weatherapi/sunrise/2.0/.json?lat=40.7127&lon=-74.0059&date=2020-10-07&offset=-05:00\n    # and obviously can be cached for a while\n    # https://api.met.no/weatherapi/sunrise/2.0/documentation\n    # Note that full moon/new moon/first quarter/last quarter aren't returned\n    # and the moonphase value should match these from WWO:\n    # New Moon\n    # Waxing Crescent\n    # First Quarter\n    # Waxing Gibbous\n    # Full Moon\n    # Waning Gibbous\n    # Last Quarter\n    # Waning Crescent\n\n    for date, day in days.items():\n        content[\"data\"][\"weather\"].append(\n            {\n                \"date\": str(date),\n                \"astronomy\": [],\n                \"maxtempC\": day[\"maxtempC\"],\n                \"maxtempF\": day[\"maxtempF\"],\n                \"mintempC\": day[\"mintempC\"],\n                \"mintempF\": day[\"mintempF\"],\n                \"avgtempC\": day[\"avgtempC\"],\n                \"avgtempF\": day[\"avgtempF\"],\n                \"totalSnow_cm\": \"not implemented\",\n                \"sunHour\": \"12\",  # This would come from astonomy data\n                \"uvIndex\": day[\"uvIndex\"],\n                \"hourly\": _convert_hourly(day[\"hourly\"]),\n            }\n        )\n\n    # for day in forecast.\n    return json.dumps(content)\n\n\nif __name__ == \"__main__\":\n    # if len(sys.argv) == 1:\n    #     for deg in range(0, 360):\n    #         print('deg: ' + str(deg) + '; 16point: ' + to_16_point(deg))\n    if len(sys.argv) == 2:\n        req = sys.argv[1].split(\"?\")\n        # to_description(sys.argv[1])\n        metno_request(req[0], req[1])\n    elif len(sys.argv) == 3:\n        with open(sys.argv[1], \"r\") as contentf:\n            content = create_standard_json_from_metno(contentf.read(), int(sys.argv[2]))\n        print(content)\n    else:\n        print(\"usage: metno <content file> <days>\")\n"
  },
  {
    "path": "lib/parse_query.py",
    "content": "import re\nimport json\nimport zlib\nimport base64\n\n\ndef serialize(parsed_query):\n    return base64.b64encode(\n        zlib.compress(json.dumps(parsed_query).encode(\"utf-8\")), altchars=b\"-_\"\n    ).decode(\"utf-8\")\n\n\ndef deserialize(url):\n\n    string = url[2:]\n\n    extension = None\n    if \".\" in string:\n        string, extension = string.split(\".\", 1)\n\n    try:\n        result = json.loads(\n            zlib.decompress(base64.b64decode(string, altchars=b\"-_\")).decode(\"utf-8\")\n        )\n    except zlib.error:\n        return None\n\n    if extension == \"png\":\n        result[\"png_filename\"] = url\n        result[\"html_output\"] = False\n\n    return result\n\n\ndef metric_or_imperial(query, lang, us_ip=False):\n    \"\"\" \"\"\"\n\n    # what units should be used\n    # metric or imperial\n    # based on query and location source (imperial for US by default)\n    if query.get(\"use_metric\", False) and not query.get(\"use_imperial\", False):\n        query[\"use_imperial\"] = False\n        query[\"use_metric\"] = True\n    elif query.get(\"use_imperial\", False) and not query.get(\"use_metric\", False):\n        query[\"use_imperial\"] = True\n        query[\"use_metric\"] = False\n    elif lang == \"us\":\n        # slack uses m by default, to override it speciy us.wttr.in\n        query[\"use_imperial\"] = True\n        query[\"use_metric\"] = False\n    else:\n        if us_ip:\n            query[\"use_imperial\"] = True\n            query[\"use_metric\"] = False\n        else:\n            query[\"use_imperial\"] = False\n            query[\"use_metric\"] = True\n\n    return query\n\n\ndef parse_query(args):\n    result = {}\n\n    reserved_args = [\"lang\"]\n\n    q = \"\"\n\n    for key, val in args.items():\n        if len(val) == 0:\n            q += key\n            continue\n        if val == \"True\":\n            val = True\n        if val == \"False\":\n            val = False\n        result[key] = val\n\n    if q is None:\n        return result\n    if \"A\" in q:\n        result[\"force-ansi\"] = True\n    if \"d\" in q:\n        result[\"dumb\"] = True\n    if \"n\" in q:\n        result[\"narrow\"] = True\n    if \"m\" in q:\n        result[\"use_metric\"] = True\n    if \"M\" in q:\n        result[\"use_metric\"] = True\n        result[\"use_ms_for_wind\"] = True\n    if \"u\" in q:\n        result[\"use_imperial\"] = True\n    if \"I\" in q:\n        result[\"inverted_colors\"] = True\n    if \"t\" in q:\n        result[\"transparency\"] = \"150\"\n    if \"T\" in q:\n        result[\"no-terminal\"] = True\n    if \"p\" in q:\n        result[\"padding\"] = True\n\n    for days in \"0123\":\n        if days in q:\n            result[\"days\"] = days\n\n    if \"q\" in q:\n        result[\"no-caption\"] = True\n    if \"Q\" in q:\n        result[\"no-city\"] = True\n    if \"F\" in q:\n        result[\"no-follow-line\"] = True\n\n    for key, val in args.items():\n        if val == \"True\":\n            val = True\n        if val == \"False\":\n            val = False\n        if val:\n            result[key] = val\n\n    # currently `view` is alias for `format`\n    if \"format\" in result and not result.get(\"view\"):\n        result[\"view\"] = result[\"format\"]\n        del result[\"format\"]\n\n    return result\n\n\ndef parse_wttrin_png_name(name):\n    \"\"\"\n    Parse the PNG filename and return the result as a dictionary.\n    For example:\n        input = City_200x_lang=ru.png\n        output = {\n            \"lang\": \"ru\",\n            \"width\": \"200\",\n            \"filetype\": \"png\",\n            \"location\": \"City\"\n        }\n    \"\"\"\n\n    parsed = {}\n    to_be_parsed = {}\n\n    if name.lower()[-4:] == \".png\":\n        parsed[\"filetype\"] = \"png\"\n        name = name[:-4]\n\n    parts = name.split(\"_\")\n    parsed[\"location\"] = parts[0]\n\n    one_letter_options = \"\"\n    for part in parts[1:]:\n        if re.match(\"(?:[0-9]+)x\", part):\n            parsed[\"width\"] = part[:-1]\n        elif re.match(\"x(?:[0-9]+)\", part):\n            parsed[\"height\"] = part[1:]\n        elif re.match(part, \"(?:[0-9]+)x(?:[0-9]+)\"):\n            parsed[\"width\"], parsed[\"height\"] = part.split(\"x\", 1)\n        elif \"=\" in part:\n            arg, val = part.split(\"=\", 1)\n            to_be_parsed[arg] = val\n        else:\n            one_letter_options += part\n\n    for letter in one_letter_options:\n        to_be_parsed[letter] = \"\"\n\n    parsed.update(parse_query(to_be_parsed))\n\n    # currently `view` is alias for `format`\n    if \"format\" in parsed and not parsed.get(\"view\"):\n        parsed[\"view\"] = parsed[\"format\"]\n        del parsed[\"format\"]\n\n    return parsed\n"
  },
  {
    "path": "lib/proxy_log.py",
    "content": "\"\"\"\nLogger of proxy queries\n\n\"\"\"\n\n# pylint: disable=consider-using-with,too-few-public-methods\n\nimport datetime\n\n\nclass Logger:\n\n    \"\"\"\n    Generic logger.\n    For specific loggers, _shorten_query() should be rewritten.\n    \"\"\"\n\n    def __init__(self, filename_access, filename_errors):\n\n        self._filename_access = filename_access\n        self._filename_errors = filename_errors\n        self._log_access = open(filename_access, \"a\", encoding=\"utf-8\")\n        self._log_errors = open(filename_errors, \"a\", encoding=\"utf-8\")\n\n    def _shorten_query(self, query):\n        return query\n\n    def log(self, query, error):\n        \"\"\"\n        Log `query` and `error`\n        \"\"\"\n\n        message = str(datetime.datetime.now())\n        query = self._shorten_query(query)\n        if error != \"\":\n            message += \" ERR \" + query + \" \" + error\n            self._log_errors.write(message + \"\\n\")\n            self._log_errors.flush()\n        else:\n            message += \" OK  \" + query\n            self._log_access.write(message + \"\\n\")\n            self._log_access.flush()\n\n\nclass LoggerWWO(Logger):\n    \"\"\"\n    WWO logger.\n    \"\"\"\n\n    def _shorten_query(self, query):\n        return \"\".join([x for x in query.split(\"&\") if x.startswith(\"q=\")])\n"
  },
  {
    "path": "lib/translations.py",
    "content": "# vim: fileencoding=utf-8\n\n\"\"\"\nTranslation of almost everything.\n\"\"\"\n\nFULL_TRANSLATION = [\n    \"am\",\n    \"ar\",\n    \"af\",\n    \"be\",\n    \"bn\",\n    \"ca\",\n    \"da\",\n    \"de\",\n    \"el\",\n    \"et\",\n    \"fr\",\n    \"fa\",\n    \"gl\",\n    \"hi\",\n    \"hu\",\n    \"ia\",\n    \"id\",\n    \"it\",\n    \"lt\",\n    \"mg\",\n    \"nb\",\n    \"nl\",\n    \"oc\",\n    \"pl\",\n    \"pt-br\",\n    \"ro\",\n    \"ru\",\n    \"ta\",\n    \"tr\",\n    \"th\",\n    \"uk\",\n    \"vi\",\n    \"zh-cn\",\n    \"zh-tw\",\n]\n\nPARTIAL_TRANSLATION = [\n    \"az\",\n    \"bg\",\n    \"bs\",\n    \"cy\",\n    \"cs\",\n    \"eo\",\n    \"es\",\n    \"eu\",\n    \"fi\",\n    \"ga\",\n    \"hi\",\n    \"hr\",\n    \"hy\",\n    \"is\",\n    \"ja\",\n    \"jv\",\n    \"ka\",\n    \"kk\",\n    \"ko\",\n    \"ky\",\n    \"lv\",\n    \"mk\",\n    \"ml\",\n    \"mr\",\n    \"nl\",\n    \"fy\",\n    \"nn\",\n    \"pt\",\n    \"pt-br\",\n    \"sk\",\n    \"sl\",\n    \"sr\",\n    \"sr-lat\",\n    \"sv\",\n    \"sw\",\n    \"te\",\n    \"uz\",\n    \"zh\",\n    \"zu\",\n    \"he\",\n]\n\nPROXY_LANGS = [\n    \"af\",\n    \"am\",\n    \"ar\",\n    \"az\",\n    \"be\",\n    \"bn\",\n    \"bs\",\n    \"ca\",\n    \"cy\",\n    \"de\",\n    \"el\",\n    \"eo\",\n    \"et\",\n    \"eu\",\n    \"fa\",\n    \"fr\",\n    \"fy\",\n    \"ga\",\n    \"gl\",\n    \"he\",\n    \"hr\",\n    \"hu\",\n    \"hy\",\n    \"ia\",\n    \"id\",\n    \"is\",\n    \"it\",\n    \"ja\",\n    \"kk\",\n    \"lt\",\n    \"lv\",\n    \"mg\",\n    \"mk\",\n    \"mr\",\n    \"nb\",\n    \"nn\",\n    \"oc\",\n    \"ro\",\n    \"ru\",\n    \"sl\",\n    \"th\",\n    \"pt-br\",\n    \"uk\",\n    \"uz\",\n    \"vi\",\n    \"zh-cn\",\n    \"zh-tw\",\n]\n\nSUPPORTED_LANGS = FULL_TRANSLATION + PARTIAL_TRANSLATION\n\n\nMESSAGE = {\n    \"NOT_FOUND_MESSAGE\": {\n        \"en\": \"\"\"\nWe were unable to find your location\nso we have brought you to Oymyakon,\none of the coldest permanently inhabited locales on the planet.\n\"\"\",\n        \"af\": \"\"\"\nOns kon nie u ligging opspoor nie\ngevolglik het ons vir u na Oymyakon geneem,\neen van die koudste permanent bewoonde plekke op aarde.\n\"\"\",\n        \"am\": \"\"\"\nአካባቢዎን ማግኘት ስላልቻልን ወደ ኦይማያኮን አምጥተንዎታል፤ \nበአለም ላይ በጣም ቀዝቃዛ እና ሰው አልባ ከሆኑት ቦታዎች አንዱ።\n\"\"\",\n        \"ar\": \"\"\"\nتعذر علينا العثور على موقعك\nلذلك قمنا بجلبك إلي أويمياكون,\n إحدى الأماكن المَأْهُولة الأكثر برودة علي الإطلاق في هذا الكوكب.\n\"\"\",\n        \"be\": \"\"\"\nВаша месцазнаходжанне вызначыць не атрымалася,\nтаму мы пакажам вам надвор'е ў Аймяконе,\nсамым халодным населеным пункце на планеце.\nБудзем спадзявацца, што ў вас сёння надвор'е лепей!\n\"\"\",\n        \"bg\": \"\"\"\nНе успяхме да открием вашето местоположение\nтака че ви доведохме в Оймякон,\nедно от най-студените постоянно обитавани места на планетата.\n\"\"\",\n        \"bn\": \"\"\"\nদুঃখিত, আপনার অবস্থান আমরা খুঁজে পাইনি।\nতাই, আমরা আপনাকে নিয়ে এসেছি ওয়মিয়াকনে, \nযা পৃথিবীর শীতলতম স্থায়ী জন-বসতিগুলোর একটি। \n\"\"\",\n        \"bs\": \"\"\"\nNismo mogli pronaći vašu lokaciju,\ntako da smo te doveli do Oymyakon,\njedan od najhladnijih stalno naseljena mjesta na planeti.\nNadamo se da ćete imati bolje vreme!\n\"\"\",\n        \"ca\": \"\"\"\nHem estat incapaços de trobar la seva ubicació,\nper això l'hem portat fins Oymyakon,\nun dels llocs més freds i permanentment deshabitats del planeta.\n\"\"\",\n        \"cs\": \"\"\"\nNepodařilo se nám najít vaši polohu,\ntakže jsme vás přivedli do Ojmjakonu.\nJe to jedno z nejchladnějších trvale obydlených míst na planetě.\nDoufáme, že budete mít lepší počasí!\n\"\"\",\n        \"cy\": \"\"\"\nNi darganfyddwyd eich lleoliad,\nfelly rydym wedi dod â chi i Oymyakon,\nun o'r llefydd oeraf ar y blaned ble mae pobl yn dal i fyw!\n\"\"\",\n        \"de\": \"\"\"\nWir konnten Ihren Standort nicht finden,\nalso haben wir Sie nach Oimjakon gebracht,\neiner der kältesten dauerhaft bewohnten Orte auf dem Planeten.\nWir hoffen, dass Sie besseres Wetter haben!\n\"\"\",\n        \"el\": \"\"\"\nΔεν μπορέσαμε να βρούμε την τοποθεσία σου,\nγια αυτό διαλέξαμε το Οϊμιάκον για εσένα,\nμία από τις πιο κρύες μόνιμα κατοικημένες περιοχές στον πλανήτη.\nΕλπίζουμε να έχεις καλύτερο καιρό!\n\"\"\",\n        \"es\": \"\"\"\nNo hemos logrado encontrar tu ubicación,\nasí que hemos decidido enseñarte el tiempo en Oimiakón,\nuno de los sitios más fríos y permanentemente deshabitados del planeta.\n\"\"\",\n        \"eu\": \"\"\"\nEzin izan dugu zure kokapena aurkitu,\nberaz eguraldia Oymyakonen erakustea erabaki dugu,\nmunduko lekurik hotz eta hutseneraiko bat\n\"\"\",\n        \"fa\": \"\"\"\nما نتونستیم مکان شما رو پیدا کنیم. به همین خاطر شما رو به اویمیاکن بردیم\n، یکی از سردترین مکان های روی زمین که اصلا قابل سکونت نیست!\n\"\"\",\n        \"fi\": \"\"\"\nEmme löytänyt sijaintiasi, joten toimme sinut Oimjakoniin,\nyhteen maailman kylmimmistä pysyvästi asutetuista paikoista.\nToivottavasti sinulla on parempi sää!\n\"\"\",\n        \"fr\": \"\"\"\nNous n'avons pas pu déterminer votre position,\nNous vous avons donc amenés à Oïmiakon,\nl'un des endroits les plus froids habités en permanence sur la planète.\nNous espérons qu'il fait meilleur chez vous !\n\"\"\",\n        \"ga\": \"\"\"\nNí rabhamar ábalta do cheantar a aimsiú\nmar sin thugamar go dtí Oymyakon,\ntú ceann do na ceantair bhuanáitrithe is fuaire ar domhan.\n\"\"\",\n        \"gl\": \"\"\"\nNon logramos atopar a túa localización\npolo que te trouxemos até Oimiakón,\nun dos lugares máis fríos e permamentemente deshabitados do planeta.\n\"\"\",\n        \"hi\": \"\"\"\nहम आपका स्थान खोजने में असमर्थ है,\nइसलिए हम आपको ओयमयाकोन पर ले आए है,\nजो ग्रह के सबसे ठंडे स्थानों में से एक है|\n\"\"\",\n        \"hu\": \"\"\"\nNem sikerült megtalálni a pozíciódat,\nígy elhoztunk Ojmjakonba;\naz egyik leghidegebb állandóan lakott településre a bolygón.\n\"\"\",\n        \"hy\": \"\"\"\nՁեր գտնվելու վայրը չհաջողվեց որոշել,\nայդ պատճառով մենք ձեզ կցուցադրենք եղանակը Օյմյակոնում.\nերկրագնդի ամենասառը բնակավայրում։\nՀույս ունենք որ ձեր եղանակը այսօր ավելի լավն է։\n\"\"\",\n        \"ia\": \"\"\"\nNos non trovate su location,\nassi nos su apporte a Oymyakon,\nun del plus frigide locos habita super le planeta!\n\"\"\",\n        \"id\": \"\"\"\nKami tidak dapat menemukan lokasi anda,\njadi kami membawa anda ke Oymyakon,\nsalah satu tempat terdingin yang selalu dihuni di planet ini!\n\"\"\",\n        \"is\": \"\"\"\nVið finnum ekki staðsetninguna þína og vísum þér þar með á Ojmjakon,\nein af köldustu byggðum jarðar.\nVonandi er betra veður hjá þér.\n\"\"\",\n        \"it\": \"\"\"\nNon siamo riusciti a trovare la sua posizione\nquindi la abbiamo portato a Oymyakon,\nuno dei luoghi abitualmente abitati più freddi del pianeta.\nCi auguriamo che le condizioni dove lei si trova siano migliori!\n\"\"\",\n        \"ja\": \"\"\"\n指定された場所が見つかりませんでした。\n代わりにオイミャコンの天気予報を表示しています。\nオイミャコンは地球上で最も寒い居住地の一つです。\n\"\"\",\n        \"ko\": \"\"\"\n지정된 장소를 찾을 수 없습니다,\n대신 오이먀콘의 일기 예보를 표시합니다,\n오이먀콘은 지구상에서 가장 추운 곳에 위치한 마을입니다!\n\"\"\",\n        \"lt\": \"\"\"\nMums nepavyko rasti jūsų vietovės,\ntodėl mes nukreipėme jus į Omjakoną,\nvieną iš šalčiausių nuolatinių gyvenviečių planetoje.\n\"\"\",\n        \"lv\": \"\"\"\nMēs nevarējām noteikt Tavu atrašanās vietu, tādēļ nogādājām Tevi Oimjakonā,\nvienā no planētas aukstākajām pastāvīgi apdzīvotajām vietām.\n\"\"\",\n        \"mk\": \"\"\"\nНеможевме да ја пронајдеме вашата локација,\nзатоа ве однесовме во Ојмајкон,\nеден од најладните трајно населени места на планетата.\n\"\"\",\n        \"mr\": \"\"\"\nआमहाला तुमचे स्थळ सापडले नाही.\nम्हणून आम्ही तुम्हाला ओयम्याकोन येथे आणले आहे,\nजे कि आपल्या ग्रहावरील सर्वात थंड वस्तिस्थानांपैकी एक आहे.\n\"\"\",\n        \"nb\": \"\"\"\nVi kunne ikke finne din lokasjon,\nså her får du Ojmjakon, et av de kaldeste bebodde stedene på planeten.\nVi håper været er bedre hos deg!\n\"\"\",\n        \"nl\": \"\"\"\nWij konden uw locatie niet vaststellen\ndus hebben we u naar Ojmjakon gebracht,\néén van de koudste permanent bewoonde gebieden op deze planeet.\n\"\"\",\n        \"fy\": \"\"\"\nWy koenen jo lokaasje net fêststelle\ndus wy ha jo nei Ojmjakon brocht,\nien fan de kâldste permanent bewenbere plakken op ierde.\n\"\"\",\n        \"oc\": \"\"\"\nAvèm pas pogut determinar vòstra posicion,\nVos avèm doncas menat a Oïmiakon,\nun dels endreches mai freds abitat permanéncia del monde.\nEsperam que fa melhor en çò vòstre !\n\"\"\",\n        \"pt\": \"\"\"\nNão conseguimos encontrar a sua localização,\nentão decidimos te mostrar o tempo em Oymyakon,\num dos lugares mais frios e permanentemente desabitados do planeta.\n\"\"\",\n        \"pt-br\": \"\"\"\nNão conseguimos encontrar a sua localização,\nentão decidimos te mostrar o tempo em Oymyakon,\num dos lugares mais frios e permanentemente desabitados do planeta.\n\"\"\",\n        \"pl\": \"\"\"\nNie udało nam się znaleźć podanej przez Ciebie lokalizacji,\nwięc zabraliśmy Cię do Ojmiakonu,\njednego z najzimniejszych, stale zamieszkanych miejsc na Ziemi.\nMamy nadzieję, że u Ciebie jest cieplej!\n\"\"\",\n        \"ro\": \"\"\"\nNu v-am putut identifica localitatea, prin urmare vă arătăm vremea din Oimiakon,\nuna dintre cele mai reci localități permanent locuite de pe planetă.\nSperăm că aveți vreme mai bună!\n\"\"\",\n        \"ru\": \"\"\"\nВаше местоположение определить не удалось,\nпоэтому мы покажем вам погоду в Оймяконе,\nсамом холодном населённом пункте на планете.\nБудем надеяться, что у вас сегодня погода лучше!\n\"\"\",\n        \"sk\": \"\"\"\nNepodarilo sa nám nájsť vašu polohu,\ntakže sme vás priviedli do Ojmiakonu.\nJe to jedno z najchladnejších trvale obývaných miest na planéte.\nDúfame, že budete mať lepšie počasie!\n\"\"\",\n        \"sr\": \"\"\"\nНисмо успели да пронађемо Вашу локацију,\nпа смо Вас довели у Ојмјакон,\nједно од најхладнијих стално насељених места на планети.\nНадамо се да је време код Вас боље него што је то случај овде!\n\"\"\",\n        \"sv\": \"\"\"\nVi lyckades inte hitta er plats så vi har istället tagit er till Ojmjakon,\nen av planetens kallaste platser med permanent bosättning.\nVi hoppas att vädret är bättre hos dig!\n\"\"\",\n        \"tr\": \"\"\"\nAradığınız konum bulunamadı. O yüzden sizi dünyadaki en soğuk sürekli\nyerleşim yerlerinden biri olan Oymyakon'e getirdik.\nUmarız sizin olduğunuz yerde havalar daha iyidir!\n\"\"\",\n        \"te\": \"\"\"\nమేము మీ స్థానాన్ని కనుగొనలేకపోయాము\nకనుక మనం \"ఓమాయకాన్కు\" తీసుకొని వచ్చాము,\nభూమిపై అత్యల్ప శాశ్వతంగా నివసించే స్థానిక ప్రదేశాలలో ఒకటి.\n\"\"\",\n        \"th\": \"\"\"\nเราไม่สามารถหาตำแหน่งของคุณได้เราจึงนำคุณไปสู่ Oymyakon หมู่บ้านที่หนาวที่สุดในโลก!\n\"\"\",\n        \"uk\": \"\"\"\nМи не змогли визначити Ваше місцезнаходження,\nтому покажемо Вам погоду в Оймяконі —\nнайхолоднішому населеному пункті на планеті.\nБудемо сподіватися, що у Вас сьогодні погода краще!\n\"\"\",\n        \"uz\": \"\"\"\nSizning joylashuvingizni aniqlay olmadik,\nshuning uchun sizga sayyoramizning eng sovuq aholi punkti - Oymyakondagi ob-havo haqida ma'lumot beramiz.\nUmid qilamizki, sizda bugungi ob-havo bundan yaxshiroq!\n\"\"\",\n        \"zh\": \"\"\"\n我们无法找到您的位置,\n当前显示奥伊米亚康(Oymyakon)，这个星球上最冷的人类定居点。\n\"\"\",\n        \"da\": \"\"\"\nVi kunne desværre ikke finde din lokation\nså vi har bragt dig til Oymyakon,\nEn af koldeste og helt ubolige lokationer på planeten.\n\"\"\",\n        \"et\": \"\"\"\nMe ei suutnud tuvastada teie asukohta\nning seetõttu paigutasime teid Oymyakoni,\nmis on üks kõige külmemaid püsivalt asustatud paiku planeedil.\n\"\"\",\n        \"vi\": \"\"\"\nChúng tôi không tìm thấy địa điểm của bạn\nvì vậy chúng tôi đưa bạn đến Oymyakon,\nmột trong những nơi lạnh nhất có người sinh sống trên trái đất.\n\"\"\",\n        \"zh-tw\": \"\"\"\n我們找不到您的位置\n所以我們帶您到奧伊米亞康，\n這個星球上有人類定居最冷之處。\n\"\"\",\n        \"mg\": \"\"\"\nTsy hita ny toerana misy anao koa nentinay tany Oymyakon ianao,\niray amin'ireo toerana mangatsiaka indrindra tsisy mponina eto an-tany.\n\"\"\",\n        \"ta\": \"\"\"\nஉங்கள் இருப்பிடத்தை எங்களால் கண்டுபிடிக்க முடியவில்லை\nஎனவே நாங்கள் உங்களை ஓமியாகோனுக்கு அழைத்து வந்தோம்.\nகிரகத்தின் குளிர்ந்த நிரந்தரமாக வசிக்கும் இடங்களில் ஒன்று.\n\"\"\",\n    },\n    \"UNKNOWN_LOCATION\": {\n        \"en\": \"Unknown location\",\n        \"af\": \"Onbekende ligging\",\n        \"am\": \"ያልታወቀ ቦታ\",\n        \"ar\": \"موقع غير معروف\",\n        \"be\": \"Невядомае месцазнаходжанне\",\n        \"bg\": \"Неизвестно местоположение\",\n        \"bn\": \"অজানা অবস্থান\",\n        \"bs\": \"Nepoznatoja lokacija\",\n        \"ca\": \"Ubicació desconeguda\",\n        \"cs\": \"Neznámá poloha\",\n        \"cy\": \"Lleoliad anhysbys\",\n        \"de\": \"Unbekannter Ort\",\n        \"da\": \"Ukendt lokation\",\n        \"el\": \"Άνγωστη τοποθεσία\",\n        \"es\": \"Ubicación desconocida\",\n        \"et\": \"Tundmatu asukoht\",\n        \"eu\": \"Kokapen ezezaguna\",\n        \"fa\": \"مکان نامعلوم\",\n        \"fi\": \"Tuntematon sijainti\",\n        \"fr\": \"Emplacement inconnu\",\n        \"ga\": \"Ceantar anaithnid\",\n        \"gl\": \"Localización descoñecida\",\n        \"hi\": \"अज्ञात स्थान\",\n        \"hu\": \"Ismeretlen lokáció\",\n        \"hy\": \"Անհայտ գտնվելու վայր\",\n        \"id\": \"Lokasi tidak diketahui\",\n        \"ia\": \"Location incognite\",\n        \"is\": \"Óþekkt staðsetning\",\n        \"it\": \"Località sconosciuta\",\n        \"ja\": \"未知の場所です\",\n        \"ko\": \"알 수 없는 장소\",\n        \"kk\": \"\",\n        \"lt\": \"Nežinoma vietovė\",\n        \"lv\": \"Nezināma atrašanās vieta\",\n        \"mk\": \"Непозната локација\",\n        \"mr\": \"अज्ञात स्थळ\",\n        \"nb\": \"Ukjent sted\",\n        \"nl\": \"Onbekende locatie\",\n        \"oc\": \"Emplaçament desconegut\",\n        \"fy\": \"Ûnbekende lokaasje\",\n        \"pl\": \"Nieznana lokalizacja\",\n        \"pt\": \"Localização desconhecida\",\n        \"pt-br\": \"Localização desconhecida\",\n        \"ro\": \"Localitate necunoscută\",\n        \"ru\": \"Неизвестное местоположение\",\n        \"sk\": \"Neznáma poloha\",\n        \"sl\": \"Neznano lokacijo\",\n        \"sr\": \"Непозната локација\",\n        \"sv\": \"Okänd plats\",\n        \"te\": \"తెలియని ప్రదేశం\",\n        \"tr\": \"Bilinmeyen konum\",\n        \"th\": \"ไม่สามารถระบุตำแหน่งได้\",\n        \"uk\": \"Невідоме місце\",\n        \"uz\": \"Аникланмаган худуд\",\n        \"zh\": \"未知地点\",\n        \"vi\": \"Địa điểm không xác định\",\n        \"zh-tw\": \"未知位置\",\n        \"mg\": \"Toerana tsy fantatra\",\n        \"ta\": \"தெரியாத இடம்\",\n    },\n    \"LOCATION\": {\n        \"en\": \"Location\",\n        \"af\": \"Ligging\",\n        \"ar\": \"الموقع\",\n        \"be\": \"Месцазнаходжанне\",\n        \"bg\": \"Местоположение\",\n        \"bn\": \"অবস্থান\",\n        \"bs\": \"Lokacija\",\n        \"ca\": \"Ubicació\",\n        \"cs\": \"Poloha\",\n        \"cy\": \"Lleoliad\",\n        \"de\": \"Ort\",\n        \"da\": \"Lokation\",\n        \"el\": \"Τοποθεσία\",\n        \"es\": \"Ubicación\",\n        \"et\": \"Asukoht\",\n        \"eu\": \"Kokaena\",\n        \"fa\": \"مکان\",\n        \"fi\": \"Tuntematon sijainti\",\n        \"fr\": \"Emplacement\",\n        \"ga\": \"Ceantar\",\n        \"gl\": \"Localización\",\n        \"hi\": \"स्थान\",\n        \"hu\": \"Lokáció\",\n        \"hy\": \"Դիրք\",\n        \"ia\": \"Location\",\n        \"id\": \"Lokasi\",\n        \"is\": \"Staðsetning\",\n        \"it\": \"Località\",\n        \"ja\": \"位置情報\",\n        \"ko\": \"위치\",\n        \"kk\": \"\",\n        \"lt\": \"Vietovė\",\n        \"lv\": \"Atrašanās vieta\",\n        \"mk\": \"Локација\",\n        \"mr\": \"स्थळ\",\n        \"nb\": \"Sted\",\n        \"nl\": \"Locatie\",\n        \"oc\": \"Emplaçament\",\n        \"fy\": \"Lokaasje\",\n        \"pl\": \"Lokalizacja\",\n        \"pt\": \"Localização\",\n        \"pt-br\": \"Localização\",\n        \"ro\": \"Localitate\",\n        \"ru\": \"Местоположение\",\n        \"sk\": \"Poloha\",\n        \"sl\": \"Lokacijo\",\n        \"sr\": \"Локација\",\n        \"sv\": \"Plats\",\n        \"zh\": \"地点\",\n        \"te\": \"స్థానము\",\n        \"tr\": \"Konum\",\n        \"th\": \"ตำแหน่ง\",\n        \"uk\": \"Місцезнаходження\",\n        \"vi\": \"Địa điểm\",\n        \"zh-tw\": \"位置\",\n        \"mg\": \"Toerana\",\n        \"ta\": \"இடம்\",\n    },\n    \"CAPACITY_LIMIT_REACHED\": {\n        \"en\": \"\"\"\nSorry, we are running out of queries to the weather service at the moment.\nHere is the weather report for the default city (just to show you what it looks like).\nWe will get new queries as soon as possible.\nYou can follow https://x.com/igor_chubin for the updates.\n======================================================================================\n\"\"\",\n        \"af\": \"\"\"\nVerskoning, ons oorskry tans die vermoë om navrae aan die weerdiens te rig.\nHier is die weerberig van 'n voorbeeld ligging (bloot om aan u te wys hoe dit lyk).\nOns sal weereens nuwe navrae kan hanteer so gou as moontlik.\nU kan vir https://x.com/igor_chubin volg vir opdaterings.\n======================================================================================\n\"\"\",\n        \"am\": \"\"\"\nይቅርታ ፤ ለጊዜው መጠይቆችን ማስተናገድ አልቻልንም፡፡\nየነባሪ ከተማው የአየር ሁኔታ ሪፖርት ይኸውልዎ (ምን እንደሚመስል ለማሳየት)።\nአዳዲስ መጠይቆችን በተቻለ ፍጥነት ለማስተናገድ እንሞክራለን።\nለበለጠ መረጃ እባክዎ https://x.com/igor_chubin ን ይከተሉ።\n======================================================================================\n\"\"\",\n        \"ar\": \"\"\"\nعذرًا ، استعلامات خدمة الطقس نفذت في الوقت الحالي.\nهذا هو تقرير الطقس للمدينة الافتراضية (فقط لتظهر لك كيف تبدو).\nسوف نتلقى استعلامات جديدة في أقرب وقت ممكن.\nيمكنك متابعة https://x.com/igor_chubin لآخر المستجدات.\n======================================================================================\n\"\"\",\n        \"be\": \"\"\"\nПрабачце, мы выйшлі за ліміты колькасці запытаў да службы надвор'я ў дадзены момант.\nВось прагноз надвор'я для горада па змаўчанні (толькі, каб паказаць вам, як гэта выглядае).\nМы вернемся як мага хутчэй.\nВы можаце сачыць на https://x.com/igor_chubin за абнаўленнямі.\n======================================================================================\n\"\"\",\n        \"bg\": \"\"\"\nСъжаляваме, количеството заявки към услугата за предсказване на време е почти изчерпано.\nЕто доклад за града по подразбиране (просто да видите как изглежда).\nЩе осогурим допълнителни заявки максимално бързо.\nМоже да последвате https://x.com/igor_chubin за обновления.\n\"\"\",\n        \"bn\": \"\"\"\nদুঃখিত, এই মুহুর্তে আবহাওয়া পরিসেবাতে  আমাদের কুইরী শেষ হয়ে আসছে। \nএখানে ডিফল্ট শহরের আবহাওয়ার প্রতিবেদন রয়েছে (এটি দেখতে কেমন তা আপনাকে দেখানোর জন্য)। \nআমরা খুব দ্রুত নতুন কুইরী পাওয়ার ব্যবস্থা করছি। \nআপডেটের জন্য আপনি https://x.com/igor_chubin অনুসরণ করতে পারেন। \n\"\"\",\n        \"bs\": \"\"\"\nŽao mi je, mi ponestaje upita i vremenska prognoza u ovom trenutku.\nOvdje je izvještaj o vremenu za default grada (samo da vam pokažem kako to izgleda).\nMi ćemo dobiti nove upite u najkraćem mogućem roku.\nMožete pratiti https://x.com/igor_chubin za ažuriranja.\n======================================================================================\n\"\"\",\n        \"ca\": \"\"\"\nDisculpa'ns, ens hem quedat momentàniament sense consultes al servei meteorològic.\nAquí t'oferim l'informe del temps a la ciutat per defecte (només per mostrar quin aspecte té).\nObtindrem noves consultes tan aviat com ens sigui possible.\nPots seguir https://x.com/igor_chubin per noves actualitzacions.\n======================================================================================\n\"\"\",\n        \"cs\": \"\"\"\nOmlouváme se, ale aktuálně nám dochází počet dotazů na službu počasí.\nZde je předpověď počasí pro výchozí město (abyste viděli, jak to vypadá).\nProblém bude vyřešen co nejdříve.\nAktualizace můžete následovat na https://x.com/igor_chubin.\n======================================================================================\n\"\"\",\n        \"de\": \"\"\"\nEntschuldigung, wir können momentan den Wetterdienst nicht erreichen.\nDafür zeigen wir Ihnen das Wetter an einem Beispielort, damit Sie sehen, wie die Seite das Wetter anzeigt.\nWir werden versuchen das Problem so schnell wie möglich zu beheben.\nFolgen Sie https://x.com/igor_chubin für Updates.\n======================================================================================\n\"\"\",\n        \"cy\": \"\"\"\nRydym yn brin o ymholiadau i'r gwasanaeth tywydd ar hyn o bryd.\nFelly dyma'r adroddiad tywydd ar gyfer y ddinas ragosod (er mwyn arddangos sut mae'n edrych).\nByddwn gyda ymholiadau newydd yn fuan.\nGellir dilyn https://x.com/igor_chubin i gael newyddion pellach.\n======================================================================================\n\"\"\",\n        \"es\": \"\"\"\nLo siento, hemos alcanzado el límite de peticiones al servicio de previsión del tiempo en este momento.\nA continuación, la previsión del tiempo para una ciudad estándar (solo para que puedas ver el formato del reporte).\nMuy pronto volveremos a tener acceso a las peticiones.\nPuedes seguir https://x.com/igor_chubin para estar al tanto de la situación.\n======================================================================================\n\"\"\",\n        \"fa\": \"\"\"\nمتأسفانه در حال حاضر ظرفیت ما برای درخواست به سرویس هواشناسی به اتمام رسیده.\nاینجا می تونید گزارش هواشناسی برای شهر پیش فرض رو ببینید (فقط برای اینه که بهتون نشون بدیم چه شکلی هست)\nما تلاش میکنیم در اسرع وقت ظرفیت جدید به دست بیاریم.\nبرای دنبال کردن اخبار جدید میتونید https://x.com/igor_chubin رو فالو کنید.\n======================================================================================\n\"\"\",\n        \"fr\": \"\"\"\nDésolé, nous avons épuisé les requêtes vers le service météo.\nVoici un bulletin météo de l'emplacement par défaut (pour vous donner un aperçu).\nNous serons très bientôt en mesure de faire de nouvelles requêtes.\nVous pouvez suivre https://x.com/igor_chubin pour rester informé.\n======================================================================================\n\"\"\",\n        \"ga\": \"\"\"\nTá brón orainn, níl mórán iarratas le fail chuig seirbhís na haimsire faoi láthair.\nSeo duit réamhaisnéis na haimsire don chathair réamhshocraithe (chun é a thaispeaint duit).\nGheobhaimid iarratais nua chomh luath agus is feidir.\nLean orainn ar https://x.com/igor_chubin don eolas is déanaí.\n======================================================================================\n\"\"\",\n        \"gl\": \"\"\"\nDesculpa, estamos a chegar ao límite de peticións ao servizo meteorolóxico neste momento.\nAquí está a previsión do tempo para a cidade por defecto (tan só para amosarche un exemplo).\nImos obter máis peticións tan pronto como poidamos.\nPodes seguir https://x.com/igor_chubin para estares actualizada.\n======================================================================================\n\"\"\",\n        \"hi\": \"\"\"\nक्षमा करें, इस समय हम मौसम सेवा से संपर्क नहीं कर पा रहे है।\nयहा पूर्व निर्धारित शहर के लिए मौसम की जानकारी (आपको यह दिखाने के लिए कि यह कैसा दिखता है)।\nहम जल्द से जल्द मौसम सेवा से संपर्क करने नई कोशिश करेंगे।\nआप अपडेट के लिए https://x.com/igor_chubin का अनुसरण कर सकते हैं।\n======================================================================================\n\"\"\",\n        \"hu\": \"\"\"\nSajnáljuk, kifogytunk az időjárási szolgáltatásra fordított erőforrásokból.\nItt van az alapértelmezett város időjárási jelentése (hogy lásd, hogyan néz ki).\nA lehető leghamarabb új erőforrásokat fogunk kapni.\nA frissítésekért tekintsd meg a https://x.com/igor_chubin oldalt.\n======================================================================================\n\"\"\",\n        \"hy\": \"\"\"\nԿներեք, այս պահին մենք գերազանցել ենք եղանակային տեսության կայանին հարցումների քանակը.\nԿարող եք տեսնել տիպային եղանակը զեկուցում հիմնական քաղաքի համար (Ուղղակի որպես նմուշ):\nՄենք մշտապես աշխատում ենք հարցումների քանակը բարելավելու ուղղությամբ:\nԿարող եք հետևել մեզ https://x.com/igor_chubin թարմացումների համար.\n======================================================================================\n\"\"\",\n        \"ia\": \"\"\"\nPardono, nos ha exhaurite inquisitione del servicio tempore alora.\nEcce es le reporto tempore por qualque citate (demonstrar le reporte).\nNos recipera inquisitione nove tosto.\nTu pote abonar a https://x.com/igor_chubin por nove information.\n======================================================================================\n\"\"\",\n        \"id\": \"\"\"\nMaaf, kami kehabian permintaan ke layanan cuaca saat ini.\nIni adalah laporan cuaca dari kota standar (hanya untuk menunjukkan kepada anda bagaimana tampilannya).\nKami akan mencoba permintaan baru lagi sesegera mungkin.\nAnda dapat mengikuti https://x.com/igor_chubin untuk informasi terbaru.\n======================================================================================\n\"\"\",\n        \"it\": \"\"\"\nScusate, attualmente stiamo esaurendo le risorse a disposizione del servizio meteo.\nQui trovate il bollettino del tempo per la città di default (solo per mostrarvi come si presenta).\nPotremo elaborare nuove richieste appena possibile.\nPotete seguire https://x.com/igor_chubin per gli aggiornamenti.\n======================================================================================\n\"\"\",\n        \"ko\": \"\"\"\n죄송합니다. 현재 날씨 정보를 가져오는 쿼리 요청이 한도에 도달했습니다.\n대신 기본으로 설정된 도시에 대한 일기 예보를 보여드리겠습니다. (이는 단지 어떻게 보이는지 알려주기 위함입니다).\n쿼리 요청이 가능한 한 빨리 이루어질 수 있도록 하겠습니다.\n업데이트 소식을 원하신다면 https://x.com/igor_chubin 을 팔로우 해주세요.\n======================================================================================\n\"\"\",\n        \"lt\": \"\"\"\nAtsiprašome, šiuo metu pasiekėme orų prognozės paslaugos užklausų ribą.\nŠtai orų prognozė numatomam miestui (tam, kad parodytume, kaip ji atrodo).\nNaujas užklausas priimsime, kai tik galėsime.\nAtnaujinimus galite sekti https://x.com/igor_chubin\n======================================================================================\n\"\"\",\n        \"lv\": \"\"\"\nAtvainojamies, šobrīd laikapstākļu pakalpojums ir noslogots!\nŠeit ir laika ziņas noklusējuma pilsētai (lai parādītu, kā tās izskatās).\nMēs atsāksim darbu, cik ātri vien varēsim.\nVar sekot https://x.com/igor_chubin, lai uzzinātu jaunumus.\n======================================================================================\n\"\"\",\n        \"mk\": \"\"\"\nИзвинете, ни снемуваат барања за до сервисот кој ни нуди временска прогноза во моментот.\nЕве една временска прогноза за град (за да видите како изгледа).\nЌе добиеме нови барања најбрзо што можеме.\nСледете го https://x.com/igor_chubin за известувања\n======================================================================================\n\"\"\",\n        \"mr\": \"\"\"\nक्षमस्व, याक्षणी आम्ही हवामान सेवेशी संपर्क करू शकत नाही.\nहा एका पूर्वनिर्धारित शहराचा हवामान अहवाल आहे (केवळ तो कसा दिसतो हे दाखवण्याकरिता).\nआम्ही लवकरात लवकर सेवा पुनः चालू करण्याचा प्रयत्न करू.\nअद्यावत माहितीसाठी तुम्ही https://x.com/igor_chubin चे अनुसरण करू शकता.\n======================================================================================\n\"\"\",\n        \"nb\": \"\"\"\nBeklager, vi kan ikke nå værtjenesten for øyeblikket.\nHer er værmeldingen for standardbyen så du får se hvordan tjenesten ser ut.\nVi vil forsøke å fikse problemet så snart som mulig.\nDu kan følge https://x.com/igor_chubin for oppdateringer.\n======================================================================================\n\"\"\",\n        \"zh\": \"\"\"\n抱歉，当前天气服务不可用。\n以下显示默认城市（只对您可见）。\n我们将会尽快获取新数据。\n您可以通过 https://x.com/igor_chubin 获取最新动态。\n======================================================================================\n\"\"\",\n        \"nl\": \"\"\"\nExcuse, wij kunnen u op dit moment dit weerbericht niet laten zien.\nHier is het weerbericht voor de standaard stad(zodat u weet hoe het er uitziet)\nWij lossen dit probleem zo snel mogelijk op.\nvoor updates kunt u ons op https://x.com/igor_chubin volgen.\n======================================================================================\n\"\"\",\n        \"oc\": \"\"\"\nO planhèm, avèm pas mai de requèstas cap al servici metèo.\nVaquí las prevision metèo de l'emplaçament per defaut (per vos donar un apercebut).\nPoirem lèu ne far de novèlas.\nPodètz seguir https://x.com/igor_chubin per demorar informat.\n======================================================================================\n\"\"\",\n        \"fy\": \"\"\"\nExcuses, wy kinne op dit moment 't waarberjocht net sjin litte.\nHjir is 't waarberjocht foar de standaard stêd.\nWy losse dit probleem sa gau mooglik op.\nFoar updates kinne jo ús op https://x.com/igor_chubin folgje.\n======================================================================================\n\"\"\",\n        \"pl\": \"\"\"\nBardzo nam przykro, ale chwilowo wykorzystaliśmy limit zapytań do serwisu pogodowego.\nTo, co widzisz jest przykładowym raportem pogodowym dla domyślnego miasta.\nPostaramy się przywrócić funkcjonalność tak szybko, jak to tylko możliwe.\nMożesz śledzić https://x.com/igor_chubin na Twitterze, aby być na bieżąco.\n======================================================================================\n\"\"\",\n        \"pt\": \"\"\"\nDesculpe-nos, estamos atingindo o limite de consultas ao serviço de previsão do tempo neste momento.\nVeja a seguir a previsão do tempo para uma cidade padrão (apenas para você ver que aspecto o relatório tem).\nEm breve voltaremos a ter acesso às consultas.\nVocê pode seguir https://x.com/igor_chubin para acompanhar a situação.\n======================================================================================\n\"\"\",\n        \"pt-br\": \"\"\"\nDesculpe-nos, atingimos o limite de consultas ao serviço de previsão do tempo neste momento.\nVeja a seguir a previsão do tempo para uma cidade padrão (apenas para você ver que aspecto o relatório tem).\nEm breve voltaremos a ter acesso às consultas.\nVocê pode seguir https://x.com/igor_chubin para acompanhar a situação.\n======================================================================================\n\"\"\",\n        \"ro\": \"\"\"\nNe pare rău, momentan am epuizat cererile alocate de către serviciul de prognoză meteo.\nVă arătăm prognoza meteo pentru localitatea implicită (ca exemplu, să vedeți cum arată).\nVom obține alocarea de cereri noi cât de curând posibil.\nPuteți urmări https://x.com/igor_chubin pentru actualizări.\n======================================================================================\n\"\"\",\n        \"te\": \"\"\"\nక్షమించండి, ప్రస్తుతానికి మేము వాతావరణ సేవకు ప్రశ్నలను గడుపుతున్నాం.\nఇక్కడ డిఫాల్ట్ నగరం కోసం వాతావరణ నివేదిక (కేవలం మీకు చూపించడానికి, ఇది ఎలా కనిపిస్తుంది).\nసాధ్యమైనంత త్వరలో కొత్త ప్రశ్నలను పొందుతారు.\nనవీకరణల కోసం https://x.com/igor_chubin ను మీరు అనుసరించవచ్చు.\n======================================================================================\n\"\"\",\n        \"tr\": \"\"\"\nÜzgünüz, an itibariyle hava durumu servisine yapabileceğimiz sorgu limitine ulaştık.\nVarsayılan şehir için hava durumu bilgisini görüyorsunuz (neye benzediğini gösterebilmek için).\nMümkün olan en kısa sürede servise yeniden sorgu yapmaya başlayacağız.\nGelişmeler için https://x.com/igor_chubin adresini takip edebilirsiniz.\n======================================================================================\n\"\"\",\n        \"th\": \"\"\"\nขออภัย การเรียกค้นหาระบบสภาพอากาศของเราหมดชั่วคราว\nเราจึงแสดงข้อมูลของเมืองตัวอย่าง (เพื่อที่จะแสดงให้คุณเห็นว่าหน้าตาเป็นยังไง)\nเราจะเรียกค้นหาใหม่โดยเร็วที่สุด\nคุณสามารถติดตามการอัพเดทได้ที่ https://x.com/igor_chubin\n======================================================================================\n\"\"\",\n        \"da\": \"\"\"\nBeklager, men vi er ved at løbe tør for forespørgsler til vejr-servicen lige nu.\nHer er vejr rapporten for standard byen (bare så du ved hvordan det kan se ud).\nVi får nye forespørsler hurtigst muligt.\nDu kan følge https://x.com/igor_chubin for at få opdateringer.\n======================================================================================\n\"\"\",\n        \"et\": \"\"\"\nVabandage, kuid hetkel on päringud ilmateenusele piiratud.\nSelle asemel kuvame hetkel näidislinna ilmaprognoosi (näitamaks, kuidas see välja näeb).\nÜritame probleemi lahendada niipea kui võimalik.\nJälgige https://x.com/igor_chubin värskenduste jaoks.\n======================================================================================\n\"\"\",\n        \"uk\": \"\"\"\nВибачте, ми перевищили максимальну кількість запитів до сервісу погоди.\nОсь прогноз погоди у нашому місті (просто показати Вам як це виглядає).\nМи відновимо роботу як тільки зможемо.\nВи можете підписатися на https://x.com/igor_chubin для отримання новин.\n======================================================================================\n\"\"\",\n        \"vi\": \"\"\"\nXin lỗi, hiện tại chúng tôi đã hết lượt yêu cầu thông tin thời tiết.\nĐây là dự báo thời tiết cho thành phố mặc định (chỉ để cho bạn thấy nó trông như thế nào).\nChung tôi sẽ có thêm lượt truy vấn sớm nhất có thể\nBạn có thể theo dõi https://x.com/igor_chubin để cập nhật thông tin mới nhất.\n======================================================================================\n\"\"\",\n        \"zh-tw\": \"\"\"\n抱歉，目前天氣服務的查詢請求太多了。\n這裡是預設城市的天氣報告（只是為您展示它的外觀）。\n我們將盡快取得新的資料。\n您可以追蹤 https://x.com/igor_chubin 以取得更新。\n======================================================================================\n\"\"\",\n        \"mg\": \"\"\"\nMiala tsiny fa misedra olana ny sampan-draharaha momba ny toetrandro amin'izao fotoana izao.\nIty ny tatitra momba ny toetr'andro ho an'ny tanàna mahazatra (mba hampisehoana anao ny endriny).\nHaivaly aminao haingana ny fangatahanao.\nAzonao atao ny manaraka ny pejy https://x.com/igor_chubin.\n\"\"\",\n        \"ta\": \"\"\"\nமன்னிக்கவும், தற்போது வானிலை சேவைக்கான வினவல்கள் எங்களிடம் இல்லை.\nஇயல்புநிலை நகரத்திற்கான வானிலை அறிக்கை இதோ (அது எப்படி இருக்கும் என்பதை உங்களுக்குக் காண்பிப்பதற்காக).\nகூடிய விரைவில் புதிய வினவல்களைப் பெறுவோம்.\nபுதுப்பிப்புகளுக்கு நீங்கள் https://x.com/igor_chubin ஐப் பின்தொடரலாம்.\n\"\"\",\n    },\n    # Historical messages:\n    #     'Check new Feature: \\033[92mwttr.in/Moon\\033[0m or \\033[92mwttr.in/Moon@2016-Mar-23\\033[0m to see the phase of the Moon'\n    #     'New feature: \\033[92mwttr.in/Rome?lang=it\\033[0m or \\033[92mcurl -H \"Accept-Language: it\" wttr.in/Rome\\033[0m for the localized version. Your lang instead of \"it\"'\n    \"NEW_FEATURE\": {\n        \"en\": \"New feature: multilingual location names \\033[92mwttr.in/станция+Восток\\033[0m (in UTF-8) and location search \\033[92mwttr.in/~Kilimanjaro\\033[0m (just add ~ before)\",\n        \"am\": \"አዲስ ባህሪ: የአካባቢ ስሞች በተለያዩ ቋንቋዎች \\033[92mwttr.in/ኢትዮጵያ\\033[0m (በ UTF-8) እና የአካባቢ ፍለጋ \\033[92mwttr.in/~Kilimanjaro\\033[0m (ከአካባቢ ስም በፊት ~ ያክሉ)\",\n        \"ar\": \"ميزة جديدة : أسماء الأماكن بلغات متعددة \\033[92mwttr.in/станция+Восток\\033[0m (in UTF-8) والبحث عن الأماكن \\033[92mwttr.in/~Kilimanjaro\\033[0m (فقط أضف ~ قبل)\",\n        \"af\": \"Nuwe eienskap: veeltalige name vir liggings \\033[92mwttr.in/станция+Восток\\033[0m (in UTF-8) en ligging soek \\033[92mwttr.in/~Kilimanjaro\\033[0m (plaas net ~ vooraan)\",\n        \"be\": \"Новыя магчымасці: назвы месц на любой мове \\033[92mwttr.in/станция+Восток\\033[0m (в UTF-8) i пошук месц \\033[92mwttr.in/~Kilimanjaro\\033[0m (трэба дадаць ~ ў пачатак)\",\n        \"bg\": \"Нова функционалност: многоезични имена на места\\033[92mwttr.in/станция+Восток\\033[0m (в UTF-8) и в търсенето \\033[92mwttr.in/~Kilimanjaro\\033[0m (добавете ~ преди)\",\n        \"bn\": \"নতুন ফিচার : বহুভাষিক অবস্থানের নাম \\ 033 [92mwttr.in/станция+Восток\\033 [0m (UTF-8)] এবং অবস্থান অনুসন্ধান \\ 033 [92mwttr.in/~Kilimanjaro\\033 [0m (শুধু আগে ~ যোগ করুন)\",\n        \"bs\": \"XXXXXXXXXXXXXXXXXXXX: XXXXXXXXXXXXXXXXXXXXXXXXXXXXX\\033[92mwttr.in/станция+Восток\\033[0m (XX UTF-8) XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\",\n        \"ca\": \"Noves funcionalitats: noms d'ubicació multilingües \\033[92mwttr.in/станция+Восток\\033[0m (en UTF-8) i la ubicació de recerca \\033[92mwttr.in/~Kilimanjaro\\033[0m (només cal afegir ~ abans)\",\n        \"cs\": \"Nová funkce: vícejazyčná jména poloh  \\033[92mwttr.in/станция+Восток\\033[0m (v UTF-8) a vyhledávání polohy \\033[92mwttr.in/~Kilimanjaro\\033[0m (pouze přidejte ~ před pozici)\",\n        \"es\": \"Nuevas funcionalidades: los nombres de las ubicaciones en varios idiomas \\033[92mwttr.in/станция+Восток\\033[0m (em UTF-8) y la búsqueda por ubicaciones \\033[92mwttr.in/~Kilimanjaro\\033[0m (tan solo inserte ~ al principio)\",\n        \"fa\": \"قابلیت جدید: پشتیبانی از نام چند زبانه مکانها \\033[92mwttr.in/станция+Восток\\033[0m (در فرمت UTF-8) و جسجتوی مکان ها \\033[92mwttr.in/~Kilimanjaro\\033[0m (فقط قبل از اون ~ اضافه کنید)\",\n        \"fr\": \"Nouvelles fonctionnalités: noms d'emplacements multilingues \\033[92mwttr.in/станция+Восток\\033[0m (en UTF-8) et recherche d'emplacement \\033[92mwttr.in/~Kilimanjaro\\033[0m (ajouter ~ devant)\",\n        \"gl\": \"Nova funcionalidade: nomes de localizacións en varios idiomas\\033[92mwttr.in/станция+Восток\\033[0m (en UTF-8) e procuras de localizacións \\033[92mwttr.in/~Kilimanjaro\\033[0m (engade ~ antes)\",\n        \"mk\": \"Нова функција: повеќе јазично локациски имиња \\033[92mwttr.in/станция+Восток\\033[0m (во UTF-8) и локациско пребарување \\033[92mwttr.in/~Kilimanjaro\\033[0m (just add ~ before)\",\n        \"nb\": \"Ny funksjon: flerspråklige stedsnavn \\033[92mwttr.in/станция+Восток\\033[0m (i UTF-8) og lokasjonssøk \\033[92mwttr.in/~Kilimanjaro\\033[0m (bare legg til ~ foran)\",\n        \"nl\": \"Nieuwe functie: tweetalige locatie namen \\033[92mwttr.in/станция+Восток\\033[0m (in UTF-8) en locatie zoeken \\033[92mwttr.in/~Kilimanjaro\\033[0m (zet er gewoon een ~ voor)\",\n        \"fy\": \"Nije funksje: twatalige lokaasje nammen \\033[92mwttr.in/станция+Восток\\033[0m (in UTF-8) en lokaasje sykjen \\033[92mwttr.in/~Kilimanjaro\\033[0m (set er gewoan in ~ foar)\",\n        \"cy\": \"Nodwedd newydd: enwau lleoliadau amlieithog \\033[92mwttr.in/станция+Восток\\033[0m (yn UTF-8) a chwilio am leoliad \\033[92mwttr.in/~Kilimanjaro\\033[0m (ychwanegwch ~ yn gyntaf)\",\n        \"de\": \"Neue Funktion: mehrsprachige Ortsnamen \\033[92mwttr.in/станция+Восток\\033[0m (in UTF-8) und Ortssuche \\033[92mwttr.in/~Kilimanjaro\\033[0m (fügen Sie ein ~ vor dem Ort ein)\",\n        \"hi\": \"नई सुविधा: बहुभाषी स्थान के नाम \\033[92mwttr.in/станция+Восток\\033[0m (in UTF-8) और स्थान खोज \\033[92mwttr.in/~Kilimanjaro\\033[0m (बस ~ आगे लगाये)\",\n        \"hu\": \"Új funkcinalitás: többnyelvű helynevek \\033[92mwttr.in/станция+Восток\\033[0m (UTF-8-ban) és pozíció keresés \\033[92mwttr.in/~Kilimanjaro\\033[0m (csak adj egy ~ jelet elé)\",\n        \"hy\": \"Փորձարկեք: տեղամասերի անունները կամայական լեզվով \\033[92mwttr.in/Դիլիջան\\033[0m (в UTF-8) և տեղանքի որոնում \\033[92mwttr.in/~Kilimanjaro\\033[0m (հարկավոր է ~ ավելացնել դիմացից)\",\n        \"ia\": \"Nove functione: location nomine multilingue \\033[92mwttr.in/станция+Восток\\033[0m (a UTF-8) e recerca de location\\033[92mwttr.in/~Kilimanjaro\\033[0m (solo adde ~ ante)\",\n        \"id\": \"Fitur baru: nama lokasi dalam multibahasa \\033[92mwttr.in/станция+Восток\\033[0m (in UTF-8) dan pencarian lokasi \\033[92mwttr.in/~Kilimanjaro\\033[0m (hanya tambah tanda ~ sebelumnya)\",\n        \"it\": \"Nuove funzionalità: nomi delle località multilingue \\033[92mwttr.in/станция+Восток\\033[0m (in UTF-8) e ricerca della località \\033[92mwttr.in/~Kilimanjaro\\033[0m (basta premettere ~)\",\n        \"ko\": \"새로운 기능: 다국어로 대응된 위치 \\033[92mwttr.in/서울\\033[0m (UTF-8에서) 장소 검색 \\033[92mwttr.in/~Kilimanjaro\\033[0m (앞에 ~를 붙이세요)\",\n        \"kk\": \"\",\n        \"lt\": \"Naujiena: daugiakalbiai vietovių pavadinimai \\033[92mwttr.in/станция+Восток\\033[0m (UTF-8) ir vietovių paieška \\033[92mwttr.in/~Kilimanjaro\\033[0m (tiesiog priekyje pridėkite ~)\",\n        \"lv\": \"Jauna iespēja: daudzvalodu atrašanās vietu nosaukumi \\033[92mwttr.in/станция+Восток\\033[0m (UTF-8) un atrašanās vietu meklēšana \\033[92mwttr.in/~Kilimanjaro\\033[0m (sākumā tikai jāpievieno ~)\",\n        \"mk\": \"Нова функција: повеќе јазично локациски имиња \\033[92mwttr.in/станция+Восток\\033[0m (во UTF-8) и локациско пребарување \\033[92mwttr.in/~Kilimanjaro\\033[0m (just add ~ before)\",\n        \"mr\": \"नवीन वैशिष्ट्य: स्थळांची बहुभाषिक नावे \\033[92mwttr.in/станция+Восток\\033[0m (UTF-8 मध्ये) आणि स्थळ शोध \\033[92mwttr.in/~Kilimanjaro\\033[0m (फक्त आधी ~ जोडा)\",\n        \"oc\": \"Novèla foncionalitat : nom de lòc multilenga \\033[92mwttr.in/станция+Восток\\033[0m (en UTF-8) e recèrca de lòc \\033[92mwttr.in/~Kilimanjaro\\033[0m (solament ajustatz ~ abans)\",\n        \"pl\": \"Nowa funkcjonalność: wielojęzyczne nazwy lokalizacji \\033[92mwttr.in/станция+Восток\\033[0m (w UTF-8) i szukanie lokalizacji \\033[92mwttr.in/~Kilimanjaro\\033[0m (poprzedź zapytanie ~ - znakiem tyldy)\",\n        \"pt\": \"Nova funcionalidade: nomes de localidades em várias línguas \\033[92mwttr.in/станция+Восток\\033[0m (em UTF-8) e procura por localidades \\033[92mwttr.in/~Kilimanjaro\\033[0m (é só colocar ~ antes)\",\n        \"pt-br\": \"Nova funcionalidade: nomes de localidades em várias línguas \\033[92mwttr.in/станция+Восток\\033[0m (em UTF-8) e procura por localidades \\033[92mwttr.in/~Kilimanjaro\\033[0m (é só colocar ~ antes)\",\n        \"ro\": \"Funcționalitate nouă: nume de localități multilingve \\033[92mwttr.in/станция+Восток\\033[0m (in UTF-8) și căutare de localități \\033[92mwttr.in/~Kilimanjaro\\033[0m (adăuați ~ în față)\",\n        \"ru\": \"Попробуйте: названия мест на любом языке \\033[92mwttr.in/станция+Восток\\033[0m (в UTF-8) и поиск мест \\033[92mwttr.in/~Kilimanjaro\\033[0m (нужно добавить ~ спереди)\",\n        \"zh\": \"新功能：多语言地点名称 \\033[92mwttr.in/станция+Восток\\033[0m (in UTF-8) 及地点搜索\\033[92mwttr.in/~Kilimanjaro\\033[0m （只需在名称前加~）\",\n        \"tr\": \"Yeni özellik: çok dilli konum isimleri \\033[92mwttr.in/станция+Восток\\033[0m (UTF-8 ile) ve konum arama \\033[92mwttr.in/~Kilimanjaro\\033[0m (sadece önüne ~ ekleyin)\",\n        \"te\": \"క్రొత్త లక్షణం: బహుభాషా స్థాన పేర్లు \\ 033 [92mwttr.in/stancelя+Vostок\\033 [0 U (UTF-8 లో) మరియు స్థానం శోధన \\ 033 [92mwttr.in/~kilimanjaro\\033 [0m (కేవలం ~ ముందుకి జోడించండి)\",\n        \"th\": \"ฟีเจอร์ใหม่: แสดงที่ตั้งได้หลายภาษา \\033[92mwttr.in/станция+Восток\\033[0m (ใน UTF-8) และการค้นหาที่ตั้ง \\033[92mwttr.in/~Kilimanjaro\\033[0m (เพียงเพิ่ม ~ ข้างหน้า)\",\n        \"da\": \"Ny funktion: flersprogede lokationsnavne \\033[92mwttr.in/станция+Восток\\033[0m (som UTF-8) og lokations søgning \\033[92mwttr.in/~Kilimanjaro\\033[0m (bare tilføj ~ inden)\",\n        \"et\": \"Uus funktsioon: mitmekeelsed asukohanimed \\033[92mwttr.in/станция+Восток\\033[0m (UTF-8 vormingus) ja asukoha otsing \\033[92mwttr.in/~Kilimanjaro\\033[0m (lisa ~ enne)\",\n        \"uk\": \"Спробуйте: назви місць будь-якою мовою \\033[92mwttr.in/станція+Восток\\033[0m (в UTF-8) та пошук місць \\033[92mwttr.in/~Kilimanjaro\\033[0m (потрібно додати ~ спочатку)\",\n        \"vi\": \"Chức năng mới: tên địa điểm đa ngôn ngữ \\033[92mwttr.in/станция+Восток\\033[0m (dùng UTF-8) và tìm kiếm địa điểm \\033[92mwttr.in/~Kilimanjaro\\033[0m (chỉ cần thêm ~ phía trước)\",\n        \"zh-tw\": \"新功能：多語言地點名稱 \\033[92mwttr.in/станция+Восток\\033[0m （使用 UTF-8 編碼）與位置搜尋 \\033[92mwttr.in/~Kilimanjaro\\033[0m （只要在地點前加 ~ 就可以了）\",\n        \"mg\": \"Fanatsrana vaovao: anarana toerana amin'ny fiteny maro\\033[92mwttr.in/станция+Восток\\033[0m (en UTF-8) sy fitadiavana toerana \\033[92mwttr.in/~Kilimanjaro\\033[0m (ampio ~ fotsiny eo aloha)\",\n        \"ta\": \"புதிய அம்சம்: பன்மொழி இருப்பிடப் பெயர்கள் \\033[92mwttr.in/станция+Восток\\033[0m (UTF-8 இல்) மற்றும் இருப்பிடத் தேடல் \\033[92mwttr.in/~Kilimanjaro\\033[0m (முன் ~ஐச் சேர்க்கவும்)\",\n    },\n    \"FOLLOW_ME\": {\n        \"en\": \"Follow \\033[46m\\033[30m@igor_chubin\\033[0m for wttr.in updates\",\n        \"ar\": \"لآخر المستجدات تابع \\033[46m\\033[30m@igor_chubin\\033[0m\",\n        \"af\": \"Volg \\033[46m\\033[30m@igor_chubin\\033[0m vir wttr.in opdaterings\",\n        \"am\": \"ለተጨማሪ wttr.in ዜና እና መረጃ \\033[46m\\033[30m@igor_chubin\\033[0m ን ይከተሉ\",\n        \"be\": \"Сачыце за \\033[46m\\033[30m@igor_chubin\\033[0m за навінамі wttr.in\",\n        \"bg\": \"Последвай \\033[46m\\033[30m@igor_chubin\\033[0m за обновления свързани с wttr.in\",\n        \"bn\": \"wttr.in আপডেটের জন্য \\033[46m\\033[30m@igor_chubin\\033[0m কে অনুসরণ করুন\",\n        \"bs\": \"XXXXXX \\033[46m\\033[30m@igor_chubin\\033[0m XXXXXXXXXXXXXXXXXXX\",\n        \"ca\": \"Segueix \\033[46m\\033[30m@igor_chubin\\033[0m per actualitzacions de wttr.in\",\n        \"cs\": \"Sledujte \\033[46m\\033[30m@igor_chubin\\033[0m pro aktualizace pro wttr.in\",\n        \"es\": \"Sigue a \\033[46m\\033[30m@igor_chubin\\033[0m para enterarte de las novedades de wttr.in\",\n        \"eu\": \"\\033[46m\\033[30m@igor_chubin\\033[0m jarraitu wttr.in berriak jasotzeko\",\n        \"cy\": \"Dilyner \\033[46m\\033[30m@igor_Chubin\\033[0m am diweddariadau wttr.in\",\n        \"fa\": \"برای دنبال کردن خبرهای wttr.in شناسه \\033[46m\\033[30m@igor_chubin\\033[0m رو فالو کنید.\",\n        \"fr\": \"Suivez \\033[46m\\033[30m@igor_Chubin\\033[0m pour rester informé sur wttr.in\",\n        \"de\": \"Folgen Sie \\033[46m\\033[30mhttps://x.com/igor_chubin\\033[0m für wttr.in Updates\",\n        \"ga\": \"Lean \\033[46m\\033[30m@igor_chubin\\033[0m don wttr.in eolas is deanaí\",\n        \"gl\": \"Segue a \\033[46m\\033[30m@igor_chubin\\033[0m para actualizacións sobre wttr.in\",\n        \"hi\": \"अपडेट के लिए फॉलो करें \\033[46m\\033[30m@igor_chubin\\033[0m\",\n        \"hu\": \"Kövesd \\033[46m\\033[30m@igor_chubin\\033[0m-t további wttr.in információkért\",\n        \"hy\": \"Նոր ֆիչռների համար հետևեք՝ \\033[46m\\033[30m@igor_chubin\\033[0m\",\n        \"ia\": \"Seque \\033[46m\\033[30m@igor_chubin\\033[0m por nove information de wttr.in\",\n        \"id\": \"Ikuti \\033[46m\\033[30m@igor_chubin\\033[0m untuk informasi wttr.in terbaru\",\n        \"it\": \"Seguite \\033[46m\\033[30m@igor_chubin\\033[0m per aggiornamenti a wttr.in\",\n        \"ko\": \"wttr.in의 업데이트 소식을 원하신다면 \\033[46m\\033[30m@igor_chubin\\033[0m 을 팔로우 해주세요\",\n        \"kk\": \"\",\n        \"lt\": \"wttr.in atnaujinimus sekite \\033[46m\\033[30m@igor_chubin\\033[0m\",\n        \"lv\": \"Seko \\033[46m\\033[30m@igor_chubin\\033[0m, lai uzzinātu jaunumus par wttr.in\",\n        \"mk\": \"Следете \\033[46m\\033[30m@igor_chubin\\033[0m за wttr.in новости\",\n        \"mr\": \"wttr.in च्या अद्यावत माहितीसाठी  \\033[46m\\033[30m@igor_chubin\\033[0m चे अनुसरण करा\",\n        \"nb\": \"Følg \\033[46m\\033[30m@igor_chubin\\033[0m for wttr.in oppdateringer\",\n        \"nl\": \"Volg \\033[46m\\033[30m@igor_chubin\\033[0m voor wttr.in updates\",\n        \"oc\": \"Seguissètz \\033[46m\\033[30m@igor_Chubin\\033[0m per demorar informat sus wttr.in\",\n        \"fy\": \"Folgje \\033[46m\\033[30m@igor_chubin\\033[0m foar wttr.in updates\",\n        \"pl\": \"Śledź \\033[46m\\033[30m@igor_chubin\\033[0m aby być na bieżąco z nowościami dotyczącymi wttr.in\",\n        \"pt\": \"Seguir \\033[46m\\033[30m@igor_chubin\\033[0m para as novidades de wttr.in\",\n        \"pt-br\": \"Seguir \\033[46m\\033[30m@igor_chubin\\033[0m para as novidades de wttr.in\",\n        \"ro\": \"Urmăriți \\033[46m\\033[30m@igor_chubin\\033[0m pentru actualizări despre wttr.in\",\n        \"ru\": \"Все новые фичи публикуются здесь: \\033[46m\\033[30m@igor_chubin\\033[0m\",\n        \"zh\": \"关注 \\033[46m\\033[30m@igor_chubin\\033[0m 获取 wttr.in 动态\",\n        \"te\": \"అనుసరించండి \\ 033 [46m \\ 033 [30m @ igor_chubin \\ 033 [wttr.in నవీకరణలను కోసం\",\n        \"tr\": \"wttr.in ile ilgili gelişmeler için \\033[46m\\033[30m@igor_chubin\\033[0m adresini takip edin\",\n        \"th\": \"ติดตาม \\033[46m\\033[30m@igor_chubin\\033[0m สำหรับการอัพเดท wttr.in\",\n        \"da\": \"Følg \\033[46m\\033[30m@igor_chubin\\033[0m for at få wttr.in opdateringer\",\n        \"et\": \"Jälgi \\033[46m\\033[30m@igor_chubin\\033[0m wttr.in uudiste tarbeks\",\n        \"uk\": \"Нові можливості wttr.in публікуються тут: \\033[46m\\033[30m@igor_chubin\\033[0m\",\n        \"vi\": \"Theo dõi \\033[46m\\033[30m@igor_chubin\\033[0m để cập nhật thông tin về wttr.in\",\n        \"zh-tw\": \"追蹤 \\033[46m\\033[30m@igor_chubin\\033[0m 以取得更多 wttr.in 的動態\",\n        \"mg\": \"Araho ao ny pejy \\033[46m\\033[30m@igor_Chubin\\033[0m raha toa ka te hahazo vaovao momban'ny wttr.in\",\n        \"ta\": \"wttr.in புதுப்பிப்புகளுக்கு \\033[46m\\033[30m@igor_chubin\\033[0m ஐப் பின்தொடரவும்\",\n    },\n}\nCAPTION = {\n    \"af\": \"Weer verslag vir:\",\n    \"am\": \"የአየር ሁኔታ ሪፖርት ለ\",\n    \"ar\": \"تقرير حالة الطقس\",\n    \"az\": \"Hava proqnozu:\",\n    \"be\": \"Прагноз надвор'я для:\",\n    \"bg\": \"Прогноза за времето в:\",\n    \"bn\": \"আবহাওয়ার প্রতিবেদন:\",\n    \"bs\": \"Vremenske prognoze za:\",\n    \"ca\": \"Informe del temps per a:\",\n    \"cs\": \"Předpověď počasí pro:\",\n    \"cy\": \"Adroddiad tywydd ar gyfer:\",\n    \"da\": \"Vejret i:\",\n    \"de\": \"Wetterbericht für:\",\n    \"el\": \"Πρόγνωση καιρού για:\",\n    \"en\": \"Weather report for:\",\n    \"eo\": \"Veterprognozo por:\",\n    \"es\": \"Pronóstico del tiempo en:\",\n    \"et\": \"Ilmaprognoos:\",\n    \"eu\": \"Eguraldiaren iragarpena:\",\n    \"fa\": \"گزارش آب و هئا برای شما:\",\n    \"fi\": \"Säätiedotus:\",\n    \"fr\": \"Prévisions météo pour:\",\n    \"fy\": \"Waarberjocht foar:\",\n    \"ga\": \"Réamhaisnéis na haimsire do:\",\n    \"he\": \":ריוואה גזמ תיזחת\",\n    \"hi\": \"मौसम की जानकारी\",\n    \"hr\": \"Vremenska prognoza za:\",\n    \"hu\": \"Időjárás előrejelzés:\",\n    \"hy\": \"Եղանակի տեսություն:\",\n    \"ia\": \"Reporto tempore por:\",\n    \"id\": \"Prakiraan cuaca:\",\n    \"it\": \"Previsioni meteo:\",\n    \"is\": \"Veðurskýrsla fyrir:\",\n    \"ja\": \"天気予報：\",\n    \"jv\": \"Weather forecast for:\",\n    \"ka\": \"ამინდის პროგნოზი:\",\n    \"kk\": \"Ауа райы:\",\n    \"ko\": \"일기 예보：\",\n    \"ky\": \"Аба ырайы:\",\n    \"lt\": \"Orų prognozė:\",\n    \"lv\": \"Laika ziņas:\",\n    \"mk\": \"Прогноза за времето во:\",\n    \"ml\": \"കാലാവസ്ഥ റിപ്പോർട്ട്:\",\n    \"mr\": \"हवामान अहवाल:\",\n    \"nb\": \"Værmelding for:\",\n    \"nl\": \"Weerbericht voor:\",\n    \"nn\": \"Vêrmelding for:\",\n    \"oc\": \"Previsions metèo per :\",\n    \"pl\": \"Pogoda w:\",\n    \"pt\": \"Previsão do tempo para:\",\n    \"pt-br\": \"Previsão do tempo para:\",\n    \"ro\": \"Prognoza meteo pentru:\",\n    \"ru\": \"Прогноз погоды:\",\n    \"sk\": \"Predpoveď počasia pre:\",\n    \"sl\": \"Vremenska napoved za\",\n    \"sr\": \"Временска прогноза за:\",\n    \"sr-lat\": \"Vremenska prognoza za:\",\n    \"sv\": \"Väderleksprognos för:\",\n    \"sw\": \"Ripoti ya hali ya hewa, jiji la:\",\n    \"te\": \"వాతావరణ సమాచారము:\",\n    \"th\": \"รายงานสภาพอากาศ:\",\n    \"tr\": \"Hava beklentisi:\",\n    \"uk\": \"Прогноз погоди для:\",\n    \"uz\": \"Ob-havo bashorati:\",\n    \"vi\": \"Báo cáo thời tiết:\",\n    \"zh\": \"天气预报：\",\n    \"zu\": \"Isimo sezulu:\",\n    \"zh-tw\": \"天氣報告：\",\n    \"mg\": \"Toetr'andro any :\",\n    \"ta\": \"வானிலை அறிக்கை:\",\n}\n\n\ndef get_message(message_name, lang):\n    if lang == \"zh-cn\":\n        lang = \"zh\"\n    if message_name not in MESSAGE:\n        return \"\"\n    message_dict = MESSAGE[message_name]\n    return message_dict.get(lang, message_dict.get(\"en\", \"\"))\n"
  },
  {
    "path": "lib/translations_v2.py",
    "content": "# vim: fileencoding=utf-8\n\n\"\"\"\nTranslation of v2\n\"\"\"\n\n# pylint: disable=line-too-long,bad-whitespace\nV2_TRANSLATION = {\n    \"en\": (\n        \"Weather report for:\",\n        \"Weather\",\n        \"Timezone\",\n        \"Now\",\n        \"Dawn\",\n        \"Sunrise\",\n        \"Zenith\",\n        \"Sunset\",\n        \"Dusk\",\n    ),\n    \"af\": (\"Weer verslag vir:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"am\": (\n        \"የአየር ሁኔታ ዘገባ ለ ፥\",\n        \"የአየር ሁኔታ\",\n        \"የጊዜ ሰቅ\",\n        \"አሁን\",\n        \"ንጋት\",\n        \"የፀሐይ መውጫ\",\n        \"\",\n        \"የፀሐይ መጥለቅ\",\n        \"ምሽት\",\n    ),\n    \"ar\": (\n        \"تقرير حالة الطقس:\",\n        \"حالة الطقس\",\n        \"المنطقة الزمنية\",\n        \"الآن \",\n        \"الفجر\",\n        \"شروق الشمس\",\n        \"الذروة\",\n        \"غروب الشمس\",\n        \"الغسق\",\n    ),\n    \"az\": (\n        \"Hava proqnozu:\",\n        \"Hava\",\n        \"Saat zonası\",\n        \"İndi\",\n        \"Şəfəq\",\n        \"Günəş çıxdı\",\n        \"Zenit\",\n        \"Gün batımı\",\n        \"Toran\",\n    ),\n    \"be\": (\n        \"Прагноз надвор'я для:\",\n        \"Надвор'е\",\n        \"Часавая зона\",\n        \"Цяпер\",\n        \"Світанак\",\n        \"Усход сонца\",\n        \"Зеніт\",\n        \"Захад сонца\",\n        \"Змярканне\",\n    ),\n    \"bg\": (\"Прогноза за времето в:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"bn\": (\n        \"আবহাওয়া প্রতিবেদন:\",\n        \"আবহাওয়া\",\n        \"টাইমজোন\",\n        \"এখন\",\n        \"ভোর\",\n        \"সূর্যোদয়\",\n        \"সুবিন্দু\",\n        \"সূর্যাস্ত\",\n        \"সন্ধ্যা\",\n    ),\n    \"bs\": (\"Vremenske prognoze za:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"ca\": (\n        \"Informe del temps per a:\",\n        \"Oratge\",\n        \"Zona horària\",\n        \"Ara\",\n        \"Albada\",\n        \"Sortida\",\n        \"Zenit\",\n        \"Posta\",\n        \"Crepuscle\",\n    ),\n    \"cs\": (\n        \"Předpověď počasí pro:\", \n        \"Počasí\", \n        \"Časové pásmo\", \n        \"Nyní\", \n        \"Svítání\", \n        \"Východ slunce\", \n        \"Vrchol\", \n        \"Západ slunce\", \n        \"Soumrak\"\n    ),\n    \"cy\": (\"Adroddiad tywydd ar gyfer:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"da\": (\n        \"Vejret i:\",\n        \"Vejret\",\n        \"Tidszone\",\n        \"Nu\",\n        \"Daggry\",\n        \"Solopgang\",\n        \"Zenit\",\n        \"Solnedgang\",\n        \"Skumring\",\n    ),\n    \"de\": (\n        \"Wetterbericht für:\",\n        \"Wetter\",\n        \"Zeitzone\",\n        \"Jetzt\",\n        \"Morgendämmerung\",\n        \"Sonnenaufgang\",\n        \"Zenit\",\n        \"Sonnenuntergang\",\n        \"Abenddämmerung\",\n    ),\n    \"el\": (\"Πρόγνωση καιρού για:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"eo\": (\n        \"Veterprognozo por:\",\n        \"Vetero\",\n        \"Horzono\",\n        \"Nun\",\n        \"Tagiĝo\",\n        \"Sunleviĝo\",\n        \"Zenito\",\n        \"Sunsubiro\",\n        \"Krepusko\",\n    ),\n    \"es\": (\n        \"El tiempo en:\",\n        \"Clima\",\n        \"Zona horaria\",\n        \"Ahora\",\n        \"Alborada\",\n        \"Amanecer\",\n        \"Cenit\",\n        \"Atardecer\",\n        \"Anochecer\",\n    ),\n    \"et\": (\n        \"Ilmaprognoos:\",\n        \"Ilm\",\n        \"Ajatsoon\",\n        \"Hetkel\",\n        \"Koit\",\n        \"Päikesetõus\",\n        \"Seniit\",\n        \"Päikeseloojang\",\n        \"Eha\",\n    ),\n    \"eu\": (\n        \"Eguraldia:\",\n        \"Ordu-eremua\",\n        \"Orain\",\n        \"Egunsentia\",\n        \"Eguzkia\",\n        \"Zenit\",\n        \"Ilunabarra\",\n        \"Ilunabarra\",\n    ),\n    \"fa\": (\"گزارش وضعیت آب و هوا\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"fi\": (\"Säätiedotus:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"fr\": (\n        \"Prévisions météo pour :\",\n        \"Météo\",\n        \"Fuseau Horaire\",\n        \"Heure\",\n        \"Aube\",\n        \"Lever du Soleil\",\n        \"Zénith\",\n        \"Coucher du Soleil\",\n        \"Crépuscule\",\n    ),\n    \"fy\": (\"Waarberjocht foar:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"ga\": (\n        \"Réamhaisnéis na haimsire do:\",\n        \"Aimsir\",\n        \"Crios ama\",\n        \"Anois\",\n        \"Breacadh an lae\",\n        \"Éirí na gréine\",\n        \"Forar\",\n        \"Dul faoi na gréine\",\n        \"Coineascar\",\n    ),\n    \"he\": (\":ריוואה גזמ תיזחת\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"hi\": (\n        \"मौसम की जानकारी\",\n        \"मौसम\",\n        \"समय मण्डल\",\n        \"अभी\",\n        \"उदय\",\n        \"सूर्योदय\",\n        \"चरम बिन्दु\",\n        \"सूर्यास्त\",\n        \"संध्याकाल\",\n    ),\n    \"hr\": (\"Vremenska prognoza za:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"hu\": (\n        \"Időjárás előrejelzés:\",\n        \"Időjárás\",\n        \"időzóna\",\n        \"aktuális\",\n        \"hajnal\",\n        \"napkelte\",\n        \"dél\",\n        \"naplemente\",\n        \"szürkület\",\n    ),\n    \"hy\": (\"Եղանակի տեսություն:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"ia\": (\n        \"Reporto tempore pro:\",\n        \"Tempore\",\n        \"Fuso Horari\",\n        \"Alora\",\n        \"Alba\",\n        \"Aurora\",\n        \"Zenit\",\n        \"Poner del sol\",\n        \"Crepusculo\",\n    ),\n    \"id\": (\"Prakiraan cuaca:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"it\": (\n        \"Previsioni meteo:\",\n        \"Tempo\",\n        \"Fuso orario\",\n        \"Ora\",\n        \"Alba\",\n        \"Sorgere del Sole\",\n        \"Zenit\",\n        \"Tramonto\",\n        \"Crepuscolo\",\n    ),\n    \"is\": (\"Veðurskýrsla fyrir:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"ja\": (\"天気予報：\", \"天気\", \"タイムゾーン\", \"今\", \"夜明け\", \"日の出\", \"天頂\", \"日の入\", \"日暮れ\"),\n    \"jv\": (\"Weather forecast for:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"ka\": (\"ამინდის პროგნოზი:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"kk\": (\"Ауа райы:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"ko\": (\"일기 예보：\", \"날씨\", \"시간대\", \"현재\", \"새벽\", \"일출\", \"정오\", \"일몰\", \"황혼\"),\n    \"ky\": (\"Аба ырайы:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"lt\": (\n        \"Orų prognozė:\",\n        \"Orai\",\n        \"Laiko zona\",\n        \"Dabar\",\n        \"Aušra\",\n        \"Saulėtekis\",\n        \"Zenitas\",\n        \"Saulėlydis\",\n        \"Sutemos\",\n    ),\n    \"lv\": (\n        \"Laika ziņas par:\",\n        \"laikapstākļiem\",\n        \"laika joslu\",\n        \"tagad\",\n        \"rītausmu\",\n        \"saullēktu\",\n        \"zenītu\",\n        \"saulrietu\",\n        \"vakara krēslu\",\n    ),\n    \"mk\": (\"Прогноза за времето во:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"ml\": (\n        \"കാലാവസ്ഥ റിപ്പോർട്ട്:\",\n        \"കാലാവസ്\",\n        \"സമയ മേഖല\",\n        \"ഇപ്പോൾ\",\n        \"പ്രഭാതത്തെ\",\n        \"ഉച്ചതിരിഞ്ഞ്\",\n        \"സൂര്യോദയം\",\n        \"പരമോന്നത\",\n        \"സൂര്യാസ്തമയം\",\n        \"സന്ധ്യ\",\n    ),\n    \"mr\": (\n        \"हवामान अहवालाचे ठिकाण:\",\n        \"हवामान\",\n        \"कालक्षेत्र\",\n        \"आता\",\n        \"पहाट\",\n        \"सूर्योदय\",\n        \"शिखरबिंदु\",\n        \"सूर्यास्त\",\n        \"संध्याकाळ\",\n    ),\n    \"nb\": (\n        \"Værmelding for:\",\n        \"Vær\",\n        \"Tidssone\",\n        \"Nå\",\n        \"Morgengry\",\n        \"Soloppgang\",\n        \"Solhøyde\",\n        \"Solnedgang\",\n        \"Skumring\",\n    ),\n    \"nl\": (\n        \"Weerbericht voor:\",\n        \"Weer\",\n        \"Tijdzone\",\n        \"Nu\",\n        \"Dageraad\",\n        \"Zonsopkomst\",\n        \"Zenit\",\n        \"Zonsondergang\",\n        \"Schemering\",\n    ),\n    \"nn\": (\"Vêrmelding for:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"oc\": (\n        \"Previsions metèo per:\" \"Metèo\",\n        \"Zòna orària\",\n        \"Ara\",\n        \"Auròra\",\n        \"Alba\",\n        \"Zenit\",\n        \"A solelh colc\",\n        \"Entrelutz\",\n    ),\n    \"pl\": (\"Pogoda w:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"pt\": (\n        \"Previsão do tempo para:\",\n        \"Tempo\",\n        \"Fuso horário\",\n        \"Agora\",\n        \"Alvorada\",\n        \"Nascer do sol\",\n        \"Zénite\",\n        \"Pôr do sol\",\n        \"Crepúsculo\",\n    ),\n    \"pt-br\": (\n        \"Previsão do tempo para:\",\n        \"Tempo\",\n        \"Fuso horário\",\n        \"Agora\",\n        \"Alvorada\",\n        \"Nascer do sol\",\n        \"Zénite\",\n        \"Pôr do sol\",\n        \"Crepúsculo\",\n    ),\n    \"ro\": (\"Prognoza meteo pentru:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"ru\": (\n        \"Прогноз погоды:\",\n        \"Погода\",\n        \"Часовой пояс\",\n        \"Сейчас\",\n        \"Рассвет\",\n        \"Восход\",\n        \"Зенит\",\n        \"Закат\",\n        \"Сумерки\",\n    ),\n    \"sk\": (\"Predpoveď počasia pre:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"sl\": (\"Vremenska napoved za\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"sr\": (\"Временска прогноза за:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"sr-lat\": (\"Vremenska prognoza za:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"sv\": (\"Väderleksprognos för:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"sw\": (\"Ripoti ya hali ya hewa, jiji la:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"te\": (\n        \"వాతావరణ సమాచారము:\",\n        \"వాతావరణం\",\n        \"కాల మండలం\",\n        \"ప్రస్తుతం\",\n        \"తెల్లవారుజాము\",\n        \"సూర్యోదయం\",\n        \"ఉన్నత స్థానం\",\n        \"సూర్యాస్తమయం\",\n        \"సందెచీకటి\",\n    ),\n    \"th\": (\"รายงานสภาพอากาศ:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"tr\": (\n        \"Hava beklentisi:\",\n        \"Hava Durumu\",\n        \"Zaman Dilimi\",\n        \"Şimdi\",\n        \"Şafak\",\n        \"Gün Doğumu\",\n        \"Doruk\",\n        \"Gün Batımı\",\n        \"Akşam\",\n    ),\n    \"uk\": (\n        \"Прогноз погоди для:\",\n        \"Погода\",\n        \"Часовий пояс\",\n        \"Зараз\",\n        \"Світанок\",\n        \"Схід сонця\",\n        \"Зеніт\",\n        \"Захід сонця\",\n        \"Сутінки\",\n    ),\n    \"uz\": (\"Ob-havo bashorati:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"vi\": (\"Báo cáo thời tiết:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"zh\": (\"天气预报：\", \"天气\", \"时区\", \"当前\", \"黎明\", \"日出\", \"正午\", \"日落\", \"黄昏\"),\n    \"zh-tw\": (\"天氣預報：\", \"天氣\", \"時區\", \"目前\", \"黎明\", \"日出\", \"日正當中\", \"日落\", \"黃昏\"),\n    \"zu\": (\"Isimo sezulu:\", \"\", \"\", \"\", \"\", \"\", \"\", \"\", \"\"),\n    \"mg\": (\n        \"Vinavina toetr'andro hoany :\",\n        \"Toetr'andro\",\n        \"Faritra ora\",\n        \"Ora\",\n        \"Mangirandratsy\",\n        \"Maneno akoho\",\n        \"Mitatao vovonana\",\n        \"Masoandro milentika\",\n        \"Crépuscule\",\n    ),\n    \"ta\": (\n        \"வானிலை அறிக்கை:\",\n        \"வானிலை\",\n        \"நேரம் மண்டலம்\",\n        \"இப்போது\",\n        \"விடியல்\",\n        \"சூரிய உதயம்\",\n        \"ஜெனித்\",\n        \"சூரிய அஸ்தமனம்\",\n        \"அந்தி\",\n    ),\n}\n"
  },
  {
    "path": "lib/view/__init__.py",
    "content": ""
  },
  {
    "path": "lib/view/line.py",
    "content": "# vim: fileencoding=utf-8\n\n\"\"\"\nOne-line output mode.\n\nInitial implementation of one-line output mode.\n\n[ ] forecast\n[ ] spark\n[ ] several locations\n[ ] location handling\n[ ] more preconfigured format lines\n[ ] add information about this mode to /:help\n\"\"\"\n\nimport sys\nimport re\nimport datetime\nimport json\nimport requests\n\nfrom astral import LocationInfo\nfrom astral import moon\nfrom astral.sun import sun\n\nimport pytz\n\nfrom constants import (\n    WWO_CODE,\n    WEATHER_SYMBOL,\n    WEATHER_SYMBOL_WI_NIGHT,\n    WEATHER_SYMBOL_WI_DAY,\n    WIND_DIRECTION,\n    WIND_DIRECTION_WI,\n    WEATHER_SYMBOL_WIDTH_VTE,\n    WEATHER_SYMBOL_PLAIN,\n)\nfrom weather_data import get_weather_data\nfrom . import v2\n#from . import v3\nfrom . import prometheus\n\nPRECONFIGURED_FORMAT = {\n    \"1\": r\"%c %t\\n\",\n    \"2\": r\"%c 🌡️%t 🌬️%w\\n\",\n    \"3\": r\"%l: %c %t\\n\",\n    \"4\": r\"%l: %c 🌡️%t 🌬️%w\\n\",\n    \"69\": r\"nice\",\n}\n\nMOON_PHASES = (\"🌑\", \"🌒\", \"🌓\", \"🌔\", \"🌕\", \"🌖\", \"🌗\", \"🌘\")\n\n\ndef convert_to_fahrenheit(temp):\n    \"Convert Celcius `temp` to Fahrenheit\"\n\n    return (temp * 9.0 / 5) + 32\n\n\ndef render_temperature(data, query):\n    \"\"\"\n    temperature (t)\n    \"\"\"\n\n    if query.get(\"use_imperial\", False):\n        temperature = \"%s°F\" % data[\"temp_F\"]\n    else:\n        temperature = \"%s°C\" % data[\"temp_C\"]\n\n    if temperature[0] != \"-\":\n        temperature = \"+\" + temperature\n\n    return temperature\n\n\ndef render_feel_like_temperature(data, query):\n    \"\"\"\n    feel like temperature (f)\n    \"\"\"\n\n    if query.get(\"use_imperial\", False):\n        temperature = \"%s°F\" % data[\"FeelsLikeF\"]\n    else:\n        temperature = \"%s°C\" % data[\"FeelsLikeC\"]\n\n    if temperature[0] != \"-\":\n        temperature = \"+\" + temperature\n\n    return temperature\n\n\ndef render_condition(data, query):\n    \"\"\"Emoji encoded weather condition (c)\"\"\"\n\n    if query.get(\"view\") == \"v2n\":\n        weather_condition = WEATHER_SYMBOL_WI_NIGHT.get(\n            WWO_CODE.get(data[\"weatherCode\"], \"Unknown\")\n        )\n        spaces = \"  \"\n    elif query.get(\"view\") == \"v2d\":\n        weather_condition = WEATHER_SYMBOL_WI_DAY.get(\n            WWO_CODE.get(data[\"weatherCode\"], \"Unknown\")\n        )\n        spaces = \"  \"\n    else:\n        weather_condition = WEATHER_SYMBOL.get(\n            WWO_CODE.get(data[\"weatherCode\"], \"Unknown\")\n        )\n        spaces = \" \" * (3 - WEATHER_SYMBOL_WIDTH_VTE.get(weather_condition, 1))\n\n    return weather_condition + spaces\n\n\ndef render_condition_fullname(data, query):\n    \"\"\"\n    condition_fullname (C)\n    \"\"\"\n\n    found = None\n    for key, val in data.items():\n        if key.startswith(\"lang_\"):\n            found = val\n            break\n    if not found:\n        found = data[\"weatherDesc\"]\n\n    try:\n        weather_condition = found[0][\"value\"]\n    except KeyError:\n        weather_condition = \"\"\n\n    return weather_condition\n\n\ndef render_condition_plain(data, query):\n    \"\"\"Plain text weather condition (x)\"\"\"\n\n    weather_condition = WEATHER_SYMBOL_PLAIN[WWO_CODE[data[\"weatherCode\"]]]\n\n    return weather_condition\n\n\ndef render_condition_int(data, query):\n    \"\"\"Weather condition code as integer (i)\"\"\"\n    return data[\"weatherCode\"]\n\n\ndef render_humidity(data, query):\n    \"\"\"\n    humidity (h)\n    \"\"\"\n\n    humidity = data.get(\"humidity\", \"\")\n    if humidity:\n        humidity += \"%\"\n    return humidity\n\n\ndef render_precipitation(data, query):\n    \"\"\"\n    precipitation (p)\n    \"\"\"\n\n    answer = data.get(\"precipMM\", \"\")\n    if answer:\n        answer += \"mm\"\n    return answer\n\n\ndef render_precipitation_chance(data, query):\n    \"\"\"\n    precipitation chance (o)\n    \"\"\"\n\n    answer = data.get(\"chanceofrain\", \"\")\n    if answer:\n        answer += \"%\"\n    return answer\n\n\ndef render_pressure(data, query):\n    \"\"\"\n    pressure (P)\n    \"\"\"\n\n    answer = data.get(\"pressure\", \"\")\n    if answer:\n        answer += \"hPa\"\n    return answer\n\n\ndef render_dewpoint(data, query):\n    \"\"\"\n    dew point (e)\n    \"\"\"\n\n    try:\n        temp_c = float(data[\"temp_C\"])\n        humidity = float(data[\"humidity\"])\n    except (KeyError, ValueError, TypeError):\n        return \"\"\n\n    if not humidity:\n        return \"\"\n\n    dew_point_c = temp_c - (100.0 - humidity) / 5.0\n\n    if query.get(\"use_imperial\", False):\n        dew_point = \"%s°F\" % int(round(dew_point_c * 9.0 / 5 + 32))\n    else:\n        dew_point = \"%s°C\" % int(round(dew_point_c))\n\n    if dew_point[0] != \"-\":\n        dew_point = \"+\" + dew_point\n\n    return dew_point\n\n\ndef render_uv_index(data, query):\n    \"\"\"\n    UV Index (u)\n    \"\"\"\n\n    answer = data.get(\"uvIndex\", \"\")\n    return answer\n\n\ndef render_wind(data, query):\n    \"\"\"\n    wind (w)\n    \"\"\"\n\n    try:\n        degree = data[\"winddirDegree\"]\n    except KeyError:\n        degree = \"\"\n\n    try:\n        degree = int(degree)\n    except ValueError:\n        degree = \"\"\n\n    if degree:\n        if query.get(\"view\") in [\"v2n\", \"v2d\"]:\n            wind_direction = WIND_DIRECTION_WI[int(((degree + 22.5) % 360) / 45.0)]\n        else:\n            wind_direction = WIND_DIRECTION[int(((degree + 22.5) % 360) / 45.0)]\n    else:\n        wind_direction = \"\"\n\n    if query.get(\"use_ms_for_wind\", False):\n        unit = \"m/s\"\n        wind = \"%s%.1f%s\" % (\n            wind_direction,\n            float(data[\"windspeedKmph\"]) / 36.0 * 10.0,\n            unit,\n        )\n    elif query.get(\"use_imperial\", False):\n        unit = \"mph\"\n        wind = \"%s%s%s\" % (wind_direction, data[\"windspeedMiles\"], unit)\n    else:\n        unit = \"km/h\"\n        wind = \"%s%s%s\" % (wind_direction, data[\"windspeedKmph\"], unit)\n\n    return wind\n\n\ndef render_location(data, query):\n    \"\"\"\n    location (l)\n    \"\"\"\n\n    return data[\"override_location\"] or data[\"location\"]\n\n\ndef render_moonphase(_, query):\n    \"\"\"moonpahse(m)\n    A symbol describing the phase of the moon\n    \"\"\"\n    moon_phase = moon.phase(date=datetime.datetime.today())\n    moon_index = int(int(32.0 * moon_phase / 28 + 2) % 32 / 4)\n    return MOON_PHASES[moon_index]\n\n\ndef render_moonday(_, query):\n    \"\"\"moonday(M)\n    An number describing the phase of the moon (days after the New Moon)\n    \"\"\"\n    moon_phase = moon.phase(date=datetime.datetime.today())\n    return str(int(moon_phase))\n\n\n##################################\n# this part should be rewritten\n# this is just a temporary solution\n\n\ndef get_geodata(location):\n    # text = requests.get(\"http://localhost:8004/%s\" % location).text\n    text = requests.get(\n        \"http://127.0.0.1:8085/:geo-location?location=%s\" % location\n    ).text\n    return json.loads(text)\n\n\ndef render_dawn(data, query, local_time_of):\n    \"\"\"dawn (D)\n    Local time of dawn\"\"\"\n    return local_time_of(\"dawn\")\n\n\ndef render_dusk(data, query, local_time_of):\n    \"\"\"dusk (d)\n    Local time of dusk\"\"\"\n    return local_time_of(\"dusk\")\n\n\ndef render_sunrise(data, query, local_time_of):\n    \"\"\"sunrise (S)\n    Local time of sunrise\"\"\"\n    return local_time_of(\"sunrise\")\n\n\ndef render_sunset(data, query, local_time_of):\n    \"\"\"sunset (s)\n    Local time of sunset\"\"\"\n    return local_time_of(\"sunset\")\n\n\ndef render_zenith(data, query, local_time_of):\n    \"\"\"zenith (z)\n    Local time of zenith\"\"\"\n    return local_time_of(\"noon\")\n\n\ndef render_local_time(data, query, local_time_of):\n    \"\"\"local_time (T)\n    Local time\"\"\"\n    return \"%{{NOW(\" + local_time_of(\"TZ\") + \")}}\"\n\n\ndef render_local_timezone(data, query, local_time_of):\n    \"\"\"local_time (Z)\n    Local time\"\"\"\n    return local_time_of(\"TZ\")\n\n\n##################################\n\nFORMAT_SYMBOL = {\n    \"c\": render_condition,\n    \"C\": render_condition_fullname,\n    \"x\": render_condition_plain,\n    \"i\": render_condition_int,\n    \"h\": render_humidity,\n    \"t\": render_temperature,\n    \"f\": render_feel_like_temperature,\n    \"w\": render_wind,\n    \"l\": render_location,\n    \"m\": render_moonphase,\n    \"M\": render_moonday,\n    \"p\": render_precipitation,\n    \"o\": render_precipitation_chance,\n    \"P\": render_pressure,\n    \"e\": render_dewpoint,\n    \"u\": render_uv_index,\n}\n\nFORMAT_SYMBOL_ASTRO = {\n    \"D\": render_dawn,\n    \"d\": render_dusk,\n    \"S\": render_sunrise,\n    \"s\": render_sunset,\n    \"z\": render_zenith,\n    \"T\": render_local_time,\n    \"Z\": render_local_timezone,\n}\n\n\ndef render_line(line, data, query):\n    \"\"\"\n    Render format `line` using `data`\n    \"\"\"\n\n    def get_local_time_of():\n\n        location = data[\"location\"]\n        geo_data = get_geodata(location)\n\n        city = LocationInfo()\n        city.latitude = geo_data[\"latitude\"]\n        city.longitude = geo_data[\"longitude\"]\n        city.timezone = geo_data[\"timezone\"]\n\n        timezone = city.timezone\n\n        local_tz = pytz.timezone(timezone)\n\n        datetime_day_start = datetime.datetime.now().replace(\n            hour=0, minute=0, second=0, microsecond=0\n        )\n        current_sun = sun(city.observer, date=datetime_day_start)\n\n        local_time_of = (\n            lambda x: city.timezone\n            if x == \"TZ\"\n            else current_sun[x]\n            .replace(tzinfo=pytz.utc)\n            .astimezone(local_tz)\n            .strftime(\"%H:%M:%S\")\n        )\n        return local_time_of\n\n    def render_symbol(match):\n        \"\"\"\n        Render one format symbol from re `match`\n        using `data` from external scope.\n        \"\"\"\n\n        symbol_string = match.group(0)\n        symbol = symbol_string[-1]\n\n        if symbol in FORMAT_SYMBOL:\n            render_function = FORMAT_SYMBOL[symbol]\n            return render_function(data, query)\n        if symbol in FORMAT_SYMBOL_ASTRO and local_time_of is not None:\n            render_function = FORMAT_SYMBOL_ASTRO[symbol]\n            return render_function(data, query, local_time_of)\n\n        return \"\"\n\n    template_regexp = r\"%[a-zA-Z]\"\n    for template_code in re.findall(template_regexp, line):\n        if template_code.lstrip(\"%\") in FORMAT_SYMBOL_ASTRO:\n            local_time_of = get_local_time_of()\n            break\n\n    return re.sub(template_regexp, render_symbol, line)\n\n\ndef render_json(data):\n    output = json.dumps(data, indent=4, sort_keys=True, ensure_ascii=False)\n\n    output = (\n        \"\\n\".join(\n            re.sub('\"[^\"]*worldweatheronline[^\"]*\"', '\"\"', line)\n            if \"worldweatheronline\" in line\n            else line\n            for line in output.splitlines()\n        )\n        + \"\\n\"\n    )\n\n    return output\n\n\ndef format_weather_data(query, parsed_query, data):\n    \"\"\"\n    Format information about current weather `data` for `location`\n    with specified in `format_line` format\n    \"\"\"\n\n    if \"data\" not in data:\n        return \"Unknown location; please try ~%s\" % parsed_query[\"location\"]\n\n    format_line = parsed_query.get(\"view\", \"\")\n    if format_line in PRECONFIGURED_FORMAT:\n        format_line = PRECONFIGURED_FORMAT[format_line]\n\n    if format_line in [\"j1\", \"j2\"]:\n        # j2 is a lightweight j1, without 'hourly' in 'weather' (weather forecast)\n        if \"weather\" in data[\"data\"] and format_line == \"j2\":\n            for i in range(len(data[\"data\"][\"weather\"])):\n                del data[\"data\"][\"weather\"][i][\"hourly\"]\n        return render_json(data[\"data\"])\n    if format_line == \"p1\":\n        return prometheus.render_prometheus(data[\"data\"])\n    if format_line[:2] == \"v2\":\n        return v2.main(query, parsed_query, data)\n    # if format_line[:2] == \"v3\":\n    #     return v3.main(query, parsed_query, data)\n\n    current_condition = data[\"data\"][\"current_condition\"][0]\n    current_condition[\"location\"] = parsed_query[\"location\"]\n    current_condition[\"override_location\"] = parsed_query[\"override_location_name\"]\n    output = render_line(format_line, current_condition, query)\n    output = output.rstrip(\"\\n\").replace(r\"\\n\", \"\\n\")\n    return output\n\n\ndef wttr_line(query, parsed_query):\n    \"\"\"\n    Return 1line weather information for `location`\n    in format `line_format`\n    \"\"\"\n    location = parsed_query[\"location\"]\n    lang = parsed_query[\"lang\"]\n\n    data = get_weather_data(location, lang)\n    output = format_weather_data(query, parsed_query, data)\n    return output\n\n\ndef main():\n    \"\"\"\n    Function for standalone module usage\n    \"\"\"\n\n    location = sys.argv[1]\n    query = {\n        \"line\": sys.argv[2],\n    }\n    parsed_query = {\n        \"location\": location,\n        \"orig_location\": location,\n        \"language\": \"en\",\n        \"format\": \"v2\",\n    }\n\n    sys.stdout.write(wttr_line(query, parsed_query))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "lib/view/moon.py",
    "content": "import sys\n\nimport os\nimport dateutil.parser\n\nfrom gevent.subprocess import Popen, PIPE\n\nsys.path.insert(0, \"..\")\nimport constants\nimport parse_query\nimport globals\n\n\ndef get_moon(parsed_query):\n\n    location = parsed_query[\"orig_location\"]\n    html = parsed_query[\"html_output\"]\n    lang = parsed_query[\"lang\"]\n    hemisphere = parsed_query[\"hemisphere\"]\n\n    date = None\n    if \"@\" in location:\n        date = location[location.index(\"@\") + 1 :]\n        location = location[: location.index(\"@\")]\n\n    cmd = [globals.PYPHOON]\n    if lang:\n        cmd += [\"-l\", lang]\n\n    if not hemisphere:\n        cmd += [\"-s\", \"south\"]\n\n    if date:\n        try:\n            dateutil.parser.parse(date)\n        except Exception as e:\n            print(\"ERROR: %s\" % e)\n        else:\n            cmd += [date]\n\n    p = Popen(cmd, stdout=PIPE, stderr=PIPE)\n    stdout = p.communicate()[0]\n    stdout = stdout.decode(\"utf-8\")\n\n    if parsed_query.get(\"no-terminal\", False):\n        stdout = globals.remove_ansi(stdout)\n\n    if parsed_query.get(\"dumb\", False):\n        stdout = stdout.translate(globals.TRANSLATION_TABLE)\n\n    if html:\n        p = Popen(\n            [\"bash\", globals.ANSI2HTML, \"--palette=solarized\", \"--bg=dark\"],\n            stdin=PIPE,\n            stdout=PIPE,\n            stderr=PIPE,\n        )\n        stdout, stderr = p.communicate(stdout.encode(\"utf-8\"))\n        stdout = stdout.decode(\"utf-8\")\n        stderr = stderr.decode(\"utf-8\")\n        if p.returncode != 0:\n            globals.error(stdout + stderr)\n\n    return stdout\n"
  },
  {
    "path": "lib/view/prometheus.py",
    "content": "\"\"\"\nRendering weather data in the Prometheus format.\n\n\"\"\"\n\nfrom datetime import datetime\n\nfrom fields import DESCRIPTION\n\n\ndef _render_current(data, for_day=\"current\", already_seen=[]):\n    \"Converts data into prometheus style format\"\n\n    output = []\n\n    for field_name, val in DESCRIPTION.items():\n\n        help, name = val\n\n        try:\n            value = data[field_name]\n            if field_name == \"weatherDesc\":\n                value = value[0][\"value\"]\n        except (IndexError, KeyError):\n            try:\n                value = data[\"astronomy\"][0][field_name]\n                if value.endswith(\" AM\") or value.endswith(\" PM\"):\n                    value = _convert_time_to_minutes(value)\n            except (IndexError, KeyError, ValueError):\n                continue\n\n        try:\n            if name == \"observation_time\":\n                value = _convert_time_to_minutes(value)\n        except ValueError:\n            continue\n\n        description = \"\"\n        try:\n            float(value)\n        except ValueError:\n            description = f', description=\"{value}\"'\n            value = \"1\"\n\n        if name not in already_seen:\n            output.append(f\"# HELP {name} {help}\")\n            already_seen.append(name)\n\n        output.append(f'{name}{{forecast=\"{for_day}\"{description}}} {value}')\n\n    return \"\\n\".join(output) + \"\\n\"\n\n\ndef _convert_time_to_minutes(time_str):\n    \"Convert time from midnight to minutes\"\n    return (\n        int(\n            (\n                datetime.strptime(time_str, \"%I:%M %p\")\n                - datetime.strptime(\"12:00 AM\", \"%I:%M %p\")\n            ).total_seconds()\n        )\n        // 60\n    )\n\n\ndef render_prometheus(data):\n    \"\"\"\n    Convert `data` into Prometheus format\n    and return it as string.\n    \"\"\"\n\n    already_seen = []\n    answer = _render_current(data[\"current_condition\"][0], already_seen=already_seen)\n    for i in range(3):\n        answer += _render_current(\n            data[\"weather\"][i], for_day=\"%sd\" % i, already_seen=already_seen\n        )\n    return answer\n"
  },
  {
    "path": "lib/view/v2.py",
    "content": "# vim: fileencoding=utf-8\n# vim: foldmethod=marker foldenable:\n\n\"\"\"\n[X] emoji\n[ ] wego icon\n[ ] v2.wttr.in\n[X] astronomical (sunset)\n[X] time\n[X] frames\n[X] colorize rain data\n[ ] date + locales\n[X] wind color\n[ ] highlight current date\n[ ] bind to real site\n[ ] max values: temperature\n[X] max value: rain\n[ ] comment github\n[ ] commit\n\n\"\"\"\n\nimport sys\n\nimport re\nimport math\nimport json\nimport datetime\nimport io\n\nimport requests\nimport diagram\nimport pyjq\nimport pytz\nimport numpy as np\nfrom astral import LocationInfo\nfrom astral import moon, sun\nfrom scipy.interpolate import interp1d\nfrom babel.dates import format_datetime\n\nfrom globals import WWO_KEY, TRANSLATION_TABLE, remove_ansi\nimport constants\nimport translations\nimport parse_query\nfrom . import line as wttr_line\n\nif not sys.version_info >= (3, 0):\n    reload(sys)  # noqa: F821\n    sys.setdefaultencoding(\"utf-8\")\n\n# data processing {{{\n\n\ndef get_data(config):\n    \"\"\"\n    Fetch data for `query_string`\n    \"\"\"\n\n    url = (\n        \"http://\"\n        \"localhost:5001/premium/v1/weather.ashx\"\n        \"?key=%s\"\n        \"&q=%s&format=json&num_of_days=3&tp=3&lang=None\"\n    ) % (WWO_KEY, config[\"location\"])\n    text = requests.get(url).text\n    parsed_data = json.loads(text)\n    return parsed_data\n\n\ndef interpolate_data(input_data, max_width):\n    \"\"\"\n    Resample `input_data` to number of `max_width` counts\n    \"\"\"\n\n    input_data = list(input_data)\n    input_data_len = len(input_data)\n    x = list(range(input_data_len))\n    y = input_data\n    xvals = np.linspace(0, input_data_len - 1, max_width)\n    yinterp = interp1d(x, y, kind=\"cubic\")\n    return yinterp(xvals)\n\n\ndef jq_query(query, data_parsed):\n    \"\"\"\n    Apply `query` to structued data `data_parsed`\n    \"\"\"\n\n    pyjq_data = pyjq.all(query, data_parsed)\n    data = list(map(float, pyjq_data))\n    return data\n\n\n# }}}\n# utils {{{\ndef colorize(string, color_code, html_output=False):\n    if html_output:\n        return \"<font color='#777777'>%s</font>\" % (string)\n    else:\n        return \"\\033[%sm%s\\033[0m\" % (color_code, string)\n\n\n# }}}\n# draw_spark {{{\n\n\ndef draw_spark(data, height, width, color_data):\n    \"\"\"\n    Spark-style visualize `data` in a region `height` x `width`\n    \"\"\"\n\n    _BARS = \" _▁▂▃▄▅▇█\"\n\n    def _box(height, row, value, max_value):\n        row_height = 1.0 * max_value / height\n        if row_height * row >= value:\n            return _BARS[0]\n        if row_height * (row + 1) <= value:\n            return _BARS[-1]\n\n        return _BARS[\n            int(1.0 * (value - row_height * row) / (row_height * 1.0) * len(_BARS))\n        ]\n\n    max_value = max(data)\n\n    output = \"\"\n    color_code = 20\n    for i in range(height):\n        for j in range(width):\n            character = _box(height, height - i - 1, data[j], max_value)\n            if data[j] != 0:\n                chance_of_rain = color_data[j] / 100.0 * 2\n                if chance_of_rain > 1:\n                    chance_of_rain = 1\n                color_index = int(5 * chance_of_rain)\n                color_code = (\n                    16 + color_index\n                )  # int(math.floor((20-16) * 1.0 * (height-1-i)/height*(max_value/data[j])))\n            output += \"\\033[38;5;%sm%s\\033[0m\" % (color_code, character)\n        output += \"\\n\"\n\n    # labeling max value\n    if max_value == 0:\n        max_line = \" \" * width\n    else:\n        max_line = \"\"\n        for j in range(width):\n            if data[j] == max_value:\n                max_line = \"%3.2fmm|%s%%\" % (max_value, int(color_data[j]))\n                orig_max_line = max_line\n\n                # aligning it\n                if len(max_line) // 2 < j and len(max_line) // 2 + j < width:\n                    spaces = \" \" * (j - len(max_line) // 2)\n                    max_line = spaces + max_line  # + spaces\n                    max_line = max_line + \" \" * (width - len(max_line))\n                elif len(max_line) // 2 + j >= width:\n                    max_line = \" \" * (width - len(max_line)) + max_line\n\n                max_line = max_line.replace(\n                    orig_max_line, colorize(orig_max_line, \"38;5;33\")\n                )\n\n                break\n\n    if max_line:\n        output = \"\\n\" + max_line + \"\\n\" + output + \"\\n\"\n\n    return output\n\n\n# }}}\n# draw_diagram {{{\ndef draw_diagram(data, height, width):\n\n    option = diagram.DOption()\n    option.size = diagram.Point([width, height])\n    option.mode = \"g\"\n\n    stream = io.BytesIO()\n    gram = diagram.DGWrapper(\n        data=[list(data), range(len(data))], dg_option=option, ostream=stream\n    )\n    gram.show()\n    return stream.getvalue().decode(\"utf-8\")\n\n\n# }}}\n# draw_date {{{\n\n\ndef draw_date(config, geo_data):\n    \"\"\" \"\"\"\n\n    tzinfo = pytz.timezone(geo_data[\"timezone\"])\n\n    locale = config.get(\"locale\", \"en_US\")\n    datetime_day_start = datetime.datetime.utcnow()\n\n    answer = \"\"\n    for day in range(3):\n        datetime_ = datetime_day_start + datetime.timedelta(hours=24 * day)\n        date = format_datetime(datetime_, \"EEE dd MMM\", locale=locale, tzinfo=tzinfo)\n\n        spaces = ((24 - len(date)) // 2) * \" \"\n        date = spaces + date + spaces\n        date = \" \" * (24 - len(date)) + date\n        answer += date\n    answer += \"\\n\"\n\n    for _ in range(3):\n        answer += \" \" * 23 + \"╷\"\n    return answer[:-1] + \" \"\n\n\n# }}}\n# draw_time {{{\n\n\ndef draw_time(geo_data):\n    \"\"\" \"\"\"\n\n    tzinfo = pytz.timezone(geo_data[\"timezone\"])\n\n    line = [\"\", \"\"]\n\n    for _ in range(3):\n        part = \"─\" * 5 + \"┴\" + \"─\" * 5\n        line[0] += part + \"┼\" + part + \"╂\"\n    line[0] += \"\\n\"\n\n    for _ in range(3):\n        line[1] += \"     6    12    18      \"\n    line[1] += \"\\n\"\n\n    # highlight current time\n    hour_number = (\n        datetime.datetime.now(tzinfo)\n        - datetime.datetime.now(tzinfo).replace(\n            hour=0, minute=0, second=0, microsecond=0\n        )\n    ).seconds // 3600\n\n    for line_number, _ in enumerate(line):\n        line[line_number] = (\n            line[line_number][:hour_number]\n            + colorize(line[line_number][hour_number], \"46\")\n            + line[line_number][hour_number + 1 :]\n        )\n\n    return \"\".join(line)\n\n\n# }}}\n# draw_astronomical {{{\ndef draw_astronomical(city_name, geo_data, config):\n    datetime_day_start = datetime.datetime.now().replace(\n        hour=0, minute=0, second=0, microsecond=0\n    )\n\n    city = LocationInfo()\n    city.latitude = geo_data[\"latitude\"]\n    city.longitude = geo_data[\"longitude\"]\n    city.timezone = geo_data[\"timezone\"]\n\n    answer = \"\"\n    moon_line = \"\"\n    for time_interval in range(72):\n\n        current_date = (\n            datetime_day_start + datetime.timedelta(hours=1 * time_interval)\n        ).replace(tzinfo=pytz.timezone(geo_data[\"timezone\"]))\n\n        try:\n            dawn = sun.dawn(city.observer, date=current_date)\n        except ValueError:\n            dawn = current_date\n\n        try:\n            dusk = sun.dusk(city.observer, date=current_date)\n        except ValueError:\n            dusk = current_date + datetime.timedelta(hours=24)\n\n        try:\n            sunrise = sun.sunrise(city.observer, date=current_date)\n        except ValueError:\n            sunrise = current_date\n\n        try:\n            sunset = sun.sunset(city.observer, date=current_date)\n        except ValueError:\n            sunset = current_date + datetime.timedelta(hours=24)\n\n        char = \".\"\n        if current_date < dawn:\n            char = \" \"\n        elif current_date > dusk:\n            char = \" \"\n        elif dawn <= current_date and current_date <= sunrise:\n            char = \"─\"\n        elif sunset <= current_date and current_date <= dusk:\n            char = \"─\"\n        elif sunrise <= current_date and current_date <= sunset:\n            char = \"━\"\n\n        answer += char\n\n        if config.get(\"view\") in [\"v2n\", \"v2d\"]:\n            moon_phases = constants.MOON_PHASES_WI\n            moon_phases = [\" %s\" % x for x in moon_phases]\n        else:\n            moon_phases = constants.MOON_PHASES\n\n        # moon\n        if time_interval in [0, 23, 47, 69]:  # time_interval % 3 == 0:\n            moon_phase = moon.phase(\n                date=datetime_day_start + datetime.timedelta(hours=time_interval)\n            )\n            moon_phase_emoji = moon_phases[\n                int(math.floor(moon_phase * 1.0 / 28.0 * 8 + 0.5)) % len(moon_phases)\n            ]\n            #    if time_interval in [0, 24, 48, 69]:\n            moon_line += moon_phase_emoji  # + \" \"\n        elif time_interval % 3 == 0:\n            if time_interval not in [24, 28]:  # se:\n                moon_line += \"   \"\n            else:\n                moon_line += \" \"\n\n    answer = moon_line + \"\\n\" + answer + \"\\n\"\n    answer += \"\\n\"\n    return answer\n\n\n# }}}\n# draw_emoji {{{\ndef draw_emoji(data, config):\n    answer = \"\"\n    if config.get(\"view\") == \"v2n\":\n        weather_symbol = constants.WEATHER_SYMBOL_WI_NIGHT\n        weather_symbol_width_vte = constants.WEATHER_SYMBOL_WIDTH_VTE_WI\n    elif config.get(\"view\") == \"v2d\":\n        weather_symbol = constants.WEATHER_SYMBOL_WI_DAY\n        weather_symbol_width_vte = constants.WEATHER_SYMBOL_WIDTH_VTE_WI\n    else:\n        weather_symbol = constants.WEATHER_SYMBOL\n        weather_symbol_width_vte = constants.WEATHER_SYMBOL_WIDTH_VTE\n\n    for i in data:\n        emoji = weather_symbol.get(constants.WWO_CODE.get(str(int(i)), \"Unknown\"))\n        space = \" \" * (3 - weather_symbol_width_vte.get(emoji, 1))\n        answer += space[:1] + emoji + space[1:]\n    answer += \"\\n\"\n    return answer\n\n\n# }}}\n# draw_wind {{{\ndef draw_wind(data, color_data, config):\n    def _color_code_for_wind_speed(wind_speed):\n\n        color_codes = [\n            (3, 241),  # 82\n            (6, 242),  # 118\n            (9, 243),  # 154\n            (12, 246),  # 190\n            (15, 250),  # 226\n            (19, 253),  # 220\n            (23, 214),\n            (27, 208),\n            (31, 202),\n            (-1, 196),\n        ]\n\n        for this_wind_speed, this_color_code in color_codes:\n            if wind_speed <= this_wind_speed:\n                return this_color_code\n        return color_codes[-1][1]\n\n    answer = \"\"\n    answer_line2 = \"\"\n\n    if config.get(\"view\") in [\"v2n\", \"v2d\"]:\n        wind_direction_list = constants.WIND_DIRECTION_WI\n    else:\n        wind_direction_list = constants.WIND_DIRECTION\n\n    for j, degree in enumerate(data):\n\n        degree = int(degree)\n        if degree:\n            wind_direction = wind_direction_list[int(((degree + 22.5) % 360) / 45.0)]\n        else:\n            wind_direction = \"\"\n\n        color_code = \"38;5;%s\" % _color_code_for_wind_speed(int(color_data[j]))\n        answer += \" %s \" % colorize(wind_direction, color_code)\n\n        # wind_speed\n        wind_speed = int(color_data[j])\n        wind_speed_str = colorize(str(wind_speed), color_code)\n        if wind_speed < 10:\n            wind_speed_str = \" \" + wind_speed_str + \" \"\n        elif wind_speed < 100:\n            wind_speed_str = \" \" + wind_speed_str\n        answer_line2 += wind_speed_str\n\n    answer += \"\\n\"\n    answer += answer_line2 + \"\\n\"\n    return answer\n\n\n# }}}\n# panel implementation {{{\n\n\ndef add_frame(output, width, config):\n    \"\"\"\n    Add frame arond `output` that has width `width`\n    \"\"\"\n\n    empty_line = \" \" * width\n    output = (\n        \"\\n\".join(\"│\" + (x or empty_line) + \"│\" for x in output.splitlines()) + \"\\n\"\n    )\n\n    weather_report = (\n        translations.CAPTION[config.get(\"lang\") or \"en\"]\n        + \" \"\n        + (config[\"override_location_name\"] or config[\"location\"])\n    )\n\n    caption = \"┤ \" + \" \" + weather_report + \" \" + \" ├\"\n    output = (\n        \"┌\"\n        + caption\n        + \"─\" * (width - len(caption))\n        + \"┐\\n\"\n        + output\n        + \"└\"\n        + \"─\" * width\n        + \"┘\\n\"\n    )\n\n    return output\n\n\ndef generate_panel(data_parsed, geo_data, config):\n    \"\"\" \"\"\"\n\n    max_width = 72\n\n    if config.get(\"use_imperial\"):\n        feels_like_query = \"[.data.weather[] | .hourly[]] | .[].FeelsLikeF\"\n        temp_query = \"[.data.weather[] | .hourly[]] | .[].tempF\"\n        wind_speed_query = \"[.data.weather[] | .hourly[]] | .[].windspeedMiles\"\n    else:\n        feels_like_query = \"[.data.weather[] | .hourly[]] | .[].FeelsLikeC\"\n        temp_query = \"[.data.weather[] | .hourly[]] | .[].tempC\"\n        wind_speed_query = \"[.data.weather[] | .hourly[]] | .[].windspeedKmph\"\n\n    precip_mm_query = \"[.data.weather[] | .hourly[]] | .[].precipMM\"\n    precip_chance_query = \"[.data.weather[] | .hourly[]] | .[].chanceofrain\"\n    weather_code_query = \"[.data.weather[] | .hourly[]] | .[].weatherCode\"\n    wind_direction_query = \"[.data.weather[] | .hourly[]] | .[].winddirDegree\"\n\n    output = \"\"\n\n    output += \"\\n\\n\"\n\n    output += draw_date(config, geo_data)\n    output += \"\\n\"\n    output += \"\\n\"\n    output += \"\\n\"\n\n    # data = jq_query(feels_like_query, data_parsed)\n    data = jq_query(temp_query, data_parsed)\n    data_interpolated = interpolate_data(data, max_width)\n    output += draw_diagram(data_interpolated, 10, max_width)\n\n    output += \"\\n\"\n\n    output += draw_time(geo_data)\n\n    data = jq_query(precip_mm_query, data_parsed)\n    color_data = jq_query(precip_chance_query, data_parsed)\n    data_interpolated = interpolate_data(data, max_width)\n    color_data_interpolated = interpolate_data(color_data, max_width)\n    output += draw_spark(data_interpolated, 5, max_width, color_data_interpolated)\n    output += \"\\n\"\n\n    data = jq_query(weather_code_query, data_parsed)\n    output += draw_emoji(data, config)\n\n    data = jq_query(wind_direction_query, data_parsed)\n    color_data = jq_query(wind_speed_query, data_parsed)\n    output += draw_wind(data, color_data, config)\n    output += \"\\n\"\n\n    output += draw_astronomical(config[\"location\"], geo_data, config)\n    output += \"\\n\"\n\n    output = add_frame(output, max_width, config)\n    return output\n\n\n# }}}\n# textual information {{{\ndef textual_information(data_parsed, geo_data, config, html_output=False):\n    \"\"\"\n    Add textual information about current weather and\n    astronomical conditions\n    \"\"\"\n\n    def _shorten_full_location(full_location, city_only=False):\n        def _count_runes(string):\n            return len(string.encode(\"utf-16-le\")) // 2\n\n        words = full_location.split(\",\")\n\n        output = words[0]\n        if city_only:\n            return output\n\n        for word in words[1:]:\n            if _count_runes(output + \",\" + word) > 50:\n                return output\n            output += \",\" + word\n\n        return output\n\n    def _colorize(text, color):\n        return colorize(text, color, html_output=html_output)\n\n    city = LocationInfo()\n    city.latitude = geo_data[\"latitude\"]\n    city.longitude = geo_data[\"longitude\"]\n    city.timezone = geo_data[\"timezone\"]\n\n    output = []\n    timezone = city.timezone\n\n    datetime_day_start = datetime.datetime.now().replace(\n        hour=0, minute=0, second=0, microsecond=0\n    )\n\n    format_line = \"%c %C, %t, %h, %w, %P\"\n    current_condition = data_parsed[\"data\"][\"current_condition\"][0]\n    query = config\n    weather_line = wttr_line.render_line(format_line, current_condition, query)\n    output.append(\"Weather: %s\" % weather_line)\n\n    output.append(\"Timezone: %s\" % timezone)\n\n    local_tz = pytz.timezone(timezone)\n\n    def _get_local_time_of(what):\n        _sun = {\n            \"dawn\": sun.dawn,\n            \"sunrise\": sun.sunrise,\n            \"noon\": sun.noon,\n            \"sunset\": sun.sunset,\n            \"dusk\": sun.dusk,\n        }[what]\n\n        current_time_of_what = _sun(city.observer, date=datetime_day_start)\n        return (\n            current_time_of_what.replace(tzinfo=pytz.utc)\n            .astimezone(local_tz)\n            .strftime(\"%H:%M:%S\")\n        )\n\n    local_time_of = {}\n    for what in [\"dawn\", \"sunrise\", \"noon\", \"sunset\", \"dusk\"]:\n        try:\n            local_time_of[what] = _get_local_time_of(what)\n        except ValueError:\n            local_time_of[what] = \"-\" * 8\n\n    tmp_output = []\n\n    tmp_output.append(\"  Now:    %%{{NOW(%s)}}\" % timezone)\n    tmp_output.append(\"Dawn:    %s\" % local_time_of[\"dawn\"])\n    tmp_output.append(\"Sunrise: %s\" % local_time_of[\"sunrise\"])\n    tmp_output.append(\"  Zenith: %s     \" % local_time_of[\"noon\"])\n    tmp_output.append(\"Sunset:  %s\" % local_time_of[\"sunset\"])\n    tmp_output.append(\"Dusk:    %s\" % local_time_of[\"dusk\"])\n\n    tmp_output = [\n        re.sub(\"^([A-Za-z]*:)\", lambda m: _colorize(m.group(1), \"2\"), x)\n        for x in tmp_output\n    ]\n\n    output.append(\n        \"%20s\" % tmp_output[0] + \" | %20s \" % tmp_output[1] + \" | %20s\" % tmp_output[2]\n    )\n    output.append(\n        \"%20s\" % tmp_output[3] + \" | %20s \" % tmp_output[4] + \" | %20s\" % tmp_output[5]\n    )\n\n    city_only = False\n    suffix = \"\"\n    if \"Simferopol\" in timezone:\n        city_only = True\n        suffix = \", Крым\"\n\n    latitude = float(geo_data[\"latitude\"])\n    longitude = float(geo_data[\"longitude\"])\n\n    if config[\"full_address\"]:\n        output.append(\n            \"Location: %s%s [%5.4f,%5.4f]\"\n            % (\n                _shorten_full_location(config[\"full_address\"], city_only=city_only),\n                suffix,\n                latitude,\n                longitude,\n            )\n        )\n\n    output = [\n        re.sub(\n            \"^( *[A-Za-z]*:)\",\n            lambda m: _colorize(m.group(1), \"2\"),\n            re.sub(\n                \"^( +[A-Za-z]*:)\",\n                lambda m: _colorize(m.group(1), \"2\"),\n                re.sub(r\"(\\|)\", lambda m: _colorize(m.group(1), \"2\"), x),\n            ),\n        )\n        for x in output\n    ]\n\n    return \"\".join(\"%s\\n\" % x for x in output)\n\n\n# }}}\n# get_geodata {{{\ndef get_geodata(location):\n    text = requests.get(\n        \"http://127.0.0.1:8085/:geo-location?location=%s\" % location\n    ).text\n    return json.loads(text)\n\n\n# }}}\n\n\ndef main(query, parsed_query, data):\n    parsed_query[\"locale\"] = \"en_US\"\n\n    location = parsed_query[\"location\"]\n    html_output = parsed_query[\"html_output\"]\n\n    geo_data = get_geodata(location)\n    if data is None:\n        data_parsed = get_data(parsed_query)\n    else:\n        data_parsed = data\n\n    if html_output:\n        parsed_query[\"text\"] = \"no\"\n        filename = \"b_\" + parse_query.serialize(parsed_query) + \".png\"\n        output = \"\"\"\n<html>\n<head>\n<title>Weather report for {orig_location}</title>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"/files/style.css\" />\n</head>\n<body>\n  <img src=\"/{filename}\" width=\"592\" height=\"532\"/>\n<pre>\n{textual_information}\n</pre>\n</body>\n</html>\n\"\"\".format(\n            filename=filename,\n            orig_location=parsed_query[\"orig_location\"],\n            textual_information=textual_information(\n                data_parsed, geo_data, parsed_query, html_output=True\n            ),\n        )\n    else:\n        output = generate_panel(data_parsed, geo_data, parsed_query)\n        if query.get(\"text\") != \"no\" and parsed_query.get(\"text\") != \"no\":\n            output += textual_information(data_parsed, geo_data, parsed_query)\n        if parsed_query.get(\"no-terminal\", False):\n            output = remove_ansi(output)\n        if parsed_query.get(\"dumb\", False):\n            output = output.translate(TRANSLATION_TABLE)\n    return output\n\n\nif __name__ == \"__main__\":\n    sys.stdout.write(main(sys.argv[1]))\n"
  },
  {
    "path": "lib/view/wttr.py",
    "content": "# vim: set encoding=utf-8\n# pylint: disable=wrong-import-position\n\n\"\"\"\nMain view (wttr.in) implementation.\nThe module is a wrapper for the modified Wego program.\n\"\"\"\n\nimport sys\nimport re\n\nfrom gevent.subprocess import Popen, PIPE\n\nsys.path.insert(0, \"..\")\nfrom translations import get_message, SUPPORTED_LANGS\nfrom globals import (\n    WEGO,\n    TRANSLATION_TABLE,\n    NOT_FOUND_LOCATION,\n    DEFAULT_LOCATION,\n    ANSI2HTML,\n    error,\n    remove_ansi,\n)\n\n\ndef get_wetter(parsed_query):\n\n    location = parsed_query[\"location\"]\n    html = parsed_query[\"html_output\"]\n    lang = parsed_query[\"lang\"]\n\n    location_not_found = False\n    if location == NOT_FOUND_LOCATION:\n        location_not_found = True\n\n    stderr = \"\"\n    returncode = 0\n    if not location_not_found:\n        stdout, stderr, returncode = _wego_wrapper(location, parsed_query)\n        first_line, stdout = _wego_postprocessing(location, parsed_query, stdout)\n\n    if location_not_found or (\n        returncode != 0\n        and (\n            \"Unable to find any matching weather\"\n            \" location to the parsed_query submitted\"\n        )\n        in stderr\n    ):\n        stdout, stderr, returncode = _wego_wrapper(DEFAULT_LOCATION, parsed_query)\n        location_not_found = True\n\n        not_found_header = \"\"\"\n>>>    _  _    ___  _  _     \n>>>   | || |  / _ \\| || |      \n>>>   | || |_| | | | || |_      \n>>>   |__   _| |_| |__   _|      \n>>>      |_|  \\___/   |_|    \n>>>                       \n>>>   404 %s: %s\n>>>                 \n\"\"\" % (\n            get_message(\"UNKNOWN_LOCATION\", lang).upper(),\n            parsed_query[\"override_location_name\"],\n        )\n\n        not_found_header = \"\\n\".join(\n            \"\\033[48;5;91m\" + x + \"   \\033[0m\"\n            for x in not_found_header.splitlines()[1:]\n        )\n\n        not_found_footer = get_message(\"NOT_FOUND_MESSAGE\", lang)\n        not_found_footer = (\n            \"\\n\".join(\n                \"\\033[48;5;91m \" + x + \" \\033[0m\"\n                for x in not_found_footer.splitlines()\n                if x\n            )\n            + \"\\n\"\n        )\n\n        first_line, stdout = _wego_postprocessing(location, parsed_query, stdout)\n        stdout = not_found_header + \"\\n----\\n\" + stdout + not_found_footer\n\n    if html:\n        return _htmlize(stdout, first_line, parsed_query)\n    return stdout\n\n\ndef _wego_wrapper(location, parsed_query):\n\n    lang = parsed_query[\"lang\"]\n    if location == DEFAULT_LOCATION:\n        location_name = DEFAULT_LOCATION.capitalize()\n    else:\n        location_name = parsed_query[\"override_location_name\"]\n\n    cmd = [WEGO, \"--city=%s\" % location]\n\n    if parsed_query.get(\"inverted_colors\"):\n        cmd += [\"-inverse\"]\n\n    if parsed_query.get(\"use_ms_for_wind\"):\n        cmd += [\"-wind_in_ms\"]\n\n    if parsed_query.get(\"narrow\"):\n        cmd += [\"-narrow\"]\n\n    if lang and lang in SUPPORTED_LANGS:\n        cmd += [\"-lang=%s\" % lang]\n\n    if parsed_query.get(\"use_imperial\", False):\n        cmd += [\"-imperial\"]\n\n    if location_name:\n        cmd += [\"-location_name\", location_name]\n\n    proc = Popen(cmd, stdout=PIPE, stderr=PIPE)\n    stdout, stderr = proc.communicate()\n    stdout = stdout.decode(\"utf-8\")\n    stderr = stderr.decode(\"utf-8\")\n\n    return stdout, stderr, proc.returncode\n\n\ndef _wego_postprocessing(location, parsed_query, stdout):\n    full_address = parsed_query[\"full_address\"]\n    lang = parsed_query[\"lang\"]\n\n    if \"days\" in parsed_query:\n        if parsed_query[\"days\"] == \"0\":\n            stdout = \"\\n\".join(stdout.splitlines()[:7]) + \"\\n\"\n        if parsed_query[\"days\"] == \"1\":\n            stdout = \"\\n\".join(stdout.splitlines()[:17]) + \"\\n\"\n        if parsed_query[\"days\"] == \"2\":\n            stdout = \"\\n\".join(stdout.splitlines()[:27]) + \"\\n\"\n\n    lines = stdout.splitlines()\n    if not lines:\n        lines = [\"\"]\n\n    first = lines[0]\n    rest = lines[1:]\n    if parsed_query.get(\"no-caption\", False):\n        if \":\" in first:\n            first = first.split(\":\", 1)[1]\n            stdout = \"\\n\".join([first.strip()] + rest) + \"\\n\"\n\n    if parsed_query.get(\"no-terminal\", False):\n        stdout = remove_ansi(stdout)\n\n    if parsed_query.get(\"no-city\", False):\n        stdout = \"\\n\".join(stdout.splitlines()[2:]) + \"\\n\"\n\n    if parsed_query.get(\"dumb\", False):\n        stdout = stdout.translate(TRANSLATION_TABLE)\n\n    if (\n        full_address\n        and parsed_query.get(\"format\", \"txt\") != \"png\"\n        and (\n            not parsed_query.get(\"no-city\")\n            and not parsed_query.get(\"no-caption\")\n            and not parsed_query.get(\"days\") == \"0\"\n        )\n    ):\n        line = \"%s: %s [%s]\\n\" % (get_message(\"LOCATION\", lang), full_address, location)\n        stdout += line\n\n    if parsed_query.get(\"padding\", False):\n        lines = [x.rstrip() for x in stdout.splitlines()]\n        max_l = max(len(remove_ansi(x)) for x in lines)\n        last_line = \" \" * max_l + \"   .\\n\"\n        stdout = \" \\n\" + \"\\n\".join(\"  %s  \" % x for x in lines) + \"\\n\" + last_line\n\n    return first, stdout\n\n\ndef _htmlize(ansi_output, title, parsed_query):\n    \"\"\"Return HTML representation of `ansi_output`.\n    Use `title` as the title of the page.\n    Format page according to query parameters from `parsed_query`.\"\"\"\n\n    cmd = [\"bash\", ANSI2HTML, \"--palette=solarized\"]\n    if not parsed_query.get(\"inverted_colors\"):\n        cmd += [\"--bg=dark\"]\n\n    proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)\n    stdout, stderr = proc.communicate(ansi_output.encode(\"utf-8\"))\n    stdout = stdout.decode(\"utf-8\")\n    stderr = stderr.decode(\"utf-8\")\n    if proc.returncode != 0:\n        error(stdout + stderr)\n\n    if parsed_query.get(\"inverted_colors\"):\n        stdout = stdout.replace(\n            '<body class=\"\">', '<body class=\"\" style=\"background:white;color:#777777\">'\n        )\n\n    title = \"<title>%s</title>\" % title\n    opengraph = _get_opengraph(parsed_query)\n    stdout = re.sub(\"<head>\", \"<head>\" + title + opengraph, stdout)\n    return stdout\n\n\ndef _get_opengraph(parsed_query):\n    \"\"\"Return OpenGraph data for `parsed_query`\"\"\"\n\n    url = parsed_query[\"request_url\"] or \"\"\n    pic_url = url.replace(\"?\", \"_\")\n\n    return (\n        '<meta property=\"og:image\" content=\"%(pic_url)s_0pq.png\" />'\n        '<meta property=\"og:site_name\" content=\"wttr.in\" />'\n        '<meta property=\"og:type\" content=\"profile\" />'\n        '<meta property=\"og:url\" content=\"%(url)s\" />'\n    ) % {\n        \"pic_url\": pic_url,\n        \"url\": url,\n    }\n"
  },
  {
    "path": "lib/weather_data.py",
    "content": "\"\"\"\nWeather data source\n\"\"\"\n\nimport json\nimport requests\nfrom globals import WWO_KEY\n\n\ndef get_weather_data(location, lang):\n    \"\"\"\n    Get weather data for `location`\n    \"\"\"\n    key = WWO_KEY\n    url = (\n        \"/premium/v1/weather.ashx\"\n        \"?key=%s&q=%s&format=json\"\n        \"&num_of_days=3&tp=3&lang=%s\"\n    ) % (key, location, lang)\n    url = \"http://127.0.0.1:5001\" + url\n\n    response = requests.get(url, timeout=10)\n    try:\n        data = json.loads(response.content)\n    except ValueError:\n        data = {}\n    return data\n"
  },
  {
    "path": "lib/wttr_srv.py",
    "content": "#!/usr/bin/env python\n# vim: set encoding=utf-8\n\n\"\"\"\nMain wttr.in rendering function implementation\n\"\"\"\n\nimport logging\nimport io\nimport os\nimport time\nfrom gevent.threadpool import ThreadPool\nfrom flask import render_template, send_file, make_response\n\nimport fmt.png\n\nimport parse_query\nfrom translations import (\n    get_message,\n    FULL_TRANSLATION,\n    PARTIAL_TRANSLATION,\n    SUPPORTED_LANGS,\n)\nfrom buttons import add_buttons\nfrom globals import (\n    get_help_file,\n    remove_ansi,\n    TRANSLATION_TABLE,\n    BASH_FUNCTION_FILE,\n    TRANSLATION_FILE,\n    LOG_FILE,\n    NOT_FOUND_LOCATION,\n    MALFORMED_RESPONSE_HTML_PAGE,\n    PLAIN_TEXT_AGENTS,\n    PLAIN_TEXT_PAGES,\n    MY_EXTERNAL_IP,\n    QUERY_LIMITS,\n)\nfrom location import is_location_blocked, location_processing\nfrom limits import Limits\nfrom view.wttr import get_wetter\nfrom view.moon import get_moon\nfrom view.line import wttr_line\n\nimport cache\n\nif not os.path.exists(os.path.dirname(LOG_FILE)):\n    os.makedirs(os.path.dirname(LOG_FILE))\nlogging.basicConfig(\n    filename=LOG_FILE, level=logging.INFO, format=\"%(asctime)s %(message)s\"\n)\n\nLIMITS = Limits(whitelist=[MY_EXTERNAL_IP], limits=QUERY_LIMITS)\n\nTASKS = ThreadPool(25)\n\n\ndef show_text_file(name, lang):\n    \"\"\"\n    show static file `name` for `lang`\n    \"\"\"\n    text = \"\"\n    if name == \":help\":\n        text = open(get_help_file(lang), \"r\").read()\n        text = text.replace(\"FULL_TRANSLATION\", \" \".join(FULL_TRANSLATION))\n        text = text.replace(\"PARTIAL_TRANSLATION\", \" \".join(PARTIAL_TRANSLATION))\n    elif name == \":bash.function\":\n        text = open(BASH_FUNCTION_FILE, \"r\").read()\n    elif name == \":iterm2\":\n        text = open(\"share/iterm2.txt\", \"r\").read()\n    elif name == \":translation\":\n        text = open(TRANSLATION_FILE, \"r\").read()\n        text = text.replace(\"NUMBER_OF_LANGUAGES\", str(len(SUPPORTED_LANGS))).replace(\n            \"SUPPORTED_LANGUAGES\", \" \".join(SUPPORTED_LANGS)\n        )\n    return text\n\n\ndef _client_ip_address(request):\n    \"\"\"Return client ip address for flask `request`.\"\"\"\n\n    if request.headers.getlist(\"X-PNG-Query-For\"):\n        ip_addr = request.headers.getlist(\"X-PNG-Query-For\")[0]\n        if ip_addr.startswith(\"::ffff:\"):\n            ip_addr = ip_addr[7:]\n    elif request.headers.getlist(\"X-Forwarded-For\"):\n        ip_addr = request.headers.getlist(\"X-Forwarded-For\")[0]\n        if ip_addr.startswith(\"::ffff:\"):\n            ip_addr = ip_addr[7:]\n    else:\n        ip_addr = request.remote_addr\n\n    return ip_addr\n\n\ndef _parse_language_header(header):\n    \"\"\"\n    >>> _parse_language_header(\"en-US,en;q=0.9\")\n    >>> _parse_language_header(\"en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7\")\n    >>> _parse_language_header(\"xx, fr-CA;q=0.8, da-DK;q=0.9\")\n    'da'\n    \"\"\"\n\n    def _parse_accept_language(accept_language):\n        languages = accept_language.split(\",\")\n        locale_q_pairs = []\n\n        for language in languages:\n            try:\n                if language.split(\";\")[0] == language:\n                    # no q => q = 1\n                    locale_q_pairs.append((language.strip(), 1))\n                else:\n                    locale = language.split(\";\")[0].strip()\n                    weight = float(language.split(\";\")[1].split(\"=\")[1])\n                    locale_q_pairs.append((locale, weight))\n            except (IndexError, ValueError):\n                pass\n\n        return locale_q_pairs\n\n    def _find_supported_language(accepted_languages):\n        def supported_langs():\n            \"\"\"Yields all pairs in the Accept-Language header\n            supported in SUPPORTED_LANGS or None if 'en' is the preferred\"\"\"\n            for lang_tuple in accepted_languages:\n                lang = lang_tuple[0]\n                if \"-\" in lang:\n                    lang = lang.split(\"-\", 1)[0]\n                if lang in SUPPORTED_LANGS:\n                    yield lang, lang_tuple[1]\n                elif lang == \"en\":\n                    yield None, lang_tuple[1]\n\n        try:\n            return max(supported_langs(), key=lambda lang_tuple: lang_tuple[1])[0]\n        except ValueError:\n            return None\n\n    return _find_supported_language(_parse_accept_language(header))\n\n\ndef get_answer_language_and_view(request):\n    \"\"\"\n    Return preferred answer language based on\n    domain name, query arguments and headers\n    \"\"\"\n\n    lang = None\n    view_name = None\n    hostname = request.headers[\"Host\"]\n    if hostname != \"wttr.in\" and hostname.endswith(\".wttr.in\"):\n        lang = hostname[:-8]\n        if lang.startswith(\"v2\") or lang.startswith(\"v3\"):\n            view_name = lang\n            lang = None\n\n    if \"lang\" in request.args:\n        lang = request.args.get(\"lang\")\n        if lang.lower() == \"none\":\n            lang = None\n\n    header_accept_language = request.headers.get(\"Accept-Language\", \"\")\n    if lang is None and header_accept_language:\n        lang = _parse_language_header(header_accept_language)\n\n    return lang, view_name\n\n\ndef get_output_format(query, parsed_query):\n    \"\"\"\n    Return preferred output format: ansi, text, html or png\n    based on arguments and headers in `request`.\n    Return new location (can be rewritten)\n    \"\"\"\n\n    if (\n        (\n            \"view\" in query\n            and not query[\"view\"].startswith(\"v2\")\n            and not query[\"view\"].startswith(\"v3\")\n        )\n        or parsed_query.get(\"png_filename\")\n        or query.get(\"force-ansi\")\n    ):\n        return False\n\n    user_agent = parsed_query.get(\"user_agent\", \"\").lower()\n    html_output = not any(agent in user_agent for agent in PLAIN_TEXT_AGENTS)\n    return html_output\n\n\ndef _cyclic_location_selection(locations, period):\n    \"\"\"Return one of `locations` (: separated list)\n    basing on the current time and query interval `period`\n    \"\"\"\n\n    locations = locations.split(\":\")\n    max_len = max(len(x) for x in locations)\n    locations = [x.rjust(max_len) for x in locations]\n\n    try:\n        period = int(period)\n    except ValueError:\n        period = 1\n\n    index = int(time.time() / period) % len(locations)\n    return locations[index]\n\n\ndef _response(parsed_query, query, fast_mode=False):\n    \"\"\"Create response text based on `parsed_query` and `query` data.\n    If `fast_mode` is True, process only requests that can\n    be handled very fast (cached and static files).\n    \"\"\"\n\n    answer = None\n    cache_signature = cache.get_signature(\n        parsed_query[\"user_agent\"],\n        parsed_query[\"request_url\"],\n        parsed_query[\"ip_addr\"],\n        parsed_query[\"lang\"],\n    )\n    answer = cache.get(cache_signature)\n\n    if parsed_query[\"orig_location\"] in PLAIN_TEXT_PAGES:\n        answer = show_text_file(parsed_query[\"orig_location\"], parsed_query[\"lang\"])\n        if parsed_query[\"html_output\"]:\n            answer = render_template(\"index.html\", body=answer)\n\n    if answer or fast_mode:\n        return answer\n\n    # at this point, we could not handle the query fast,\n    # so we handle it with all available logic\n    loc = (parsed_query[\"orig_location\"] or \"\").lower()\n    if parsed_query.get(\"view\"):\n        if not parsed_query.get(\"location\"):\n            parsed_query[\"location\"] = loc\n\n        output = wttr_line(query, parsed_query)\n    elif loc == \"moon\" or loc.startswith(\"moon@\"):\n        output = get_moon(parsed_query)\n    else:\n        output = get_wetter(parsed_query)\n\n    if parsed_query.get(\"png_filename\"):\n        if parsed_query.get(\"view\") != \"v3\":\n            # originally it was just a usual function call,\n            # but it was a blocking call, so it was moved\n            # to separate threads:\n            #\n            #    output = fmt.png.render_ansi(\n            #        output, options=parsed_query)\n            result = TASKS.spawn(\n                fmt.png.render_ansi, cache._update_answer(output), options=parsed_query\n            )\n            output = result.get()\n    else:\n        if (\n            query.get(\"days\", \"3\") != \"0\"\n            and not query.get(\"no-follow-line\")\n            and ((parsed_query.get(\"view\") or \"v2\")[:2] in [\"v2\", \"v3\"])\n        ):\n            if parsed_query[\"html_output\"]:\n                output = add_buttons(output)\n            else:\n                message = get_message(\"FOLLOW_ME\", parsed_query[\"lang\"])\n                if parsed_query.get(\"no-terminal\", False):\n                    message = remove_ansi(message)\n                if parsed_query.get(\"dumb\", False):\n                    message = message.translate(TRANSLATION_TABLE)\n                output += \"\\n\" + message + \"\\n\"\n\n    return cache.store(cache_signature, output)\n\n\ndef parse_request(location, request, query, fast_mode=False):\n    \"\"\"Parse request and provided extended information for the query,\n    including location data, language, output format, view, etc.\n\n    Incoming data:\n\n        `location`              location name extracted from the query url\n        `request.args`\n        `request.headers`\n        `request.remote_addr`\n        `request.referrer`\n        `request.query_string`\n        `query`                 parsed command line arguments\n\n    Parameters priorities (from low to high):\n\n        * HTTP-header\n        * Domain name\n        * URL\n        * Filename\n\n    Return: dictionary with parsed parameters\n    \"\"\"\n\n    if location and location.startswith(\"b_\"):\n        result = parse_query.deserialize(location)\n        result[\"request_url\"] = request.url\n        if result:\n            return result\n\n    png_filename = None\n    if location is not None and location.lower().endswith(\".png\"):\n        png_filename = location\n        location = location[:-4]\n    if location and \":\" in location and location[0] != \":\":\n        location = _cyclic_location_selection(location, query.get(\"period\", 1))\n\n    parsed_query = {\n        \"ip_addr\": _client_ip_address(request),\n        \"user_agent\": request.headers.get(\"User-Agent\", \"\").lower(),\n        \"request_url\": request.url,\n    }\n\n    if png_filename:\n        parsed_query[\"png_filename\"] = png_filename\n        parsed_query.update(parse_query.parse_wttrin_png_name(png_filename))\n\n    lang, _view = get_answer_language_and_view(request)\n\n    parsed_query[\"view\"] = parsed_query.get(\"view\", query.get(\"view\", _view))\n    parsed_query[\"location\"] = parsed_query.get(\"location\", location)\n    parsed_query[\"orig_location\"] = parsed_query[\"location\"]\n    parsed_query[\"lang\"] = parsed_query.get(\"lang\", lang)\n\n    parsed_query[\"html_output\"] = get_output_format(query, parsed_query)\n    parsed_query[\"json_output\"] = (parsed_query.get(\"view\", \"\") or \"\").startswith(\"j\")\n\n    if not fast_mode:  # not png_filename and not fast_mode:\n        (\n            location,\n            override_location_name,\n            full_address,\n            country,\n            query_source_location,\n            hemisphere,\n        ) = location_processing(parsed_query[\"location\"], parsed_query[\"ip_addr\"])\n\n        us_ip = (\n            query_source_location[2] in [\"United States\", \"United States of America\"]\n            and \"slack\" not in parsed_query[\"user_agent\"]\n        )\n        query = parse_query.metric_or_imperial(query, lang, us_ip=us_ip)\n\n        if country and location != NOT_FOUND_LOCATION:\n            location = \"%s,%s\" % (location, country)\n\n        parsed_query.update(\n            {\n                \"location\": location,\n                \"override_location_name\": override_location_name,\n                \"full_address\": full_address,\n                \"country\": country,\n                \"query_source_location\": query_source_location,\n                \"hemisphere\": hemisphere,\n            }\n        )\n\n    parsed_query.update(query)\n    return parsed_query\n\n\ndef wttr(location, request):\n    \"\"\"Main rendering function, it processes incoming weather queries,\n    and depending on the User-Agent string and other paramters of the query\n    it returns output in HTML, ANSI or other format.\n    \"\"\"\n\n    def _wrap_response(response_text, html_output, json_output, png_filename=None):\n        if not isinstance(response_text, str) and not isinstance(response_text, bytes):\n            return response_text\n\n        if png_filename:\n            response = make_response(\n                send_file(\n                    io.BytesIO(response_text),\n                    download_name=png_filename,\n                    mimetype=\"image/png\",\n                )\n            )\n\n            for key, value in {\n                \"Cache-Control\": \"no-cache, no-store, must-revalidate\",\n                \"Pragma\": \"no-cache\",\n                \"Expires\": \"0\",\n            }.items():\n                response.headers[key] = value\n        else:\n            response = make_response(response_text)\n            if html_output:\n                response.mimetype = \"text/html\"\n            elif json_output:\n                response.mimetype = \"application/json\"\n            else:\n                response.mimetype = \"text/plain\"\n        return response\n\n    if is_location_blocked(location):\n        return (\"\", 403)  # Forbidden\n\n    try:\n        LIMITS.check_ip(_client_ip_address(request))\n    except RuntimeError as exception:\n        return (str(exception), 429)  # Too many requests\n\n    query = parse_query.parse_query(request.args)\n\n    # first, we try to process the query as fast as possible\n    # (using the cache and static files),\n    # and only if \"fast_mode\" was unsuccessful,\n    # use the full track\n    parsed_query = parse_request(location, request, query, fast_mode=True)\n    response = _response(parsed_query, query, fast_mode=True)\n\n    ############################\n    # Service Down.\n\n    if os.path.exists(\"/tmp/service-down\"):\n        # parsed_query = parse_request(location, request, query)\n        if parsed_query[\"html_output\"]:\n            response = MALFORMED_RESPONSE_HTML_PAGE\n            http_code = 500  # Internal Server Error\n        else:\n            response = get_message(\"CAPACITY_LIMIT_REACHED\", parsed_query[\"lang\"])\n            http_code = 503  # Service Unavailable\n\n        # if exception is occured, we return not a png file but text\n        if \"png_filename\" in parsed_query:\n            del parsed_query[\"png_filename\"]\n\n        return (\n            _wrap_response(\n                response,\n                parsed_query[\"html_output\"],\n                parsed_query[\"json_output\"],\n                png_filename=parsed_query.get(\"png_filename\"),\n            ),\n            http_code,\n        )\n\n    ############################\n\n    http_code = 200\n    try:\n        if not response:\n            parsed_query = parse_request(location, request, query)\n            response = _response(parsed_query, query)\n            # if not response or (isinstance(response, str) and not response.strip()):\n            #    return RuntimeError(\"Empty answer\")\n\n            if parsed_query[\"location\"] == NOT_FOUND_LOCATION:\n                http_code = 404\n\n    # pylint: disable=broad-except\n    except Exception:\n        logging.error(\"Exception has occured\", exc_info=1)\n        if parsed_query[\"html_output\"]:\n            response = MALFORMED_RESPONSE_HTML_PAGE\n            http_code = 500  # Internal Server Error\n        else:\n            response = get_message(\"CAPACITY_LIMIT_REACHED\", parsed_query[\"lang\"])\n            http_code = 503  # Service Unavailable\n\n        # if exception is occured, we return not a png file but text\n        if \"png_filename\" in parsed_query:\n            del parsed_query[\"png_filename\"]\n    return (\n        _wrap_response(\n            response,\n            parsed_query[\"html_output\"],\n            parsed_query[\"json_output\"],\n            png_filename=parsed_query.get(\"png_filename\"),\n        ),\n        http_code,\n    )\n\n\nif __name__ == \"__main__\":\n    import doctest\n\n    doctest.testmod()\n"
  },
  {
    "path": "requirements.txt",
    "content": "flask\ngeoip2\ngeopy\nrequests\ngevent\ndnspython\npylint\ncyrtranslit\nastral>=2.0,<=2.2\ntimezonefinder\npytz\npyte\npython-dateutil>=2.5.0,<=2.8.1\ndiagram\npyjq\nscipy\nnumpy\npillow\nbabel\npylru>=1.0.7,<=1.2.1\npysocks\nsupervisor\nnumba\nemoji>=1.6.0,<=1.7.0\ngrapheme\npycountry\naiohttp>=3.10.11 # not directly required, pinned by Snyk to avoid a vulnerability\nyq\n"
  },
  {
    "path": "share/aliases",
    "content": "MDW         : MDW Chicago\nmdw         : MDW Chicago\nMsk         : Moscow\nMoskva      : Moscow\nMoskau      : Moscow\nKyiv        : Kiev,Ukraine\nKiew        : Kiev,Ukraine\nKiev        : Kiev,Ukraine\nKijev       : Kiev\nKharkov     : Kharkiv\nspb         : Saint Petersburg\nDnipro      : Dnipropetrovsk\nst.petersburg: Saint Petersburg\nsanfrancisco: San Francisco\nsan fransisco:San Francisco\nSan+Francisco:San Francisco\nSan-Francisco:San Francisco\nDnipropetrovsk:Dnepropetrovsk\nDnepr       : Dnipropetrovsk\nsanjose     : San Jose\nsan josé    : San Jose\nnewyork     : New York\nnewy-yourk  : New York\nnew-york    : New York\nSaint-Petersburg: Saint Petersburg\nKrakow      : Krakow,pl\nindonesia   : Jakarta\nhanoi,vietnam:Hanoi\nnuernberg   : Nuremberg\nnürnberg    : Nuremberg\nnorway      : Oslo\nville de bruxelles - stad brussel: Brussels\nfrankfurt am main:Frankfurt, Hessen\nfrankfurt   :Frankfurt, Hessen\nfrankfurt oder : Frankfurt, Brandenburg\nfrankfurt (oder): Frankfurt, Brandenburg\ntel-aviv    : Tel Aviv\nsao paulo   : São Paulo\nlos-angeles : Los Angeles\nSevastopol  : Sevastopol, Ukraine\nSimferopol  : Simferopol, Ukraine\nBeersheva   : Beersheba\nBe'ersheva  : Beersheba\nBe'er Sheva : Beersheba\nLugansk     : Luhansk\nBjalistoko  : Białystok\nChicago     : Chicago,IL\nParis       : Paris,France\nGiessen     : Giessen, Germany\nBraga       : Braga, Portugal\nKashan      : ~Kashan,Iran\nBaku        : Baku,Az\nRome        : Rome, Italia\nYYZ         : Toronto Pearson Airport\nbrasilia    : Palacio da Alvorada,Brasilia\nTula        : Tula,Ru\n"
  },
  {
    "path": "share/ansi2html.sh",
    "content": "#!/bin/sh\n\n# Convert ANSI (terminal) colours and attributes to HTML\n\n# Licence: LGPLv2\n# Author:\n#    http://www.pixelbeat.org/docs/terminal_colours/\n# Examples:\n#    ls -l --color=always | ansi2html.sh > ls.html\n#    git show --color | ansi2html.sh > last_change.html\n#    Generally one can use the `script` util to capture full terminal output.\n# Changes:\n#    V0.1, 24 Apr 2008, Initial release\n#    V0.2, 01 Jan 2009, Phil Harnish <philharnish@gmail.com>\n#                         Support `git diff --color` output by\n#                         matching ANSI codes that specify only\n#                         bold or background colour.\n#                       P@draigBrady.com\n#                         Support `ls --color` output by stripping\n#                         redundant leading 0s from ANSI codes.\n#                         Support `grep --color=always` by stripping\n#                         unhandled ANSI codes (specifically ^[[K).\n#    V0.3, 20 Mar 2009, http://eexpress.blog.ubuntu.org.cn/\n#                         Remove cat -v usage which mangled non ascii input.\n#                         Cleanup regular expressions used.\n#                         Support other attributes like reverse, ...\n#                       P@draigBrady.com\n#                         Correctly nest <span> tags (even across lines).\n#                         Add a command line option to use a dark background.\n#                         Strip more terminal control codes.\n#    V0.4, 17 Sep 2009, P@draigBrady.com\n#                         Handle codes with combined attributes and color.\n#                         Handle isolated <bold> attributes with css.\n#                         Strip more terminal control codes.\n#    V0.23, 22 Dec 2015\n#      http://github.com/pixelb/scripts/commits/master/scripts/ansi2html.sh\n\ngawk --version >/dev/null || exit 1\n\nif [ \"$1\" = \"--version\" ]; then\n    printf '0.22\\n' && exit\nfi\n\nif [ \"$1\" = \"--help\" ]; then\n    printf '%s\\n' \\\n'This utility converts ANSI codes in data passed to stdin\nIt has 2 optional parameters:\n   --bg=dark --palette=linux|solarized|tango|xterm\nE.g.: ls -l --color=always | ansi2html.sh --bg=dark > ls.html' >&2\n    exit\nfi\n\n[ \"$1\" = \"--bg=dark\" ] && { dark_bg=yes; shift; }\n\nif [ \"$1\" = \"--palette=solarized\" ]; then\n   # See http://ethanschoonover.com/solarized\n   P0=073642;  P1=D30102;  P2=859900;  P3=B58900;\n   P4=268BD2;  P5=D33682;  P6=2AA198;  P7=EEE8D5;\n   P8=002B36;  P9=CB4B16; P10=586E75; P11=657B83;\n  P12=839496; P13=6C71C4; P14=93A1A1; P15=FDF6E3;\n  shift;\nelif [ \"$1\" = \"--palette=solarized-xterm\" ]; then\n   # Above mapped onto the xterm 256 color palette\n   P0=262626;  P1=AF0000;  P2=5F8700;  P3=AF8700;\n   P4=0087FF;  P5=AF005F;  P6=00AFAF;  P7=E4E4E4;\n   P8=1C1C1C;  P9=D75F00; P10=585858; P11=626262;\n  P12=808080; P13=5F5FAF; P14=8A8A8A; P15=FFFFD7;\n  shift;\nelif [ \"$1\" = \"--palette=tango\" ]; then\n   # Gnome default\n   P0=000000;  P1=CC0000;  P2=4E9A06;  P3=C4A000;\n   P4=3465A4;  P5=75507B;  P6=06989A;  P7=D3D7CF;\n   P8=555753;  P9=EF2929; P10=8AE234; P11=FCE94F;\n  P12=729FCF; P13=AD7FA8; P14=34E2E2; P15=EEEEEC;\n  shift;\nelif [ \"$1\" = \"--palette=xterm\" ]; then\n   P0=000000;  P1=CD0000;  P2=00CD00;  P3=CDCD00;\n   P4=0000EE;  P5=CD00CD;  P6=00CDCD;  P7=E5E5E5;\n   P8=7F7F7F;  P9=FF0000; P10=00FF00; P11=FFFF00;\n  P12=5C5CFF; P13=FF00FF; P14=00FFFF; P15=FFFFFF;\n  shift;\nelse # linux console\n   P0=000000;  P1=AA0000;  P2=00AA00;  P3=AA5500;\n   P4=0000AA;  P5=AA00AA;  P6=00AAAA;  P7=AAAAAA;\n   P8=555555;  P9=FF5555; P10=55FF55; P11=FFFF55;\n  P12=5555FF; P13=FF55FF; P14=55FFFF; P15=FFFFFF;\n  [ \"$1\" = \"--palette=linux\" ] && shift\nfi\n\n[ \"$1\" = \"--bg=dark\" ] && { dark_bg=yes; shift; }\n\n# Mac OSX's GNU sed is installed as gsed\n# use e.g. homebrew 'gnu-sed' to get it\nif ! sed --version >/dev/null 2>&1; then\n  if gsed --version >/dev/null 2>&1; then\n    alias sed=gsed\n  else\n    echo \"Error, can't find an acceptable GNU sed.\" >&2\n    exit 1\n  fi\nfi\n\nprintf '%s' \"<html>\n<head>\n<meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=utf-8\\\"/>\n<link rel=\\\"stylesheet\\\" type=\\\"text/css\\\" href=\\\"https://adobe-fonts.github.io/source-code-pro/source-code-pro.css\\\">\n<link rel=\\\"stylesheet\\\" type=\\\"text/css\\\" href=\\\"/files/style.css\\\" />\n<style type=\\\"text/css\\\">\n.ef0,.f0 { color: #$P0; } .eb0,.b0 { background-color: #$P0; }\n.ef1,.f1 { color: #$P1; } .eb1,.b1 { background-color: #$P1; }\n.ef2,.f2 { color: #$P2; } .eb2,.b2 { background-color: #$P2; }\n.ef3,.f3 { color: #$P3; } .eb3,.b3 { background-color: #$P3; }\n.ef4,.f4 { color: #$P4; } .eb4,.b4 { background-color: #$P4; }\n.ef5,.f5 { color: #$P5; } .eb5,.b5 { background-color: #$P5; }\n.ef6,.f6 { color: #$P6; } .eb6,.b6 { background-color: #$P6; }\n.ef7,.f7 { color: #$P7; } .eb7,.b7 { background-color: #$P7; }\n.ef8, .f0 > .bold,.bold > .f0 { color: #$P8; font-weight: normal; }\n.ef9, .f1 > .bold,.bold > .f1 { color: #$P9; font-weight: normal; }\n.ef10,.f2 > .bold,.bold > .f2 { color: #$P10; font-weight: normal; }\n.ef11,.f3 > .bold,.bold > .f3 { color: #$P11; font-weight: normal; }\n.ef12,.f4 > .bold,.bold > .f4 { color: #$P12; font-weight: normal; }\n.ef13,.f5 > .bold,.bold > .f5 { color: #$P13; font-weight: normal; }\n.ef14,.f6 > .bold,.bold > .f6 { color: #$P14; font-weight: normal; }\n.ef15,.f7 > .bold,.bold > .f7 { color: #$P15; font-weight: normal; }\n.eb8  { background-color: #$P8; }\n.eb9  { background-color: #$P9; }\n.eb10 { background-color: #$P10; }\n.eb11 { background-color: #$P11; }\n.eb12 { background-color: #$P12; }\n.eb13 { background-color: #$P13; }\n.eb14 { background-color: #$P14; }\n.eb15 { background-color: #$P15; }\n\"\n\n# The default xterm 256 colour palette\nfor red in 0 1 2 3 4 5 ; do\n  for green in 0 1 2 3 4 5 ; do\n    for blue in 0 1 2 3 4 5 ; do\n      c=$((16 + ($red * 36) + ($green * 6) + $blue))\n      r=$((($red * 40 + 55) * ($red > 0)))\n      g=$((($green * 40 + 55) * ($green > 0)))\n      b=$((($blue * 40 + 55) * ($blue > 0)))\n      printf \".ef%d { color: #%2.2x%2.2x%2.2x; } \" $c $r $g $b\n      printf \".eb%d { background-color: #%2.2x%2.2x%2.2x; }\\n\" $c $r $g $b\n    done\n  done\ndone\nfor gray in $(seq 0 23); do\n  c=$(($gray+232))\n  l=$(($gray*10 + 8))\n  printf \".ef%d { color: #%2.2x%2.2x%2.2x; } \" $c $l $l $l\n  printf \".eb%d { background-color: #%2.2x%2.2x%2.2x; }\\n\" $c $l $l $l\ndone\n\nprintf '%s' '\n.f9 { color: '`[ \"$dark_bg\" ] && printf \"#$P7;\" || printf \"#$P0;\"`' }\n.b9 { background-color: #'`[ \"$dark_bg\" ] && printf $P0 || printf $P15`'; }\n.f9 > .bold,.bold > .f9, body.f9 > pre > .bold {\n  /* Bold is heavy black on white, or bright white\n     depending on the default background */\n  color: '`[ \"$dark_bg\" ] && printf \"#$P15;\" || printf \"#$P0;\"`'\n  font-weight: '`[ \"$dark_bg\" ] && printf 'normal;' || printf 'bold;'`'\n}\n.reverse {\n  /* CSS does not support swapping fg and bg colours unfortunately,\n     so just hardcode something that will look OK on all backgrounds. */\n  '\"color: #$P0; background-color: #$P7;\"'\n}\n.underline { text-decoration: underline; }\n.line-through { text-decoration: line-through; }\n.blink { text-decoration: blink; }\n\n/* Avoid pixels between adjacent span elements.\n   Note this only works for lines less than 80 chars\n   where we close span elements on the same line.\nspan { display: inline-block; }\n*/\n</style>\n</head>\n\n<body class=\"\">\n<pre>\n'\n\np='\\x1b\\['        #shortcut to match escape codes\n\n# Handle various xterm control sequences.\n# See /usr/share/doc/xterm-*/ctlseqs.txt\nsed \"\n# escape ampersand and quote\ns#&#\\&amp;#g; s#\\\"#\\&quot;#g;\ns#\\x1b[^\\x1b]*\\x1b\\\\\\##g  # strip anything between \\e and ST\ns#\\x1b][0-9]*;[^\\a]*\\a##g # strip any OSC (xterm title etc.)\n\ns#\\r\\$## # strip trailing \\r\n\n# strip other non SGR escape sequences\ns#[\\x07]##g\ns#\\x1b[]>=\\][0-9;]*##g\ns#\\x1bP+.\\{5\\}##g\n# Mark cursor positioning codes \\\"Jr;c;\ns#${p}\\([0-9]\\{1,2\\}\\)G#\\\"J;\\1;#g\ns#${p}\\([0-9]\\{1,2\\}\\);\\([0-9]\\{1,2\\}\\)H#\\\"J\\1;\\2;#g\n\n# Mark clear as \\\"Cn where n=1 is screen and n=0 is to end-of-line\ns#${p}H#\\\"C1;#g\ns#${p}K#\\\"C0;#g\n# Mark Cursor move columns as \\\"Mn where n is +ve for right, -ve for left\ns#${p}C#\\\"M1;#g\ns#${p}\\([0-9]\\{1,\\}\\)C#\\\"M\\1;#g\ns#${p}\\([0-9]\\{1,\\}\\)D#\\\"M-\\1;#g\ns#${p}\\([0-9]\\{1,\\}\\)P#\\\"X\\1;#g\n\ns#${p}[0-9;?]*[^0-9;?m]##g\n\n\" |\n\n# Normalize the input before transformation\nsed \"\n# escape HTML (ampersand and quote done above)\ns#>#\\&gt;#g; s#<#\\&lt;#g;\n\n# normalize SGR codes a little\n\n# split 256 colors out and mark so that they're not\n# recognised by the following 'split combined' line\n:e\ns#${p}\\([0-9;]\\{1,\\}\\);\\([34]8;5;[0-9]\\{1,3\\}\\)m#${p}\\1m${p}¬\\2m#g; t e\ns#${p}\\([34]8;5;[0-9]\\{1,3\\}\\)m#${p}¬\\1m#g;\n\n:c\ns#${p}\\([0-9]\\{1,\\}\\);\\([0-9;]\\{1,\\}\\)m#${p}\\1m${p}\\2m#g; t c   # split combined\ns#${p}0\\([0-7]\\)#${p}\\1#g                                 #strip leading 0\ns#${p}1m\\(\\(${p}[4579]m\\)*\\)#\\1${p}1m#g                   #bold last (with clr)\ns#${p}m#${p}0m#g                                          #add leading 0 to norm\n\n# undo any 256 color marking\ns#${p}¬\\([34]8;5;[0-9]\\{1,3\\}\\)m#${p}\\1m#g;\n\n# map 16 color codes to color + bold\ns#${p}9\\([0-7]\\)m#${p}3\\1m${p}1m#g;\ns#${p}10\\([0-7]\\)m#${p}4\\1m${p}1m#g;\n\n# change 'reset' code to \\\"R\ns#${p}0m#\\\"R;#g\n\" |\n\n# Convert SGR sequences to HTML\nsed \"\n# common combinations to minimise html (optional)\n:f\ns#${p}3[0-7]m${p}3\\([0-7]\\)m#${p}3\\1m#g; t f\n:b\ns#${p}4[0-7]m${p}4\\([0-7]\\)m#${p}4\\1m#g; t b\ns#${p}3\\([0-7]\\)m${p}4\\([0-7]\\)m#<span class=\\\"f\\1 b\\2\\\">#g\ns#${p}4\\([0-7]\\)m${p}3\\([0-7]\\)m#<span class=\\\"f\\2 b\\1\\\">#g\n\ns#${p}1m#<span class=\\\"bold\\\">#g\ns#${p}4m#<span class=\\\"underline\\\">#g\ns#${p}5m#<span class=\\\"blink\\\">#g\ns#${p}7m#<span class=\\\"reverse\\\">#g\ns#${p}9m#<span class=\\\"line-through\\\">#g\ns#${p}3\\([0-9]\\)m#<span class=\\\"f\\1\\\">#g\ns#${p}4\\([0-9]\\)m#<span class=\\\"b\\1\\\">#g\n\ns#${p}38;5;\\([0-9]\\{1,3\\}\\)m#<span class=\\\"ef\\1\\\">#g\ns#${p}48;5;\\([0-9]\\{1,3\\}\\)m#<span class=\\\"eb\\1\\\">#g\n\ns#${p}[0-9;]*m##g # strip unhandled codes\n\" |\n\n# Convert alternative character set and handle cursor movement codes\n# Note we convert here, as if we do at start we have to worry about avoiding\n# conversion of SGR codes etc., whereas doing here we only have to\n# avoid conversions of stuff between &...; or <...>\n#\n# Note we could use sed to do this based around:\n#   sed 'y/abcdefghijklmnopqrstuvwxyz{}`~/▒␉␌␍␊°±␤␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π£◆·/'\n# However that would be very awkward as we need to only conv some input.\n# The basic scheme that we do in the awk script below is:\n#  1. enable transliterate once \"T1; is seen\n#  2. disable once \"T0; is seen (may be on diff line)\n#  3. never transliterate between &; or <> chars\n#  4. track x,y movements and active display mode at each position\n#  5. buffer line/screen and dump when required\nsed \"\n# change 'smacs' and 'rmacs' to \\\"T1 and \\\"T0 to simplify matching.\ns#\\x1b(0#\\\"T1;#g;\ns#\\x0E#\\\"T1;#g;\n\ns#\\x1b(B#\\\"T0;#g\ns#\\x0F#\\\"T0;#g\n\" |\n(\ngawk '\nfunction dump_line(l,del,c,blanks,ret) {\n  for(c=1;c<maxX;c++) {\n    if ((c SUBSEP l) in attr || length(cur)) {\n      ret = ret blanks fixas(cur,attr[c,l])\n      if(del) delete attr[c,l]\n      blanks=\"\"\n    }\n    if ((c SUBSEP l) in dump) {\n      ret=ret blanks dump[c,l]\n      if(del) delete dump[c,l]\n      blanks=\"\"\n    } else blanks=blanks \" \"\n  }\n  if(length(cur)) ret=ret blanks\n  return ret\n}\n\nfunction dump_screen(l,ret) {\n  for(l=1;l<=maxY;l++)\n    ret=ret dump_line(l,0) \"\\n\"\n  return ret fixas(cur, \"\")\n}\n\nfunction atos(a,i,ret) {\n  for(i=1;i<=length(a);i++) if(i in a) ret=ret a[i]\n  return ret\n}\n\nfunction fixas(a,s,spc,i,attr,rm,ret) {\n  spc=length(a)\n  l=split(s,attr,\">\")\n  for(i=1;i<=spc;i++) {\n    rm=rm?rm:(a[i]!=attr[i]\">\")\n    if(rm) {\n      ret=ret \"</span>\"\n      delete a[i];\n    }\n  }\n  for(i=1;i<l;i++) {\n    attr[i]=attr[i]\">\"\n    if(a[i]!=attr[i]) {\n      a[i]=attr[i]\n      ret = ret attr[i]\n    }\n  }\n  return ret\n}\n\nfunction encode(string,start,end,i,ret,pos,sc,buf) {\n   if(!end) end=length(string);\n   if(!start) start=1;\n   state=3\n   for(i=1;i<=length(string);i++) {\n     c=substr(string,i,1)\n     if(state==2) {\n       sc=sc c\n       if(c==\";\") {\n          c=sc\n          state=last_mode\n       } else continue\n     } else {\n       if(c==\"\\r\") { x=1; continue }\n       if(c==\"<\") {\n         # Change attributes - store current active\n         # attributes in span array\n         split(substr(string,i),cord,\">\");\n         i+=length(cord[1])\n         span[++spc]=cord[1] \">\"\n         continue\n       }\n       else if(c==\"&\") {\n         # All goes to single position till we see a semicolon\n         sc=c\n         state=2\n         continue\n       }\n       else if(c==\"\\b\") {\n          # backspace move insertion point back 1\n          if(spc) attr[x,y]=atos(span)\n          x=x>1?x-1:1\n          continue\n       }\n       else if(c==\"\\\"\") {\n          split(substr(string,i+2),cord,\";\")\n          cc=substr(string,i+1,1);\n          if(cc==\"T\") {\n              # Transliterate on/off\n              if(cord[1]==1&&state==3) last_mode=state=4\n              if(cord[1]==0&&state==4) last_mode=state=3\n          }\n          else if(cc==\"C\") {\n              # Clear\n              if(cord[1]+0) {\n                # Screen - if Recording dump screen\n                if(dumpStatus==dsActive) ret=ret dump_screen()\n                dumpStatus=dsActive\n                delete dump\n                delete attr\n                x=y=1\n              } else {\n                # To end of line\n                for(pos=x;pos<maxX;pos++) {\n                  dump[pos,y]=\" \"\n                  if (!spc) delete attr[pos,y]\n                  else attr[pos,y]=atos(span)\n                }\n              }\n          }\n          else if(cc==\"J\") {\n              # Jump to x,y\n              i+=length(cord[2])+1\n              # If line is higher - dump previous screen\n              if(dumpStatus==dsActive&&cord[1]<y) {\n                ret=ret dump_screen();\n                dumpStatus=dsNew;\n              }\n              x=cord[2]\n              if(length(cord[1]) && y!=cord[1]){\n                y=cord[1]\n                if(y>maxY) maxY=y\n                # Change y - start recording\n                dumpStatus=dumpStatus?dumpStatus:dsReset\n              }\n          }\n          else if(cc==\"M\") {\n              # Move left/right on current line\n              x+=cord[1]\n          }\n          else if(cc==\"X\") {\n              # delete on right\n              for(pos=x;pos<=maxX;pos++) {\n                nx=pos+cord[1]\n                if(nx<maxX) {\n                  if((nx SUBSEP y) in attr) attr[pos,y] = attr[nx,y]\n                  else delete attr[pos,y]\n                  if((nx SUBSEP y) in dump) dump[pos,y] = dump[nx,y]\n                  else delete dump[pos,y]\n                } else if(spc) {\n                  attr[pos,y]=atos(span)\n                  dump[pos,y]=\" \"\n                }\n              }\n          }\n          else if(cc==\"R\") {\n              # Reset attributes\n              while(spc) delete span[spc--]\n          }\n          i+=length(cord[1])+2\n          continue\n       }\n       else if(state==4&&i>=start&&i<=end&&c in Trans) c=Trans[c]\n     }\n     if(dumpStatus==dsReset) {\n       delete dump\n       delete attr\n       ret=ret\"\\n\"\n       dumpStatus=dsActive\n     }\n     if(dumpStatus==dsNew) {\n       # After moving/clearing we are now ready to write\n       # somthing to the screen so start recording now\n       ret=ret\"\\n\"\n       dumpStatus=dsActive\n     }\n     if(dumpStatus==dsActive||dumpStatus==dsOff) {\n       dump[x,y] = c\n       if(!spc) delete attr[x,y]\n       else attr[x,y] = atos(span)\n       if(++x>maxX) maxX=x;\n     }\n    }\n    # End of line if dumping increment y and set x back to first col\n    x=1\n    if(!dumpStatus) return ret dump_line(y,1);\n    else if(++y>maxY) maxY=y;\n    return ret\n}\nBEGIN{\n  OFS=FS\n  # dump screen status\n  dsOff=0    # Not dumping screen contents just write output direct\n  dsNew=1    # Just after move/clear waiting for activity to start recording\n  dsReset=2  # Screen cleared build new empty buffer and record\n  dsActive=3 # Currently recording\n  F=\"abcdefghijklmnopqrstuvwxyz{}`~\"\n  T=\"▒␉␌␍␊°±␤␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π£◆·\"\n  maxX=80\n  delete cur;\n  x=y=1\n  for(i=1;i<=length(F);i++)Trans[substr(F,i,1)]=substr(T,i,1);\n}\n\n{ $0=encode($0) }\n1\nEND {\n  if(dumpStatus) {\n    print dump_screen();\n  }\n}'\n)\n\nprintf '</pre>\n</body>\n</html>\\n'\n"
  },
  {
    "path": "share/bash-function.txt",
    "content": "#! /usr/bin/env bash\n# If you source this file, it will set WTTR_PARAMS as well as show weather.\n\n# WTTR_PARAMS is space-separated URL parameters, many of which are single characters that can be\n# lumped together. For example, \"F q m\" behaves the same as \"Fqm\".\nif [[ -z \"$WTTR_PARAMS\" ]]; then\n  # Form localized URL parameters for curl\n  if [[ -t 1 ]] && [[ \"$(tput cols)\" -lt 125 ]]; then\n      WTTR_PARAMS+='n'\n  fi 2> /dev/null\n  for _token in $( locale LC_MEASUREMENT ); do\n    case $_token in\n      1) WTTR_PARAMS+='m' ;;\n      2) WTTR_PARAMS+='u' ;;\n    esac\n  done 2> /dev/null\n  unset _token\n  export WTTR_PARAMS\nfi\n\nwttr() {\n  local location=\"${1// /+}\"\n  test \"$#\" -gt 0 && shift\n  local args=()\n  for p in $WTTR_PARAMS \"$@\"; do\n    args+=(\"--data-urlencode\" \"$p\")\n  done\n  curl -fGsS -H \"Accept-Language: ${LANG%_*}\" \"${args[@]}\" --compressed \"wttr.in/${location}\"\n}\n\nwttr \"$@\"\n"
  },
  {
    "path": "share/blacklist",
    "content": "NOT_FOUND\napple-touch-icon.png\napple-touch-icon-precomposed.png\napple-touch-icon-152x152-precomposed.png\n\n"
  },
  {
    "path": "share/docker/supervisord.conf",
    "content": "[supervisord]\nnodaemon=true\nlogfile=/var/log/supervisor/supervisord.log\npidfile=/var/run/supervisord.pid\n\n[program:srv]\ncommand=python3 /app/bin/srv.py\nstderr_logfile=/var/log/supervisor/srv-stderr.log\nstdout_logfile=/var/log/supervisor/srv-stdout.log\n\n[program:proxy]\ncommand=python3 /app/bin/proxy.py\nstderr_logfile=/var/log/supervisor/proxy-stderr.log\nstdout_logfile=/var/log/supervisor/proxy-stdout.log\n\n[program:geoproxy]\ncommand=python3 /app/bin/geo-proxy.py\nstderr_logfile=/var/log/supervisor/geoproxy-stderr.log\nstdout_logfile=/var/log/supervisor/geoproxy-stdout.log\n\n[include]\nfiles=/etc/supervisor/conf.d/*.conf\n"
  },
  {
    "path": "share/help.txt",
    "content": "Usage:\n\n    $ curl wttr.in          # current location\n    $ curl wttr.in/muc      # weather in the Munich airport\n\nSupported location types:\n\n    /paris                  # city name\n    /~Eiffel+tower          # any location (+ for spaces)\n    /Москва                 # Unicode name of any location in any language\n    /muc                    # airport code (3 letters)\n    /@stackoverflow.com     # domain name\n    /94107                  # area codes\n    /-78.46,106.79          # GPS coordinates\n\nMoon phase information:\n\n    /moon                   # Moon phase (add ,+US or ,+France for these cities)\n    /moon@2016-10-25        # Moon phase for the date (@2016-10-25)\n\nUnits:\n\n    m                       # metric (SI) (used by default everywhere except US)\n    u                       # USCS (used by default in US)\n    M                       # show wind speed in m/s\n\nView options:\n\n    0                       # only current weather\n    1                       # current weather + today's forecast\n    2                       # current weather + today's + tomorrow's forecast\n    A                       # ignore User-Agent and force ANSI output format (terminal)\n    d                       # restrict output to standard console font glyphs\n    F                       # do not show the \"Follow\" line\n    n                       # narrow version (only day and night)\n    q                       # quiet version (no \"Weather report\" text)\n    Q                       # superquiet version (no \"Weather report\", no city name)\n    T                       # switch terminal sequences off (no colors)\n\nPNG options:\n\n    /paris.png              # generate a PNG file\n    p                       # add frame around the output\n    t                       # transparency 150\n    transparency=...        # transparency from 0 to 255 (255 = not transparent)\n    background=...          # background color in form RRGGBB, e.g. 00aaaa\n\nOptions can be combined:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # in PNG the file mode are specified after _\n    /Rome_0pq_lang=it.png   # long options are separated with underscore\n\nLocalization:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nSupported languages:\n\n    FULL_TRANSLATION (supported)\n    PARTIAL_TRANSLATION (in progress)\n\nSpecial URLs:\n\n    /:help                  # show this page\n    /:bash.function         # show recommended bash function wttr()\n    /:translation           # show the information about the translators\n\n"
  },
  {
    "path": "share/iterm2.txt",
    "content": "\u001b]1337;File=name=TnVyZW1iZXJnLnBuZw==;size=46226;inline=1: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\u0007\n"
  },
  {
    "path": "share/list-of-iata-codes.txt",
    "content": "GKA\nMAG\nHGU\nLAE\nPOM\nWWK\nUAK\nGOH\nSFJ\nTHU\nAEY\nEGS\nHFN\nHZK\nIFJ\nKEF\nPFJ\nRKV\nSIJ\nVEY\nYAM\nYAV\nYAW\nYAY\nYAZ\nYBB\nYBC\nYBG\nYBK\nYBL\nYBR\nYCB\nYCD\nYCG\nYCH\nYCL\nYCO\nYCT\nYCW\nYCY\nYZS\nYDA\nYDB\nYDC\nYDF\nYDL\nYDN\nYDQ\nYEG\nYEK\nYEN\nYET\nYEU\nYEV\nYFB\nYFC\nYFO\nYFR\nYFS\nYGK\nYGL\nYGP\nYGQ\nYGR\nYHB\nYHD\nYHI\nYHK\nYHM\nYHU\nYHY\nYHZ\nYIB\nYIO\nYJN\nYJT\nYKA\nYKF\nYKL\nYKY\nYKZ\nYLD\nYLJ\nYLL\nYLT\nYLW\nYMA\nYMJ\nYMM\nYMO\nYMW\nYMX\nYNA\nYND\nYNM\nYOC\nYOD\nYOJ\nYOW\nYPA\nYPE\nYPG\nYPL\nYPN\nYPQ\nYPR\nYPY\nYQA\nYQB\nYQF\nYQG\nYQH\nYQK\nYQL\nYQM\nYQQ\nYQR\nYQT\nYQU\nYQV\nYQW\nYQX\nYQY\nYQZ\nYRB\nYRI\nYRJ\nYRM\nYRT\nYSB\nYSC\nYSJ\nYSM\nYSR\nYSU\nYSY\nYTE\nYTH\nYTR\nYTS\nYTZ\nYUB\nYUL\nYUT\nYUX\nYUY\nYVC\nYVG\nYVM\nYVO\nYVP\nYVQ\nYVR\nYVT\nYVV\nYWA\nYWG\nYWK\nYWL\nYWY\nYXC\nYXD\nYXE\nYXH\nYXJ\nYXL\nYXP\nYXR\nYXS\nYXT\nYXU\nYXX\nYXY\nYYB\nYYC\nYYD\nYYE\nYYF\nYYG\nYYH\nYYJ\nYYL\nYYN\nYYQ\nYYR\nYYT\nYYU\nYYW\nYYY\nYYZ\nYZD\nYZE\nYZF\nYZH\nYZP\nYZR\nYZT\nYZU\nYZV\nYZW\nYZX\nZFA\nZFM\nBJA\nALG\nDJG\nQFD\nVVZ\nTMR\nGJL\nAAE\nCZL\nTEE\nHRM\nTID\nTIN\nQAS\nTAF\nTLM\nORN\nMUW\nAZR\nBSK\nELG\nGHA\nHME\nINZ\nTGR\nLOO\nTMX\nOGX\nIAM\nCOO\nOUA\nBOY\nACC\nTML\nNYI\nTKD\nABJ\nBYK\nDJO\nHGO\nMJC\nSPY\nASK\nABV\nAKR\nBNI\nCBQ\nENU\nQUS\nIBA\nILR\nJOS\nKAD\nKAN\nMIU\nMDI\nLOS\nMXJ\nPHC\nSKO\nYOL\nZAR\nMFQ\nNIM\nTHZ\nAJY\nZND\nMIR\nTUN\nGAF\nGAE\nDJE\nEBM\nSFA\nTOE\nLRL\nLFW\nANR\nBRU\nCRL\nQKT\nLGG\nOST\nAOC\nBBH\nSXF\nDRS\nERF\nFRA\nFMO\nHAM\nTHF\nCGN\nDUS\nMUC\nNUE\nLEJ\nSCN\nSTR\nTXL\nHAJ\nBRE\nQEF\nHHN\nMHG\nXFW\nKEL\nLBC\nZCA\nESS\nMGL\nPAD\nDTM\nAGB\nOBF\nRBM\nFDH\nSZW\nZSN\nBYU\nHOQ\nZNV\nZQF\nZQC\nZQW\nZQL\nBWE\nKSF\nBRV\nEME\nWVN\nBMK\nNRD\nFLF\nGWT\nKDL\nURE\nEPU\nTLL\nTAY\nENF\nKEV\nHEM\nHEL\nHYV\nIVL\nJOE\nJYV\nKAU\nKEM\nKAJ\nKOK\nKAO\nKTT\nKUO\nLPP\nMHQ\nMIK\nOUL\nPOR\nRVN\nSVL\nSOT\nTMP\nTKU\nQVY\nVAA\nVRK\nBFS\nENK\nBHD\nLDY\nBHX\nCVT\nGLO\nMAN\nNQY\nLYE\nYEO\nCWL\nSWS\nBRS\nLPL\nLTN\nPLH\nBOH\nSOU\nQLA\nACI\nGCI\nJER\nESH\nBQH\nLGW\nLCY\nFAB\nBBS\nLHR\nSEN\nLYX\nMSE\nCAX\nBLK\nHUY\nBWF\nLBA\nCEG\nIOM\nNCL\nMME\nEMA\nKOI\nLSI\nWIC\nABZ\nINV\nGLA\nEDI\nILY\nPIK\nBEB\nSCS\nDND\nSYY\nTRE\nADX\nLMO\nCBG\nNWI\nSTN\nEXT\nFZO\nOXF\nMHZ\nFFD\nBZZ\nODH\nNHT\nQCY\nBEQ\nHRT\nWTN\nKNF\nMPN\nAMS\nMST\nEIN\nGRQ\nDHR\nLEY\nLWR\nRTM\nUTC\nENS\nLID\nWOE\nORK\nGWY\nDUB\nNOC\nKIR\nSNN\nSXL\nWAT\nAAR\nBLL\nCPH\nEBJ\nKRP\nODE\nRKE\nRNN\nSGD\nSKS\nTED\nFAE\nSTA\nAAL\nLUX\nAES\nANX\nALF\nBNN\nBOO\nBGO\nBJF\nKRS\nBDU\nNorway\nVDB\nFRO\nOSL\nHAU\nHAA\nKSU\nKKN\nFAN\nMOL\nMJF\nLKL\nNTB\nOLA\nRRS\nRYG\nNorway\nSKE\nSRP\nSSJ\nTOS\nNorway\nTRD\nSVG\nGDN\nKRK\nKTW\nPOZ\nRZE\nSZZ\nOSP\nWAW\nWRO\nIEG\nRNB\nGOT\nJKG\nLDK\nGSE\nKVB\nTHN\nKSK\nMXX\nNYO\nKID\nJLD\nOSK\nKLR\nMMX\nHAD\nVXO\nEVG\nGEV\nHUV\nKRF\nLYC\nSDL\nOER\nKRN\nSFT\nUME\nVHM\nAJR\nORB\nVST\nLLA\nARN\nBMA\nBLE\nHLF\nGVX\nLPI\nNRK\nVBY\nSPM\nRMS\nGHF\nZCN\nZNF\nGKE\nRLG\nFEL\nIGS\nGUT\nALJ\nAGZ\nBIY\nBFN\nCPT\nDUR\nELS\nGCJ\nGRJ\nHDS\nJNB\nKIM\nKMH\nKLZ\nHLA\nLAY\nMGH\nMEZ\nNCS\nDUH\nPLZ\nPHW\nPZB\nNTY\nPTG\nUTW\nRCB\nROD\nSBU\nSIS\nSZK\nLTA\nULD\nUTN\nUTT\nVRU\nVIR\nPRY\nWEL\nFRW\nJWA\nBBK\nMUB\nGBE\nPKW\nBZV\nFTX\nOUE\nPNR\nMTS\nBGF\nBBT\nBSG\nSSG\nASI\nMRU\nRRG\nTKC\nDLA\nMVR\nFOM\nNGE\nGOU\nBFX\nBPC\nYAO\nLVI\nLUN\nMFU\nNLA\nKIW\nHAH\nNWA\nAJN\nDZA\nRUN\nZSE\nTNR\nZVA\nSMS\nTMM\nMOQ\nDIE\nWMR\nZWA\nAMB\nANM\nHVA\nMJN\nNOS\nBPY\nWMN\nSVB\nVOH\nWAI\nIVA\nFTU\nWFI\nRVA\nWVK\nMNJ\nMXM\nTLE\nSSY\nBUG\nCAB\nNOV\nSVP\nLAD\nMEG\nSPP\nGXG\nPBN\nVHC\nSZA\nSDD\nLUO\nUGO\nXGN\nOYE\nOKN\nLBQ\nBMM\nPOG\nOMB\nMKU\nLBV\nMVB\nPCP\nTMS\nBEW\nINH\nVXC\nMPM\nMZB\nMNC\nAPL\nPOL\nUEL\nTET\nVNX\nDES\nSEZ\nPRI\nAEH\nMQQ\nNDJ\nFYT\nBUQ\nBFO\nVFA\nHRE\nKAB\nMVZ\nGWE\nWKM\nBLZ\nKGJ\nLLW\nZZU\nMSU\nFIH\nNLO\nMNB\nFDU\nKKW\nMDK\nBDT\nGMA\nLIQ\nFKI\nIRP\nBUX\nBKY\nGOM\nKND\nFBM\nKWZ\nFMI\nKMN\nKGA\nMJM\nBKO\nGAQ\nKYS\nMZI\nTOM\nBJL\nFUE\nVDE\nSPC\nLPA\nACE\nTFS\nTFN\nMLN\nFNA\nMLW\nROB\nAGA\nTTA\nFEZ\nERH\nMEK\nOUD\nRBA\nCMN\nRAK\nNNA\nOZZ\nAHU\nTTU\nTNG\nZIG\nCSK\nKLC\nDKR\nXLS\nBXE\nKGG\nTUD\nIEO\nTIY\nKFA\nEMN\nKED\nNKC\nSEY\nATR\nNDB\nFIG\nFAA\nLEK\nSID\nBVC\nMMO\nSNE\nVXE\nADD\nAMH\nAXU\nBJR\nDIR\nGMB\nGDQ\nJIM\nLLI\nMQX\nASO\nBJM\nHGA\nBBO\nKMU\nALY\nABS\nCAI\nHRG\nEGR\nLXR\nMUH\nPSD\nSKV\nASW\nELT\nEDL\nKIS\nKTL\nLOK\nLAU\nMBA\nWIL\nWJR\nGHT\nAKF\nBEN\nSEB\nTIP\nLTD\nGYI\nKGL\nKME\nDOG\nELF\nKSL\nEBD\nJUB\nMAK\nKRT\nARK\nDAR\nDOD\nIRI\nJRO\nLKY\nMYW\nMWZ\nPMA\nTGT\nZNZ\nEBB\nSRT\nTIA\nBOJ\nGOZ\nPDV\nSOF\nVAR\nLCA\nPFO\nAKT\nDBV\nOSI\nPUY\nRJK\nSPU\nZAG\nZAD\nALC\nLEI\nOVD\nODB\nBIO\nBCN\nBJZ\nLCG\nGRO\nGRX\nIBZ\nXRY\nMJV\nMAD\nAGP\nMAH\nOZP\nPNA\nREU\nSLM\nEAS\nSCQ\nLEU\nTOJ\nVLC\nVLL\nVIT\nVGO\nSDR\nZAZ\nSVQ\nCQF\nLTQ\nAGF\nBOD\nEGC\nCNG\nPIS\nMCU\nLIG\nNIT\nTLS\nPUF\nLDE\nANG\nBVE\nPGX\nBIQ\nXAC\nLBI\nDCM\nRDZ\nRYN\nRCO\nCMR\nDLE\nOBS\nLPY\nXBK\nXVF\nXMU\nETZ\nBIA\nCLY\nFSC\nAJA\nSOZ\nAUF\nCMF\nCFE\nBOU\nXCD\nQNJ\nLYS\nQNX\nRNE\nNCY\nGNB\nVAF\nVHY\nAUR\nCHR\nLYN\nQXB\nCEQ\nEBU\nCCF\nMRS\nNCE\nPGF\nCTT\nMPL\nBZR\nAVN\nMEN\nBVA\nLEH\nORE\nXCR\nURO\nTUF\nCET\nLVA\nLBG\nCSF\nCDG\nTNF\nORY\nPOX\nQYR\nNVS\nLIL\nBES\nCER\nDNR\nGFR\nDOL\nLRT\nEDM\nCFR\nLME\nRNS\nLAI\nUIP\nNTE\nSBK\nMXN\nVNE\nSNR\nBSL\nDIJ\nMZM\nEPL\nENC\nRHE\nSXB\nTLN\nFNI\nMQC\nFSP\nPYR\nAGQ\nAXD\nVOL\nJKH\nIOA\nHER\nKSO\nKIT\nEFL\nKLX\nKGS\nAOK\nCFU\nKSJ\nKVA\nKZI\nLRS\nLXS\nLRA\nJMK\nMJT\nPVK\nRHO\nGPA\nCHQ\nJSI\nSMI\nJTR\nJSH\nSKU\nSKG\nZTH\nBUD\nDEB\nCRV\nBRI\nFOG\nTAR\nLCC\nPSR\nBDS\nSUF\nCTA\nLMP\nPNL\nPMO\nREG\nTPS\nNSY\nAHO\nDCI\nCAG\nOLB\nTTB\nMXP\nBGY\nTRN\nALL\nGOA\nLIN\nPMF\nQPZ\nCUF\nAVB\nBZO\nBLQ\nTSF\nFRL\nVBS\nTRS\nRMI\nVIC\nQPA\nVRN\nVCE\nSAY\nCIA\nFCO\nEBA\nQLT\nNAP\nPSA\nFLR\nGRS\nPEG\nLJU\nMBX\nPOW\nKLV\nOSR\nPED\nPRV\nPRG\nBRQ\nTLV\nBEV\nETH\nHFA\nRPN\nVDA\nSDV\nMLA\nGRZ\nINN\nLNZ\nSZG\nVIE\nSMA\nBGC\nFLW\nFAO\nGRW\nHOR\nTER\nPDL\nPIX\nOPO\nPXO\nLIS\nSJZ\nVRL\nOMO\nSJJ\nARW\nBCM\nBAY\nBBU\nCND\nCLJ\nCSB\nCRA\nIAS\nOMR\nOTP\nSBZ\nSUJ\nSCV\nTCE\nTGM\nTSR\nGVA\nSIR\nEML\nLUG\nBRN\nZRH\nACH\nSMV\nESB\nANK\nADA\nUAB\nAFY\nAYT\nGZT\nKYA\nMLX\nMZH\nVAS\nASR\nDNZ\nIST\nBZI\nBDM\nESK\nADB\nIGL\nDLM\nBXN\nEZS\nDIY\nERC\nERZ\nTZX\nVAN\nBAL\nBZY\nKIV\nOHD\nSKP\nGIB\nBEG\nINI\nTGD\nPRN\nTIV\nBTS\nKSC\nPZY\nSLD\nTAT\nNCA\nPLS\nXSC\nEPS\nBRX\nLRM\nPUJ\nPOP\nSDQ\nSTI\nCBV\nGUA\nLCE\nSAP\nGJA\nRTB\nTEA\nTGU\nOCJ\nKIN\nMBJ\nPOT\nKTP\nACA\nNTR\nAGU\nHUX\nCVJ\nCME\nCUL\nCTM\nCEN\nCPE\nCJS\nCUU\nCVM\nCZM\nDGO\nTPQ\nESE\nGDL\nGYM\nTCN\nHMO\nCLQ\nISJ\nSLW\nLZC\nLMM\nBJX\nLAP\nLTO\nMAM\nMID\nMXL\nMLM\nMTT\nLOV\nMEX\nMTY\nMZT\nNOG\nNLD\nOAX\nPAZ\nPBC\nPCA\nPPE\nPDS\nUPN\nPVR\nPXM\nQRO\nREX\nSJD\nSFH\nSLP\nTXA\nTRC\nTGZ\nTIJ\nTAM\nTSL\nTLC\nTAP\nCUN\nVSA\nVER\nZCL\nZIH\nZMM\nZLO\nBEF\nMGA\nPUZ\nBOC\nCHX\nDAV\nBLB\nPAC\nPTY\nOTR\nGLF\nLIR\nLIO\nNOB\nSJO\nPMZ\nXQP\nSAL\nCAP\nPAP\nBCA\nBYM\nAVI\nCCC\nCFG\nCYO\nCMW\nSCU\nGAO\nHAV\nHOG\nLCL\nMOA\nMZO\nGER\nUPB\nSNU\nVRA\nVTU\nCYB\nGCM\nASD\nMHH\nSAQ\nAXP\nTCB\nCCZ\nBIM\nGGT\nELH\nGHB\nRSD\nFPO\nIGA\nLGI\nSML\nMYG\nNAS\nZSA\nBZE\nAIT\nRAR\nNAN\nSUV\nTBU\nVAV\nTRW\nTBF\nWLS\nAPW\nPPG\nRUR\nTUB\nAAA\nTIH\nREA\nFAV\nXMH\nGMR\nKKR\nMKP\nPKP\nTKP\nAXR\nMVT\nTKX\nNHV\nBOB\nRGI\nHUH\nMOZ\nHOI\nMAU\nRFP\nVLI\nKNQ\nKOC\nLIF\nGEA\nMEE\nTOU\nUVE\nNOU\nAKL\nTUO\nAMZ\nCHC\nCHT\nDUD\nGIS\nHKK\nHLZ\nKKE\nKAT\nALR\nMON\nTEU\nMRO\nNPL\nNSN\nIVC\nOAM\nPMR\nPPQ\nZQN\nROT\nTRG\nTIU\nBHE\nWKA\nWHK\nWLG\nWRE\nWSZ\nWAG\nHEA\nJAA\nKBL\nKDH\nMMZ\nMZR\nUND\nBAH\nAHB\nHOF\nABT\nBHH\nDMM\nDHA\nGIZ\nELQ\nURY\nHAS\nJED\nHBT\nMED\nEAM\nAQI\nRAH\nRUH\nRAE\nSHW\nSLF\nTUU\nTIF\nTUI\nEJH\nYNB\nABD\nQMJ\nMRX\nAWZ\nBUZ\nKIH\nBDH\nKSH\nSDG\nIFN\nRAS\nTHR\nBND\nKER\nXBJ\nRZR\nSYZ\nTBZ\nAZD\nACZ\nZBR\nZAH\nAMM\nADJ\nAQJ\nOMF\nKWI\nBEY\nAUH\nAZI\nDXB\nFJR\nRKT\nSHJ\nKHS\nMSH\nMCT\nSLL\nTTH\nLYP\nGWD\nGIL\nKHI\nLHE\nMFG\nMJD\nMUX\nWNS\nPJG\nPSI\nPEW\nUET\nRYK\nISB\nRAZ\nSKZ\nSDT\nSUL\nBDN\nPZH\nBSR\nALP\nDAM\nDEZ\nLTK\nPMS\nCIS\nROP\nSPN\nUAM\nGUM\nTIQ\nMAJ\nKWA\nCXI\nMDY\nTKK\nPNI\nROR\nKSA\nYAP\nKNH\nTTT\nGNI\nKHH\nCYI\nKYD\nRMQ\nTNN\nMZG\nPIF\nTSA\nTPE\nWOT\nHUN\nNRT\nMMJ\nIBR\nIWO\nSHM\nOBO\nCTS\nHKD\nSPK\nMMB\nSHB\nWKJ\nIKI\nUBJ\nTSJ\nMBE\nAKJ\nOIR\nRIS\nKUM\nFUJ\nFUK\nTNE\nKOJ\nKMI\nOIT\nKKJ\nKMJ\nNGS\nASJ\nTKN\nKMQ\nOKI\nTOY\nHIJ\nOKJ\nIZO\nYGJ\nKCZ\nMYJ\nITM\nTTJ\nTKS\nTAK\nAOJ\nGAJ\nSDS\nHNA\nAXT\nMSJ\nSDJ\nHAC\nOIM\nHND\nOKO\nKWJ\nCHN\nRSU\nSHO\nKAG\nCJU\nPUS\nUSN\nSSN\nOSN\nGMP\nSWU\nKPO\nTAE\nYEC\nOKA\nDNA\nISG\nUEO\nMMD\nMMY\nKTD\nSHI\nRNJ\nOGN\nMNL\nCBO\nCGY\nPAG\nGES\nZAM\nBAG\nSJI\nTAC\nBCD\nDGT\nMPH\nILO\nKLO\nPPS\nCOC\nGHU\nPRA\nROS\nSFN\nAEP\nCOR\nLPG\nMDZ\nLGS\nAFA\nCTC\nSDE\nIRJ\nTUC\nUAQ\nRCU\nVDR\nLUQ\nCNQ\nRES\nFMA\nIGR\nAOL\nPSS\nSLA\nJUJ\nORA\nEHL\nCRD\nEQS\nREL\nVDM\nPMY\nPUD\nRGA\nRGL\nUSH\nULA\nPMQ\nRZA\nBHI\nMDQ\nNQN\nRSA\nBRC\nTDL\nVLG\nCPC\nCDJ\nAQA\nAJU\nAFL\nARU\nBEL\nBGX\nPLU\nBFH\nBSB\nBAU\nBVB\nCAC\nCNF\nCGR\nXAP\nCLN\nCCM\nCAW\nCMG\nCWB\nCRQ\nCXJ\nCGB\nCZS\nPPB\nMAO\nIGU\nFLN\nFEN\nFOR\nGIG\nGYN\nGRU\nATM\nITB\nIOS\nIPN\nIMP\nJDF\nJPA\nJOI\nCPV\nVCP\nLIP\nLDB\nLAZ\nMAB\nMGF\nMOC\nPLL\nMCZ\nMCP\nMVF\nMNX\nNVT\nGEL\nNAT\nPOA\nPOO\nPFB\nPET\nPNZ\nPNB\nPMG\nPVH\nRBR\nREC\nSDU\nRAO\nSTU\nSJK\nSLZ\nCGH\nSJP\nSSZ\nSSA\nTMT\nTHE\nTFF\nTBT\nTUR\nSJL\nPAV\nURG\nUDI\nUBA\nVAG\nBVH\nVIX\nQPS\nARI\nBBA\nCCH\nCJC\nPUQ\nGXQ\nIQQ\nSCL\nANF\nWPR\nLSQ\nWPU\nCCP\nIPC\nZOS\nLSC\nZCO\nPMC\nWCH\nZAL\nATF\nOCC\nCUE\nGPS\nGYE\nLTX\nXMS\nMCH\nMEC\nPVO\nUIO\nETR\nSNC\nTPC\nTUA\nASU\nCIO\nAXM\nPUU\nBGA\nBOG\nBAQ\nBSC\nBUN\nCUC\nCTG\nCLO\nTCO\nCZU\nEJA\nFLA\nGPI\nIBE\nIPI\nAPO\nLET\nEOH\nMGN\nMTR\nMVP\nMZL\nNVA\nOCV\nOTU\nPCR\nPEI\nPPN\nPSO\nPVA\nMDE\nRCH\nSJE\nSMR\nADZ\nSVI\nTME\nAUC\nUIB\nULQ\nVUP\nVVC\nBJO\nCBB\nCIJ\nLPB\nPOI\nPSZ\nSRE\nTJA\nTDD\nVVI\nBYC\nPBM\nCAY\nPCL\nCHM\nCIX\nAYP\nANS\nATA\nLIM\nJJI\nJUL\nTBP\nYMS\nCHH\nIQT\nAQP\nTRU\nPIO\nTPP\nTCQ\nPEM\nPIU\nTYL\nCUZ\nMVD\nSTY\nAGV\nAAO\nBLA\nBNS\nBRM\nCBL\nCAJ\nCUP\nCZE\nCUM\nGUI\nGUQ\nLSP\nLFR\nMAR\nMRD\nPMV\nCCS\nMUN\nPYH\nPBL\nPZO\nSVZ\nSNV\nSTD\nSFD\nSOM\nSTB\nTUV\nVLN\nVLV\nVDP\nLTM\nANU\nBGI\nDCF\nDOM\nFDF\nSFG\nPTP\nGND\nSTT\nSTX\nBQN\nFAJ\nSIG\nMAZ\nPSE\nSJU\nSKB\nSLU\nUVF\nAUA\nBON\nCUR\nEUX\nSXM\nAXA\nTAB\nPOS\nEIS\nCIW\nMQS\nSVD\nALA\nBXH\nTSE\nDMB\nFRU\nOSS\nCIT\nURA\nPWQ\nPLX\nAKX\nGYD\nYKS\nMJZ\nBQS\nKHV\nPVS\nGDX\nPWE\nPKC\nUUS\nVVO\nHTA\nBTK\nIKT\nUUD\nKBP\nDOK\nDNK\nSIP\nIEV\nLWO\nODS\nLED\nMMK\nGME\nVTB\nKGD\nMHP\nMSQ\nABA\nBAX\nKEJ\nOMS\nKRR\nMCX\nMRV\nSTW\nROV\nAER\nASF\nVOG\nCEK\nMQF\nNJC\nPEE\nSGC\nSVX\nASB\nKRW\nCRZ\nDYU\nBHK\nSKD\nTAS\nBZK\nSVO\nKLD\nVOZ\nVKO\nSCW\nKZN\nREN\nUFA\nKUF\nAMD\nAKD\nIXU\nBOM\nPAB\nBHJ\nIXG\nBDQ\nBHO\nBHU\nNMB\nGOI\nIDR\nJLR\nJGA\nIXY\nHJR\nKLH\nIXK\nNAG\nISK\nPNQ\nPBD\nRAJ\nRPR\nSSE\nSTV\nUDR\nCMB\nACJ\nRML\nGOY\nJAF\nTRR\nPNH\nREP\nTNX\nIXA\nAJL\nIXB\nBBI\nCCU\nCOH\nDBD\nGAY\nIMF\nIXW\nJRH\nIXH\nIXS\nIXI\nDIB\nPAT\nIXR\nRRK\nVTZ\nCXB\nCGP\nIRD\nJSR\nRJH\nSPD\nZYL\nDAC\nHKG\nAGR\nIXD\nATQ\nVNS\nKUU\nIXC\nDED\nDEL\nGWL\nJDH\nJAI\nJSA\nIXJ\nKNU\nKTU\nLUH\nIXL\nLKO\nPGH\nSXR\nTNI\nLPQ\nPKZ\nZVK\nVTE\nMFM\nBWA\nKTM\nPKR\nSIF\nBIR\nAGX\nBLR\nBEP\nVGA\nCJB\nCOK\nCCJ\nCDP\nBPM\nIXM\nIXE\nMAA\nIXZ\nPNY\nRJA\nTIR\nTRZ\nTRV\nPBH\nMLE\nDMK\nUTP\nLPT\nPRH\nHHQ\nPHS\nNAW\nKBV\nPAN\nUSM\nHKT\nUNN\nHDY\nTST\nUTH\nSNO\nLOE\nDAD\nHAN\nNHA\nHUI\nPQC\nSGN\nNYU\nHEH\nKET\nKYP\nLSH\nMDL\nMGZ\nMYT\nMOG\nPBU\nAKY\nSNW\nTHL\nRGN\nUPG\nBIK\nNBX\nTIM\nDJJ\nWMX\nMKQ\nGTO\nPLW\nMDC\nPSJ\nOTI\nTTE\nLUW\nIndonesia\nFKQ\nKNG\nBXB\nMKW\nSOQ\nBTU\nKCH\nLMN\nMUR\nMYY\nSBW\nLDU\nBKI\nLBU\nTWU\nBWN\nPKU\nDUM\nCGK\nGNS\nMES\nKTG\nPNK\nDJB\nBKS\nPLM\nRGT\nBTJ\nAOR\nKBR\nKUA\nKTE\nIPH\nJHB\nKUL\nLGK\nMKZ\nTGG\nPEN\nDIL\nQPG\nXSP\nSIN\nABM\nASP\nBNE\nOOL\nCNS\nCTL\nISA\nMCY\nMKY\nPPP\nROK\nTSV\nWEI\nAVV\nABX\nMEB\nHBA\nLST\nMBW\nMEL\nAustralia\nADL\nJAD\nKTA\nKGI\nKNX\nLEA\nPHE\nPER\nUMR\nXCH\nBWU\nCBR\nCFS\nCDU\nDBO\nNLK\nSYD\nTMW\nWGA\nPEK\nHLD\nTSN\nTYN\nCAN\nCSX\nKWL\nNNG\nSZX\nCGO\nWUH\nFNJ\nLHW\nXIY\nULN\nJHG\nKMG\nXMN\nKHN\nFOC\nHGH\nNGB\nNKG\nHFE\nTAO\nSHA\nYNT\nCKG\nKWE\nCTU\nXIC\nKHG\nHTN\nURC\nHRB\nMDG\nDLC\nPVG\nTOD\nSZB\nNTQ\nHBE\nBTI\nLUR\nPIZ\nITO\nORL\nBTT\nZ84\nUTO\nFYU\nSVW\nFRN\nTLJ\nCZF\nBED\nSNP\nEHM\nSTG\nILI\nPTU\nBMX\nOSC\nOAR\nMHR\nBYS\nNXP\nFSM\nMRI\nGNT\nPNC\nSVN\nGFK\nPBF\nNSE\nHNM\nPRC\nTTN\nBOS\nSUU\nRME\nENV\nBFM\nOAK\nOMA\nNOW\nOGG\nICT\nMCI\nMSN\nDLG\nHRO\nPHX\nBGR\nFXE\nGGG\nAND\nGEG\nHWO\nSFO\nCTB\nARA\nGNV\nMEM\nDUG\nBIG\nCNW\nANN\nCAR\nLRF\nHUA\nPOB\nDHT\nDLF\nLAX\nANB\nCLE\nDOV\nCVG\nFME\nNID\nHON\nJNU\nLFT\nEWR\nBOI\nINS\nGCK\nMOT\nHHI\nMXF\nDAL\nFCS\nHLN\nNKX\nLUF\nHHR\nHUL\nEND\nNTD\nEDW\nLCH\nKOA\nMYR\nNLC\nACK\nFAF\nHOP\nDCA\nNHK\nPSX\nBYH\nACY\nTIK\nPUB\nPQI\nGRF\nADQ\nUPP\nFLL\nMKO\nINL\nSLC\nCDS\nBIX\nLSF\nFRI\nMDT\nLNK\nLAN\nMUE\nMSS\nHKY\nSPG\nFMY\nIAH\nMLT\nADW\nINT\nVCV\nCEW\nGTB\nPHN\nBFL\nELP\nHRL\nCAE\nDMA\nNPA\nPNS\nRDR\nHOU\nBKF\nORT\nPAQ\nPIT\nBRW\nEFD\nNUW\nALI\nVAD\nMIA\nSEA\nCHA\nBDR\nJAN\nGLS\nLGB\nHDH\nIPT\nIND\nSZL\nAKC\nGWO\nHPN\nFOK\nJBR\nLNA\nNZY\nBIF\nYUM\nCNM\nDLH\nBET\nLOU\nFHU\nLIH\nHUF\nHVR\nMWH\nMPV\nRIC\nSHV\nCDV\nORF\nBPT\nSAV\nHIF\nOME\nPIE\nMNM\nCXO\nSCC\nSAT\nROC\nCOF\nTEB\nRCA\nRDU\nDAY\nENA\nMLC\nIAG\nCFD\nPHF\nESF\nLTS\nTUS\nMIB\nBAB\nIKK\nGSB\nPVD\nSBY\nRIU\nBUR\nDTW\nTPA\nPMB\nPOE\nEIL\nHIB\nLFK\nMAF\nGRB\nADM\nWRI\nSBO\nAGS\nISN\nLIT\nSWF\nBDE\nSAC\nHOM\nTBN\nMGE\nSKA\nHTL\nPAM\nDFW\nMLB\nTCM\nAUS\nLCK\nMQT\nTYS\nHLR\nSTL\nMIV\nSPS\nLUK\nATL\nMER\nMCC\nGRR\nINK\nFAT\nVRB\nIPL\nBNA\nLRD\nEDF\nOTZ\nAOO\nDYS\nELD\nLGA\nTLH\nDPA\nACT\nAUG\nINJ\nMKL\nMKK\nFTK\nSJT\nCXL\nCIC\nBTV\nJAX\nDRO\nIAD\nCLL\nSFF\nMKE\nABI\nCOU\nPDX\nTNT\nPBI\nFTW\nOGS\nBFI\nSKF\nHNL\nDSM\nEWN\nSAN\nMLU\nSSC\nONT\nGVT\nROW\nDET\nBRO\nDHN\nWWD\nMTC\nFMN\nCRP\nSYR\nNQX\nMDW\nSJC\nHOB\nPNE\nDEN\nPHL\nSUX\nMCN\nTCS\nPMD\nRND\nNJK\nCMH\nFYV\nFSI\nPNM\nFFO\nGAL\nMWL\nIAB\nNBG\nBFT\nTXK\nPBG\nAPG\nTCC\nANC\nGRK\nZUN\nBLI\nNQA\nEKN\nHFD\nSFZ\nMOB\nNUQ\nSAF\nBKH\nDRI\nBSF\nOLS\nMCF\nBLV\nOPF\nDRT\nRSW\nAKN\nMUI\nJHM\nJFK\nHST\nRAL\nFLV\nWAL\nHMN\nNXX\nCYS\nSCK\nCHS\nRNO\nKTN\nYIP\nVBG\nBHM\nNEL\nLSV\nRIV\nMOD\nSMF\nUGN\nCOS\nBUF\nSKY\nPAE\nMUO\nCDC\nBDL\nMFE\nNGU\nCEF\nLBB\nORD\nBCT\nFAI\nNYG\nCVS\nNGF\nOFF\nGKN\nART\nPSP\nAMA\nFOD\nBAD\nFOE\nCOT\nILM\nUnited States\nTYR\nBWI\nHBR\nLNY\nAEX\nWSD\nCDB\nTUL\nSIT\nISP\nMSP\nILG\nDUT\nMSY\nPWM\nOKC\nALB\nVDZ\nLFI\nSNA\nCBM\nTMB\nNTU\nGUS\nCPR\nVPS\nSEM\nEYW\nCLT\nLAS\nMCO\nFLO\nGTF\nYNG\nFBK\nMMV\nWRB\nBKK\nNAH\nTTR\nKDI\nSBG\nMLG\nBDO\nCBN\nJOG\nCXP\nPCB\nSRG\nBTH\nTJQ\nPGK\nTNJ\nSIQ\nBDJ\nPKN\nPKY\nMOF\nENE\nRTG\nKOE\nLBJ\nBPN\nTRK\nSRI\nAMI\nBMU\nWGP\nSUB\nSOC\nICN\nCNX\nCEI\nNST\nNAK\nKOP\nUBP\nKKC\nTHS\nDPS\nATH\nNGO\nUKB\nPUW\nLWS\nELM\nITH\nMRY\nSBA\nDAB\nLPX\nRIX\nSQQ\nHLJ\nKUN\nPLQ\nVNO\nPNV\nEVN\nLWN\nASA\nASM\nMSW\nGZA\nBUS\nKUT\nTBS\nRIY\nTAI\nHOD\nADE\nAXK\nAAY\nSAH\nBHN\nSCT\nFMM\nNAV\nEZE\nEBL\nEMD\nHEW\nKIX\nTAG\nJAV\nJCH\nJEG\nPMI\nDRW\nURT\nTKA\nGZM\nHVN\nAVL\nGSO\nFSD\nAYQ\nMHT\nAPF\nRDN\nSDF\nCHO\nROA\nLEX\nEVV\nABQ\nBZN\nBIL\nBTM\nTVC\nFRS\nBHB\nRKD\nJAC\nRFD\nDME\nSYX\nMFN\nLJG\nGSP\nBMI\nGPT\nAZO\nTOL\nFWA\nDEC\nCID\nLSE\nCWA\nPIA\nATW\nRST\nCMI\nMHK\nKGC\nHVB\nDLU\nMZV\nSSH\nFKL\nNBO\nSEU\nFTE\nARM\nGJT\nSGU\nDWH\nS46\nSRQ\nBDA\nVNY\nMLI\nPFN\nHIR\nPPT\nINU\nFUN\nOVB\nXKH\nBIS\nTEX\nINC\nHGN\nRAP\nCLD\nFNT\nDVO\nFNC\nSTM\nKOS\nYOA\nNPE\nLEV\nLXA\nRDD\nEUG\nIDA\nMFR\nKBZ\nRDM\nPCN\nWDH\nYWH\nTNA\nCZX\nYBP\nTJM\nCAK\nHSV\nPKB\nMGM\nTRI\nPAH\nJIB\nHAK\nMFA\nPGA\nUII\nFCA\nMBS\nBGM\nBGW\nNNT\nROI\nBFV\nTDX\nBLH\nCRK\nSDK\nLXG\nODY\nSHE\nMNI\nPSG\nLYA\nXUZ\nMWQ\nKHM\nDLI\nVKG\nCAH\nVCL\nTBB\nPYY\nBWK\nNSI\nCKY\nAAH\nFKB\nSFB\nJST\nLUA\nBHP\nLDN\nJMO\nNGX\nPPL\nRUM\nDNP\nRUK\nJUM\nTPJ\nTMI\nSKH\nIMK\nDOP\nBJH\nDHI\nMWX\nJTY\nJIK\nJKL\nMLO\nJNX\nPAS\nKZS\nRMF\nNRN\nUSU\nBXU\nDPL\nLAO\nLGP\nOZC\nCEB\nNOE\nJUI\nBPS\nPMW\nCLV\nMSO\nBKQ\nBDB\nGCN\nSGR\nHIS\nAPA\nCVN\nFST\nLVS\nIWS\nLHX\nLRU\nBKD\nTPL\nOZA\nKDM\nLAK\nYWJ\nZFN\nYGH\nTAH\nYPC\nSRZ\nSAB\nEGE\nSKN\nCGF\nMFD\nCSG\nLAW\nFNL\nFLG\nTVL\nTWF\nMVY\nCON\nGON\nSTC\nBPE\nGTR\nGOJ\nHQM\nERI\nHYA\nSDX\nMGW\nCRW\nAVP\nBJI\nTHG\nFGI\nBNK\nFAR\nMKC\nRBE\nGCC\nTOF\nPHY\nCJM\nJZH\nSWA\nGEO\nAGT\nOGL\nKAI\nDNH\nAOI\nCPO\nTCP\nLYB\nBJV\nTBJ\nSAW\nSCE\nBME\nNTL\nKLU\nHFT\nHVG\nMEH\nVDS\nIKA\nMHD\nUIK\nMEI\nSPI\nCEZ\nHDN\nGUP\nLBL\nLAA\nGLD\nCOD\nNorway\nISC\nSGF\nNVK\nBVG\nNorway\nNSK\nAAQ\nJLN\nABE\nXNA\nGUW\nKZO\nSBN\nBKA\nARH\nRTW\nNUX\nNOJ\nSCO\nUCT\nUSK\nPEX\nNNM\nPKV\nKGP\nKJA\nKGF\nURJ\nIWA\nCGQ\nKIJ\nJON\nSMD\nACV\nOAJ\nTCL\nDBQ\nATD\nAKS\nBAS\nFRE\nMBU\nIRA\nSCZ\nMUA\nGZO\nMNY\nRNL\nRUS\nVAO\nKGE\nRBV\nBUA\nCMU\nDAU\nGUR\nPNP\nHKN\nUNG\nKRI\nKMA\nKVG\nMDU\nMAS\nMXH\nMIS\nTIZ\nTBG\nRAB\nVAI\nWBM\nLLU\nCNP\nJFR\nJGO\nJJU\nJSU\nJNN\nJNS\nNAQ\nJHS\nJUV\nJQA\nGRY\nTHO\nVPN\nYWS\nYAA\nYWM\nYFX\nYHA\nYRG\nYCK\nYLE\nSUR\nYAX\nWNN\nYNO\nXBE\nKIF\nYOG\nYHP\nYKU\nZTB\nZLT\nYAC\nYAG\nXKS\nYKG\nYAT\nYBE\nYBX\nYRF\nYCS\nYDP\nYER\nYFA\nYFH\nYMN\nYGB\nYGO\nYGT\nYGW\nYGX\nYGZ\nYQC\nCXH\nYNS\nYHO\nYHR\nYIK\nYIV\nAKV\nYKQ\nYPJ\nYLC\nYLH\nYSG\nXGR\nYMH\nYMT\nYUD\nYNC\nYNE\nYNL\nYOH\nYPH\nYPM\nYPO\nYPW\nYQD\nYQN\nYRA\nYRL\nYSF\nYSK\nYST\nYTL\nYVZ\nYWP\nYXN\nYZG\nZAC\nILF\nZBF\nZEM\nZFD\nZGI\nZJN\nZKE\nMSA\nZMT\nZPB\nZRJ\nZSJ\nZTM\nZUM\nZWL\nBLJ\nCBH\nBMW\nELU\nKMS\nHDF\nHEI\nHGL\nSJY\nNQT\nUnited Kingdom\nCAL\nEOI\nFIE\nNRL\nPPW\nSOY\nNDY\nLWK\nWRY\nLEQ\nPZE\nVLY\nBRR\nCFN\nCNL\nLKN\nOSY\nNorway\nNorway\nRET\nSDN\nSOG\nSVJ\nSOJ\nNorway\nVRY\nBZG\nLCJ\nOSD\nHFS\nKSD\nTYF\nAGH\nSQO\nHMV\nVTS\nQRA\nMQP\nAAM\nMBD\nGNZ\nORP\nSWX\nTLD\nDIS\nCIP\nSLI\nYVA\nWAQ\nJVA\nBMD\nMXT\nTVA\nWTA\nWTS\nWAM\nWPB\nDWB\nWMP\nTTS\nWMA\nMJA\nCBT\nDUE\nVPE\nMSZ\nKOU\nMJL\nTCH\nVPY\nSRH\nCMK\nLUD\nOND\nOMD\nSWP\nERS\nBOA\nMAT\nINO\nNIO\nKRZ\nBSU\nTSH\nLJA\nPFR\nGMZ\nBTE\nKBS\nKEN\nOXB\nSMW\nVIL\nESU\nEUN\nNDR\nCape Verde\nCape Verde\nBCO\nBEI\nDSE\nDEM\nGDE\nGOR\nABK\nMTF\nTIE\nALU\nBSA\nMGQ\nGLK\nBUO\nAAC\nATZ\nASV\nLKG\nMYD\nNYK\nSRX\nTOB\nMJI\nLAQ\nATB\nUYL\nPZU\nBKZ\nTKQ\nLDI\nMUZ\nSHY\nTBO\nRUA\nULU\nDIU\nABR\nABY\nAHN\nALM\nALO\nALW\nAPN\nATY\nBFD\nBFF\nBKW\nBQK\nBRL\nCEC\nCGI\nCIU\nCKB\nCLM\nCMX\nDDC\nDUJ\nEAU\nEKO\nEWB\nFAY\nGGW\nGRI\nHOT\nHTS\nKIO\nIRK\nJMS\nLAR\nLBE\nLBF\nLEB\nLMT\nLNS\nLWT\nLYH\nMKG\nMLS\nMSL\nOTH\nOWB\nPIB\nPIH\nPIR\nPLN\nPSM\nRDG\nRHI\nRKS\nRUT\nSBP\nSHR\nSLK\nSLN\nSMX\nTUP\nUIN\nVCT\nVLD\nWRL\nYKM\nECN\nRJL\nIDY\nANE\nLTT\nJSY\nPEV\nQGY\nSOB\nAOT\nQSR\nCVU\nBNX\nUSQ\nKSY\nSFQ\nKCM\nAJI\nADF\nISE\nEDO\nSZF\nILZ\nGDT\nMDS\nSLX\nAZS\nJBQ\nPBR\nAAZ\nUTK\nAHS\nPEU\nMIJ\nCYW\nCUA\nGUB\nJAL\nCTD\nONX\nJQE\nPLP\nTTQ\nBCL\nTNO\nPBP\nPJM\nSYQ\nJEE\nPAX\nTND\nCOX\nATC\nCAT\nCRI\nPID\nAIU\nMGS\nMHX\nMUK\nMOI\nPYE\nICI\nPTF\nKDV\nMNF\nMFJ\nNGI\nLKB\nLBS\nTVU\nKXF\nRTA\nSVU\nEUA\nHPA\nTonga\nNTT\nVBV\nIUE\nFUT\nMXS\nAPK\nAHE\nAUQ\nUAP\nUAH\nMTV\nSLH\nTOH\nEAE\nCCV\nLOD\nSSR\nPBJ\nLPM\nLNB\nMWF\nLNE\nNUS\nZGU\nRCL\nSON\nTGH\nULB\nVLS\nSWJ\nOLZ\nAUY\nAWD\nDLY\nFTA\nIPA\nTGJ\nBMY\nILP\nFBD\nDWD\nAJF\nEWD\nKHD\nBXR\nRJN\nBJB\nAFZ\nNSH\nSRY\nLRR\nADU\nOMH\nAAN\nBNP\nBHV\nCJL\nDBA\nDEA\nDSK\nJIW\nHDD\nKDD\nORW\nPAJ\nKDU\nSYW\nTUK\nISU\nKAC\nGXF\nADK\nGST\nSGY\nHCR\nHNS\nKLG\nMCG\nMOU\nANI\nVAK\nWRG\nLUP\nENT\nLZN\nHCN\nMFK\nKUH\nOKD\nHSG\nNKM\nIWJ\nFKS\nONJ\nSYO\nMYE\nKUV\nMPK\nWJU\nYNY\nHIN\nCJJ\nSFS\nCYU\nCGM\nJOL\nSGS\nSUG\nTDG\nWNP\nBSO\nSFE\nTUG\nVRC\nCYP\nCRM\nMBT\nRXS\nTTG\nLHS\nOES\nING\nGGS\nSST\nNEC\nJDO\nLEC\nMEA\nMII\nVDC\nRIA\nTOW\nESR\nZPC\nSOD\nSCY\nLOH\nESM\nPSY\nCRC\nGLJ\nLQM\nLPD\nNQU\nPDA\nEYP\nGYA\nPUR\nRIB\nREY\nSRJ\nORG\nMVS\nLHC\nCJA\nHUU\nNZC\nSRA\nMDO\nMYC\nVIG\nJPR\nBBQ\nDSD\nBBR\nSFC\nGBJ\nNEV\nVIJ\nBQU\nUNI\nKOV\nPPK\nDZN\nUKK\nKSN\nKVD\nNAJ\nCNN\nPYJ\nCKH\nCYX\nIKS\nKXK\nDYR\nOHO\nUJE\nMPW\nVSG\nOZH\nKWG\nHRK\nIFO\nCWC\nRWN\nUDJ\nCSH\nCEE\nAMV\nKSZ\nPES\nGNA\nMVQ\nEIE\nKYZ\nNOZ\nHTG\nIAA\nGRV\nNAL\nOGZ\nESL\nWKK\nBLF\nGLH\nPSC\nKQA\nLPS\nSLY\nHMA\nNYA\nOVS\nIJK\nKVX\nNYM\nRAT\nNFG\nKRO\nLBD\nAZN\nFEG\nNMA\nNCU\nUGC\nKSQ\nTMJ\nRYB\nEGO\nURS\nLPK\nVKT\nUUA\nJOK\nCSY\nULY\nOSW\nPEZ\nSKX\nBWO\nHBX\nKCT\nWRZ\nBBM\nSHL\nGAU\nDMU\nTEZ\nBZL\nOUI\nBHR\nBDP\nMEY\nKEP\nGAN\nHAQ\nKDO\nMAQ\nBMV\nHPH\nCXR\nVCS\nVCA\nDIN\nUIH\nPXU\nVII\nBMO\nTVY\nKAW\nLIW\nMNU\nBSX\nPKK\nSWQ\nTMC\nBUI\nSEH\nTJS\nDTD\nBEJ\nTJG\nSMQ\nLUV\nARD\nBLG\nLGL\nODN\nMKM\nBKM\nLWY\nBBN\nTMG\nKUD\nTKG\nHLP\nNTX\nPSU\nSQG\nPDO\nLSW\nPKG\nLBW\nNNX\nLPU\nALH\nGYL\nAUU\nBCI\nBDD\nBVI\nBHQ\nHTI\nBEU\nBRK\nBUC\nGIC\nOKY\nBQL\nBHS\nBLT\nCVQ\nCAZ\nCPD\nCNC\nCNJ\nCED\nCTN\nCMA\nCNB\nCUQ\nOOM\nDMD\nNLF\nDPO\nELC\nEPR\nFLS\nGET\nGLT\nGTE\nGFF\nHID\nHOK\nMHU\nHGD\nJCK\nKAX\nKNS\nKFG\nKRB\nKWM\nKUG\nLNO\nLEL\nLDH\nIRG\nLSY\nLHG\nLRE\nLER\nLVO\nUBB\nMKR\nMIM\nMGT\nMNG\nMCV\nMQL\nMMG\nMRZ\nMOV\nMYA\nMGB\nONG\nMYI\nMBH\nNRA\nNAA\nNTN\nZNE\nOLP\nPUG\nPMK\nPBO\nCCK\nGOV\nPKE\nPLO\nEDR\nPQQ\nPTJ\nULP\nRAM\nRMA\nSGO\nMJK\nSBR\nSRN\nXTG\nTCA\nVCD\nSYU\nWNR\nWYA\nWUN\nWOL\nWIN\nBWT\nOKR\nXMY\nNAY\nCIF\nCIH\nDAT\nHET\nBAV\nSJW\nTGO\nHLH\nXIL\nBHY\nCGD\nDYG\nMXZ\nZUH\nLZH\nZHA\nENH\nNNY\nXFN\nYIH\nAKA\nGOQ\nHZG\nIQN\nXNN\nENY\nUYN\nAVK\nLTI\nBYN\nDLZ\nHVD\nMXV\nDIG\nLUM\nSYM\nZAT\nKOW\nJDZ\nJIU\nJUZ\nLYG\nHYN\nLYI\nJJN\nTXN\nWEF\nWEH\nWUX\nWUS\nWNZ\nYNZ\nYIW\nHSN\nBPX\nDAX\nGYS\nLZO\nMIG\nNAO\nLZY\nWXN\nAKU\nIQM\nKCA\nKRL\nKRY\nYIN\nHEK\nJMU\nJNZ\nNDG\nYNJ\nWKL\nWME\nLRV\nIOR\nNNR\nGTI\nNBB\nORH\nAQG\nSHP\nYCU\nJGN\nDSN\nPWT\nSPW\nJEF\nUNT\nPVC\nSBH\nKMW\nSUI\nTBW\nOBN\nERM\nCVF\nFUL\nNVI\nQSF\nLRH\nSUN\nMCW\nAZA\nXAU\nAKP\nANV\nATK\nGAM\nHPB\nKAL\nKSM\nKVL\nMYU\nRBY\nSHH\nSVA\nWTK\nOMC\nYPX\nYTQ\nARC\nQOW\nFON\nTMU\nCYZ\nKVK\nGVR\nPJA\nQBC\nHGR\nACR\nGOP\nSDP\nHMI\nWUZ\nTBH\nACP\nGBT\nIIL\nPFQ\nTCG\nMQM\nAFS\nDRG\nLEN\nRGS\nEGM\nCQD\nDHM\nNDC\nSLV\nIGG\nKNW\nKVC\nPTH\nTOG\nEGN\nLKH\nWLH\nCHG\nUAS\nBHG\nYVB\nSKT\nPDP\nWVB\nMPA\nAOE\nCKZ\nMSR\nSIC\nTEQ\nYEI\nLSS\nKMV\nVQS\nYIF\nHDM\nMRQ\nGFN\nOAG\nTRO\nCOQ\nHOJ\nESC\nYAK\nGUL\nCES\nNSO\nDGE\nMTL\nCPX\nMWA\nBMQ\nOKB\nKIK\nIUD\nGBZ\nIMT\nAET\nMGC\nSWD\nGRM\nAUW\nMYP\nLKS\nMVA\nQSA\nWSY\nMIE\nLAF\nVGT\nENW\nMTJ\nRIW\nPDT\nLYM\nPKH\nKTR\nAustralia\nNOA\nUKC\nCEJ\nTNL\nBQT\nOSH\nAGE\nEAT\nARE\nRIN\nUKX\nRMT\nQLS\nZJI\nQNC\nGDZ\nIAR\nOHE\nJNG\nDRK\nNYT\nZXB\nWUA\nGYY\nBRD\nLWB\nPGV\nCYF\nOXR\nTEN\nNIU\nSCH\nNBC\nIAO\nLGO\nNLP\nCKC\nUST\nNLV\nRHP\nSTS\nISM\nLCQ\nLGU\nBMC\nMLD\nASE\nULV\nERV\nGED\nZSW\nGBN\nHYS\nSUS\nLYU\nGPZ\nTVF\nEGV\nARV\nIKV\nYBV\nNGP\nAVX\nMHV\nZIN\nINQ\nSWT\nHUT\nSTJ\nNDZ\nVOK\nGUC\nSIA\nTOA\nMBL\nPGD\nWFK\nJHW\nYTM\nSME\nSHD\nDVL\nDIK\nSDY\nCDR\nAIA\nMCK\nMTH\nGDV\nOLF\nWYS\nALS\nCNY\nELY\nVEL\nSRR\nSOW\nMYL\nSMN\nMMH\nFRD\nESD\nAST\nONP\nEMK\nUNK\nUUK\nSHX\nNUI\nEEK\nKUK\nKWT\nKWK\nMLL\nRSH\nKGK\nKMO\nCIK\nEAA\nHUS\nHSL\nNUL\nVEE\nWBQ\nCEM\nSHG\nIYK\nVIS\nMCE\nCYR\nCPQ\nTWB\nAYK\nAGN\nELV\nFNR\nHNH\nAFE\nMTM\nHYG\nEGX\nKPV\nPIP\nWSN\nAKK\nKYK\nKLN\nABL\nBKC\nIAN\nOBU\nORV\nWLK\nKTS\nELI\nGLV\nTLA\nWAA\nWMO\nKKA\nSMK\nSKK\nTNC\nAKB\nCYT\nAUK\nKPN\nKFP\nNLG\nPML\nKLW\nKWN\nKOT\nKYU\nSCM\nNNL\nKKH\nNIB\nAKI\nAIN\nAPZ\nRDS\nPNT\nSGV\nIGB\nNCN\nTKJ\nIRC\nSLQ\nHKB\nAQC\nMHM\nMLY\nYSO\nYWB\nYTF\nYGV\nYXK\nXTL\nXLB\nXSI\nYBT\nZGR\nYCR\nYRS\nYOP\nYBY\nZNA\nYGG\nYJM\nYDT\nZEL\nYFJ\nRNI\nBZA\nRFS\nSIU\nWSP\nPLD\nCOZ\nNEG\nRVR\nSPB\nARR\nJSM\nUYU\nABF\nABN\nDRJ\nICK\nOEM\nSMZ\nTOT\nAGI\nCSC\nORJ\nNAI\nIMB\nKAR\nUSI\nMHA\nPJC\nACD\nRVE\nVGZ\nEBG\nCAQ\nCOG\nTLU\nCFB\nOPS\nGRP\nCMP\nBVS\nSFK\nPIN\nBRA\nSTZ\nMQH\nAUX\nNVP\nLVR\nFRC\nDOU\nLBR\nROO\nGPB\nJCB\nRVD\nAAX\nMBZ\nRBB\nCIZ\nBAZ\nDMT\nGNM\nQDJ\nNZA\nLBZ\nAMC\nGSQ\nMRB\nAWA\nJIJ\nMKS\nDBM\nDBT\nQHR\nGOB\nMYB\nMRE\nRBX\nCPA\nMAX\nBDI\nWHF\nPAF\nHTY\nRVV\nILD\nBIU\nGJR\nSAK\nIIA\nTDK\nULG\nVGD\nLDG\nHSK\nCQM\nNJF\nCSA\nRKH\nAGC\nFTY\nTSO\nTII\nZAJ\nCCN\nFUG\nLCX\nACX\nHZH\nOSU\nADS\nDTS\nKHE\nSZS\nHJJ\nYQI\nISO\nFFA\nCKS\nMWK\nPGU\nYES\nOSB\nTJH\nAXJ\nKKX\nAGJ\nUGA\nULO\nBPR\nLBX\nTJU\nTAZ\nBWB\nDRB\nWGE\nBRT\nDKI\nLZR\nHLT\nHCQ\nFIZ\nRVT\nPVU\nSBS\nDTA\nRIF\nPUC\nLAM\nHII\nINW\nDGL\nMZK\nAEA\nAAK\nKUC\nAIS\nTMN\nBEZ\nNIG\nBBG\nMTK\nMNK\nNON\nTSU\nWTZ\nKTF\nAFT\nRNA\nCHY\nNNB\nXYA\nBOW\nFTI\nLVK\nRMY\nGFY\nNDU\nAGM\nTRM\nSMO\nUDD\nZSY\nOLM\nDWA\nRIL\nSAA\nPDK\nBMG\nSUA\nMMU\nAPC\nSDM\nVNC\nPHK\nECP\nSBD\nVAL\nCAU\nAWK\nQNV\nSQL\nOSZ\nRWI\nSXQ\nSEE\nPHA\nSQH\nTKF\nFRJ\nGEX\nRYY\n4U9\nLVM\n6S0\nBIV\nHEN\nLAL\nSYH\nIDL\nRBK\nFNU\nMYQ\nPCW\nMGY\nRID\nFDY\nPEA\nEBE\nEMP\nESX\nBBP\nSPF\nQYD\nOLV\nONQ\nBJC\nSLE\nUTM\nZKB\nLND\nMWC\nJVL\nGKY\nLZU\nBWG\nRVS\nNHD\nKGO\nDBB\nBCE\nCKL\nTCZ\nUKS\nJCI\nESN\nHMR\nMYV\nDUC\nUVA\nLOT\nCCR\nOCA\nYUS\nYOO\nLHA\nSGH\nMSI\nHEX\nCDA\nJAB\nHGS\nTOP\nNGQ\nCSO\nTKI\nPWK\nKLS\nZTA\nPUE\nKHC\nUKA\nILN\nAVW\nCGZ\nBXK\nE63\nMMI\nSTK\nRWL\nYZY\nCDW\nAIZ\nTVI\nHSH\nGML\nTMA\nQXR\nDVT\nYGE\nYRV\nHDO\nZHY\nMCL\nLHD\nPPC\nKHW\nTXG\nHLG\nFZG\nXYE\nDWC\nRKP\nMVV\nMFX\nOKF\nOKU\nPSH\nCKF\nOMN\nTTD\nHIO\nKHT\nGAI\nAZ3\nYTA\nTSB\nYSD\nBNU\nCVX\nYCC\nIZA\nXFL\nMVL\nRBD\nWST\nBID\nNME\nOOK\nOBY\nVIN\nBGE\nZKG\nYBI\nSPZ\nWHP\nMAE\nYZZ\nYAB\nBCV\nMPY\nLDX\nKJI\nCPB\nHMB\nRVY\nPOJ\nJTC\nOIA\nRDC\nSXX\nBYO\nSXO\nCFC\nCAF\nERN\nCCI\nFBE\nCFO\nAAF\nUMU\nDTI\nFBA\nOLC\nHUW\nIRZ\nORX\nUNA\nTEF\nGZP\nDQH\nFRP\nTAN\nPYM\nOQU\nOWD\nBAF\nIJD\nMGJ\nCXY\nGHG\nDXR\nASH\nLWM\nOXC\nFIT\nVPC\nPYP\nRMG\nGAD\nDKX\nWDR\nJYL\nDNN\nCTJ\nLGC\nMLJ\nPIM\nFFC\nGVL\nPHD\nUDG\nHHH\nDNL\nMRN\nPBX\nTOC\nPLV\nWUU\nHUE\nOYL\nWYE\nGBK\nAFW\n57C\nRMK\nLGH\nRTS\nKEW\nYSP\nYHF\nYHN\nYKX\nYMG\nYXZ\nYEM\nYFD\nLWC\nEGT\nPMP\nXMC\nEET\nYUE\nLOP\nZML\nHDG\nUMP\nLOZ\nFBG\nWMI\nJXA\nYGM\nEYK\nRAC\nRZP\nREI\nRIR\nTIW\nJKA\nHMJ\nHIW\nHZL\nCBE\nYBO\nKLF\nLNR\nJOT\nVYS\nJXN\nBBX\nOBE\nSEF\nAVO\nGIF\nZPH\nOCF\nJES\n52A\nCCO\nHQU\nAIK\nCDN\nLBT\nSOP\nRCZ\nDLL\nSVH\nBUU\nLHV\nLPR\nBKL\nDKK\nVAY\nLDJ\nANQ\nVNW\nGVQ\nCLW\nCGX\nJZP\nCRE\nIGQ\nRNM\nBXO\nOEB\nWBW\nLNN\nUMD\nRLK\nFFT\nLEW\nMRK\nDRM\nGDW\nLWA\nMFI\nISW\nCWI\nBVY\nYRQ\nPOF\nEPM\nEOK\nPSL\nSTP\nSOO\nVNA\nDKS\nBYT\nADY\nGAS\nHOA\nKEY\nILU\nATJ\nOVA\nRGK\nFLD\nPCZ\nSTE\nERY\nPEF\nGQQ\nTPN\nPTZ\nCKV\nLPC\nCTH\nBST\nLLK\nGBB\nZTU\nLKP\nDEE\nAOH\nDSO\nSSI\nBFP\nGGE\nHDI\nRNT\nPOC\nCTY\nCEU\nBEC\nPDG\nGTU\nQFO\nSNY\nGKL\nRPB\nIFL\nBIN\nMOO\nECA\nJYO\nVAM\nLLF\nLSZ\nONS\nTDR\nSDC\nWBU\nBBJ\nPAO\nFFZ\nP08\nP52\nA39\nE25\nYTY\nPTK\nKSI\nEEN\nGKK\nRCS\nRHD\nKMP\nIOW\nTLQ\nMWM\nANP\nFXO\nODO\nZTR\nHRI\nPEQ\nHBG\nQCJ\nQSC\nYKN\nXSB\nZBM\nKTI\nGYU\nCNI\nKRH\nCCL\nHWD\nMZP\nJHQ\nARB\nSHT\nTEM\nGAH\nWIO\nBFJ\nULK\nGNY\nKZR\nVLU\nBEO\n4A7\nBMP\nYCN\nBJP\nBQB\nSEK\nIVR\nGLI\nIMM\nYIC\nPTB\nKGN\nSBM\nKFE\nBJU\nMZJ\nGEU\nSAD\nKJP\nSIK\nTTI\nGFL\n5B2\nCGC\nMTN\nLHM\nFZI\nIZG\nNEW\nCOE\nBMT\nDNV\nCOJ\nTIX\nNYE\nAAP\nFCM\nLIX\nOJC\nGIU\nEUM\nTKT\nYLK\nYEE\nNU8\nND4\nNF4\nYCM\nYPD\nOQN\nMNZ\nKFS\n2H0\nGXH\nCIY\nKVM\nZKP\nUMS\nADH\nNLT\nBOR\nFDW\nOBC\nTDJ\nAQB\nNOR\nBTZ\nDAW\nWAR\nEWK\nBSJ\nTZR\nFBR\nS40\nCLS\nM94\nEVW\nK83\nLRO\nEUF\n6J4\nMEO\nAUO\nCZG\nEKY\nA50\nMIC\n23M\nDBN\nPUK\nCVO\nPXH\nCWT\nOGD\nW63\nRKR\nAKO\nSHN\nWNA\nPKA\nYBW\n2A5\nWKR\nGFO\nDYL\nTGI\nTJL\nOAL\nOCW\n7W6\nMHC\nYEL\nUKF\nJZI\nDAN\n0V4\nERG\nCQW\nBEM\nNKT\nSUY\nOUZ\nQUO\nKAA\nMBI\nSGX\nAOG\nZYI\nHYW\nLDS\nAVA\nKSS\nWTB\nTNH\nSZV\nLII\nNTI\nWSR\nDTB\nSSV\nMEQ\nBUW\nKAZ\nMNA\nSGQ\nOKL\nKOX\nCMQ\nWMB\nRCM\nDCN\nKNO\nHBI\nEMV\nEMT\nFAH\nIXT\nI16\nKRQ\nSSF\nJSV\nJAS\n87K\nMRF\nE38\nBQE\nCZA\nBUY\nCCB\nIOB\nEKI\nC03\nCUB\nGMJ\nMPR\nGYH\nPXE\nHVS\nIGX\nSZT\nDU9\nSUT\nFCI\nHNZ\nLEE\nPPY\nDIQ\nERD\nERL\nCNO\nHTR\nUYF\nBWW\nPRB\nHAF\nHCJ\nWJF\nCJF\nGUZ\nUBT\nBOX\nFYJ\nTDF\nPZL\nKJH\nHPG\nYIE\nHNY\nWOS\nIGT\nASN\nGMU\nMKT\nNGD\nTOI\nSCD\nEDN\nALX\nPKT\nGPN\nHZP\nUWL\nTQK\nHDE\nPTT\nAHQ\nLXN\n19S\nCBF\nOKK\n2K7\nEHA\nFTG\nGBG\nGUY\nMEJ\nULS\nIDP\n3AU\nLQR\nLZZ\nBYY\nPRX\nCFV\nGXY\nOEL\nFET\nLGD\nSZY\nMPO\nUKT\nYBA\nBNG\nOFK\nAWO\nTFL\nTPF\nBZC\nITP\nKBN\nIKL\nAIR\nJRN\nJIA\nVLP\nJUA\nCCX\nBMB\nQBX\nAPQ\nFLB\nPCS\nBNC\nBNB\nMTP\nVPZ\nDRV\nSXK\nMLZ\nPDU\nATI\nHSM\nSWH\nTTL\nKWB\nKOO\nAOU\nN/A\nSQX\nLDM\nRHV\nOHS\nRZS\nTMF\nIFU\nKIE\nYKO\nBUT\nTLI\nTQL\nBPL\nACS\nWVI\nGLU\nJGG\nDLK\nKM8\nXTO\nYSE\nMRT\nYAH\nYAL\n\nYBU\nYCE\nYCP\nYCQ\nXRR\nYDO\nYEY\nYGD\nYHE\nYHT\nYDG\nYJF\nYKJ\nYLR\nYME\nYML\nYOS\nYPS\nYQS\nYRO\nYRP\nYSH\nYSL\nYVD\nYVE\nYXQ\nYSN\nKES\nXPK\nZGF\nZJG\nYTD\nPIW\nXPP\nWPC\nZST\nZUC\nFNB\nFSS\nBXP\nDGP\nLMR\nSXN\nNDD\nMAI\nADI\nMWE\nALN\nAXN\nCLU\nBBD\nBIH\nBKE\nBPI\nWMH\nBTL\nBYI\nCCY\nCNU\nCRG\nCSV\nDAA\nDAG\nDMN\nDRA\nEED\nEGI\nEKA\nHYI\nHYR\nJCT\nLLQ\nLOL\nMBG\nMCB\nMDH\nMMT\nNHZ\nNRB\nOGB\nOLU\nOTM\nOZR\nPWY\nPOU\nRNH\nRSL\nRWF\nSNS\nSOA\nSUZ\nTPH\nUAO\nUKI\nUOX\nHTV\nVTN\nWMC\nWWR\nXMR\nZZV\nECV\nCDT\nTEV\nTN0\nQLP\nBJY\nRUV\nXPL\nUPL\nQSN\nSNJ\nKMX\nXXN\nKNR\nPYK\nXIJ\nMPD\nATG\nSGI\nRQW\nENN\nWWA\nQUT\nIEJ\nAAV\nBPH\nMXI\nVMR\nBAT\nQHP\nTOQ\nLGR\nCNR\nTLX\nZIC\nTTC\nAPI\nCVE\nPAL\nPZA\nTQS\nMQZ\nRIJ\nJAE\nIKU\nVYI\nGVN\nNLI\nVLK\nINA\nZIX\nRTC\nHIM\nRDP\nPUT\nABH\nARY\nBLN\nBZD\nBWQ\nCVC\nCWW\nCYG\nCMD\nDRN\nDNQ\nDYA\nECH\nFRB\nGUH\nHXX\nHTU\nKRA\nKPS\nKGY\nTGN\nMRG\nRPM\nQRM\nPPI\nSIO\nSNB\nSWC\nTYB\nTUM\nWGT\nWKB\nQRR\nSXE\nWWY\nNGA\nLHK\nWDS\nHTT\nUUN\nBFU\nRUG\nWHU\nSXJ\nYKH\n"
  },
  {
    "path": "share/salt/README.md",
    "content": "# Opinionated example of deployment via Salt Stack\n\n## Assumptions:\n  * user & group srv:srv exist, this is used as a generic service runner\n  * you want to run the service on port 80, directly exposed to the interwebs (you really want to add a reverse SSL proxy in between)\n  * You have, or are willing to deploy Salt Stack.\n  * A bit of assembly is required since you need to move pillar.sls into your saltroot/pillar/ and the rest into saltroot/wttr/\n  * You want metric-sm units. Just roll your own wegorc to change this\n\n## Caveats:\n  * Doesn't do enough to make a recent master checkout work, i.e. needs further improvement. Latest known working revision is 0d76ba4a3e112694665af6653040807835883b22\n"
  },
  {
    "path": "share/salt/init.sls",
    "content": "wttr:\n  service.running:\n    - enable: True\n    - watch:\n      - file: /srv/ephemeral/start.sh\n      - git: wttr-repo\n    - require:\n      - pkg: wttr-dependencies\n      - git: wttr-repo\n      - cmd: wego\n      - archive: geolite-db\n\n# package names are from Ubuntu 18.04, you may need to adjust if on a different distribution\nwttr-dependencies:\n  pkg.installed:\n    - pkgs:\n      - golang\n      - gawk\n      - python-setuptools\n      - python-dev\n      - python-dnspython\n      - python-geoip2\n      - python-geopy\n      - python-gevent\n      - python-flask\n      - python-pil\n      - authbind\n\nwttr-repo:\n  git.latest:\n    - name: https://github.com/chubin/wttr.in\n    - rev: master\n    - target: /srv/ephemeral/wttr.in\n    - require:\n      - /srv/ephemeral\n\nwttr-start:\n  file.managed:\n    - name: /srv/ephemeral/start.sh\n    - source: salt://wttr/start.sh\n    - mode: '0770'\n    - user: srv\n    - group: srv\n\nwegorc:\n  file.managed:\n    - name: /srv/ephemeral/.wegorc\n    - user: srv\n    - group: srv\n    - source: salt://wttr/wegorc\n    - template: jinja\n    - context:\n      apikey: {{ pillar['wttr']['apikey'] }}\n\ngeolite-db:\n   archive.extracted:\n    - name: /srv/ephemeral\n    - source: http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz\n    - source_hash: http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz.md5\n    - keep_source: True\n    - options: --strip-components=1 # flatten directory structure\n    - enforce_toplevel: False\n\n# Could benefit from improvement, won't get updated automatically at all\nwego:\n  cmd.run:\n    - onlyif: 'test ! -e /srv/ephemeral/bin/wego'\n    - env:\n      - GOPATH: /srv/ephemeral\n    - name: go get -u github.com/schachmat/wego && go install github.com/schachmat/wego\n    - cwd: /srv/ephemeral/\n    - require:\n      - pkg: wttr-dependencies\n      - file: wegorc\n\n/srv/ephemeral:\n  file.directory:\n    - makedirs: True\n\n{% for dir in '/srv/ephemeral/wttr.in/log','/srv/ephemeral/wttr.in/cache' %}\n{{ dir }}:\n  file.directory:\n    - user: srv\n    - group: srv\n    - makedirs: True\n    - recurse:\n        - user\n        - group\n    - require_in:\n      - service: wttr\n{% endfor %}\n\n/etc/systemd/system/wttr.service:\n  file:\n    - managed\n    - source: salt://wttr/wttr.service\n    - require:\n      - file: wttr-start\n      - file: authbind-80\n    - require_in:\n      - service: wttr\n\nauthbind-80:\n  file:\n    - managed\n    - name: /etc/authbind/byport/80\n    - user: srv\n    - group: srv\n    - mode: 770\n    - replace: False\n    - require:\n      - pkg: wttr-dependencies\n"
  },
  {
    "path": "share/salt/pillar.sls",
    "content": "wttr:\n  apikey: insert-api-key-here-and-make-this-pillar-available-to-salt\n"
  },
  {
    "path": "share/salt/start.sh",
    "content": "#!/bin/sh\nexport WEGORC=\"/srv/ephemeral/.wegorc\"\nexport GOPATH=\"/srv/ephemeral\"\n\nexport WTTR_MYDIR=\"/srv/ephemeral/wttr.in\"\nexport WTTR_GEOLITE=\"/srv/ephemeral/GeoLite2-City.mmdb\"\nexport WTTR_WEGO=\"$GOPATH/bin/wego\"\n\nexport WTTR_LISTEN_HOST=\"0.0.0.0\"\nexport WTTR_LISTEN_PORT=\"80\"\n\npython $WTTR_MYDIR/bin/srv.py\n"
  },
  {
    "path": "share/salt/wegorc",
    "content": "# wego configuration\n# \n# This config has https://github.com/schachmat/ingo syntax.\n# Empty lines or lines starting with # will be ignored.\n# All other lines must look like \"KEY=VALUE\" (without the quotes).\n# The VALUE must not be enclosed in quotes as well!\n\n# aat-frontend: Show geo coordinates (default false)\naat-coords=false\n\n# aat-frontend: Monochrome output (default false)\naat-monochrome=false\n\n# BACKEND to be used (default forecast.io)\nbackend=forecast.io\n\n# NUMBER of days of weather forecast to be displayed (default 3)\ndays=3\n\n# forecast backend: the api KEY to use (default )\nforecast-api-key={{ apikey }}\n\n# forecast backend: print raw requests and responses (default false)\nforecast-debug=false\n\n# forecast backend: the LANGUAGE to request from forecast.io (default en)\nforecast-lang=en\n\n# FRONTEND to be used (default ascii-art-table)\nfrontend=ascii-art-table\n\n# json frontend: do not indent the output (default false)\njsn-no-indent=false\n\n# LOCATION to be queried (default 40.748,-73.985)\nlocation=40.748,-73.985\n\n# openweathermap backend: the api KEY to use (default )\nowm-api-key=\n\n# openweathermap backend: print raw requests and responses (default false)\nowm-debug=false\n\n# openweathermap backend: the LANGUAGE to request from openweathermap (default en)\nowm-lang=en\n\n# UNITSYSTEM to use for output.\n# Choices are: metric, imperial, si, metric-ms (default metric)\nunits=metric-ms\n\n# worldweatheronline backend: the api KEY to use (default )\nwwo-api-key=\n\n# worldweatheronline backend: print raw requests and responses (default false)\nwwo-debug=false\n\n# worldweatheronline backend: the LANGUAGE to request from worldweatheronline (default en)\nwwo-lang=en\n"
  },
  {
    "path": "share/salt/wttr.service",
    "content": "[Unit]\nDescription=Wttr weather service\n\n[Service]\nExecStart=/usr/bin/authbind --deep /srv/ephemeral/start.sh\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n"
  },
  {
    "path": "share/screenrc",
    "content": "screen -t srv.py bash -c \"cd ~/wttr.in; ve/bin/python bin/srv.py; bash -i\"\nscreen -t proxy.py bash -c \"cd ~/wttr.in; ve/bin/python bin/proxy.py; bash -i\"\n"
  },
  {
    "path": "share/scripts/build-welang.sh",
    "content": "#!/usr/bin/env bash\n\n# The scipr is used to build a standalone we-lang binary from\n# the wttr.in Go source code. The script is needed as long as\n# a standalone we-lang binary is used.\n#\n# The script requires a configured Go compiler in PATH.\n\n\nshow_usage() {\n  cat <<EOF\nUsage:\n\n    $0 WELANG_PATH\n\nBuild we-lang from the source code and install it as a binary to WELANG_PATH.\nEOF\n}\n\nfatal() {\n  rm -rf \"$DIR\"\n  echo \"FATAL: $*\"\n  exit 1\n}\n\nadd_main() {\n  cat <<EOF > main.go\npackage main\n\nfunc main() {\n  Cmd()\n}\nEOF\n}\n\nif [[ -z $1 ]]; then\n  show_usage\n  exit 0\nfi\n\nDST_FILE=\"$1\"\nDIR=$(mktemp -d /tmp/build-welang-XXXXXXXXX)\n\ncp -R \"internal/view/v1\" \"$DIR/v1\"\n\nsed -i 's/^package .*/package main/' \"$DIR\"/v1/*.go\n\ncd \"$DIR\"/v1 || fatal \"can't change into the build directory\"\n\ngo mod init github.com/chubin/we-lang || fatal \"Can't do 'go mod init'\"\ngo mod tidy || fatal \"Can't do 'go mod tidy'\"\nadd_main\ngo build -o \"$DST_FILE\" *.go || fatal \"Building error\"\n\nrm -rf \"$DIR\"\n\n\n"
  },
  {
    "path": "share/scripts/clean-cache.sh",
    "content": "#!/bin/bash\n\nLOGFILE=/tmp/clean-cache.log\n\n_log() {\n  echo \"$(date +\"[%Y-%m-%d %H:%M:%S]\") $*\" >> \"$LOGFILE\"\n}\n\n_log_pipe() {\n  while read -r line; do\n    _log \"$line\"\n  done\n}\n\nCACHEDIR=\"/wttr.in/cache\"\n\n_log Cleaning up the cache.\n_log Before:\ndf -h \"$CACHEDIR\" | _log_pipe\n\nfor dir in wego proxy-wwo png lru\ndo\n  mv \"${CACHEDIR}/${dir}\" \"${CACHEDIR}/${dir}.old\"\n  mkdir \"${CACHEDIR}/${dir}\"\n  rm -rf \"${CACHEDIR}/${dir}.old\"\ndone\n\n_log After:\ndf -h \"$CACHEDIR\" | _log_pipe\n_log \"=============================\"\n\ncd /wttr.in/log\nmv main.log main.log.1\ntouch main.log\n\n"
  },
  {
    "path": "share/scripts/log-space.sh",
    "content": "#!/usr/bin/env bash\n\nLOG_DIR=\"/wttr.in/log\"\nLOG_FILE=\"$LOG_DIR/diskspace.log\"\n\nDISK=/wttr.in\n\nlog() {\n  mkdir -p \"$LOG_DIR\"\n\n  echo \"$(date +\"[%Y-%m-%d %H:%M:%S]\") $*\" | tee -a \"$LOG_FILE\"\n}\n\nlog $(df -k \"$DISK\" | tail -1 | awk '{print $4}')\n"
  },
  {
    "path": "share/scripts/start-screen.sh",
    "content": "#!/bin/bash\n\nSESSION_NAME=wttr.in\nSCREENRC_PATH=$(dirname $(dirname \"$0\"))/screenrc\n\nscreen -dmS \"$SESSION_NAME\" -c \"$SCREENRC_PATH\"\n\n"
  },
  {
    "path": "share/static/malformed-response.html",
    "content": "<html>\n<title>wttr.in</title>\n<head>\n<script async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\n</head>\n<body style='background:black'>\n<pre style='color:#cccccc'>\nSorry, we processed more than 1M requests today and we ran out of our datasource capacity.\nWe hope to solve the problem as soon as possible, so you can enjoy\nyour favourite weather service 24x365 even if it rains or snows.\n\nWe will solve the problem as soon as possible.\n<a href=\"https://twitter.com/igor_chubin\" class=\"twitter-follow-button\" data-show-count=\"false\" data-button=\"grey\">Follow @igor_chubin</a> <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script><span style='position: relative; bottom: 6px;'>for the updates. </span>\n\nIf you like to code (and you surely do), you can check the <span style='position: relative; bottom: -6px;'><a aria-label=\"Star chubin/wttr.in on GitHub\" data-count-aria-label=\"# stargazers on GitHub\" data-count-api=\"/repos/chubin/wttr.in#stargazers_count\" data-count-href=\"/chubin/wttr.in/stargazers\" data-icon=\"octicon-star\" href=\"https://github.com/chubin/wttr.in\" class=\"github-button\">wttr.in</a></span> repository\nto see how the scalability problem is (not yet) solved.\n\n</pre>\n<blockquote class=\"twitter-tweet\" data-theme=\"dark\" data-lang=\"en\"><p lang=\"en\" dir=\"ltr\">How do you check the weather? curl wttr.in — Sure thing! <a href=\"https://twitter.com/hashtag/wttrin?src=hash\">#wttrin</a> <a href=\"https://t.co/mgYzW2ajyq\">pic.twitter.com/mgYzW2ajyq</a></p>&mdash; Igor Chubin (@igor_chubin) <a href=\"https://twitter.com/igor_chubin/status/700846126467944448\">February 20, 2016</a></blockquote>\n<script async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\n\n<script async defer id=\"github-bjs\" src=\"https://buttons.github.io/buttons.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "share/static/style.css",
    "content": "body {\n    background: black;\n    color: #bbbbbb;\n}\n\n/* Switch to light mode if the user prefers it */\n/*\n@media (prefers-color-scheme: light) {\n  body {\n    background-color: #ffffff;\n    color: #000000;\n  }\n}\n*/\n\npre {\n/*    font-family: source_code_proregular; */\n\n/*\nfont-family: Courier New,Courier,Lucida Sans Typewriter,Lucida Typewriter,monospace;\nfont-size: 70%;\n*/\n\n/*font-family: Lucida Console,Lucida Sans Typewriter,monaco,Bitstream Vera Sans Mono,monospace; */\n/*Droid Sans Mono*/\nfont-family: \"Source Code Pro\", \"DejaVu Sans Mono\", Menlo, \"Lucida Sans Typewriter\", \"Lucida Console\", monaco, \"Bitstream Vera Sans Mono\", monospace;\n/*font-family: bitstream_vera_sans_monoroman;*/\nfont-size: 75%;\n}\n"
  },
  {
    "path": "share/systemd/README.md",
    "content": "To add **wttr.in** to systemd as a service, do the following steps.\n\n\n1. **Create a systemd service file**: You’ll need to create a service file in `~/.config/systemd/user/` (for user-level) or `/etc/systemd/system/` (for system-wide) directory. Let’s create it for a user.\n\nCreate the directory if it doesn’t exist:\n\n```bash\nmkdir -p ~/.config/systemd/user/\n```\n\nThen, create the service file called `myscript.service`:\n\n```bash\ncp share/systemd/wttrin.service ~/.config/systemd/user/wttrin.service\n```\n\n2. **Reload the systemd daemon**: This will ensure systemd recognizes the new service.\n\n```bash\nsystemctl --user daemon-reload\n```\n\n4. **Enable and start your service**:\n\nTo start the service immediately, run:\n\n```bash\nsystemctl --user start wttrin.service\n```\n\n5. **Check the status**: To verify that your service is running correctly, you can check its status:\n\n```bash\nsystemctl --user status wttrin.service\n```\n\n6. **Start service automatically**: This will ensure the service is running after reboot.\n\nTo enable it to start automatically at boot, run:\n\n```bash\nsystemctl --user enable wttrin.service\n```\n\nEnable user services even if the user is not logged in (specify the user name instead of `USER`):\n\n```bash\nsudo loginctl enable-linger USER\n```\n"
  },
  {
    "path": "share/systemd/wttrin.service",
    "content": "[Unit]\nDescription=wttr.in services\n\n[Service]\nType=oneshot\nRemainAfterExit=yes\nExecStart=/home/igor/src/wttr.in/share/systemd/wttrin.sh session1\nExecStop=/usr/bin/tmux kill-session -t session1\n\n[Install]\nWantedBy=default.target\n"
  },
  {
    "path": "share/systemd/wttrin.sh",
    "content": "#!/usr/bin/env bash\n\nSESSION_NAME=\"\"\nSRC_DIR=/home/igor/src/wttr.in\nSERVICES_FILE=config/services/services.yaml\n\nstart_service() {\n  local name=\"$1\"\n  local workdir=\"$2\"\n  local cmd=\"$3\"\n\n  if [[ -z \"$SESSION_NAME\" ]]; then\n    echo Unknown SESSION_NAME. Exiting >&2\n    exit 1\n  fi\n\n  local WINDOW_NAME=\"$name\"\n  local TEXT_TO_ENTER=\"cd $workdir && $cmd\"\n\n  if ! tmux has-session -t \"$SESSION_NAME\" >& /dev/null; then\n    tmux new-session -d -s \"$SESSION_NAME\"\n  fi\n\n  # Create a new window if it doesn't exist\n  tmux list-windows -t \"$SESSION_NAME\" | grep -q \"^.\\+ $WINDOW_NAME \" || tmux new-window -t \"$SESSION_NAME\" -n \"$WINDOW_NAME\"\n\n  sleep 0.05\n\n  # Send text to the new window and press Enter\n  tmux send-keys -t \"$SESSION_NAME:$WINDOW_NAME\" \"$TEXT_TO_ENTER\" C-m\n}\n\n\nmain() {\n  local name\n  local cmd\n\n  if [[ -n $1 ]]; then\n    SESSION_NAME=$1\n  else\n    echo Usage: $0 SESSION_NAME >&2\n    exit 1\n  fi\n\n  cd \"$SRC_DIR\" || exit 1\n\n  while read -r line; do\n    name=$(jq -r .name <<< \"$line\")\n    workdir=$(jq -r .workdir <<< \"$line\")\n    cmd=$(jq -r .command <<< \"$line\")\n\n    start_service \"$name\" \"$workdir\" \"$cmd\"\n  done <<< \"$(yq -c .services[] < \"$SERVICES_FILE\")\"\n}\n\nmain \"$@\"\n"
  },
  {
    "path": "share/templates/index.html",
    "content": "<html>\n<head>\n<meta name=\"color-scheme\" content=\"dark light\">\n<link rel=\"stylesheet\" type=\"text/css\" href=\"https://adobe-fonts.github.io/source-code-pro/source-code-pro.css\">\n<link rel=\"stylesheet\" type=\"text/css\" href=\"/files/style.css\" />\n</head>\n<body>\n<pre>\n{{ body }}\n</pre>\n</body>\n</html>\n"
  },
  {
    "path": "share/test-thunder.txt",
    "content": "Prévisions météo pour: Test-Milon, France\n\n \u001b[38;5;226m _`/\"\"\u001b[38;5;250m.-.    \u001b[0m Averse de pluie légère\n \u001b[38;5;226m  ,\\_\u001b[38;5;250m(   ).  \u001b[0m \u001b[38;5;154m17\u001b[0m °C\u001b[0m          \n \u001b[38;5;226m   /\u001b[38;5;250m(___(__) \u001b[0m \u001b[1m↙\u001b[0m \u001b[38;5;118m5\u001b[0m km/h\u001b[0m       \n \u001b[38;5;111m     ‘ ‘ ‘ ‘ \u001b[0m 14 km\u001b[0m          \n \u001b[38;5;111m    ‘ ‘ ‘ ‘  \u001b[0m 3.6 mm\u001b[0m         \n                                                       ┌─────────────┐                                                       \n┌──────────────────────────────┬───────────────────────┤ sam. 09 juin├───────────────────────┬──────────────────────────────┐\n│             Matin            │          Après-midi   └──────┬──────┘       Soir            │             Nuit             │\n├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤\n│               Brume          │               Nuageux        │ \u001b[38;5;226m _`/\"\"\u001b[38;5;250m.-.    \u001b[0m Foyers orageux │ \u001b[38;5;226m _`/\"\"\u001b[38;5;250m.-.    \u001b[0m Averse de plui…│\n│ \u001b[38;5;251m _ - _ - _ - \u001b[0m \u001b[38;5;190m21\u001b[0m °C\u001b[0m          │ \u001b[38;5;250m     .--.    \u001b[0m \u001b[38;5;220m25\u001b[0m-\u001b[38;5;220m26\u001b[0m °C\u001b[0m       │ \u001b[38;5;226m  ,\\_\u001b[38;5;250m(   ).  \u001b[0m \u001b[38;5;220m25\u001b[0m-\u001b[38;5;220m27\u001b[0m °C\u001b[0m       │ \u001b[38;5;226m  ,\\_\u001b[38;5;250m(   ).  \u001b[0m \u001b[38;5;226m22\u001b[0m °C\u001b[0m          │\n│ \u001b[38;5;251m  _ - _ - _  \u001b[0m \u001b[1m←\u001b[0m \u001b[38;5;118m5\u001b[0m-\u001b[38;5;118m6\u001b[0m km/h\u001b[0m     │ \u001b[38;5;250m  .-(    ).  \u001b[0m \u001b[1m←\u001b[0m \u001b[38;5;118m4\u001b[0m-\u001b[38;5;118m5\u001b[0m km/h\u001b[0m     │ \u001b[38;5;226m   /\u001b[38;5;250m(___(__) \u001b[0m \u001b[1m↑\u001b[0m \u001b[38;5;118m4\u001b[0m-\u001b[38;5;118m6\u001b[0m km/h\u001b[0m     │ \u001b[38;5;226m   /\u001b[38;5;250m(___(__) \u001b[0m \u001b[1m→\u001b[0m \u001b[38;5;118m5\u001b[0m-\u001b[38;5;154m9\u001b[0m km/h\u001b[0m     │\n│ \u001b[38;5;251m _ - _ - _ - \u001b[0m 19 km\u001b[0m          │ \u001b[38;5;250m (___.__)__) \u001b[0m 18 km\u001b[0m          │ \u001b[38;5;228;5m    ⚡\u001b[38;5;111;25m‘‘\u001b[38;5;228;5m⚡\u001b[38;5;111;25m‘‘ \u001b[0m 16 km\u001b[0m          │ \u001b[38;5;111m     ‘ ‘ ‘ ‘ \u001b[0m 15 km\u001b[0m          │\n│               0.0 mm | 0%\u001b[0m    │               0.0 mm | 0%\u001b[0m    │ \u001b[38;5;111m    ‘ ‘ ‘ ‘  \u001b[0m 0.7 mm | 46%\u001b[0m   │ \u001b[38;5;111m    ‘ ‘ ‘ ‘  \u001b[0m 2.4 mm | 82%\u001b[0m   │\n└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘\n                                                       ┌─────────────┐                                                       \n┌──────────────────────────────┬───────────────────────┤ dim. 10 juin├───────────────────────┬──────────────────────────────┐\n│             Matin            │          Après-midi   └──────┬──────┘       Soir            │             Nuit             │\n├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤\n│ \u001b[38;5;226m   \\  /\u001b[0m       Partiellement …│ \u001b[38;5;226m   \\  /\u001b[0m       Partiellement …│ \u001b[38;5;226m _`/\"\"\u001b[38;5;240;1m.-.    \u001b[0m Averse de plui…│ \u001b[38;5;226m _`/\"\"\u001b[38;5;240;1m.-.    \u001b[0m Averse de plui…│\n│ \u001b[38;5;226m _ /\"\"\u001b[38;5;250m.-.    \u001b[0m \u001b[38;5;226m22\u001b[0m-\u001b[38;5;226m24\u001b[0m °C\u001b[0m       │ \u001b[38;5;226m _ /\"\"\u001b[38;5;250m.-.    \u001b[0m \u001b[38;5;220m25\u001b[0m-\u001b[38;5;220m27\u001b[0m °C\u001b[0m       │ \u001b[38;5;226m  ,\\_\u001b[38;5;240;1m(   ).  \u001b[0m \u001b[38;5;226m24\u001b[0m-\u001b[38;5;220m26\u001b[0m °C\u001b[0m       │ \u001b[38;5;226m  ,\\_\u001b[38;5;240;1m(   ).  \u001b[0m \u001b[38;5;190m21\u001b[0m °C\u001b[0m          │\n│ \u001b[38;5;226m   \\_\u001b[38;5;250m(   ).  \u001b[0m \u001b[1m↙\u001b[0m \u001b[38;5;154m9\u001b[0m-\u001b[38;5;190m10\u001b[0m km/h\u001b[0m    │ \u001b[38;5;226m   \\_\u001b[38;5;250m(   ).  \u001b[0m \u001b[1m↙\u001b[0m \u001b[38;5;226m13\u001b[0m-\u001b[38;5;220m19\u001b[0m km/h\u001b[0m   │ \u001b[38;5;226m   /\u001b[38;5;240;1m(___(__) \u001b[0m \u001b[1m↙\u001b[0m \u001b[38;5;220m17\u001b[0m-\u001b[38;5;202m30\u001b[0m km/h\u001b[0m   │ \u001b[38;5;226m   /\u001b[38;5;240;1m(___(__) \u001b[0m \u001b[1m↙\u001b[0m \u001b[38;5;226m15\u001b[0m-\u001b[38;5;202m31\u001b[0m km/h\u001b[0m   │\n│ \u001b[38;5;226m   /\u001b[38;5;250m(___(__) \u001b[0m 20 km\u001b[0m          │ \u001b[38;5;226m   /\u001b[38;5;250m(___(__) \u001b[0m 20 km\u001b[0m          │ \u001b[38;5;21;1m   ‚‘‚‘‚‘‚‘  \u001b[0m 17 km\u001b[0m          │ \u001b[38;5;21;1m   ‚‘‚‘‚‘‚‘  \u001b[0m 18 km\u001b[0m          │\n│               0.0 mm | 0%\u001b[0m    │               1.8 mm | 56%\u001b[0m   │ \u001b[38;5;21;1m   ‚’‚’‚’‚’  \u001b[0m 4.1 mm | 82%\u001b[0m   │ \u001b[38;5;21;1m   ‚’‚’‚’‚’  \u001b[0m 1.6 mm | 72%\u001b[0m   │\n└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘\n                                                       ┌─────────────┐                                                       \n┌──────────────────────────────┬───────────────────────┤ lun. 11 juin├───────────────────────┬──────────────────────────────┐\n│             Matin            │          Après-midi   └──────┬──────┘       Soir            │             Nuit             │\n├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤\n│ \u001b[38;5;226m _`/\"\"\u001b[38;5;250m.-.    \u001b[0m Pluie éparse à │               Nuageux        │ \u001b[38;5;226m _`/\"\"\u001b[38;5;240;1m.-.    \u001b[0m Averse de plui…│ \u001b[38;5;226m _`/\"\"\u001b[38;5;240;1m.-.    \u001b[0m Averse de plui…│\n│ \u001b[38;5;226m  ,\\_\u001b[38;5;250m(   ).  \u001b[0m \u001b[38;5;190m21\u001b[0m °C\u001b[0m          │ \u001b[38;5;250m     .--.    \u001b[0m \u001b[38;5;226m24\u001b[0m-\u001b[38;5;220m26\u001b[0m °C\u001b[0m       │ \u001b[38;5;226m  ,\\_\u001b[38;5;240;1m(   ).  \u001b[0m \u001b[38;5;226m23\u001b[0m-\u001b[38;5;220m25\u001b[0m °C\u001b[0m       │ \u001b[38;5;226m  ,\\_\u001b[38;5;240;1m(   ).  \u001b[0m \u001b[38;5;190m20\u001b[0m °C\u001b[0m          │\n│ \u001b[38;5;226m   /\u001b[38;5;250m(___(__) \u001b[0m \u001b[1m↑\u001b[0m \u001b[38;5;226m14\u001b[0m-\u001b[38;5;214m23\u001b[0m km/h\u001b[0m   │ \u001b[38;5;250m  .-(    ).  \u001b[0m \u001b[1m↑\u001b[0m \u001b[38;5;220m18\u001b[0m-\u001b[38;5;214m22\u001b[0m km/h\u001b[0m   │ \u001b[38;5;226m   /\u001b[38;5;240;1m(___(__) \u001b[0m \u001b[1m↗\u001b[0m \u001b[38;5;226m13\u001b[0m-\u001b[38;5;214m23\u001b[0m km/h\u001b[0m   │ \u001b[38;5;226m   /\u001b[38;5;240;1m(___(__) \u001b[0m \u001b[1m↗\u001b[0m \u001b[38;5;190m10\u001b[0m-\u001b[38;5;214m21\u001b[0m km/h\u001b[0m   │\n│ \u001b[38;5;111m     ‘ ‘ ‘ ‘ \u001b[0m 18 km\u001b[0m          │ \u001b[38;5;250m (___.__)__) \u001b[0m 18 km\u001b[0m          │ \u001b[38;5;21;1m   ‚‘‚‘‚‘‚‘  \u001b[0m 14 km\u001b[0m          │ \u001b[38;5;21;1m   ‚‘‚‘‚‘‚‘  \u001b[0m 14 km\u001b[0m          │\n│ \u001b[38;5;111m    ‘ ‘ ‘ ‘  \u001b[0m 0.1 mm | 22%\u001b[0m   │               0.0 mm | 0%\u001b[0m    │ \u001b[38;5;21;1m   ‚’‚’‚’‚’  \u001b[0m 5.2 mm | 73%\u001b[0m   │ \u001b[38;5;21;1m   ‚’‚’‚’‚’  \u001b[0m 5.3 mm | 72%\u001b[0m   │\n└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘\n"
  },
  {
    "path": "share/translation.txt",
    "content": "wttr.in is translated in NUMBER_OF_LANGUAGES languages:\n\n    SUPPORTED_LANGUAGES\n\nTranslated/improved/corrected by:\n\n    * Afrikaans:            Casper Labuschage @casperl (on github)\n    * Arabic                Besher Aladdam @akai54 (on github),\n                            Ahmed D. ALi @_nakanakaii (twitter) / @nakanakaii (github)\n    * Arhamic               Robel Kassa @rawbubble\n    * Armenian:             Aram Bayadyan @aramix, Mikayel Ghazaryan @mkdotam,\n                            Grigor Khachatryan @grigortw\n    * Azerbaijani:          Dmytro Nikitiuk, Elsevar Abbasov,\n                            Eldar Velibekov (@welibekov on github)\n    * Basque:               Iker Sagasti (@isagasti on github)\n    * Belarusian:           Igor Chubin, Anton Zhavoronkov @edogby (on github)\n    * Bosnian:              Ismar Kunc @ismarkunc\n    * Bengali:              Nazia Tasnim (@appledora on github)\n    * Bulgarian:            Vladimir Vitkov @zeridon (on github)\n    * Brazilian-PT:         Tupã Negreiros @TupaNegreiros (on github), Gabriel Monteiro @krosct (on github)\n    * Catalan:              Angel Jarabo @legna29A\n    * Chinese(Traditional): Jeff Huang\n    * Chinese(Simplified):  YouthLin Chen(@YouthLin on github), Junhan (@junhan-z on github),\n                            Felix Wong (@gnowxilef on github)\n    * Croatian:             Siniša Kusić @ku5ic\n    * Czech:                Juraj Kakody,\n                            Ondřej Povolný (@Remogeus on github)\n    * Danish:               Kim Schulz @kimusan (on github)\n    * Dutch:                Youri Claes, Edwin Martin @edwinm\n    * Esperanto:            Igor Chubin\n    * Estonian:             Jaan Jänesmäe @janesmae (on github)\n    * Finnish:              @Maxifi\n    * French:               Igor Chubin, @daftaupe, @iago-lito, @Marc66 (on github)\n    * Frisian:              Anne Douwe Bouma @anned20 (on github)\n    * Galician              Diego Blanco @diego-treitos (on github)\n    * German:               Igor Chubin, @MAGICC (https://kthx.at), Simon Neutert @simonneutert (on github)\n    * Greek:                Panayotis Vryonis and @Petewg (on github)\n    * Hebrew:               E.R.\n    * Hindi:                Aakash Gajjar @skyme5 (gh)\n    * Hungarian:            Mark Petruska\n    * Icelandic:            Óli G. @dvergur, Skúli Arnlaugsson @Arnlaugsson\n    * Indonesian:           Andria Arisal @andria009\n    * Interlingua:          Dustin Redmond @dustinkredmond (on github)\n    * Irish:                Robert Devereux @RobertDev (gh), Conor O'Callaghan @ivernus (gh)\n    * Italian:              Diego Maniacco, Riccardo Volpe aka YITA @yitaverse (gh)\n    * Japanese:             @ryunix\n    * Kazakh:               Akku Tutkusheva, Oleg Tropinin\n    * Korean:               Jeremy Bae @opt9, Jung Winter @res_tin\n    * Latvian:              Gunārs Danovskis,\n                            Edgars Andersons (GitHub: @eandersons)\n    * Lithuanian            Juras Rutavičius\n    * Macedonian:           Matej Plavevski @MatejMecka\n    * Marathi:              Sanket Pandit Garade (@sanketgarade on github)\n    * Norwegian:            Fredrik Fjeld @fredrikfjeld\n    * Nynorsk:              Kevin Brubeck Unhammer (https://unhammer.org/k/)\n    * Occitan:              Quentin PAGÈS @Quenty-tolosan (gh)\n    * Persian:              Javad @threadripper_,\n                            @kagetora66 (on github)\n    * Polish:               Wojtek Łukasiewicz @wojtuch (on github)\n    * Portuguese:           Fernando Bitti Loureiro @fbitti (on github),\n                            Hugo Carvalho (@hugok79 on github)\n    * Romanian:             Gabriel Moruz\n    * Russian:              Igor Chubin, @layerex (on github), Vladimir Kalashnikov\n    * Serbian:              Milan Stevanović @FathVader\n    * Slovak:               Juraj Kakody\n    * Slovenian:            B.S.\n    * Spanish:              Fernando Bitti Loureiro @fbitti (on github)\n    * Swedish:              John Eriksson\n    * Swahili:              Joel Mukuthu\n    * Tamil:                Parthiban @parthi1984 (on github)\n    * Telugu:               Pavan Srinivas Mamidala @pavansrinivasmamidala (on github),\n                            Vishal Boddu @bodduv (on github)\n    * Turkish:              Atabey Kaygun, Yilmaz @edigu, Volkan Tokmak(@volkanto), Oğuz Ersen\n    * Thai:                 Vatunyoo Suwannapisit @kerlos\n    * Ukrainian:            Igor Chubin, Serhiy @pavse\n    * Uzbek:                Shukhrat Mukimov\n    * Vietnamese:           Lưu Vĩnh Phúc @phuclv90 (on github)\n    * Welsh:                Daniel Thomas\n\nand many many others.\n\nIn the not likely case wttr.in is not yet translated in your language\nyou can help with the translation.\nPlease start with one of the following steps:\n\n    * Open a GitHub issue: github.com/chubin/wttr.in\n    * Write an email to igor@chub.in\n    * Write PM or tweet to igor_chubin\n"
  },
  {
    "path": "share/translations/af-help.txt",
    "content": "Gebruik:\n\n    $ curl wttr.in          # huidige ligging\n    $ cur wttr.in/muc       # weerberig in München se lughawe\n\nOndersteunde soorte ligging:\n\n    /paris                  # stadsnaam\n    /~Eiffel+tower          # enige ligging\n    /Москва                 # Unikode naam van enige ligging in enige taal\n    /muc                    # lughawe kode (3 letters)\n    /@stackoverflow.com     # domeinnaam\n    /94107                  # gebiedskodes\n    /-78.46,106.79          # GPS koördinate\n\nBesondere liggings:\n\n    /moon                   # Fase van die maan (voeg +US of ,+France by vir daardie stede)\n    /moon@2016-10-25        # Fase van die maan vir die datum (@2016-10-25)\n\nEenhede:\n\n    m                       # metrike (SI) (word orals gebruik behalwe vir die VSA)\n    u                       # USCS (gebruik in die VSA)\n    M                       # vertoon die spoed van die wind in m/s\n\nBesigtig keuses:\n\n    0                       # slegs die huidige weer\n    1                       # huidige weer + 1 dag\n    2                       # huidige weer + 2 dae\n    F                       # moet nie die \"Volg\" lyn wys nie\n    n                       # smal weergawe (slegs dag en nag)\n    q                       # stil weergawe (geen \"Weerberig\" teks nie)\n    Q                       # baie stil weergawe (geen \"Weerberig), geen stadsnaam\n    T                       # skakel terminaal kodes af (geen kleur)\n\nPNG keuses:\n\n    /paris.png              # skep 'n PNG leêr\n    p                       # voeg 'n raam by rondom die uitset\n    t                       # deursigtigheid 150\n    transparency=...        # deursigtigheid vanaf 0 tot 255 (255 = nie deursigtig nie)\n\nKeuses can saamgevoeg word\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # met PNG word die lêer mode daarna gegee \n    /Rome_0pq_lang=it.png   # lang keuses word met 'n onderstreping verdeel\n\nLokalisering:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nOndersteunde tale:\n\n    FULL_TRANSLATION (word ondersteun)\n    PARTIAL_TRANSLATION (in wording)\n\nSpesiale URLe:\n\n    /:help                  # vertoon hierdie bladsy\n    /:bash.function         # vertoon aanbeveling vir bash funksie wttr()\n    /:translation           # vertoon die besonderhede van die vertalers\n\n"
  },
  {
    "path": "share/translations/af.txt",
    "content": "113: Helder                                 : Clear\n113: Sonnig                                 : Sunny\n116: Gedeeltelik bewolk                     : Partly cloudy\n119: Bewolk                                 : Cloudy\n122: Oortrokke                              : Overcast\n143: Mis toestande                          : Mist\n176: Gedeeltelike reën moontlik             : Patchy rain possible\n179: Gedeeltelike sneeu moontlik            : Patchy snow possible\n182: Gedeeltelike ysreën moontlik           : Patchy sleet possible\n185: Gedeeltelik ysige motreën moontlik     : Patchy freezing drizzle possible\n200: Donderbuie moontlik                    : Thundery outbreaks possible\n227: Waaiende sneeu                         : Blowing snow\n230: Sneeustorm                             : Blizzard\n248: Mis toestande                          : Fog\n260: Vriesende mis toestande                : Freezing fog\n263: Gedeeltelike ligte motreën             : Patchy light drizzle\n266: Ligte motreën                          : Light drizzle\n281: Vriesende motreën                      : Freezing drizzle\n284: Erg vriesende motreën                  : Heavy freezing drizzle\n293: Gedeeltelike ligte reën                : Patchy light rain\n296: Ligte reën                             : Light rain\n299: Matige reën by tye                     : Moderate rain at times\n302: Matige reën                            : Moderate rain\n305: Swaar reën by tye                      : Heavy rain at times\n308: Swaar reën                             : Heavy rain\n311: Ligte vriesende reën                   : Light freezing rain\n314: Matige tot swaar vriesende reën        : Moderate or heavy freezing rain\n317: Ligte ysreën                           : Light sleet\n320: Matige tot swaar ysreën                : Moderate or heavy sleet\n323: Verspreide ligte sneeu                 : Patchy light snow\n326: Ligte sneeu                            : Light snow\n329: Verspreide ligte sneeu                 : Patchy moderate snow\n332: Matige sneeu                           : Moderate snow\n335: Verspreide swaar sneeu                 : Patchy heavy snow\n338: Swaar sneeu                            : Heavy snow\n350: Haelkorrels                            : Ice pellets\n353: Ligte bui reën                         : Light rain shower\n356: Matige tot swaar bui reënbui           : Moderate or heavy rain shower\n359: Stortreën                              : Torrential rain shower\n362: Ligte buie ysreën                      : Light sleet showers\n365: Ligte tot swaar buie ysreën            : Moderate or heavy sleet showers\n368: Ligte buie sneeu                       : Light snow showers\n371: Ligte tot swaar buie sneeu             : Moderate or heavy snow showers\n386: Verspreide ligte buie en donderbuie    : Patchy light rain with thunder\n389: Ligte tot swaar buie en donderbuie     : Moderate or heavy rain with thunder\n392: Verspreide ligte sneeu met donderbuie  : Patchy light snow with thunder\n395: Matige of swaar sneeu met donderbuie   : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/am-help.txt",
    "content": "አጠቃቀም:\n\n    $ curl wttr.in          # አሁን ያሉበት አካባቢ\n    $ curl wttr.in/add      # የአየር ሁነታ በቦሌ አዲስ አበባ አለምአቀፍ ኤርፖርት \n\nተቀባይነት ያላቸው ቦታዎች:\n\n    /paris                  # የከተማ ስም\n    /~Eiffel+tower          # ማንኛውም ቦታ\n    /Москва                 # nom Unicode ou emplacement quelconque dans n'importe quelle langue\n    /muc                    # የኤርፖርት ኮድ (3 lettres)\n    /@stackoverflow.com     # nom de domaine\n    /94107                  # የፖስታ ኮድ (ለአሜሪካ ብቻ)\n    /-78.46,106.79          # coordonnées GPS\n\nEmplacements particuliers:\n\n    /moon                   # phases de la lune (ajouter ,+US ou ,+France pour accéder aux villes du même nom)\n    /moon@2016-10-25        # phases de la lune pour cette date (@2016-10-25)\n\nUnités:\n\n    ?m                      # système métrique (par défaut partout sauf pour les États-Unis d'Amérique)\n    ?u                      # USCS (par défaut pour les États-Unis d'Amérique)\n    ?M                      # affiche la vitesse du vent en m/s\n\nOption d'affichage:\n\n    ?0                      # aujourd'hui seulement\n    ?1                      # aujourd'hui + demain\n    ?2                      # aujourd'hui + 2 jours\n    ?n                      # version courte (seulement le jour et la nuit)\n    ?q                      # version silencieuse (pas d'en-tête \"Prévisions météo pour\")\n    ?Q                      # version super-silencieuse (pas d'en-tête \"Prévisions météo pour\", pas de nom de la ville)\n    ?T                      # séquences d'échappement pour terminaux désactivées (pas de couleurs)\n\nየPNG አማራጮች:\n\n    /paris.png              # génère un fichier PNG\n    ?p                      # ajoute un cadre autour de la sortie\n    ?t                      # transparency 150 (transparence 150)\n    transparency=...        # transparence de 0 à 255 (255 = pas de transparence)\n\nCombiner les options:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # dans le mode PNG les options sont spécifiées après _\n    /Rome_0pq_lang=it.png   # les options longues sont séparées par des underscores _\n\nLocalisation:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nቋንቋዎች:\n\n    FULL_TRANSLATION (ሙሉ በሙሉ የተተረጎሙ)\n    PARTIAL_TRANSLATION (በከፊል የተተረጎሙ)\n\nURLs particulières:\n\n    /:help                  # affiche cette page\n    /:bash.function         # fonction bash recommandée wttr()\n    /:translation           # affiche les informations sur la traduction de wttr.in\n\n"
  },
  {
    "path": "share/translations/am.txt",
    "content": "113: ጥርት ያለ                           : Clear\n113: ፀሐያማ                             : Sunny\n116: ከፊል ደመናማ                        : Partly cloudy\n119: ደመናማ                             : Cloudy\n122: ደመናማ                             : Overcast\n143: ጭጋግ                              : Mist\n176: ዝናብ ሊዘንብ ይችላል                   : Patchy rain possible\n179: በረዶ ሊጥል ይችላል                    : Patchy snow possible\n182: አልፎ አልፎ በረዶ አዘል ዝናብ ሊዘንብ ይችላል : Patchy sleet possible\n185: አልፎ አልፎ በረዶ አዘል ካፍያ ሊጥል ይችላል : Patchy freezing drizzle possible\n200:                                    : Thundery outbreaks possible\n227: ነፋሻማ በረዶ                         : Blowing snow\n230: በረዶ አዘል አውሎ ነፋስ                : Blizzard\n248: ጭጋግ                              : Fog\n260: በረዶ ጭጋግ                         : Freezing fog\n263: ቀላል ካፍያ                          : Patchy light drizzle\n266: ቀላል ካፍያ                          : Light drizzle\n281: በረዶ ካፍያ                          : Freezing drizzle\n284: ከባድ በረዶ ካፍያ                      : Heavy freezing drizzle\n293: አልፎ አልፎ ቀላል ዝናብ                 : Patchy light rain\n296: ቀላል ዝናብ                          : Light rain\n299: አልፎ አልፎ መለስተኛ ዝናብ              : Moderate rain at times\n302: መለስተኛ ዝናብ                       : Moderate rain\n305: አልፎ አልፎ ከባድ ዝናብ                : Heavy rain at times\n308: ከባድ ዝናብ                          : Heavy rain\n311: ቀላል የበረዶ ዝናብ                    : Light freezing rain\n314: መለስተኛ ወይም ከባድ የበረዶ ዝናብ       : Moderate or heavy freezing rain\n317:                                    : Light sleet\n320:                                    : Moderate or heavy sleet\n323: አልፎ አልፎ ቀላል በረዶ                 : Patchy light snow\n326: ቀላል በረዶ                           : Light snow\n329: አልፎ አልፎ መለስተኛ በረዶ              : Patchy moderate snow\n332: መለስተኛ በረዶ                        : Moderate snow\n335: አልፎ አልፎ ከባድ በረዶ                 : Patchy heavy snow\n338: ከባድ በረዶ                           : Heavy snow\n350: የበረዶ እንክብሎች                     : Ice pellets\n353: ቀላል የዝናብ ካፍያ                    : Light rain shower\n356: መለስተኛ ወይም ከባድ የዝናብ ካፍያ       : Moderate or heavy rain shower\n359: ዶፍ ዝናብ                           : Torrential rain shower\n362:                                    : Light sleet showers\n365:                                    : Moderate or heavy sleet showers\n368: ቀላል የበረዶ ካፍያ                     : Light snow showers\n371: መለስተኛ ወይም ከባድ የበረዶ ካፍያ        : Moderate or heavy snow showers\n386: ቀላል ዝናብ ከነጎድጓድ ጋር               : Patchy light rain with thunder\n389: መለስተኛ ወይም ከባድ ዝናብ ከነጎድጓድ ጋር  : Moderate or heavy rain with thunder\n392: ቀላል በረዶ ከነጎድጓድ ጋር                : Patchy light snow with thunder\n395: መለስተኛ ወይም ከባድ በረዶ ከነጎድጓድ ጋር   : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/ar-help.txt",
    "content": "الإستخدام:\n\n    $ curl wttr.in          # الموقع الحالي\n    $ curl wttr.in/muc      # الطقس في مطار ميونخ\n\nأنواع الأماكن المدعومة:\n\n    /paris                  # اسم المدينة\n    /~Eiffel+tower          # أي مكان\n    /Москва                 # اسم يونيكود ﻷي مكان بأي لغة\n    /muc                    # الاسم النمطي للمطار (3 احرف)\n    /@stackoverflow.com     # اسم النطاق\n/94107                  # رمز المنطقة\n    /-78.46,106.79          # GPS إحداثيات الـ\n\nالأماكن الخاصة:\n\n    /moon                   # مرحلة القمر (أضف ,+US أو ,+France لمدينة معينة)\n    /moon@2016-10-25        # مرحلة القمر بتاريخ (2016-10-25)\n\nالوحدات:\n\n    m                       # النظام المتريّ (SI) (يستخدم في العادة في كل الأماكن ما عدا الولايات المتحدة)\n    u                       # وحدات القياس العرفية الأمريكية (يستخدم في العادة في الولايات المتحدة)\n    M                       # إظهار سرعة الرياح بوحدة م/ث\n\nخيارات العرض:\n\n    0                       # الطقس الحالي فقط\n    1                       # الطقس الحالي وطقس اليوم\n    2                       # الطقس الحالي وطقس اليوم ويوم غد\n    A                       # تجاهل الوكيل المستخدم وقم بتطبيق نمط ANSI   (الطرفية)\n    F                       # \"لا تظهر سطر \"المتابعة\n    n                       # النسخة الخفيفة جدا (النهار والليل فقط)\n    q                       # النسخة الصامتة (من غير عبارة \"تقرير جوي\")\n    Q                       # النسخة الصامتة كليا (بدون عبارة \"تقرير جوي\" أو اسم المدينة)\n    T                       # العودة لنمط تسلسل الطرفية (من غير ألوان)\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPNG خيارات:\n\n    /paris.png              # PNG إنشاء صورة بصيغة  \n    p                       # إضافة إطار حول المخرج\n    t                       # الشفافية 150\n    transparency=...        # الشفافية من 0 إلي 255 (255 = غير شفاف)\n    background=...          # لون الخلفية بنمط RRGGBB\n\nيمكن جمع الخيارات:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # يتم تحديد خيار ملف  PNG بعد الشرطة السفلية\n    /Rome_0pq_lang=it.png   # الخيارات الطويلة يتم فصلهم عن طريق شرطة سفلية\n\nالترجمة:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nاللغات المدعومة:\n\n    FULL_TRANSLATION (مدعومة)\n    PARTIAL_TRANSLATION (جار العمل)\n\nروابط URLs خاصة :\n\n    /:help                  # عرض هذه الصفحة\n    /:bash.function         # wttr() bash عرض الميزة الخاصةبـ\n    /:translation           # عرض المعلومات حول المترجمين\n\n"
  },
  {
    "path": "share/translations/ar.txt",
    "content": "113: صاف                                                   : Clear \n113: مشمس                                                  : Sunny\n116: غائم جزئياً‏                                           : Partly cloudy\n119: غائم                                                  : Cloudy \n122: ملبد بالغيوم                                         : Overcast\n143: شبورة                                                 : Mist\n176: احتمال هطول أمطار متفرقة                            : Patchy rain possible\n179: احتمال هطول ثلوج متفرقة                             : Patchy snow possible\n182: احتمال هطول المطر الثلجي متفرقة                     : Patchy sleet possible\n185: احتمال هطول أمطار متفرقة                            : Patchy freezing drizzle possible\n200: احتمال ظهور الرعد                                    : Thundery outbreaks possible\n227: هبوب ثلجية                                           : Blowing snow\n230: عاصفة ثلجية                                          : Blizzard\n248: ضباب\t                                                 : Fog    \n260: ضباب بارد\t\t                                        : Freezing fog\n263: رذاذ خفيف متقطع                                      : Patchy light drizzle\n266: رذاذ خفيف                                            : Light drizzle \n281: رذاذ بارد\t\t\t                                      : Freezing drizzle\n284: رذاذ غزير بارد                                      : Heavy freezing drizzle\t\t\t\n293: أمطار خفيفة متفرقة                                   : Patchy light rain\n296: أمطار خفيفة                                          : Light rain \n299: أمطار معتدلة أحياناً                                 : Moderate rain at times\n302: أمطار معتدلة                                         : Moderate rain\n305: أمطار كثيفة أحياناً                                  : Heavy rain at times\n308: أمطار كثيفة                                          : Heavy rain\n311: أمطار باردة خفيفة                                   : Light freezing rain\n314: أمطار باردة معتدلة أو كثيفة                        : Moderate or heavy freezing rain\n317: مطر ثلجي خفيف                                       : Light sleet\n320: مطر ثلجي معتدل أو كثيف                             : Moderate or heavy sleet\n323: ثلوج خفيفة متفرقة                                   : Patchy light snow\n326: ثلوج خفيفة                                          : Light snow\n329: ثلوج معتدلة متفرقة                                 : Patchy moderate snow\n332: ثلوج معتدلة                                         : Moderate snow\n335: ثلوج كثيفة متفرقة                                   : Patchy heavy snow\n338: ثلوج كثيفة                                          : Heavy snow\n350: حبيبات جليدية                                       : Ice pellets\n353: رذاذ مطر خفيف                                       : Light rain shower\n356: رذاذ مطر معتدل أو كثيف                             : Moderate or heavy rain shower\n359: رذاذ مطر غزير                                       : Torrential rain shower\n362: رذاذ مطر ثلجي خفيف                                 : Light sleet showers\n365: رذاذ مطر ثلجي معتدل أو كثيف                        : Moderate or heavy sleet showers\n368: رذاذ ثلجي خفيف                                     : Light snow showers\n371: رذاذ ثلجي معتدل أو كثيف                            : Moderate or heavy snow showers\n386: أمطار خفيفة متفرقة مصحوبة بالرعد                  : Patchy light rain with thunder\n389: أمطار معتدلة أو كثيفة متفرقة مصحوبة بالرعد       : Moderate or heavy rain with thunder\n392: ثلوج خفيفة متفرقة مصحوبة بالرعد                   : Patchy light snow with thunder\n395: ثلوج معتدلة أو كثيفة متفرقة مصحوبة بالرعد         : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/az.txt",
    "content": "113: Aydınlı                            : Clear                             : Ясно                         \n113: Günəşli                            : Sunny                             : Солнечно\n116: Dəyişkən buludlu                   : Partly cloudy                     : Переменная облачность\n119: Buludlu                            : Cloudy                            : Облачно              \n122: Buludlu                            : Overcast                          : Пасмурно\n143: Çən                                : Mist                              : Дымка\n176: Bəzi yerlərdə yagış                : Patchy rain possible              : Местами дождь\n179: Bəzi yerlərdə qar                  : Patchy snow possible              : Местами снег\n182: Bəzi yerlərdə qar və yagış         : Patchy sleet possible             : Местами дождь со снегом\n185: Bəzi yerlərdə soyuq çisklinli hava : Patchy freezing drizzle possible  : Местами замерзающая морось\n200: Bəzi yerlərdə tufan                : Thundery outbreaks possible       : Местами грозы              \n227: Yüngül küləkli qar                 : Blowing snow                      : Поземок\n230: Çovqun                             : Blizzard                          : Метель\n248: Duman                              : Fog                               : Туман\n260: Güclü soyuq duman                  : Freezing fog                      : Переохлажденный туман\n263: Bəzi yerlərdə zəif çiskin          : Patchy light drizzle              : Местами слабая морось\n266: zəif çiskin                        : Light drizzle                     : Слабая морось\n281: Soyuq çiskin                       : Freezing drizzle                  : Замерзающая морось\n284: Güclü soyuq çiskin                 : Heavy freezing drizzle            : Сильная замерзающая морось\n293: Bəzi yerlərdə yüngül yagış         : Patchy light rain                 : Местами небольшой дождь\n296: Yüngül yagiş                       : Light rain                        : Небольшой дождь\n299: Bəzi vaxtlarda mülayim yagış       : Moderate rain at times            : Временами умеренный дождь\n302: Mülayim yagış                      : Moderate rain                     : Умеренный дождь\n305: Bəzi vaxtlarda güclü yagış         : Heavy rain at times               : Временами сильный дождь\n308: Güclü yagış                        : Heavy rain                        : Сильный дождь\n311: Zəif soyuq yagış                   : Light freezing rain               : Слабый переохлажденный дождь\n314: Mülayim yaxud güclü soyuq yagış    : Moderate or heavy freezing rain   : Умеренный или сильный переохлажденный дождь\n317: Yüngül yagış və qar                : Light sleet                       : Небольшой дождь со снегом\n320: Mülayim yaxud güclü yagış və qar   : Moderate or heavy sleet           : Умеренный или сильный дождь со снегом\n323: Bəzi yerlərdə yüngül qar           : Patchy light snow                 : Местами небольшой снег\n326: Yüngül qar                         : Light snow                        : Небольшой снег\n329: Bəzi yerlərdə mülayim qar          : Patchy moderate snow              : Местами умеренный снег\n332: Mülayim qar                        : Moderate snow                     : Умеренный снег\n335: Bəzi yerlərdə güclü qar            : Patchy heavy snow                 : Местами сильный снег\n338: Güclü qar                          : Heavy snow                        : Сильный снег\n350: Buzlu yagış                        : Ice pellets                       : Ледяной дождь\n353: Yüngül leysanlı yagış              : Light rain shower                 : Небольшой ливневый дождь\n356: Mülayim yaxud güclü leysanlı yagış : Moderate or heavy rain shower     : Умеренный или сильный ливневый дождь\n359: Çox güclü leysan                   : Torrential rain shower            : Очень сильный ливень\n362: Yüngül leysanlı yagış və sulu qar  : Light sleet showers               : Небольшой ливневый дождь со снегом\n365: Yüngül qar                         : Moderate or heavy sleet showers   : Небольшой снег\n368: Yüngül leysanlı yagış və qar       : Light snow showers                : Небольшой ливневый дождь со снегом\n371: Mülayim yaxud güclü qarlı leysan   : Moderate or heavy snow showers    : Умеренный или сильный снежный ливень\n386: Bəzi yerlərdə yüngül tufan və yagış: Patchy light rain with thunder      : Местами небольшой дождь с грозой\n389: Mülayim yaxud güclü yagış və tufan : Moderate or heavy rain with thunder : Умеренный или сильный дождь с грозой\n392: Bəzi yerlərdə yüngül tufan və qar  : Patchy light snow with thunder      : Местами небольшой снег с грозой\n395: Mülayim yaxud güclü qar və tufan   : Moderate or heavy snow with thunder : Умеренный или сильный снег с грозой \n\n"
  },
  {
    "path": "share/translations/be-help.txt",
    "content": "Выкарыстанне:\n\n    $ curl wttr.in          # надвор'е ў вашым месцы\n    $ curl wttr.in/msq      # надвор'е ў аэрапорце Мінск\n\nМагчымыя тыпы месцазнаходжання:\n\n    /novaja-mysz            # населены пункт\n    /~dipgorodok            # якое-небудзь месца\n    /жабінка                # назва якога-небудзь месца юнікодам на нейкай мове\n    /gme                    # трохлітарны код аэрапорта\n    /@osm.by                # даменнае імя\n    /220121                 # паштовы індэкс\n    /53.953994,27.537774    # каардынаты GPS\n\nАдмысловыя месцазнаходжанні:\n\n    /moon                   # Фаза месяца (дадайце ,+US або ,+France для горада Moon у ЗША або ў Францыі)\n    /moon@2016-10-25        # Фаза Месяца для гэтай даты (@2016-10-25)\n\nАдзінкі вымярэння:\n\n    m                       # метрычная (СІ) (звычайна ўжываецца паўсюль акрамя ЗША)\n    u                       # USCS (ўжываецца ў ЗША)\n    M                       # паказваць хуткасць ветру ў м/с\n\nОпцыі прагляду:\n\n    0                       # толькі надвор'е цяпер\n    1                       # надвор'е цяпер + 1 дзень\n    2                       # надвор'е цяпер + 2 дні\n    A                       # не зважаць на User-Agent і мусова ўжываць фармат вываду ANSI (як у тэрмінале)\n    F                       # не паказваць радок \"Сачыце за навінамі\"\n    n                       # вузкая версія (толькі дзень і ноч)\n    q                       # ціхая версія (без тэксту \"Прагноз надвор'я для\")\n    Q                       # надта ціхая версія (без \"Прагноз надвор'я для\", без назвы месца)\n    T                       # выключыць паслядоўнасці тэрміналу (без колераў)\n\nОпцыі PNG:\n\n    /szklow.png             # выдаць файл PNG\n    p                       # дадаць рамку вакол\n    t                       # празрыстасць 150\n    transparency=...        # празрыстасць ад 0 да 255 (255 = непразрыста)\n\nОпцыі можна спалучаць:\n\n    /iuje?pq\n    /dzvinsk?0pq&lang=be\n    /bielastok_0pq.png      # для PNG опцыі падаюцца пасля знаку _\n    /turau_0pq_lang=be.png  # доўгія опцыі адасабляюцца знакам _\n\nЛакалізацыя:\n\n    $ curl be.wttr.in/Minsk\n    $ curl wttr.in/minsk?lang=be\n    $ curl -H \"Accept-Language: be\" wttr.in/minsk\n\nДаступныя мовы:\n\n    FULL_TRANSLATION (падтрымліваюцца)\n    PARTIAL_TRANSLATION (не цалкам)\n\nАдмысловыя адрасы:\n\n    /:help                  # паказаць гэтую старонку\n    /:bash.function         # паказаць рэкамендаваную функцыю bash wttr()\n    /:translation           # паказаць спіс перакладаў\n\n"
  },
  {
    "path": "share/translations/be.txt",
    "content": "113: Ясна                                       : Clear                               : \n113: Сонечна                                    : Sunny                               : \n116: Пераменная воблачнасць                     : Partly cloudy                       : \n119: Воблачнасць                                : Cloudy                              : \n122: Хмарна                                     : Overcast                            : \n143: Смуга                                      : Mist                                : \n176: Месцамі дождж                              : Patchy rain possible                : \n179: Месцамі снег                               : Patchy snow possible                : \n182: Месцамі дождж са снегам                    : Patchy sleet possible               : \n185: Месцамі сцюдзёная імжа                     : Patchy freezing drizzle possible    : \n200: Месцамі навальніцы                         : Thundery outbreaks possible         : \n227: Нізавая завіруха                           : Blowing snow                        : \n230: Мяцеліца                                   : Blizzard                            : \n248: Туман                                      : Fog                                 : \n260: Сцюдзёны туман                             : Freezing fog                        : \n263: Месцамі невялікая імжа                     : Patchy light drizzle                : \n266: Невялікая імжа                             : Light drizzle                       : \n281: Сцюдзёная імжа                             : Freezing drizzle                    : \n284: Моцная сцюдзёная імжа                      : Heavy freezing drizzle              : \n293: Месцамі невялікі дождж                     : Patchy light rain                   : \n296: Невялікі дождж                             : Light rain                          : \n299: Часам умераны дождж                        : Moderate rain at times              : \n302: Умераны дождж                              : Moderate rain                       : \n305: Часам моцны дождж                          : Heavy rain at times                 : \n308: Моцны дождж                                : Heavy rain                          : \n311: Невялікі сцюдзёны дождж                    : Light freezing rain                 : \n314: Умераны ці моцны сцюдзёны дождж            : Moderate or heavy freezing rain     : \n317: Невялікі дождж са снегам                   : Light sleet                         : \n320: Умераны ці моцны дождж са снегам           : Moderate or heavy sleet             : \n323: Месцамі невялікі снег                      : Patchy light snow                   : \n326: Невялікі снег                              : Light snow                          : \n329: Месцамі умераны снег                       : Patchy moderate snow                : \n332: Умераны снег                               : Moderate snow                       : \n335: Месцамі моцны снег                         : Patchy heavy snow                   : \n338: Моцны снег                                 : Heavy snow                          : \n350: Ледзяны дождж                              : Ice pellets                         : \n353: Слабы ліўневы дождж                        : Light rain shower                   : \n356: Умераны ці моцны ліўневы дождж             : Moderate or heavy rain shower       : \n359: Вельмі моцны ліўневы дождж                 : Torrential rain shower              : \n362: Невялікі ліўневы дождж са снегам           : Light sleet showers                 : \n365: Умераны ці моцны ліўневы дождж са снегам   : Moderate or heavy sleet showers     : \n368: Невялікі ліўневы снег                      : Light snow showers                  : \n371: Умераны ці моцны ліўневы снег              : Moderate or heavy snow showers      : \n386: Месцамі невялікі дождж з навальніцай       : Patchy light rain with thunder      : \n389: Умераны ці моцны дождж з навальніцай       : Moderate or heavy rain with thunder : \n392: Месцамі невялікі снег з навальніцай        : Patchy light snow with thunder      : \n395: Умераны ці моцны снег з навальніцай        : Moderate or heavy snow with thunder : \n"
  },
  {
    "path": "share/translations/bg-help.txt",
    "content": "Употреба:\n\n    $ curl wttr.in          # текущо местоположение\n    $ curl wttr.in/sof      # времето на Софийското летище\n\nПоддържани типове местоположения:\n\n    /paris                  # име на град\n    /~Eiffel+tower          # място/забележителност\n    /Москва                 # Юникод име на местоположение\n    /sof                    # Код на летище (3 букви)\n    /@stackoverflow.com     # име на домейн\n    /94107                  # пощенски код\n    /-78.46,106.79          # GPS координати\n\nСпециални местоположение:\n\n    /moon                   # Фаза на луната (добавете ,+US or ,+France за тези места)\n    /moon@2016-10-25        # Фаза на луната за дата (@2016-10-25)\n\nМерни единици:\n\n    m                       # метрични (SI) (по подразбиране навсякъде извън US)\n    u                       # USCS (използвани по подразбиране в US)\n    M                       # покажи скоростта на вятъра в m/s\n\nВъзможности на изгледа:\n\n    0                       # само текущото време\n    1                       # текущо време + 1 ден\n    2                       # текущо време + 2 дни\n    A                       # игнорирай User-Agent и форсирай ANSI формат (за терминал)\n    F                       # не показвай реда \"Следвай\"\n    n                       # тясна версия (само ден и нощ)\n    q                       # тиха версия (без текст \"Прогноза за времето\")\n    Q                       # свръх тиха версия(без \"Прогноза за времето\", без име на местоположение)\n    T                       # изключи терминалните настройки (без цветове)\n\nPNG възможности:\n\n    /paris.png              # генериране на PNG \n    p                       # Сложи рамка около резултата\n    t                       # полупрозрачен фон 150\n    transparency=...        # полупрозрачен фон от 0 до 255 (255 = непрозрачно)\n\nОпциите могат да се комбинират:\n\n    /Paris?0pq\n    /Paris?0pq&lang=bg\n    /Paris_0pq.png          # при генериране на PNG възможностите са отделени с _\n    /Rome_0pq_lang=bg.png   # дългите опции са разделени с подчертавка\n\nЛокализация:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=bg\n    $ curl -H \"Accept-Language: bg\" wttr.in/paris\n\nПоддържани преводи:\n\n    FULL_TRANSLATION (Напълно преведени)\n    PARTIAL_TRANSLATION (В процес на превод)\n\nСпециални Адреси (URL):\n\n    /:help                  # тази страница\n    /:bash.function         # препоръчителна bash функция wttr()\n    /:translation           # покажи информация за преводачите\n\n"
  },
  {
    "path": "share/translations/bn-help.txt",
    "content": "ব্যবহার:\n\n    $ curl wttr.in          # এখন যেখানে আছ\n    $ curl wttr.in/cdg      # প্যারিস - চার্লস ডি গল বিমানবন্দরে আবহাওয়ার পূর্বাভাস\n\nগৃহীত কমান্ডের ধরন:\n\n    /paris                  # শহরের নাম\n    /~Eiffel+tower          # যেকোনো স্থানের নাম\n    /Москва                 # ইউনিকোড নাম বা যেকোনো ভাষায় যেকোনো স্থানের নাম\n    /muc                    # বিমানবন্দর কোড (3 অক্ষর)\n    /@stackoverflow.com     # ডোমেন নাম\n    /94107                  # জিপ কোড (শুধুমাত্র মার্কিন যুক্তরাষ্ট্রে)\n    /-78.46,106.79          # জিপিএস স্থানাঙ্ক\n\nবিশেষ কমান্ড:\n\n    /moon                   # চাঁদের পর্যায়গুলি (একই নামের শহরগুলি অ্যাক্সেস করতে যোগ করুন, + US বা, + France)\n    /moon@2016-10-25        # এই তারিখের জন্য চাঁদের পর্যায়গুলি (@ 2016-10-25)\n\nইউনিট:\n\n    ?m                      # মেট্রিক সিস্টেম (মার্কিন যুক্তরাষ্ট্র ছাড়া সব জায়গায় ডিফল্ট)\n    ?u                      # USCS (মার্কিন যুক্তরাষ্ট্রের জন্য ডিফল্ট)\n    ?M                      # বাতাসের গতি m / s তে প্রদর্শন করে\n\nবিকল্প প্রদর্শন :\n\n    ?0                      # শুধুমাত্র আজ\n    ?1                      # আজ + আগামীকাল\n    ?2                      # আজ + 2 দিন\n    ?n                      # সংক্ষিপ্ত সংস্করণ (শুধুমাত্র দিন এবং রাত)\n    ?q                      # নীরব সংস্করণ (কোন \"আবহাওয়ার পূর্বাভাস\" হেডার নেই)\n    ?Q                      # অতি-নীরব সংস্করণ (কোন \"আবহাওয়ার পূর্বাভাস\" হেডার নেই, শহরের নাম নেই)\n    ?T                      # ডিজেবল্ড টার্মিনালের জন্য এস্কেপ সিকুএন্সে  (কোনও রঙ নেই)\n\nবিকল্প PNG:\n\n    /paris.png              # একটি PNG ফাইল তৈরি করুন\n    ?p                      # আউটপুটের চারপাশে একটি ফ্রেম যুক্ত করুন\n    ?t                      # স্বচ্ছতা 150 (স্বচ্ছতা 150)\n    transparency=...        # 0 থেকে 255 পর্যন্ত স্বচ্ছতা (255 = অস্বছ)\n\nবিকল্প একত্রিত করুন:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # পিএনজি মোডে বিকল্পগুলি _ এর পরে নির্দিষ্ট করা হয়\n    /Rome_0pq_lang=it.png   # দীর্ঘ বিকল্পগুলি আন্ডারস্কোর দ্বারা পৃথক করা হয় _\n\nভাষান্তর :\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nসাপোরটেড ভাষাসমূহ :\n\n    FULL_TRANSLATION (সম্পূর্ণ সাপোর্ট )\n    PARTIAL_TRANSLATION (অসম্পূর্ণ সাপোর্ট )\n\nবিশেষ ইউআরএলসমূহ:\n\n    /:help                  # এই পেইজটি প্রদর্শন করুন\n    /:bash.function         # রেকমেন্ডেড ব্যাশ  ফাংশন wttr ()\n    /:translation           # wttr.in এর অনুবাদ সম্পর্কে তথ্য প্রদর্শন করুন\n\n"
  },
  {
    "path": "share/translations/bn.txt",
    "content": ": বজ্রঝড়ের সঙ্গে ভারী বৃষ্টি ও শিলাবৃষ্টি                            : Heavy rain and hail with thunderstorm\n: বজ্রঝড়ের সঙ্গে ভারী বৃষ্টি                                   : Heavy rain with thunderstorm\n: বজ্রঝড়ের সঙ্গে হালকা বৃষ্টি ও শিলাবৃষ্টি                           : Light rain and hail with thunderstorm\n: হালকা বৃষ্টি আর তুষারপাত                                  : Light rain and snow shower\n: বজ্রবিদ্যুৎ সহ হালকা বৃষ্টি                                  : Light rain with thunderstorm\n: হালকা তুষারপাত                                        : Light snow shower\n: আংশিক কুয়াশা                                         : Partial fog\n: বজ্রবিদ্যুৎ সহ বৃষ্টি ও শিলাবৃষ্টি                       : Rain and hail with thunderstorm\n: বজ্রবিদ্যুৎ সহ বৃষ্টি                                 : Rain with thunderstorm\n: অগভীর কুয়াশা                                 : Shallow fog\n: ধোঁয়া                                            : Smoke\n: আকস্মিক ঝড়ো বাতাস                                           : Squalls\n: আশেপাশে বজ্রঝড়                                   : Thunderstorm in vicinity\n: তুষার                                            : Snow\n: বৃষ্টি                                            : Rain\n: হালকা বৃষ্টি, ঝরনা বৃষ্টি                            : Light Rain, Rain Shower\n: মাঝারী বৃষ্টিপাত                                          : Rain Shower\n: টুকরো টুকরো কুয়াশা                             : Patches of fog\n: গুঁড়ি গুঁড়ি বৃষ্টি                                          : Drizzle\n: হালকা গুঁড়ি গুঁড়ি বৃষ্টি                                   : Light drizzle\n: হালকা ভাসমান তুষার                               : Low drifting snow\n: হালকা বৃষ্টি ও তুষারপাত                        : Light rain and snow\n: আশেপাশে বৃষ্টিপাত                                   : Shower in vicinity\n: বজ্রবিদ্যুৎ সহ বৃষ্টি                                  : Rain with thunderstorm\n: বৃষ্টি ও তুষারপাত                  : Rain and snow shower\n: বজ্রঝড়                                            : Thunderstorm\n: গুঁড়ি গুঁড়ি মাঝারী বৃষ্টি                                 : Drizzle and rain\n: বজ্রঝড়ের সঙ্গে শিলাবৃষ্টি                                   : Hail with thunderstorm\n: কুয়াশা                                            : Haze\n: হালকা গুঁড়ি গুঁড়ি বৃষ্টি                           : Light drizzle and rain\n: হালকা বৃষ্টি এবং বজ্রঝড় সহ ছোট শিলাবৃষ্টি/তুষারপাত      : Light rain and small hail/snow pallets with thunderstorm\n113 : পরিষ্কার                                  : Clear\n113 : রৌদ্রজ্জ্বল                                    : Sunny\n116 : আংশিক মেঘলা                        : Partly cloudy\n119 : মেঘলা                                      : Cloudy\n122 : মেঘাচ্ছন্ন                                      : Overcast\n143 : কুয়াশা                                      : Mist\n176 : অল্প বৃষ্টি হতে পারে                     : Patchy rain possible\n179 : অল্প তুষারপাত হতে পারে            : Patchy snow possible\n182 : অল্প শিলাবৃষ্টি হতে পারে     : Patchy sleet possible\n185 : ঠাণ্ডা হিমশীতল বৃষ্টির সম্ভাবনা          : Patchy freezing drizzle possible\n200 : বজ্রপাতের প্রাদুর্ভাবের সম্ভাবনা                             : Thundery outbreaks possible\n227 : উড়ন্ত তুষার                                    : Blowing snow\n230 : তুষারঝড়                                     : Blizzard\n248 : কুয়াশা                                   : Fog\n260 : হিমশীতল কুয়াশা                         : Freezing fog\n263 : খণ্ড খণ্ড হালকা গুঁড়ি গুঁড়ি বৃষ্টি                   : Patchy light drizzle\n266 : হালকা গুঁড়ি গুঁড়ি বৃষ্টি                                : Light drizzle\n281 : হিমশীতল গুঁড়ি গুঁড়ি বৃষ্টি                            : Freezing drizzle\n284 : ভারী হিমশীতল গুঁড়ি গুঁড়ি বৃষ্টি                        : Heavy freezing drizzle\n293 : খণ্ড খণ্ড হালকা বৃষ্টি                    : Patchy light rain\n296 : হালকা বৃষ্টি                                 : Light rain\n299 : মাঝে মাঝে মাঝারি বৃষ্টি                  : Moderate rain at times\n302 : মাঝারি বৃষ্টি                                : Moderate rain\n305 : মাঝে মাঝে ভারী বৃষ্টি                    : Heavy rain at times\n308 : ভারী বৃষ্টি                                  : Heavy rain\n311 : হিমশীতল হালকা বৃষ্টি                     : Light freezing rain\n314 : মাঝারি বা ভারী হিমায়িত বৃষ্টি            : Moderate or heavy freezing rain\n317 : হালকা  শিলা               : Light sleet\n320 : মাঝারি বা ভারী শিলাবৃষ্টি    : Moderate or heavy sleet\n323 : খণ্ড খণ্ড হালকা তুষারপাত           : Patchy light snow\n326 : হালকা তুষারপাত                      : Light snow\n329 : খণ্ড খণ্ড মাঝারি তুষারপাত        : Patchy moderate snow\n332 : মাঝারি তুষারপাত                     : Moderate snow\n335 : খণ্ড খণ্ড ভারী তুষারপাত               : Patchy heavy snow\n338 : ভারী তুষারপাত                       : Heavy snow\n350 : বরফ প্যালেট                                       : Ice pellets\n353 : হালকা বৃষ্টির ঝরনা                              : Light rain shower\n356 : মাঝারি বা ভারী বৃষ্টির ঝরনা                    : Moderate or heavy rain shower\n359 : মুষলধারে বৃষ্টি                        : Torrential rain shower\n362 : হালকা বরফমিশ্রিত ঝিরঝির বৃষ্টি              : Light sleet showers\n365 : মাঝারি বা ভারী বরফমিশ্রিত ঝিরঝির বৃষ্টি    : Moderate or heavy sleet showers\n368 : হাল্কা তুষারপাত                     : Light snow showers\n371 : মাঝারি বা ভারী তুষারপাত           : Moderate or heavy snow showers\n386 : বজ্রসহ খণ্ড খণ্ড হালকা বৃষ্টি          : Patchy light rain with thunder\n389 : বজ্রসহ মাঝারি বা ভারী বৃষ্টি           : Moderate or heavy rain with thunder\n392 : বজ্রপাত সহ খণ্ড খণ্ড হালকা তুষারপাত : Patchy light snow with thunder\n395 : মাঝারি বা ভারী তুষারপাত সহ বজ্রপাত  : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/bs.txt",
    "content": "113 : Vedro                                   : Clear\n113 : Sunčano                                 : Sunny\n116 : Djelomična naoblaka                     : Partly cloudy\n119 : Oblačno                                 : Cloudy\n122 : Tmurno                                  : Overcast\n143 : Magla                                   : Mist\n176 : Moguća je slaba kiša                    : Patchy rain possible\n179 : Moguć slab snijeg                       : Patchy snow possible\n182 : Moguća je slaba susnježiva              : Patchy sleet possible\n185 : Moguća je ledena sitna kiša             : Patchy freezing drizzle possible\n200 : Moguća je grmljavina                    : Thundery outbreaks possible\n227 : Topljenje snijega                       : Blowing snow\n230 : Snježna mećava                          : Blizzard\n248 : Magla                                   : Fog\n260 : Ledena magla                            : Freezing fog\n263 : Mjestimično sitna kiša                  : Patchy light drizzle\n266 : Sitna kiša                              : Light drizzle\n281 : Ledena sitna kiša                       : Freezing drizzle\n284 : Teško zamrzavanje                       : Heavy freezing drizzle\n293 : Mjestimično slaba kiša                  : Patchy light rain\n296 : Blaga kiša                              : Light rain\n299 : Ponekad umjerena kiša                   : Moderate rain at times\n302 : Umjerena kiša                           : Moderate rain\n305 : Ponekad je kiša                         : Heavy rain at times\n308 : Pljusak                                 : Heavy rain\n311 : Kruta kiša                              : Light freezing rain\n314 : Umjerena ili teška hladna kiša          : Moderate or heavy freezing rain\n317 : Lagana susnježica                       : Light sleet\n320 : Umjerena ili jaka susnježica            : Moderate or heavy sleet\n323 : Mjestimično slab snijeg                 : Patchy light snow\n326 : Slab snijeg                             : Light snow\n329 : Mjestimično blag snijeg                 : Patchy moderate snow\n332 : Umjeren snijeg                          : Moderate snow\n335 : Umjereno jak snijeg                     : Patchy heavy snow\n338 : Jak snijeg                              : Heavy snow\n350 : Grad/tuča                               : Ice pellets\n353 : Lagani pljusak                          : Light rain shower\n356 : Umjeren ili jak pljusak                 : Moderate or heavy rain shower\n359 : Prolom oblaka                           : Torrential rain shower\n362 : Slaba kiša sa gradom                    : Light sleet showers\n365 : Umjerena ili jaka kiša sa gradom        : Moderate or heavy sleet showers\n368 : Blaga susnježica                        : Light snow showers\n371 : Umjerena ili jaka susnježica            : Moderate or heavy snow showers\n386 : Slaba kiša s grmljavinom                : Patchy light rain with thunder\n389 : Umjerena ili jaka kiša s grmljavinom    : Moderate or heavy rain with thunder\n392 : Slabi snijeg s grmljavinom              : Patchy light snow with thunder\n395 : Umjereni ili teški snijeg s grmljavinom : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/ca-help.txt",
    "content": "Instruccions:\n\n    $ curl wttr.in          # el clima de la ubicació actual\n    $ curl wttr.in/muc      # el clima de l'aeroport de Múnich\n\nTipus d'ubicacions suportades:\n\n    /paris                  # el nom d'una ciutat\n    /~Eiffel+tower          # el nom de qualsevol lloc famós\n    /Москва                 # el nom Unicode de qualsevol lloc en qualsevol idioma\n    /muc                    # el codi d'un aeroport (3 lletres)\n    /@stackoverflow.com     # el nom d'un domini web\n    /94107                  # un codi d'àrea\n    /-78.46,106.79          # coordenades de GPS\n\nLlocs especials:\n\n    /moon                   # la fase de la lluna (afegeix ,+US o ,+France per a aquests països)\n    /moon@2016-10-25        # la fase de la lluna en una data especfica (@2016-10-25)\n\nUnitats:\n\n    ?m                      # mètriques (SI) (l'estàndard a tots els llocs excepte als EEUU)\n    ?u                      # Sistema Unificat de Classificació del Sòl o USCS (l'estàndard als EEUU)\n    ?M                      # mostrar la velocitat del vent en m/s\n\nOpcions de visualització:\n\n    ?0                      # noms el clima actual\n    ?1                      # el clima actual + la previsió d'1 dia\n    ?2                      # el clima actual + la previsió de 2 dies\n    ?n                      # versió curta (només el dia i la nit)\n    ?q                      # versió silenciosa (sense el text de \"El temps a\")\n    ?Q                      # versió supersilenciosa (ni \"El temps a\" ni el nom de la ciutat)\n    ?T                      # desactiva les seqüències del terminal (sense colors)\n\nOpcions de PNG:\n\n    /paris.png              # genera una imatge PNG\n    ?p                      # afegeix una vora al voltant de la imatge\n    ?t                      # transparència 150\n    transparency=...        # transparència de 0 a 255 (255 = sense transparència)\n\nLes opcions es poden utilitzar conjuntament:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # amb PNG les opcions s'especifiquen després del caràcter _\n    /Rome_0pq_lang=it.png   # una llarga seqüència d'opcions es poden separar amb el caràcter _\n\nUbicació:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nIdiomes suportats:\n\n    FULL_TRANSLATION (soportados)\n    PARTIAL_TRANSLATION (en progreso)\n\nURLs especials:\n\n    /:help                  # mostra aquesta pàgina\n    /:bash.function         # suggereix una funció wttr() en bash\n    /:translation           # mostra informació sobre els traductors\n"
  },
  {
    "path": "share/translations/ca.txt",
    "content": "113 : Clar                                  : Clear\n113 : Assolellat                            : Sunny\n116 : Parcialment ennuvolat                 : Partly cloudy\n119 : Ennuvolat                             : Cloudy\n122 : Molt ennuvolat                        : Overcast\n143 : Boirina                               : Mist\n176 : Possible pluja intermitent            : Patchy rain possible\n179 : Possible neu intermitent              : Patchy snow possible\n182 : Possible aiguaneu intermitent         : Patchy sleet possible\n185 : Possible plugim gelat intermitent     : Patchy freezing drizzle possible\n200 : Possible tempesta elèctrica           : Thundery outbreaks possible\n227 : Tempesta de neu                       : Blowing snow\n230 : Torb                                  : Blizzard\n248 : Boira                                 : Fog\n260 : Boira gebradora                       : Freezing fog\n263 : Plugim suau intermitent               : Patchy light drizzle\n266 : Plugim suau                           : Light drizzle\n281 : Plugim gelat                          : Freezing drizzle\n284 : Plugim gelat intens                   : Heavy freezing drizzle\n293 : Pluja suau intermitent                : Patchy light rain\n296 : Pluja suau                            : Light rain\n299 : Pluja moderada puntual                : Moderate rain at times\n302 : Pluja moderada                        : Moderate rain\n305 : Pluja forta puntual                   : Heavy rain at times\n308 : Pluja forta                           : Heavy rain\n311 : Calamarsa                             : Light freezing rain\n314 : Pedra o granís                        : Moderate or heavy freezing rain\n317 : Aiguaneu suau                         : Light sleet\n320 : Aiguaneu moderada o forta             : Moderate or heavy sleet\n323 : Nevada suau intermitent               : Patchy light snow\n326 : Nevada suau                           : Light snow\n329 : Nevada moderada intermitent           : Patchy moderate snow\n332 : Nevada moderada                       : Moderate snow\n335 : Nevada forta intermitent              : Patchy heavy snow\n338 : Nevada forta                          : Heavy snow\n350 : Gebra                                 : Ice pellets\n353 : Ruixats de pluja suau                 : Light rain shower\n356 : Ruixats de pluja moderada o forta     : Moderate or heavy rain shower\n359 : Ruixats de pluja torrencial           : Torrential rain shower\n362 : Ruixats d'aiguaneu suau               : Light sleet showers\n365 : Ruixats d'aiguaneu moderada o forta   : Moderate or heavy sleet showers\n368 : Ruixats de neu suau                   : Light snow showers\n371 : Nevada moderada o forta               : Moderate or heavy snow showers\n386 : Intervals de pluges amb trons         : Patchy light rain with thunder\n389 : Pluja moderada o forta amb trons      : Moderate or heavy rain with thunder\n392 : Nevada lleugera intermitent amb trons : Patchy light snow with thunder\n395 : Nevada moderada o forta amb trons     : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/cs-help.txt",
    "content": "Použití:\n\n    $ curl wttr.in          # lokální informace\n    $ curl wttr.in/muc      # počasí v letšiti v Mnichově\n\nPodporované typy lokací:\n\n    /paris                  # název města\n    /~Eiffel+tower          # jakákoliv lokace (+ pro mezery)\n    /Москва                 # Unicode názvy pro lokace (včetně češtiny)\n    /muc                    # kód letiště (3 písmena)\n    /@stackoverflow.com     # doména\n    /94107                  # kód areálu\n    /-78.46,106.79          # GPS souřadnice\n\nSpeciální lokace:\n\n    /moon                   # Fáze měsíce (přidejte ,+US nebo ,+France pro tyto města)\n    /moon@2016-10-25        # Fáze měsíce pro datum (@2016-10-25)\n\nJednotky:\n\n    m                       # metrické (SI) (used by default everywhere except US)\n    u                       # USCS (used by default in US)\n    M                       # zobrazení rychlosti větru v m/s\n\nNastavení zobrazení:\n\n    0                       # pouze momentální počasí\n    1                       # momentální počasí + dnešní předpověď\n    2                       # momentální počasí + dnešní + zítřejší předpověď\n    A                       # ignorovat User-Agent a používát ANSI výstup (terminál)\n    F                       # nezobrazovat řádek \"Odebírat\"\n    n                       # zmenšená verze (jen den a noc)\n    q                       # tichá verze (bez textu \"Předpověď počasí\")\n    Q                       # extra tichá verze (bez textu \"Předpověď počasí\" a názvu města)\n    T                       # vypnutí barev\n\nnastavení PNG:\n\n    /paris.png              # vygeneruje PNG\n    p                       # přidá rámeček\n    t                       # průhlednost 150\n    transparency=...        # průhlednost od 0 do 255 (255 = neprůhledný)\n\nNastavení se dá kombinovat:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # v PNG se nastavení přidává za _\n    /Rome_0pq_lang=it.png   # dlouhé nastavení se odděluje _\n\nLokalizace:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nPodporované jazyky:\n\n    ar af be ca da de el et fr fa hi hu ia id it nb nl oc pl pt-br ro ru tr th uk vi zh-cn zh-tw (supported)\n    az bg bs cy cs eo es eu fi ga hi hr hy is ja jv ka kk ko ky lt lv mk ml nl fy nn pt pt-br sk sl sr sr-lat sv sw te uz zh zu he (in progress)\n\nSpeciální URL:\n\n    /:help                  # tato stránka\n    /:bash.function         # zobrazí doporučenou bash funkci wttr()\n    /:translation           # zobrazí informace o překladech\n\n"
  },
  {
    "path": "share/translations/cs.txt",
    "content": ": Unášený sníh                                      : Low drifting snow\n: Částečná mlha                                     : Patches of fog\n: Mrholení                                          : Drizzle\n: Slabé mrholení                                    : Light drizzle\n: Sníh                                              : Snow\n: Déšť                                              : Rain\n: Lehký déšť                                        : Light Rain\n: Dešťová sprcha                                    : Rain Shower\n113: Jasno                                          : Clear\n113: Slunečno                                       : Sunny\n116: Částečně zataženo                              : Partly cloudy\n119: Zataženo                                       : Cloudy\n122: Zamračeno                                      : Overcast\n143: MLha                                           : Mist\n176: Možnost deště                                  : Patchy rain possible\n179: Možnost sněžení                                : Patchy snow possible\n182: Možnost kroup                                  : Patchy sleet possible\n185: Možnost mrazivého mrholení                     : Patchy freezing drizzle possible\n200:                                                : Thundery outbreaks possible\n227: Padající sníh                                  : Blowing snow\n230: Vánice                                         : Blizzard\n248: Mlha                                           : Fog\n260: Mrazivá mlha                                   : Freezing fog\n263: Nepravidelné slabé mrholení                    : Patchy light drizzle\n266: Slabé mrholení                                 : Light drizzle\n281: Mrazivé mrholení                               : Freezing drizzle\n284: Silné mrazivé mrholení                         : Heavy freezing drizzle\n293: Nepravidelný slabý déšť                        : Patchy light rain\n296: Slabý déšť                                     : Light rain\n299: Občasný déšť                                   : Moderate rain at times\n302: Déšť                                           : Moderate rain\n305: Občasný hustý déšť                             : Heavy rain at times\n308: Silný déšť                                     : Heavy rain\n311: Slabý mrazivý déšť                             : Light freezing rain\n314: Smíšený mrazivý déšť                           : Moderate or heavy freezing rain\n317: Slabé kroupění                                 : Light sleet\n320: Smíšené kroupění                               : Moderate or heavy sleet\n323: Nepravidelné slabé sněžení                     : Patchy light snow\n326: Slabé sněžení                                  : Light snow\n329: Nepravidelné sněžení                           : Patchy moderate snow\n332: Sněžení                                        : Moderate snow\n335: Nepravidelné husté sněžení                     : Patchy heavy snow\n338: Silné sněžení                                  : Heavy snow\n350: Kroupy                                         : Ice pellets\n353: Lehká déšťová sprcha                           : Light rain shower\n356: Smíšený déšťová sprcha                         : Moderate or heavy rain shower\n359: Přívalová déšťová sprcha                       : Torrential rain shower\n362: Slabé přeháňková sprcha                        : Light sleet showers\n365: Silné přeháňková sprcha                        : Moderate or heavy sleet showers\n368: Slabé sprcha se sněžením                       : Light snow showers\n371: Silné sprcha se sněžením                       : Moderate or heavy snow showers\n386: Nepravidelná slabá bouřka                      : Patchy light rain with thunder\n389: Silná bouřka                                   : Moderate or heavy rain with thunder\n392: Nepravidelný slabá bouřka se sněžením          : Patchy light snow with thunder\n395: Silné sněžení s bouřkou                        : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/cy.txt",
    "content": "113: Glir                               : Clear\n113: Heulog                             : Sunny\n116: Rhannol gymylog                    : Partly cloudy\n119: Cymylog                            : Cloudy\n122: Cymylog                            : Overcast\n143: Niwlog                             : Mist\n176: Glaw anghyson yn bosib             : Patchy rain possible\n179: Eira anghyson yn bosib             : Patchy snow possible\n182: Eirlaw anghyson yn bosib           : Patchy sleet possible\n185: Rhewi a glaw mân anghyson yn bosib : Patchy freezing drizzle possible\n200: Mellt yn bosib                     : Thundery outbreaks possible\n227: Eira yn cael ei chwythu            : Blowing snow\n230: Storm eira                         : Blizzard\n248: Niwl                               : Fog\n260: Niwl rhewllyd                      : Freezing fog\n263: Glaw mân ysgafn anghyson           : Patchy light drizzle\n266: Glaw mân ysgafn                    : Light drizzle\n281: Glaw mân rhewllyd                  : Freezing drizzle\n284: Glaw mân rhewllyd trwm               : Heavy freezing drizzle\n293: Glaw ysgafn anghyson               : Patchy light rain\n296: Glaw ysgafn                        : Light rain\n299: Glaw cymedrol ar adegau            : Moderate rain at times\n302: Glaw cymedrol                      : Moderate rain\n305: Glaw trwm ar adegau                : Heavy rain at times\n308: Glaw trwm                          : Heavy rain\n311: Glaw rhewllyd ysgafn               : Light freezing rain\n314: Glaw rhewllyd trwm neu cymedrol    : Moderate or heavy freezing rain\n317: Eirlaw ysgafn                      : Light sleet\n320: Eirlaw cymedrol neu trwn           : Moderate or heavy sleet\n323: Eira ysgafn anghyson               : Patchy light snow\n326: Eira ysgafn                        : Light snow\n329: Eira cymedrol anghyson             : Patchy moderate snow\n332: Eira cymedrol                      : Moderate snow\n335: Eira trwm anghyson                 : Patchy heavy snow\n338: Eira trwm                          : Heavy snow\n350: Pelenni iâ                         : Ice pellets\n353: Cawod o law ysgafn                 : Light rain shower\n356: Cawod o law cymedrol neu trwm      : Moderate or heavy rain shower\n359: Cawod o law trwm                   : Torrential rain shower\n362: Cawodydd o eirlaw ysgafn           : Light sleet showers\n365: Cawodydd o eirlaw cymedrol new trwm: Moderate or heavy sleet showers\n368: Cawodydd o eira ysgafn             : Light snow showers\n368: Cawod o law ac eira ysgafn, Niwl   : Light Rain And Snow Shower, Mist\n371: Cawodydd o eira cymedrol neu trwm  : Moderate or heavy snow showers\n386: Glaw ysgafn anghyson gyda mellt    : Patchy light rain with thunder\n389: Glaw cymedrol neu trwm gyda mellt  : Moderate or heavy rain with thunder\n392: Eira ysgafn anghyson gyda mellt    : Patchy light snow with thunder\n395: Eira cymedrol neu trwm gyda mellt  : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/da-help.txt",
    "content": "Brugsanvisning:\n\n    $ curl wttr.in          # Nuværende lokation\n    $ curl wttr.in/aarhus   # Vejret i Aarhus\n\nUnderstøttede lokationsspecifikationer:\n\n    /Skanderborg            # Bynavn\n    /~Aarhus+stadion        # Valgfri lokation\n    /Москва                 # Unicode-navn på lokation på alle sprog\n    /cph                    # Flyvepladskode (3 bogstaver)\n    /@stackoverflow.com     # Domænenavn\n    /94107                  # Postnummer (kun USA)\n    /-78.46,106.79          # GPS-koordinater\n\nSærlige lokationer:\n\n    /moon                   # Månefase (brug med ,+US eller ,+France for disse lokationer)\n    /moon@2014-10-26        # Månefase for specifik dato (@2014-10-26)\n\nEnheder:\n\n    ?m                      # Metrisk (SI) (standard alle steder undtagen i USA)\n    ?u                      # USCS (standard i USA)\n    ?M                      # Vindstyrke i meter per sekund\n\nVisningsvalg:\n\n    ?0                      # Øjebliksvejr\n    ?1                      # Øjebliksvejr + 1 dag\n    ?2                      # Øjebliksvejr + 2 dage\n    ?n                      # Simplificeret visning (kun dag og nat)\n    ?q                      # Begrænset visning (ingen \"Vejrmelding\"-tekst)\n    ?Q                      # Meget begrænset visning (ingen \"Vejrmelding\", ingen bynavn)\n    ?T                      # Ingen terminalsekvenser (ingen farver)\n\nPNG valg:\n\n    /paris.png              # Generér en PNG-fil\n    ?p                      # Tilføj ramme\n    ?t                      # Sæt gennemsigtighed til 150\n    transparency=...        # Tilpas gennemsigtighed fra 0 til 255 (255 = ikke gennemsigtigt)\n\nKombinationsmuligheder:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # For .PNG er fil-modus specificeret efter _\n    /Rome_0pq_lang=it.png   # Sprog defineres efter underscore (_)\n\nOversættelser:\n\n    $ curl da.wttr.in/Aarhus\n    $ curl wttr.in/aarhus?lang=da\n    $ curl -H \"Accept-Language: da\" wttr.in/aarhus\n\nUnderstøttede sprog:\n\n    FULL_TRANSLATION (understøttet)\n    PARTIAL_TRANSLATION (under udarbejdelse)\n\nSærlige URL'er:\n\n    /:help                  # Vis denne side\n    /:bash.function         # Vis den foreslåede bash-funktion wttr()\n    /:translation           # Vis information om oversætterne\n"
  },
  {
    "path": "share/translations/da.txt",
    "content": "113: Skyfrit                                : Clear\n113: Sol                                    : Sunny\n116: Delvist skyet                          : Partly cloudy\n119: Skyet                                  : Cloudy\n122: Overskyet                              : Overcast\n143: Diset                                  : Mist\n176: Skiftende regn                         : Patchy rain possible\n179: Skiftende sne                          : Patchy snow possible\n182: Skiftende slud                         : Patchy sleet possible\n185: Skiftende kold småregn                 : Patchy freezing drizzle possible\n200: Fare for torden                        : Thundery outbreaks possible\n227: Snefygning                             : Blowing snow\n230: Snestorm                               : Blizzard\n248: Tåge                                   : Fog\n260: Frysende tåge                          : Freezing fog\n263: Skiftende og let støvregn              : Patchy light drizzle\n266: Let støvregn                           : Light drizzle\n281: Kold støvregn                          : Freezing drizzle\n284: Kraftig kold regn                      : Heavy freezing drizzle\n293: Skiftende let regn                     : Patchy light rain\n296: Let regn                               : Light rain\n299: Skiftevist en smule regn               : Moderate rain at times\n302: En smule regn                          : Moderate rain\n305: Skiftevist kraftig regn                : Heavy rain at times\n308: Kraftig regn                           : Heavy rain\n311: Let og frysende regn                   : Light freezing rain\n314: Moderat eller kraftig frysende regn    : Moderate or heavy freezing rain\n317: Let slud                               : Light sleet\n320: Moderat eller kraftig slud             : Moderate or heavy sleet\n323: Byger af let sne                       : Patchy light snow\n326: Let sne                                : Light snow\n329: Byger med moderat sne                  : Patchy moderate snow\n332: Moderat sne                            : Moderate snow\n335: Byger med kraftig sne                  : Patchy heavy snow\n338: Kraftig sne                            : Heavy snow\n350: Haglbyger                              : Ice pellets\n353: Lette regnbyger                        : Light rain shower\n356: Moderate eller kraftige regnbyger      : Moderate or heavy rain shower\n359: Skybrud                                : Torrential rain shower\n362: Lette sludbyger                        : Light sleet showers\n365: Moderate eller kraftige sludbyger      : Moderate or heavy sleet showers\n368: Lette snebyger                         : Light snow showers\n371: Moderate eller kraftige snebyger       : Moderate or heavy snow showers\n386: Byger af let regn med torden           : Patchy light rain with thunder\n389: Moderat eller krafig regn med torden   : Moderate or heavy rain with thunder\n392: Byger af let sne med torden            : Patchy light snow with thunder\n395: Moderat eller kraftig sne med torden   : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/de-help.txt",
    "content": "Benutzung:\n\n    $ curl wttr.in          # aktuelle Position\n    $ curl wttr.in/muc      # Wetter, Flughafen München\n\nUnterstütze Ortstypen:\n\n    /paris                  # Stadtname\n    /~Eiffel+tower          # wählbarer Ort\n    /Москва                 # Unicode Name von einem Ort in irgendeiner Sprache\n    /muc                    # IATA-Flughafencode (3 Buchstaben)\n    /@stackoverflow.com     # Domainname\n    /94107                  # Area code (nur für USA)\n    /-78.46,106.79          # GPS Koordinaten\n\nSpezielle Orte:\n\n    /moon                   # Mondphase (bei Benutzung von z.B. ,+US oder ,+France wird die Phase des jeweiligen Ortes angezeigt)\n    /moon@2016-10-25        # Mondphase eines Tages (@2016-10-25)\n\nMaßeinheiten:\n\n    ?m                      # metrisch (SI) (standard überall außer bei Orten in den USA)\n    ?u                      # USCS (standard in den USA)\n    ?M                      # Windgeschwindigkeiten in m/s\n\nAnsichteinstellungen:\n\n    ?0                      # Zeige nur aktuelles Wetter\n    ?1                      # Zeige aktuelles Wetter + 1 Tag\n    ?2                      # Zeige aktuelles Wetter + 2 Tage\n    ?n                      # Kleine Version (nur Tag & Nacht)\n    ?q                      # Schmale Version (kein 'Wetter Report' Text)\n    ?Q                      # Superschmale Version (kein 'Wetter Report' Text und Ortsname)\n    ?T                      # Keine Farben\n\nPNG optionen:\n\n    /paris.png              # generiert eine PNG Datei\n    ?p                      # fügt einen Rahmen hinzu\n    ?t                      # Transparenz von 150\n    transparency=...        # Transparenz von 0 bis 255 (255 = nicht transparent)\n\nOptionen können kombiniert werden:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # wird eine PNG benutzt, dann werden diese Optionen nach einem _ (Unterstrich) hinzugefügt\n    /Rome_0pq_lang=it.png   # einzelne Optionen werden mit einem _ (Unterstrich) getrennt\n\nLokalisierung:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nUnterstützte Sprachen:\n\n    FULL_TRANSLATION (supported)\n    PARTIAL_TRANSLATION (in progress)\n\nSpezialseiten:\n\n    /:help                  # zeigt diese Seite an\n    /:bash.function         # zeigt empfehlenswerte bash Funktion wttr() an\n    /:translation           # zeigt Informationen der Übersetzer an\n\n"
  },
  {
    "path": "share/translations/de.txt",
    "content": ": Dunst in der Nähe                                         : Haze in vicinity\n: Starker Regen- und Schneeschauer                          : Heavy rain and snow shower\n: Starker Regenschauer                                      : Heavy rain shower\n: Leichter Nieselregen und Schneegriesel                    : Light drizzle and snow grains\n: Leichter Regen- und Nebelschauer                          : Light rain and mist shower\n: Leichter Hagel-/Schneegraupelschauer                      : Light small hail/snow pellets shower\n: Leichter Schauer unbekannter Niederschlag                 : Light unknown precipitation shower\n: Regen und leichter Hagel/Schneegraupel mit Gewitter       : Rain and small hail/snow pellets with thunderstorm\n: Schneeschauer in der Nähe                                 : Snow shower in vicinity\n: Gewitterausbrüche in der Nähe                             : Thundery outbreaks nearby\n: Bodennahe Schneeverwehung                                 : Low drifting snow\n: Nebelfelder                                               : Patches of fog\n: Nieselregen                                               : Drizzle\n: Leichter Nieselregen und Regen                            : Light drizzle and rain\n: Schnee                                                    : Snow\n: Regen                                                     : Rain\n: Regenschauer                                              : Rain Shower\n: Sandverwehungen                                           : Blowing sand\n: Weitläufige Sandverwehungen                               : Blowing widespread dust\n: Weitläufige Sandverwehungen in der Nähe                   : Blowing widespread dust in vicinity\n: Nieselregen und Nebel                                     : Drizzle and fog\n: Nieselregen und Regen                                     : Drizzle and rain\n: Nieselregen und Regenschauer                              : Drizzle and rain shower\n: Nieselregen mit Gewitter                                  : Drizzle with thunderstorm\n: Sandsturm                                                 : Dust storm\n: Nebel in der Nähe                                         : Fog in vicinity\n: Gefrierender Nieselregen und Regen                        : Freezing drizzle and rain\n: Gefrierender Nebel                                        : Freezing mist\n: Gefrierender Regen                                        : Freezing rain\n: Gefrierender Regen und Schnee                             : Freezing rain and snow\n: Gefrierender unbekannter Niederschlag                     : Freezing unknown precipitation\n: Trichterwolke in der Nähe                                 : Funnel cloud in vicinity\n: Hagelschauer                                              : Hail shower\n: Hagel mit Gewitter                                        : Hail with thunderstorm\n: Dunst                                                     : Haze\n: Starke Schneeverwehungen                                  : Heavy blowing snow\n: Starker Nieselregen                                       : Heavy drizzle\n: Starker Nieselregen und Regen                             : Heavy drizzle and rain\n: Starker gefrierender unbekannter Niederschlag             : Heavy freezing unknown precipitation\n: Starker Hagel mit Gewitter                                : Heavy hail with thunderstorm\n: Starke Eiskörner                                          : Heavy ice pallets\n: Starker Regen und Hagelschauer                            : Heavy rain and hail shower\n: Starker Regen und Hagelschauer mit Gewitter               : Heavy rain and hail with thunderstorm\n: Starker Regen und kleiner Hagelschauer                    : Heavy rain and small hail/snow pallets shower\n: Starker Regen und kleiner Hagel mit Gewitter              : Heavy rain and small hail/snow pallets with thunderstorm\n: Starker Regen und Schnee                                  : Heavy rain and snow\n: Starker Regen und Schnee sowie kleiner Hagel mit Gewitter : Heavy rain and snow and small hail/snow pallets with thunderstorm\n: Starker Regen mit Gewitter                                : Heavy rain with thunderstorm\n: Starker kleiner Hagelschauer                              : Heavy small hail/snow pallets shower\n: Starker kleiner Hagel mit Gewitter                        : Heavy small hail/snow pallets with thunderstorm\n: Starker Schnee und kleiner Hagelschauer                   : Heavy snow and small hail/snow pallets shower\n: Starker Schnee und kleiner Hagel mit Gewitter             : Heavy snow and small hail/snow pallets with thunderstorm\n: Starker Schneeschauer                                     : Heavy snow shower\n: Starker Schnee mit Gewitter                               : Heavy snow with thunderstorm\n: Eiskristalle                                              : Ice crystals\n: Eiskörner                                                 : Ice pallets\n: Leichte Schneeverwehungen                                 : Light blowing snow\n: Leichter Nieselregen und Nebel                            : Light drizzle and fog\n: Leichter Nieselregen und Eiskörner                        : Light drizzle and ice pallets\n: Leichter Nieselregen und Regen und Schnee                 : Light drizzle and rain and snow\n: Leichter Nieselregen und Regenschauer                     : Light drizzle and rain shower\n: Leichter Nieselregen und Regen mit Gewitter               : Light drizzle and rain with thunderstorm\n: Leichter Nieselregen und Schnee                           : Light drizzle and snow\n: Leichter Nieselregen mit Gewitter                         : Light drizzle with thunderstorm\n: Leichter gefrierender Nieselregen                         : Light freezing drizzle\n: Leichter gefrierender Nieselregen und Regen               : Light freezing drizzle and rain\n: Leichter gefrierender Nieselregen und Schnee              : Light freezing drizzle and snow\n: Leichter gefrierender Nebel                               : Light freezing fog\n: Leichter gefrierender Regen und Schnee                    : Light freezing rain and snow\n: Leichter gefrierender Schneegraupel und Nebel             : Light freezing snow grains and fog\n: Leichter gefrierender unbekannter Niederschlag            : Light freezing unknown precipitation\n: Leichter Hagelschauer                                     : Light hail shower\n: Leichte Eiskristalle                                      : Light ice crystals\n: Leichte Eiskörner                                         : Light ice pallets\n: Leichte bodennahe Verwehungen                             : Light low drifting\n: Leichte bodennahe Schneeverwehungen                       : Light low drifting snow\n: Leichter Regen und Hagelschauer                           : Light rain and hail shower\n: Leichter Regen und Hagel mit Gewitter                     : Light rain and hail with thunderstorm\n: Leichter Regen und Eiskörner                              : Light rain and ice pallets\n: Leichter Regen und Nebel                                  : Light rain and mist\n: Leichter Regen und kleiner Hagelschauer                   : Light rain and small hail/snow pallets shower\n: Leichter Regen und kleiner Hagel mit Gewitter             : Light rain and small hail/snow pallets with thunderstorm\n: Leichter Regen und Schnee                                 : Light rain and snow\n: Leichter Regen und Schnee sowie kleiner Hagelschauer      : Light rain and snow and small hail/snow pallets shower\n: Leichter Regen und Schneegraupel                          : Light rain and snow grains\n: Leichter Regen und Schneeschauer                          : Light rain and snow shower\n: Leichter Regen und Schnee mit Gewitter                    : Light rain and snow with thunderstorm\n: Leichter Regen mit Gewitter                               : Light rain with thunderstorm\n: Leichter Schauer                                          : Light shower\n: Leichter Hagelschauer                                     : Light showers of ice pellets\n: Leichter kleiner Hagel                                    : Light small hail/snow pallets\n: Leichter kleiner Hagelschauer                             : Light small hail/snow pallets shower\n: Leichter kleiner Hagel mit Gewitter                       : Light small hail/snow pallets with thunderstorm\n: Leichter Schnee und Eiskörner                             : Light snow and ice pallets\n: Leichter Schnee und kleiner Hagel                         : Light snow and small hail/snow pallets\n: Leichter Schneeschauer mit kleinem Hagel                  : Light snow and small hail/snow pallets shower\n: Leichter Schnee mit kleinem Hagel und Gewitter            : Light snow and small hail/snow pallets with thunderstorm\n: Leichter Schnee und Schneegraupel                         : Light snow and snow grains\n: Leichtes Schneegraupel                                    : Light snow grains\n: Leichter Schneeschauer                                    : Light snow shower\n: Leichter Schnee mit Gewitter                              : Light snow with thunderstorm\n: Leichtes Gewitter                                         : Light thunderstorm\n: Leichter unbekannter Niederschlag                         : Light unknown precipitation\n: Leicht ausgeprägte Staub- oder Sandwirbel                 : Light well-developed dust/sand whirls\n: Bodennaher verwehender Sand                               : Low drifting sand\n: Bodennaher verwehender Staub                              : Low drifting widespread dust\n: Nebel mit Gewitter                                        : Mist with thunderstorm\n: Mäßig bis starker Regen mit Gewitter                      : Moderate or heavy rain in area with thunder\n: Mäßig bis starker Schnee mit Gewitter                     : Moderate or heavy snow in area with thunder\n: Teilweise Nebel                                           : Partial fog\n: Nebelfelder in der Nähe                                   : Patches of fog in vicinity\n: Ortsweise gefrierender Nieselregen                        : Patchy freezing drizzle nearby\n: Gebietsweise leichter Regen mit Gewitter                  : Patchy light rain in area with thunder\n: Gebietsweise leichter Schnee mit Gewitter                 : Patchy light snow in area with thunder\n: Örtlich Regen                                             : Patchy rain nearby\n: Örtlich Schneeregen                                       : Patchy sleet nearby\n: Örtlich Schnee                                            : Patchy snow nearby\n: Regen und Hagelschauer                                    : Rain and hail shower\n: Regen und Hagel mit Gewitter                              : Rain and hail with thunderstorm\n: Regen und Nebel                                           : Rain and mist\n: Regen und Nebel mit Gewitter                              : Rain and mist with thunderstorm\n: Regen und kleiner Hagelschauer                            : Rain and small hail/snow pallets shower\n: Regen und kleiner Hagel mit Gewitter                      : Rain and small hail/snow pallets with thunderstorm\n: Regen und Schnee                                          : Rain and snow\n: Regen und Schnee sowie kleiner Hagelschauer               : Rain and snow and small hail/snow pallets shower\n: Regen und Schneegraupel                                   : Rain and snow grains\n: Regen und Schneeschauer                                   : Rain and snow shower\n: Regen und Schnee mit Gewitter                             : Rain and snow with thunderstorm\n: Regen in der Nähe                                         : Rain in vicinity\n: Regenschauer in der Nähe                                  : Rain shower in vicinity\n: Regen mit Gewitter                                        : Rain with thunderstorm\n: Sand                                                      : Sand\n: Sandsturm                                                 : Sandstorm\n: Seichter Nebel                                            : Shallow fog\n: Seichter Dunst                                            : Shallow mist\n: Schauer                                                   : Shower\n: Schauer in der Nähe                                       : Shower in vicinity\n: Leichter Hagel                                             : Small hail/snow pallets\n: Leichter Hagelschauer                                      : Small hail/snow pallets shower\n: Leichter Hagel mit Gewitter                                : Small hail/snow pallets with thunderstorm\n: Rauch                                                     : Smoke\n: Schnee und Eiskörner                                      : Snow and ice pallets\n: Schnee und Nebel                                          : Snow and mist\n: Schnee- und leichte Hagelschauer                           : Snow and small hail/snow pellets shower\n: Schnee- und leichte Hagelschauer mit Gewitter              : Snow and small hail/snow pallets with thunderstorm\n: Schnee und Schneegraupel                                  : Snow and snow grains\n: Schneegraupel                                             : Snow grains\n: Schneeschauer                                             : Snow shower\n: Schnee mit Gewitter                                       : Snow with thunderstorm\n: Gewitterböen                                              : Squalls\n: Gewitter                                                  : Thunderstorm\n: Gewitter in der Nähe                                      : Thunderstorm in vicinity\n: Gewitter in der Nähe                                      : Thundery outbreaks in nearby\n: Unbekannter Niederschlag                                  : Unknown precipitation\n: Schauer mit unbekanntem Niederschlag                      : Unknown precipitation shower\n: Unbekannter Niederschlag mit Gewitter                     : Unknown precipitation with thunderstorm\n: Vulkanasche                                               : Volcanic ash\n: Vulkanasche in der Nähe                                   : Volcanic ash in vicinity\n: Stark ausgeprägte Staub-/Sandwirbel in der Nähe           : Well-developed dust/sand whirls in vicinity\n: flächendeckender Staub                                    : Widespread dust\n113: Wolkenlos                                              : Clear\n113: Sonnig                                                 : Sunny\n116: Leicht Bewölkt                                         : Partly cloudy\n119: Wolkig                                                 : Cloudy\n122: Bedeckt                                                : Overcast\n143: Nebel                                                  : Mist\n176: Stellenweise Regen möglich                             : Patchy rain possible\n179: Stellenweise Schnee möglich                            : Patchy snow possible\n182: Stellenweise Schneeregen möglich                       : Patchy sleet possible\n185: Stellenweise gefrierende Nässe möglich                 : Patchy freezing drizzle possible\n200: Gewitter möglich                                       : Thundery outbreaks possible\n227: Schneesturm                                            : Blowing snow\n230: Blizzard                                               : Blizzard\n248: Nebel                                                  : Fog\n260: Gefrierender Nebel                                     : Freezing fog\n263: Stellenweise Nieselregen                               : Patchy light drizzle\n266: Leichter Nieselregen                                   : Light drizzle\n281: Gefrierender Nieselregen                               : Freezing drizzle\n284: Starker gefrierender Nieselregen                       : Heavy freezing drizzle\n293: Stellenweise leichter Regen                            : Patchy light rain\n296: Leichter Regen                                         : Light rain\n299: Stellenweise gemäßigter Regen                          : Moderate rain at times\n302: Gemäßigter Regen                                       : Moderate rain\n305: Stellenweise starker Regen                             : Heavy rain at times\n308: Starker Regen                                          : Heavy rain\n311: Leichter gefrierender Regen                            : Light freezing rain\n314: Gemäßigter oder starker gefrierender Regen             : Moderate or heavy freezing rain\n317: Leichter Schneeregen                                   : Light sleet\n320: Gemäßigter oder starker Schneeregen                    : Moderate or heavy sleet\n323: Stellenweise leichter Schneefall                       : Patchy light snow\n326: Leichter Schneefall                                    : Light snow\n329: Stellenweise gemäßigter Schneefall                     : Patchy moderate snow\n332: Gemäßigter Schneefall                                  : Moderate snow\n335: Stellenweise starker Schneefall                        : Patchy heavy snow\n338: Starker Schneefall                                     : Heavy snow\n350: Eiskörner                                              : Ice pellets\n353: Leichter Regen                                         : Light rain shower\n356: Gemäßigter oder starker Regen                          : Moderate or heavy rain shower\n359: Wolkenbruch                                            : Torrential rain shower\n362: Leichter Schneeregen                                   : Light sleet showers\n365: Gemäßigter oder starker Schneeregen                    : Moderate or heavy sleet showers\n368: Leichter Schneefall                                    : Light snow showers\n371: Gemäßigter oder starker Schneefall                     : Moderate or heavy snow showers\n386: Stellenweise leichter Regen mit Gewitter               : Patchy light rain with thunder\n389: Gemäßigter oder starker Regen mit Gewitter             : Moderate or heavy rain with thunder\n392: Stellenweise leichter Schneefall mit Gewitter          : Patchy light snow with thunder\n395: Gemäßigter oder starker Schneefall mit Gewitter        : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/dk-help.txt",
    "content": "Brugsanvisning:\n\n    $ curl wttr.in          # nuværende lokation\n    $ curl wttr.in/osl      # vejret på Gardermoen flyveplads\n\nUnderstøttede lokationsspecifikationer:\n\n    /gistrup                # bynavn\n    /~Aalborg+stadion       # valgfri lokation\n    /Москва                 # Unicode navn på lokation på alle sprog\n    /cph                    # flyvepladskode (3 bogstaver)\n    /@stackoverflow.com     # domønenavn\n    /94107                  # postnummer (kun USA)\n    /-78.46,106.79          # GPS-koordinater\n\nSpecielle lokationer:\n\n    /moon                   # Månefase (brug med ,+US eller ,+France for disse lokationer)\n    /moon@2014-10-26        # Månefase for specifik dato (@2014-10-26)\n\nEnheder:\n\n    ?m                      # metrisk (SI) (standard alle steder undtaget i USA)\n    ?u                      # USCS (standard i USA)\n    ?M                      # vindstyrke i meter per sekund\n\nVisningsvalg:\n\n    ?0                      # kun vejret nu\n    ?1                      # vejret nu + 1 dag\n    ?2                      # vejret nu + 2 dage\n    ?n                      # smal visning (kun dag og nat)\n    ?q                      # stille visning (ingen \"Vejrmelding\"-tekst)\n    ?Q                      # superstille visning (ingen \"Vejrmelding\", ingen bynavn)\n    ?T                      # ingen terminalsekvenser (ingen farver)\n\nPNG valg:\n\n    /paris.png              # generer en PNG-fil\n    ?p                      # tegn ramme på\n    ?t                      # gennemsigtighed 150\n    transparency=...        # gennemsigtighed fra 0 til 255 (255 = ikke gennemsigtigt)\n\nTilvalg kan kombineres:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # for PNG er filmodus specificeret efter _\n    /Rome_0pq_lang=it.png   # lange tilvalg separeres med underscore (_)\n\nOversættelser:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nUnderstøttede sprog:\n\n    FULL_TRANSLATION (understøttet)\n    PARTIAL_TRANSLATION (under udarbejdning)\n\nSpecielle URLer:\n\n    /:help                  # vis denne side\n    /:bash.function         # vis den foreslåede bash-funktion wttr()\n    /:translation           # vis information om oversætterne\n"
  },
  {
    "path": "share/translations/el-help.txt",
    "content": "Χρήση:\r\n\r\n    $ curl wttr.in          # καιρός τρέχουσας τοποθεσίας (κατά προσέγγιση, βάσει IP)\r\n    $ curl wttr.in/ath      # ο καιρός στο Διεθνή Αερολιμένα Αθηνών «Ελ. Βενιζέλος»\r\n\r\nΥποστηριζόμενες μορφές τοποθεσιών:\r\n\r\n    /paris                  # όνομα πόλης\r\n    /~Eiffel+tower          # κάποια τοποθεσία\r\n    /Москва                 # Unicode όνομα οποιασδήποτε τοποθεσίας σε οποιαδήποτε γλώσσα\r\n    /ath                    # κωδικός αεροδρομίου (3 γράμματα)\r\n    /@stackoverflow.com     # (διαδικτυακό) όνομα τομέα (domain)\r\n    /94107                  # κωδικός περιοχής\r\n    /-78.46,106.79          # γεωγραφικές συντεταγμένες (GPS) \r\n\r\nΕξειδικευμένες τοποθεσίες:\r\n\r\n    /moon                   # Φάση Σελήνης (προσθέστε ,+US ή ,+France για τις πόλεις)\r\n    /moon@2016-10-25        # Φάση Σελήνης για την ημερομηνία (@2016-10-25)\r\n    /moon@2019-06-18.png?T -omoon.png # Φάση Σελήνης για την ημερομηνία (@2019-06-18), όχι ANSI, εξοδος στο αρχείο `moon.png`\r\n\r\nΣύστημα μέτρησης:\r\n\r\n    m                       # μετρικό (SI) (προεπιλογή για οπουδήποτε εκτός ΗΠΑ)\r\n    u                       # USCS (προεπιλογή για τις ΗΠΑ)\r\n    M                       # εμφάνιση ταχύτητας ανέμου σε m/s \r\n\r\nΕπιλογές Προβολής:\r\n\r\n    0                       # καιρός τρέχουσας ημέρας μόνο\r\n    1                       # καιρός τρέχουσας ημέρας + 1 ημέρα\r\n    2                       # καιρός τρέχουσας ημέρας + 2 ημέρες\r\n    A                       # παραβλέπει τον User-Agent και επιβάλει μορφή εξόδου ANSI (τερματικό)\r\n    F                       # μη εμφάνιση της γραμμής \"Follow\"\r\n    n                       # συνοπτική εκδοχή (ημέρα και νύχτα μόνο)\r\n    q                       # σιωπηλή εκδοχή (όχι κείμενο \"Weather report\")\r\n    Q                       # υπερσιωπηλή εκδοχή (όχι κείμενο \"Weather report\", όχι όνομα πόλης)\r\n    T                       # απενεργοποίηση ακολουθιών τερματικού (όχι χρώματα)\r\n\r\nΕπιλογές PNG:\r\n\r\n    /paris.png              # δημιουργία PNG αρχείου\r\n    p                       # προσθήκη πλαισίου γύρω από τα περιέχομενα εξόδου\r\n    t                       # διαφάνεια 150\r\n    transparency=nnn        # διαφάνεια nnn (από 0 έως 255 - 255 = αδιαφανές)\r\n\r\nΟι επιλογές μπορούν να συνδυαστούν:\r\n\r\n    /Paris?0pq\r\n    /Paris?0pq&lang=fr\r\n    /Paris?_0pq.png          # η έξοδος σε PNG αρχείο ορίζεται μετά από το _\r\n    /Rome?_0pq_lang=it.png   # μακροσκελείς επιλογές διαχωριζόμενες με κάτω παύλα (underscore)\r\n    /Athens?\"1pTng&lang=el\"  # συνδυασμένες επιλογές μπορούν να περικλείονται σε εισαγωγικά!\r\n     \r\n\r\nΤοπικοποίηση:\r\n\r\n    $ curl fr.wttr.in/Paris\r\n    $ curl wttr.in/paris?lang=fr\r\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\r\n\r\nΥποστηριζόμενες γλώσσες:\r\n\r\n    FULL_TRANSLATION (πλήρως υποστηριζόμενες)\r\n    PARTIAL_TRANSLATION (εργασία σε εξέλιξη)\r\n\r\nΕιδικά URLs:\r\n\r\n    /:help                  # εμφάνιση της παρούσας βοήθειας\r\n    /:bash.function         # εμφάνιση συνιστώμενων bash λειτουργιών wttr()\r\n    /:translation           # εμφάνιση πληροφοριών για τους μεταφραστές\r\n\r\n"
  },
  {
    "path": "share/translations/el.txt",
    "content": "113: Καθαρός                            : Clear\r\n113: Λιακάδα                            : Sunny\r\n116: Αραιή συννεφιά                     : Partly cloudy\r\n119: Συννεφιά                           : Cloudy\r\n122: Πυκνή νέφωση                       : Overcast\r\n143: Αραιή ομίχλη                       : Mist\r\n176: Πιθανή βροχή τοπικά                : Patchy rain possible\r\n179: Πιθανή χιονόπτωση τοπικά           : Patchy snow possible\r\n182: Πιθανή χαλαζόπτωση τοπικά          : Patchy sleet possible\r\n185: Πιθανό παγωμ. ψιλόβροχο τοπικά     : Patchy freezing drizzle possible\r\n200: Πιθανή πτώση κεραυνών              : Thundery outbreaks possible\r\n227: Ριπές χιονιού                      : Blowing snow\r\n230: Χιονοθύελλα                        : Blizzard\r\n248: Ομίχλη                             : Fog\r\n260: Παγωμένη ομίχλη                    : Freezing fog\r\n263: Ασθενής ψιχάλα  τοπικά             : Patchy light drizzle\r\n266: Ασθενής ψιχάλα                     : Light drizzle\r\n281: Παγωμένο ψιλόβροχο                 : Freezing drizzle\r\n284: Πυκνό παγωμένο ψιλόβροχο           : Heavy freezing drizzle\r\n293: Ασθενής όμβρος τοπικά              : Patchy light rain\r\n296: Ασθενής βροχόπτωση                 : Light rain\r\n299: Μέτρια βροχή παροδικά              : Moderate rain at times\r\n302: Μέτρια βροχόπτωση                  : Moderate rain\r\n305: Έντονη βροχή παροδικά              : Heavy rain at times\r\n308: Έντονη βροχόπτωση                  : Heavy rain\r\n311: Αραιό χιονόνερο                    : Light freezing rain\r\n314: Μέτριο ή έντονο χιονόνερο          : Moderate or heavy freezing rain\r\n317: Ασθενής χαλαζόπτωση                : Light sleet\r\n320: Μέτρια ή έντονη χαλαζόπτωση        : Moderate or heavy sleet\r\n323: Αραιή χιονόπτωση κατά τόπους       : Patchy light snow\r\n326: Αραιή χιονόπτωση                   : Light snow\r\n329: Μέτρια χιονόπτωση τοπικά           : Patchy moderate snow\r\n332: Μέτρια χιονόπτωση                  : Moderate snow\r\n335: Πυκνή χιονόπτωση τοπικά            : Patchy heavy snow\r\n338: Πυκνή χιονόπτωση                   : Heavy snow\r\n350: Χιονόνερο                          : Ice pellets\r\n353: Ασθενής βροχή παροδικά             : Light rain shower\r\n356: Μέτρια ή έντονη βροχή παροδικά     : Moderate or heavy rain shower\r\n359: Καταρρακτώδης βροχή παροδικά       : Torrential rain shower\r\n362: Ασθενής χαλαζόπτωση παροδικά       : Light sleet showers\r\n365: Μέτρια/έντονη χαλαζόπτωση παροδικά : Moderate or heavy sleet showers\r\n368: Αραιή χιονόπτωση παροδικά          : Light snow showers\r\n371: Μέτρια ή πυκνή χιονόπτωση παροδικά : Moderate or heavy snow showers\r\n386: Ασθενής βροχή με κεραυνούς τοπικά  : Patchy light rain with thunder\r\n389: Μέτρια ή δυνατή βροχή με κεραυνούς : Moderate or heavy rain with thunder\r\n392: Ασθενής χιονόπτωση-κεραυνοί τοπικά : Patchy light snow with thunder\r\n395: Μέτρια ή πυκνή χιονόπτωση-κεραυνοί : Moderate or heavy snow with thunder\r\n"
  },
  {
    "path": "share/translations/en.txt",
    "content": "113:                                    : Clear\n113:                                    : Sunny\n116:                                    : Partly cloudy\n119:                                    : Cloudy\n122:                                    : Overcast\n143:                                    : Mist\n176:                                    : Patchy rain possible\n179:                                    : Patchy snow possible\n182:                                    : Patchy sleet possible\n185:                                    : Patchy freezing drizzle possible\n200:                                    : Thundery outbreaks possible\n227:                                    : Blowing snow\n230:                                    : Blizzard\n248:                                    : Fog\n260:                                    : Freezing fog\n263:                                    : Patchy light drizzle\n266:                                    : Light drizzle\n281:                                    : Freezing drizzle\n284:                                    : Heavy freezing drizzle\n293:                                    : Patchy light rain\n296:                                    : Light rain\n299:                                    : Moderate rain at times\n302:                                    : Moderate rain\n305:                                    : Heavy rain at times\n308:                                    : Heavy rain\n311:                                    : Light freezing rain\n314:                                    : Moderate or heavy freezing rain\n317:                                    : Light sleet\n320:                                    : Moderate or heavy sleet\n323:                                    : Patchy light snow\n326:                                    : Light snow\n329:                                    : Patchy moderate snow\n332:                                    : Moderate snow\n335:                                    : Patchy heavy snow\n338:                                    : Heavy snow\n350:                                    : Ice pellets\n353:                                    : Light rain shower\n356:                                    : Moderate or heavy rain shower\n359:                                    : Torrential rain shower\n362:                                    : Light sleet showers\n365:                                    : Moderate or heavy sleet showers\n368:                                    : Light snow showers\n371:                                    : Moderate or heavy snow showers\n386:                                    : Patchy light rain with thunder\n389:                                    : Moderate or heavy rain with thunder\n392:                                    : Patchy light snow with thunder\n395:                                    : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/eo.txt",
    "content": "113: Klara                                  : Clear\n113: Suna                                   : Sunny\n116: Parte nuba                             : Partly cloudy\n119: Nuba                                   : Cloudy\n122: Sensuna                                : Overcast\n143: Nebulo                                 : Mist\n176: Flikeca pluvo ebla                     : Patchy rain possible\n179: Flikeca neĝo ebla                      : Patchy snow possible\n182: Flikeca hajlneĝo ebla                  : Patchy sleet possible\n185: Flikeca frosta drizelo ebla            : Patchy freezing drizzle possible\n200: Tondro ebla                            : Thundery outbreaks possible\n227: Blova neĝo                             : Blowing snow\n230: Blizardo                               : Blizzard\n248: Nebulo                                 : Fog\n260: Frosta nebulo                          : Freezing fog\n263: Flikeca malforta drizelo               : Patchy light drizzle\n266: Malforta drizelo                       : Light drizzle\n281: Frosta drizelo                         : Freezing drizzle\n284: Forta frosta drizelo                   : Heavy freezing drizzle\n293: Flikeca forta pluvo                    : Patchy light rain\n296: Malforta pluvo                         : Light rain\n299: Modera pluvo foje                      : Moderate rain at times\n302: Modera pluvo                           : Moderate rain\n305: Forta pluvvo foje                      : Heavy rain at times\n308: Forta pluvo                            : Heavy rain\n311: Malforta glacipluvo                    : Light freezing rain\n314: Modera aŭ forta glacipluvo             : Moderate or heavy freezing rain\n317: Malforta grajlo                        : Light sleet\n320: Modera aŭ forta hajlneĝo               : Moderate or heavy sleet\n323: Flikeca malforta neĝo                  : Patchy light snow\n326: Malforta neĝo                          : Light snow\n329: Flikeca modera neĝo                    : Patchy moderate snow\n332: Modera neĝo                            : Moderate snow\n335: Flikeca forta neĝo                     : Patchy heavy snow\n338: Forta neĝo                             : Heavy snow\n350: Grajlo                                 : Ice pellets\n353: Malforta pluvoverŝo                    : Light rain shower\n356: Modera pluvoverŝo                      : Moderate or heavy rain shower\n359: Torrenta pluvoverŝo                    : Torrential rain shower\n362: Malforta glacipluvego                  : Light sleet showers\n365: Modera aŭ forta glacipluvego           : Moderate or heavy sleet showers\n368: Malforta hajlneĝo                      : Light snow showers\n371: Modera aŭ forta neĝipluvego            : Moderate or heavy snow showers\n386: Flikeca malforta pluvo kun tondro      : Patchy light rain with thunder\n389: Modera aŭ forta pluvo kun tondro       : Moderate or heavy rain with thunder\n392: Flikeca malforta neĝo kun tondro       : Patchy light snow with thunder\n395: Modera aŭ forta neĝo kun tondro        : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/es-help.txt",
    "content": "Instrucciones:\n\n    $ curl wttr.in          # El clima en su ubicación actual\n    $ curl wttr.in/muc      # El clima en el aeropuerto de Múnich\n\nTipos de ubicación soportados:\n\n    /paris                  # El nombre de una ciudad\n    /~Eiffel+tower          # El nombre de cualquier sitio famoso\n    /Москва                 # El nombre en Unicode de cualquier sitio en cualquier idioma\n    /muc                    # El código de un aeropuerto (3 letras)\n    /@stackoverflow.com     # El nombre de un dominio web\n    /94107                  # Un código de area\n    /-78.46,106.79          # Coordenadas de GPS\n\nSitios especiales:\n\n    /moon                   # La fase de la luna (añade ,+US o ,+France para estos paises)\n    /moon@2016-10-25        # La fase de la luna en una fecha específica (@2016-10-25)\n\nUnidades:\n\n    ?m                      # Métricas (SI) (el estándar en todos los sitios excepto en EEUU)\n    ?u                      # Sistema Unificado de Clasificación del Suelo o USCS (el estándar en EEUU)\n    ?M                      # Mostrar la velocidad del viento en m/s\n\nOpciones de visualización:\n\n    ?0                      # Solamente el clima actual\n    ?1                      # El clima actual + la previsión del día siguiente\n    ?2                      # El clima actual + la previsión de los dos días siguientes\n    ?A                      # ignora al agente del usuario y fuerza el formato de salida ANSI (terminal)\n    ?F                      # No muestra la linea de \"Seguir\"\n    ?n                      # Versión corta (solo día y noche)\n    ?q                      # Versión silenciosa (sin el texto de \"El tiempo en\")\n    ?Q                      # Versión supersilenciosa (ni \"El tiempo en\" ni el nombre de la ciudad)\n    ?T                      # Desactiva las secuencias de terminal (sin colores)\n\nOpciones de PNG:\n\n    /paris.png              # Genera una imagen PNG\n    ?p                      # Añade un borde alrededor de la imagen\n    ?t                      # Transparencia = 150\n    transparency=...        # Transparencia de 0 a 255 (255 = sin transparencia)\n\nLas opciones se pueden utilizar conjuntamente:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # En modo PNG las opciones se especifican después del carácter _ (guión bajo)\n    /Rome_0pq_lang=it.png   # Una larga secuencia de opciones se puede separar por el carácter _ (guión bajo)\n\nUbicación:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nIdiomas soportados:\n\n    FULL_TRANSLATION (soportados)\n    PARTIAL_TRANSLATION (en progreso)\n\nURLs especiales:\n\n    /:help                  # Muestra esta página\n    /:bash.function         # Muestra una función wttr() sugerida en bash\n    /:translation           # Muestra información acerca de los traductores\n"
  },
  {
    "path": "share/translations/es.txt",
    "content": "114: Despejado                                   : Clear                                              :\n113: Soleado                                     : Sunny                                              :\n116: Parcialmente nublado                        : Partly cloudy                                      :\n119: Nublado                                     : Cloudy                                             :\n122: Cubierto de nubes                           : Overcast                                           :\n143: Niebla                                      : Mist                                               :\n176: Posible lluvia irregular                    : Patchy rain possible                               :\n179: Posible aguanieve irregular                 : Patchy snow possible                               :\n182: Posible aguanieve irregular                 : Patchy sleet possible                              :\n185: Posible llovizna helada irregular           : Patchy freezing drizzle possible                   :\n200: Posibles brotes de tormentas                : Thundery outbreaks possible                        :\n227: Nieve tormentosa                            : Blowing snow                                       :\n230: Ventisca                                    : Blizzard                                           :\n248: Niebla                                      : Fog                                                :\n260: Niebla helada                               : Freezing fog                                       :\n263: Llovizna ligera irregular                   : Patchy light drizzle                               :\n266: Llovizna ligera                             : Light drizzle                                      :\n281: Llovizna helada                             : Freezing drizzle                                   :\n284: Llovizna muy helada                         : Heavy freezing drizzle                             :\n293: Lluvia ligera irregular                     : Patchy light rain                                  :\n296: Lluvia ligera                               : Light rain                                         :\n299: Lluvia moderada ocasional                   : Moderate rain at times                             :\n302: Lluvia moderada                             : Moderate rain                                      :\n305: Lluvia fuerte ocasional                     : Heavy rain at times                                :\n308: Lluvia fuerte                               : Heavy rain                                         :\n311: Lluvia ligera helada                        : Light freezing rain                                :\n314: Lluvia helada moderada o fuerte             : Moderate or heavy freezing rain                    :\n317: Aguanieve ligero                            : Light sleet                                        :\n320: Aguanieve moderado o fuerte                 : Moderate or heavy sleet                            :\n323: Nieve ligera irregular                      : Patchy light snow                                  :\n326: Nieve ligera                                : Light snow                                         :\n329: Nieve moderada irregular                    : Patchy moderate snow                               :\n332: Nieve moderada                              : Moderate snow                                      :\n335: Nieve pesada irregular                      : Patchy heavy snow                                  :\n338: Nieve pesada                                : Heavy snow                                         :\n350: Perdigones de hielo                         : Ice pellets                                        :\n353: Aguacero ligero                             : Light rain shower                                  :\n356: Aguacero moderado o fuerte                  : Moderate or heavy rain shower                      :\n359: Aguacero torrencial                         : Torrential rain shower                             :\n362: Aguacero ligero con aguanieve               : Light sleet showers                                :\n365: Aguacero con aguanieve moderado o fuerte    : Moderate or heavy sleet showers                    :\n368: Aguacero con nieve ligera                   : Light snow showers                                 :\n371: Aguacero con nieve moderada o fuerte        : Moderate or heavy snow showers                     :\n386: Lluvia ligera irregular con truenos         : Patchy light rain with thunder                     :\n389: Lluvia moderada o fuerte con truenos        : Moderate or heavy rain with thunder                :\n392: Nevada ligera irregular con truenos         : Patchy light snow with thunder                     :\n395: Nevada moderada o fuerte con truenos        : Moderate or heavy snow with thunder                :\n   : Bruma en las cercanías                      : Haze in vicinity                                   :\n   : Fuerte lluvia y nevada                      : Heavy rain and snow shower                         :\n   : Fuerte aguacero                             : Heavy rain shower                                  :\n   : Llovizna ligera y granos de nieve           : Light drizzle and snow grains                      :\n   : Lluvia ligera y bruma                       : Light rain and mist shower                         :\n   : Granizo ligero o chubasco de nieve granulada  : Light small hail/snow pellets shower               :\n   : Chubasco ligero de precipitación desconocida  : Light unknown precipitation shower                 :\n   : Lluvia y granizo ligero o nieve granulada con tormenta  : Rain and small hail/snow pellets with thunderstorm :\n   : Chubasco de nieve en las cercanías          : Snow shower in vicinity                            :\n   : Brotes de tormenta en las cercanías         : Thundery outbreaks nearby                          :\n   : Nieve arrastrada a nivel del suelo          : Low drifting snow                                  :\n   : Bancos de niebla                            : Patches of fog                                     :\n   : Llovizna                                    : Drizzle                                            :\n   : Llovizna ligera y lluvia                    : Light drizzle and rain                             :\n   : Nieve                                       : Snow                                               :\n   : Lluvia                                      : Rain                                               :\n   : Aguacero                                    : Rain Shower                                        :\n   : Arena arrastrada por el viento              : Blowing sand                                       :\n   : Polvo generalizado arrastrado por el viento  : Blowing widespread dust                            :\n   : Polvo generalizado arrastrado por el viento en las cercanías  : Blowing widespread dust in vicinity                :\n   : Llovizna y niebla                           : Drizzle and fog                                    :\n   : Llovizna y lluvia                           : Drizzle and rain                                   :\n   : Llovizna y aguacero                         : Drizzle and rain shower                            :\n   : Llovizna con tormenta                       : Drizzle with thunderstorm                          :\n   : Tormenta de polvo                           : Dust storm                                         :\n   : Niebla en las cercanías                     : Fog in vicinity                                    :\n   : Llovizna helada y lluvia                    : Freezing drizzle and rain                          :\n   : Niebla helada                               : Freezing mist                                      :\n   : Lluvia helada                               : Freezing rain                                      :\n   : Lluvia helada y nieve                       : Freezing rain and snow                             :\n   : Precipitación desconocida helada            : Freezing unknown precipitation                     :\n   : Nube embudo en las cercanías                : Funnel cloud in vicinity                           :\n   : Chubasco de granizo                         : Hail shower                                        :\n   : Granizo con tormenta                        : Hail with thunderstorm                             :\n   : Bruma                                       : Haze                                               :\n   : Fuertes ventiscas de nieve                  : Heavy blowing snow                                 :\n   : Fuerte llovizna                             : Heavy drizzle                                      :\n   : Fuerte llovizna y lluvia                    : Heavy drizzle and rain                             :\n   : Fuerte precipitación desconocida helada     : Heavy freezing unknown precipitation               :\n   : Fuerte granizo con tormenta                 : Heavy hail with thunderstorm                       :\n   : Fuertes gránulos de hielo                   : Heavy ice pallets                                  :\n   : Fuerte lluvia y chubasco de granizo         : Heavy rain and hail shower                         :\n   : Fuerte lluvia y granizo con tormenta        : Heavy rain and hail with thunderstorm              :\n   : Fuerte lluvia y granizo pequeño o chubasco de nieve granulada  : Heavy rain and small hail/snow pallets shower      :\n   : Fuerte lluvia y granizo pequeño o nieve granulada con tormenta  : Heavy rain and small hail/snow pallets with thunderstorm :\n   : Fuerte lluvia y nieve                       : Heavy rain and snow                                :\n   : Fuerte lluvia y nieve junto con granizo pequeño o nieve granulada con tormenta  : Heavy rain and snow and small hail/snow pallets with thunderstorm :\n   : Fuerte lluvia con tormenta                  : Heavy rain with thunderstorm                       :\n   : Fuerte chubasco de granizo pequeño o nieve granulada  : Heavy small hail/snow pallets shower               :\n   : Fuerte granizo pequeño o nieve granulada con tormenta  : Heavy small hail/snow pallets with thunderstorm    :\n   : Fuerte nieve y chubasco de granizo pequeño o nieve granulada  : Heavy snow and small hail/snow pallets shower      :\n   : Fuerte nieve y granizo pequeño o nieve granulada con tormenta  : Heavy snow and small hail/snow pallets with thunderstorm :\n   : Fuerte chubasco de nieve                    : Heavy snow shower                                  :\n   : Fuerte nieve con tormenta                   : Heavy snow with thunderstorm                       :\n   : Cristales de hielo                          : Ice crystals                                       :\n   : Gránulos de hielo                           : Ice pallets                                        :\n   : Ventiscas de nieve ligeras                  : Light blowing snow                                 :\n   : Llovizna ligera y niebla                    : Light drizzle and fog                              :\n   : Llovizna ligera y gránulos de hielo         : Light drizzle and ice pallets                      :\n   : Llovizna ligera, lluvia y nieve             : Light drizzle and rain and snow                    :\n   : Llovizna ligera y aguacero                  : Light drizzle and rain shower                      :\n   : Llovizna ligera y lluvia con tormenta       : Light drizzle and rain with thunderstorm           :\n   : Llovizna ligera y nieve                     : Light drizzle and snow                             :\n   : Llovizna ligera con tormenta                : Light drizzle with thunderstorm                    :\n   : Llovizna helada ligera                      : Light freezing drizzle                             :\n   : Llovizna helada ligera y lluvia             : Light freezing drizzle and rain                    :\n   : Llovizna helada ligera y nieve              : Light freezing drizzle and snow                    :\n   : Niebla helada ligera                        : Light freezing fog                                 :\n   : Lluvia helada ligera y nieve                : Light freezing rain and snow                       :\n   : Granos de nieve helados ligeros y niebla    : Light freezing snow grains and fog                 :\n   : Precipitación desconocida helada ligera     : Light freezing unknown precipitation               :\n   : Chubasco de granizo ligero                  : Light hail shower                                  :\n   : Cristales de hielo ligeros                  : Light ice crystals                                 :\n   : Gránulos de hielo ligeros                   : Light ice pallets                                  :\n   : Arrastrados ligeros a nivel del suelo       : Light low drifting                                 :\n   : Nieve arrastrada ligera a nivel del suelo   : Light low drifting snow                            :\n   : Lluvia ligera y chubasco de granizo         : Light rain and hail shower                         :\n   : Lluvia ligera y granizo con tormenta        : Light rain and hail with thunderstorm              :\n   : Lluvia ligera y gránulos de hielo           : Light rain and ice pallets                         :\n   : Lluvia ligera y bruma                       : Light rain and mist                                :\n   : Lluvia ligera y chubasco de granizo pequeño o nieve granulada  : Light rain and small hail/snow pallets shower      :\n   : Lluvia ligera y granizo pequeño o nieve granulada con tormenta  : Light rain and small hail/snow pallets with thunderstorm :\n   : Lluvia ligera y nieve                       : Light rain and snow                                :\n   : Lluvia ligera, nieve y chubasco de granizo pequeño o nieve granulada  : Light rain and snow and small hail/snow pallets shower :\n   : Lluvia ligera y granos de nieve             : Light rain and snow grains                         :\n   : Lluvia ligera y chubasco de nieve           : Light rain and snow shower                         :\n   : Lluvia ligera y nieve con tormenta          : Light rain and snow with thunderstorm              :\n   : Lluvia ligera con tormenta                  : Light rain with thunderstorm                       :\n   : Chubasco ligero                             : Light shower                                       :\n   : Chubascos ligeros de gránulos de hielo      : Light showers of ice pellets                       :\n   : Granizo pequeño o nieve granulada ligera    : Light small hail/snow pallets                      :\n   : Chubasco ligero de granizo pequeño o nieve granulada  : Light small hail/snow pallets shower               :\n   : Granizo pequeño o nieve granulada ligera con tormenta  : Light small hail/snow pallets with thunderstorm    :\n   : Nieve ligera y gránulos de hielo            : Light snow and ice pallets                         :\n   : Nieve ligera y granizo pequeño o nieve granulada  : Light snow and small hail/snow pallets             :\n   : Chubasco de nieve ligera con granizo pequeño o nieve granulada  : Light snow and small hail/snow pallets shower      :\n   : Nieve ligera con granizo pequeño o nieve granulada y tormenta  : Light snow and small hail/snow pallets with thunderstorm :\n   : Nieve ligera y granos de nieve              : Light snow and snow grains                         :\n   : Granos de nieve ligeros                     : Light snow grains                                  :\n   : Chubasco de nieve ligero                    : Light snow shower                                  :\n   : Nieve ligera con tormenta                   : Light snow with thunderstorm                       :\n   : Tormenta ligera                             : Light thunderstorm                                 :\n   : Precipitación desconocida ligera            : Light unknown precipitation                        :\n   : Remolinos de polvo o arena ligeros bien desarrollados  : Light well-developed dust/sand whirls              :\n   : Arena arrastrada a nivel del suelo          : Low drifting sand                                  :\n   : Polvo generalizado arrastrado a nivel del suelo  : Low drifting widespread dust                       :\n   : Bruma con tormenta                          : Mist with thunderstorm                             :\n   : Lluvia moderada a fuerte con truenos en la zona  : Moderate or heavy rain in area with thunder        :\n   : Nieve moderada a fuerte con truenos en la zona  : Moderate or heavy snow in area with thunder        :\n   : Niebla parcial                              : Partial fog                                        :\n   : Bancos de niebla en las cercanías           : Patches of fog in vicinity                         :\n   : Llovizna helada localizada en las cercanías  : Patchy freezing drizzle nearby                     :\n   : Lluvia ligera localizada con truenos en la zona  : Patchy light rain in area with thunder             :\n   : Nieve ligera localizada con truenos en la zona  : Patchy light snow in area with thunder             :\n   : Lluvia localizada en las cercanías          : Patchy rain nearby                                 :\n   : Aguanieve localizada en las cercanías       : Patchy sleet nearby                                :\n   : Nieve localizada en las cercanías           : Patchy snow nearby                                 :\n   : Lluvia y chubasco de granizo                : Rain and hail shower                               :\n   : Lluvia y granizo con tormenta               : Rain and hail with thunderstorm                    :\n   : Lluvia y bruma                              : Rain and mist                                      :\n   : Lluvia y bruma con tormenta                 : Rain and mist with thunderstorm                    :\n   : Lluvia y chubasco de granizo pequeño o nieve granulada  : Rain and small hail/snow pallets shower            :\n   : Lluvia y granizo pequeño o nieve granulada con tormenta  : Rain and small hail/snow pallets with thunderstorm :\n   : Lluvia y nieve                              : Rain and snow                                      :\n   : Lluvia, nieve y chubasco de granizo pequeño o nieve granulada  : Rain and snow and small hail/snow pallets shower   :\n   : Lluvia y granos de nieve                    : Rain and snow grains                               :\n   : Lluvia y chubasco de nieve                  : Rain and snow shower                               :\n   : Lluvia y nieve con tormenta                 : Rain and snow with thunderstorm                    :\n   : Lluvia en las cercanías                     : Rain in vicinity                                   :\n   : Aguacero en las cercanías                   : Rain shower in vicinity                            :\n   : Lluvia con tormenta                         : Rain with thunderstorm                             :\n   : Arena                                       : Sand                                               :\n   : Tormenta de arena                           : Sandstorm                                          :\n   : Niebla poco profunda                        : Shallow fog                                        :\n   : Bruma poco profunda                         : Shallow mist                                       :\n   : Chubasco                                    : Shower                                             :\n   : Chubasco en las cercanías                   : Shower in vicinity                                 :\n   : Granizo pequeño o nieve granulada ligera    : Small hail/snow pallets                            :\n   : Chubasco de granizo pequeño o nieve granulada  : Small hail/snow pallets shower                     :\n   : Granizo pequeño o nieve granulada con tormenta  : Small hail/snow pallets with thunderstorm          :\n   : Humo                                        : Smoke                                              :\n   : Nieve y gránulos de hielo                   : Snow and ice pallets                               :\n   : Nieve y bruma                               : Snow and mist                                      :\n   : Nieve y chubascos ligeros de granizo o nieve granulada  : Snow and small hail/snow pellets shower            :\n   : Nieve y chubascos ligeros de granizo o nieve granulada con tormenta  : Snow and small hail/snow pallets with thunderstorm :\n   : Nieve y granos de nieve                     : Snow and snow grains                               :\n   : Granos de nieve                             : Snow grains                                        :\n   : Chubasco de nieve                           : Snow shower                                        :\n   : Nieve con tormenta                          : Snow with thunderstorm                             :\n   : Rachas de tormenta                          : Squalls                                            :\n   : Tormenta                                    : Thunderstorm                                       :\n   : Tormenta en las cercanías                   : Thunderstorm in vicinity                           :\n   : Brotes de tormenta en las cercanías         : Thundery outbreaks in nearby                       :\n   : Precipitación desconocida                   : Unknown precipitation                              :\n   : Chubasco con precipitación desconocida      : Unknown precipitation shower                       :\n   : Precipitación desconocida con tormenta      : Unknown precipitation with thunderstorm            :\n   : Ceniza volcánica                            : Volcanic ash                                       :\n   : Ceniza volcánica en las cercanías           : Volcanic ash in vicinity                           :\n   : Remolinos de polvo o arena bien desarrollados en las cercanías  : Well-developed dust/sand whirls in vicinity        :\n   : Polvo generalizado                          : Widespread dust                                    :\n"
  },
  {
    "path": "share/translations/et-help.txt",
    "content": "Kasutus:\n\n    $ curl wttr.in          # praegune asukoht\n    $ curl wttr.in/tll      # ilmaprognoos Tallinna Lennujaamas\n\nToetatud asukohatüübid:\n\n    /paris                  # linna nimi\n    /~suur+munamägi         # mistahes asukoht\n    /Москва                 # Ükskõik millises keeles Unicode'i vormingus asukoha nimi\n    /muc                    # IATA Lennujaama kood (3 tähemärki)\n    /@stackoverflow.com     # domeeninimi\n    /94107                  # Piirkonna kood (Ainult USA)\n    /-78.46,106.79          # GPS-koordinaadid\n\nErilised asukohad:\n\n    /moon                   # Kuu faas (lisage, +US või +France linnade jaoks))\n    /moon@2016-10-25        # Kuu faas kindlal kuupäeval (@2016-10-25)\n\nÜhikud:\n\n    ?m                      # meetriline (SI) (kasutatakse vaikimisi kõikjal peale USA)\n    ?u                      # USCS (kasutusel vaikimisi USA)\n    ?M                      # kuva tuule kiirust m/s\n\nVaadete valikuid:\n\n    ?0                      # kuva ainult praegune ilm\n    ?1                      # kuva praegune ilm + 1 päeva prognoos\n    ?2                      # kuva praegune ilm + 2 päeva prognoos\n    ?n                      # kitsas vaade (Päeva & Öö prognoos)\n    ?q                      # taltsas variant ('ilmaprognoos' tekstita)\n    ?Q                      # eriti taltsas variant (asukohata ja 'ilmaprognoos' tekstita)\n    ?T                      # värvideta\n\nPNG valikud:\n\n    /paris.png              # loo PNG fail\n    ?p                      # lisab raami ümber väljundi\n    ?t                      # läbipaistvus 150\n    transparency=...        # läbipaistvus 0-st kuni 255-ni (255 = pole läbipaistev)\n\nValikuid saab kombineerida:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # PNG failis saab valikuid määrata peale _ (alakriips) tähemärki\n    /Rome_0pq_lang=it.png   # pikad valikud on eraldatud alakriipsuga\n\nLokaliseerimine:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nToetattud keeled:\n\n    FULL_TRANSLATION (toetatud)\n    PARTIAL_TRANSLATION (teoksil)\n\nErilehed:\n\n    /:help                  # kuvab käesolevat lehte\n    /:bash.function         # kuvab soovitatud bash-funktsiooni wttr()\n    /:translation           # kuvab infot tõlkijate kohta\n"
  },
  {
    "path": "share/translations/et.txt",
    "content": "113: Selge                              : Clear\n113: Päikeseline                        : Sunny\n116: Vahelduv pilvisus                  : Partly cloudy\n119: Pilvine                            : Cloudy\n122: Sombune                            : Overcast\n143: Uduvine                            : Mist\n176: Paiguti vihmasaju võimalus         : Patchy rain possible\n179: Paiguti lumesaju võimalus          : Patchy snow possible\n182: Paiguti lörtsisaju võimalus        : Patchy sleet possible\n185: Paiguti jääudu võimalus            : Patchy freezing drizzle possible\n200: Äikese võimalus                    : Thundery outbreaks possible\n227: Tuisk                              : Blowing snow\n230: Lumetorm                           : Blizzard\n248: Udu                                : Fog\n260: Jääudu                             : Freezing fog\n263: Paiguti nõrk uduvihm               : Patchy light drizzle\n266: Nõrk uduvihm                       : Light drizzle\n281: Jääudu                             : Freezing drizzle\n284: Tugev uduvihm                      : Heavy freezing drizzle\n293: Vahelduv nõrk vihm                 : Patchy light rain\n296: Nõrk vihm                          : Light rain\n299: Vahelduv mõõdukas vihm             : Moderate rain at times\n302: Mõõdukas vihm                      : Moderate rain\n305: Vahelduv tugev vihm                : Heavy rain at times\n308: Tugev vihm                         : Heavy rain\n311: Nõrk jäävihm                       : Light freezing rain\n314: Mõõdukas või tugev jäävihm         : Moderate or heavy freezing rain\n317: Nõrk lörtsisadu                    : Light sleet\n320: Mõõdukas või tugev lörtsisadu      : Moderate or heavy sleet\n323: Paiguti nõrk lumesadu              : Patchy light snow\n326: Nõrk lumesadu                      : Light snow\n329: Paiguti mõõdukas lumesadu          : Patchy moderate snow\n332: Mõõdukas lumesadu\t                : Moderate snow\n335: Paiguti tugev lumesadu             : Patchy heavy snow\n338: Tugev lumesadu                     : Heavy snow\n350: Rahe                               : Ice pellets\n353: Nõrk hoogvihm                      : Light rain shower\n356: Mõõdukas või tugev hoogvihm        : Moderate or heavy rain shower\n359: Padu hoogvihm                      : Torrential rain shower\n362: Nõrk hooglörts                     : Light sleet showers\n365: Mõõdukas või tugev hooglörts       : Moderate or heavy sleet showers\n368: Nõrk hooglumi                      : Light snow showers\n371: Mõõdukas või tugev hooglumi        : Moderate or heavy snow showers\n386: Paiguti nõrk vihm äikesega         : Patchy light rain with thunder\n389: Mõõdukas või tugev vihm äikesega   : Moderate or heavy rain with thunder\n392: Paiguti nõrk lumesadu äikesega     : Patchy light snow with thunder\n395: Mõõdukas või tugev lumesadu äikesega : Moderate or heavy snow with thunder\n   : Hoogvihm                           : Rain shower\n   : Tugev hoogvihm                     : Heavy showers\n   : Nõrk hoogvihm                      : Light showers\n   : Tugev hooglumi                     : Heavy snow showers\n   : Äikesevihm                         : Thundery showers\n   : Tugev äikesevihm                   : Thundery heavy rain\n   : Äikesega lumesadu                  : Thundery snow showers\n   : Tugev hooglumi                     : Heavy snow showers\n"
  },
  {
    "path": "share/translations/eu-help.txt",
    "content": "Argibideak:\n\n    $ curl wttr.in          # eguraldia zure kokapenean\n    $ curl wttr.in/bio      # eguraldia Bilboko aireportuan\n\nOnartzen diren kokapen motak:\n\n    /bilbao                 # hiri baten izena\n    /~Bilbao+Guggenheim+museum          # leku famatu baten izena\n    /Москва                 # Edozein lekuko edozein hizkuntzako Unicode izena\n    /bio                    # aeroportu baten kodea (3 letra)\n    /@stackoverflow.com     # web domeinu baten izena\n    /94107                  # area kode bat\n    /-78.46,106.79          # GPS koordenadak\n\nLeku bereziak:\n\n    /moon                   # ilargiaran aldia (gehitu ,+US o ,+France herrialde hauetarako)\n    /moon@2016-10-25        # ilargiaren aldia data konkretu batean (@2016-10-25)\n\nUnitateak:\n\n    ?m                      # metrikak (SI) (leku guztietako estandarra, AEB ezik)\n    ?u                      # Lurra sailkatzeko sistema batua edo LSSB (AEB estandarra)\n    ?M                      # haizeko abiadura erakutsi (m/s)\n\nBistaratzeko aukerak:\n\n    ?0                      # oraingo eguraldia bakarrik\n    ?1                      # oraingo eguraldia + egun bateko iragarpena\n    ?2                      # oraingo eguraldia + bi egunerako iragarpena\n    ?n                      # bertsio laburra (eguna eta gaua bakarrik)\n    ?q                      # bertsio isila (\"Eguraldia...\" textua barik)\n    ?Q                      # bertsio super isila (\"Eguraldia ...\" eta hiriaren izenik ez)\n    ?T                      # terminalaren sekuentziak desaktibatu (kolorerik ez)\n\nPNG aukerak:\n\n    /paris.png              # irudi PNG bat sortzen du\n    ?p                      # irudiaren inguruan ertz bat gehitzen du\n    ?t                      # 150 gardentasuna\n    transparency=...        # 0tik 255era gardentasuna (255 = gardentasunik ez)\n\nElkarrekin erabili daiteken aukerak:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # PNG-an aukerak _ karakteren ondoren zehazten dira\n    /Rome_0pq_lang=it.png   # aukera sekuentzia luze bat _ karakterearekin bereiz daiteke\n\nKokapena:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nOnartzen diren hizkuntzak:\n\n    FULL_TRANSLATION (onartuak)\n    PARTIAL_TRANSLATION (abian)\n\nURL bereziak:\n\n    /:help                  # orrialde hau erakutsi\n    /:bash.function         # wttr() funtzio bat bash-en iradokitzen du\n    /:translation           # itzultzaileei buruzko informazioa erakusten du\n"
  },
  {
    "path": "share/translations/eu.txt",
    "content": "114: Oskarbia: Clear\n113: Eguzkitsu: Sunny\n116: Neurri batean hodeitsu: Partly cloudy\n119: Hodeitsu: Cloudy\n122: Iluna: Overcast\n143: Lanbroa: Mist\n176: Posible euri irregularra: Patchy rain possible\n179: Posible elurbusti irregularra: Patchy snow possible\n182: Posible elurbusti irregularra: Patchy sleet possible\n185: Posible zirimiri hotz irregularra: Patchy freezing drizzle possible\n200: Posible ekaitz agerraldi: Thundery outbreaks possible\n227: Elur-ekaitza: Blowing snow\n230: Elur-ekaitza: Blizzard\n248: Lainoa: Fog\n260: Laino hotza: Freezing fog\n263: Garo irregularra: Patchy light drizzle\n266: Garoa: Light drizzle\n281: Garo hotza: Freezing drizzle\n284: Zirimiri hotz-hotza: Heavy freezing drizzle\n293: Zirimiri irregularra: Patchy light rain\n296: Zirimiri: Light rain\n299: Noizbehinkako euri ertaina: Moderate rain at times\n302: Euri ertaina: Moderate rain\n305: Noizbehinkako euri-zaparrada: Heavy rain at times\n308: Euri-zaparrada: Heavy rain\n311: Zirimiri hotza: Light freezing rain\n314: Euri ertain edo zaparrada hotza: Moderate or heavy freezing rain\n317: Elurbusti arina: Light sleet\n320: Elurbusti ertain edo gogorra: Moderate or heavy sleet\n323: Gazura irregularra: Patchy light snow\n326: Gazura: Light snow\n329: Noizbehinkako elur ertaina: Patchy moderate snow\n332: Elur ertaina: Moderate snow\n335: Nieve pesada irregular: Patchy heavy snow\n338: Nieve pesada: Heavy snow\n350: Txingorra: Ice pellets\n353: Zaparrada arina: Light rain shower\n356: Zaparrada ertain edo gogorra: Moderate or heavy rain shower\n359: Uholde-zaparrada: Torrential rain shower\n362: Elurbusti zaparrada arina: Light sleet showers\n365: Elurbusti zaparrada ertaina edo gogorra: Moderate or heavy sleet showers\n368: Elur zaparrada arina: Light snow showers\n371: Elur zaparrada ertaina edo gogorra: Moderate or heavy snow showers\n386: Zirimiri irregularra trumoiekin: Patchy light rain with thunder\n389: Euri ertaina edo gogorra trumoiekin: Moderate or heavy rain with thunder\n392: Elur arina irregularra trumoiekin: Patchy light snow with thunder\n395: Elur ertaina edo gogorra trumoiekin: Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/fa-help.txt",
    "content": "                                                                          :نحوه استفاده\n\n    $ curl wttr.in          # موقعیت فعلی\n    $ curl wttr.in/muc      # وضعیت اب و هوا در فرودگاه مونیخ\n\n                                                     :انواع مکان های پشتیبانی شده\n\n    /paris                  # نام شهر\n    /~Eiffel+tower          # هر مکانی\n    /Москва                 # نام یونیکد هر مکانی در هر زبانی\n    /muc                    # کد فرودگاه (3 حرفی)\n    /@stackoverflow.com     # نام دامنه\n    /94107                  # کد منطقه\n    /-78.46,106.79          # موقعیت جغرافیایی\n\n                                                                :مکان های خاص\n\n    /moon                   # فازهای ماه (+US یا +France را برای این شهرها اضافه کنید)\n    /moon@2016-10-25        # فازهای ماه برای تاریخ خاص (@2016-10-25)\n\n                                                                           :واحدها\n\n    ?m                      # متریک (سیستم SI) (به طور پیشفرض در همه جا به جز امریکا استفاده می شود.)\n    ?u                      # USCS (به طور پیشفرض در امریکا استفاده می شود)\n    ?M                      # نمایش سرعت باد بر حسب متر بر ثانیه\n\n                                                                    :تنظیمات نمایش\n\n    ?0                      # فقط اب و هوای امروز\n    ?1                      # اب و هوای امروز + 1 روز\n    ?2                      # اب و هوای امروز + 2 روز\n    ?n                      # نسخه باریک (فقط روز و شب)\n    ?q                      # نسخه ساکت (بدون نوشته \"گزارش اب و هوا\")\n    ?Q                      # نسخه خیلی ساکت (بدون نوشته \"گزارش اب و هوا\" و اسم شهر)\n    ?T                      # حالت بدون رنگ\n\n                                                                    :تنظیمات خروجی PNG\n\n    /paris.png              # ساختن فایل PNG\n    ?p                      # اضافه کردن حاشیه در خروجی\n    ?t                      # قرار دادن شفافیت روی 150\n    transparency=...        # شفافیت از 0 تا 255 (255 یعنی بدون شفافیت)\n\n                                                        :تنظیمات ترکیبی\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # در PNG حالت فایل بعد از _ ذکر می شود\n    /Rome_0pq_lang=it.png   # تنظیمات بلند توسط اندرلاین جدا می شوند\n\n                                                                    :محلی سازی\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\n                                                            :زبان های پشتیبانی شده\n\n    FULL_TRANSLATION (پشتیبانی شده)\n    PARTIAL_TRANSLATION (در حال پیشرفت)\n\n                                                                    :ادرس های خاص\n\n    /:help                  # نمایش این صفحه\n    /:bash.function         # نمایش تابع پیشنهادی بش برای wttr()\n    /:translation           # نمایش اطلاعات در مورد مترجمین\n\n"
  },
  {
    "path": "share/translations/fa.txt",
    "content": "113: صاف                                                    : Clear\n113: آفتابی                                                 : Sunny\n116: نیمه ابری                                              : Partly cloudy\n119: ابری                                                   : Cloudy\n122: پوشیده از ابر                                          : Overcast\n143: شبنم                                                   : Mist\n176: احتمال بارش پراکنده باران                              : Patchy rain possible\n179: احتمال بارش پراکنده برف                                : Patchy snow possible\n182: احتمال بارش پراکنده تگرگ                               : Patchy sleet possible\n185: احتمال بارش پراکنده قطرات منجمد باران                  : Patchy freezing drizzle possible\n200: احتمال رعد و برق                                       : Thundery outbreaks possible\n227: بارش سنگین برف                                         : Blowing snow\n230: کولاک                                                  : Blizzard\n248: مه                                                     : Fog\n260: مه یخ زده                                              : Freezing fog\n263: بارش پراکنده نم نم باران                               : Patchy light drizzle\n266: بارش نم نم باران                                       : Light drizzle\n281: بارش ریزباران یخ بسته\t                                 : Freezing drizzle\n284: بارش سنگین ریزباران یخ بسته\t                           : Heavy freezing drizzle\n293: بارش پراکنده باران                                     : Patchy light rain\n296: بارش باران                                             : Light rain\n299: بارش یکنواخت و ملایم باران                             : Moderate rain at times\n302: بارش ملایم باران                                       : Moderate rain\n305: بارش سنگین باران به صورت یکنواخت                       : Heavy rain at times\n308: بارش سنگین باران                                       : Heavy rain\n311: بارش نم نم باران یخ بسته                               : Light freezing rain\n314: بارش ملایم یا سنگین باران یخ بسته                      : Moderate or heavy freezing rain\n317: بارش سبک تگرگ                                          : Light sleet\n320: بارش ملایم یا سنگین تگرگ                               : Moderate or heavy sleet\n323: بارش پراکنده و سبک برف                                 : Patchy light snow\n326: بارش سبک برف                                           : Light snow\n329: بارش پراکنده و ملایم برف                               : Patchy moderate snow\n332: بارش ملایم برف                                         : Moderate snow\n335: بارش پراکنده و سنگین برف                               : Patchy heavy snow\n338: بارش سنگین برف                                         : Heavy snow\n350: بارش دانه های ریز یخ                                   : Ice pellets\n353: دوش باران سبک                                          : Light rain shower\n356: دوش باران ملایم یا سنگین                               : Moderate or heavy rain shower\n359: دوش باران سیلی                                         : Torrential rain shower\n362: بارش سبک دوش تگرگ                                      : Light sleet showers\n365: بارش ملایم یا سنگین دوش تگرگ                           : Moderate or heavy sleet showers\n368: بارش سبک دوش برف                                       : Light snow showers\n371: بارش ملایم یا سنگین دوش برف                            : Moderate or heavy snow showers\n386: بارش پراکنده باران همراه با رعد و برق                  : Patchy light rain with thunder\n389: بارش ملایم یا سنگین باران همراه با رعد و برق           : Moderate or heavy rain with thunder\n392: بارش پراکنده برف ملایم یا سنگین همراه با رعد و برق     : Patchy light snow with thunder\n395: بارش ملایم یا سنگین برف همراه با رعد و برق             : Moderate or heavy snow with thunder"
  },
  {
    "path": "share/translations/fr-help.txt",
    "content": "Usage:\n\n    $ curl wttr.in          # emplacement actuel\n    $ curl wttr.in/cdg      # météo à l'aéroport de Paris - Charles de Gaulle\n\nTypes d'emplacements acceptés:\n\n    /paris                  # nom de la ville\n    /~Eiffel+tower          # emplacement quelconque\n    /Москва                 # nom Unicode ou emplacement quelconque dans n'importe quelle langue\n    /muc                    # code aéroport (3 lettres)\n    /@stackoverflow.com     # nom de domaine\n    /94107                  # code postal (seulement aux États-Unis)\n    /-78.46,106.79          # coordonnées GPS\n\nEmplacements particuliers:\n\n    /moon                   # phases de la lune (ajouter ,+US ou ,+France pour accéder aux villes du même nom)\n    /moon@2016-10-25        # phases de la lune pour cette date (@2016-10-25)\n\nUnités:\n\n    ?m                      # système métrique (par défaut partout sauf pour les États-Unis d'Amérique)\n    ?u                      # USCS (par défaut pour les États-Unis d'Amérique)\n    ?M                      # affiche la vitesse du vent en m/s\n\nOption d'affichage:\n\n    ?0                      # aujourd'hui seulement\n    ?1                      # aujourd'hui + demain\n    ?2                      # aujourd'hui + 2 jours\n    ?n                      # version courte (seulement le jour et la nuit)\n    ?q                      # version silencieuse (pas d'en-tête \"Prévisions météo pour\")\n    ?Q                      # version super-silencieuse (pas d'en-tête \"Prévisions météo pour\", pas de nom de la ville)\n    ?T                      # séquences d'échappement pour terminaux désactivées (pas de couleurs)\n\nOptions PNG:\n\n    /paris.png              # génère un fichier PNG\n    ?p                      # ajoute un cadre autour de la sortie\n    ?t                      # transparency 150 (transparence 150)\n    transparency=...        # transparence de 0 à 255 (255 = pas de transparence)\n\nCombiner les options:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # dans le mode PNG les options sont spécifiées après _\n    /Rome_0pq_lang=it.png   # les options longues sont séparées par des underscores _\n\nLocalisation:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nLangues supportées:\n\n    FULL_TRANSLATION (Support complet)\n    PARTIAL_TRANSLATION (Support incomplet)\n\nURLs particulières:\n\n    /:help                  # affiche cette page\n    /:bash.function         # fonction bash recommandée wttr()\n    /:translation           # affiche les informations sur la traduction de wttr.in\n\n"
  },
  {
    "path": "share/translations/fr.txt",
    "content": "113: Ensoleillé                                  : Sunny                                              :\n114: Temps clair                                 : Clear                                              :\n116: Partiellement couvert                       : Partly cloudy                                      :\n119: Nuageux                                     : Cloudy                                             :\n122: Couvert                                     : Overcast                                           :\n143: Brumeux                                     : Mist                                               :\n176: Pluies éparses possibles                    : Patchy rain possible                               :\n179: Chutes de neige éparses possibles           : Patchy snow possible                               :\n182: Chutes éparses de neige fondue possibles    : Patchy sleet possible                              :\n185: Bruines givrantes éparses possibles         : Patchy freezing drizzle possible                   :\n200: Orages possibles                            : Thundery outbreaks possible                        :\n227: Poudrerie                                   : Blowing snow                                       :\n230: Blizzard                                    : Blizzard                                           :\n248: Brouillard                                  : Fog                                                :\n260: Brouillard givrant                          : Freezing fog                                       :\n263: Bruines éparses et légères                  : Patchy light drizzle                               :\n266: Bruine légère                               : Light drizzle                                      :\n281: Bruine givrante                             : Freezing drizzle                                   :\n284: Forte bruine givrante                       : Heavy freezing drizzle                             :\n293: Pluies éparses et légères                   : Patchy light rain                                  :\n296: Pluie légère                                : Light rain                                         :\n299: Pluie modérée intermittente                 : Moderate rain at times                             :\n302: Pluie modérée                               : Moderate rain                                      :\n305: Forte pluie intermittente                   : Heavy rain at times                                :\n308: Forte pluie                                 : Heavy rain                                         :\n311: Pluie verglaçante légère                    : Light freezing rain                                :\n314: Pluie verglaçante modérée à forte           : Moderate or heavy freezing rain                    :\n317: Chutes légères de neige fondue              : Light sleet                                        :\n320: Chutes de neige fondue modérées à fortes    : Moderate or heavy sleet                            :\n323: Chutes de neige éparses et légères          : Patchy light snow                                  :\n326: Chutes de neige légères                     : Light snow                                         :\n329: Chutes de neige éparses et modérées         : Patchy moderate snow                               :\n332: Chutes de neige modérées                    : Moderate snow                                      :\n335: Fortes chutes de neige éparses              : Patchy heavy snow                                  :\n338: Fortes chutes de neige                      : Heavy snow                                         :\n350: Grésil                                      : Ice pellets                                        :\n353: Averses légères                             : Light rain shower                                  :\n356: Averses modérées à fortes                   : Moderate or heavy rain shower                      :\n359: Averses torrentielles                       : Torrential rain shower                             :\n362: Averses légères de neige fondue             : Light sleet showers                                :\n365: Averses de neige fondue modérées à fortes   : Moderate or heavy sleet showers                    :\n368: Légères averses de neige                    : Light snow showers                                 :\n371: Averses de neige modérées à fortes          : Moderate or heavy snow showers                     :\n386: Pluies légères et éparses avec tonnerre     : Patchy light rain with thunder                     :\n389: Pluies orageuses modérées à fortes          : Moderate or heavy rain with thunder                :\n392: Neige légère et éparse avec tonnerre        : Patchy light snow with thunder                     :\n395: Chutes de neige orageuses modérées à fortes : Moderate or heavy snow with thunder                :\n   : Brume à proximité                           : Haze in vicinity                                   :\n   : Fortes pluies et averses de neige           : Heavy rain and snow shower                         :\n   : Fortes averses de pluie                     : Heavy rain shower                                  :\n   : Bruine légère et grains de neige            : Light drizzle and snow grains                      :\n   : Averse légère de pluie et de brume          : Light rain and mist shower                         :\n   : Averse légère de grêlons/flocons de neige   : Light small hail/snow pellets shower               :\n   : Averse légère de précipitations inconnues   : Light unknown precipitation shower                 :\n   : Pluie et grêlons/flocons de neige avec orage : Rain and small hail/snow pellets with thunderstorm :\n   : Averse de neige à proximité                 : Snow shower in vicinity                            :\n   : Éclats orageux à proximité                  : Thundery outbreaks nearby                          :\n   : Poudrerie basse                             : Low drifting snow                                  :\n   : Plaques de brouillard                       : Patches of fog                                     :\n   : Bruine                                      : Drizzle                                            :\n   : Bruine légère et pluie                      : Light drizzle and rain                             :\n   : Neige                                       : Snow                                               :\n   : Pluie                                       : Rain                                               :\n   : Averse de pluie                             : Rain Shower                                        :\n   : Sable soufflé                               : Blowing sand                                       :\n   : Souffle de sable étendu                     : Blowing widespread dust                            :\n   : Souffle de sable étendu à proximité         : Blowing widespread dust in vicinity                :\n   : Bruine et brouillard                        : Drizzle and fog                                    :\n   : Bruine et pluie                             : Drizzle and rain                                   :\n   : Bruine et averse de pluie                   : Drizzle and rain shower                            :\n   : Bruine avec orage                           : Drizzle with thunderstorm                          :\n   : Tempête de poussière                        : Dust storm                                         :\n   : Brouillard à proximité                      : Fog in vicinity                                    :\n   : Bruine et pluie verglaçante                 : Freezing drizzle and rain                          :\n   : Brume verglaçante                           : Freezing mist                                      :\n   : Pluie verglaçante                           : Freezing rain                                      :\n   : Pluie verglaçante et neige                  : Freezing rain and snow                             :\n   : Précipitations inconnues verglaçantes       : Freezing unknown precipitation                     :\n   : Nuage en entonnoir à proximité              : Funnel cloud in vicinity                           :\n   : Averse de grêle                             : Hail shower                                        :\n   : Grêle avec orage                            : Hail with thunderstorm                             :\n   : Brume                                       : Haze                                               :\n   : Forte poudrerie                             : Heavy blowing snow                                 :\n   : Forte bruine                                : Heavy drizzle                                      :\n   : Forte bruine et pluie                       : Heavy drizzle and rain                             :\n   : Fortes précipitations inconnues verglaçantes : Heavy freezing unknown precipitation              :\n   : Forte grêle avec orage                      : Heavy hail with thunderstorm                       :\n   : Fort grésil                                 : Heavy ice pallets                                  :\n   : Fortes pluies et averses de grêle           : Heavy rain and hail shower                         :\n   : Fortes pluies et grêle avec orage           : Heavy rain and hail with thunderstorm              :\n   : Fortes pluies et averses de grêlons/flocons de neige : Heavy rain and small hail/snow pallets shower :\n   : Fortes pluies et averses de grêlons/flocons de neige avec orage : Heavy rain and small hail/snow pallets with thunderstorm :\n   : Forte pluie et neige                        : Heavy rain and snow                                :\n   : Forte pluie et neige, averses de grêlons/flocons de neige avec orage : Heavy rain and snow and small hail/snow pallets with thunderstorm :\n   : Pluie forte avec orage                      : Heavy rain with thunderstorm                       :\n   : Forte averse de grêlons/flocons de neige    : Heavy small hail/snow pallets shower               :\n   : Forte averse de grêlons/flocons de neige avec orage : Heavy small hail/snow pallets with thunderstorm :\n   : Fortes chutes de neige et averses de grêlons/flocons de neige : Heavy snow and small hail/snow pallets shower :\n   : Fortes chutes de neige et averses de grêlons/flocons de neige avec orage : Heavy snow and small hail/snow pallets with thunderstorm :\n   : Fortes chutes de neige                      : Heavy snow shower                                  :\n   : Fortes chutes de neige avec orage           : Heavy snow with thunderstorm                       :\n   : Cristaux de glace                           : Ice crystals                                       :\n   : Grésil                                      : Ice pallets                                        :\n   : Légère poudrerie                            : Light blowing snow                                 :\n   : Bruine légère et brouillard                 : Light drizzle and fog                              :\n   : Bruine légère et grésil                     : Light drizzle and ice pallets                      :\n   : Bruine légère, pluie et neige               : Light drizzle and rain and snow                    :\n   : Bruine légère et averse de pluie            : Light drizzle and rain shower                      :\n   : Bruine légère et pluie avec orage           : Light drizzle and rain with thunderstorm           :\n   : Bruine légère et neige                      : Light drizzle and snow                             :\n   : Bruine légère avec orage                    : Light drizzle with thunderstorm                    :\n   : Bruine verglaçante légère                   : Light freezing drizzle                             :\n   : Légère bruine verglaçante et pluie          : Light freezing drizzle and rain                    :\n   : Légère bruine verglaçante et neige          : Light freezing drizzle and snow                    :\n   : Léger brouillard givrant                    : Light freezing fog                                 :\n   : Légère pluie verglaçante et neige           : Light freezing rain and snow                       :\n   : Légers grains de neige verglaçants et brouillard : Light freezing snow grains and fog            :\n   : Légères précipitations verglaçantes inconnues : Light freezing unknown precipitation             :\n   : Légère averse de grêle                      : Light hail shower                                  :\n   : Légers cristaux de glace                    : Light ice crystals                                 :\n   : Léger grésil                                : Light ice pallets                                  :\n   : Souffle léger près du sol                   : Light low drifting                                 :\n   : Poudrerie légère et basse                   : Light low drifting snow                            :\n   : Pluie légère et averse de grêle             : Light rain and hail shower                         :\n   : Pluie légère et grêle avec orage            : Light rain and hail with thunderstorm              :\n   : Pluie légère et grésil                      : Light rain and ice pallets                         :\n   : Pluie légère et brume                       : Light rain and mist                                :\n   : Pluie légère et averses de grêlons/flocons de neige : Light rain and small hail/snow pallets shower :\n   : Pluie légère et averses de grêlons/flocons de neige avec orage : Light rain and small hail/snow pallets with thunderstorm :\n   : Pluie légère et neige                       : Light rain and snow                                :\n   : Pluie légère et neige et averses de grêlons/flocons de neige : Light rain and snow and small hail/snow pallets shower :\n   : Légère pluie et grains de neige             : Light rain and snow grains                         :\n   : Légère pluie et averses de neige            : Light rain and snow shower                         :\n   : Légère pluie et neige avec orage            : Light rain and snow with thunderstorm              :\n   : Légère pluie avec orage                     : Light rain with thunderstorm                       :\n   : Averse légère                               : Light shower                                       :\n   : Averse légère de grésil                     : Light showers of ice pellets                       :\n   : Légers grêlons/flocons de neige             : Light small hail/snow pallets                      :\n   : Averse légère de grêlons/flocons de neige   : Light small hail/snow pallets shower               :\n   : Légers grêlons/flocons de neige avec orage  : Light small hail/snow pallets with thunderstorm    :\n   : Neige légère et grésil                      : Light snow and ice pallets                         :\n   : Neige légère et chutes de grêlons/flocons de neige : Light snow and small hail/snow pallets      :\n   : Neige légère et averses de grêlons/flocons de neige : Light snow and small hail/snow pallets shower :\n   : Neige légère et averses de grêlons/flocons de neige avec orage : Light snow and small hail/snow pallets with thunderstorm :\n   : Neige légère et grains de neige             : Light snow and snow grains                         :\n   : Légers grains de neige                      : Light snow grains                                  :\n   : Légère averse de neige                      : Light snow shower                                  :\n   : Neige légère avec orage                     : Light snow with thunderstorm                       :\n   : Orage léger                                 : Light thunderstorm                                 :\n   : Légères précipitations inconnues            : Light unknown precipitation                        :\n   : Tourbillons légers et bien developpés de poussière/sable : Light well-developed dust/sand whirls :\n   : Léger souffle de sable bas                  : Low drifting sand                                  :\n   : Léger souffle de poussière étendue          : Low drifting widespread dust                       :\n   : Brume avec orage                            : Mist with thunderstorm                             :\n   : Pluie modérée ou forte avec orage           : Moderate or heavy rain in area with thunder        :\n   : Neige modérée ou forte avec orage           : Moderate or heavy snow in area with thunder        :\n   : Brouillard partiel                          : Partial fog                                        :\n   : Plaques de brouillard à proximité           : Patches of fog in vicinity                         :\n   : Bruine verglaçante éparse à proximité       : Patchy freezing drizzle nearby                     :\n   : Pluie légère et éparse localisée avec orage : Patchy light rain in area with thunder             :\n   : Neige légère et éparse localisée avec orage : Patchy light snow in area with thunder             :\n   : Pluie éparse à proximité                    : Patchy rain nearby                                 :\n   : Pluie verglaçante éparse à proximité        : Patchy sleet nearby                                :\n   : Neige éparse à proximité                    : Patchy snow nearby                                 :\n   : Averse de pluie et grêle                    : Rain and hail shower                               :\n   : Pluie et grêle avec orage                   : Rain and hail with thunderstorm                    :\n   : Pluie et brume                              : Rain and mist                                      :\n   : Pluie et brume avec orage                   : Rain and mist with thunderstorm                    :\n   : Pluie et averses de grêlons/flocons de neige : Rain and small hail/snow pallets shower           :\n   : Pluie et averses de grêlons/flocons de neige avec orage : Rain and small hail/snow pallets with thunderstorm :\n   : Pluie et neige                              : Rain and snow                                      :\n   : Pluie et neige avec averses de grêlons/flocons de neige : Rain and snow and small hail/snow pallets shower :\n   : Pluie et grains de neige                    : Rain and snow grains                               :\n   : Averse de pluie et neige                    : Rain and snow shower                               :\n   : Pluie et neige avec orage                   : Rain and snow with thunderstorm                    :\n   : Pluie à proximité                           : Rain in vicinity                                   :\n   : Averse de pluie à proximité                 : Rain shower in vicinity                            :\n   : Pluie avec orage                            : Rain with thunderstorm                             :\n   : Sable                                       : Sand                                               :\n   : Tempête de sable                            : Sandstorm                                          :\n   : Brouillard léger                            : Shallow fog                                        :\n   : Brume légère                                : Shallow mist                                       :\n   : Averse                                      : Shower                                             :\n   : Averse à proximité                          : Shower in vicinity                                 :\n   : Grêlons/flocons de neige                    : Small hail/snow pallets                            :\n   : Averse de grêlons/flocons de neige          : Small hail/snow pallets shower                     :\n   : Averse de grêlons/flocons de neige avec orage : Small hail/snow pallets with thunderstorm        :\n   : Fumée                                       : Smoke                                              :\n   : Neige et grésil                             : Snow and ice pallets                               :\n   : Neige et brume                              : Snow and mist                                      :\n   : Neige et averses de grêlons/flocons de neige : Snow and small hail/snow pellets shower           :\n   : Neige et averses de grêlons/flocons de neige avec orage : Snow and small hail/snow pallets with thunderstorm :\n   : Neige et grains de neige                    : Snow and snow grains                               :\n   : Grains de neige                             : Snow grains                                        :\n   : Averse de neige                             : Snow shower                                        :\n   : Neige avec orage                            : Snow with thunderstorm                             :\n   : Bourrasques                                 : Squalls                                            :\n   : Orage                                       : Thunderstorm                                       :\n   : Orage à proximité                           : Thunderstorm in vicinity                           :\n   : Éclats orageux à proximité                  : Thundery outbreaks in nearby                       :\n   : Précipitations inconnues                    : Unknown precipitation                              :\n   : Averse de précipitations inconnues          : Unknown precipitation shower                       :\n   : Précipitations inconnues avec orage         : Unknown precipitation with thunderstorm            :\n   : Cendres volcaniques                         : Volcanic ash                                       :\n   : Cendres volcaniques à proximité             : Volcanic ash in vicinity                           :\n   : Tourbillons de sable/poussière bien développés à proximité : Well-developed dust/sand whirls in vicinity :\n   : Poussière étendue                           : Widespread dust                                    :\n"
  },
  {
    "path": "share/translations/fy.txt",
    "content": "113: Helder                       : Clear                             \n113: Sinnich                      : Sunny\n116: Bytsje bewolkt               : Partly cloudy\n119: Bewolkt                      : Cloudy\n122: Bewolkt                      : Overcast\n143: Mistich                      : Mist\n176: Misskien lokaal reinbui      : Patchy rain possible\n179: Misskien lokaal snie         : Patchy snow possible\n182: Misskien lokaal hagel        : Patchy sleet possible\n185: Misskien lokaal izel         : Patchy freezing drizzle possible\n200: Misskien in onwaarsbui       : Thundery outbreaks possible\n227: Snie wyn                     : Blowing snow\n230: Sniestoarm                   : Blizzard\n248: Mistich                      : Fog\n260: Rijp                         : Freezing fog\n263: Lokaal motrein               : Patchy light drizzle\n266: Motrein                      : Light drizzle\n281: Izel                         : Freezing drizzle\n284: Swiere izel                  : Heavy freezing drizzle\n293: Lokaal in bytsje rein        : Patchy light rain\n296: Bytsje rein                  : Light rain\n299: Út en troch rein             : Moderate rain at times\n302: Rein                         : Moderate rain\n305: Út en troch swiere rein      : Heavy rain at times\n308: Swiere rein                  : Heavy rain\n311: Lichte izel                  : Light freezing rain\n314: Swiere izel                  : Moderate or heavy freezing rain\n317: Lichte hagel                 : Light sleet\n320: Swiere hagel                 : Moderate or heavy sleet\n323: Lokaal lichte snie           : Patchy light snow\n326: Lichte snie                  : Light snow\n329: Lokaal snie                  : Patchy moderate snow\n332: Snie                         : Moderate snow\n335: Lokaal swiere snie           : Patchy heavy snow\n338: Swiere snie                  : Heavy snow\n350: Hagel                        : Ice pellets\n353: Lichte reinbuien             : Light rain shower\n356: Reinbuien                    : Moderate or heavy rain shower\n359: Ekstreem swiere reinbuien    : Torrential rain shower\n362: Lichte hagelbuien            : Light sleet showers\n365: Hagelbuien                   : Moderate or heavy sleet showers\n368: Lichte sniebuien             : Light snow showers\n371: Sniebuien                    : Moderate or heavy snow showers\n386: Lokaal lichte rein mei onwaar: Patchy light rain with thunder      weer\n389: Rein mei onwaar              : Moderate or heavy rain with thunder\n392: Lokaal lichte snie mei onwaar: Patchy light snow with thunder      nweer\n395: Snie mei onwaar              : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/ga.txt",
    "content": "113: Geal                               : Clear\n113: Grianmhar                          : Sunny\n116: Breacscamallach                    : Partly cloudy\n119: Scamallach                         : Cloudy\n122: Scamallach                         : Overcast\n143: Ceochán                            : Mist\n176: Ceathanna                          : Patchy rain possible\n179: Ceathanna sneachta                 : Patchy snow possible\n182: Ceathanna flichshneachta           : Patchy sleet possible\n185: Ceathanna cloichshneachta          : Patchy freezing drizzle possible\n200: Ceathanna toirní                   : Thundery outbreaks possible\n227: Stealladh sneachta                 : Blowing snow\n230: Síobadh sneachta                   : Blizzard\n248: Ceo                                : Fog\n260: Ceo reoite                         : Freezing fog\n263: Ceobhrán                           : Patchy light drizzle\n266: Ceobhrán éadrom                    : Light drizzle\n281: Ceobhrán reoite                    : Freezing drizzle\n284: Ceobhrán reoite trom               : Heavy freezing drizzle\n293: Breachbháisteach éadrom            : Patchy light rain\n296: Báisteach éadrom                   : Light rain\n299: Báisteach mheasartha uaireanta     : Moderate rain at times\n302: Báisteach mheasartha               : Moderate rain\n305: Báisteach throm uairanta           : Heavy rain at times\n308: Báisteach throm                    : Heavy rain\n311: Báisteach reoite éadrom            : Light freezing rain\n314: Báisteach mheasartha nó reoite throm : Moderate or heavy freezing rain\n317: Flichshneachta éadrom              : Light sleet\n320: Flichshneachta measartha nó trom   : Moderate or heavy sleet\n323: Breacsneachta éadrom               : Patchy light snow\n326: Sneachta éadrom                    : Light snow\n329: Breacsneachta measartha            : Patchy moderate snow\n332: Sneachta measartha                 : Moderate snow\n335: Sneachta trom uaireanta            : Patchy heavy snow\n338: Sneachta trom                      : Heavy snow\n350: Chloichshneachta                   : Ice pellets\n353: Cith éadrom                        : Light rain shower\n356: Cith measartha no trom             : Moderate or heavy rain shower\n359: Duartan\t                        : Torrential rain shower\n362: Ceathanna flichshneachta           : Light sleet showers\n365: Ceathanna flichshneachta measartha nó troma : Moderate or heavy sleet showers\n368: Ceathanna sneachta éadroma         : Light snow showers\n371: Ceathanna sneachta measartha nó troma : Moderate or heavy snow showers\n386: Ceathanna éadroma le toirneach     : Patchy light rain with thunder\n389: Báisteach measartha nó throm le tóirneach : Moderate or heavy rain with thunder\n392: Sneachta éadrom le toirneach       : Patchy light snow with thunder\n395: Sneachta measartha nó trom le toirneach : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/gl-help.txt",
    "content": "Instrucións:\n\n    $ curl wttr.in          # o tempo na sua localización actual\n    $ curl wttr.in/muc      # o tempo no aeroporto de Múnic\n\nTipos de localización soportados:\n\n    /paris                  # o nome dunha cidade\n    /~Eiffel+tower          # o nome de calquera lugar famoso\n    /Москва                 # nome Unicode de calquera lugar en calquera idioma\n    /muc                    # o código dun aeroporto (3 letras)\n    /@stackoverflow.com     # o nome dun dominio web\n    /94107                  # um código de área\n    /-78.46,106.79          # coordenadas do GPS\n\nLugares especiais:\n\n    /moon                   # A fase da lúa (crecente ,+US ou ,+France para estas cidades)\n    /moon@2016-10-25        # A fase da lúa nunha determinada data (@2016-10-25)\n\nUnidades:\n\n    ?m                      # Métricas (SI) (por defecto en todos os lugares agás en EEUU)\n    ?u                      # Sistema Unificado de Clasificación de Solo ou USCS (por defecto en EEUU)\n    ?M                      # Amosar a velocidade do vento en m/s\n\nOpcións de visualización:\n\n    ?0                      # Soamente o clima actual\n    ?1                      # O clima actual + a previsión de 1 dia\n    ?2                      # O clima actual + a previsión de 2 dias\n    ?n                      # Versión curta (só o dia e a noite)\n    ?q                      # Versión breve (sen o texto de \"Previsión do Tempo\")\n    ?Q                      # Versión superbreve (sen \"Previsión do Tempo\" e o nome da cidade)\n    ?T                      # Desactiva as secuencias de escape no terminal (sen cores)\n\nOpións de PNG:\n\n    /paris.png              # Xera unha imaxe PNG\n    ?p                      # Amece un borde ao redor da imaxe\n    ?t                      # Transparencia 150\n    transparency=...        # Transparencia de 0 a 255 (255 = sen transparencia)\n\nAs opcións poden ser usadas en conxunto:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # Em PNG as opcións especificanse depois do caracter _\n    /Rome_0pq_lang=it.png   # Nunha secuencia longa de opcións, poden ser separadas polo caracter _\n\nLocalizaión:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nLinguas soportadas:\n\n    FULL_TRANSLATION (soportadas)\n    PARTIAL_TRANSLATION (en proceso)\n\nURLs especiais:\n\n    /:help                  # Amosa esta páxina\n    /:bash.function         # Suxire unha función wttr() en bash\n    /:translation           # Amosa información respecto dos tradutores\n\n"
  },
  {
    "path": "share/translations/gl.txt",
    "content": "113: Despexado                          : Clear\n113: Solleiro                           : Sunny\n116: Parcialmente Nubrado               : Partly cloudy\n119: Nubrado                            : Cloudy\n122: Cuberto                            : Overcast\n143: Neboa                              : Mist\n176: Posibel choiva                     : Patchy rain possible\n179: Posibel neve                       : Patchy snow possible\n182: Posibel auganeve                   : Patchy sleet possible\n185: Posibel barruzo xeado              : Patchy freezing drizzle possible\n200: Posibeis treboadas                 : Thundery outbreaks possible\n227: Cebrisca                           : Blowing snow\n230: Treboada de neve                   : Blizzard\n248: Brétema                            : Fog\n260: Brétema xeada                      : Freezing fog\n263: Barruzo lixeiro casual             : Patchy light drizzle\n266: Barruzo lixeiro                    : Light drizzle\n281: Barruzo xeado                      : Freezing drizzle\n284: Barruzo xeado forte                : Heavy freezing drizzle\n293: Chuvisca casual                    : Patchy light rain\n296: Chuvisca                           : Light rain\n299: Choiva casual                      : Moderate rain at times\n302: Choiva                             : Moderate rain\n305: Dioivo casual                      : Heavy rain at times\n308: Dioivo                             : Heavy rain\n311: Orballo xeado                      : Light freezing rain\n314: Xistra                             : Moderate or heavy freezing rain\n317: Auganeve lixeira                   : Light sleet\n320: Auganeve                           : Moderate or heavy sleet\n323: Nevarisca casual                   : Patchy light snow\n326: Nevarisca                          : Light snow\n329: Nevada casual                      : Patchy moderate snow\n332: Nevada                             : Moderate snow\n335: Nevada forte casual                : Patchy heavy snow\n338: Nevada forte                       : Heavy snow\n350: Sarabia                            : Ice pellets\n353: Orballo                            : Light rain shower\n356: Bategada                           : Moderate or heavy rain shower\n359: Choiva torrencial                  : Torrential rain shower\n362: Torba                              : Light sleet showers\n365: Torba forte                        : Moderate or heavy sleet showers\n368: Choiva con neve lixeira            : Light snow showers\n371: Choiva con neve forte              : Moderate or heavy snow showers\n386: Barruzo casual con tronos          : Patchy light rain with thunder\n389: Treboada                           : Moderate or heavy rain with thunder\n392: Nevarisca casual con tronos        : Patchy light snow with thunder\n395: Nevada con tronos                  : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/gu-help.txt",
    "content": "Usage:\n\n    $ curl wttr.in          # current location\n    $ curl wttr.in/muc      # weather in the Munich airport\n\nSupported location types:\n\n    /paris                  # city name\n    /~Eiffel+tower          # any location (+ for spaces)\n    /Москва                 # Unicode name of any location in any language\n    /muc                    # airport code (3 letters)\n    /@stackoverflow.com     # domain name\n    /94107                  # area codes\n    /-78.46,106.79          # GPS coordinates\n\nMoon phase information:\n\n    /moon                   # Moon phase (add ,+US or ,+France for these cities)\n    /moon@2016-10-25        # Moon phase for the date (@2016-10-25)\n\nUnits:\n\n    m                       # metric (SI) (used by default everywhere except US)\n    u                       # USCS (used by default in US)\n    M                       # show wind speed in m/s\n\nView options:\n\n    0                       # only current weather\n    1                       # current weather + today's forecast\n    2                       # current weather + today's + tomorrow's forecast\n    A                       # ignore User-Agent and force ANSI output format (terminal)\n    F                       # do not show the \"Follow\" line\n    n                       # narrow version (only day and night)\n    q                       # quiet version (no \"Weather report\" text)\n    Q                       # superquiet version (no \"Weather report\", no city name)\n    T                       # switch terminal sequences off (no colors)\n\nPNG options:\n\n    /paris.png              # generate a PNG file\n    p                       # add frame around the output\n    t                       # transparency 150\n    transparency=...        # transparency from 0 to 255 (255 = not transparent)\n    background=...          # background color in form RRGGBB, e.g. 00aaaa\n\nOptions can be combined:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # in PNG the file mode are specified after _\n    /Rome_0pq_lang=it.png   # long options are separated with underscore\n\nLocalization:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nSupported languages:\n\n    FULL_TRANSLATION (supported)\n    PARTIAL_TRANSLATION (in progress)\n\nSpecial URLs:\n\n    /:help                  # show this page\n    /:bash.function         # show recommended bash function wttr()\n    /:translation           # show the information about the translators\n\n"
  },
  {
    "path": "share/translations/gu.txt",
    "content": ": Fortes pluies et orages de grêle                 : Heavy rain and hail with thunderstorm\n: Fortes pluies orageuses                          : Heavy rain with thunderstorm\n: Orages de pluie et grêle légères                 : Light rain and hail with thunderstorm\n: Pluie légère et averses                          : Light rain and snow shower\n: Pluies légères orageuses                         : Light rain with thunderstorm\n: Chutes de neige légères                          : Light snow shower\n: Nappes de brouillard                             : Partial fog\n: Orage de pluie et de grêle                       : Rain and hail with thunderstorm\n: Pluies orageuses                                 : Rain with thunderstorm\n: Brouillard léger                                 : Shallow fog\n: Brume                                            : Smoke\n: Grains                                           : Squalls\n: Orages proches                                   : Thunderstorm in vicinity\n: Neige                                            : Snow\n: Pluie                                            : Rain\n: Pluie légère, Averses                            : Light Rain, Rain Shower\n: Averses                                          : Rain Shower\n: Nappes de brouillard                             : Patches of fog\n: Bruine                                           : Drizzle\n: Bruine légère                                    : Light drizzle\n: Chasse-neige basse                               : Low drifting snow\n: Pluie et neige légères                           : Light rain and snow\n: Averses proches                                  : Shower in vicinity\n: Pluie et orages                                  : Rain with thunderstorm\n: Averse de pluie et neige mêlées                  : Rain and snow shower\n: Orage                                            : Thunderstorm\n: Bruine et pluie                                  : Drizzle and rain\n: Orage de grêle                                   : Hail with thunderstorm\n: Brume                                            : Haze\n: Bruine legère et pluie                           : Light drizzle and rain\n: Orage, pluie légère et grèle / neige roulée      : Light rain and small hail/snow pallets with thunderstorm\n113 : Temps clair                                  : Clear\n113 : Ensoleillé                                   : Sunny\n116 : Partiellement couvert                        : Partly cloudy\n119 : Nuageux                                      : Cloudy\n122 : Couvert                                      : Overcast\n143 : Brumeux                                      : Mist\n176 : Pluies éparses possibles                     : Patchy rain possible\n179 : Chutes de neige éparses possibles            : Patchy snow possible\n182 : Chutes éparses de neige fondue possibles     : Patchy sleet possible\n185 : Bruines givrantes éparses possibles          : Patchy freezing drizzle possible\n200 : Orages possibles                             : Thundery outbreaks possible\n227 : Poudrerie                                    : Blowing snow\n230 : Blizzard                                     : Blizzard\n248 : Brouillard                                   : Fog\n260 : Brouillard givrant                           : Freezing fog\n263 : Bruines éparses et légères                   : Patchy light drizzle\n266 : Bruine légère                                : Light drizzle\n281 : Bruine givrante                              : Freezing drizzle\n284 : Forte bruine givrante                        : Heavy freezing drizzle\n293 : Pluies éparses et légères                    : Patchy light rain\n296 : Pluie légère                                 : Light rain\n299 : Pluie modérée intermittente                  : Moderate rain at times\n302 : Pluie modérée                                : Moderate rain\n305 : Forte pluie intermittente                    : Heavy rain at times\n308 : Forte pluie                                  : Heavy rain\n311 : Pluie verglaçante légère                     : Light freezing rain\n314 : Pluie verglaçante modérée à forte            : Moderate or heavy freezing rain\n317 : Chutes légères de neige fondue               : Light sleet\n320 : Chutes de neige fondue modérées à fortes     : Moderate or heavy sleet\n323 : Chutes de neige éparses et légères           : Patchy light snow\n326 : Chutes de neige légères                      : Light snow\n329 : Chutes de neige éparses et modérées          : Patchy moderate snow\n332 : Chutes de neige modérées                     : Moderate snow\n335 : Fortes chutes de neige éparses               : Patchy heavy snow\n338 : Fortes chutes de neige                       : Heavy snow\n350 : Grésil                                       : Ice pellets\n353 : Averses légères                              : Light rain shower\n356 : Averses modérées à fortes                    : Moderate or heavy rain shower\n359 : Averses torrentielles                        : Torrential rain shower\n362 : Averses légères de neige fondue              : Light sleet showers\n365 : Averses de neige fondue modérées à fortes    : Moderate or heavy sleet showers\n368 : Averses de neige légères                     : Light snow showers\n371 : Averses de neige modérées à fortes           : Moderate or heavy snow showers\n386 : Pluies orageuses légères et éparses          : Patchy light rain with thunder\n389 : Pluies orageuses modérées à fortes           : Moderate or heavy rain with thunder\n392 : Chutes de neige orageuses légères et éparses : Patchy light snow with thunder\n395 : Chutes de neige orageuses modérées à fortes  : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/he.txt",
    "content": "113 :                                     בהיר: Clear\n113 :                                     שמשי: Sunny\n116 :                                        מעונן חלקית : Partly cloudy\n119 :                                        מעונן : Cloudy\n122 :                                        מעונן : Overcast\n143 :                                        ערפל : Mist\n176 :                                        סיכוי לגשם מקומי : Patchy rain possible\n179 :                                        סיכוי לשלג מקומי : Patchy snow possible\n182 :                                        סיכוי לגשם מעורב בשלג מקומי : Patchy sleet possible\n185 :                                        סיכוי לברד מקומי : Patchy freezing drizzle possible\n200 :                                        סיכוי לסופת ברקים : Thundery outbreaks possible\n227 :                                        משבי שלג : Blowing snow\n230 :                                        סופת שלג : Blizzard\n248 :                                        ערפל : Fog\n260 :                                        קרה : Freezing fog\n263 :                                        ברד מקומי קל : Patchy light drizzle\n266 :                                        ברד קל : Light drizzle\n281 :                                        ברד : Freezing drizzle\n284 :                                        ברד כבד : Heavy freezing drizzle\n293 :                                        גשם מקומי קל : Patchy light rain\n296 :                                        גשם קל : Light rain\n299 :                                        גשם לסירוגין : Moderate rain at times\n302 :                                        גשם  : Moderate rain\n305 :                                        גשם כבד לסירוגין : Heavy rain at times\n308 :                                        גשם כבד : Heavy rain\n311 :                                        גשם קופא קל : Light freezing rain\n314 :                                        גשם קופא בינוני עד כבד : Moderate or heavy freezing rain\n317 :                                        גשם מעורב בשלג קל : Light sleet\n320 :                                        גשם מעורב בשלג בינוני עד כבד : Moderate or heavy sleet\n323 :                                        שלג מקומי קל : Patchy light snow\n326 :                                        שלג קל : Light snow\n329 :                                        שלג מקומי בינוני : Patchy moderate snow\n332 :                                        שלג בינוני : Moderate snow\n335 :                                        שלג מקומי כבד : Patchy heavy snow\n338 :                                        שלג כבד : Heavy snow\n350 :                                        ברד : Ice pellets\n353 :                                        גשם קל : Light rain shower\n356 :                                        גשם בינוני עד כבד : Moderate or heavy rain shower\n359 :                                        ממטרים כבדים : Torrential rain shower\n362 :                                        גשם מעורב בשלג קל : Light sleet showers\n365 :                                        גשם מעורב בשלג בינוני עד כבד : Moderate or heavy sleet showers\n368 :                                        שלג קל : Light snow showers\n371 :                                        שלג בינוני עד כבד : Moderate or heavy snow showers\n386 :                                        גשם מקומי קל ורעמים : Patchy light rain with thunder\n389 :                                        גשם בינוני עד כבד ורעמים : Moderate or heavy rain with thunder\n392 :                                        שלג קל ורעמים : Patchy light snow with thunder\n395 :                                        שלג בינוני עד כבד ורעמים : Moderate or heavy snow with thunder"
  },
  {
    "path": "share/translations/hi-help.txt",
    "content": "उपयोग:\n\n    $ curl wttr.in          # वर्तमान स्थान के मौसम की जानकारी \n    $ curl wttr.in/muc      # म्यूनिख हवाई अड्डे का मौसम\n\nसमर्थित स्थान प्रकार:\n\n    /paris                  # शहर का नाम\n    /~Eiffel+tower          # कोई भी स्थान (एक से अधिक शब्दो को जोड़ने के लिए + का उपयोग करे)\n    /Москва                 # किसी भी भाषा में किसी भी स्थान का यूनिकोड नाम\n    /muc                    # एयरपोर्ट कोड (3 अक्षर)\n    /@stackoverflow.com     # डोमेन नाम\n    /94107                  # क्षेत्र कोड\n    /-78.46,106.79          # जीपीएस निर्देशांक\n\nचंद्र चरण की जानकारी:\n\n    /moon                   # चंद्रमा चरण (शहरों के लिए +US या, +France जोड़ें)\n    /moon@2016-10-25        # तिथि के लिए चंद्र चरण (@2016-10-25)\n\nइकाइयां:\n\n    m                       # मेट्रिक (एसआई) (यूएस को छोड़कर हर जगह डिफ़ॉल्ट रूप से उपयोग किया जाता है)\n    u                       # यूएससीएस (यूएस में डिफ़ॉल्ट रूप से प्रयुक्त)\n    M                       # हवा की गति मीटर/सेकंड में दिखाएं\n\nविकल्प देखें:\n\n    0                       # केवल वर्तमान मौसम\n    1                       # वर्तमान मौसम और आज का पूर्वानुमान\n    2                       # वर्तमान मौसम और आज का और कल का पूर्वानुमान\n    A                       # युसेर-एजेंट को अनदेखा करें और एएनएसआई आउटपुट (टर्मिनल) को बाध्य करें\n    F                       # \"फॉलो\" लाइन न दिखाएं\n    n                       # संकीर्ण संस्करण (केवल दिन और रात के लिये)\n    q                       # शांत संस्करण (कोई \"मौसम रिपोर्ट\" पाठ नहीं)\n    Q                       # अति शांत संस्करण (\"मौसम की जानकारी\" और शहर का नाम नहीं)\n    T                       # टर्मिनल अनुक्रम बंद करें (रंगो के बिना)\n\nपीएनजी विकल्प:\n\n    /paris.png              # पीएनजी फ़ाइल जनरेट करें\n    p                       # आउटपुट के चारों ओर फ्रेम जोड़ें\n    t                       # पारदर्शिता 150\n    transparency=...        # पारदर्शिता 0 से 255 तक (255 = पारदर्शी नहीं)\n    background=...          # RRGGBB के रूप में पृष्ठभूमि का रंग, जैसे की 00aaaa\n\nविकल्पों को जोड़ा जा सकता है:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # पीएनजी में फ़ाइल मोड को \"_\" के बाद निर्दिष्ट किया जाता है\n    /Rome_0pq_lang=it.png   # लंबे विकल्पों को अंडरस्कोर से अलग किया जाता है\n\nस्थानीयकरण:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nसमर्थित भाषाएँ:\n\n    FULL_TRANSLATION (समर्थित)\n    PARTIAL_TRANSLATION (प्रगति में)\n\nविशेष यूआरएल:\n\n    /:help                  # इस पेज को दिखाएं\n    /:bash.function         # अनुशंसित बैश फ़ंक्शन wttr () दिखाएं\n    /:translation           # अनुवादकों के बारे में जानकारी दिखाएं\n"
  },
  {
    "path": "share/translations/hi.txt",
    "content": ": तेज बारिश और गरज के साथ ओलावृष्टि                 \t\t   : Heavy rain and hail with thunderstorm\n: गरज के साथ तेज बारिश                          \t    \t : Heavy rain with thunderstorm\n: गरज के साथ हल्की बारिश और ओलावृष्टि                   \t \t: Light rain and hail with thunderstorm\n: हल्की बारिश और बर्फ की बौछार                       \t\t\t : Light rain and snow shower\n: गरज के साथ हल्की बारिश                     \t\t     \t    : Light rain with thunderstorm\n: हल्की बर्फ़ की बौछार                            \t\t      : Light snow shower\n: आंशिक कोहरा                                 \t\t      : Partial fog\n: घना कोहरा                                      \t\t     : Patchy fog\n: गरज के साथ बारिश और ओलावृष्टि                     \t\t   : Rain and hail with thunderstorm\n: गरज के साथ बारिश                            \t\t   \t\t : Rain with thunderstorm\n: उथला कोहरा             \t\t\t                   \t\t \t \t: Shallow fog\n: धुआं              \t                        \t\t  \t\t  : Smoke\n: तूफ़ान                                  \t\t\t          : Squalls\n: आसपास में आंधी                               \t\t\t\t    : Thunderstorm in vicinity\n: हिमपात                                    \t\t\t       : Snow\n: वर्षा                                          \t\t\t      : Rain\n: हल्की बारिश, बारिश की बौछार                  \t\t\t         : Light Rain, Rain Shower\n: बारिश की बौछार                               \t\t\t       : Rain Shower\n: कोहरे के धब्बे                                   \t\t\t     : Patches of fog\n: बूंदा बांदी                                      \t\t\t      : Drizzle\n: हल्की बूंदाबांदी                                  \t\t\t     : Light drizzle\n: कम बहती बर्फ                                  \t\t\t\t   : Low drifting snow\n: हल्की बारिश और हिमपात                       \t\t\t        : Light rain and snow\n: आस-पास शावर                                 \t\t\t\t \t\t: Shower in vicinity\n: गरज के साथ बारिश                                \t\t\t\t  : Rain with thunderstorm\n: बारिश और बर्फ की बौछार                                      : Rain and snow shower\n: आंधी तूफान                                     \t\t \t       : Thunderstorm\n: बूंदा बांदी और बारिश                              \t\t\t\t     : Drizzle and rain\n: गरज के साथ ओलावृष्टि                               \t\t\t\t    : Hail with thunderstorm\n: धुंध                                                         : Haze\n: हल्की बूंदा बांदी और बारिश                                      : Light drizzle and rain\n: गरज के साथ हल्की बारिश और छोटे-छोटे ओले/बर्फ की पट्टियां           : Light rain and small hail/snow pallets with thunderstorm\n113 : स्पष्ट                               \t\t\t\t\t\t\t\t\t\t   : Clear\n113 : धूपदार                            \t\t\t\t\t\t\t\t       : Sunny\n116 : आंशिक रूप से बादल छाएंगे              \t\t\t\t\t          : Partly cloudy\n119 : बादल                             \t\t\t\t\t\t\t         : Cloudy\n122 : घटाटोप                                \t\t\t\t\t\t      : Overcast\n143 : कोहरा                                 \t\t\t\t\t  \t     : Mist\n176 : हल्की बारिश संभव                   \t\t\t    \t\t\t\t\t\t\t  : Patchy rain possible\n179 : हल्की बर्फ़बारी संभव         \t\t\t\t\t\t\t   \t\t\t\t\t\t\t   : Patchy snow possible\n182 : हल्की ओले के साथ वर्षा संभव    \t\t\t\t\t\t\t\t\t\t  \t\t\t\t : Patchy sleet possible\n185 : जमने वाली हल्की बूंदाबांदी संभव    \t\t\t\t    \t\t\t\t  \t      : Patchy freezing drizzle possible\n200 : गरज का प्रकोप संभव       \t\t\t\t\t\t                       : Thundery outbreaks possible\n227 : उड़ाने वाली बर्फ                \t\t\t\t\t\t                  : Blowing snow\n230 : बर्फानी तूफान                            \t\t     \t\t   \t    : Blizzard\n248 : कोहरा                        \t\t\t\t   \t\t\t\t            : Fog\n260 : अत्यधिक ठंडा कोहरा         \t\t\t\t\t                        : Freezing fog\n263 : हल्की हल्की बूंदा बांदी           \t\t\t\t\t\t\t\t\t            : Patchy light drizzle\n266 : हल्की बूंदाबांदी                 \t\t \t\t   \t\t\t               : Light drizzle\n281 : जमा देने वाली हवा                                          : Freezing drizzle\n284 : भारी जमने वाली बूंदा बांदी                                     : Heavy freezing drizzle\n293 : हल्की हल्की बारिश                                           : Patchy light rain\n296 : हलकी बारिश                                               : Light rain\n299 : कभी-कभी मध्यम बारिश                                        : Moderate rain at times\n302 : औसत दर्जे की वर्षा                  \t\t                      : Moderate rain\n305 : रुक-रुक कर हो रही भारी बारिश       \t\t                       : Heavy rain at times\n308 : भारी वर्षा                           \t\t\t                     : Heavy rain\n311 : हल्की जमने वाली बारिश                \t\t                       : Light freezing rain\n314 : मध्यम या भारी जमने वाली बारिश         \t                       : Moderate or heavy freezing rain\n317 : हल्की ओले के साथ वर्षा                 \t            \t\t\t\t    : Light sleet\n320 : मध्यम या भारी ओले के साथ वर्षा                      \t\t         : Moderate or heavy sleet\n323 : हल्की हल्की बर्फ                         \t\t\t                : Patchy light snow\n326 : हल्की बर्फ                           \t  \t\t\t                : Light snow\n329 : हल्की मध्यम हिमपात                  \t\t                     : Patchy moderate snow\n332 : मध्यम हिमपात                              \t\t\t\t          : Moderate snow\n335 : हल्की भारी हिमपात                        \t\t\t               : Patchy heavy snow\n338 : भारी हिमपात                              \t\t\t             : Heavy snow\n350 : ओले के साथ वर्षा                  \t\t\t\t\t\t\t\t\t        : Ice pellets\n353 : हल्की बोछारे                              \t\t              : Light rain shower\n356 : मध्यम या भारी बारिश की बौछार  \t\t\t\t\t\t\t                 : Moderate or heavy rain shower\n359 : मूसलाधार बारिश की बौछार        \t\t\t\t\t\t\t                : Torrential rain shower\n362 : हल्की ओले के साथ बौछारें          \t\t\t\t\t\t\t\t\t\t  \t    : Light sleet showers\n365 : मध्यम से भारी ओले के साथ बौछारें          \t\t\t  \t\t\t\t\t    : Moderate or heavy sleet showers\n368 : हल्की बर्फ़बारी              \t\t\t\t\t\t\t\t\t\t\t\t\t       : Light snow showers\n371 : मध्यम या भारी हिमपात की बौछार   \t\t\t\t\t\t\t\t\t\t        : Moderate or heavy snow showers\n386 : गरज के साथ हल्की बारिश       \t\t\t\t\t\t\t\t\t\t\t\t\t\t   : Patchy light rain with thunder\n389 : गरज के साथ मध्यम या भारी बारिश \t\t\t\t\t\t\t\t\t            : Moderate or heavy rain with thunder\n392 : गरज के साथ हल्की हल्की बर्फ़\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  : Patchy light snow with thunder\n395 : गरज के साथ मध्यम या भारी हिमपात\t\t\t\t\t\t\t\t\t\t\t\t\t\t  : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/hr.txt",
    "content": "   :     Kiša                                    : Rain                                               :\n113 : Vedro                                       : Clear                                              :\n113 : Sunčano                                     : Sunny                                              :\n116 : Djelomično oblačno                          : Partly cloudy                                      :\n119 : Oblačno                                     : Cloudy                                             :\n122 : Tmurno                                      : Overcast                                           :\n143 : Magla                                       : Mist                                               :\n176 : Moguća povremena kiša                       : Patchy rain possible                               :\n179 : Moguć povremeni snijeg                      : Patchy snow possible                               :\n182 : Moguća povremena susnježica                 : Patchy sleet possible                              :\n185 : Moguća ledena rosulja                       : Patchy freezing drizzle possible                   :\n200 : Moguć prolom oblaka                         : Thundery outbreaks possible                        :\n227 : Nanosi snijega                              : Blowing snow                                       :\n230 : Mećava                                      : Blizzard                                           :\n248 : Magla                                       : Fog                                                :\n260 : Ledena magla                                : Freezing fog                                       :\n263 : Povremena rosulja                           : Patchy light drizzle                               :\n266 : Lagana rosulja                              : Light drizzle                                      :\n281 : Ledena rosulja                              : Freezing drizzle                                   :\n284 : Jaka ledena rosulja                         : Heavy freezing drizzle                             :\n293 : Povremena lagana kiša                       : Patchy light rain                                  :\n296 : Lagana kiša                                 : Light rain                                         :\n299 : Umjerena povremena kiša                     : Moderate rain at times                             :\n302 : Umjerena kiša                               : Moderate rain                                      :\n305 : Povremeni pljuskovi                         : Heavy rain at times                                :\n308 : Jaka kiša                                   : Heavy rain                                         :\n311 : Lagana ledena kiša                          : Light freezing rain                                :\n314 : Umjerena ili jaka ledena kiša               : Moderate or heavy freezing rain                    :\n317 : Lagana susnježica                           : Light sleet                                        :\n320 : Umjerena ili jaka susnježica                : Moderate or heavy sleet                            :\n323 : Povremen lagan snijeg                       : Patchy light snow                                  :\n326 : Lagan snijeg                                : Light snow                                         :\n329 : Povremen umjeren snijeg                     : Patchy moderate snow                               :\n332 : Umjeren snijeg                              : Moderate snow                                      :\n335 : Povremen jak snijeg                         : Patchy heavy snow                                  :\n338 : Jak snijeg                                  : Heavy snow                                         :\n350 : Ledena tuča                                 : Ice pellets                                        :\n353 : Lagani pljusak                              : Light rain shower                                  :\n356 : Umjeren ili jak pljusak                     : Moderate or heavy rain shower                      :\n359 : Obilan pljusak                              : Torrential rain shower                             :\n362 : Lagana susnježica                           : Light sleet showers                                :\n365 : Umjerena ili jaka susnježica                : Moderate or heavy sleet showers                    :\n368 : Lagani snježni pljuskovi                    : Light snow showers                                 :\n371 : Umjereni ili jaki snježni pljuskovi         : Moderate or heavy snow showers                     :\n386 : Povremena lagana kiša s grmljavinom         : Patchy light rain with thunder                     :\n389 : Umjerena ili jaka kiša s grmljavinom        : Moderate or heavy rain with thunder                :\n392 : Povremen lagan snijeg s grmljavinom         : Patchy light snow with thunder                     :\n395 : Umjeren ili jak snijeg s grmljavinom        : Moderate or heavy snow with thunder                :\n   : Maglica u blizini                           : Haze in vicinity                                   :\n   : Jak kišni i snježni pljusak                 : Heavy rain and snow shower                         :\n   : Jak kišni pljusak                           : Heavy rain shower                                  :\n   : Lagana kišica i snježni kristali            : Light drizzle and snow grains                      :\n   : Lagana kiša i pljusak magle                 : Light rain and mist shower                         :\n   : Lagan pljusak sitne tuče/snježnih kuglica   : Light small hail/snow pellets shower               :\n   : Lagan pljusak nepoznatih oborina            : Light unknown precipitation shower                 :\n   : Kiša i sitna tuča/snježne kuglice s grmljavinom  : Rain and small hail/snow pellets with thunderstorm :\n   : Snježni pljusak u blizini                   : Snow shower in vicinity                            :\n   : Grmljavinske oluje u blizini                : Thundery outbreaks nearby                          :\n   : Nisko vijanje snijega                       : Low drifting snow                                  :\n   : Polja magle                                 : Patches of fog                                     :\n   : Kišica                                      : Drizzle                                            :\n   : Lagana kišica i kiša                        : Light drizzle and rain                             :\n   : Snijeg                                      : Snow                                               :\n   : Kišni pljusak                               : Rain Shower                                        :\n   : Vijanje pijeska                             : Blowing sand                                       :\n   : Široko rasprostranjeno vijanje prašine      : Blowing widespread dust                            :\n   : Široko rasprostranjeno vijanje prašine u blizini  : Blowing widespread dust in vicinity                :\n   : Kišica i magla                              : Drizzle and fog                                    :\n   : Kišica i kiša                               : Drizzle and rain                                   :\n   : Kišica i kišni pljusak                      : Drizzle and rain shower                            :\n   : Kišica s grmljavinom                        : Drizzle with thunderstorm                          :\n   : Pješčana oluja                              : Dust storm                                         :\n   : Magla u blizini                             : Fog in vicinity                                    :\n   : Smrzavajuća kišica i kiša                   : Freezing drizzle and rain                          :\n   : Smrzavajuća magla                           : Freezing mist                                      :\n   : Smrzavajuća kiša                            : Freezing rain                                      :\n   : Smrzavajuća kiša i snijeg                   : Freezing rain and snow                             :\n   : Smrzavajuće nepoznate oborine               : Freezing unknown precipitation                     :\n   : Lijevasta oblak u blizini                   : Funnel cloud in vicinity                           :\n   : Pljusak tuče                                : Hail shower                                        :\n   : Tuča s grmljavinom                          : Hail with thunderstorm                             :\n   : Maglica                                     : Haze                                               :\n   : Jako vijanje snijega                        : Heavy blowing snow                                 :\n   : Jaka kišica                                 : Heavy drizzle                                      :\n   : Jaka kišica i kiša                          : Heavy drizzle and rain                             :\n   : Jake smrzavajuće nepoznate oborine          : Heavy freezing unknown precipitation               :\n   : Jaka tuča s grmljavinom                     : Heavy hail with thunderstorm                       :\n   : Jaki ledeni kristali                        : Heavy ice pallets                                  :\n   : Jaka kiša i pljusak tuče                    : Heavy rain and hail shower                         :\n   : Jaka kiša i tuča s grmljavinom              : Heavy rain and hail with thunderstorm              :\n   : Jaka kiša i sitna tuča/snježne kuglice pljusak  : Heavy rain and small hail/snow pallets shower      :\n   : Jaka kiša i sitna tuča/snježne kuglice s grmljavinom  : Heavy rain and small hail/snow pallets with thunderstorm :\n   : Jaka kiša i snijeg                          : Heavy rain and snow                                :\n   : Jaka kiša i snijeg te sitna tuča/snježne kuglice s grmljavinom  : Heavy rain and snow and small hail/snow pallets with thunderstorm :\n   : Jaka kiša s grmljavinom                     : Heavy rain with thunderstorm                       :\n   : Jak pljusak sitne tuče/snježnih kuglica     : Heavy small hail/snow pallets shower               :\n   : Jaka sitna tuča/snježne kuglice s grmljavinom  : Heavy small hail/snow pallets with thunderstorm    :\n   : Jak snijeg i pljusak sitne tuče/snježnih kuglica  : Heavy snow and small hail/snow pallets shower      :\n   : Jak snijeg i sitna tuča/snježne kuglice s grmljavinom  : Heavy snow and small hail/snow pallets with thunderstorm :\n   : Jak snježni pljusak                         : Heavy snow shower                                  :\n   : Jak snijeg s grmljavinom                    : Heavy snow with thunderstorm                       :\n   : Ledeni kristali                             : Ice crystals                                       :\n   : Ledeni kristali                             : Ice pallets                                        :\n   : Lagan vijanje snijega                       : Light blowing snow                                 :\n   : Lagana kišica i magla                       : Light drizzle and fog                              :\n   : Lagana kišica i ledeni kristali             : Light drizzle and ice pallets                      :\n   : Lagana kišica i kiša i snijeg               : Light drizzle and rain and snow                    :\n   : Lagana kišica i kišni pljusak               : Light drizzle and rain shower                      :\n   : Lagana kišica i kiša s grmljavinom          : Light drizzle and rain with thunderstorm           :\n   : Lagana kišica i snijeg                      : Light drizzle and snow                             :\n   : Lagana kišica s grmljavinom                 : Light drizzle with thunderstorm                    :\n   : Lagan smrzavajući kišica                    : Light freezing drizzle                             :\n   : Lagan smrzavajući kišica i kiša             : Light freezing drizzle and rain                    :\n   : Lagan smrzavajući kišica i snijeg           : Light freezing drizzle and snow                    :\n   : Lagan smrzavajući magla                     : Light freezing fog                                 :\n   : Lagan smrzavajući kiša i snijeg             : Light freezing rain and snow                       :\n   : Lagan smrzavajući snježni kristali i magla  : Light freezing snow grains and fog                 :\n   : Lagan smrzavajući nepoznate oborine         : Light freezing unknown precipitation               :\n   : Lagan pljusak tuče                          : Light hail shower                                  :\n   : Lagani ledeni kristali                      : Light ice crystals                                 :\n   : Lagani ledeni kristali                      : Light ice pallets                                  :\n   : Lagan nisko vijanje                         : Light low drifting                                 :\n   : Lagan nisko vijanje snijega                 : Light low drifting snow                            :\n   : Lagana kiša i pljusak tuče                  : Light rain and hail shower                         :\n   : Lagana kiša i tuča s grmljavinom            : Light rain and hail with thunderstorm              :\n   : Lagana kiša i ledeni kristali               : Light rain and ice pallets                         :\n   : Lagana kiša i magla                         : Light rain and mist                                :\n   : Lagana kiša i pljusak sitne tuče/snježnih kuglica  : Light rain and small hail/snow pallets shower      :\n   : Lagana kiša i sitna tuča/snježne kuglice s grmljavinom  : Light rain and small hail/snow pallets with thunderstorm :\n   : Lagana kiša i snijeg                        : Light rain and snow                                :\n   : Lagana kiša i snijeg te pljusak sitne tuče/snježnih kuglica  : Light rain and snow and small hail/snow pallets shower :\n   : Lagana kiša i snježni kristali              : Light rain and snow grains                         :\n   : Lagana kiša i snježni pljusak               : Light rain and snow shower                         :\n   : Lagana kiša i snijeg s grmljavinom          : Light rain and snow with thunderstorm              :\n   : Lagana kiša s grmljavinom                   : Light rain with thunderstorm                       :\n   : Lagan pljusak                               : Light shower                                       :\n   : Lagan pljusak ledenih kuglica               : Light showers of ice pellets                       :\n   : Lagan sitna tuča/snježne kuglice            : Light small hail/snow pallets                      :\n   : Lagan pljusak sitne tuče/snježnih kuglica   : Light small hail/snow pallets shower               :\n   : Lagan sitna tuča/snježne kuglice s grmljavinom  : Light small hail/snow pallets with thunderstorm    :\n   : Lagan snijeg i ledeni kristali              : Light snow and ice pallets                         :\n   : Lagan snijeg i sitna tuča/snježne kuglice   : Light snow and small hail/snow pallets             :\n   : Lagan snježni pljusak sa sitnom tučom/snježnim kuglicama  : Light snow and small hail/snow pallets shower      :\n   : Lagan snijeg sa sitnom tučom/snježnim kuglicama i grmljavinom  : Light snow and small hail/snow pallets with thunderstorm :\n   : Lagan snijeg i snježni kristali             : Light snow and snow grains                         :\n   : Lagan snježni kristali                      : Light snow grains                                  :\n   : Lagan snježni pljusak                       : Light snow shower                                  :\n   : Lagan snijeg s grmljavinom                  : Light snow with thunderstorm                       :\n   : Lagan grmljavina                            : Light thunderstorm                                 :\n   : Lagan nepoznate oborine                     : Light unknown precipitation                        :\n   : Lagano razvijeni vrtlozi prašine ili pijeska  : Light well-developed dust/sand whirls              :\n   : Nisko vijanje pijeska                       : Low drifting sand                                  :\n   : Nisko vijanje široko rasprostranjene prašine  : Low drifting widespread dust                       :\n   : Magla s grmljavinom                         : Mist with thunderstorm                             :\n   : Umjerena do jaka kiša s grmljavinom         : Moderate or heavy rain in area with thunder        :\n   : Umjeren do jak snijeg s grmljavinom         : Moderate or heavy snow in area with thunder        :\n   : Djelomična magla                            : Partial fog                                        :\n   : Polja magle u blizini                       : Patches of fog in vicinity                         :\n   : Povremeno smrzavajuća kišica u blizini      : Patchy freezing drizzle nearby                     :\n   : Povremeno lagana kiša s grmljavinom u području  : Patchy light rain in area with thunder             :\n   : Povremeno lagan snijeg s grmljavinom u području  : Patchy light snow in area with thunder             :\n   : Povremeno kiša u blizini                    : Patchy rain nearby                                 :\n   : Povremeno susnježica u blizini              : Patchy sleet nearby                                :\n   : Povremeno snijeg u blizini                  : Patchy snow nearby                                 :\n   : Kiša i pljusak tuče                         : Rain and hail shower                               :\n   : Kiša i tuča s grmljavinom                   : Rain and hail with thunderstorm                    :\n   : Kiša i magla                                : Rain and mist                                      :\n   : Kiša i magla s grmljavinom                  : Rain and mist with thunderstorm                    :\n   : Kiša i pljusak sitne tuče/snježnih kuglica  : Rain and small hail/snow pallets shower            :\n   : Kiša i sitna tuča/snježne kuglice s grmljavinom  : Rain and small hail/snow pallets with thunderstorm :\n   : Kiša i snijeg                               : Rain and snow                                      :\n   : Kiša i snijeg te pljusak sitne tuče/snježnih kuglica  : Rain and snow and small hail/snow pallets shower   :\n   : Kiša i snježni kristali                     : Rain and snow grains                               :\n   : Kiša i snježni pljusak                      : Rain and snow shower                               :\n   : Kiša i snijeg s grmljavinom                 : Rain and snow with thunderstorm                    :\n   : Kiša u blizini                              : Rain in vicinity                                   :\n   : Kišni pljusak u blizini                     : Rain shower in vicinity                            :\n   : Kiša s grmljavinom                          : Rain with thunderstorm                             :\n   : Pijesak                                     : Sand                                               :\n   : Pješčana oluja                              : Sandstorm                                          :\n   : Plitka magla                                : Shallow fog                                        :\n   : Plitka maglica                              : Shallow mist                                       :\n   : Pljusak                                     : Shower                                             :\n   : Pljusak u blizini                           : Shower in vicinity                                 :\n   : Sitna tuča/snježne kuglice                  : Small hail/snow pallets                            :\n   : Pljusak sitne tuče/snježnih kuglica         : Small hail/snow pallets shower                     :\n   : Sitna tuča/snježne kuglice s grmljavinom    : Small hail/snow pallets with thunderstorm          :\n   : Dim                                         : Smoke                                              :\n   : Snijeg i ledeni kristali                    : Snow and ice pallets                               :\n   : Snijeg i magla                              : Snow and mist                                      :\n   : Snijeg i lagan pljusak sitne tuče/snježnih kuglica  : Snow and small hail/snow pellets shower            :\n   : Snijeg i lagan pljusak sitne tuče/snježnih kuglica s grmljavinom  : Snow and small hail/snow pallets with thunderstorm :\n   : Snijeg i snježni kristali                   : Snow and snow grains                               :\n   : Snježni kristali                            : Snow grains                                        :\n   : Snježni pljusak                             : Snow shower                                        :\n   : Snijeg s grmljavinom                        : Snow with thunderstorm                             :\n   : Grmljavinske oluje                          : Squalls                                            :\n   : Grmljavina                                  : Thunderstorm                                       :\n   : Grmljavina u blizini                        : Thunderstorm in vicinity                           :\n   : Grmljavinske oluje u blizini                : Thundery outbreaks in nearby                       :\n   : Nepoznate oborine                           : Unknown precipitation                              :\n   : Pljusak s nepoznatim oborinama              : Unknown precipitation shower                       :\n   : Nepoznate oborine s grmljavinom             : Unknown precipitation with thunderstorm            :\n   : Vulkanski pepeo                             : Volcanic ash                                       :\n   : Vulkanski pepeo u blizini                   : Volcanic ash in vicinity                           :\n   : Dobro razvijeni vrtlozi prašine/pijeska u blizini  : Well-developed dust/sand whirls in vicinity        :\n   : Široko rasprostranjena prašina              : Widespread dust                                    :\n"
  },
  {
    "path": "share/translations/hu-help.txt",
    "content": "Használat:\n\n    $ curl wttr.in          # jelenlegi tartózkodási hely\n    $ curl wttr.in/muc      # időjárás a müncheni repülőtéren\n\nTámogatott pozíciómeghatározások:\n\n    /paris                  # város\n    /~Eiffel+tower          # bármilyen hely\n    /Москва                 # Unicode név bármilyen nyelven\n    /muc                    # repülőtér kód (3 betű)\n    /@stackoverflow.com     # domain név\n    /94107                  # körzetszám\n    /-78.46,106.79          # GPS koordináták\n\nSpeciális helyek:\n\n    /moon                   # holdfázis (a végére tehető ,+US vagy ,+France például)\n    /moon@2016-10-25        # holdfázis az adott dátumhoz (@2016-10-25)\n\nMértékegységek:\n\n    m                       # metrikus (SI) (használatban mindenhol az USA kivételével)\n    u                       # USA hagyományos (alapértelmezett az USA-ban)\n    M                       # szélsebesség m/s-ban\n\nMegjelenítési beállítások:\n\n    0                       # csak az aktuális időjárás\n    1                       # aktuális időjárás + 1 nap\n    2                       # aktuális időjárás + 2 nap\n    A                       # User-Agent figyelmen kívül hagyása, ANSI output kikényszerítése (terminálokban)\n    F                       # ne jeneítse meg a \"Kövesd\" sort\n    n                       # keskeny változat (csak nappal és éjszaka)\n    q                       # csendes verzió (\"Időjárás előrejelzés\" szöveg nélkül)\n    Q                       # szupercsendes verzió (\"Időjárás előrejelzés\" szöveg és hely nélkül)\n    T                       # terminál szekvenciák kikapcsolása (színek nélküli megjelenés)\n\nPNG beállítások:\n\n    /paris.png              # PNG kép készítése\n    p                       # keret a kép köré\n    t                       # 150-es \"átlátszóság\"\n    transparency=...        # \"átlátszóság\" 0 és 255 között (255 = egyáltalán nem átlátszó)\n\nA beállítások kombinálhatók:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # PNG módban az opciók egy aláhúzásjel után megadhatók\n    /Rome_0pq_lang=it.png   # a hosszú opcióneveket aláhúzásjelekkel kell elválasztani\n\nMegjelenítés különböző nyelveken:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nTámogatott nyelvek:\n\n    FULL_TRANSLATION (teljesen támogatott)\n    PARTIAL_TRANSLATION (folyamatban...)\n\nSpeciális URL-ek:\n\n    /:help                  # segítség (ez az oldal)\n    /:bash.function         # ajánlott bash függvény\n    /:translation           # információ a fordítókról\n\n"
  },
  {
    "path": "share/translations/hu.txt",
    "content": "113: Derült                              : Clear\n113: Napos                               : Sunny\n116: Közepesen felhős                    : Partly cloudy\n119: Felhős                              : Cloudy\n122: Borult                              : Overcast\n143: Pára                                : Mist\n176: Szórványos zápor                    : Patchy rain possible\n179: Szórványos havazás                  : Patchy snow possible\n182: Szórványos havas eső                : Patchy sleet possible\n185: Szórványos ónos szitálás            : Patchy freezing drizzle possible\n200: Viharos széllökések előfordulhatnak : Thundery outbreaks possible\n227: Hófúvás                             : Blowing snow\n230: Hóvihar                             : Blizzard\n248: Köd                                 : Fog\n260: Zúzmarás köd                        : Freezing fog\n263: Szórványos gyenge szitálás          : Patchy light drizzle\n266: Gyenge szitálás                     : Light drizzle\n281: Ónos szitálás                       : Freezing drizzle\n284: Erős ónos szitálás                  : Heavy freezing drizzle\n293: Szórványos gyenge eső               : Patchy light rain\n296: Gyenge eső                          : Light rain\n299: Időnként eső                        : Moderate rain at times\n302: Eső                                 : Moderate rain\n305: Időnként intenzív eső               : Heavy rain at times\n308: Intenzív eső                        : Heavy rain\n311: Gyenge ónos eső                     : Light freezing rain\n314: Ónos eső                            : Moderate or heavy freezing rain\n317: Gyenge havas eső                    : Light sleet\n320: Havas eső                           : Moderate or heavy sleet\n323: Szórványos hószállingózás           : Patchy light snow\n326: Hószállingózás                      : Light snow\n329: Szórványos havazás                  : Patchy moderate snow\n332: Havazás                             : Moderate snow\n335: Szórványos intenzív havazás         : Patchy heavy snow\n338: Intenzív havazás                    : Heavy snow\n350: Jégeső                              : Ice pellets\n353: Gyenge zápor                        : Light rain shower\n356: Zápor                               : Moderate or heavy rain shower\n359: Zuhogó záporeső                     : Torrential rain shower\n362: Gyenge havas záporeső               : Light sleet showers\n365: Havas záporeső                      : Moderate or heavy sleet showers\n368: Gyenge hózápor                      : Light snow showers\n371: Hózápor                             : Moderate or heavy snow showers\n386: Szórványos zivatar                  : Patchy light rain with thunder\n389: Zivatar                             : Moderate or heavy rain with thunder\n392: Szórványos hózivatar                : Patchy light snow with thunder\n395: Hózivatar                           : Moderate or heavy snow with thunder\n   : Hóvúvás                             : Low drifting snow\n   : Ködfoltok                           : Patches of fog\n   : Szitálás                            : Drizzle\n   : Gyenge szitálás                     : Light drizzle\n   : Havazás                             : Snow\n   : Eső                                 : Rain\n   : Gyenge eső                          : Light Rain\n   : Talajmenti köd                      : Shallow fog\n"
  },
  {
    "path": "share/translations/hy.txt",
    "content": "113: Պարզ                               : Clear                             : Ясно                         \n113: Արևոտ                              : Sunny                             : Солнечно\n116: Մասամբ ամպամած                     : Partly cloudy                     : Переменная облачность\n119: Ամպամած                            : Cloudy                            : Облачно              \n122: Ամպամած                            : Overcast                          : Пасмурно\n143: Խոնավ                              : Mist                              : Дымка\n176: Տեղ-տեղ անձրև                      : Patchy rain possible              : Местами дождь\n179: Տեղ-տեղ ձյուն                      : Patchy snow possible              : Местами снег\n182: Տեղ-տեղ ձյունախառն անձրև           : Patchy sleet possible             : Местами дождь со снегом\n185: Տեղ-տեղ սառեցնող մրրիկ             : Patchy freezing drizzle possible  : Местами замерзающая морось\n200: Ամպրոպ                             : Thundery outbreaks possible       : Местами грозы              \n227: Ձնաբուք                            : Blowing snow                      : Поземок\n230: Ձնաբուք                            : Blizzard                          : Метель\n248: Մառախուղ                           : Fog                               : Туман\n260: Սառեցնող մառախուղ                  : Freezing fog                      : Переохлажденный туман\n263: Տեղ-տեղ թույլ մրրիկ                : Patchy light drizzle              : Местами слабая морось\n266: Թույլ մրրիկ                        : Light drizzle                     : Слабая морось\n281: Սառեցնող մրրիկ                     : Freezing drizzle                  : Замерзающая морось\n284: ՈՒժեղ սառեցնող մրրիկ               : Heavy freezing drizzle            : Сильная замерзающая морось\n293: Տեղ-տեղ թույլ անձրև                : Patchy light rain                 : Местами небольшой дождь\n296: Թույլ անձրև                        : Light rain                        : Небольшой дождь\n299: Չափավոր անձրև երբեմն               : Moderate rain at times            : Временами умеренный дождь\n302: Չափավոր անձրև                      : Moderate rain                     : Умеренный дождь\n305: Ուժեղ անձրև երբեմն                 : Heavy rain at times               : Временами сильный дождь\n308: Ուժեղ անձրև                        : Heavy rain                        : Сильный дождь\n311: Թույլ սառեցնող անձրև               : Light freezing rain               : Слабый переохлажденный дождь\n314: Չափավոր կամ ուժեղ սառեցնող անձրև   : Moderate or heavy freezing rain   : Умеренный или сильный переохлажденный дождь\n317: Թույլ մանրակարկուտ                 : Light sleet                       : Небольшой дождь со снегом\n320: Չափավոր կամ ուժեղ մանրակարկուտ     : Moderate or heavy sleet           : Умеренный или сильный дождь со снегом\n323: Տեղ-տեղ թույլ ձյուն                : Patchy light snow                 : Местами небольшой снег\n326: Թույլ ձյուն                        : Light snow                        : Небольшой снег\n329: Տեղ-տեղ չափավոր ձյուն              : Patchy moderate snow              : Местами умеренный снег\n332: Չափավոր ձյուն                      : Moderate snow                     : Умеренный снег\n335: Տեղ-տեղ ուժեղ ձյուն                : Patchy heavy snow                 : Местами сильный снег\n338: ՈՒժեղ ձյուն                        : Heavy snow                        : Сильный снег\n350: Սառցաբեկորներ                      : Ice pellets                       : Ледяной дождь\n353: Թույլ տեղատարափ անձրև              : Light rain shower                 : Небольшой ливневый дождь\n356: Չափավոր կամ ուժեղ տեղատարափ անձրև  : Moderate or heavy rain shower     : Умеренный или сильный ливневый дождь\n359: Ուժեղ տեղատարափ անձրև              : Torrential rain shower            : Очень сильный ливень\n362: Թույլ ձյունախառն անձրև             : Light sleet showers               : Небольшой ливневый дождь со снегом\n365: Չափավոր կամ ուժեղ ձյունախառն անձրև ։ Moderate or heavy sleet showers   : Небольшой снег\n368: Թույլ ձյունախառն անձրև             : Light snow showers                : Небольшой ливневый дождь со снегом\n371: Չափավոր կամ ուժեղ ձյան տարափ       : Moderate or heavy snow showers    : Умеренный или сильный снежный ливень\n386: Տեղ-տեղ թույլ անձրև և ամպրոպ       : Patchy light rain with thunder      : Местами небольшой дождь с грозой\n389: Չափավոր կամ ուժեղ անձրև և ամպրոպ   : Moderate or heavy rain with thunder : Умеренный или сильный дождь с грозой\n392: Տեղ-տեղ թույլ ձյուն և ամպրոպ       : Patchy light snow with thunder      : Местами небольшой снег с грозой\n395: Ուժեղ ձյուն և ամպրոպ               : Moderate or heavy snow with thunder : Умеренный или сильный снег с грозой \n"
  },
  {
    "path": "share/translations/ia-help.txt",
    "content": "Instructiones:\n\n    $ curl wttr.in          # le tempore a vostre location actual\n    $ curl wttr.in/muc      # le tempore del aeroporto de Múnich\n\nTypos de location appoiava:\n\n    /paris                  # le nomine de un citate\n    /~Eiffel+tower          # le nomine de qualque sito famose\n    /Москва                 # le nomine Unicode de qualque sito in qualque lingua\n    /muc                    # le codice de un aeroporto (3 litteras)\n    /@stackoverflow.com     # le nomine de un dominio internet\n    /94107                  # un codice de area\n    /-78.46,106.79          # coordinatas de GPS\n\nSitos speciales:\n\n    /moon                   # le phase del luna (adjunge ,+US o ,+France por iste paises)\n    /moon@2016-10-25        # le phase del luna in un data specific (@2016-10-25)\n\nUnitates:\n\n    ?m                      # metric (SI) (le standardo in tote le sitos extra in EEUU)\n    ?u                      # Systema Uniforme de Classification del Solo o USCS (le standardo in EEUU)\n    ?M                      # demonstrar le velocitate del vento in m/s\n\nOptiones visual:\n\n    ?0                      # solmente le tempore actual\n    ?1                      # le tempore actual + le prevision de 1 die\n    ?2                      # le tempore actual + le prevision de 2 die\n    ?n                      # version curte (solmente le die et le nocte)\n    ?q                      # version silentiose (sin le texto de \"Le tempore a\")\n    ?Q                      # version supersilentiose (nec \"Le tempore a\" nec le nomine del citate)\n    ?T                      # desactiva le sequentias de terminal (sin colores)\n\nOptiones de PNG:\n\n    /paris.png              # genera un imagine PNG\n    ?p                      # adde un frontiera circa le imagine\n    ?t                      # transparentia 150\n    transparency=...        # transparentia de 0 a 255 (255 = sin transparentia)\n\nLe optiones pote usar insimul:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # in PNG le optiones sera post que le character _\n    /Rome_0pq_lang=it.png   # un grande secuentia de optiones pote seperate per le character _\n\nLocation:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nLinguas appoiava:\n\n    FULL_TRANSLATION (appoiava)\n    PARTIAL_TRANSLATION (in progresso)\n\nURLs speciales:\n\n    /:help                  # monstra isto pagina\n    /:bash.function         # proponera un function wttr() in bash\n    /:translation           # monstra aviso super le traductores\n"
  },
  {
    "path": "share/translations/ia.txt",
    "content": "113: Clar                               : Clear\n113: Allegre                            : Sunny\n116: Pauc Nubilose                     : Partly cloudy\n119: Nubilose                           : Cloudy\n122: Gris                               : Overcast\n143: Nebula                             : Mist\n176: Pauc pluvia possibile              : Patchy rain possible\n179: Pauc nive possibile                : Patchy snow possible\n182: Pauc nive miscite con pluvia       : Patchy sleet possible\n185: Pauc nive glacial con pluvia       : Patchy freezing drizzle possible\n200: Rar tonitro possibile              : Thundery outbreaks possible\n227: Ventose nive                       : Blowing snow\n230: Tempesta de nive                   : Blizzard\n248: Bruma                              : Fog\n260: Bruma glacial                      : Freezing fog\n263: Pauc pluvia                        : Patchy light drizzle\n266: Pluveva                            : Light drizzle\n281: Pluveva glacial                    : Freezing drizzle\n284: Multe pluvia glacial               : Heavy freezing drizzle\n293: Pauc pluvia                        : Patchy light rain\n296: Pluveva                            : Light rain\n299: Pluvia moderate a vices            : Moderate rain at times\n302: Pluvia moderate                    : Moderate rain\n305: Multe pluvia a vices               : Heavy rain at times\n308: Multe pluvia                       : Heavy rain\n311: Pauc pluvia glacial                : Light freezing rain\n314: Multe o moderate pluvia glacial    : Moderate or heavy freezing rain\n317: Pauc nive miscite con pluvia       : Light sleet\n320: Multe o moderate nive miscite      : Moderate or heavy sleet\n323: Breve nive                         : Patchy light snow\n326: Pauc nive                          : Light snow\n329: Breve nive moderate                : Patchy moderate snow\n332: Nive moderate                      : Moderate snow\n335: Multe nive a veces                 : Patchy heavy snow\n338: Multe nive                         : Heavy snow\n350: Bolletas de glacie                 : Ice pellets\n353: Pauc pluvia                        : Light rain shower\n356: Multe o moderate pluvia            : Moderate or heavy rain shower\n359: Tempesta de pluvia                 : Torrential rain shower\n362: Pauc pluvia con glacie             : Light sleet showers\n365: Multe o moderate pluvia con glacie : Moderate or heavy sleet showers\n368: Pauc nive con pluvia               : Light snow showers\n371: Multe o moderate nive con pluvia   : Moderate or heavy snow showers\n386: Pauc pluvia con tonitro            : Patchy light rain with thunder\n389: Moderate pluvia con tonitro        : Moderate or heavy rain with thunder\n392: Pauc nive con tonitro              : Patchy light snow with thunder\n395: Moderate o multe nive con tonitro  : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/id-help.txt",
    "content": "Cara penggunaan:\n\n    $ curl wttr.in          # lokasi saat ini\n    $ curl wttr.in/muc      # cuaca di bandara Munich\n\nDukungan tipe lokasi:\n\n    /paris                  # nama kota\n    /~Eiffel+tower          # sembarang lokasi\n    /Москва                 # nama Unicode dari semabarang lokasi dalam sembarang bahasa\n    /muc                    # kode bandara (3 huruf)\n    /@stackoverflow.com     # nama domain\n    /94107                  # kode area\n    /-78.46,106.79          # koordinat GPS\n\nLokasi khusus:\n\n    /moon                   # bentuk Bulan (tambahkan ,+US atau ,+France untuk kota-kota tersebut)\n    /moon@2016-10-25        # bentuk Bulan untuk tanggal (@2016-10-25)\n\nSatuan:\n\n    ?m                      # metrik (SI) (digunakan sebagai standar di semua tempat kecuali US)\n    ?u                      # USCS (digunakan sebagai standar di US)\n    ?M                      # tampilkan kecepatan angin dalam m/s\n\nOpsi tampilan:\n\n    ?0                      # hanya cuaca saat ini\n    ?1                      # cuaca saat ini + 1 hari\n    ?2                      # cuaca saat ini + 2 hari\n    ?n                      # versi sempit (hanya siang dan malam)\n    ?q                      # versi diam (tanpa teks \"Laporan cuaca\")\n    ?Q                      # versi sangat diam (tanpa teks \"Laporan cuaca\", tanpa nama kota)\n    ?T                      # ganti urutan terminal (tanpa warna)\n\nOpsi PNG:\n\n    /paris.png              # hasilkan suatu berkas PNG\n    ?p                      # tambahkan bingkai di sekeliling hasil\n    ?t                      # transparansi 150\n    transparency=...        # transparansi dari 0 sampai 255 (255 = tidak transparan)\n\nOpsi dapat digabung:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # dalam PNG mode berkas ditentukan sesudah _\n    /Rome_0pq_lang=it.png   # opsi panjang dipisahkan dengan underscore\n\nLokalisasi:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nDukungan bahasa:\n\n    FULL_TRANSLATION (supported)\n    PARTIAL_TRANSLATION (in progress)\n\nURL khusus:\n\n    /:help                  # tampilkan halaman ini\n    /:bash.function         # tampilkan fungsi bash yang direkomendasikan wttr()\n    /:translation           # tampilkan informasi tentang translator\n\n"
  },
  {
    "path": "share/translations/id.txt",
    "content": "113: Langit bersih                          : Clear \n113: Cerah                                  : Sunny\n116: Sebagian berawan                       : Partly cloudy\n119: Berawan                                : Cloudy\n122: Mendung                                : Overcast\n143: Berkabut                               : Mist\n176: Mungkin hujan tidak merata             : Patchy rain possible\n179: Mungkin bersalju tidak merata          : Patchy snow possible\n182: Mungkin hujan es tidak merata          : Patchy sleet possible\n185: Mungkin gerimis beku tidak merata      : Patchy freezing drizzle possible\n200: Mungkin banyak petir                   : Thundery outbreaks possible\n227: Hembusan salju                         : Blowing snow\n230: Badai salju                            : Blizzard\n248: Kabut                                  : Fog\n260: Kabut beku                             : Freezing fog\n263: Gerimis ringan tidak merata            : Patchy light drizzle\n266: Gerimis ringan                         : Light drizzle\n281: Gerimis beku                           : Freezing drizzle\n284: Gerimis beku rapat                     : Heavy freezing drizzle\n293: Hujan ringan tidak merata              : Patchy light rain\n296: Hujan ringan                           : Light rain\n299: Hujan di beberapa waktu                : Moderate rain at times\n302: Hujan                                  : Moderate rain\n305: Hujan lebat di beberapa waktu          : Heavy rain at times\n308: Hujan lebat                            : Heavy rain\n311: Hujan beku ringan                      : Light freezing rain\n314: Hujan beku                             : Moderate or heavy freezing rain\n317: Hujan es ringan                        : Light sleet\n320: Hujan es                               : Moderate or heavy sleet\n323: Salju ringan tidak merata              : Patchy light snow\n326: Salju ringan                           : Light snow\n329: Salju tidak merata                     : Patchy moderate snow\n332: Salju                                  : Moderate snow\n335: Salju lebat tidak merata               : Patchy heavy snow\n338: Salju lebat                            : Heavy snow\n350: Bongkahan es                           : Ice pellets\n353: Hujan ringan                           : Light rain shower\n356: Hujan lebat                            : Moderate or heavy rain shower\n359: Hujan sangat lebat                     : Torrential rain shower\n362: Hujan es ringan                        : Light sleet showers\n365: Hujan es                               : Moderate or heavy sleet showers\n368: Hujan salju ringan                     : Light snow showers\n371: Hujan salju                            : Moderate or heavy snow showers\n386: Hujan ringan dengan petir tidak merata : Patchy light rain with thunder\n389: Hujan dengan petir                     : Moderate or heavy rain with thunder\n392: Salju ringan dengan petir tidak merata : Patchy light snow with thunder\n395: Salju dengan petir                     : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/is.txt",
    "content": "113 : Heiðskýrt                                   : Clear\n113 : Sól                                         : Sunny\n116 : Léttskýjað                                  : Partly cloudy\n119 : Skýjað                                      : Cloudy\n122 : Alskýjað                                    : Overcast\n143 : Mistur                                      : Mist\n176 : Hætta á rigningu á köflum                   : Patchy rain possible\n179 : Hætta á snjókomu á köflum                   : Patchy snow possible\n182 : Hætta á slyddu á köflum                     : Patchy sleet possible\n185 : Hætta á frostúða á köflum                   : Patchy freezing drizzle possible\n200 : Hætta á þrumuveðri                          : Thundery outbreaks possible\n227 : Skafrenningur                               : Blowing snow\n230 : Snjóbylur                                   : Blizzard\n248 : Þoka                                        : Fog\n260 : Frostþoka                                   : Freezing fog\n263 : Lítilsháttar súld á köflum                  : Patchy light drizzle\n266 : Lítilsháttar súld                           : Light drizzle\n281 : Frostúði                                    : Freezing drizzle\n284 : Mikill frostúði                             : Heavy freezing drizzle\n293 : Lítilsháttar rigning á köflum               : Patchy light rain\n296 : Lítilsháttar rigning                        : Light rain\n299 : Dálítil rigning á köflum                    : Moderate rain at times\n302 : Dálítil rigning                             : Moderate rain\n305 : Mikil rigning á köflum                      : Heavy rain at times\n308 : Mikil rigning                               : Heavy rain\n311 : Lítilsháttar frostrigning                   : Light freezing rain\n314 : Dálítið eða mikið frostregn                 : Moderate or heavy freezing rain\n317 : Lítilsháttar slydda                         : Light sleet\n320 : Dálítil eða mikil slydda                    : Moderate or heavy sleet\n323 : Lítilsháttar snjókoma á köflum              : Patchy light snow\n326 : Lítilsháttar snjókoma                       : Light snow\n329 : Dálítil snjókoma á köflum                   : Patchy moderate snow\n332 : Dálítil snjókoma                            : Moderate snow\n335 : Mikill snjókoma á köflum                    : Patchy heavy snow\n338 : Mikill snjókoma                             : Heavy snow\n350 : Haglél                                      : Ice pellets\n353 : Skúrir                                      : Light rain shower\n356 : Dálitlir eða mikilir Skúrir                 : Moderate or heavy rain shower\n359 : Úrhellis rigning                            : Torrential rain shower\n362 : Slydduél                                    : Light sleet showers\n365 : Dálítil eða mikil slydduél                  : Moderate or heavy sleet showers\n368 : Lítilshátta Snjóél                          : Light snow showers\n371 : Dálítil eða mikil snjóél                    : Moderate or heavy snow showers\n386 : Lítilsháttar skúrir með þrumuveðri á köflum : Patchy light rain with thunder\n389 : Dálítil eða mikil rigning með þrumuveðri    : Moderate or heavy rain with thunder\n392 : Lítilsháttar él með þrumuveðri á köflum     : Patchy light snow with thunder\n395 : Dálítil eða mikill snjórkoma með þrumuveðri : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/it-help.txt",
    "content": "Istruzioni:\n\n\t$ curl wttr.in\t\t\t\t# Il tempo nella tua posizione attuale\n\t$ curl wttr.in/muc\t\t\t# Meteo all'aeroporto di Monaco\n\nTipi di località supportate:\n\n\t/paris\t\t\t\t\t# Il nome di una città\n\t/~Torre+Eiffel\t\t\t\t# Il nome di qualsiasi sito famoso\n\t/Москва\t\t\t\t\t# Il nome Unicode di qualsiasi sito in qualsiasi lingua\n\t/muc\t\t\t\t\t# Il codice di un aeroporto (3 lettere)\n\t/@stackoverflow.com\t\t\t# Il nome di un dominio web\n\t/94107\t\t\t\t\t# Un prefisso\n\t/-78.46.106.79\t\t\t\t# Coordinate GPS\n\nSiti speciali:\n\n\t/moon\t\t\t\t\t# La fase lunare (aggiungere ,+US o ,+France per questi paesi)\n\t/moon@2016-10-25\t\t\t# La fase lunare in una data specifica (@2016-10-25)\n\nUnità:\n\n\t?m\t\t\t\t\t# Metrico (SI) (lo standard ovunque tranne che negli Stati Uniti)\n\t?u\t\t\t\t\t# Sistema unificato di classificazione del suolo o USCS (lo standard negli Stati Uniti)\n\t?M\t\t\t\t\t# Mostra la velocità del vento in m/s\n\nOpzioni di visualizzazione:\n\n\t?0\t\t\t\t\t# Solo meteo attuale\n\t?1\t\t\t\t\t# Meteo attuale + previsioni per il giorno successivo\n\t?2\t\t\t\t\t# Il tempo attuale + le previsioni per i prossimi due giorni\n\t?A\t\t\t\t\t# ignora l'agente utente e forza il formato di output ANSI (terminale)\n\t?F\t\t\t\t\t# Non mostra la riga \"Segui\".\n\t?n\t\t\t\t\t# Versione breve (solo giorno e notte)\n\t?q\t\t\t\t\t# Versione silenziosa (senza il testo \"Previsioni meteo:\")\n\t?Q\t\t\t\t\t# Versione super silenziosa (né \"Previsioni meteo:\" né nome della città)\n\t?T\t\t\t\t\t# Modalità testuale (nessun colore)\n\nOpzioni utili per il formato PNG:\n\n\t/paris.png\t\t\t\t# Genera un'immagine PNG\n\t?p\t\t\t\t\t# Aggiunge un bordo attorno all'immagine\n\t?t\t\t\t\t\t# Trasparenza = 150\n\ttransparency=150\t\t\t# Trasparenza da 0 a 255 (255 = nessuna trasparenza)\n\nLe opzioni possono essere utilizzate insieme:\n\n\t/Paris?0pq\n\t/Paris?0pq&lang=fr\n\t/Paris_0pq.png\t\t\t\t# In modalità PNG le opzioni sono specificate dopo il carattere _ (trattino basso) anziché ?\n\t/Rome_0pq_lang=it.png\t\t\t# In modalità PNG usare opzioni brevi e lunghe, ma separate con  _ (underscore) anziché ? e &\n\nPosizione:\n\n\t$ curl fr.wttr.in/Paris\n\t$ curl wttr.in/paris?lang=fr\n\t$ curl -H \"Accetta lingua: fr\" wttr.in/paris\n\nLingue supportate:\n\n\tFULL_TRANSLATION (supportato)\n\tPARTIAL_TRANSLATION (in corso)\n\nURL speciali:\n\n\t/:aiuto\t\t\t\t\t# Mostra questa pagina\n\t/:bash.function\t\t\t\t# Visualizza una funzione wttr() suggerita in bash\n\t/:translation\t\t\t\t# Visualizza le informazioni sui traduttori\n"
  },
  {
    "path": "share/translations/it.txt",
    "content": ": Pioggia intensa e grandine con temporali                             : Heavy rain and hail with thunderstorm\n: Pioggia intensa con temporale                                        : Heavy rain with thunderstorm\n: Pioggia leggera e grandine con temporali                             : Light rain and hail with thunderstorm\n: Pioggia leggera e nevicata                                           : Light rain and snow shower\n: Pioggia leggera con temporale                                        : Light rain with thunderstorm\n: Leggera nevicata                                                     : Light snow shower\n: Nebbia parziale                                                      : Partial fog\n: Pioggia e grandine con temporali                                     : Rain and hail with thunderstorm\n: Pioggia con temporale                                                : Rain with thunderstorm\n: Nebbia leggera                                                       : Shallow fog\n: Foschia                                                              : Smoke\n: Burrasche                                                            : Squalls\n: Temporali nelle vicinanze                                            : Thunderstorm in vicinity\n: Neve                                                                 : Snow\n: Pioggia                                                              : Rain\n: Pioggia leggera, Rovesci di pioggia                                  : Light Rain, Rain Shower\n: Rovesci di pioggia                                                   : Rain Shower\n: Banchi di nebbia                                                     : Patches of fog\n: Pioggerellina                                                        : Drizzle\n: Pioggerellina leggera                                                : Light drizzle\n: Bassi cumuli di neve                                                 : Low drifting snow\n: Pioggia leggera e neve                                               : Light rain and snow\n: Rovesci nelle vicinanze                                              : Shower in vicinity\n: Pioggia con temporale                                                : Rain with thunderstorm\n: Rovesci di pioggia e neve                                            : Rain and snow shower\n: Temporale                                                            : Thunderstorm\n: Pioggerellina e pioggia                                              : Drizzle and rain\n: Grandine con temporale                                               : Hail with thunderstorm\n: Foschia                                                              : Haze\n: Pioggerellina leggera e pioggia                                      : Light drizzle and rain\n: Pioggia leggera e piccoli cumuli di grandine/neve con temporale      : Light rain and small hail/snow pallets with thunderstorm\n: Pioggia a tratti nelle vicinanze                                     : Patchy rain nearby\n113: Sereno                                                            :  Clear\n113: Soleggiato                                                        :  Sunny\n116: Parzialmente nuvoloso                                             :  Partly cloudy\n119: Nuvoloso                                                          :  Cloudy\n122: Coperto                                                           :  Overcast\n143: Nebbia                                                            :  Mist\n176: Possibile pioggia a zone                                          :  Patchy rain possible\n179: Possibili nevicate a zone                                         :  Patchy snow possible\n182: Possibile nevischio a zone                                        :  Patchy sleet possible\n185: Possibile pioviggine ghiacciata                                   :  Patchy freezing drizzle possible\n200: Possibili violenti temporali improvvisi                           :  Thundery outbreaks possible\n227: Neve a raffiche                                                   :  Blowing snow\n230: Bufera di neve                                                    :  Blizzard\n248: Nebbia                                                            :  Fog\n260: Nebbia gelata                                                     :  Freezing fog\n263: Pioggerellina leggera a zone                                      :  Patchy light drizzle\n266: Pioggerellina leggera                                             :  Light drizzle\n281: Pioggia gelata                                                    :  Freezing drizzle\n284: Pioviggine ghiacciata                                             :  Heavy freezing drizzle\n293: Pioggia leggera a zone                                            :  Patchy light rain\n296: Pioggia leggera                                                   :  Light rain\n299: Pioggia moderata irregolare                                       :  Moderate rain at times\n302: Pioggia moderata                                                  :  Moderate rain\n305: Pioggia forte irregolare                                          :  Heavy rain at times\n308: Pioggia forte                                                     :  Heavy rain\n311: Pioggia leggera ghiacciata                                        :  Light freezing rain\n314: Pioggia gelata moderata o pesante                                 :  Moderate or heavy freezing rain\n317: Nevischio leggero                                                 :  Light sleet\n320: Nevischio moderato o pesante                                      :  Moderate or heavy sleet\n323: Neve leggera a zone chiare                                        :  Patchy light snow\n326: Neve leggera                                                      :  Light snow\n329: Neve moderata a zone                                              :  Patchy moderate snow\n332: Neve moderata                                                     :  Moderate snow\n335: Abbondante nevicata a zone                                        :  Patchy heavy snow\n338: Abbondante nevicata                                               :  Heavy snow\n350: Grandine                                                          :  Ice pellets\n353: Pioggia leggera a scrosci                                         :  Light rain shower\n356: Pioggia moderata o intensa a scrosci                              :  Moderate or heavy rain shower\n359: Piogge torrenziali a scrosci                                      :  Torrential rain shower\n362: Nevischio leggero a colpi                                         :  Light sleet showers\n365: Rovesci di pioggia moderati o pesanti                             :  Moderate or heavy sleet showers\n368: Deboli rovesci di neve                                            :  Light snow showers\n371: Rovesci di neve moderati o abbondanti                             :  Moderate or heavy snow showers\n386: Pioggia leggera con tuoni e fulmini                               :  Patchy light rain with thunder\n389: Pioggia moderata o intensa con tuoni e fulmini                    :  Moderate or heavy rain with thunder\n392: Neve leggera a zone con tuoni                                     :  Patchy light snow with thunder\n395: Neve moderata o pesante con tuoni                                 :  Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/ja.txt",
    "content": "113: 快晴                               : Clear\n113: 晴れ                               : Sunny\n116: 所により曇り                       : Partly cloudy\n119: 曇り                               : Cloudy\n122: 曇り                               : Overcast\n143: 靄                                 : Mist\n176: 所により雨                         : Patchy rain possible\n179: 所により雪                         : Patchy snow possible\n182: 所により凍雨                       : Patchy sleet possible\n185: 所により着氷性の霧雨               : Patchy freezing drizzle possible\n200: 雷雨の発生                         : Thundery outbreaks possible\n227: 吹雪                               : Blowing snow\n230: 猛吹雪                             : Blizzard\n248: 霧                                 : Fog\n260: 着氷性の霧                         : Freezing fog\n263: 所により弱い霧雨                   : Patchy light drizzle\n266: 弱い霧雨                           : Light drizzle\n281: 着氷性の霧雨                       : Freezing drizzle\n284: 強い着氷性の霧雨                   : Heavy freezing drizzle\n293: 所により弱い雨                     : Patchy light rain\n296: 弱い雨                             : Light rain\n299: 時々雨                             : Moderate rain at times\n302: 雨                                 : Moderate rain\n305: 時々強い雨                         : Heavy rain at times\n308: 強い雨                             : Heavy rain\n311: 弱い着氷性の雨                     : Light freezing rain\n314: 着氷性の雨または強い着氷性の雨     : Moderate or heavy freezing rain\n317: 弱い凍雨                           : Light sleet\n320: 凍雨または強い凍雨                 : Moderate or heavy sleet\n323: 所により弱い雪                     : Patchy light snow\n326: 弱い雪                             : Light snow\n329: 所により雪                         : Patchy moderate snow\n332: 雪                                 : Moderate snow\n335: 所により強い雪                     : Patchy heavy snow\n338: 強い雪                             : Heavy snow\n350: 凍雨                               : Ice pellets\n353: 弱い驟雨                           : Light rain shower\n356: 驟雨または強い驟雨                 : Moderate or heavy rain shower\n359: 激しい驟雨                         : Torrential rain shower\n362: 弱い凍雨                           : Light sleet showers\n365: 凍雨または強い凍雨                 : Moderate or heavy sleet showers\n368: 弱い驟雪                           : Light snow showers\n368: 弱い雨と驟雪と靄                   : Light Rain And Snow Shower, Mist\n371: 驟雪または強い驟雪                 : Moderate or heavy snow showers\n386: 所により雷を伴う弱い雨             : Patchy light rain with thunder\n389: 雷を伴う雨または強い雨             : Moderate or heavy rain with thunder\n392: 所により雷を伴う弱い雪             : Patchy light snow with thunder\n395: 雷を伴う雪または強い雪             : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/kk-help.txt",
    "content": "Использование:\n\n    $ curl wttr.in          # текущее местоположение\n    $ curl wttr.in/svo      # погода в аэропорту Шереметьево (код ICAO: SVO)\n\nПоддерживаемые типы местоположений:\n\n    /paris                  # город\n    /~Eiffel+tower          # любое местоположение\n    /Москва                 # юникодное имя любого местоположения на любом языке\n    /muc                    # код аэропорта ICAO (3 буквы)\n    /@stackoverflow.com     # доменное имя\n    /94107                  # почтовый индекс (только для США)\n    /-78.46,106.79          # GPS-координаты\n\nСпециальные условные местоположения:\n\n    /moon                   # Фаза Луны (добавьте ,+US или ,+France для города Moon в США/Франции)\n    /moon@2016-10-25        # Фаза Луны для указанной даты (@2016-10-25)\n\nЕдиницы измерений:\n\n    ?m                      # метрические (СИ) (используются везде кроме США)\n    ?u                      # USCS (используются в США)\n    ?M                      # показывать скорость ветра в м/с\n\nОпции отображения:\n\n    ?0                      # только текущая погода\n    ?1                      # погода сегодня + 1 день\n    ?2                      # погода сегодня + 2 дня\n    ?n                      # узкая версия (только день и ночь)\n    ?q                      # тихая версия (без текста \"Прогноз погоды\")\n    ?Q                      # сверхтихая версия (без \"Прогноз погоды\", нет названия города)\n    ?T                      # отключить терминальные последовательности (без цветов)\n\nPNG-опции:\n\n    /paris.png              # сгенерировать PNG-файл\n    ?p                      # добавить рамочку вокруг\n    ?t                      # transparency=150 (прозрачность 150)\n    transparency=...        # прозрачность от 0 до 255 (255 = не прозрачный)\n\nОпции можно комбинировать:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # в PNG-запросах опции указываются после _\n    /Rome_0pq_lang=it.png   # длинные опции разделяются знаком подчёркивания _\n\nЛокализация:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nПоддерживаемые языки:\n\n    FULL_TRANSLATION (поддерживаются)\n    PARTIAL_TRANSLATION (в процессе)\n\nСпециальные страницы:\n\n    /:help                  # показать эту страницу\n    /:bash.function         # показать рекомендованную функцию wttr()\n    /:translation           # показать список переводчиков wttr.in\n\n"
  },
  {
    "path": "share/translations/kk.txt",
    "content": "113: Ашық                               : Clear                             : Ясно                         \n113: Шуақ күн                           : Sunny                             : Солнечно\n116: Көшпелі бұлт                       : Partly cloudy                     : Переменная облачность\n119: Күн бұлтты                         : Cloudy                            : Облачно              \n122: Бұлыңғыр күн                       : Overcast                          : Пасмурно\n143: Мұнар                              : Mist                              : Дымка\n176: Кей жерлерде жаңбыр жауады         : Patchy rain possible              : Местами дождь\n179: Кей жерлерде кар жауады            : Patchy snow possible              : Местами снег\n182: Кей жерлерде қар және жауын аралас : Patchy sleet possible             : Местами дождь со снегом\n185: Кей жерлерде үсік сіркіреме        : Patchy freezing drizzle possible  : Местами замерзающая морось\n200: Кей жерлерде найзағай              : Thundery outbreaks possible       : Местами грозы              \n227: Жаяу бұрқасын                      : Blowing snow                      : Поземок\n230: Бұрқасын                           : Blizzard                          : Метель\n248: Тұман                              : Fog                               : Туман\n260: Аса суықтау тұман                  : Freezing fog                      : Переохлажденный туман\n263: Кей жерлерде әлсіз аяз             : Patchy light drizzle              : Местами слабая морось\n266: Әлсіз аяз                          : Light drizzle                     : Слабая морось\n281: Қақаған аяз                        : Freezing drizzle                  : Замерзающая морось\n284: Қатты қақаған аяз                  : Heavy freezing drizzle            : Сильная замерзающая морось\n293: Кей жерлерде аз ғана жаңбыр        : Patchy light rain                 : Местами небольшой дождь\n296: Аздаған жаңбыр                     : Light rain                        : Небольшой дождь\n299: Орташа жауын кезеңдері             : Moderate rain at times            : Временами умеренный дождь\n302: Орташа жауын                       : Moderate rain                     : Умеренный дождь\n305: Қатты жауын кезеңдері              : Heavy rain at times               : Временами сильный дождь\n308: Қатты жаңбыр                       : Heavy rain                        : Сильный дождь\n311: Әлсіз суықтау жаңбыр               : Light freezing rain               : Слабый переохлажденный дождь\n314: Орташа немесе қатты суықтау жаңбыр : Moderate or heavy freezing rain   : Умеренный или сильный переохлажденный дождь\n317: Аздаған жаңбыр аралас қар          : Light sleet                       : Небольшой дождь со снегом\n320: Орташа немесе қатты жаңбыр аралас қар : Moderate or heavy sleet           : Умеренный или сильный дождь со снегом\n323: Кей жерлерде аздаған қар           : Patchy light snow                 : Местами небольшой снег\n326: Аздаған қар                        : Light snow                        : Небольшой снег\n329: Кей жерлерде орташа жауған қар     : Patchy moderate snow              : Местами умеренный снег\n332: Орташа жауған қар                  : Moderate snow                     : Умеренный снег\n335: Кей жерлерде қатты жауған қар      : Patchy heavy snow                 : Местами сильный снег\n338: Қатты жауған қар                   : Heavy snow                        : Сильный снег\n350: Мұздай жаңбыр                      : Ice pellets                       : Ледяной дождь\n353: Аздаған нөсер жауын                : Light rain shower                 : Небольшой ливневый дождь\n356: Орташа немесе қатты нөсер жауын    : Moderate or heavy rain shower     : Умеренный или сильный ливневый дождь\n359: Өте қатты нөсер жауын              : Torrential rain shower            : Очень сильный ливень\n362: Аздаған нөсер жауын аралас қар     : Light sleet showers               : Небольшой ливневый дождь со снегом\n365: Аздаған қар                        : Moderate or heavy sleet showers   : Небольшой снег\n368: Аздаған нөсер жауын аралас қар     : Light snow showers                : Небольшой ливневый дождь со снегом\n371: Орташа немесе қатты қарлы нөсер       : Moderate or heavy snow showers    : Умеренный или сильный снежный ливень\n386: Кей жерлерде шамалы найзағайлы жауын  : Patchy light rain with thunder      : Местами небольшой дождь с грозой\n389: Орташа немесе қатты найзағайлы нөсер  : Moderate or heavy rain with thunder : Умеренный или сильный дождь с грозой\n392: Кей жерлерде шамалы қар және найзағай : Patchy light snow with thunder      : Местами небольшой снег с грозой\n395: Орташа немесе қатты қар және найзағай : Moderate or heavy snow with thunder : Умеренный или сильный снег с грозой \n"
  },
  {
    "path": "share/translations/lt-help.txt",
    "content": "Naudojimas:\n\n    $ curl wttr.in          # dabartinė vietovė\n    $ curl wttr.in/plq      # oras Palangos oro uoste\n\nPalaikomos vietovių rūšys:\n\n    /panemunė               # miesto pavadinimas\n    /~Eiffel+tower          # bet kuri vietovė (+ vietoj tarpų)\n    /Магілёў                # bet kurios vietovės pavadinimas Unikodu\n    /plq                    # oro uosto kodas (3 raidės)\n    /@stackoverflow.com     # domeno vardas\n    /94107                  # pašto kodas (tik JAV)\n    /-78.46,106.79          # GPS koordinatės\n\nMėnulio fazių informacija:\n\n    /moon                   # Mėnulio fazė (pridėkite ,+US arba +,France šio pavadinimo miestams)\n    /moon@2016-10-25        # Mėnulio fazė datai (@2016-10-25)\n\nMatai:\n\n    ?m                      # metrai (SI) (pagal nutylėjimą, naudojama visu išskyrus JAV)\n    ?u                      # USCS (pagal nutylėjimą, naudojama JAV)\n    ?M                      # vėjo greitis m/s\n\nRodymo parinktys:\n\n    ?0                      # tik faktiniai orai\n    ?1                      # faktiniai orai + šiandienos prognozė\n    ?2                      # faktiniai orai + šiandienos + rytojaus prognozės\n    A                       # ignoruoti naudotojo agentą (User-Agent) ir priverstinai formatuoti išvestį į ANSI (terminale)\n    F                       # nerodyti eilutės apie atnaujinimų sekimą\n    n                       # siaura versija (tik diena ir naktis)\n    q                       # tylesnė versija (be teksto „Orų prognozė“)\n    Q                       # labai tyli versija (be teksto „Orų prognozė“ ir be vietovės pavadinimo\n    T                       # išjungti terminalo sekas (be spalvų)\n\nPNG parinktys:\n\n    /panemunė.png           # sukurti PNG failą\n    p                       # apvesti išvestį rėmeliu\n    t                       # skaidrumas 150\n    transparency=...        # skaidrumas nuo 0 iki 255 (255 = neskaidrus)\n    background=...\t    # fono spalva RRGGBB forma, pvz., 00aaaa\n\nParinktis galima jungti:\n\n    /Panemunė?0pq\n    /Panemunė?0pq&lang=lt\n    /Panemunė_0pq.png          # PNG failo pobūdis nurodomas po _\n    /Rēzekne_0pq_lang=lv.png   # ilgavardės parinktys atskiriamos apatiniu brūkšniu\n\nKalbos:\n\n    $ curl lt.wttr.in/Panemunė\n    $ curl wttr.in/panemunė?lang=lt\n    $ curl -H \"Accept-Language: lt\" wttr.in/panemunė\n\nPalaikomos kalbos\n\n    FULL_TRANSLATION (išverstos)\n    PARTIAL_TRANSLATION (tebeverčiamos)\n\nYpatingi URL:\n\n    /:help                  # rodyti šį puslapį\n    /:bash.function         # rodyti rekomenduojamą bash funkciją wttr()\n    /:translation           # rodyti informaciją apie vertėjus\n"
  },
  {
    "path": "share/translations/lt.txt",
    "content": "113: Giedra                                  : Clear                               :\n113: Saulėta                                 : Sunny                               :\n116: Nepastoviai debesuota                   : Partly cloudy                       :\n119: Debesuota su pragiedruliais             : Cloudy                              :\n122: Debesuota                               : Overcast                            :\n143: Migla                                   : Mist                                :\n176: Galimas silpnas lietus                  : Patchy rain possible                :\n179: Galimas nedidelis snygis                : Patchy snow possible                :\n182: Galima nedidelė šlapdriba               : Patchy sleet possible               :\n185: Galima nedidelė lijundra                : Patchy freezing drizzle possible    :\n200: Spėjama perkūnija                       : Thundery outbreaks possible         :\n227: Pustymas                                : Blowing snow                        :\n230: Pūga                                    : Blizzard                            :\n248: Rūkas                                   : Fog                                 :\n260: Šarma                                   : Freezing fog                        :\n263: Protarpiais dulksna                     : Patchy light drizzle                :\n266: Dulksna                                 : Light drizzle                       :\n281: Lijundra                                : Freezing drizzle                    :\n284: Stipri lijundra                         : Heavy freezing drizzle              :\n293: Protarpiais silpnas lietus              : Patchy light rain                   :\n296: Silpnas lietus                          : Light rain                          :\n299: Protarpiais lietus                      : Moderate rain at times              :\n302: Lietus                                  : Moderate rain                       :\n305: Protarpiais stiprus lietus              : Heavy rain at times                 :\n308: Stiprus lietus                          : Heavy rain                          :\n311: Silpna lijundra                         : Light freezing rain                 :\n314: Vidutinė arba stipri lijundra           : Moderate or heavy freezing rain     :\n317: Lengva šlapdriba                        : Light sleet                         :\n320: Vidutinė arba stipri šlapdriba          : Moderate or heavy sleet             :\n323: Protarpiais lengvas snygis              : Patchy light snow                   :\n326: Lengvas snygis                          : Light snow                          :\n329: Protarpiais vidutinis snygis            : Patchy moderate snow                :\n332: Snygis                                  : Moderate snow                       :\n335: Protarpiais stiprus snygis              : Patchy heavy snow                   :\n338: Stiprus snygis                          : Heavy snow                          :\n350: Kruša                                   : Ice pellets                         :\n353: Nesmarki liūtis                         : Light rain shower                   :\n356: Vidutinė arba smarki liūtis             : Moderate or heavy rain shower       :\n359: Smarki liūtis                           : Torrential rain shower              :\n362: Protarpiais lengva šlapdriba            : Light sleet showers                 :\n365: Protarpiais vidutinė/smarki šlapdriba   : Moderate or heavy sleet showers     :\n368: Protarpiais lengvas snygis              : Light snow showers                  :\n371: Protarpiais vidutinis/sunkus snygis     : Moderate or heavy snow showers      :\n386: Protarpiais lengvas lietūs su perkūnija : Patchy light rain with thunder      :\n389: Vidutinis/sunkus lietus su perkūnija    : Moderate or heavy rain with thunder :\n392: Protarpiais lengvas snygis su perkūija  : Patchy light snow with thunder      :\n395: Vidutinis/sunkus snygis su perkūnija    : Moderate or heavy snow with thunder :\n"
  },
  {
    "path": "share/translations/lv-help.txt",
    "content": "Izmantošana:\n\n    $ curl wttr.in          # pašreizējā atrašanās vieta\n    $ curl wttr.in/rix      # laikapstākļi Rīgas lidostā\n\nAtbalstītie atrašanās vietu veidi:\n\n    /paris                  # pilsētas nosaukums\n    /~Eiffel+tower          # jebkura atrašanās vieta (+ atstarpju vietā)\n    /Москва                 # jebkuras atašanās vietas Unicode nosaukums jebkurā valodā\n    /rix                    # lidostas kods (3 burti)\n    /@stackoverflow.com     # domēna vārds\n    /94107                  # pasta indekss (tikai ASV)\n    /-78.46,106.79          # GPS koordinātas\n\nInformācija par Mēness fāzēm:\n\n    /moon                   # Mēness fāze (jāpievieno ,+US vai ,+France noteiktai pilsētai)\n    /moon@2016-10-25        # Mēness fāze datumā (@2016-10-25)\n\nMērvienības:\n\n    m                       # Metriskā sistēma (SI) (pēc noklusējuma izmanto visur izņemot ASV)\n    u                       # USCS (pēc noklusējuma izmanto ASV)\n    M                       # rādīt vēja ātrumu ar m/s\n\nSkata iespējas:\n\n    0                       # tikai pašreizējie laikapstākļi\n    1                       # pašreizējie laikapstākļi un šodienas prognoze\n    2                       # pašreizējie laikapstākļi un šodienas un rītdienas prognoze\n    A                       # neņemt vērā User-Agent un uzspiest ANSI izvades veidolu (terminālis)\n    d                       # ierobežot izvadi ar standarta konsoles fonta glifiem\n    F                       # nerādīt sekošanas rindu\n    n                       # šaurā versija (tikai diena un nakts)\n    q                       # saīsinātā versija (bez teksta \"Laikapstākļi\")\n    Q                       # īpaši saīsinātā versija (bez teksta \"Laikapstākļi\" un pilsētas nosaukuma)\n    T                       # izslēgt termināļa virknes (bez krāsām)\n\nPNG iespējas:\n\n    /paris.png              # izveidot PNG datni\n    p                       # izvadei pievienot rāmi\n    t                       # caurspīdīgums 150\n    transparency=...        # caurspīdīgums no 0 - 255 (255 = necaurspīdīgs)\n    background=...          # fona krāsa veidolā RRGGBB, piem. 00aaaa\n\nIespējas var apvienot:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # PNG datnes nosaukumā iespējas tiek rakstītas aiz _\n    /Rome_0pq_lang=it.png   # garās iespējas tiek atadlītas ar apakšsvītru\n\nLokalizācija:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nAtbalstītās valodas:\n\n    FULL_TRANSLATION (atbalstītas)\n    PARTIAL_TRANSLATION (pie tām tiek strādāts)\n\nĪpaši URL:\n\n    /:help                  # parāda šo lapu\n    /:bash.function         # parāda ieteikto bash funkciju wttr()\n    /:translation           # parāda informāciju par tulkotājiem\n"
  },
  {
    "path": "share/translations/lv.txt",
    "content": "   : Tuvumā īslaicīgs lietus                      : Patchy rain nearby\n   : Tuvumā pērkona negaiss                       : Thunderstorm in vicinity\n113: Skaidrs                                      : Clear\n113: Saulains                                     : Sunny\n116: Daļēji mākoņains                             : Partly cloudy\n119: Mākoņains                                    : Cloudy\n122: Apmācies                                     : Overcast\n143: Dūmaka                                       : Mist\n176: Vietām iespējams lietus                      : Patchy rain possible\n179: Vietām iespējams sniegs                      : Patchy snow possible\n182: Vietām iespējams sals                        : Patchy sleet possible\n185: Vietām iespējama sasalstoša smidzināšana     : Patchy freezing drizzle possible\n200: Iespējams pērkona negaiss                    : Thundery outbreaks possible\n227: Sniegputenis                                 : Blowing snow\n230: Sniega vētra                                 : Blizzard\n248: Migla                                        : Fog\n260: Sasalstoša migla                             : Freezing fog\n263: Vietām viegla smidzināšana                   : Patchy light drizzle\n266: Viegla smidzināšana                          : Light drizzle\n281: Sasalstoša smidzināšana                      : Freezing drizzle\n284: Spēcīga sasalstoša smidzināšana              : Heavy freezing drizzle\n293: Vietām viegls lietus                         : Patchy light rain\n296: Viegls lietus                                : Light rain\n299: Īslaicīgs mērens lietus                      : Moderate rain at times\n302: Mērens lietus                                : Moderate rain\n305: Īslaicīgs spēcīgs lietus                     : Heavy rain at times\n308: Spēcīgs lietus                               : Heavy rain\n311: Viegls sasalstošs lietus                     : Light freezing rain\n314: Mērens vai spēcīgs un sasalstošs lietus      : Moderate or heavy freezing rain\n317: Viegls slapjdraņķis                          : Light sleet\n320: Mērens vai spēcīgs slapjdraņķis              : Moderate or heavy sleet\n323: Vietām viegls sniegs                         : Patchy light snow\n326: Viegls sniegs                                : Light snow\n329: Vietām mērens sniegs                         : Patchy moderate snow\n332: Mērens sniegs                                : Moderate snow\n335: Vietām spēcīgs sniegs                        : Patchy heavy snow\n338: Spēcīgs sniegs                               : Heavy snow\n350: Krusa                                        : Ice pellets\n353: Vieglas lietusgāzes                          : Light rain shower\n356: Mērenas vai spēcīgas lietusgāzes             : Moderate or heavy rain shower\n359: Spēcīgas lietusgāzes                         : Torrential rain shower\n362: Vieglas slapjdraņķa gāzes                    : Light sleet showers\n365: Mērens vai spēcīgs sniegs                    : Moderate or heavy sleet showers\n368: Vieglas sniega gāzes                         : Light snow showers\n371: Mērenas vai spēcīgs sniega gāzes             : Moderate or heavy snow showers\n386: Vietām viegls lietus ar pērkona negaisu      : Patchy light rain with thunder\n389: Mērens vai spēcīgs lietus ar pērkona negaisu : Moderate or heavy rain with thunder\n392: Vietām viegls sniegs ar pērkona negaisu      : Patchy light snow with thunder\n395: Mērens vai spēcīgs sniegs ar pērkona negaisu : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/messages/en.yaml",
    "content": "lang:\n    name: English\n    code: \"en\"\n    issue: \"\"\n    translators:\n        - \"Igor Chubin @igor_chubin\"\n    locale: \"en_US\"\n\ntranslated:\n    help: true\n    weather: true\n    messages: true\n\nmessages:\n    \n    caption: 'Weather report for:'\n\n    location: Location\n\n    unknown_location: Unknown location\n\n    capacity_limit_reached: |2\n\n      Sorry, we are running out of queries to the weather service at the moment.\n      Here is the weather report for the default city (just to show you what it looks like).\n      We will get new queries as soon as possible.\n      You can follow https://twitter.com/igor_chubin for the updates.\n      ======================================================================================\n\n    follow_me: |-\n      Follow \\\\e[46m\\\\e[30m@igor_chubin\\\\e[0m for wttr.in updates\n\n    new_feature: |-\n      New feature: multilingual location names \\\\e[92mwttr.in/станция+Восток\\\\e[0m (in UTF-8) and location search \\\\e[92mwttr.in/~Kilimanjaro\\\\e[0m (just add ~ before)\n\n    not_found_message: |2\n\n      We were unable to find your location\n      so we have brought you to Oymyakon,\n      one of the coldest permanently inhabited locales on the planet.\n\n\nviews:\n\n    v1:\n\n      morning: \"Morning\"\n      noon: \"Noon\"\n      evening: \"Evening\"\n      night: \"Night\"\n\n    v2:\n\n      weather_report_for: \"Weather report for:\"\n      weather: \"Weather\"\n      timezone: \"Timezone\"\n      now: \"Now\"\n      dawn: \"Dawn\"\n      sunrise: \"Sunrise\"\n      zenith: \"Zenith\"\n      sunset: \"Sunset\"\n      dusk: \"Dusk\"\n"
  },
  {
    "path": "share/translations/messages/gu.yaml",
    "content": "lang:\n    name: Gujarati\n    code: gu\n    issue: \"774\"\n    translators:\n        - @wylited (on GitHub)\n    locale: gu_IN\n\ntranslated:\n    help: false\n    weather: false\n    messages: false\n\nmessages:\n    \n    caption: 'Weather report for:'\n\n    location: Location\n\n    unknown_location: Unknown location\n\n    capacity_limit_reached: |2\n\n      Sorry, we are running out of queries to the weather service at the moment.\n      Here is the weather report for the default city (just to show you what it looks like).\n      We will get new queries as soon as possible.\n      You can follow https://twitter.com/igor_chubin for the updates.\n      ======================================================================================\n\n    follow_me: |-\n      Follow \\\\e[46m\\\\e[30m@igor_chubin\\\\e[0m for wttr.in updates\n\n    new_feature: |-\n      New feature: multilingual location names \\\\e[92mwttr.in/станция+Восток\\\\e[0m (in UTF-8) and location search \\\\e[92mwttr.in/~Kilimanjaro\\\\e[0m (just add ~ before)\n\n    not_found_message: |2\n\n      We were unable to find your location\n      so we have brought you to Oymyakon,\n      one of the coldest permanently inhabited locales on the planet.\n\n\nviews:\n\n    v1:\n\n      morning: \"Morning\"\n      noon: \"Noon\"\n      evening: \"Evening\"\n      night: \"Night\"\n\n    v2:\n\n      weather_report_for: \"Weather report for:\"\n      weather: \"Weather\"\n      timezone: \"Timezone\"\n      now: \"Now\"\n      dawn: \"Dawn\"\n      sunrise: \"Sunrise\"\n      zenith: \"Zenith\"\n      sunset: \"Sunset\"\n      dusk: \"Dusk\"\n"
  },
  {
    "path": "share/translations/mg-help.txt",
    "content": "Fampiasana azy:\n\n    $ curl wttr.in                # toetr'andro eo amin'ny toerana misy anao\n    $ curl wttr.in/antananarivo   # totr'andro any Antananarivo\n\nKarazana toerana azo ampesaina:\n\n    /fianarantsoa           # nom de la ville\n    /~Eiffel+tower          # anaran-toerana rehetra\n    /Москва                 # anarana Unikody na anaran-toerana rehetra amin'ny fiteny rehetra\n    /tnr                    # kaody ny seranam-piaramanidina (litera 3)\n    /@stackoverflow.com     # anarana domaina (rohy)\n    /94107                  # Kaody postaly (hoan'ny Etazonia iany)\n    /-78.46,106.79          # coordonnées GPS\n\nToerana somary miavaka:\n\n    /moon                   # Dignana ny volana(ampio ,+US ou ,+France raha toa ka misy toerana mitondra anio anarana io)\n    /moon@2016-10-25        # Dignana ny volana hoan'ny daty iray(@2016-10-25)\n\nRefy:\n\n    ?m                      # rafitra metrika (fampiasain'ny rehetra afatsy ny Amerika Avaratra)\n    ?u                      # USCS (Fampiasan'ny Etazonia)\n    ?M                      # mampiseho ny hafainganam-pandehan'ny rivotra amin'ny metatra isan-segondra\n\nFomba fampisehoana:\n\n    ?0                      # androany fotsiny\n    ?1                      # androany sy rampitso\n    ?2                      # androany miampy roa andro\n    ?n                      # kinova fohy (atoandro sy ariva fotsiny)\n    ?q                      # kinova tsotra (tsisy \"Vinavina ny totrandro androany\")\n    ?Q                      # version super-silencieuse (pas d'en-tête \"Prévisions météo pour\", pas de nom de la ville)\n    ?T                      # séquences d'échappement pour terminaux désactivées (pas de couleurs)\n\nFomba fampisehoana sary PNG:\n\n    /antananarivo.png       # mamoka sary PNG\n    ?p                      # manisy kadra manodidina ilay seho mivoaka\n    ?t                      # transparency 150 (fangaraharana 150)\n    transparency=...        # fangaraharana ao anatin'ny 0 atramin'ny 255 (255 = tsisy fangaraharana)\n\nManambatra anireo safidy:\n\n    /antananarivo?0pq\n    /antananarivo?0pq&lang=mg\n    /antananarivo_0pq.png          # raha toa ka mampiasa fampisehoana aminn'ny sary PNG dia asina tsipik'ambany `_` manelanelana azy\n    /Rome_0pq_lang=it.png          # ireo safidy lava dia sarahina amin'ny tsipik'ambany `_` ian'ny koa \n\nToerana:\n\n    $ curl fr.wttr.in/antananarivo\n    $ curl wttr.in/antananarivo?lang=mg\n    $ curl -H \"Accept-Language: mg\" wttr.in/paris\n\nLangues supportées:\n\n    FULL_TRANSLATION (Voadika teny tanteraka)\n    PARTIAL_TRANSLATION (Voadika teny ampahany)\n\nURLs particulières:\n\n    /:help                  # mampiseho ito pejy ito\n    /:bash.function         # sosokevitra fonction bash wttr()\n    /:translation           # mampahafantra ny momba ny fandikanteny ao amin'ny wttr.in\n"
  },
  {
    "path": "share/translations/mg.txt",
    "content": ": Oram-be manavandra sy oram-baratra                            : Heavy rain and hail with thunderstorm\n: Oram-be sy oram-baratra                                       : Heavy rain with thunderstorm\n: Oram-baratra malefaka sy  manavandra                          : Light rain and hail with thunderstorm\n: Orana malefaka sy ranomandry                                  : Light rain and snow shower\n: Oranam-baratra malefaka                                       : Light rain with thunderstorm\n: Orana malefaka ranomandry                                     : Light snow shower\n: Zavona ampahany                                               : Partial fog\n: Oram-baratra manavandra                                       : Rain and hail with thunderstorm\n: Zavona malefaka                                               : Shallow fog\n: Zavona                                                        : Smoke\n: Oram-baratra                                                  : Squalls\n: Orages proches                                                : Thunderstorm in vicinity\n: Oram-panala                                                   : Snow\n: Orana                                                         : Rain\n: Orana malefaka                                                : Light Rain, Rain Shower\n: Ranonorana                                                    : Rain Shower\n: Vongan-zavona                                                 : Patches of fog\n: Pitipitik'orana                                               : Drizzle\n: Pitipitik'orana                                               : Light drizzle\n: Oram-panala mitsoka ambany                                    : Low drifting snow\n: Oram-panala malefaka                                          : Light rain and snow\n: Oram-be manakaiky                                             : Shower in vicinity\n: Oram-baratra                                                  : Rain with thunderstorm\n: Oram-be sy oram-panala                                        : Rain and snow shower\n: Ora-mikija                                                    : Thunderstorm\n: Pitipitik'orana                                               : Drizzle and rain\n: Oram-be manavandra                                            : Hail with thunderstorm\n: Zavona                                                        : Haze\n: Zavona arahin'orana                                           : Light drizzle and rain\n: Ora-mikija, orana malefaka et avandra / Oram-panala           : Light rain and small hail/snow pallets with thunderstorm\n113 : Tsara ny andro                                            : Clear\n113 : Masoandro mibalika                                        : Sunny\n116 : Rakodrahona ampahany                                      : Partly cloudy\n119 : Rakodrahona                                               : Cloudy\n122 : Manjombona                                                : Overcast\n143 : Zavona                                                    : Mist\n176 : Mety hanorana matevina                                    : Patchy rain possible\n179 : Mety hisy oram-panala matevina                            : Patchy snow possible\n182 : Mety hanerika kely                                        : Patchy sleet possible\n185 : Mety hisy zavona mandry sy matevina                       : Patchy freezing drizzle possible\n200 : Mety hisy Ora-mikija                                      : Thundery outbreaks possible\n227 : Oram-panala                                               : Blowing snow\n230 : Tafiotran’orampanala                                      : Blizzard\n248 : Zavona                                                    : Fog\n260 : Zavona mangatsiaka                                        : Freezing fog\n263 : Zavona matevina                                           : Patchy light drizzle\n266 : Zavona malefakaa                                          : Light drizzle\n281 : Zavona mandry                                             : Freezing drizzle\n284 : Zavona mangatsika mafy                                    : Heavy freezing drizzle\n293 : Orana matevina                                            : Patchy light rain\n296 : Orana malefaka                                            : Light rain\n299 : Orana malefaka miverimberina                              : Moderate rain at times\n302 : Orana malefaka                                            : Moderate rain\n305 : Oram-be miverimberina                                     : Heavy rain at times\n308 : Oram-be                                                   : Heavy rain\n311 : Orana mangatsiaka                                         : Light freezing rain\n314 : Orana malefaka na mafy mangatsiaka                        : Moderate or heavy freezing rain\n317 : Tafiotran’orampanala maivana                              : Light sleet\n320 : Tafiotran’orampanala malefaka na mafy                     : Moderate or heavy sleet\n323 : Oram-panala matevina                                      : Patchy light snow\n326 : Oram-panala maivana                                       : Light snow\n329 : Oram-panala malefaka                                      : Patchy moderate snow\n332 : Latsakoram-panala malefaka                                : Moderate snow\n335 : Oram-panala mavesatra sy matevina                         : Patchy heavy snow\n338 : Oram-panala mafy                                          : Heavy snow\n350 : Pitipitika ranomandro                                     : Ice pellets\n353 : Oram-be malefaka                                          : Light rain shower\n356 : Orana antoniny sy mavesatra                               : Moderate or heavy rain shower\n359 : Oram-be mikija                                            : Torrential rain shower\n362 : Pitipitik'oram-panala mikija                              : Light sleet showers\n365 : Pitipitik'oram-panala malefaka na mavesatra               : Moderate or heavy sleet showers\n368 : Pitipitik'oram-panala maivana                             : Light snow showers\n371 : Rotsak'oram-panala maivana sy mavesatra                   : Moderate or heavy snow showers\n386 : Oram-baratra matevina                                     : Patchy light rain with thunder\n389 : Oram-baratra malefaka na mavesatra                        : Moderate or heavy rain with thunder\n392 : Rotsak'oram-panala maivana arahim-baratra                 : Patchy light snow with thunder\n395 : Rotsak'oram-panala malefaka na mavesatra arahim-baratra   : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/mk.txt",
    "content": "113: Ведро: Clear \n113: Сончево: Sunny\n116: Делумно Облачно: Partly cloudy \n119: Облачно: Cloudy \n122: Облачно: Overcast \n143: Слаба магла: Mist \n176: Умерено врнежливо во близина: Patchy rain nearby  \n176: Умерено врнежливо можно: Patchy rain possible \n179: Умерено снежливо можно: Patchy snow possible  \n182: Умерено можно: Patchy sleet possible \n185: Умерено: Patchy freezing drizzle possible \n200: Грмежи во близина: Thundery outbreaks in nearby \n200: Грмежи можно: Thundery outbreaks possible \n227: Снег: Blowing snow \n230: Виулица: Blizzard \n248: Магла: Fog \n260: Смрзнувачка магла: Freezing fog \n263: Умерен слаб дожд: Patchy light drizzle \n266: Роса: Light drizzle \n281: Смрзнувачка роса: Freezing drizzle \n284: Тежка смрзнувачка роса: Heavy freezing drizzle \n293: Умерен слаб дожд: Patchy light rain  \n296: Слаб дожд: Light rain \n299: Умерен дожд понекогаш: Moderate rain at times \n302: Умерен дожд: Moderate rain \n305: Пороен дожд: Heavy rain at times \n308: Пороен дожд : Heavy rain \n311: Смрзнувачки дожд: Light freezing rain \n314: Умерен или тешки врнежи со дожд: Moderate or heavy freezing rain \n317: Дожд со лед: Light sleet \n320: Умерен или тежок дожд со лед: Moderate or heavy sleet \n323: Умерени врнежи на слаб снег: Patchy light snow \n326: Слабо врнежи снег: Light snow \n329: Умерени врнежи на снег: Patchy moderate snow \n332: Умерен врнежи на снег: Moderate snow \n335: Умерено тешки врнежи на снег: Patchy heavy snow \n338: Тешки врнежи со снег: Heavy snow \n350: Град: Ice pellets \n353: Слаби врнежи: Light rain shower \n356: Умерени или тешки врнежи: Moderate or heavy rain shower \n359: Пороен дожд: Torrential rain shower \n362: Слаби дождови: Light sleet showers \n365: Умерено или тешки : Moderate or heavy sleet showers \n368: Слаби врнежи снег: Light snow showers \n371: Умерено или тежки врнежи со снег: Moderate or heavy snow showers \n386: Умерено слаб дожд во области со грмежи: Patchy light rain in area with thunder \n386: Умерено слаб дожд со грмежи: Patchy light rain with thunder \n389: Умерен или тешки врнежи во области со грмежи: Moderate or heavy rain in area with thunder \n389: Умерен или тешки врнежи со грмежи: Moderate or heavy rain with thunder \n392: Умерено слаб снег со грмежи: Patchy light snow with thunder \n395: Умерен или тешки врнежи снег во области со грмежи: Moderate or heavy snow in area with thunder \n395: Умерен или тешки врнежи снег со грмежи: Moderate or heavy snow with thunder \n"
  },
  {
    "path": "share/translations/mr-help.txt",
    "content": "वापर:\n\n    $ curl wttr.in          # वर्तमान स्थळाचे हवामान\n    $ curl wttr.in/muc      # म्युनिक विमानतळावरील हवामान\n\nउपलब्धीत/प्रयोज्य स्थळांचे प्रकार:\n\n    /paris                  # शहराचे नाव\n    /~Eiffel+tower          # कोणत्याही स्थळाचे नाव (रिकाम्या ठिकाणी (स्पेस ऐवजी) +)\n    /Москва                 # युनिकोड स्वरूपात कोणत्याही भाषेतील कोणत्याही स्थळाचे नाव\n    /muc                    # विमातळाचे संकेत (कोड) (३ अक्षरे)\n    /@stackoverflow.com     # संकेतस्थळाचे डोमेन नाव\n    /94107                  # क्षेत्र कोड\n    /-78.46,106.79          # जीपीएस सहनिर्देशक (रेखांश, अक्षांश)\n\nचंद्राच्या कलेची माहिती:\n\n    /moon                   # चंद्राची कला (विशिष्ट स्थळासाठी +US, +France इत्यादी जोडा)\n    /moon@2016-10-25        # विशिष्ट दिनी चंद्राची कला (@2016-10-25)\n\nएकक:\n\n    m                       # दशमान (मेट्रिक/SI) (अमेरिका वगळता सर्वत्र वापरली जाते)\n    u                       # USCS (अमेरिकेत वापरली जाते)\n    M                       # वाऱ्याचा वेग मीटर प्रति सेकंद (m/s) मध्ये दाखवा\n\nदृश्य पर्याय:\n\n    0                       # केवळ वर्तमान हवामान\n    1                       # वर्तमान + आजचा हवामान अंदाज\n    2                       # वर्तमान + आजचा + उद्याचा हवामान अंदाज\n    A                       # (टर्मिनल मध्ये) युसर-एजन्ट दुर्लक्षित करून एएनएसआय (ANSI) स्वरूप वापरा\n    F                       # \"अनुसरण करा\" (फॉलो) ची ओळ अदृश्य करा\n    n                       # अरुंद स्वरूप (फक्त दुपार व रात्र)\n    q                       # शांत स्वरूप  (\"हवामान अंदाज\" मजकूर अदृश्य)\n    Q                       # अतिशांत स्वरूप  (\"हवामान अंदाज\" मजकूर व शहराचे नाव अदृश्य)\n    T                       # टर्मिनल सिक्वेन्स(क्रम) बंद (बेरंगीत)\n\nPNG पर्याय:\n\n    /paris.png              # PNG फाईल निर्माण करा\n    p                       # प्रतिमेभोवती चौकट जोडा \n    t                       # 150  पारदर्शकता\n    transparency=...        # 0 ते 255 पारदर्शकता (255 = अपारदर्शक)\n    background=...          # RRGGBB (लाल हिरवा निळा) स्वरूपात पार्श्वभूमीचा रंग, उदा. 00aaaa\n\nपर्याय एकत्र करू शकता:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # PNG फाईलच्या बाबतीत पर्याय अधोरेखे \"_\" नंतर लिहिले जातात\n    /Rome_0pq_lang=it.png   # लांब पर्याय हे अधोरेखेने विभाजित केले जातात\n\nभाषांतर:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nउपलब्ध भाषा:\n\n    FULL_TRANSLATION (उपलब्ध)\n    PARTIAL_TRANSLATION (काम चालू)\n\nविशेष दुवे:\n\n    /:help                  # हे पृष्ठ दाखवा\n    /:bash.function         # शिफारस केलेले बॅश \"wttr()\" कार्य दाखवा \n    /:translation           # भाषांतर करणाऱ्यांची माहिती दाखवा\n\n"
  },
  {
    "path": "share/translations/mr.txt",
    "content": "    : मुसळधार पाऊस, गारा व झंझावात      : Heavy rain and hail with thunderstorm\n    : मुसळधार पाऊस व झंझावात          : Heavy rain with thunderstorm\n    : हलका पाऊस, गारा व झंझावात        : Light rain and hail with thunderstorm\n    : हलका पाऊस व हिमवर्षाव          : Light rain and snow shower\n    : हलका पाऊस व झंझावात            : Light rain with thunderstorm\n    : हलका हिमवर्षाव                : Light snow shower\n    : आंशिक दाट धुके                 : Partial fog\n    : पाऊस, गारा व झंझावात            : Rain and hail with thunderstorm\n    : पाऊस व झंझावात                : Rain with thunderstorm\n    : उथळ दाट धुके                 : Shallow fog\n    : धूर                        : Smoke\n    : चंडवात                      : Squalls\n    : झंझावात जवळपास                : Thunderstorm in vicinity\n    : हिमवर्षाव                    : Snow\n    : पाऊस                       : Rain\n    : हलका पाऊस, पावसाच्या सरी         : Light Rain, Rain Shower\n    : पावसाच्या सरी                  : Rain Shower\n    : तुरळक दाट धुके                : Patches of fog\n    : रिमझिम                      : Drizzle\n    : हलका रिमझिम पाऊस              : Light drizzle\n    : कमी वाहणारे बर्फ               : Low drifting snow\n    : हलका पाऊस आणि बर्फ            : Light rain and snow\n    : पावसाची सर जवळपास             : Shower in vicinity\n    : पाऊस व झंझावात                : Rain with thunderstorm\n    : पाऊस व हिमवर्षाव              : Rain and snow shower\n    : झंझावात                      : Thunderstorm\n    : रिमझिम व पाऊस                : Drizzle and rain\n    : गारा व झंझावात                 : Hail with thunderstorm\n    : विरळ धुके                    : Haze\n    : हलके रिमझिम व पाऊस            : Light drizzle and rain\n    : झंझावात सह हलका पाऊस व लहान गारा  : Light rain and small hail/snow pallets with thunderstorm\n113 : स्वच्छ                      : Clear\n113 : ऊन                        : Sunny\n116 : काहीसे ढगाळ                   : Partly cloudy\n119 : ढगाळ                       : Cloudy\n122 : मळभ                       : Overcast\n143 : धुके                        : Mist\n176 : तुरळक पावसाची शक्यता            : Patchy rain possible\n179 : तुरळक बर्फाची शक्यता            : Patchy snow possible\n182 : तुरळक हिमयुक्त पावसाची शक्यता      : Patchy sleet possible\n185 : तुरळक थंड रिमझिमची शक्यता        : Patchy freezing drizzle possible\n200 : झंझावाताची शक्यता                : Thundery outbreaks possible\n227 : वाहणारा बर्फ                  : Blowing snow\n230 : हिमवादळ                     : Blizzard\n248 : दाट धुके                     : Fog\n260 : थंड दाट धुके                  : Freezing fog\n263 : तुरळक रिमझिम                 : Patchy light drizzle\n266 : हलके रिमझिम                  : Light drizzle\n281 : थंड रिमझिम                   : Freezing drizzle\n284 : अतिथंड रिमझिम                 : Heavy freezing drizzle\n293 : तुरळक हलका पाऊस              : Patchy light rain\n296 : हलका पाऊस                   : Light rain\n299 : अधूनमधून हलका पाऊस            : Moderate rain at times\n302 : मध्यम पाऊस                  : Moderate rain\n305 : अधूनमधून मुसळधार पाऊस          : Heavy rain at times\n308 : मुसळधार पाऊस                 : Heavy rain\n311 : हलका थंड पाऊस                : Light freezing rain\n314 : मध्यम ते अतिथंड पाऊस           : Moderate or heavy freezing rain\n317 : हलका हिमयुक्त पाऊस             : Light sleet\n320 : मध्यम ते अतिथंड हिमयुक्त पाऊस     : Moderate or heavy sleet\n323 : तुरळक हलका हिमवर्षाव           : Patchy light snow\n326 : हलका हिमवर्षाव                : Light snow\n329 : तुरळक मध्यम हिमवर्षाव          : Patchy moderate snow\n332 : मध्यम हिमवर्षाव               : Moderate snow\n335 : तुरळक जोरदार हिमवर्षाव          : Patchy heavy snow\n338 : जोरदार हिमवर्षाव               : Heavy snow\n350 : मऊ गारा                     : Ice pellets\n353 : पावसाच्या हलक्या सरी             : Light rain shower\n356 : पावसाच्या मध्यम ते जोरात सरी       : Moderate or heavy rain shower\n359 : मुसळधार पावसाच्या सरी            : Torrential rain shower\n362 : हिमयुक्त पावसाच्या हलक्या सरी       : Light sleet showers\n365 : हिमयुक्त पावसाच्या मध्यम ते जोरात सरी : Moderate or heavy sleet showers\n368 : बर्फाच्या हलक्या सरी             : Light snow showers\n371 : बर्फाच्या मध्यम ते जोरात सरी       : Moderate or heavy snow showers\n386 : तुरळक हलका पाऊस व गडगडाट      : Patchy light rain with thunder\n389 : मध्यम ते जोरात पाऊस व गडगडाट    : Moderate or heavy rain with thunder\n392 : तुरळक हलका बर्फ व गडगडाट      : Patchy light snow with thunder\n395 : मध्यम ते जोरात बर्फ व गडगडाट    : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/nb-help.txt",
    "content": "Bruk:\n\n    $ curl wttr.in          # nåværende lokasjon\n    $ curl wttr.in/osl      # været på Gardermoen flyplass\n\nStøttede lokasjonsspesifiseringer:\n\n    /oslo                   # bynavn\n    /~Ullevål+stadion       # valgfri lokasjon\n    /Москва                 # Unicode navn på lokasjon på alle språk\n    /osl                    # flyplasskode (3 bokstaver)\n    /@stackoverflow.com     # domenenavn\n    /94107                  # postnummer (bare USA)\n    /-78.46,106.79          # GPS-koordinater\n\nSpesielle lokasjoner:\n\n    /moon                   # Månefase (legg til ,+US eller ,+France disse byene)\n    /moon@2016-10-25        # Månefase for spesifisert dato (@2016-10-25)\n\nEnheter:\n\n    ?m                      # metrisk (SI) (standard alle steder unntatt USA)\n    ?u                      # USCS (standard i USA)\n    ?M                      # vindstyrke i meter per sekund\n\nVisningsvalg:\n\n    ?0                      # kun været nå\n    ?1                      # været nå + 1 dag\n    ?2                      # været nå + 2 dager\n    ?n                      # smal visning (bare dag og natt)\n    ?q                      # stille visning (ingen \"Værmelding\"-tekst)\n    ?Q                      # superstille visning (ingen \"Værmelding\", ingen bynavn)\n    ?T                      # ingen terminalsekvenser (ingen farger)\n\nPNG valg:\n\n    /paris.png              # generer en PNG-fil\n    ?p                      # legg til ramme\n    ?t                      # gjennomsiktighet 150\n    transparency=...        # gjennomsiktighet fra 0 til 255 (255 = ikke gjennomsiktig)\n\nTilvalg kan kombineres:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # for PNG er filmodus spesifisert etter _\n    /Rome_0pq_lang=it.png   # lange tilvalg separeres med understrek\n\nOversettelser:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nStøttede språk:\n\n    FULL_TRANSLATION (støttet)\n    PARTIAL_TRANSLATION (under arbeid)\n\nSpesielle URLer:\n\n    /:help                  # vis denne siden\n    /:bash.function         # vis den foreslåtte bash-funksjonen wttr()\n    /:translation           # vis informasjon om oversetterne\n"
  },
  {
    "path": "share/translations/nb.txt",
    "content": "113: Sol                                    : Sunny\n114: Klart                                  : Clear\n116: Delvis skyet                           : Partly cloudy\n119: Skyet                                  : Cloudy\n122: Overskyet                              : Overcast\n143: Dis                                    : Mist\n176: Sjanser for skiftende regn             : Patchy rain possible\n179: Sjanser for skiftende snø              : Patchy snow possible\n182: Sjanser for skiftende sludd            : Patchy sleet possible\n185: Sjanser for skiftende, kaldt duskregn  : Patchy freezing drizzle possible\n200: Fare for torden                        : Thundery outbreaks possible\n227: Snøfokk                                : Blowing snow\n230: Snøstorm                               : Blizzard\n248: Tåke                                   : Fog\n260: Kald tåke                              : Freezing fog\n263: Skiftende, lett duskregn               : Patchy light drizzle\n266: Lett duskregn                          : Light drizzle\n281: Kaldt duskregn                         : Freezing drizzle\n284: Kraftig, kaldt duskregn                : Heavy freezing drizzle\n293: Skiftende, lett regn                   : Patchy light rain\n296: Lett regn                              : Light rain\n299: Til tider noe regn                     : Moderate rain at times\n302: Noe regn                               : Moderate rain\n305: Til tider kraftig regn                 : Heavy rain at times\n308: Kraftig regn                           : Heavy rain\n311: Lett, kaldt regn                       : Light freezing rain\n314: Moderat eller kraftig kaldt regn       : Moderate or heavy freezing rain\n317: Lett sludd                             : Light sleet\n320: Moderat eller kraftig sludd            : Moderate or heavy sleet\n323: Skiftende, lett snø                    : Patchy light snow\n326: Lett snø                               : Light snow\n329: Skiftende, moderat snø                 : Patchy moderate snow\n332: Noe snø                                : Moderate snow\n335: Skiftende, kraftig snøfall             : Patchy heavy snow\n338: Kraftig snøfall                        : Heavy snow\n350: Hagl                                   : Ice pellets\n353: Lett regnskur                          : Light rain shower\n356: Moderat eller tung regnskur            : Moderate or heavy rain shower\n359: Styrtregn                              : Torrential rain shower\n362: Lette sluddbyger                       : Light sleet showers\n365: Moderate eller tunge sluddbyger        : Moderate or heavy sleet showers\n368: Lette snøbyger                         : Light snow showers\n371: Moderate eller kraftige snøbyger       : Moderate or heavy snow showers\n386: Skiftende, lett regn med torden        : Patchy light rain with thunder\n389: Moderat eller kraftig regn med torden  : Moderate or heavy rain with thunder\n392: Skiftende, lett snø med torden         : Patchy light snow with thunder\n395: Moderat eller kraftig snø med torden   : Moderate or heavy snow with thunder\n\n: Dis i nærheten                            : Haze in vicinity\n: Kraftig regn- og snøbyge                  : Heavy rain and snow shower\n: Kraftig regnbyge                          : Heavy rain shower\n: Lett duskregn og snøkorn                  : Light drizzle and snow grains\n: Lett regn- og tåkebyge                    : Light rain and mist shower\n: Lett byge med små hagl                    : Light small hail shower\n: Lett byge med ukjent nedbør               : Light unknown precipitation shower\n: Regn og små hagl med tordenvær            : Rain and small hail with thunderstorm\n: Snøbyge i nærheten                        : Snow shower in vicinity\n: Tordenvær i nærheten                      : Thundery outbreaks nearby\n: Snøfokk nær bakken                        : Low drifting snow\n: Tåkebanker                                : Patches of fog\n: Duskregn                                  : Drizzle\n: Lett duskregn og regn                     : Light drizzle and rain\n: Snø                                       : Snow\n: Regn                                      : Rain\n: Regnbyge                                  : Rain shower\n: Sandfokk                                  : Blowing sand\n: Utbredt støvfokk                          : Blowing widespread dust\n: Utbredt støvfokk i nærheten               : Blowing widespread dust in vicinity\n: Duskregn og tåke                          : Drizzle and fog\n: Duskregn og regn                          : Drizzle and rain\n: Duskregn og regnbyge                      : Drizzle and rain shower\n: Duskregn med tordenvær                    : Drizzle with thunderstorm\n: Støvstorm                                 : Dust storm\n: Tåke i nærheten                           : Fog in vicinity\n: Underkjølt duskregn og regn               : Freezing drizzle and rain\n: Underkjølt tåke                           : Freezing mist\n: Underkjølt regn                           : Freezing rain\n: Underkjølt regn og snø                    : Freezing rain and snow\n: Underkjølt ukjent nedbør                  : Freezing unknown precipitation\n: Skydrage i nærheten                       : Funnel cloud in vicinity\n: Haglbyge                                  : Hail shower\n: Hagl med tordenvær                        : Hail with thunderstorm\n: Dis                                       : Haze\n: Kraftig snøfokk                           : Heavy blowing snow\n: Kraftig duskregn                          : Heavy drizzle\n: Kraftig duskregn og regn                  : Heavy drizzle and rain\n: Kraftig underkjølt ukjent nedbør          : Heavy freezing unknown precipitation\n: Kraftig hagl med tordenvær                : Heavy hail with thunderstorm\n: Kraftige ispellets                        : Heavy ice pellets\n: Kraftig regn- og haglbyge                 : Heavy rain and hail shower\n: Kraftig regn og hagl med tordenvær        : Heavy rain and hail with thunderstorm\n: Kraftig byge med regn og små hagl         : Heavy rain and small hail shower\n: Kraftig regn og små hagl med tordenvær    : Heavy rain and small hail with thunderstorm\n: Kraftig regn og snø                       : Heavy rain and snow\n: Kraftig regn og snø med tordenvær         : Heavy rain and snow with thunderstorm\n: Kraftig regn med tordenvær                : Heavy rain with thunderstorm\n: Kraftig byge med små hagl                 : Heavy small hail shower\n: Kraftig snøbyge                           : Heavy snow shower\n: Kraftig snø med tordenvær                 : Heavy snow with thunderstorm\n: Iskrystaller                              : Ice crystals\n: Lett snøfokk                              : Light blowing snow\n: Lett duskregn og tåke                     : Light drizzle and fog\n: Lett duskregn og ispellets                : Light drizzle and ice pellets\n: Lett duskregn, regn og snø                : Light drizzle and rain and snow\n: Lett duskregn og regnbyge                 : Light drizzle and rain shower\n: Lett duskregn og regn med tordenvær       : Light drizzle and rain with thunderstorm\n: Lett duskregn og snø                      : Light drizzle and snow\n: Lett duskregn med tordenvær               : Light drizzle with thunderstorm\n: Lett underkjølt duskregn                  : Light freezing drizzle\n: Lett underkjølt duskregn og regn          : Light freezing drizzle and rain\n: Lett underkjølt duskregn og snø           : Light freezing drizzle and snow\n: Lett underkjølt tåke                      : Light freezing fog\n: Lett underkjølt regn og snø               : Light freezing rain and snow\n: Lett underkjølt ukjent nedbør             : Light freezing unknown precipitation\n: Lett haglbyge                             : Light hail shower\n: Lett iskrystaller                         : Light ice crystals\n: Lett ispellets                            : Light ice pellets\n: Lett regn og dis                          : Light rain and mist\n: Lett byge med små hagl                    : Light rain and small hail shower\n: Lett regn og små hagl med tordenvær       : Light rain and small hail with thunderstorm\n: Lett regn og snø                          : Light rain and snow\n: Lett regn- og snøbyge                     : Light rain and snow shower\n: Lett regn med tordenvær                   : Light rain with thunderstorm\n: Lett snø og ispellets                     : Light snow and ice pellets\n: Lett snø og små hagl                      : Light snow and small hail\n: Lett snøbyge                              : Light snow shower\n: Lett snø med tordenvær                    : Light snow with thunderstorm\n: Lett tordenvær                            : Light thunderstorm\n: Delvis tåke                               : Partial fog\n: Tåkebanker i nærheten                     : Patches of fog in vicinity\n: Lokalt lett regn med tordenvær            : Patchy light rain in area with thunder\n: Lokalt lett snø med tordenvær             : Patchy light snow in area with thunder\n: Regn og haglbyge                          : Rain and hail shower\n: Regn og hagl med tordenvær                : Rain and hail with thunderstorm\n: Regn og dis                               : Rain and mist\n: Regn og dis med tordenvær                 : Rain and mist with thunderstorm\n: Regn og snø                               : Rain and snow\n: Regn- og snøbyge                          : Rain and snow shower\n: Regn og snø med tordenvær                 : Rain and snow with thunderstorm\n: Regn i nærheten                           : Rain in vicinity\n: Regnbyge i nærheten                       : Rain shower in vicinity\n: Regn med tordenvær                        : Rain with thunderstorm\n: Sandstorm                                 : Sandstorm\n: Lav tåke                                  : Shallow fog\n: Lav dis                                   : Shallow mist\n: Byge                                      : Shower\n: Byge i nærheten                           : Shower in vicinity\n: Små hagl                                  : Small hail\n: Byge med små hagl                         : Small hail shower\n: Små hagl med tordenvær                    : Small hail with thunderstorm\n: Snø og ispellets                          : Snow and ice pellets\n: Snø og tåke                               : Snow and mist\n: Snøbyge                                   : Snow shower\n: Snø med tordenvær                         : Snow with thunderstorm\n: Vindkast                                  : Squalls\n: Tordenvær                                 : Thunderstorm\n: Ukjent nedbør                             : Unknown precipitation\n: Byge med ukjent nedbør                    : Unknown precipitation shower\n: Ukjent nedbør med tordenvær               : Unknown precipitation with thunderstorm\n: Vulkansk aske                             : Volcanic ash\n: Vulkansk aske i nærheten                  : Volcanic ash in vicinity\n: Utbredt støv                              : Widespread dust\n"
  },
  {
    "path": "share/translations/nl-help.txt",
    "content": "Gebruik:\n\n    $ curl wttr.in              # huidige locatie\n    $ curl wttr.in/muc          # weer op de luchthaven van München\n\nOndersteunde locatiesoorten:\n\n    /paris                      # stadsnaam\n    /~Eiffel+tower              # elke locatie (+ for spaties)\n    /Москва                     # Unicodenaam van elke locatie in elke taal\n    /muc                        # vliegveldcode (3 letters)\n    /@stackoverflow.com         # domeinnaam\n    /94107                      # gebiedscode\n    /-78.46,106.76              # GPS-coördinaten\n\nMaanstand informatie:\n\n    /moon                       # Maanstand (voeg ,+US of ,+France toe voor deze plekken)\n    /moon@2016-10-25            # Maanstand op deze datum (@2016-10-25)\n\nEenheden:\n\n    m                          # metriek (SI) (overal gebruikt als standaard behalve in US)\n    u                          # USCS (standaard in US)\n    M                          # laat windsnelheid in m/s zien\n\nBeeld opties:\n\n    0                          # alleen huidig weer\n    1                          # huidig weer + verwachting voor vandaag\n    2                          # huidig weer + verwachting voor vandaag en morgen\n    A                          # negeer User-Agent en forceer ANSI uitvoerformaat (terminal)\n    F                          # Toon niet de \"Follow\" regel\n    n                          # smalle versie (alleen dag en nacht)\n    q                          # stille versie (geen \"Weerbericht\" tekst)\n    Q                          # superstille versie (geen \"Weerbericht\", geen stadsnaam)\n    T                          # schakel terminalcodes uit (geen kleur)\n\nPNG opties:\n\n    /paris.png                  # genereert een PNG-bestand\n    ?p                          # voegt een rand toe rond de uitvoer\n    ?t                          # transparantie 150\n    transparency=...            # transparantie van 0 to 255 (255 is ondoorzichtig)\n    background=...              # achtergrondkleur in formaat RRGGBB, bijv. 00aaaa\n\n  Opties kunnen worden gecombineerd:\n\n      /Paris?0pq\n      /Paris?0pq&lang=fr\n      /Paris_0pq.png          # in PNG het bestandstype specificeren achter _\n      /Rome_0pq_lang=it.png   # lange opties worden gescheiden met _\n\nLokalisatie:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nOndersteunde talen:\n\n    FULL_TRANSLATION (supported)\n    PARTIAL_TRANSLATION (in progress)\n\nSpeciale URLs:\n\n\t/:help\t\t\t\t\t\t# toon helppagina\n\t/:bash.function\t\t# toon voorgestelde wttr() bash-functie\n\t/:translation\t\t\t# toon informatie van de vertalers\n\n"
  },
  {
    "path": "share/translations/nl.txt",
    "content": ": Zware regen en hagel met onweer                      : Heavy rain and hail with thunderstorm\n: Zware regen met onweer                               : Heavy rain with thunderstorm\n: Lichte regen en hagel met onweer                     : Light rain and hail with thunderstorm\n: Lichte regen en sneeuwbui                            : Light rain and snow shower\n: Lichte regen met onweer                              : Light rain with thunderstorm\n: Lichte sneeuwbui                                     : Light snow shower\n: Plaatselijke mist                                    : Partial fog\n: Regen en hagel met onweer                            : Rain and hail with thunderstorm\n: Regen met onweer                                     : Rain with thunderstorm\n: Lichte mist                                          : Shallow fog\n: Nevel                                                : Smoke\n: Windstoten                                           : Squalls\n: Onweer in de buurt                                   : Thunderstorm in vicinity\n: Sneeuw                                               : Snow\n: Regen                                                : Rain\n: Lichte regen, regenbuien                             : Light Rain, Rain Shower\n: Regenbuien                                           : Rain Shower\n: Plaatselijke mist                                    : Patches of fog\n: Motregen                                             : Drizzle\n: Lichte motregen                                      : Light drizzle\n: Laag stuifsneeuw                                     : Low drifting snow\n: Lichte regen en sneeuw                               : Light rain and snow\n: Buien in de buurt                                    : Shower in vicinity\n: Regen met onweer                                     : Rain with thunderstorm\n: Regen en sneeuwbuien                                 : Rain and snow shower\n: Onweer                                               : Thunderstorm\n: Motregen en regen                                    : Drizzle and rain\n: Hagel met onweer                                     : Hail with thunderstorm\n: Nevel                                                : Haze\n: Lichte motregen en regen                             : Light drizzle and rain\n: Lichte regen en korrelhagel/sneeuwpallets met onweer : Light rain and small hail/snow pallets with thunderstorm\n113: Helder                               : Clear\n113: Zonnig                               : Sunny\n116: Deels bewolkt                        : Partly cloudy\n119: Bewolkt                              : Cloudy\n122: Geheel bewolkt                       : Overcast\n143: Mist                                 : Mist\n176: Mogelijk plaatselijk regen           : Patchy rain possible\n179: Mogelijk plaatselijk sneeuw          : Patchy snow possible\n182: Mogelijk plaatselijk hagel           : Patchy sleet possible\n185: Mogelijk plaatselijk ijzel           : Patchy freezing drizzle possible\n200: Mogelijk een onweersbui              : Thundery outbreaks possible\n227: Sneeuwwinden                         : Blowing snow\n230: Sneeuwstorm                          : Blizzard\n248: Mist                                 : Fog\n260: Rijp                                 : Freezing fog\n263: Plaatselijk motregen                 : Patchy light drizzle\n266: Motregen                             : Light drizzle\n281: Ijzel                                : Freezing drizzle\n284: Zware ijzel                          : Heavy freezing drizzle\n293: Plaatselijk lichte regen             : Patchy light rain\n296: Lichte regen                         : Light rain\n299: Af en toe regen                      : Moderate rain at times\n302: Regen                                : Moderate rain\n305: Af en toe zware regen                : Heavy rain at times\n308: Zware regen                          : Heavy rain\n311: Lichte ijzel                         : Light freezing rain\n314: Zware ijzel                          : Moderate or heavy freezing rain\n317: Lichte hagel                         : Light sleet\n320: Zware hagel                          : Moderate or heavy sleet\n323: Plaatselijk lichte sneeuw            : Patchy light snow\n326: Lichte sneeuw                        : Light snow\n329: Plaatselijke sneeuw                  : Patchy moderate snow\n332: Sneeuw                               : Moderate snow\n335: Plaatselijk zware sneeuw             : Patchy heavy snow\n338: Zware sneeuw                         : Heavy snow\n350: Hagel                                : Ice pellets\n353: Lichte regenbuien                    : Light rain shower\n356: Regenbuien                           : Moderate or heavy rain shower\n359: Extreem zware regenbuien             : Torrential rain shower\n362: Lichte hagelbuien                    : Light sleet showers\n365: Hagelbuien                           : Moderate or heavy sleet showers\n368: Lichte sneeuwbuien                   : Light snow showers\n371: Sneeuwbuien                          : Moderate or heavy snow showers\n386: Plaatselijk lichte regen met onweeer : Patchy light rain with thunder\n389: Regen met onweer                     : Moderate or heavy rain with thunder\n392: Plaatselijk lichte sneeuw met onweer : Patchy light snow with thunder\n395: Sneeuw met onweer                    : Moderate or heavy snow with thunder\n\n"
  },
  {
    "path": "share/translations/nn.txt",
    "content": "113: Klart                                  : Clear\n113: Sol                                    : Sunny\n116: Til dels skya                          : Partly cloudy\n119: Skya                                   : Cloudy\n122: Overskya                               : Overcast\n143: Dis                                    : Mist\n176: Sjansar for skiftande regn             : Patchy rain possible\n179: Sjansar for skiftande snø              : Patchy snow possible\n182: Sjansar for skiftande sludd            : Patchy sleet possible\n185: Sjansar for skiftande, kald duskregn   : Patchy freezing drizzle possible\n200: Sjansar for tore                       : Thundery outbreaks possible\n227: Snøfokk                                : Blowing snow\n230: Snøstorm                               : Blizzard\n248: Tåke                                   : Fog\n260: Kald tåke                              : Freezing fog\n263: Skiftande, lett duskregn               : Patchy light drizzle\n266: Lett duskregn                          : Light drizzle\n281: Kald duskregn                          : Freezing drizzle\n284: Tung, kald duskregn                    : Heavy freezing drizzle\n293: Skiftande, lett regn                   : Patchy light rain\n296: Lett regn                              : Light rain\n299: Til tider noko regn                    : Moderate rain at times\n302: Noko regn                              : Moderate rain\n305: Til tider tung regn                    : Heavy rain at times\n308: Tung regn                              : Heavy rain\n311: Lett. kald regn                        : Light freezing rain\n314: Moderat eller tung, kald regn          : Moderate or heavy freezing rain\n317: Lett sludd                             : Light sleet\n320: Moderat eller tung sludd               : Moderate or heavy sleet\n323: Skiftande, lett snø                    : Patchy light snow\n326: Lett snø                               : Light snow\n329: Skiftande, moderat snø                 : Patchy moderate snow\n332: Noko snø                               : Moderate snow\n335: Skiftande, kraftige snøfall            : Patchy heavy snow\n338: Kraftige snøfall                       : Heavy snow\n350: Hagl                                   : Ice pellets\n353: Lett regnskur                          : Light rain shower\n356: Moderat eller tung regnskur            : Moderate or heavy rain shower\n359: Styrtregn                              : Torrential rain shower\n362: Lette sluddbyger                       : Light sleet showers\n365: Moderate eller tunge sluddbyger        : Moderate or heavy sleet showers\n368: Lette snøbyger                         : Light snow showers\n371: Moderate eller tunge snøbyger          : Moderate or heavy snow showers\n386: Skiftande, lett regn med tore          : Patchy light rain with thunder\n389: Moderat eller tung regn med tore       : Moderate or heavy rain with thunder\n392: Skiftande, lett snø med tore           : Patchy light snow with thunder\n395: Moderat eller tung snø med tore        : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/oc-help.txt",
    "content": "Usatge:\n\n    $ curl wttr.in          # emplaçament actual\n    $ curl wttr.in/cdg      # metèo a l'aeropòrt de Paris - Charles de Gaulle\n\nTypes d'emplacements acceptés:\n\n    /toulouse               # nom de la vila\n    /~Eiffel+tower          # emplaçament qual que siá\n    /Москва                 # nom Unicode o emplaçament qual que siá dins quala que siá lenga\n    /muc                    # còde aeropòrt (3 letras)\n    /@stackoverflow.com     # nom de domeni\n    /94107                  # còde postal (sonque pels Estats Units)\n    /-78.46,106.79          # coordenadas GPS\n\nEmplacements particuliers:\n\n    /moon                   # passas de la luna (ajustar ,+US o ,+France per accedir a las vilas del meteis nom)\n    /moon@2016-10-25        # passas de la luna per aquesta data (@2016-10-25)\n\nUnitats:\n\n    ?m                      # sistèma metric (per defaut pertot levat als Estats Units d d'America)\n    ?u                      # USCS (per defaut pels Estats-Units d'America)\n    ?M                      # afichar la velocitat del vent en m/s\n\nOpcion d'afichatge:\n\n    ?0                      # uèi solament\n    ?1                      # uèi + deman\n    ?2                      # uèi + 2 jorns\n    ?n                      # version corta (sonque pel jorn e la nuèch)\n    ?q                      # version silenciosa (cap d'entèsta \"Previsions metèo per\")\n    ?Q                      # version super-silencieuse (pas d'en-tête \"Prévisions météo pour\", pas de nom de la ville)\n    ?T                      # sequéncias d'ecapament pels terminals desactivadas (cap de colors)\n\nOpcions PNG:\n\n    /paris.png              # gnèra un fichièr PNG\n    ?p                      # ajuta un quadre altorn de la sortida\n    ?t                      # transparéncia 150 (transparence 150)\n    transparency=...        # transparéncia de 0 fins a 255 (255 = cap de transparéncia)\n\nCombinar las opcions:\n\n    /Toulouse?0pq\n    /Toulouse?0pq&lang=oc\n    /Toulouse_0pq.png        # dins lo mòde PNG las opcions son especificadas après _\n    /Rome_0pq_lang=it.png   # las opcions longas son separadas per de underscores _\n\nLocalizacion:\n\n    $ curl fr.wttr.in/Toulouse\n    $ curl wttr.in/toulouse?lang=oc\n    $ curl -H \"Accept-Language: oc\" wttr.in/toulouse\n\nLengas suportadas:\n\n    FULL_TRANSLATION (Support complèt)\n    PARTIAL_TRANSLATION (Support incomplèt)\n\nURLs particularas:\n\n    /:help                  # mostra aquesta pagina\n    /:bash.function         # foncion bash recomandada wttr()\n    /:translation           # mostra las informacions sus la traduccion de wttr.in\n"
  },
  {
    "path": "share/translations/oc.txt",
    "content": ": Pluèja                                           : Rain\n: Plugeta, Raissas                                 : Light Rain, Rain Shower\n: Raissas                                          : Rain Shower\n113 : Temps clar                                   : Clear\n113 : Solelh                                       : Sunny\n116 : Nivolós en partida                           : Partly cloudy\n119 : Nivolós                                      : Cloudy\n122 : Ennivolat                                    : Overcast\n143 : Brumós                                       : Mist\n176 : Possiblas raissas esparpalhadas              : Patchy rain possible\n179 : Possiblas nevadas esparpalhadas              : Patchy snow possible\n182 : Possiblas nèus fondudas esparpalhadas        : Patchy sleet possible\n185 : Possiblas plovinas gelibrantas esparpalhadas : Patchy freezing drizzle possible\n200 : Auratges possibles                           : Thundery outbreaks possible\n227 : Nèu e vent                                   : Blowing snow\n230 : Blisard                                      : Blizzard\n248 : Fums                                         : Fog\n260 : Nèbla gelibranta                             : Freezing fog\n263 : Plovina leugièra esparpalhada                : Patchy light drizzle\n266 : Plovina leugièra                             : Light drizzle\n281 : Plovina gelibranta                           : Freezing drizzle\n284 : Fòrta plovina gelibranta                     : Heavy freezing drizzle\n293 : Plugeta fina                                 : Patchy light rain\n296 : Plovina                                      : Light rain\n299 : Pluèja moderada intermitenta                 : Moderate rain at times\n302 : Pluèja moderada                              : Moderate rain\n305 : Forte pluie intermittente                    : Heavy rain at times\n308 : Raissa                                       : Heavy rain\n311 : Pluie verglaçante légère                     : Light freezing rain\n314 : Pluie verglaçante modérée à forte            : Moderate or heavy freezing rain\n317 : Aiganèu leugièra                             : Light sleet\n320 : Aiganèu moderada o fòrta                     : Moderate or heavy sleet\n323 : Nevada esparpalhada e leugièra               : Patchy light snow\n326 : Nevada leugièra                              : Light snow\n329 : Nevada esparpalhada parciala                 : Patchy moderate snow\n332 : Nevada moderada                              : Moderate snow\n335 : Nevada fòrta parciala                        : Patchy heavy snow\n338 : Nevada fòrta                                 : Heavy snow\n350 : Pèiras de glaça                              : Ice pellets\n353 : Pluèja leugièra                              : Light rain shower\n356 : Pluèja moderada a fòrta                      : Moderate or heavy rain shower\n359 : Pluèja torrenciala                           : Torrential rain shower\n362 : Granissa leugièra                            : Light sleet showers\n365 : Granissa moderada a fòrta                    : Moderate or heavy sleet showers\n368 : Nevadas leugièra                             : Light snow showers\n371 : Granissa moderada a violenta                 : Moderate or heavy snow showers\n386 : Pluèja auratjosa leugièra esparpalhada       : Patchy light rain with thunder\n389 : Pluèja auratjosa moderada a violenta         : Moderate or heavy rain with thunder\n392 : Nevada auratjosa esparpalhada e leugièra     : Patchy light snow with thunder\n395 : Nevada auratjosa moderada a violenta         : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/pl-help.txt",
    "content": "Użycie:\n\n    $ curl wttr.in          # aktualna lokalizacja\n    $ curl wttr.in/waw      # wybrana lokalizacja (WAW - Lotnisko Okęcie)\n\nOpcje wyboru lokalizacji:\n\n    /paris                  # miasto\n    /~Eiffel+tower          # miejsce\n    /Москва                 # nazwa miasta w dowolnym języku (jako Unicode string)\n    /waw                    # kod lotniska IATA (3 znaki)\n    /@stackoverflow.com     # domena\n    /94107                  # kod obszaru (tylko w USA)\n    /-78.46,106.79          # współrzędne geograficzne\n\nSpecjalne miejsca:\n\n    /moon                   # faza księżyca (używając n.p. ,+US lub ,+France zostanie wyświetlona faza dla podanego miejsca)\n    /moon@2016-10-25        # faza księżyca danego dnia (@2016-10-25)\n\nJednostki:\n\n    ?m                      # system metryczny (SI) (standard poza USA)\n    ?u                      # USCS (standard w USA)\n    ?M                      # Prędkość wiatru w m/s\n\nUstawienia wyświetlania:\n\n    ?0                      # Pokaż jedynie aktualną pogodę\n    ?1                      # Pokaż pogodę na jutro\n    ?2                      # Pokaż pogodę na pojutrze\n    ?A                      # Zignoruj User-Agent i wymuś format wyjścia ANSI (terminal)\n    ?F                      # nie pokazuj linii \"Subskrybuj\"\n    ?n                      # Wersja kompaktowa (tylko noc i dzień)\n    ?q                      # Wersja okrojona (bez tekstu 'Pogoda w')\n    ?Q                      # Wersja bardziej okrojona (bez tekstu 'Pogoda w' i nazwy miasta)\n    ?T                      # Wersja jednokolorowa\n\nOpcje PNG:\n\n    /paris.png              # Generuje plik PNG\n    ?p                      # Dodaje obramowanie do obrazka\n    ?t                      # Przezroczystość 150\n    transparency=...        # Przezroczystość między 0 a 255 (255 = brak przezroczystości)\n    background=...          # Kolor tła w formie RRGGBB\n\nOpcje mogą być ze sobą łączone:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # jeśli generujemy obrazek PNG, to te opcje podajemy po _ (znaku podkreślenia)\n    /Rome_0pq_lang=it.png   # _ (znakiem podkreślenia) oddzielamy opcje od siebie\n\nLokalizacja:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nObsługiwane języki:\n\n    FULL_TRANSLATION (obsługiwane)\n    PARTIAL_TRANSLATION (w tłumaczeniu)\n\nStrony specjalne:\n\n    /:help                  # wyświetla tę stronę\n    /:bash.function         # wyświetla proponowaną funkcję `wttr()` dla powłoki bash\n    /:translation           # wyświetla informacje o tłumaczach\n"
  },
  {
    "path": "share/translations/pl.txt",
    "content": "113: Bezchmurnie                                              : Clear\n113: Słonecznie                                               : Sunny\n116: Lekkie zachmurzenie                                      : Partly cloudy\n119: Zachmurzenie                                             : Cloudy\n122: Całkowite zachmurzenie                                   : Overcast\n143: Zamglenie                                                : Mist\n176: Możliwe miejscowe opady deszczu                          : Patchy rain possible\n179: Możliwe miejscowe opady śniegu                           : Patchy snow possible\n182: Możliwe miejscowe opady deszczu ze śniegiem              : Patchy sleet possible\n185: Możliwe miejscowe opady marznącego deszczu               : Patchy freezing drizzle possible\n200: Możliwa burza                                            : Thundery outbreaks possible\n227: Zawieja śnieżna                                          : Blowing snow\n230: Śnieżyca                                                 : Blizzard\n248: Mgła                                                     : Fog\n260: Marznąca mgła                                            : Freezing fog\n263: Przelotna mżawka                                         : Patchy light drizzle\n266: Mżawka                                                   : Light drizzle\n281: Marznąca mżawka                                          : Freezing drizzle\n284: Marznąca mżawka                                          : Heavy freezing drizzle\n293: Przelotne lekkie opady deszczu                           : Patchy light rain\n296: Lekkie opady deszczu                                     : Light rain\n299: Przelotne umiarkowane opady deszczu                      : Moderate rain at times\n302: Umiarkowane opady deszczu                                : Moderate rain\n305: Przelotne silne opady deszczu                            : Heavy rain at times\n308: Silne opady deszczu                                      : Heavy rain\n311: Lekki marznący deszcz                                    : Light freezing rain\n314: Umiarkowany lub silny marznący deszcz                    : Moderate or heavy freezing rain\n317: Lekki deszcz ze śniegiem                                 : Light sleet\n320: Umiarkowany lub silny deszcz ze śniegiem                 : Moderate or heavy sleet\n323: Miejscowe lekkie opady śniegu                            : Patchy light snow\n326: Lekkie opady śniegu                                      : Light snow\n329: Miejscowe umiarkowane opady śniegu                       : Patchy moderate snow\n332: Umiarkowane opady śniegu                                 : Moderate snow\n335: Miejscowe silne opady śniegu                             : Patchy heavy snow\n338: Silne opady śniegu                                       : Heavy snow\n350: Gradobicie                                               : Ice pellets\n353: Lekkie opady deszczu                                     : Light rain shower\n356: Umiarkowane lub silne opady deszczu                      : Moderate or heavy rain shower\n359: Oberwanie chmury                                         : Torrential rain shower\n362: Lekki deszcz ze śniegiem                                 : Light sleet showers\n365: Umiarkowany lub silny deszcz ze śniegiem                 : Moderate or heavy sleet showers\n368: Lekkie opady śniegu                                      : Light snow showers\n371: Umiarkowane lub silne opady śniegu                       : Moderate or heavy snow showers\n386: Miejscowe lekkie opady deszczu i burza z piorunami       : Patchy light rain with thunder\n389: Umiarkowane lub silne opady deszczu i burza z piorunami  : Moderate or heavy rain with thunder\n392: Miejscowe lekkie opady śniegu i burza z piorunami        : Patchy light snow with thunder\n395: Umiarkowane lub silne opady śniegu i burza z piorunami   : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/pt-br-help.txt",
    "content": "Uso:\n\n    $ curl wttr.in          # apresenta o clima na sua localização atual\n    $ curl wttr.in/muc      # apresenta o clima no aeroporto de Munique\n\nTipos de locais suportados:\n\n    /paris                  # o nome de uma cidade\n    /~Eiffel+tower          # o nome de um lugar famoso (\"+\" para espaços)\n    /Москва                 # o nome Unicode de qualquer lugar em qualquer idioma\n    /muc                    # o código de um aeroporto (3 letras)\n    /@stackoverflow.com     # o nome de um domínio web\n    /94107                  # um código de área\n    /-78.46,106.79          # as coordenadas do GPS de um lugar\n\nLugares especiais:\n\n    /moon                   # as fases da Lua (adicione \"+US\" ou \"+France\" para ver as fases da lua nesse lugares)\n    /moon@2016-10-25        # as fases da Lua em uma determinada data (25/10/2016)\n\nUnidades:\n\n    m                       # Sistema Internacional de Unidades (SI) (o padrão em todos os lugares exceto nos EUA)\n    u                       # Sistema Unificado de Clasificaçāo de Solo ou USCS (o padrão nos EUA)\n    M                       # mostra a velocidade do vento em m/s\n\nOpçōes de visualização:\n\n    0                       # somente o clima atual\n    1                       # o clima atual + a previsão de 1 dia\n    2                       # o clima atual + a previsão de 2 dias\n    A\t\t\t    # ignora o User-Agent e força o formato de saída ANSI (terminal)\n    d\t\t\t    # restringe a saída aos caracteres da fonte padrão do console\n    F\t\t\t    # não imprime a linha \"Seguir\"\n    n                       # versão curta (só o dia e a noite)\n    q                       # versão simples (sem o texto de \"Previsão do Tempo\")\n    Q                       # versão super simples (sem \"Previsão do Tempo\" e sem o nome da cidade)\n    T                       # imprime uma versão sem cores\n\nOpçōes de PNG:\n\n    /paris.png              # gera uma imagem PNG\n    p                       # acrescenta uma borda ao redor da imagem\n    t                       # define a transparência em 150\n    transparency=...        # transparência de 0 a 255 (255 = sem transparência)\n\nAs opções podem ser usadas em conjunto: (observe que para as opções de PNG, o nome do local deve anteceder um \"_\" e para as demais opções \"?\")\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # em PNG as opções se especificam depois do caracter _\n    /Rome_0pq_lang=it.png   # uma longa sequência de opções podem ser separadas pelo caracter _\n\nTradução:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nIdiomas suportadas:\n\n    FULL_TRANSLATION (suportadas)\n    PARTIAL_TRANSLATION (em andamento)\n\nURLs especiais:\n\n    /:help                  # mostra esta página\n    /:bash.function         # sugere uma função wttr() em bash\n    /:translation           # mostra informações a respeito dos tradutores\n"
  },
  {
    "path": "share/translations/pt-br.txt",
    "content": "113: Limpo                                        :  Clear\n113: Ensolarado                                   :  Sunny\n116: Céu com nuvens\t                          :  Partly cloudy\n119: Encoberto                                    :  Cloudy\n122: Nublado                                      :  Overcast\n143: Névoa                                        :  Mist\n176: Chuva fraca próxima \t\t\t  :  Patchy rain nearby\n176: Possível chuva fraca                         :  Patchy rain possible\n179: Possível neve fraca   \t                  :  Patchy snow possible\n182: Possível granizo \t                          :  Patchy sleet possible\n185: Possível garoa gelada                        :  Patchy freezing drizzle possible\n200: Chuvarada próxima  \t\t          :  Thundery outbreaks in nearby\n200: Possível chuvarada       \t\t          :  Thundery outbreaks possible\n227: Neve com vento                               :  Blowing snow\n230: Nevasca                                      :  Blizzard\n248: Nevoeiro                                     :  Fog\n260: Névoa congelante                             :  Freezing fog\n263: Garoa irregular                              :  Patchy light drizzle\n266: Garoa                                        :  Light drizzle\n281: Garoa gelada                                 :  Freezing drizzle\n284: Garoa muito gelada                           :  Heavy freezing drizzle\n293: Garoa irregular                              :  Patchy light rain\n296: Garoa                                        :  Light rain\n299: Chuva média ocasional                        :  Moderate rain at times\n302: Chuva média\t\t\t\t  :  Moderate rain\n305: Chuva forte ocasional                        :  Heavy rain at times\n308: Chuva forte                                  :  Heavy rain\n311: Garoa gelada                                 :  Light freezing rain\n314: Chuva forte/média gelada                     :  Moderate or heavy freezing rain\n317: Granizo fraco                                :  Light sleet\n320: Granizo forte/médio                          :  Moderate or heavy sleet\n323: Neve fraca irregular                         :  Patchy light snow\n326: Neve fraca                                   :  Light snow\n329: Neve média irregular                         :  Patchy moderate snow\n332: Neve média                                   :  Moderate snow\n335: Neve forte irregular                         :  Patchy heavy snow\n338: Neve forte                                   :  Heavy snow\n350: Pelotas de gelo                              :  Ice pellets\n353: Chuva fraca                                  :  Light rain shower\n356: Chuva forte/média \t                          :  Moderate or heavy rain shower\n359: Chuva torrencial                             :  Torrential rain shower\n362: Chuva de granizo fraco                       :  Light sleet showers\n365: Chuva de granizo forte/média                 :  Moderate or heavy sleet showers\n368: Chuva de neve fraca                          :  Light snow showers\n371: Chuva de neve forte/média  \t          :  Moderate or heavy snow showers\n386: Garoa irregular com trovão                   :  Patchy light rain with thunder\n389: Chuva forte/média com trovão  \t          :  Moderate or heavy rain in area with thunder\n389: Chuva forte/média com trovão                 :  Moderate or heavy rain with thunder\n392: Neve fraca com trovão                        :  Patchy light snow with thunder\n395: Neve forte/média com trovão próxima          :  Moderate or heavy snow in area with thunder\n395: Neve forte/média com trovão \t          :  Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/pt-help.txt",
    "content": "Utilização:\n\n    $ curl wttr.in          # o clima na sua localização atual\n    $ curl wttr.in/muc      # o clima no aeroporto de Munique\n\nTipos de localização suportados:\n\n    /paris                  # o nome de uma cidade\n    /~Eiffel+tower          # o nome de um lugar famoso (+ para espaços)\n    /Москва                 # o nome Unicode de qualquer lugar em qualquer idioma\n    /muc                    # o código de um aeroporto (3 letras)\n    /@stackoverflow.com     # o nome de um domínio web\n    /94107                  # um código de área\n    /-78.46,106.79          # coordenadas do GPS\n\nInformações sobre as fases da lua:\n\n    /moon                   # A fase da lua (acrescente ,+US ou ,+France para estas cidades)\n    /moon@2016-10-25        # A fase da lua numa determinada data (@2016-10-25)\n\nUnidades:\n\n    m                       # sistema métrico (SI) (usado por omissão em todos os lugares exceto nos EUA)\n    u                       # sistema Unificado de Clasificaçāo de Solo ou USCS (usado por omissão nos EUA)\n    M                       # mostrar a velocidade do vento em m/s\n\nOpçōes de visualização:\n\n    0                       # apenas o clima atual\n    1                       # o clima atual + a previsão de hoje\n    2                       # o clima atual + as previsões de hoje + amanhã\n    A                       # ignora User-Agent e força output ANSI (terminal)\n    d                       # restringe o output a glifos da fonte padrão da consola\n    F                       # não mostra a linha \"Segue\"\n    n                       # versão curta (só o dia e a noite)\n    q                       # versão silenciosa (sem o texto de \"Previsão do Tempo\")\n    Q                       # versão super-silenciosa (sem \"Previsão do Tempo\" e o nome da cidade)\n    T                       # desliga as sequências de terminal (sem cores)\n\nOpçōes de PNG:\n\n    /paris.png              # gera uma imagem PNG\n    p                       # acrescenta uma borda ao redor da imagem\n    t                       # transparência 150\n    transparency=...        # transparência de 0 a 255 (255 = sem transparência)\n    background=...          # cor de fundo na forma RRGGBB, por exemplo, 00aaaa\n\nAs opções podem ser usadas em conjunto:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # em PNG as opções especificam-se depois do caracter _\n    /Rome_0pq_lang=it.png   # opções longas podem ser separadas com um caracter _\n\nLocalizaçāo:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nIdiomas suportados:\n\n    FULL_TRANSLATION (suportadas)\n    PARTIAL_TRANSLATION (em curso)\n\nURLs especiais:\n\n    /:help                  # mostra esta página\n    /:bash.function         # mostra uma função bash wttr() recomendada\n    /:translation           # mostra informação a respeito dos tradutores\n\n"
  },
  {
    "path": "share/translations/pt.txt",
    "content": "113: Limpo                                        :  Clear\n113: Ensolarado                                   :  Sunny\n116: Céu com nuvens                               :  Partly cloudy\n119: Encoberto                                    :  Cloudy\n122: Nublado                                      :  Overcast\n143: Névoa                                        :  Mist\n176: Chuva fraca nas proximidades                 :  Patchy rain nearby\n176: Possibilidade de chuva irregular             :  Patchy rain possible\n179: Possibilidade de neve irregular              :  Patchy snow possible\n182: Possibilidade de granizo                     :  Patchy sleet possible\n185: Possibilidade de chuvisco gelado             :  Patchy freezing drizzle possible\n200: Trovoada nas proximidades                    :  Thundery outbreaks in nearby\n200: Possibilidade de trovoada                    :  Thundery outbreaks possible\n227: Neve com vento                               :  Blowing snow\n230: Nevasca                                      :  Blizzard\n248: Nevoeiro                                     :  Fog\n260: Nevoeiro gelado                              :  Freezing fog\n263: Chuvisco irregular                           :  Patchy light drizzle\n266: Chuviscos                                    :  Light drizzle\n281: Chuvisco gelado                              :  Freezing drizzle\n284: Chuvisco muito gelado                        :  Heavy freezing drizzle\n293: Chuvisco irregular                           :  Patchy light rain\n296: Chuva fraca                                  :  Light rain\n299: Chuva moderada ocasionalmente                :  Moderate rain at times\n302: Chuva moderada                               :  Moderate rain\n305: Chuva forte ocasional                        :  Heavy rain at times\n308: Chuva forte                                  :  Heavy rain\n311: Chuvisco gelado                              :  Light freezing rain\n314: Chuva moderada ou forte gelada               :  Moderate or heavy freezing rain\n317: Granizo fraco                                :  Light sleet\n320: Granizo moderado ou forte                    :  Moderate or heavy sleet\n323: Neve fraca irregular                         :  Patchy light snow\n326: Neve fraca                                   :  Light snow\n329: Neve moderada irregular                      :  Patchy moderate snow\n332: Neve moderada                                :  Moderate snow\n335: Neve forte irregular                         :  Patchy heavy snow\n338: Neve forte                                   :  Heavy snow\n350: Pelotas de gelo                              :  Ice pellets\n353: Chuva fraca                                  :  Light rain shower\n356: Chuva moderada ou forte                      :  Moderate or heavy rain shower\n359: Chuva torrencial                             :  Torrential rain shower\n362: Chuva de granizo fraco                       :  Light sleet showers\n365: Chuvas moderadas ou fortes de granizo        :  Moderate or heavy sleet showers\n368: Chuva de neve fraca                          :  Light snow showers\n371: Chuvas moderadas ou fortes de neve           :  Moderate or heavy snow showers\n386: Chuva fraca e irregular com trovoada         :  Patchy light rain with thunder\n389: Chuva moderada ou forte na área com trovoada :  Moderate or heavy rain in area with thunder\n389: Chuva moderada ou forte com trovoada         :  Moderate or heavy rain with thunder\n392: Neve fraca com trovoada                      :  Patchy light snow with thunder\n395: Neve moderada ou forte na área com trovoada  :  Moderate or heavy snow in area with thunder\n395: Neve moderada ou forte com trovoada          :  Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/ro-help.txt",
    "content": "Utilizare:\n\n    $ curl wttr.in          # localizare curentă\n    $ curl wttr.in/otp      # Aeroportul Internațional Henri Coandă (OTP)\n\nTipuri de localizări acceptate:\n\n    /Cluj                   # numele localității\n    /~coloana+infinitului   # locuri binecunoscute sau puncte de interes\n    /Москва                 # nume Unicode în orice limbă\n    /otp                    # cod aeroport (3 litere)\n    /@stackoverflow.com     # nume de domeniu\n    /94107                  # cod poștal (doar pentru Statele Unite)\n    /-78.46,106.79          # coordonate GPS\n\nLocalizări speciale:\n\n    /moon                   # faza lunii (adăugați ,+US sau ,+France pentru a arăta orașele cu acest nume)\n    /moon@2016-10-25        # faza lunii într-o anumită dată (@2016-10-25)\n\nUnități de măsură:\n\n    ?m                      # sistem metric (implicit, mai puțin pentru Statele Unite ale Americii)\n    ?u                      # USCS (implicit pentru Statele Unite ale Americii)\n    ?M                      # afișează viteza vântului în m/s\n\nOpțiuni de afișare:\n\n    ?0                      # azi\n    ?1                      # azi și mâine\n    ?2                      # azi, mâine și poimâine\n    ?n                      # doar ziua și noaptea\n    ?q                      # fără antet \"Prognoza meteo pentru\"\n    ?Q                      # fără antet \"Prognoza meteo pentru\", fără numele localității\n    ?T                      # fără coduri speciale în terminal (fără culori)\n\nOpțiuni PNG:\n\n    /Băicoi.png             # generează un fișier PNG\n    ?p                      # cu chenar\n    ?t                      # cu transparență 150\n    transparency=...        # cu transparență în intervalul [0-255] (255 = fără transparență)\n\nCombinarea opțiunilor:\n\n    /Lehliu-Gară?0q\n    /Vaslui?0q&lang=ro\n    /Videle_0pq.png         # în modul PNG opțiunile se specifică după _\n    /Roma_0pq_lang=it.png   # opțiunile cu nume lung se separă prin _\n\nLimba de afișare:\n\n    $ curl ro.wttr.in/Tărtășești\n    $ curl wttr.in/Paris?lang=fr\n    $ curl -H \"Accept-Language: de\" wttr.in/berlin\n\nLimbi suportate:\n\n    FULL_TRANSLATION (Suport complet)\n    PARTIAL_TRANSLATION (Suport incomplet)\n\nURL-uri speciale:\n\n    /:help                  # afișează această pagină\n    /:bash.function         # funcție bash wttr()\n    /:translation           # afișează informații despre traducerile din wttr.in\n\n"
  },
  {
    "path": "share/translations/ro.txt",
    "content": "113: Senin                                          :  Clear\n113: Însorit                                        :  Sunny\n116: Parțial înnorat                                :  Partly cloudy\n119: Înnorat                                        :  Cloudy\n122: Cer acoperit                                   :  Overcast\n143: Ceață                                          :  Mist\n176: Posibilă ploaie pe alocuri                     :  Patchy rain possible\n179: Posibilă ninsoare pe alocuri                   :  Patchy snow possible\n182: Posibilă lapoviță pe alocuri                   :  Patchy sleet possible\n185: Posibilă burniță înghețată pe alocuri          :  Patchy freezing drizzle possible\n200: Posibile tunete                                :  Thundery outbreaks possible\n227: Zăpadă în rafale                               :  Blowing snow\n230: Viscol                                         :  Blizzard\n248: Ceață                                          :  Fog\n260: Ceață înghețată                                :  Freezing fog\n263: Burniță ușoară pe alocuri                      :  Patchy light drizzle\n266: Burniță ușoară                                 :  Light drizzle\n281: Burniță înghețată                              :  Freezing drizzle\n284: Burnită înghețată abundentă                    :  Heavy freezing drizzle\n293: Ploaie ușoară pe alocuri                       :  Patchy light rain\n296: Ploaie ușoară                                  :  Light rain\n299: Momente de ploaie moderată                     :  Moderate rain at times\n302: Ploaie moderată                                :  Moderate rain\n305: Momente de ploaie torențială                   :  Heavy rain at times\n308: Ploaie torențială                              :  Heavy rain\n311: Ploaie înghețată ușoară                        :  Light freezing rain\n314: Ploaie înghețată moderată sau torențială       :  Moderate or heavy freezing rain\n317: Lapoviță ușoară                                :  Light sleet\n320: Lapoviță moderată sau torențială               :  Moderate or heavy sleet\n323: Ninsoare ușoară pe alocuri                     :  Patchy light snow\n326: Ninsoare ușoară                                :  Light snow\n329: Ninsoare moderată pe alocuri                   :  Patchy moderate snow\n332: Ninsoare moderată                              :  Moderate snow\n335: Ninsoare abundentă pe alocuri                  :  Patchy heavy snow\n338: Ninsoare abundentă                             :  Heavy snow\n350: Grindină                                       :  Ice pellets\n353: Averse de ploaie ușoară                        :  Light rain shower\n356: Averse de ploaie moderată sau torențială       :  Moderate or heavy rain shower\n359: Averse de ploaie torențială                    :  Torrential rain shower\n362: Averse de lapoviță ușoară                      :  Light sleet showers\n365: Averse de lapoviță moderată sau torențială     :  Moderate or heavy sleet showers\n368: Averse de ninsoare ușoară                      :  Light snow showers\n371: Averse de ninsoare moderată sau torențială     :  Moderate or heavy snow showers\n386: Ploi ușoare cu tunete pe alocuri               :  Patchy light rain with thunder\n389: Ploaie moderată sau furtună cu tunete          :  Moderate or heavy rain with thunder\n392: Ninsoare ușoară cu tunete pe alocuri           :  Patchy light snow with thunder\n395: Ninsoare moderată sau abundentă cu tunete      :  Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/ru-help.txt",
    "content": "Использование:\n\n    $ curl wttr.in          # текущее местоположение\n    $ curl wttr.in/svo      # погода в аэропорту Шереметьево (код ICAO: SVO)\n\nПоддерживаемые типы местоположений:\n\n    /paris                  # город\n    /~Eiffel+tower          # любое местоположение\n    /Москва                 # юникодное имя любого местоположения на любом языке\n    /muc                    # код аэропорта ICAO (3 буквы)\n    /@stackoverflow.com     # доменное имя\n    /94107                  # почтовый индекс (только для США)\n    /-78.46,106.79          # GPS-координаты\n\nСпециальные условные местоположения:\n\n    /moon                   # Фаза Луны (добавьте ,+US или ,+France для города Moon в США/Франции)\n    /moon@2016-10-25        # Фаза Луны для указанной даты (@2016-10-25)\n\nЕдиницы измерений:\n\n    ?m                      # метрические (СИ) (используются везде кроме США)\n    ?u                      # USCS (используются в США)\n    ?M                      # показывать скорость ветра в м/с\n\nОпции отображения:\n\n    ?0                      # только текущая погода\n    ?1                      # погода сегодня + 1 день\n    ?2                      # погода сегодня + 2 дня\n    ?n                      # узкая версия (только день и ночь)\n    ?q                      # тихая версия (без текста \"Прогноз погоды\")\n    ?Q                      # сверхтихая версия (без \"Прогноз погоды\", нет названия города)\n    ?T                      # отключить терминальные последовательности (без цветов)\n\nPNG-опции:\n\n    /paris.png              # сгенерировать PNG-файл\n    ?p                      # добавить рамочку вокруг\n    ?t                      # transparency=150 (прозрачность 150)\n    transparency=...        # прозрачность от 0 до 255 (255 = не прозрачный)\n\nОпции можно комбинировать:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # в PNG-запросах опции указываются после _\n    /Rome_0pq_lang=it.png   # длинные опции разделяются знаком подчёркивания _\n\nЛокализация:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nПоддерживаемые языки:\n\n    FULL_TRANSLATION (поддерживаются)\n    PARTIAL_TRANSLATION (в процессе)\n\nСпециальные страницы:\n\n    /:help                  # показать эту страницу\n    /:bash.function         # показать рекомендованную функцию wttr()\n    /:translation           # показать список переводчиков wttr.in\n\n"
  },
  {
    "path": "share/translations/ru.txt",
    "content": "   : Мгла в окрестностях                                               : Haze in vicinity                                                  :\n   : Сильный ливневой дождь со снегом                                  : Heavy rain and snow shower                                        :\n   : Сильный ливневой дождь                                            : Heavy rain shower                                                 :\n   : Слабая морось и снежные зёрна                                     : Light drizzle and snow grains                                     :\n   : Слабый ливневой дождь с дымкой                                    : Light rain and mist shower                                        :\n   : Слабый ливень из мелкого града/снежной крупы                      : Light small hail/snow pellets shower                              :\n   : Слабые ливневые осадки неустановленного вида                      : Light unknown precipitation shower                                :\n   : Гроза, дождь с мелким градом/снежной крупой                       : Rain and small hail/snow pellets with thunderstorm                :\n   : Ливневой снег в окрестностях                                      : Snow shower in vicinity                                           :\n   : Грозовая активность неподалёку                                    : Thundery outbreaks nearby                                         :\n   : Позёмка                                                           : Low drifting snow                                                 :\n   : Туман на ряде участков                                            : Patches of fog                                                    :\n   : Морось                                                            : Drizzle                                                           :\n   : Слабая морось и дождь                                             : Light drizzle and rain                                            :\n   : Снег                                                              : Snow                                                              :\n   : Дождь                                                             : Rain                                                              :\n   : Ливневый дождь                                                    : Rain Shower                                                       :\n   : Песчаная низовая метель                                           : Blowing sand                                                      :\n   : Повсеместная пылевая низовая метель                               : Blowing widespread dust                                           :\n   : Повсеместная пылевая низовая метель в окрестностях                : Blowing widespread dust in vicinity                               :\n   : Морось и туман                                                    : Drizzle and fog                                                   :\n   : Морось и дождь                                                    : Drizzle and rain                                                  :\n   : Ливневый дождь и морось                                           : Drizzle and rain shower                                           :\n   : Гроза с моросью                                                   : Drizzle with thunderstorm                                         :\n   : Пыльная буря                                                      : Dust storm                                                        :\n   : Туман в окрестностях                                              : Fog in vicinity                                                   :\n   : Переохлаждённая морось и дождь                                    : Freezing drizzle and rain                                         :\n   : Переохлаждённая дымка                                             : Freezing mist                                                     :\n   : Переохлаждённый дождь                                             : Freezing rain                                                     :\n   : Переохлаждённый дождь и снег                                      : Freezing rain and snow                                            :\n   : Переохлаждённые осадки неустановленного вида                      : Freezing unknown precipitation                                    :\n   : Воронкообразное облако в окрестностях                             : Funnel cloud in vicinity                                          :\n   : Ливень с градом                                                   : Hail shower                                                       :\n   : Гроза с градом                                                    : Hail with thunderstorm                                            :\n   : Мгла                                                              : Haze                                                              :\n   : Сильная низовая метель                                            : Heavy blowing snow                                                :\n   : Сильная морось                                                    : Heavy drizzle                                                     :\n   : Сильная морось и дождь                                            : Heavy drizzle and rain                                            :\n   : Сильные переохлаждённые осадки неустановленного вида              : Heavy freezing unknown precipitation                              :\n   : Гроза с сильным градом                                            : Heavy hail with thunderstorm                                      :\n   : Сильная ледяная крупа                                             : Heavy ice pallets                                                 :\n   : Сильный ливневой дождь с градом                                   : Heavy rain and hail shower                                        :\n   : Гроза с сильным дождём и градом                                   : Heavy rain and hail with thunderstorm                             :\n   : Сильный ливневой дождь с мелким градом/снежной крупой             : Heavy rain and small hail/snow pallets shower                     :\n   : Гроза, сильный дождь с мелким градом/снежной крупой               : Heavy rain and small hail/snow pallets with thunderstorm          :\n   : Сильный дождь со снегом                                           : Heavy rain and snow                                               :\n   : Гроза, сильный дождь со снегом/мелким градом/снежной крупой       : Heavy rain and snow and small hail/snow pallets with thunderstorm :\n   : Гроза с сильным дождём                                            : Heavy rain with thunderstorm                                      :\n   : Сильный ливень из мелкого града/снежной крупы                     : Heavy small hail/snow pallets shower                              :\n   : Гроза с сильным мелким градом/снежной крупой                      : Heavy small hail/snow pallets with thunderstorm                   :\n   : Сильный ливень из снега с мелким градом/снежной крупой            : Heavy snow and small hail/snow pallets shower                     :\n   : Гроза, сильный снег с мелким градом/снежной крупой                : Heavy snow and small hail/snow pallets with thunderstorm          :\n   : Сильный ливень из снега                                           : Heavy snow shower                                                 :\n   : Гроза, сильный снег                                               : Heavy snow with thunderstorm                                      :\n   : Осадки в виде кристаллов льда                                     : Ice crystals                                                      :\n   : Осадки в виде ледяной крупы                                       : Ice pallets                                                       :\n   : Слабая низовая метель                                             : Light blowing snow                                                :\n   : Слабая морось и туман                                             : Light drizzle and fog                                             :\n   : Слабая морось и ледяная крупа                                     : Light drizzle and ice pallets                                     :\n   : Слабая морось, дождь и снег                                       : Light drizzle and rain and snow                                   :\n   : Ливневый дождь и слабая морось                                    : Light drizzle and rain shower                                     :\n   : Гроза, слабая морось и дождь                                      : Light drizzle and rain with thunderstorm                          :\n   : Слабая морось, снег                                               : Light drizzle and snow                                            :\n   : Гроза, слабая морось                                              : Light drizzle with thunderstorm                                   :\n   : Слабая переохлаждённая морось                                     : Light freezing drizzle                                            :\n   : Слабая переохлаждённая морось и дождь                             : Light freezing drizzle and rain                                   :\n   : Слабая переохлаждённая морось и снег                              : Light freezing drizzle and snow                                   :\n   : Слабый переохлаждённый туман                                      : Light freezing fog                                                :\n   : Слабый переохлаждённый дождь и снег                               : Light freezing rain and snow                                      :\n   : Слабый переохлаждённый туман и снежные зёрна                      : Light freezing snow grains and fog                                :\n   : Слабые переохлаждённые осадки неустановленного вида               : Light freezing unknown precipitation                              :\n   : Слабый ливень из града                                            : Light hail shower                                                 :\n   : Слабое выпадение ледяных кристаллов                               : Light ice crystals                                                :\n   : Слабое выпадение ледяной крупы                                    : Light ice pallets                                                 :\n   : Слабый позёмок                                                    : Light low drifting                                                :\n   : Слабый позёмный снегоперенос                                      : Light low drifting snow                                           :\n   : Слабый ливневой дождь с градом                                    : Light rain and hail shower                                        :\n   : Гроза, слабый дождь с градом                                      : Light rain and hail with thunderstorm                             :\n   : Слабый дождь с ледяной крупой                                     : Light rain and ice pallets                                        :\n   : Слабый дождь и дымка                                              : Light rain and mist                                               :\n   : Слабый ливневой дождь с мелким градом/снежной крупой              : Light rain and small hail/snow pallets shower                     :\n   : Гроза, слабый дождь и мелкий град/снежная крупа                   : Light rain and small hail/snow pallets with thunderstorm          :\n   : Слабый дождь и снег                                               : Light rain and snow                                               :\n   : Слабый ливневой дождь с мелким градом/снежной крупой и снегом     : Light rain and snow and small hail/snow pallets shower            :\n   : Слабый дождь и снежные зёрна                                      : Light rain and snow grains                                        :\n   : Слабый ливневой дождь со снегом                                   : Light rain and snow shower                                        :\n   : Гроза, слабый дождь и снег                                        : Light rain and snow with thunderstorm                             :\n   : Гроза, слабый дождь                                               : Light rain with thunderstorm                                      :\n   : Слабый ливень                                                     : Light shower                                                      :\n   : Слабые ливни из ледяной крупы                                     : Light showers of ice pellets                                      :\n   : Слабые осадки из мелкого града/снежной крупы                      : Light small hail/snow pallets                                     :\n   : Слабые ливневые осадки из мелкого града/снежной крупы             : Light small hail/snow pallets shower                              :\n   : Гроза, слабые осадки из мелкого града/снежной крупы               : Light small hail/snow pallets with thunderstorm                   :\n   : Слабый снег с ледяной крупой                                      : Light snow and ice pallets                                        :\n   : Слабый снег с мелким градом/снежной крупой                        : Light snow and small hail/snow pallets                            :\n   : Слабый ливень из снега и мелкого града/снежной крупы              : Light snow and small hail/snow pallets shower                     :\n   : Гроза, снег с мелким градом/снежной крупой                        : Light snow and small hail/snow pallets with thunderstorm          :\n   : Слабые осадки в виде снега и снежных зёрен                        : Light snow and snow grains                                        :\n   : Слабые осадки в виде снежных зёрен                                : Light snow grains                                                 :\n   : Слабый ливневый снег                                              : Light snow shower                                                 :\n   : Гроза, слабые осадки в виде снега                                 : Light snow with thunderstorm                                      :\n   : Слабая гроза                                                      : Light thunderstorm                                                :\n   : Слабые осадки неустановленного вида                               : Light unknown precipitation                                       :\n   : Слабые сформированные пылевые/песчаные вихри                      : Light well-developed dust/sand whirls                             :\n   : Песчаный позёмок                                                  : Low drifting sand                                                 :\n   : Повсеместный пылевой позёмок                                      : Low drifting widespread dust                                      :\n   : Гроза с дымкой                                                    : Mist with thunderstorm                                            :\n   : Грозовая активность, сильный или умеренный дождь в окрестностях   : Moderate or heavy rain in area with thunder                       :\n   : Грозовая активность, сильный или умеренный снег в окрестностях    : Moderate or heavy snow in area with thunder                       :\n   : Местами туман                                                     : Partial fog                                                       :\n   : Туман на ряде участков в окрестностях                             : Patches of fog in vicinity                                        :\n   : Переохлаждённая морось на ряде участков неподалёку                : Patchy freezing drizzle nearby                                    :\n   : Грозовая активность, на ряде участков слабый дождь в окрестностях : Patchy light rain in area with thunder                            :\n   : Грозовая активность, на ряде участков слабый снег в окрестностях  : Patchy light snow in area with thunder                            :\n   : Дождь на ряде участков неподалёку                                 : Patchy rain nearby                                                :\n   : Мокрый снег на ряде участков неподалёку                           : Patchy sleet nearby                                               :\n   : Снег на ряде участков неподалёку                                  : Patchy snow nearby                                                :\n   : Ливневый дождь с градом                                           : Rain and hail shower                                              :\n   : Гроза, дождь с градом                                             : Rain and hail with thunderstorm                                   :\n   : Дождь и дымка                                                     : Rain and mist                                                     :\n   : Гроза, дождь и дымка                                              : Rain and mist with thunderstorm                                   :\n   : Ливневый дождь с мелким градом/снежной крупой                     : Rain and small hail/snow pallets shower                           :\n   : Гроза, дождь с мелким градом/снежной крупой                       : Rain and small hail/snow pallets with thunderstorm                :\n   : Дождь и снег                                                      : Rain and snow                                                     :\n   : Ливневый дождь с мелким градом/снежной крупой и снегом            : Rain and snow and small hail/snow pallets shower                  :\n   : Дождь со снежными зёрнами                                         : Rain and snow grains                                              :\n   : Ливневый дождь и снег                                             : Rain and snow shower                                              :\n   : Гроза, дождь и снег                                               : Rain and snow with thunderstorm                                   :\n   : Дождь в окрестностях                                              : Rain in vicinity                                                  :\n   : Ливневый дождь в окрестностях                                     : Rain shower in vicinity                                           :\n   : Гроза с дождём                                                    : Rain with thunderstorm                                            :\n   : Осадки в виде частиц песка                                        : Sand                                                              :\n   : Песчаная буря                                                     : Sandstorm                                                         :\n   : Приземный туман                                                   : Shallow fog                                                       :\n   : Приземная дымка                                                   : Shallow mist                                                      :\n   : Ливень                                                            : Shower                                                            :\n   : Ливень в окрестностях                                             : Shower in vicinity                                                :\n   : Осадки в виде мелкого града/снежной крупы                         : Small hail/snow pallets                                           :\n   : Ливневые осадки в виде мелкого града/снежной крупы                : Small hail/snow pallets shower                                    :\n   : Гроза, осадки в виде мелкого града/снежной крупы                  : Small hail/snow pallets with thunderstorm                         :\n   : Дым                                                               : Smoke                                                             :\n   : Осадки в виде снега и ледяной крупы                               : Snow and ice pallets                                              :\n   : Снег и дымка                                                      : Snow and mist                                                     :\n   : Ливневые осадки в виде снега и мелкого града/снежной крупы        : Snow and small hail/snow pellets shower                           :\n   : Гроза, осадки в виде снега и мелкого града/снежной крупы          : Snow and small hail/snow pallets with thunderstorm                :\n   : Снег и снежные зёрна                                              : Snow and snow grains                                              :\n   : Снежные зёрна                                                     : Snow grains                                                       :\n   : Ливневые осадки в виде снега                                      : Snow shower                                                       :\n   : Гроза, осадки в виде снега                                        : Snow with thunderstorm                                            :\n   : Шквал                                                             : Squalls                                                           :\n   : Гроза                                                             : Thunderstorm                                                      :\n   : Гроза в окрестностях                                              : Thunderstorm in vicinity                                          :\n   : Грозовая активность неподалёку                                    : Thundery outbreaks in nearby                                      :\n   : Осадки неустановленного вида                                      : Unknown precipitation                                             :\n   : Ливневые осадки неустановленного вида                             : Unknown precipitation shower                                      :\n   : Гроза с осадками неустановленного вида                            : Unknown precipitation with thunderstorm                           :\n   : Вулканическая пыль                                                : Volcanic ash                                                      :\n   : Вулканическая пыль в окрестностях                                 : Volcanic ash in vicinity                                          :\n   : Сформированные пылевые/песчаные вихри в окрестностях              : Well-developed dust/sand whirls in vicinity                       :\n   : Повсеместно пыль в воздухе                                        : Widespread dust                                                   :\n113: Ясно                                                              : Clear                                                             :\n113: Солнечно                                                          : Sunny                                                             :\n116: Переменная облачность                                             : Partly cloudy                                                     :\n119: Облачно                                                           : Cloudy                                                            :\n122: Пасмурно                                                          : Overcast                                                          :\n143: Дымка                                                             : Mist                                                              :\n176: На ряде участков возможен дождь                                   : Patchy rain possible                                              :\n179: На ряде участков возможен снег                                    : Patchy snow possible                                              :\n182: На ряде участков возможен мокрый снег                             : Patchy sleet possible                                             :\n185: На ряде участков возможна переохлаждённая морось                  : Patchy freezing drizzle possible                                  :\n200: Возможна грозовая активность                                      : Thundery outbreaks possible                                       :\n227: Снежная низовая метель                                            : Blowing snow                                                      :\n230: Близзард                                                          : Blizzard                                                          :\n248: Туман                                                             : Fog                                                               :\n260: Переохлаждённый туман                                             : Freezing fog                                                      :\n263: На ряде участков слабая морось                                    : Patchy light drizzle                                              :\n266: Слабая морось                                                     : Light drizzle                                                     :\n281: Переохлаждённая морось                                            : Freezing drizzle                                                  :\n284: Сильные осадки в виде переохлаждённой мороси                      : Heavy freezing drizzle                                            :\n293: На ряде участков слабый дождь                                     : Patchy light rain                                                 :\n296: Слабый дождь                                                      : Light rain                                                        :\n299: Временами умеренный дождь                                         : Moderate rain at times                                            :\n302: Умеренный дождь                                                   : Moderate rain                                                     :\n305: Временами сильный дождь                                           : Heavy rain at times                                               :\n308: Сильный дождь                                                     : Heavy rain                                                        :\n311: Слабый переохлаждённый дождь                                      : Light freezing rain                                               :\n314: Умеренный или сильный переохлаждённый дождь                       : Moderate or heavy freezing rain                                   :\n317: Слабый мокрый снег                                                : Light sleet                                                       :\n320: Умеренный или сильный мокрый снег                                 : Moderate or heavy sleet                                           :\n323: На ряде участков слабый снег                                      : Patchy light snow                                                 :\n326: Слабые осадки в виде снега                                        : Light snow                                                        :\n329: На ряде участков умеренный снегопад                               : Patchy moderate snow                                              :\n332: Умеренный снегопад                                                : Moderate snow                                                     :\n335: На ряде участков сильный снегопад                                 : Patchy heavy snow                                                 :\n338: Сильный снегопад                                                  : Heavy snow                                                        :\n350: Осадки в виде ледяной крупы                                       : Ice pellets                                                       :\n353: Слабый ливневой дождь                                             : Light rain shower                                                 :\n356: Сильный или умеренный ливневой дождь                              : Moderate or heavy rain shower                                     :\n359: Проливной ливневый дождь                                          : Torrential rain shower                                            :\n362: Слабый ливневой мокрый снег                                       : Light sleet showers                                               :\n365: Сильный или умеренный ливневой мокрый снег                        : Moderate or heavy sleet showers                                   :\n368: Слабые ливневые осадки в виде снега                               : Light snow showers                                                :\n371: Сильные или умеренные ливнёвые осадки в виде снега                : Moderate or heavy snow showers                                    :\n386: Грозовая активность, на ряде участков слабый дождь                : Patchy light rain with thunder                                    :\n389: Грозовая активность, сильный или умеренный дождь                  : Moderate or heavy rain with thunder                               :\n392: Грозовая активность, на ряде участков слабые осадки в виде снега  : Patchy light snow with thunder                                    :\n395: Грозовая активность, сильные или умеренные осадки в виде снега    : Moderate or heavy snow with thunder                               :\n"
  },
  {
    "path": "share/translations/sl.txt",
    "content": "113: Jasno                                      : Clear\n113: Sončno                                     : Sunny\n116: Delno oblačno                              : Partly cloudy\n119: Oblačno                                    : Cloudy\n122: Pretežno oblačno                           : Overcast\n143: Megleno                                    : Mist\n176: Možne plohe                                : Patchy rain possible\n179: Možno občasno sneženje                     : Patchy snow possible\n182: Možen žled                                 : Patchy sleet possible\n185: Možna pomrznjena rosa                      : Patchy freezing drizzle possible\n200: Možno neurje z grmenjem                    : Thundery outbreaks possible\n227: Snežno neurje                              : Blowing snow\n230: Snežno neurje                              : Blizzard\n248: Megla                                      : Fog\n260: Zmrznjena megla                            : Freezing fog\n263: Rahlo rosenje                              : Patchy light drizzle\n266: Rahel dež                                  : Light drizzle\n281: Zmrznjeno rosenje                          : Freezing drizzle\n284: Močno zmrznjeno rosenje                    : Heavy freezing drizzle\n293: Občasno rahel dež                          : Patchy light rain\n296: Rahel dež                                  : Light rain\n299: Občasno droben dež                         : Moderate rain at times\n302: Droben dež                                 : Moderate rain\n305: Občasno močan dež                          : Heavy rain at times\n308: Močan dež                                  : Heavy rain\n311: Rahel zmrznjen dež                         : Light freezing rain\n314: Zmrznjen dež                               : Moderate or heavy freezing rain\n317: Rahel žled                                 : Light sleet\n320: Žled                                       : Moderate or heavy sleet\n323: Občasno rahlo sneženje                     : Patchy light snow\n326: Rahel sneg                                 : Light snow\n329: Občasno rahlo sneženje                     : Patchy moderate snow\n332: Rahel sneg                                 : Moderate snow\n335: Občasno močan sneg                         : Patchy heavy snow\n338: Močan sneg                                 : Heavy snow\n350: Led                                        : Ice pellets\n353: Rahla ploha                                : Light rain shower\n356: Rahle ali močne plohe                      : Moderate or heavy rain shower\n359: Hudourniški dež                            : Torrential rain shower\n362: Rahel žled                                 : Light sleet showers\n365: Žled                                       : Moderate or heavy sleet showers\n368: Občasno rahlo sneženje                     : Light snow showers\n371: Rahle ali močne snežne padavine            : Moderate or heavy snow showers\n386: Občasno rahel dež z grmenjem               : Patchy light rain with thunder\n389: Dež z grmenjem                             : Moderate or heavy rain with thunder\n392: Občasen sneg z grmenjem                    : Patchy light snow with thunder\n395: Sneg z grmenjem                            : Moderate or heavy snow with thunder"
  },
  {
    "path": "share/translations/ta-help.txt",
    "content": "பயன்பாடு:\n\n    $ curl wttr.in          # தற்போதைய இடம்\n    $ curl wttr.in/cdg      # பாரிஸ் - சார்லஸ் டி கோல் விமான நிலையத்தில் வானிலை முன்னறிவிப்பு\n\nஏற்றுக்கொள்ளப்பட்ட வகைகள்:\n\n    /paris                  # நகரத்தின் பெயர்\n    /~Eiffel+tower          # எந்த இடம்\n    /Москва                 # யூனிகோட் பெயர் அல்லது எந்த மொழியிலும் எந்த இடம்\n    /muc                    # விமான நிலைய குறியீடு (3 எழுத்துகள்)\n    /@stackoverflow.com     # டொமைன் பெயர்\n    /94107                  # அஞ்சல் குறியீடு (அமெரிக்காவில் மட்டும்)\n    /-78.46,106.79          # ஜிபிஎஸ் ஒருங்கிணைப்புகள்\n\nசிறப்பு வகைகள்:\n\n    /moon                   # சந்திரனின் கட்டங்கள் (அதே பெயரில் உள்ள நகரங்களை அணுக, + அமெரிக்கா அல்லது + பிரான்ஸ் சேர்க்கவும்)\n    /moon@2016-10-25        # இந்த தேதிக்கான சந்திரனின் கட்டங்கள் (@2016-10-25)\n\nஅலகுகள்:\n\n    ?m                      # மெட்ரிக் அமைப்பு (அமெரிக்காவைத் தவிர எல்லா இடங்களிலும் இயல்புநிலை)\n    ?u                      # USCS (அமெரிக்க ஐக்கிய நாடுகளுக்கு இயல்புநிலை)\n    ?M                      # காற்றின் வேகத்தை m/s இல் காட்டுகிறது\n\nகாட்சி விருப்பம்:\n\n    ?0                      # இன்று மட்டும்\n    ?1                      # இன்று + நாளை\n    ?2                      # இன்று + 2 நாட்கள்\n    ?n                      # குறுகிய பதிப்பு (பகல் மற்றும் இரவு மட்டும்)\n    ?q                      # சைலண்ட் பதிப்பு (\"தலைப்புக்கான வானிலை முன்னறிவிப்பு\" இல்லை)\n    ?Q                      # சூப்பர்-சைலண்ட் பதிப்பு (\"வானிலை முன்னறிவிப்பு\" தலைப்பு இல்லை, நகரத்தின் பெயர் இல்லை)\n    ?T                      # முடக்கப்பட்ட டெர்மினல்களுக்கான தப்பிக்கும் காட்சிகள் (வண்ணங்கள் இல்லை)\n\nPNG விருப்பங்கள்:\n\n    /paris.png              # ஒரு PNG கோப்பை உருவாக்கவும்\n    ?p                      # வெளியீட்டைச் சுற்றி ஒரு சட்டத்தைச் சேர்க்கவும்\n    ?t                      # வெளிப்படைத்தன்மை 150\n    transparency=...        # 0 முதல் 255 வரை வெளிப்படைத்தன்மை (255 = வெளிப்படைத்தன்மை இல்லை)\n\nவிருப்பங்களை இணைக்கவும்:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # PNG பயன்முறையில் விருப்பங்கள் _ க்குப் பிறகு குறிப்பிடப்படுகின்றன\n    /Rome_0pq_lang=it.png   # நீண்ட விருப்பங்கள் அடிக்கோடிட்டால் பிரிக்கப்படுகின்றன _\n\nஇடம்:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nஆதரிக்கப்படும் மொழிகள்:\n\n    FULL_TRANSLATION (முழு மொழிபெயர்ப்பு)\n    PARTIAL_TRANSLATION (முழுமையற்ற மொழிபெயர்ப்பு)\n\nURLs குறிப்பாக:\n\n    /:help                  # இந்தப் பக்கத்தைக் காட்டவும்\n    /:bash.function         # பரிந்துரைக்கப்பட்ட bash செயல்பாடு wttr()\n    /:translation           # மொழிபெயர்ப்பு பற்றிய தகவலைக் காட்டுகிறது wttr.in\n"
  },
  {
    "path": "share/translations/ta.txt",
    "content": ": இடியுடன் கூடிய கனமழை மற்றும் ஆலங்கட்டி மழை          : Heavy rain and hail with thunderstorm\n: இடியுடன் கூடிய கனமழை                              : Heavy rain with thunderstorm\n: லேசான மழை மற்றும் இடியுடன் கூடிய ஆலங்கட்டி மழை      : Light rain and hail with thunderstorm\n: லேசான மழை மற்றும் பனி மழை                        : Light rain and snow shower\n: லேசான மழை மற்றும் இடியுடன் கூடிய மழை               : Light rain with thunderstorm\n: லேசான பனி மழை                                   : Light snow shower\n: பகுதி மூடுபனி                                       : Partial fog\n: இடியுடன் கூடிய ஆலங்கட்டி மழை                       : Rain and hail with thunderstorm\n: இடியுடன் கூடிய மழை                                : Rain with thunderstorm\n: லேசான மூடுபனி                                     : Shallow fog\n: புகை                                             : Smoke\n: பலமான காற்று                                      : Squalls\n: இடியுடன் கூடிய மழை அருகில்                          : Thunderstorm in vicinity\n: பனி                                              : Snow\n: மழை                                             : Rain\n: லேசான மழை, மழை பொழிவு                          : Light Rain, Rain Shower\n: மழை பொழிவு                                       : Rain Shower\n: மூடுபனி திட்டுகள்                                    : Patches of fog\n: தூறல்                                             : Drizzle\n: லேசான தூறல்                                      : Light drizzle\n: குறைந்த பனிப்பொழிவு                                : Low drifting snow\n: லேசான மழை மற்றும் பனி                             : Light rain and snow\n: அருகாமையில் மழை                                  : Shower in vicinity\n: இடியுடன் கூடிய மழை                                : Rain with thunderstorm\n: மழை மற்றும் பனி மழை                               : Rain and snow shower\n: இடியுடன் கூடிய மழை                                 : Thunderstorm\n: தூறல் மற்றும் மழை                                  : Drizzle and rain\n: இடியுடன் கூடிய ஆலங்கட்டி மழை                       : Hail with thunderstorm\n: மூட்டம்                                            : Haze\n: லேசான தூறல் மற்றும் மழை                            : Light drizzle and rain\n: லேசான தூறல் மற்றும் இடியுடன் கூடிய சிறிய ஆலங்கட்டி மழை/பனிப் பலகைகள்       : Light rain and small hail/snow pallets with thunderstorm\n113 : தெளிந்த வானம்                                 : Clear\n113 : வெயில்                                        : Sunny\n116 : ஒரளவு மேகமூட்டம்                               : Partly cloudy\n119 : மேகமூட்டம்                                     : Cloudy\n122 : முற்றிலும் மேகமூட்டம்                             : Overcast\n143 : பனி மூட்டம்                                    : Mist\n176 : சீரற்ற மழை சாத்தியம்                             : Patchy rain possible\n179 : சீரற்ற பனி சாத்தியம்                              : Patchy snow possible\n182 : பனிப்பொழிவு சாத்தியம்                            : Patchy sleet possible\n185 : உறைபனி தூறல் சாத்தியம்                         : Patchy freezing drizzle possible\n200 : இடியுடன் கூடிய மழை சாத்தியமாகும்                  : Thundery outbreaks possible\n227 : வீசும் பனி                                     : Blowing snow\n230 : பனிப்புயல்                                      : Blizzard\n248 : மூடுபனி                                       : Fog\n260 : உறைபனி மூடுபனி                               : Freezing fog\n263 : மெல்லிய தூறல்                                 : Patchy light drizzle\n266 : லேசான தூறல்                                  : Light drizzle\n281 : உறையும் தூறல்                                 : Freezing drizzle\n284 : கடும் உறைபனி தூறல்                            : Heavy freezing drizzle\n293 : சீரற்ற லேசான மழை                             : Patchy light rain\n296 : லேசான மழை                                  : Light rain\n299 : அவ்வப்போது மிதமான மழை பெய்யும்                 : Moderate rain at times\n302 : மிதமான மழை                                  : Moderate rain\n305 : அவ்வப்போது பலத்த மழை                         : Heavy rain at times\n308 : பலத்த மழை                                    : Heavy rain\n311 : லேசான உறைபனி மழை                          : Light freezing rain\n314 : மிதமான அல்லது கடுமையான உறைபனி மழை          : Moderate or heavy freezing rain\n317 : லேசான தூறல்                                  : Light sleet\n320 : மிதமான அல்லது கடுமையான தூறல்                 : Moderate or heavy sleet\n323 : சீரற்ற லேசான பனி                              : Patchy light snow\n326 : லேசான பனி                                   : Light snow\n329 : சீரற்ற மிதமான பனி                              : Patchy moderate snow\n332 : மிதமான பனி                                   : Moderate snow\n335 : சீரற்ற கடுமையான பனி                            : Patchy heavy snow\n338 : கடுமையான பனி                                 : Heavy snow\n350 : பனி துகள்கள்                                   : Ice pellets\n353 : லேசான சாரல் மழை                              : Light rain shower\n356 : மிதமான அல்லது கடுமையான சாரல் மழை             : Moderate or heavy rain shower\n359 : சாரல் மழை                                    : Torrential rain shower\n362 : லேசான தூறல் மழை                             : Light sleet showers\n365 : மிதமான அல்லது கனத்த தூறல் மழை பெய்யும்         : Moderate or heavy sleet showers\n368 : லேசான பனி மழை                              : Light snow showers\n371 : மிதமான அல்லது கனத்த பனி மழை                  : Moderate or heavy snow showers\n386 : சீரற்ற இடியுடன் கூடிய லேசான மழை                 : Patchy light rain with thunder\n389 : இடியுடன் கூடிய மிதமான அல்லது பலத்த மழை         : Moderate or heavy rain with thunder\n392 : சீரற்ற இடியுடன் கூடிய லேசான பனி                  : Patchy light snow with thunder\n395 : மிதமான அல்லது கனத்த இடியுடன் கூடிய பனி          : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/te-help.txt",
    "content": "వాడుకొనుట:\n\n    $ curl wttr.in          # ప్రస్తుత స్థానం\n    $ curl wttr.in/muc      # మునిక్ విమానాశ్రయంలో వాతావరణం\n\nనిర్వహించబడిన స్థాన రకాలు:\n\n    /paris                  # పట్టనం పేరు\n    /~Eiffel+tower          # ఏదైనా ప్రదేశం (+ స్పేస్ కోసం)\n    /Москва                 # ఏ భాషలోనైనా ఏదైనా స్థానం యొక్క యూనికోడ్ పేరు\n    /muc                    # విమానాశ్రయం కోడ్ (3 అక్షరాలు)\n    /@stackoverflow.com     # డొమైన్ పేరు\n    /94107                  # ప్రాంతం సంకేతాలు (ఏరియా కోడ్‌లు)\n    /-78.46,106.79          # జిపియస్ కోఆర్డినేట్‌లు\n\nచంద్రుని దశ సమాచారం:\n\n    /moon                   # చంద్రుని దశ (,+US లేదా ,+France జోడించు ఈ నగరాల కోసం)\n    /moon@2016-10-25        # తేదీకి చంద్ర దశ (@2016-10-25)\n\nయూనిట్లు:\n\n    m                       # మెట్రిక్ పద్ధతి\n    u                       # USCS (అమెరికా సంయుక్త రాష్ట్రాల్లో అప్రమేయంగా ఉపయోగించబడుతుంది)\n    M                       # గాలి వేగం m/sలో\n\nఎంపికలను వీక్షించండి:\n\n    0                       # ప్రస్తుత వాతావరణం మాత్రమే\n    1                       # ప్రస్తుత వాతావరణం + నేటి సూచన\n    2                       # ప్రస్తుత వాతావరణం + నేటి మరియు రేపటి సూచన\n    A                       # ANSI ఫార్మాట్‌లో అవుట్‌పుట్\n    F                       # \"ఫాలో\" లైన్ చూపించవద్దు\n    n                       # చిన్న సంస్కరణ (పగలు మరియు రాత్రి మాత్రమే)\n    q                       # చాలా చిన్న సంస్కరణ (\"వాతావరణ నివేదిక\" వచనం లేదు)\n    Q                       # అతి చిన్న సంస్కరణ (\"వాతావరణ నివేదిక\" లేదు, నగరం పేరు లేదు)\n    T                       # క్లోజ్ టెర్మినల్ సీక్వెన్స్ (రంగులు లేకుండా)\n\nPNG ఎంపికలు:\n\n    /paris.png              # PNG ఫైల్‌ను రూపొందించండి\n    p                       # అవుట్‌పుట్ చుట్టూ ఫ్రేమ్‌ని జోడించండి\n    t                       # పారదర్శకత 150\n    transparency=...        # పారదర్శకత 0 నుండి 255 వరకు (255 = పారదర్శకం కాదు)\n    background=...          # నేపథ్య రంగు RRGGBB రూపంలో ఉదాహరణకు 00aaaa\n\nఎంపికలు కలపవచ్చు:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # PNGలో (ఫైల్ మోడ్‌ను _ తర్వాత పేర్కొనవచ్చు)\n    /Rome_0pq_lang=it.png   # పొడవైన ఎంపికలను అండర్‌స్కోర్‌తో వేరు చేయవచ్చు\n\nస్థానికీకరణ:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nనిర్వహించబడిన భాషలు:\n\n    am ar af be bn ca da de el et fr fa hi hu ia id it lt mg nb nl oc pl pt-br ro ru ta tr th uk vi zh-cn zh-tw (supported)\n    az bg bs cy cs eo es eu fi ga hi hr hy is ja jv ka kk ko ky lv mk ml mr nl fy nn pt pt-br sk sl sr sr-lat sv sw te uz zh zu he (in progress)\n\nప్రత్యేక URLs:\n\n    /:help                  # ఈ పేజీని చూపుతుంది\n    /:bash.function         # సిఫార్సు చేయబడిన bash ఫంక్షన్‌ను wttr() చూపుతుంది\n    /:translation           # అనువాదకుల గురించిన సమాచారాన్ని చూపుతుంది\n\n"
  },
  {
    "path": "share/translations/te.txt",
    "content": "113:                                    : స్పష్టం\n113:                                    : ఎండ\n116:                                    : కొంత మేఘావృతం\n119:                                    : మేఘావృతం\n122:                                    : దట్టమైన మబ్బులు\n143:                                    : పొగమంచు\n176:                                    : మందమైన వర్షం సాధ్యమవుతుంది\n179:                                    : పదునైన మంచు సాధ్యం\n182:                                    : సాధ్యమయ్యే పదునైన దుప్పటి\n185:                                    : పదునైన ఘనీభవన చినుకులు సాధ్యం\n200:                                    : Thundery వ్యాప్తి సాధ్యం\n227:                                    : మంచు వెదజల్లు\n230:                                    : మంచు తుఫాను\n248:                                    : పొగమంచు\n260:                                    : చల్లటి పొగమంచు\n263:                                    : పదునైన తేలికపాటి చిల్లు\n266:                                    : కాంతి చినుకులు\n281:                                    : ఘనీభవన చినుకులు\n284:                                    : భారీ గడ్డకట్టే చినుకులు\n293:                                    : తేలికపాటి వర్షం\n296:                                    : తేలికపాటి వర్షం\n299:                                    : సమయాల్లో మితమైన వర్షం\n302:                                    : ఆధునిక వర్షం\n305:                                    : సమయాల్లో భారీ వర్షం\n308:                                    : భారీవర్షం\n311:                                    : కాంతి ఘనీభవన వర్షం\n314:                                    : ఆధునిక లేదా భారీ ఘనీభవన వర్షం\n317:                                    : కాంతి స్లేట్\n320:                                    : ఆధునిక లేదా భారీ స్లీప్\n323:                                    : పదునైన తేలికపాటి మంచు\n326:                                    : తేలికపాటి మంచు\n329:                                    : మందమైన మోస్తరు మంచు\n332:                                    : ఆధునిక మంచు\n335:                                    : మందమైన భారీ మంచు\n338:                                    : భారీ మంచు\n350:                                    : మంచు ముక్కలు\n353:                                    : తేలికపాటి వర్షం షవర్\n356:                                    : ఆధునిక లేదా భారీ వర్షం షవర్\n359:                                    : కుండపోత వర్షం షవర్\n362:                                    : లైట్ స్లేట్ వర్షం\n365:                                    : మోడరేట్ లేదా భారీ షీట్ వర్షం\n368:                                    : తేలికపాటి మంచు వర్షం\n371:                                    : మితమైన లేదా భారీ మంచు వర్షం\n386:                                    : ఉరుములతో కూడిన తేలికపాటి వర్షం\n389:                                    : ఉరుములతో మితమైన లేదా భారీ వర్షం\n392:                                    : ఉరుములతో మందమైన తేలికపాటి మంచు\n395:                                    : ఉరుములతో మోస్తరు లేదా భారీ మంచు\n"
  },
  {
    "path": "share/translations/th-help.txt",
    "content": "วิธีใช้:\n\n    $ curl wttr.in          # ตำแหน่งปัจจุบัน\n    $ curl wttr.in/muc      # สภาพอากาศที่สนามบินมิวนิค\n\nรองรับสถานที่หลายรูปแบบ:\n\n    /paris                  # ชื่อเมือง\n    /~Eiffel+tower          # สถานที่ใดก็ได้\n    /Москва                 # ชื่อ Unicode ของสถานที่และภาษาใดก็ได้\n    /muc                    # รหัสสนามบิน (3 ตัวอักษร)\n    /@stackoverflow.com     # โดเมนเนม\n    /94107                  # รหัสพื้นที่\n    /-78.46,106.79          # ตำแหน่ง GPS\n\nสถานที่พิเศษ:\n\n    /moon                   # จันทรคติ (เพิ่ม ,+US หรือ ,+France สำหรับเมือง)\n    /moon@2016-10-25        # จันทรคติ สำหรับวันที่ (@2016-10-25)\n\nหน่วย:\n\n    m                       # เมตริก (SI) (ใช้กับทุกที่ยกเว้นประเทศอเมริกา)\n    u                       # USCS (ใช้ในประเทศอเมริกา)\n    M                       # แสดงความเร็วลม เมตร/วินาที\n\nดูตัวเลือก:\n\n    0                       # เฉพาะสภาพอากาศปัจจุบัน\n    1                       # สภาพอากาศของวันพรุ่งนี้\n    2                       # สภาพอากาศของวันมะรืน\n    A                       # ไม่สนใจ User-Agent และบังคับใช้ฟอร์แมต ANSI (terminal)\n    F                       # ไม่แสดงบรรทัดติดตาม\n    n                       # แสดงผลแบบแคบ (เฉพาะตอนเช้าและค่ำ)\n    q                       # แสดงผลแบบเงียบ (ไม่แสดงรายงานสภาพอากาศ)\n    Q                       # แสดงผลแบบเงียบที่สุด (ไม่แสดงรายงานสภาพอากาศและชื่อเมือง)\n    T                       # ปิดการทำงาน terminal sequences (ไม่มีสี)\n\nตัวเลือก PNG:\n\n    /paris.png              # สร้างไฟล์ PNG\n    p                       # เพิ่มกรอบรอบๆไฟล์ที่สร้าง\n    t                       # โปร่งใส 150\n    transparency=...        # โปร่งใส จาก 0 ถึง 255 (255 = ไม่โปร่งใส)\n\nตัวเลือกสามารถรวมกันได้:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # สำหรับการสร้าง PNG ให้เพิ่มตัวเลือกต่อท้าย _\n    /Rome_0pq_lang=it.png   # ตัวเลือกหลายตัวให้ต่อด้วย _ \n\nตัวเลือกภาษา:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nภาษาที่รองรับ:\n\n    FULL_TRANSLATION (รองรับ)\n    PARTIAL_TRANSLATION (อยู่ระหว่างการแปล)\n\nURL พิเศษ:\n\n    /:help                  # แสดงหน้านี้\n    /:bash.function         # แสดงคำแนะนำ bash function wttr()\n    /:translation           # แสดงข้อมูลของผู้ร่วมแปล\n\n"
  },
  {
    "path": "share/translations/th.txt",
    "content": "113: ฟ้าโปร่ง                                  : Clear                               :\n113: แดดจัด                                   : Sunny                               :\n116: มีเมฆบางส่วน                              : Partly cloudy                       :\n119: มีเมฆมาก                                 : Cloudy                              :\n122: มืดครึ้ม                                   : Overcast                            :\n143: มีหมอก                                   : Mist                                :\n176: มีโอกาสฝนตกเป็นหย่อม ๆ                     : Patchy rain possible                :\n179: มีโอกาสหิมะตกเป็นหย่อม ๆ                    : Patchy snow possible                :\n182: มีโอกาสลูกเห็บตกเป็นหย่อม ๆ                  : Patchy sleet possible               :\n185: มีโอกาสละอองฝนเยือกแข็งตกเป็นหย่อม ๆ         : Patchy freezing drizzle possible    :\n200: มีโอกาสฟ้าผ่า                              : Thundery outbreaks possible         :\n227: หิมะพัดผ่าน                                : Blowing snow                        :\n230: พายุหิมะ                                  : Blizzard                            :\n248: หมอก                                    : Fog                                 :\n260: หมอกเยือกแข็ง                             : Freezing fog                        :\n263: ละอองฝนเป็นหย่อม ๆ                        : Patchy light drizzle                :\n266: ฝนพรำ                                   : Light drizzle                       :\n281: ละอองฝนเยือกแข็ง                          : Freezing drizzle                    :\n284: ละอองฝนเยือกแข็งอย่างหนัก                   : Heavy freezing drizzle              :\n293: ฝนตกเบาบางเป็นหย่อม ๆ                     : Patchy light rain                   :\n296: ฝนตกเล็กน้อย                              : Light rain                          :\n299: ฝนตกปานกลางในช่วงเวลานั้น                  : Moderate rain at times              :\n302: ฝนตกปานกลาง                             : Moderate rain                       :\n305: ฝนตกหนักในช่วงเวลานั้น                      : Heavy rain at times                 :\n308: ฝนตกหนัก                                 : Heavy rain                          :\n311: ฝนเยือกแข็งเบาบาง                         : Light freezing rain                 :\n314: ฝนเยือกแข็งปานกลางหรือหนัก                  : Moderate or heavy freezing rain     :\n317: ลูกเห็บเบาบาง                             : Light sleet                         :\n320: ลูกเห็บปานกลางหรือหนัก                      : Moderate or heavy sleet             :\n323: หิมะตกโปรยปรายเป็นหย่อม ๆ                  : Patchy light snow                   :\n326: หิมะตกเบาบาง                             : Light snow                          :\n329: หิมะตกปานกลางเป็นหย่อม ๆ                   : Patchy moderate snow                :\n332: หิมะตกปานกลาง                            : Moderate snow                       :\n335: หิมะตกหนักเป็นหย่อม ๆ                       : Patchy heavy snow                   :\n338: หิมะตกหนัก                                : Heavy snow                          :\n350: มีเกล็ดน้ำแข็ง                              : Ice pellets                         :\n353: ฝนตกโปรยปราย                            : Light rain shower                   :\n356: ฝนตกปานกลางหรือหนัก                       : Moderate or heavy rain shower       :\n359: ฝนตกชุก                                  : Torrential rain shower              :\n362: ลูกเห็บตกเบาบาง                           : Light sleet showers                 :\n365: ลูกเห็บตกปานกลางหรือหนัก                    : Moderate or heavy sleet showers     :\n368: หิมะตกโปรยปราย                           : Light snow showers                  :\n371: หิมะตกปานกลางหรือหนัก                      : Moderate or heavy snow showers      :\n386: ฝนตกและมีฟ้าผ่าเป็นหย่อม ๆ                   : Patchy light rain with thunder      :\n389: ฝนตกและมีฟ้าผ่าปานกลางหรือหนัก               : Moderate or heavy rain with thunder :\n392: หิมะตกและมีฟ้าผ่าเป็นหย่อม ๆ                  : Patchy light snow with thunder      :\n395: หิมะตกและมีฟ้าผ่าปานกลางหรือหนัก              : Moderate or heavy snow with thunder :\n"
  },
  {
    "path": "share/translations/tr-help.txt",
    "content": "Komut Satırı Kullanımı:\n\n    $ curl wttr.in          # bulunduğunuz konum\n    $ curl wttr.in/esb      # Esenboğa havalimanında hava durumu\n\nDesteklenen konum türleri:\n\n    /istanbul               # şehir adı\n    /~Anıtkabir             # herhangi bir konum (boşluk için + kullanın)\n    /Москва                 # herhangi bir dildeki herhangi bir konumun Unicode adı\n    /esb                    # havalimanı kodu (3 harfli)\n    /@stackoverflow.com     # etki alanı adı\n    /06800                  # posta kodları\n    /39.925325,32.836987    # Yer belirleme sistemi (GPS) koordinatları\n\nAy evresi bilgisi:\n\n    /moon                   # Ay evresi (bu isimdeki şehirler için ,+US veya ,+France ekleyin)\n    /moon@2016-10-25        # Belirli bir tarih için ay evresi (@2016-10-25)\n\nÖlçü birimleri:\n\n    m                       # metrik sistem (SI) (ABD dışında her yer için varsayılan)\n    u                       # USCS (ABD için varsayılan)\n    M                       # Rüzgar hızını metre/saniye (m/s) olarak göster\n\nSeçenekleri görüntüle:\n\n    0                       # yalnızca bugün için hava durumu\n    1                       # Bugün ve 1 gün sonrası için hava durumu\n    2                       # Bugün ve 2 gün sonrası için hava durumu\n    A                       # Kullanıcı aracısı (User-Agent) bilgilerini göz ardı eder ve terminalde ANSI çıktı biçimini zorlar\n    F                       # \"Follow (Takip et)\" satırını göstermez\n    n                       # dar görünüm (yalnızca gece ve gündüz)\n    q                       # sessiz görünüm (\"Hava durumu\" yazısı yok)\n    Q                       # aşırı sessiz görünüm (\"Hava durumu\" yazısı ve şehir adı yok)\n    T                       # terminal geçişlerini kapatır (renkler yok)\n\nPNG seçenekleri:\n\n    /istanbul.png           # bir PNG dosyası üretir\n    p                       # çıktı etrafına bir çerçeve ekler\n    t                       # 150 birim saydamlık\n    transparency=...        # 0 ila 255 arasında saydamlık (255 = saydam değil)\n    background=...          # KKYYMM biçiminde arka plan rengi, örn. 00aaaa\n\nSeçenekler birleştirilebilir:\n\n    /istanbul?0pq\n    /istanbul?0pq&lang=tr\n    /istanbul_0pq.png       # PNG dosya modları _ karakterinden sonra belirtilir\n    /izmir_0pq_lang=tr.png  # uzun seçenekler alt çizgi ile ayrılır\n\nYerelleştirme:\n\n    $ curl tr.wttr.in/istanbul\n    $ curl wttr.in/izmir?lang=tr\n    $ curl -H \"Accept-Language: tr\" wttr.in/izmir\n\nDesteklenen diller:\n\n    FULL_TRANSLATION (destekleniyor)\n    PARTIAL_TRANSLATION (geliştirme aşamasında)\n\nÖzel adresler:\n\n    /:help                  # bu sayfayı göster\n    /:bash.function         # tavsiye edilen wttr() bash fonksiyonunu göster\n    /:translation           # çevirmenler hakkındaki bilgileri göster\n\n"
  },
  {
    "path": "share/translations/tr.txt",
    "content": "113: Açık\t\t\t\t\t\t: Clear\n113: Güneşli\t\t\t\t\t\t: Sunny\n116: Parçalı bulutlu\t\t\t\t\t: Partly cloudy\n119: Bulutlu\t\t\t\t\t\t: Cloudy\n122: Kapalı\t\t\t\t\t\t: Overcast\n143: Puslu\t\t\t\t\t\t: Mist\n176: Yer yer yağmur görülebilir\t\t\t\t: Patchy rain possible\n179: Yer yer kar görülebilir\t\t\t\t: Patchy snow possible\n182: Yer yer karla karışık yağmur görülebilir\t\t: Patchy sleet possible\n185: Yer yer donan çisenti olabilir\t\t\t: Patchy freezing drizzle possible\n200: Gök gürültülü fırtına görülebilir\t\t\t: Thundery outbreaks possible\n227: Tipi halinde kar yağışı\t\t\t\t: Blowing snow\n230: Kar fırtınası\t\t\t\t\t: Blizzard\n248: Sisli\t\t\t\t\t\t: Fog\n260: Donan sis\t\t\t\t\t\t: Freezing fog\n263: Yer yer hafif donan çisenti\t\t\t: Patchy light drizzle\n266: Yer yer donan çisenti\t\t\t\t: Light drizzle\n281: Donan çisenti\t\t\t\t\t: Freezing drizzle\n284: Kuvvetli don\t\t\t\t\t: Heavy freezing drizzle\n293: Yer yer hafif yağmurlu\t\t\t\t: Patchy light rain\n296: Hafif yağmurlu\t\t\t\t\t: Light rain\n299: Zaman zaman orta kuvvette yağmur\t\t\t: Moderate rain at times\n302: Orta kuvvette yağmur\t\t\t\t: Moderate rain\n305: Zaman zaman şiddetli yağmur\t\t\t: Heavy rain at times\n308: Şiddetli yağmur\t\t\t\t\t: Heavy rain\n311: Ayaz ile hafif yağmur\t\t\t\t: Light freezing rain\n314: Ayaz ile orta kuvvette veya şiddetli yağmur\t: Moderate or heavy freezing rain\n317: Hafif karla karışık yağmur\t\t\t\t: Light sleet\n320: Orta kuvvette veya şiddetli sulu kar\t\t: Moderate or heavy sleet\n323: Yer yer hafif kar yağışı\t\t\t\t: Patchy light snow\n326: Hafif kar yağışı\t\t\t\t\t: Light snow\n329: Yer yer orta şiddette kar yağışı\t\t\t: Patchy moderate snow\n332: Orta kuvvette kar yağışı\t\t\t\t: Moderate snow\n335: Yer yer kuvvetli kar yağışı\t\t\t: Patchy heavy snow\n338: Kuvvetli kar yağışı\t\t\t\t: Heavy snow\n350: Dolu yağışı\t\t\t\t\t: Ice pellets\n353: Hafif sağanak yağmur\t\t\t\t: Light rain shower\n356: Orta kuvvette veya şiddetli sağanak yağmur\t\t: Moderate or heavy rain shower\n359: Sel riski olan şiddetli sağanak yağmur\t\t: Torrential rain shower\n362: Hafif karla karışık sağanak yağmur\t\t\t: Light sleet showers\n365: Orta veya şiddetli karla karışık sağanak yağmur\t: Moderate or heavy sleet showers\n368: Hafif sağanak kar yağışı\t\t\t\t: Light snow showers\n371: Orta kuvvette veya şiddetli sağanak kar yağışı\t: Moderate or heavy snow showers\n386: Yer yer gök gürültülü ve yağmurlu\t\t\t: Patchy light rain with thunder\n389: Orta kuvvette veya şiddetli gök gürültülü yağmur\t: Moderate or heavy rain with thunder\n392: Yer yer gök gürültülü ve karlı\t\t\t: Patchy light snow with thunder\n395: Orta kuvvette veya şiddetli gök gürültülü kar\t: Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/uk-help.txt",
    "content": "Використання:\n\n    $ curl wttr.in          # поточне місцеположення\n    $ curl wttr.in/kbp      # погода в аеропорту Бориспіль (код ICAO: KBP)\n\nПідтримуються наступні типи місцеположень:\n\n    /paris                  # місто\n    /~Eiffel+tower          # будь-яке місцеположення\n    /Киів                   # юнікодне ім'я будь-якого місцеположення будь-якою мовою\n    /muc                    # код аеропорту ICAO (3 літери)\n    /@stackoverflow.com     # доменне им'я\n    /94107                  # поштовый індекс (тільки для США)\n    /-78.46,106.79          # GPS-координати\n\nСпеціальні умовні місцеположення:\n\n    /moon                   # Фаза Місяця (додайте ,+US або ,+France для міста Moon у США або Франції)\n    /moon@2016-10-25        # Фаза Місяця для вказаної дати (@2016-10-25)\n\nОдиниці вимірювань:\n\n    ?m                      # метричні (СІ) (використовуються всюди крім США)\n    ?u                      # USCS (використовуються у США)\n    ?M                      # показувати швидкість вітру в м/с\n\nОпції відображення:\n\n    ?0                      # тільки поточна погода\n    ?1                      # погода сьогодні + 1 день\n    ?2                      # погода сьогодні + 2 дня\n    ?n                      # вузька версія (тільки день та ніч)\n    ?q                      # тиха версія (без тексту \"Прогноз погоди\")\n    ?Q                      # надтиха версія (без \"Прогноз погоди\", немає назви міста)\n    ?T                      # відключити послідовності терміналу (без кольорів)\n\nPNG-опції:\n\n    /paris.png              # сгенерувати PNG-файл\n    ?p                      # добавити рамку навколо\n    ?t                      # transparency=150 (прозорість 150)\n    transparency=...        # прозорість від 0 до 255 (255 = не прозорий)\n\nОпції можна комбінувати:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # в PNG-запитах опції вказуються після знаку _\n    /Rome_0pq_lang=it.png   # довгі опції розділяются знаком підкреслення _\n\nЛокалізація:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nМови що підтримуються:\n\n    FULL_TRANSLATION (підтримується)\n    PARTIAL_TRANSLATION (в процесі)\n\nСпеціальні строрінки:\n\n    /:help                  # показати цю сторінку\n    /:bash.function         # показати рекомендовану функцію wttr()\n    /:translation           # показати список перекладачів wttr.in\n\n"
  },
  {
    "path": "share/translations/uk.txt",
    "content": "113: Ясно                               : Clear                               :\n113: Сонячно                            : Sunny                               :\n116: Змінна хмарність                   : Partly cloudy                       :\n119: Хмарно                             : Cloudy                              :\n122: Похмуро                            : Overcast                            :\n143: Невеликий туман                    : Mist                                :\n176: Місцями дощ                        : Patchy rain possible                :\n179: Місцями сніг                       : Patchy snow possible                :\n182: Місцями дощ зі снігом              : Patchy sleet possible               :\n185: Місцями ожеледь                    : Patchy freezing drizzle possible    :\n200: Місцями грози                      : Thundery outbreaks possible         :\n227: Заметіль                           : Blowing snow                        :\n230: Снігова буря                       : Blizzard                            :\n248: Туман                              : Fog                                 :\n260: Крижаний туман                     : Freezing fog                        :\n263: Місцями мряка                      : Patchy light drizzle                :\n266: Мряка                              : Light drizzle                       :\n281: Ожеледь                            : Freezing drizzle                    :\n284: Сильна ожеледь                     : Heavy freezing drizzle              :\n293: Місцями невеликий дощ              : Patchy light rain                   :\n296: Невеликий дощ                      : Light rain                          :\n299: Часом помірний дощ                 : Moderate rain at times              :\n302: Помірний дощ                       : Moderate rain                       :\n305: Часом сильний дощ                  : Heavy rain at times                 :\n308: Сильний дощ                        : Heavy rain                          :\n311: Слабкий крижаний дощ               : Light freezing rain                 :\n314: Крижаний дощ                       : Moderate or heavy freezing rain     :\n317: Невеликий дощ зі снігом            : Light sleet                         :\n320: Дощ зі снігом                      : Moderate or heavy sleet             :\n323: Місцями невеликий сніг             : Patchy light snow                   :\n326: Невеликий сніг                     : Light snow                          :\n329: Місцями помірний сніг              : Patchy moderate snow                :\n332: Помірний сніг                      : Moderate snow                       :\n335: Місцями сильний сніг               : Patchy heavy snow                   :\n338: Сильний сніг                       : Heavy snow                          :\n350: Льодяний дощ                       : Ice pellets                         :\n353: Невелика злива                     : Light rain shower                   :\n356: Злива                              : Moderate or heavy rain shower       :\n359: Дуже сильна злива                  : Torrential rain shower              :\n362: Невеликий мокрий сніг              : Light sleet showers                 :\n365: Мокрий сніг                        : Moderate or heavy sleet showers     :\n368: Невеликий сніг                     : Light snow showers                  :\n371: Сніг                               : Moderate or heavy snow showers      :\n386: Місцями дощ з грозою               : Patchy light rain with thunder      :\n389: Дощ з грозою                       : Moderate or heavy rain with thunder :\n392: Місцями сніг з грозою              : Patchy light snow with thunder      :\n395: Сніг з грозою                      : Moderate or heavy snow with thunder :\n"
  },
  {
    "path": "share/translations/ukr-help.txt",
    "content": "Використання:\n\n    $ curl wttr.in          # поточне місцеположення\n    $ curl wttr.in/kbp      # погода в аеропорту Бориспіль (код ICAO: KBP)\n\nПідтримуються наступні типи місцеположень:\n\n    /paris                  # місто\n    /~Eiffel+tower          # будь-яке місцеположення\n    /Киів                   # юнікодне ім'я будь-якого місцеположення будь-якою мовою\n    /muc                    # код аеропорту ICAO (3 літери)\n    /@stackoverflow.com     # доменне им'я\n    /94107                  # поштовый індекс (тільки для США)\n    /-78.46,106.79          # GPS-координати\n\nСпеціальні умовні місцеположення:\n\n    /moon                   # Фаза Місяця (додайте ,+US або ,+France для міста Moon у США або Франції)\n    /moon@2016-10-25        # Фаза Місяця для вказаної дати (@2016-10-25)\n\nОдиниці вимірювань:\n\n    ?m                      # метричні (СІ) (використовуються всюди крім США)\n    ?u                      # USCS (використовуються у США)\n    ?M                      # показувати швидкість вітру в м/с\n\nОпції відображення:\n\n    ?0                      # тільки поточна погода\n    ?1                      # погода сьогодні + 1 день\n    ?2                      # погода сьогодні + 2 дня\n    ?n                      # вузька версія (тільки день та ніч)\n    ?q                      # тиха версія (без тексту \"Прогноз погоди\")\n    ?Q                      # надтиха версія (без \"Прогноз погоди\", немає назви міста)\n    ?T                      # відключити послідовності терміналу (без кольорів)\n\nPNG-опції:\n\n    /paris.png              # сгенерувати PNG-файл\n    ?p                      # добавити рамку навколо\n    ?t                      # transparency=150 (прозорість 150)\n    transparency=...        # прозорість від 0 до 255 (255 = не прозорий)\n\nОпції можна комбінувати:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # в PNG-запитах опції вказуються після знаку _\n    /Rome_0pq_lang=it.png   # довгі опції розділяются знаком підкреслення _\n\nЛокалізація:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nМови що підтримуються:\n\n    FULL_TRANSLATION (підтримується)\n    PARTIAL_TRANSLATION (в процесі)\n\nСпеціальні строрінки:\n\n    /:help                  # показати цю сторінку\n    /:bash.function         # показати рекомендовану функцію wttr()\n    /:translation           # показати список перекладачів wttr.in\n"
  },
  {
    "path": "share/translations/uz.txt",
    "content": "113: Ochiq havo                         \t\t\t\t  : Clear                             \t : Ясно                         \n113: Quyoshli                           \t\t\t\t  : Sunny                             \t : Солнечно\n116: Qisman bulutli                   \t\t\t\t\t  : Partly cloudy                     \t : Переменная облачность\n119: Bulutli                            \t\t\t\t  : Cloudy                            \t : Облачно              \n122: Bulutli                            \t\t\t\t  : Overcast                          \t : Пасмурно\n143: Tuman                              \t\t\t\t  : Mist                              \t : Дымка\n176: Joylarda yomg'ir ehtimoli\t\t\t\t\t\t\t\t\t  : Patchy rain possible              \t : Местами дождь\n179: Joylarda qor ehtimoli\t\t\t\t\t\t\t\t\t\t\t  : Patchy snow possible              \t : Местами снег\n182: Joylarda yomg'ir aralash qor ehtimoli \t\t\t  : Patchy sleet possible             \t : Местами дождь со снегом\n185: Joylarda muzlatuvchi mayda yomg'ir ehtimoli  : Patchy freezing drizzle possible  \t : Местами замерзающая морось\n200: Momoqaldiroq ehtimoli              \t\t\t\t  : Thundery outbreaks possible       \t : Местами грозы              \n227: Qorli izg'irin\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  : Blowing snow                      \t : Поземок\n230: Bo'ron\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  : Blizzard                          \t : Метель\n248: Tuman                              \t\t\t\t  : Fog                               \t : Туман\n260: Sovuq tuman\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: Freezing fog                      \t : Переохлажденный туман\n263: Joylarda yengil yomg'ir\t\t\t\t\t\t\t\t\t\t  : Patchy light drizzle              \t : Местами слабая морось\n266: Yengil yomg'ir                      \t\t\t\t  : Light drizzle                     \t : Слабая морось\n281: Muzlatuvchi yomg'ir                 \t\t\t\t  : Freezing drizzle                  \t : Замерзающая морось\n284: Kuchli muzlatuvchi yomg'ir          \t\t\t\t  : Heavy freezing drizzle            \t : Сильная замерзающая морось\n293: Joylarda yengil yomg'ir             \t\t\t\t  : Patchy light rain                 \t : Местами небольшой дождь\n296: Yengil yomg'ir                      \t\t\t\t  : Light rain                        \t : Небольшой дождь\n299: Vaqti bilan o'rtacha yomg'ir        \t\t\t\t  : Moderate rain at times            \t : Временами умеренный дождь\n302: O'rtacha yomg'ir                    \t\t\t\t  : Moderate rain                     \t : Умеренный дождь\n305: Vaqti bilan kuchli yomg'ir          \t\t\t\t  : Heavy rain at times               \t : Временами сильный дождь\n308: Kuchli yomg'ir                      \t\t\t\t  : Heavy rain                        \t : Сильный дождь\n311: Yengil muzlatuvchi yomg'ir          \t\t\t\t  : Light freezing rain               \t : Слабый переохлажденный дождь\n314: O'rtacha yoki kuchli muzlatuvchi yomg'ir\t\t  : Moderate or heavy freezing rain   \t : Умеренный или сильный переохлажденный дождь\n317: Yengil yomg'ir aralash qor          \t\t\t\t  : Light sleet                       \t : Небольшой дождь со снегом\n320: O'rtacha yoki kuchli yomg'ir aralash qor \t  : Moderate or heavy sleet           \t : Умеренный или сильный дождь со снегом\n323: Joylarda yengil qor                          : Patchy light snow                 \t : Местами небольшой снег\n326: Yengil qor                          \t\t\t\t  : Light snow                        \t : Небольшой снег\n329: Joylarda o'rtacha qor               \t\t\t\t  : Patchy moderate snow              \t : Местами умеренный снег\n332: O'rtacha qor                        \t\t\t\t  : Moderate snow                     \t : Умеренный снег\n335: Joylarda kuchli qor                 \t\t\t\t  : Patchy heavy snow                 \t : Местами сильный снег\n338: Kuchli qor                          \t\t\t\t  : Heavy snow                        \t : Сильный снег\n350: Do'l                                \t\t\t\t  : Ice pellets                       \t : Ледяной дождь\n353: Qisqa jala                          \t\t\t\t  : Light rain shower                 \t : Небольшой ливневый дождь\n356: O'rtacha yoki kuchli jala                    : Moderate or heavy rain shower     \t : Умеренный или сильный ливневый дождь\n359: Shiddatli jala                      \t\t\t\t  : Torrential rain shower            \t : Очень сильный ливень\n362: Qisqa qorli jala                    \t\t\t\t  : Light sleet showers               \t : Небольшой ливневый дождь со снегом\n365: O'rtacha yoki kuchli qorli jala     \t\t\t\t  : Moderate or heavy sleet showers   \t : Небольшой снег\n368: Qisqa qor aralash yomg'ir           \t\t\t\t  : Light snow showers                \t : Небольшой ливневый дождь со снегом\n371: O'rtacha yoki kuchli qorli jala     \t\t\t\t  : Moderate or heavy snow showers    \t : Умеренный или сильный снежный ливень\n386: Joylarda yengil yomg'ir va momaqaldiroq\t\t  : Patchy light rain with thunder      : Местами небольшой дождь с грозой\n389: O'rtacha yoki kuchli yomg'ir va momaqaldiroq : Moderate or heavy rain with thunder : Умеренный или сильный дождь с грозой\n392: Joylarda yengil qor va momaqaldiroq \t\t\t\t  : Patchy light snow with thunder      : Местами небольшой снег с грозой\n395: O'rtacha yoku kuchli qor va momaqaldiroq\t\t  : Moderate or heavy snow with thunder : Умеренный или сильный снег с грозой \n"
  },
  {
    "path": "share/translations/vi-help.txt",
    "content": "Cách dùng:\n\n    $ curl wttr.in          # vị trí hiện tại\n    $ curl wttr.in/sgn      # thời tiết sân bay Tân Sơn Nhất\n\nCác loại địa điểm được hỗ trợ:\n\n    /paris                  # tên thành phố\n    /~Eiffel+tower          # địa điểm nổi tiếng bất kỳ\n    /Москва                 # tên địa điểm Unicode trong bất cứ ngôn ngữ nào\n    /sgn                    # mã sân bay IATA (3 ký tự)\n    /@stackoverflow.com     # tên miền\n    /94107                  # mã vùng (chỉ cho Hoa Kỳ)\n    /-78.46,106.79          # tọa độ\n\nĐịa điểm đặc biệt:\n\n    /moon                   # pha mặt trăng (thêm ,+US hoặc ,+France để lấy chu kỳ mặt trăng cho địa điểm đó)\n    /moon@2016-10-25        # pha mặt trăng của 1 ngày (@2016-10-25)\n\nĐơn vị:\n\n    ?m                      # hệ mét (SI) (mặc định cho mọi nơi trừ Mỹ)\n    ?u                      # USCS (mặc định cho Mỹ)\n    ?M                      # tốc độ gió theo m/s\n\nTùy chọn hiển thị:\n\n    ?0                      # Chỉ hiện thời tiết hiện tại\n    ?1                      # Thời tiết hiện tại + 1 ngày\n    ?2                      # Thời tiết hiện tại + 2 ngày\n    ?n                      # bản rút gọn (chỉ có ngày & đêm)\n    ?q                      # bản thu nhỏ (không có dòng \"Báo cáo thời tiết\")\n    ?Q                      # bản siêu nhỏ (không có dòng \"Báo cáo thời tiết\" và địa điểm)\n    ?T                      # tắt escape sequence cho terminal (không màu)\n\nTùy chọn PNG:\n\n    /paris.png              # tạo ra file PNG\n    ?p                      # thêm khung xung quanh\n    ?t                      # độ trong suốt = 150\n    transparency=...        # độ trong suốt từ 0 tới 255 (255 = không trong suốt)\n\nKết hợp các tùy chọn:\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # với file PNG thì tùy chọn nằm phía sau dấu _\n    /Rome_0pq_lang=it.png   # các tùy chọn phân cách với nhau bằng dấu _\n\nBản địa hóa:\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\nCác ngôn ngữ được hỗ trợ:\n\n    FULL_TRANSLATION (hỗ trợ)\n    PARTIAL_TRANSLATION (chưa dịch hoàn toàn)\n\nURL đặc biệt:\n\n    /:help                  # hiện trang này\n    /:bash.function         # hiện hàm wttr() được đề nghị cho bash\n    /:translation           # hiện thông tin về người biên dịch\n\n"
  },
  {
    "path": "share/translations/vi.txt",
    "content": "113: Trời trong                            : Clear\n113: Trời nắng                             : Sunny\n116: Có mây                                : Partly cloudy\n119: Nhiều mây                             : Cloudy\n122: Âm u                                  : Overcast\n143: Sương mù                              : Mist\n176: Có mưa rải rác                        : Patchy rain possible\n179: Có tuyết rải rác                      : Patchy snow possible\n182: Có mưa đá rải rác                     : Patchy sleet possible\n185: Có mưa phùn băng rải rác              : Patchy freezing drizzle possible\n200: Có dông                               : Thundery outbreaks possible\n227: Tuyết bay                             : Blowing snow\n230: Bão tuyết                             : Blizzard\n248: Sương mù                              : Fog\n260: Sương mù đóng băng                    : Freezing fog\n263: Mưa phùn nhẹ rải rác                  : Patchy light drizzle\n266: Mưa phùn nhẹ                          : Light drizzle\n281: Mưa phùn băng                         : Freezing drizzle\n284: Mưa phùn băng to                      : Heavy freezing drizzle\n293: Mưa nhẹ rải rác                       : Patchy light rain\n296: Mưa nhỏ                               : Light rain\n299: Thỉnh thoảng có mưa vừa               : Moderate rain at times\n302: Mưa vừa                               : Moderate rain\n305: Thỉnh thoảng có mưa to                : Heavy rain at times\n308: Mưa to                                : Heavy rain\n311: Mưa băng giá nhẹ                      : Light freezing rain\n314: Mưa băng giá vừa đến to               : Moderate or heavy freezing rain\n317: Mưa đá nhỏ                            : Light sleet\n320: Mưa đá vừa đến to                     : Moderate or heavy sleet\n323: Tuyết rơi nhẹ rải rác                 : Patchy light snow\n326: Tuyết rơi nhẹ                         : Light snow\n329: Tuyết rơi vừa rải rác                 : Patchy moderate snow\n332: Tuyết rơi vừa                         : Moderate snow\n335: Tuyết rơi dày rải rác                 : Patchy heavy snow\n338: Tuyết rơi dày                         : Heavy snow\n350: Mưa đá                                : Ice pellets\n353: Mưa rào nhẹ                           : Light rain shower\n356: Mưa rào vừa đến to                    : Moderate or heavy rain shower\n359: Mưa rào xối xả                        : Torrential rain shower\n362: Mưa rào đá nhẹ                        : Light sleet showers\n365: Mưa rào đá vừa đến to                 : Moderate or heavy sleet showers\n368: Mưa rào tuyết nhỏ                     : Light snow showers\n371: Mưa rào tuyết vừa đến to              : Moderate or heavy snow showers\n386: Mưa rào nhẹ có dông rải rác           : Patchy light rain with thunder\n389: Mưa dông vừa đến to                   : Moderate or heavy rain with thunder\n392: Tuyết rơi nhẹ có dông rải rác         : Patchy light snow with thunder\n395: Tuyết rơi vừa đến dày có dông rải rác : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/zh-cn-help.txt",
    "content": "用法：\n\n    $ curl wttr.in          # 当前位置\n    $ curl wttr.in/pek      # 机场三字码\n\n支持的位置类型：\n\n    /paris                  # 城市名称\n    /~Eiffel+tower          # 任意地点\n    /北京                    # 任意语言的任意地点\n    /PEK                    # 机场三字码\n    /@stackoverflow.com     # 域名\n    /94107                  # 区域代码\n    /-78.46,106.79          # GPS 坐标\n\n特殊位置：\n\n    /moon                   # 月相（加上 ,+US 或 ,+France 以查看特定城市的月相）\n    /moon@2016-10-25        # 特定日期的月相（@2016-10-25）\n\n单位：\n\n    m                       # 公制（国际单位制）（除美国外该单位制为默认值）\n    u                       # USCS（美国默认单位制）\n    M                       # 以米/秒为单位显示风速\n\n查看选项：\n\n    0                       # 仅当前天气\n    1                       # 当前天气 + 未来 1 天\n    2                       # 当前天气 + 未来 2 天\n    A                       # 忽略用户代理(User-Agent)并强制使用 ANSI 输出格式（终端模式）\n    F                       # 不显示「关注」(Follow)那行\n    n                       # 较窄模式（仅日夜）\n    q                       # 简练模式（无「天气预报」文字）\n    Q                       # 极简模式（无「天气预报」、无城市名称）\n    T                       # 关闭终端转义序列（无颜色）\n\nPNG 选项：\n\n    /paris.png              # 生成 PNG 文件\n    p                       # 在输出图像周围增加缩进空白\n    t                       # 透明度 150\n    transparency=...        # 透明度从 0 到 255（255 = 不透明）\n\n可合并使用的选项\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # PNG 文件模式中在下划线 _ 后指定选项\n    /Rome_0pq_lang=it.png   # 用下划线分隔长选项\n\n本地化：\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\n支持的语言：\n\n    FULL_TRANSLATION (supported)\n    PARTIAL_TRANSLATION (in progress)\n\n特殊 URL：\n\n    /:help                  # 显示此页面\n    /:bash.function         # 显示建议的 bash 函数 wttr()\n    /:translation           # 显示翻译者信息\n\n"
  },
  {
    "path": "share/translations/zh-cn.txt",
    "content": "113:晴                                    : Clear\n113:晴                                    : Sunny\n116:少云                                  : Partly cloudy\n119:多云                                  : Cloudy\n122:阴                                    : Overcast\n143:轻雾                                  : Mist\n176:局部下小雨                             : Patchy rain possible\n179:局部下小雪                             : Patchy snow possible\n182:局部有雨夹雪                            : Patchy sleet possible\n185:局部有冻毛毛雨                          : Patchy freezing drizzle possible\n200:可能打雷                               : Thundery outbreaks possible\n227:小雪                                  : Blowing snow\n230:暴雪                                  : Blizzard\n248:雾                                    : Fog\n260:冻雾                                  : Freezing fog\n263:局部毛毛雨                              : Patchy light drizzle\n266:毛毛雨                                 : Light drizzle\n281:冻毛毛雨                               : Freezing drizzle\n284:大冻毛毛雨                              : Heavy freezing drizzle\n293:局部小雨                               : Patchy light rain\n296:小雨                                  : Light rain\n299:有时中雨                               : Moderate rain at times\n302:中雨                                  : Moderate rain\n305:有时大雨                               : Heavy rain at times\n308:大雨                                  : Heavy rain\n311:小冻雨                                 : Light freezing rain\n314:中或大冻雨                              : Moderate or heavy freezing rain\n317:小雨夹雪                                 : Light sleet\n320:中或大雨夹雪                            : Moderate or heavy sleet\n323:局部小雪                               : Patchy light snow\n326:小雪                                  : Light snow\n329:局部中雪                               : Patchy moderate snow\n332:中雪                                  : Moderate snow\n335:局部大雪                               : Patchy heavy snow\n338:大雪                                  : Heavy snow\n350:冰丸                                  : Ice pellets\n353:小阵雨                                : Light rain shower\n356:中或大阵雨                             : Moderate or heavy rain shower\n359:暴阵雨                                : Torrential rain shower\n362:小阵雨夹雪                             : Light sleet showers\n365:中或大阵雨夹雪                          : Moderate or heavy sleet showers\n368:小阵雪                                : Light snow showers\n371:中或大阵雪                             : Moderate or heavy snow showers\n386:局部小雷阵雨                            : Patchy light rain with thunder\n389:中或大雷阵雨                            : Moderate or heavy rain with thunder\n392:小雷阵雪                               : Patchy light snow with thunder\n395:中或大雷阵雪                            : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "share/translations/zh-tw-help.txt",
    "content": "使用方法\n\n    $ curl wttr.in          # 目前位置\n    $ curl wttr.in/muc      # 慕尼黑機場的天氣\n\n支援的位置類型：\n\n    /paris                  # 城市名稱\n    /~Eiffel+tower          # 任意地點\n    /Москва                 # 任意地點在任何語言的 Unicode 名稱\n    /muc                    # 機場代碼（3個字母）\n    /@stackoverflow.com     # 網域名稱\n    /94107                  # 區域代碼\n    /-78.46,106.79          # GPS 座標\n\n特殊位置：\n\n    /moon                   # 月相（加入 ,+US 或 ,+France 來觀看這些地方的月相）\n    /moon@2016-10-25        # 特定日期的月相 (@2016-10-25)\n\n單位：\n\n    m                       # 公制（國際單位制）（除了美國以外的地方皆預設使用此單位制）\n    u                       # USCS（美國預設使用）\n    M                       # 以公尺／秒為單位顯示風速\n\n檢視選項：\n\n    0                       # 僅目前的天氣\n    1                       # 目前的天氣+未來1天\n    2                       # 目前的天氣+未來2天\n    A                       # 忽略使用者代理字串並強制使用 ANSI 輸出格式（終端機）\n    F                       # 不要顯示「追蹤」那行\n    n                       # 窄版（僅日夜）\n    q                       # 安靜版（無「天氣報告」文字）\n    Q                       # 超安靜版（無「天氣報告」、無城市名稱）\n    T                       # 關閉終端機序列（無色彩）\n\nPNG 選項：\n\n    /paris.png              # 生成 PNG 檔案\n    p                       # 在輸出周圍新增框架\n    t                       # 透明度 150\n    transparency=...        # 透明度從 0 到 255（255 = 不透明）\n\n可合併使用的選項\n\n    /Paris?0pq\n    /Paris?0pq&lang=fr\n    /Paris_0pq.png          # PNG 檔案模式於 _ 後指定\n    /Rome_0pq_lang=it.png   # 以底線分隔長選項\n\n在地化：\n\n    $ curl fr.wttr.in/Paris\n    $ curl wttr.in/paris?lang=fr\n    $ curl -H \"Accept-Language: fr\" wttr.in/paris\n\n支援的語言：\n\n    FULL_TRANSLATION (supported)\n    PARTIAL_TRANSLATION (in progress)\n\n特殊 URL：\n\n    /:help                  # 顯示此頁面\n    /:bash.function         # 顯示建議的 bash 函式 wttr()\n    /:translation           # 顯示關於譯者的資訊\n\n"
  },
  {
    "path": "share/translations/zh-tw.txt",
    "content": "113: 晴朗                            : Clear\n113: 陽光充足                        : Sunny\n116: 晴時多雲                        : Partly cloudy\n119: 多雲                            : Cloudy\n122: 陰天                            : Overcast\n143: 薄霧                            : Mist\n176: 可能下小雨                      : Patchy rain possible\n179: 可能下小雪                      : Patchy snow possible\n182: 可能有雨夾雪                    : Patchy sleet possible\n185: 可能有凍毛毛雨                  : Patchy freezing drizzle possible\n200: 可能打雷                        : Thundery outbreaks possible\n227: 吹雪                            : Blowing snow\n230: 雪暴                            : Blizzard\n248: 霧                              : Fog\n260: 凍霧                            : Freezing fog\n263: 局部毛毛細雨                    : Patchy light drizzle\n266: 毛毛細雨                        : Light drizzle\n281: 凍毛毛雨                        : Freezing drizzle\n284: 重凍毛毛雨                      : Heavy freezing drizzle\n293: 局部小雨                        : Patchy light rain\n296: 小雨                            : Light \n299: 有時中雨                        : Moderate rain at times\n302: 中雨                            : Moderate rain\n305: 有時大雨                        : Heavy rain at times\n308: 大雨                            : Heavy rain\n311: 小凍雨                          : Light freezing rain\n314: 中或大凍雨                      : Moderate or heavy freezing rain\n317: 小雨夾雪                        : Light sleet\n320: 中或大雨夾雪                    : Moderate or heavy sleet\n323: 局部小雪                        : Patchy light snow\n326: 小雪                            : Light snow\n329: 局部中雪                        : Patchy moderate snow\n332: 中雪                            : Moderate snow\n335: 局部大雪                        : Patchy heavy snow\n338: 大雪                            : Heavy snow\n350: 冰珠                            : Ice pellets\n353: 小陣雨                          : Light rain shower\n356: 中或大陣雨                      : Moderate or heavy rain shower\n359: 豪陣雨                          : Torrential rain shower\n362: 小陣雨夾雪                      : Light sleet showers\n365: 中或大陣雨夾雪                  : Moderate or heavy sleet showers\n368: 小陣雪                          : Light snow showers\n371: 中或大陣雪                      : Moderate or heavy snow showers\n386: 局部小雷雨                      : Patchy light rain with thunder\n389: 中或大雷雨                      : Moderate or heavy rain with thunder\n392: 可能會打雷的小陣雪              : Patchy light snow with thunder\n395: 可能會打雷的中或大陣雪          : Moderate or heavy snow with thunder\n"
  },
  {
    "path": "spec/options/options.yaml",
    "content": "query_options:\n  - name: current_only\n    short: \"0\"\n    description: \"Show only current weather\"\n    type: boolean\n    default: false\n    active: true\n  - name: current_plus_today\n    short: \"1\"\n    description: \"Show current weather and today's forecast\"\n    type: boolean\n    default: false\n    active: true\n  - name: current_plus_two_days\n    short: \"2\"\n    description: \"Show current weather, today's, and tomorrow's forecast\"\n    type: boolean\n    default: false\n    active: true\n  - name: current_plus_three_days\n    short: \"3\"\n    description: \"Show current weather, forecast for today, tomorrow, and day after\"\n    type: boolean\n    default: false\n    active: true\n  - name: ansi_output\n    short: A\n    description: \"Force ANSI output format for terminals\"\n    type: boolean\n    default: false\n    active: true\n  - name: standard_font\n    short: d\n    description: \"Restrict output to standard console font glyphs\"\n    type: boolean\n    default: false\n    active: true\n  - name: no_follow\n    short: F\n    description: \"Do not show the 'Follow' line\"\n    type: boolean\n    default: false\n    active: true\n  - name: metric\n    short: m\n    description: \"Use metric (SI) units (default everywhere except US)\"\n    type: boolean\n    values:\n      - true\n      - false\n    default: true\n    active: true\n    note: \"Overridden by 'uscs' if specified; default is 'uscs' in US\"\n  - name: uscs\n    short: u\n    description: \"Use USCS units (default in the US)\"\n    type: boolean\n    values:\n      - true\n      - false\n    default: false\n    active: true\n    note: \"Default is 'uscs' in US, 'metric' elsewhere\"\n  - name: wind_ms\n    short: M\n    description: \"Show wind speed in meters per second\"\n    type: boolean\n    default: false\n    active: true\n  - name: narrow\n    short: n\n    description: \"Show only day and night forecast (narrow version)\"\n    type: boolean\n    default: false\n    active: true\n  - name: frame\n    short: p\n    description: \"Add a frame around the PNG output\"\n    type: boolean\n    default: false\n    active: true\n    note: \"Applicable only for PNG output\"\n  - name: quiet\n    short: q\n    description: \"Quiet version, no 'Weather report' text\"\n    type: boolean\n    default: false\n    active: true\n  - name: superquiet\n    short: Q\n    description: \"Superquiet version, no 'Weather report' text or city name\"\n    type: boolean\n    default: false\n    active: true\n\n  - name: period\n    type: integer\n    description: \"Update interval for cyclic location selection\"\n    default: null\n    active: true\n  - name: random\n    type: integer\n    description: \"Random number, used to bypass the first caching layer (alias: dummy, nonce)\"\n    active: true\n  - name: dummy\n    type: integer\n    description: \"Random number, used to bypass the first caching layer (alias: random, nonce)\"\n    active: true\n  - name: nonce\n    type: integer\n    description: \"Random number, used to bypass the first caching layer (alias: dummy, random)\"\n    active: true\n  - name: no_color\n    short: T\n    description: \"Switch off terminal color sequences (no colors)\"\n    type: boolean\n    default: false\n    active: true\n  - name: lang\n    description: \"Specify output language\"\n    type: string\n    values_map:\n      am: \"Amharic\"\n      ar: \"Arabic\"\n      af: \"Afrikaans\"\n      be: \"Belarusian\"\n      bn: \"Bengali\"\n      ca: \"Catalan\"\n      da: \"Danish\"\n      de: \"German\"\n      el: \"Greek\"\n      et: \"Estonian\"\n      en: \"English\"\n      fr: \"French\"\n      fa: \"Persian\"\n      gl: \"Galician\"\n      hi: \"Hindi\"\n      hu: \"Hungarian\"\n      ia: \"Interlingua\"\n      id: \"Indonesian\"\n      it: \"Italian\"\n      lt: \"Lithuanian\"\n      mg: \"Malagasy\"\n      nb: \"Norwegian Bokmål\"\n      nl: \"Dutch\"\n      oc: \"Occitan\"\n      pl: \"Polish\"\n      pt-br: \"Portuguese (Brazil)\"\n      ro: \"Romanian\"\n      ru: \"Russian\"\n      ta: \"Tamil\"\n      tr: \"Turkish\"\n      th: \"Thai\"\n      ua: \"Ukrainian\"\n      vi: \"Vietnamese\"\n      zh-cn: \"Chinese (Simplified)\"\n      zh-tw: \"Chinese (Traditional)\"\n      az: \"Azerbaijani (partial support)\"\n      ba: \"Bashkir (partial support)\"\n      bg: \"Bulgarian (partial support)\"\n      cy: \"Welsh (partial support)\"\n      bs: \"Bosnian (partial support)\"\n      by: \"Belarusian (partial support)\"\n      cz: \"Czech (partial support)\"\n      eo: \"Esperanto (partial support)\"\n      es: \"Spanish (partial support)\"\n      eu: \"Basque (partial support)\"\n      fi: \"Finnish (partial support)\"\n      ga: \"Irish (partial support)\"\n      hr: \"Croatian (partial support)\"\n      hy: \"Armenian (partial support)\"\n      is: \"Icelandic (partial support)\"\n      ja: \"Japanese (partial support)\"\n      jv: \"Javanese (partial support)\"\n      ka: \"Georgian (partial support)\"\n      kk: \"Kazakh (partial support)\"\n      ko: \"Korean (partial support)\"\n      ky: \"Kyrgyz (partial support)\"\n      lv: \"Latvian (partial support)\"\n      mk: \"Macedonian (partial support)\"\n      ml: \"Malayalam (partial support)\"\n      mr: \"Marathi (partial support)\"\n      fy: \"Frisian (partial support)\"\n      nn: \"Norwegian Nynorsk (partial support)\"\n      pt: \"Portuguese (partial support)\"\n      sk: \"Slovak (partial support)\"\n      sl: \"Slovenian (partial support)\"\n      sr: \"Serbian (partial support)\"\n      sr-lat: \"Serbian (Latin) (partial support)\"\n      sv: \"Swedish (partial support)\"\n      sw: \"Swahili (partial support)\"\n      te: \"Telugu (partial support)\"\n      ts: \"Tsonga (partial support)\"\n      zu: \"Zulu (partial support)\"\n      he: \"Hebrew (partial support)\"\n      zh: \"Chinese (partial support)\"\n    default: en\n    active: true\n    note: \"Languages from 'az' to 'zh' have partial support; others have full support\"\n  - name: background\n    description: \"Set background color for PNG output in hex (RRGGBB format)\"\n    type: string\n    default: null\n    validate:\n      - \"length 6\"\n      - \"regexp [0-9a-fA-F]{6}\"\n    active: true\n    note: \"Applicable only for PNG output\"\n  - name: format\n    description: \"Specify output format for one-line weather info\"\n    type: string\n      # values_map:\n      #   \"1\": \"Location and condition\"\n      #   \"2\": \"Location, condition, temperature\"\n      #   \"3\": \"Location: condition temperature\"\n      #   \"4\": \"Location: condition, temperature details, wind speed\"\n      #   custom: \"Percent notation (e.g., %l, %c, %t, %w, %m, etc.)\"\n      # values:\n      #   - \"1\"\n      #   - \"2\"\n      #   - \"3\"\n      #   - \"4\"\n      #   - \"custom\"\n    default: null\n    active: true\n    note: \"Used for status bars in tools like tmux\"\n  - name: date\n    description: \"Specify forecast date offset (days in the future)\"\n    type: integer\n    range:\n      min: 1\n      max: null\n    default: 0\n    active: false\n    note: \"Proposed but not officially supported; limited evidence\"\n\n  - name: force-ansi\n    short: A\n    description: \"Force ANSI output mode\"\n    type: boolean\n    default: false\n    active: true\n    note: \"Enables ANSI formatting regardless of terminal capabilities\"\n\n  - name: dumb\n    short: d\n    description: \"Use dumb terminal mode\"\n    type: boolean\n    default: false\n    active: true\n    note: \"Disables advanced terminal features\"\n\n  - name: narrow\n    short: n\n    description: \"Use narrow layout for output\"\n    type: boolean\n    default: false\n    active: true\n    note: \"Optimizes output for narrow displays\"\n\n  - name: use_metric\n    short: m\n    description: \"Use metric units for measurements\"\n    type: boolean\n    default: false\n    active: true\n    note: \"Sets units to metric system; 'M' also enables milliseconds for wind speed\"\n\n  - name: use_ms_for_wind\n    short: M\n    description: \"Use milliseconds for wind speed (requires metric units)\"\n    type: boolean\n    default: false\n    active: true\n    note: \"Only active when used with 'M' flag for metric units\"\n\n  - name: use_imperial\n    short: u\n    description: \"Use imperial units for measurements\"\n    type: boolean\n    default: false\n    active: true\n    note: \"Sets units to imperial system\"\n\n  - name: inverted_colors\n    short: I\n    description: \"Invert colors in output\"\n    type: boolean\n    default: false\n    active: true\n    note: \"Swaps foreground and background colors\"\n\n  - name: transparency\n    short: t\n    description: \"Set transparency level for PNG output\"\n    type: integer\n    range:\n      min: 0\n      max: 255\n    default: 150\n    active: true\n    note: \"Applicable only for PNG output; 255 = not transparent\"\n\n  - name: no-terminal\n    short: T\n    description: \"Disable terminal-specific formatting\"\n    type: boolean\n    default: false\n    active: true\n    note: \"Output is not tailored to terminal environment\"\n\n  - name: padding\n    short: p\n    description: \"Add padding to output\"\n    type: boolean\n    default: false\n    active: true\n    note: \"Adds extra spacing around output content\"\n\n  - name: days\n    description: \"Set the number of forecast days to display\"\n    type: integer\n    range:\n      min: 0\n      max: 3\n    default: null\n    active: true\n    note: \"Limits forecast output to the specified number of days\"\n\n  - name: no-caption\n    short: q\n    description: \"Disable captions in output\"\n    type: boolean\n    default: false\n    active: true\n    note: \"Removes descriptive text or labels from output\"\n\n  - name: no-city\n    short: Q\n    description: \"Hide city name in output\"\n    type: boolean\n    default: false\n    active: true\n    note: \"Omits location or city name from display\"\n\n  - name: no-follow-line\n    short: F\n    description: \"Disable follow line feature\"\n    type: boolean\n    default: false\n    active: true\n    note: \"Prevents automatic line following in output\"\n\n  - name: question_mark\n    short: \"?\"\n    description: \"Workaround for multiple usage of the question mark in the query\"\n    type: boolean\n    default: false\n    active: true\n\nformat_specifiers:\n  - specifier: \"%c\"\n    description: \"Weather condition\"\n    active: true\n  - specifier: \"%C\"\n    description: \"Weather condition text\"\n    active: true\n  - specifier: \"%h\"\n    description: \"Humidity\"\n    active: true\n  - specifier: \"%t\"\n    description: \"Temperature\"\n    active: true\n  - specifier: \"%w\"\n    description: \"Wind\"\n    active: true\n  - specifier: \"%l\"\n    description: \"Location\"\n    active: true\n  - specifier: \"%m\"\n    description: \"Moon phase\"\n    active: true\n  - specifier: \"%M\"\n    description: \"Moon day\"\n    active: true\n  - specifier: \"%p\"\n    description: \"Precipitation\"\n    active: true\n  - specifier: \"%D\"\n    description: \"Dawn\"\n    active: true\n  - specifier: \"%S\"\n    description: \"Sunrise\"\n    active: true\n  - specifier: \"%z\"\n    description: \"Zenith\"\n    active: true\n  - specifier: \"%s\"\n    description: \"Sunset\"\n    active: true\n  - specifier: \"%d\"\n    description: \"Dusk\"\n    active: true\n  - specifier: \"%H\"\n    description: \"High temperature for the day\"\n    active: false\n    note: \"Proposed in issue #585\"\n  - specifier: \"%L\"\n    description: \"Low temperature for the day\"\n    active: false\n    note: \"Proposed in issue #585\"\n"
  },
  {
    "path": "srv.go",
    "content": "package main\n\nimport (\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"io\"\n\tstdlog \"log\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/alecthomas/kong\"\n\tlog \"github.com/sirupsen/logrus\"\n\n\t\"github.com/chubin/wttr.in/internal/config\"\n\tgeoip \"github.com/chubin/wttr.in/internal/geo/ip\"\n\tgeoloc \"github.com/chubin/wttr.in/internal/geo/location\"\n\t\"github.com/chubin/wttr.in/internal/logging\"\n\t\"github.com/chubin/wttr.in/internal/options\"\n\t\"github.com/chubin/wttr.in/internal/processor\"\n\t\"github.com/chubin/wttr.in/internal/types\"\n\t// v1 \"github.com/chubin/wttr.in/internal/view/v1\"\n)\n\n//nolint:gochecknoglobals\nvar cli struct {\n\tConfigFile string `name:\"config-file\" arg:\"\" optional:\"\" help:\"Name of configuration file\"`\n\n\tConfigCheck             bool   `name:\"config-check\" help:\"Check configuration\"`\n\tConfigDump              bool   `name:\"config-dump\" help:\"Dump configuration\"`\n\tConvertGeoIPCache       bool   `name:\"convert-geo-ip-cache\" help:\"Convert Geo IP data cache to SQlite\"`\n\tConvertGeoLocationCache bool   `name:\"convert-geo-location-cache\" help:\"Convert Geo Location data cache to SQlite\"`\n\tGeoResolve              string `name:\"geo-resolve\" help:\"Resolve location\"`\n\tLogLevel                string `name:\"log-level\" short:\"l\" help:\"Show log messages with level\" default:\"info\"`\n\tCheckQueriesInLog       string `name:\"check-queries-in-log\" help:\"Check queries in the log file\"`\n\tOutputLog               string `name:\"output-log\" help:\"Output log\"`\n\n\t// V1 v1.Configuration\n}\n\nconst logLineStart = \"LOG_LINE_START \"\n\nfunc suppressMessages() []string {\n\treturn []string{\n\t\t\"error reading preface from client\",\n\t\t\"TLS handshake error from\",\n\t\t\"URL query contains semicolon, which is no longer a supported separator\",\n\t\t\"connection error: PROTOCOL_ERROR\",\n\t}\n}\n\nfunc copyHeader(dst, src http.Header) {\n\tfor k, vv := range src {\n\t\tfor _, v := range vv {\n\t\t\tdst.Add(k, v)\n\t\t}\n\t}\n}\n\nfunc serveHTTP(mux *http.ServeMux, port int, logFile io.Writer, errs chan<- error) {\n\tsrv := &http.Server{\n\t\tAddr:         fmt.Sprintf(\":%d\", port),\n\t\tErrorLog:     stdlog.New(logFile, logLineStart, stdlog.LstdFlags),\n\t\tReadTimeout:  5 * time.Second,\n\t\tWriteTimeout: 10 * time.Second,\n\t\tIdleTimeout:  1 * time.Second,\n\t\tHandler:      mux,\n\t}\n\terrs <- srv.ListenAndServe()\n}\n\nfunc serveHTTPS(mux *http.ServeMux, port int, certFile, keyFile string, logFile io.Writer, errs chan<- error) {\n\ttlsConfig := &tls.Config{\n\n\t\t// CipherSuites: []uint16{\n\t\t// \ttls.TLS_CHACHA20_POLY1305_SHA256,\n\t\t// \ttls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,\n\t\t// \ttls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\n\t\t// },\n\t\t// MinVersion: tls.VersionTLS13,\n\t}\n\tsrv := &http.Server{\n\t\tAddr:         fmt.Sprintf(\":%d\", port),\n\t\tErrorLog:     stdlog.New(logFile, logLineStart, stdlog.LstdFlags),\n\t\tReadTimeout:  5 * time.Second,\n\t\tWriteTimeout: 20 * time.Second,\n\t\tIdleTimeout:  1 * time.Second,\n\t\tTLSConfig:    tlsConfig,\n\t\tHandler:      mux,\n\t}\n\terrs <- srv.ListenAndServeTLS(certFile, keyFile)\n}\n\nfunc serve(conf *config.Config) error {\n\tvar (\n\t\t// mux is main HTTP/HTTP requests multiplexer.\n\t\tmux = http.NewServeMux()\n\n\t\t// logger is optimized requests logger.\n\t\tlogger = logging.NewRequestLogger(\n\t\t\tconf.Logging.AccessLog,\n\t\t\ttime.Duration(conf.Logging.Interval)*time.Second)\n\n\t\trp *processor.RequestProcessor\n\n\t\t// errs is the servers errors channel.\n\t\terrs = make(chan error, 1)\n\n\t\t// numberOfServers started. If 0, exit.\n\t\tnumberOfServers int\n\n\t\terrorsLog = logging.NewLogSuppressor(\n\t\t\tconf.Logging.ErrorsLog,\n\t\t\tsuppressMessages(),\n\t\t\tlogLineStart,\n\t\t)\n\n\t\terr error\n\t)\n\n\trp, err = processor.NewRequestProcessor(conf)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"log processor initialization: %w\", err)\n\t}\n\n\terr = errorsLog.Open()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = rp.Start()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tmux.HandleFunc(\"/\", mainHandler(rp, logger))\n\n\tif conf.Server.PortHTTP != 0 {\n\t\tgo serveHTTP(mux, conf.Server.PortHTTP, errorsLog, errs)\n\t\tnumberOfServers++\n\t}\n\tif conf.Server.PortHTTPS != 0 {\n\t\tgo serveHTTPS(mux, conf.Server.PortHTTPS, conf.Server.TLSCertFile, conf.Server.TLSKeyFile, errorsLog, errs)\n\t\tnumberOfServers++\n\t}\n\tif numberOfServers == 0 {\n\t\treturn types.ErrNoServersConfigured\n\t}\n\n\treturn <-errs // block until one of the servers writes an error\n}\n\nfunc mainHandler(\n\trp *processor.RequestProcessor,\n\tlogger *logging.RequestLogger,\n) func(http.ResponseWriter, *http.Request) {\n\treturn func(w http.ResponseWriter, r *http.Request) {\n\t\tif err := logger.Log(r); err != nil {\n\t\t\tlog.Println(err)\n\t\t}\n\n\t\tresponse, err := rp.ProcessRequest(r)\n\t\tif err != nil {\n\t\t\tlog.Println(err)\n\n\t\t\treturn\n\t\t}\n\t\tif response.StatusCode == 0 {\n\t\t\tlog.Println(\"status code 0\", response)\n\n\t\t\treturn\n\t\t}\n\n\t\tcopyHeader(w.Header(), response.Header)\n\t\tw.Header().Set(\"Access-Control-Allow-Origin\", \"*\")\n\t\tw.WriteHeader(response.StatusCode)\n\t\t_, err = w.Write(response.Body)\n\t\tif err != nil {\n\t\t\tlog.Println(err)\n\t\t}\n\t}\n}\n\nfunc main() {\n\tvar (\n\t\tconf *config.Config\n\t\terr  error\n\t)\n\n\tctx := kong.Parse(&cli)\n\tctx.FatalIfErrorf(setLogLevel(cli.LogLevel))\n\n\tif cli.ConfigFile != \"\" {\n\t\tconf, err = config.Load(cli.ConfigFile)\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"reading config from %s: %s\\n\", cli.ConfigFile, err)\n\t\t}\n\t} else {\n\t\tconf = config.Default()\n\t}\n\n\tif cli.ConfigDump {\n\t\t//nolint:forbidigo\n\t\tfmt.Print(string(conf.Dump()))\n\n\t\treturn\n\t}\n\n\tif cli.ConfigCheck {\n\t\treturn\n\t}\n\n\tswitch {\n\tcase cli.ConvertGeoIPCache:\n\t\tctx.FatalIfErrorf(convertGeoIPCache(conf))\n\tcase cli.ConvertGeoLocationCache:\n\t\tctx.FatalIfErrorf(convertGeoLocationCache(conf))\n\tcase cli.CheckQueriesInLog != \"\":\n\t\tif cli.OutputLog == \"\" {\n\t\t\tctx.Fatalf(\"missing output log (--output-log)\")\n\t\t}\n\t\twttrinOptions, err := options.NewFromFile(\"spec/options/options.yaml\")\n\t\tctx.FatalIfErrorf(err)\n\n\t\terr = options.ProcessLogFile(cli.CheckQueriesInLog, cli.OutputLog, wttrinOptions)\n\t\tctx.FatalIfErrorf(err)\n\n\tcase cli.GeoResolve != \"\":\n\t\tsr := geoloc.NewSearcher(conf)\n\t\tloc, err := sr.Search(cli.GeoResolve)\n\t\tctx.FatalIfErrorf(err)\n\t\tif loc != nil {\n\t\t\t//nolint:forbidigo\n\t\t\tfmt.Println(*loc)\n\t\t}\n\tdefault:\n\t\terr = serve(conf)\n\t\tctx.FatalIfErrorf(err)\n\t}\n}\n\nfunc convertGeoIPCache(conf *config.Config) error {\n\tgeoIPCache, err := geoip.NewCache(conf)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn geoIPCache.ConvertCache()\n}\n\nfunc convertGeoLocationCache(conf *config.Config) error {\n\tgeoLocCache, err := geoloc.NewCache(conf)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn geoLocCache.ConvertCache(false)\n}\n\nfunc setLogLevel(logLevel string) error {\n\tparsedLevel, err := log.ParseLevel(logLevel)\n\tif err != nil {\n\t\treturn err\n\t}\n\tlog.SetLevel(parsedLevel)\n\n\treturn nil\n}\n"
  },
  {
    "path": "test/proxy-data/data1",
    "content": "{\"data\":{\"request\":[{\"type\":\"LatLon\",\"query\":\"Lat 27.64 and Lon -80.40\"}],\"nearest_area\":[{\"areaName\":[{\"value\":\"Vero Beach\"}],\"country\":[{\"value\":\"United States of America\"}],\"region\":[{\"value\":\"Florida\"}],\"latitude\":\"27.638\",\"longitude\":\"-80.398\",\"population\":\"17262\",\"weatherUrl\":[{\"value\":\"https://www.worldweatheronline.com/v2/weather.aspx?q=27.6387163,-80.3975399\"}]}],\"current_condition\":[{\"observation_time\":\"10:24 AM\",\"localObsDateTime\":\"2020-04-26 06:24 AM\",\"temp_C\":\"22\",\"temp_F\":\"72\",\"weatherCode\":\"143\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0006_mist.png\"}],\"weatherDesc\":[{\"value\":\"Mist\"}],\"windspeedMiles\":\"4\",\"windspeedKmph\":\"6\",\"winddirDegree\":\"240\",\"winddir16Point\":\"WSW\",\"precipMM\":\"0.4\",\"humidity\":\"94\",\"visibility\":\"10\",\"pressure\":\"1015\",\"cloudcover\":\"75\",\"FeelsLikeC\":\"25\",\"FeelsLikeF\":\"76\",\"uvIndex\":1}],\"weather\":[{\"date\":\"2020-04-26\",\"astronomy\":[{\"sunrise\":\"06:46 AM\",\"sunset\":\"07:53 PM\",\"moonrise\":\"09:12 AM\",\"moonset\":\"11:17 PM\",\"moon_phase\":\"Waxing Crescent\",\"moon_illumination\":\"22\"}],\"maxtempC\":\"30\",\"maxtempF\":\"87\",\"mintempC\":\"23\",\"mintempF\":\"73\",\"totalSnow_cm\":\"0.0\",\"sunHour\":\"6.5\",\"uvIndex\":\"9\",\"hourly\":[{\"time\":\"0\",\"tempC\":\"25\",\"tempF\":\"77\",\"windspeedMiles\":\"7\",\"windspeedKmph\":\"12\",\"winddirDegree\":\"235\",\"winddir16Point\":\"SW\",\"weatherCode\":\"176\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0025_light_rain_showers_night.png\"}],\"weatherDesc\":[{\"value\":\"Patchy rain possible\"}],\"precipMM\":\"0.4\",\"humidity\":\"85\",\"visibility\":\"9\",\"pressure\":\"1015\",\"cloudcover\":\"86\",\"HeatIndexC\":\"28\",\"HeatIndexF\":\"82\",\"DewPointC\":\"22\",\"DewPointF\":\"72\",\"WindChillC\":\"25\",\"WindChillF\":\"77\",\"WindGustMiles\":\"14\",\"WindGustKmph\":\"22\",\"FeelsLikeC\":\"28\",\"FeelsLikeF\":\"82\",\"chanceofrain\":\"76\",\"chanceofremdry\":\"0\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"89\",\"chanceofsunshine\":\"0\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"71\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"1\"},{\"time\":\"300\",\"tempC\":\"24\",\"tempF\":\"76\",\"windspeedMiles\":\"7\",\"windspeedKmph\":\"12\",\"winddirDegree\":\"242\",\"winddir16Point\":\"WSW\",\"weatherCode\":\"386\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0032_thundery_showers_night.png\"}],\"weatherDesc\":[{\"value\":\"Patchy light rain with thunder\"}],\"precipMM\":\"0.4\",\"humidity\":\"88\",\"visibility\":\"9\",\"pressure\":\"1015\",\"cloudcover\":\"81\",\"HeatIndexC\":\"27\",\"HeatIndexF\":\"80\",\"DewPointC\":\"22\",\"DewPointF\":\"72\",\"WindChillC\":\"24\",\"WindChillF\":\"76\",\"WindGustMiles\":\"13\",\"WindGustKmph\":\"21\",\"FeelsLikeC\":\"27\",\"FeelsLikeF\":\"80\",\"chanceofrain\":\"70\",\"chanceofremdry\":\"0\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"87\",\"chanceofsunshine\":\"0\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"13\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"1\"},{\"time\":\"600\",\"tempC\":\"24\",\"tempF\":\"75\",\"windspeedMiles\":\"7\",\"windspeedKmph\":\"12\",\"winddirDegree\":\"246\",\"winddir16Point\":\"WSW\",\"weatherCode\":\"386\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0032_thundery_showers_night.png\"}],\"weatherDesc\":[{\"value\":\"Patchy light rain with thunder\"}],\"precipMM\":\"0.6\",\"humidity\":\"89\",\"visibility\":\"10\",\"pressure\":\"1015\",\"cloudcover\":\"74\",\"HeatIndexC\":\"26\",\"HeatIndexF\":\"79\",\"DewPointC\":\"22\",\"DewPointF\":\"72\",\"WindChillC\":\"24\",\"WindChillF\":\"75\",\"WindGustMiles\":\"12\",\"WindGustKmph\":\"20\",\"FeelsLikeC\":\"26\",\"FeelsLikeF\":\"79\",\"chanceofrain\":\"77\",\"chanceofremdry\":\"0\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"87\",\"chanceofsunshine\":\"0\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"12\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"1\"},{\"time\":\"900\",\"tempC\":\"26\",\"tempF\":\"78\",\"windspeedMiles\":\"7\",\"windspeedKmph\":\"12\",\"winddirDegree\":\"246\",\"winddir16Point\":\"WSW\",\"weatherCode\":\"386\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0016_thundery_showers.png\"}],\"weatherDesc\":[{\"value\":\"Patchy light rain with thunder\"}],\"precipMM\":\"1.1\",\"humidity\":\"83\",\"visibility\":\"10\",\"pressure\":\"1017\",\"cloudcover\":\"80\",\"HeatIndexC\":\"28\",\"HeatIndexF\":\"83\",\"DewPointC\":\"22\",\"DewPointF\":\"72\",\"WindChillC\":\"26\",\"WindChillF\":\"78\",\"WindGustMiles\":\"11\",\"WindGustKmph\":\"17\",\"FeelsLikeC\":\"28\",\"FeelsLikeF\":\"83\",\"chanceofrain\":\"73\",\"chanceofremdry\":\"0\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"88\",\"chanceofsunshine\":\"0\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"42\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"9\"},{\"time\":\"1200\",\"tempC\":\"29\",\"tempF\":\"84\",\"windspeedMiles\":\"7\",\"windspeedKmph\":\"12\",\"winddirDegree\":\"247\",\"winddir16Point\":\"WSW\",\"weatherCode\":\"353\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0009_light_rain_showers.png\"}],\"weatherDesc\":[{\"value\":\"Light rain shower\"}],\"precipMM\":\"0.7\",\"humidity\":\"68\",\"visibility\":\"10\",\"pressure\":\"1017\",\"cloudcover\":\"76\",\"HeatIndexC\":\"32\",\"HeatIndexF\":\"90\",\"DewPointC\":\"22\",\"DewPointF\":\"72\",\"WindChillC\":\"29\",\"WindChillF\":\"84\",\"WindGustMiles\":\"9\",\"WindGustKmph\":\"15\",\"FeelsLikeC\":\"32\",\"FeelsLikeF\":\"90\",\"chanceofrain\":\"74\",\"chanceofremdry\":\"0\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"85\",\"chanceofsunshine\":\"0\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"95\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"31\",\"uvIndex\":\"9\"},{\"time\":\"1500\",\"tempC\":\"30\",\"tempF\":\"86\",\"windspeedMiles\":\"7\",\"windspeedKmph\":\"11\",\"winddirDegree\":\"259\",\"winddir16Point\":\"WSW\",\"weatherCode\":\"386\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0016_thundery_showers.png\"}],\"weatherDesc\":[{\"value\":\"Patchy light rain with thunder\"}],\"precipMM\":\"1.0\",\"humidity\":\"63\",\"visibility\":\"10\",\"pressure\":\"1016\",\"cloudcover\":\"62\",\"HeatIndexC\":\"33\",\"HeatIndexF\":\"92\",\"DewPointC\":\"22\",\"DewPointF\":\"72\",\"WindChillC\":\"30\",\"WindChillF\":\"86\",\"WindGustMiles\":\"9\",\"WindGustKmph\":\"14\",\"FeelsLikeC\":\"33\",\"FeelsLikeF\":\"92\",\"chanceofrain\":\"76\",\"chanceofremdry\":\"0\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"87\",\"chanceofsunshine\":\"0\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"96\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"87\",\"uvIndex\":\"9\"},{\"time\":\"1800\",\"tempC\":\"28\",\"tempF\":\"82\",\"windspeedMiles\":\"6\",\"windspeedKmph\":\"9\",\"winddirDegree\":\"259\",\"winddir16Point\":\"WSW\",\"weatherCode\":\"386\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0016_thundery_showers.png\"}],\"weatherDesc\":[{\"value\":\"Patchy light rain with thunder\"}],\"precipMM\":\"1.5\",\"humidity\":\"70\",\"visibility\":\"10\",\"pressure\":\"1015\",\"cloudcover\":\"72\",\"HeatIndexC\":\"31\",\"HeatIndexF\":\"88\",\"DewPointC\":\"22\",\"DewPointF\":\"71\",\"WindChillC\":\"28\",\"WindChillF\":\"82\",\"WindGustMiles\":\"9\",\"WindGustKmph\":\"15\",\"FeelsLikeC\":\"31\",\"FeelsLikeF\":\"88\",\"chanceofrain\":\"72\",\"chanceofremdry\":\"0\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"86\",\"chanceofsunshine\":\"0\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"93\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"48\",\"uvIndex\":\"9\"},{\"time\":\"2100\",\"tempC\":\"25\",\"tempF\":\"77\",\"windspeedMiles\":\"7\",\"windspeedKmph\":\"11\",\"winddirDegree\":\"243\",\"winddir16Point\":\"WSW\",\"weatherCode\":\"176\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0025_light_rain_showers_night.png\"}],\"weatherDesc\":[{\"value\":\"Patchy rain possible\"}],\"precipMM\":\"0.2\",\"humidity\":\"74\",\"visibility\":\"10\",\"pressure\":\"1016\",\"cloudcover\":\"75\",\"HeatIndexC\":\"27\",\"HeatIndexF\":\"81\",\"DewPointC\":\"20\",\"DewPointF\":\"68\",\"WindChillC\":\"25\",\"WindChillF\":\"77\",\"WindGustMiles\":\"13\",\"WindGustKmph\":\"21\",\"FeelsLikeC\":\"27\",\"FeelsLikeF\":\"81\",\"chanceofrain\":\"81\",\"chanceofremdry\":\"0\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"90\",\"chanceofsunshine\":\"0\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"61\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"1\"}]},{\"date\":\"2020-04-27\",\"astronomy\":[{\"sunrise\":\"06:45 AM\",\"sunset\":\"07:54 PM\",\"moonrise\":\"09:58 AM\",\"moonset\":\"No moonset\",\"moon_phase\":\"Waxing Crescent\",\"moon_illumination\":\"30\"}],\"maxtempC\":\"24\",\"maxtempF\":\"76\",\"mintempC\":\"19\",\"mintempF\":\"66\",\"totalSnow_cm\":\"0.0\",\"sunHour\":\"11.6\",\"uvIndex\":\"11\",\"hourly\":[{\"time\":\"0\",\"tempC\":\"22\",\"tempF\":\"71\",\"windspeedMiles\":\"11\",\"windspeedKmph\":\"17\",\"winddirDegree\":\"304\",\"winddir16Point\":\"NW\",\"weatherCode\":\"176\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0025_light_rain_showers_night.png\"}],\"weatherDesc\":[{\"value\":\"Patchy rain possible\"}],\"precipMM\":\"0.1\",\"humidity\":\"67\",\"visibility\":\"10\",\"pressure\":\"1018\",\"cloudcover\":\"72\",\"HeatIndexC\":\"23\",\"HeatIndexF\":\"74\",\"DewPointC\":\"15\",\"DewPointF\":\"60\",\"WindChillC\":\"22\",\"WindChillF\":\"71\",\"WindGustMiles\":\"19\",\"WindGustKmph\":\"31\",\"FeelsLikeC\":\"22\",\"FeelsLikeF\":\"71\",\"chanceofrain\":\"77\",\"chanceofremdry\":\"0\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"92\",\"chanceofsunshine\":\"0\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"0\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"1\"},{\"time\":\"300\",\"tempC\":\"20\",\"tempF\":\"67\",\"windspeedMiles\":\"13\",\"windspeedKmph\":\"20\",\"winddirDegree\":\"323\",\"winddir16Point\":\"NW\",\"weatherCode\":\"113\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0008_clear_sky_night.png\"}],\"weatherDesc\":[{\"value\":\"Clear\"}],\"precipMM\":\"0.1\",\"humidity\":\"59\",\"visibility\":\"10\",\"pressure\":\"1017\",\"cloudcover\":\"49\",\"HeatIndexC\":\"20\",\"HeatIndexF\":\"67\",\"DewPointC\":\"12\",\"DewPointF\":\"53\",\"WindChillC\":\"20\",\"WindChillF\":\"67\",\"WindGustMiles\":\"22\",\"WindGustKmph\":\"36\",\"FeelsLikeC\":\"20\",\"FeelsLikeF\":\"67\",\"chanceofrain\":\"51\",\"chanceofremdry\":\"30\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"63\",\"chanceofsunshine\":\"29\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"0\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"1\"},{\"time\":\"600\",\"tempC\":\"19\",\"tempF\":\"67\",\"windspeedMiles\":\"15\",\"windspeedKmph\":\"24\",\"winddirDegree\":\"340\",\"winddir16Point\":\"NNW\",\"weatherCode\":\"116\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0004_black_low_cloud.png\"}],\"weatherDesc\":[{\"value\":\"Partly cloudy\"}],\"precipMM\":\"0.0\",\"humidity\":\"54\",\"visibility\":\"10\",\"pressure\":\"1018\",\"cloudcover\":\"1\",\"HeatIndexC\":\"19\",\"HeatIndexF\":\"67\",\"DewPointC\":\"10\",\"DewPointF\":\"49\",\"WindChillC\":\"19\",\"WindChillF\":\"67\",\"WindGustMiles\":\"24\",\"WindGustKmph\":\"39\",\"FeelsLikeC\":\"19\",\"FeelsLikeF\":\"67\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"88\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"13\",\"chanceofsunshine\":\"83\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"0\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"1\"},{\"time\":\"900\",\"tempC\":\"20\",\"tempF\":\"68\",\"windspeedMiles\":\"14\",\"windspeedKmph\":\"22\",\"winddirDegree\":\"339\",\"winddir16Point\":\"NNW\",\"weatherCode\":\"113\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0001_sunny.png\"}],\"weatherDesc\":[{\"value\":\"Sunny\"}],\"precipMM\":\"0.0\",\"humidity\":\"51\",\"visibility\":\"10\",\"pressure\":\"1020\",\"cloudcover\":\"1\",\"HeatIndexC\":\"21\",\"HeatIndexF\":\"69\",\"DewPointC\":\"9\",\"DewPointF\":\"49\",\"WindChillC\":\"20\",\"WindChillF\":\"68\",\"WindGustMiles\":\"19\",\"WindGustKmph\":\"31\",\"FeelsLikeC\":\"20\",\"FeelsLikeF\":\"68\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"87\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"26\",\"chanceofsunshine\":\"80\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"0\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"11\"},{\"time\":\"1200\",\"tempC\":\"23\",\"tempF\":\"73\",\"windspeedMiles\":\"13\",\"windspeedKmph\":\"21\",\"winddirDegree\":\"230\",\"winddir16Point\":\"SW\",\"weatherCode\":\"113\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0001_sunny.png\"}],\"weatherDesc\":[{\"value\":\"Sunny\"}],\"precipMM\":\"0.0\",\"humidity\":\"43\",\"visibility\":\"10\",\"pressure\":\"1020\",\"cloudcover\":\"0\",\"HeatIndexC\":\"24\",\"HeatIndexF\":\"76\",\"DewPointC\":\"9\",\"DewPointF\":\"49\",\"WindChillC\":\"23\",\"WindChillF\":\"73\",\"WindGustMiles\":\"15\",\"WindGustKmph\":\"24\",\"FeelsLikeC\":\"24\",\"FeelsLikeF\":\"76\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"88\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"0\",\"chanceofsunshine\":\"88\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"5\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"11\"},{\"time\":\"1500\",\"tempC\":\"24\",\"tempF\":\"74\",\"windspeedMiles\":\"12\",\"windspeedKmph\":\"20\",\"winddirDegree\":\"12\",\"winddir16Point\":\"NNE\",\"weatherCode\":\"113\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0001_sunny.png\"}],\"weatherDesc\":[{\"value\":\"Sunny\"}],\"precipMM\":\"0.0\",\"humidity\":\"41\",\"visibility\":\"10\",\"pressure\":\"1019\",\"cloudcover\":\"0\",\"HeatIndexC\":\"25\",\"HeatIndexF\":\"76\",\"DewPointC\":\"10\",\"DewPointF\":\"49\",\"WindChillC\":\"24\",\"WindChillF\":\"74\",\"WindGustMiles\":\"14\",\"WindGustKmph\":\"23\",\"FeelsLikeC\":\"25\",\"FeelsLikeF\":\"76\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"83\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"0\",\"chanceofsunshine\":\"86\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"11\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"11\"},{\"time\":\"1800\",\"tempC\":\"22\",\"tempF\":\"71\",\"windspeedMiles\":\"13\",\"windspeedKmph\":\"21\",\"winddirDegree\":\"33\",\"winddir16Point\":\"NNE\",\"weatherCode\":\"113\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0001_sunny.png\"}],\"weatherDesc\":[{\"value\":\"Sunny\"}],\"precipMM\":\"0.0\",\"humidity\":\"53\",\"visibility\":\"10\",\"pressure\":\"1019\",\"cloudcover\":\"0\",\"HeatIndexC\":\"23\",\"HeatIndexF\":\"74\",\"DewPointC\":\"12\",\"DewPointF\":\"53\",\"WindChillC\":\"22\",\"WindChillF\":\"71\",\"WindGustMiles\":\"16\",\"WindGustKmph\":\"26\",\"FeelsLikeC\":\"22\",\"FeelsLikeF\":\"71\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"86\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"0\",\"chanceofsunshine\":\"86\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"0\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"11\"},{\"time\":\"2100\",\"tempC\":\"20\",\"tempF\":\"68\",\"windspeedMiles\":\"11\",\"windspeedKmph\":\"17\",\"winddirDegree\":\"38\",\"winddir16Point\":\"NE\",\"weatherCode\":\"113\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0008_clear_sky_night.png\"}],\"weatherDesc\":[{\"value\":\"Clear\"}],\"precipMM\":\"0.0\",\"humidity\":\"60\",\"visibility\":\"10\",\"pressure\":\"1020\",\"cloudcover\":\"0\",\"HeatIndexC\":\"20\",\"HeatIndexF\":\"68\",\"DewPointC\":\"12\",\"DewPointF\":\"54\",\"WindChillC\":\"20\",\"WindChillF\":\"68\",\"WindGustMiles\":\"18\",\"WindGustKmph\":\"29\",\"FeelsLikeC\":\"20\",\"FeelsLikeF\":\"68\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"81\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"0\",\"chanceofsunshine\":\"88\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"0\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"1\"}]},{\"date\":\"2020-04-28\",\"astronomy\":[{\"sunrise\":\"06:44 AM\",\"sunset\":\"07:54 PM\",\"moonrise\":\"10:50 AM\",\"moonset\":\"12:13 AM\",\"moon_phase\":\"Waxing Crescent\",\"moon_illumination\":\"37\"}],\"maxtempC\":\"25\",\"maxtempF\":\"76\",\"mintempC\":\"19\",\"mintempF\":\"67\",\"totalSnow_cm\":\"0.0\",\"sunHour\":\"10.3\",\"uvIndex\":\"9\",\"hourly\":[{\"time\":\"0\",\"tempC\":\"20\",\"tempF\":\"68\",\"windspeedMiles\":\"10\",\"windspeedKmph\":\"16\",\"winddirDegree\":\"34\",\"winddir16Point\":\"NNE\",\"weatherCode\":\"113\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0008_clear_sky_night.png\"}],\"weatherDesc\":[{\"value\":\"Clear\"}],\"precipMM\":\"0.0\",\"humidity\":\"61\",\"visibility\":\"10\",\"pressure\":\"1021\",\"cloudcover\":\"0\",\"HeatIndexC\":\"20\",\"HeatIndexF\":\"68\",\"DewPointC\":\"12\",\"DewPointF\":\"54\",\"WindChillC\":\"20\",\"WindChillF\":\"68\",\"WindGustMiles\":\"18\",\"WindGustKmph\":\"28\",\"FeelsLikeC\":\"20\",\"FeelsLikeF\":\"68\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"82\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"0\",\"chanceofsunshine\":\"89\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"0\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"1\"},{\"time\":\"300\",\"tempC\":\"20\",\"tempF\":\"67\",\"windspeedMiles\":\"9\",\"windspeedKmph\":\"15\",\"winddirDegree\":\"35\",\"winddir16Point\":\"NE\",\"weatherCode\":\"113\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0008_clear_sky_night.png\"}],\"weatherDesc\":[{\"value\":\"Clear\"}],\"precipMM\":\"0.0\",\"humidity\":\"61\",\"visibility\":\"10\",\"pressure\":\"1020\",\"cloudcover\":\"0\",\"HeatIndexC\":\"20\",\"HeatIndexF\":\"67\",\"DewPointC\":\"12\",\"DewPointF\":\"53\",\"WindChillC\":\"20\",\"WindChillF\":\"67\",\"WindGustMiles\":\"17\",\"WindGustKmph\":\"27\",\"FeelsLikeC\":\"20\",\"FeelsLikeF\":\"67\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"85\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"0\",\"chanceofsunshine\":\"89\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"0\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"1\"},{\"time\":\"600\",\"tempC\":\"20\",\"tempF\":\"68\",\"windspeedMiles\":\"9\",\"windspeedKmph\":\"14\",\"winddirDegree\":\"53\",\"winddir16Point\":\"NE\",\"weatherCode\":\"116\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0004_black_low_cloud.png\"}],\"weatherDesc\":[{\"value\":\"Partly cloudy\"}],\"precipMM\":\"0.0\",\"humidity\":\"62\",\"visibility\":\"10\",\"pressure\":\"1020\",\"cloudcover\":\"5\",\"HeatIndexC\":\"20\",\"HeatIndexF\":\"68\",\"DewPointC\":\"13\",\"DewPointF\":\"55\",\"WindChillC\":\"20\",\"WindChillF\":\"68\",\"WindGustMiles\":\"15\",\"WindGustKmph\":\"25\",\"FeelsLikeC\":\"20\",\"FeelsLikeF\":\"68\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"86\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"13\",\"chanceofsunshine\":\"84\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"0\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"1\"},{\"time\":\"900\",\"tempC\":\"22\",\"tempF\":\"71\",\"windspeedMiles\":\"10\",\"windspeedKmph\":\"16\",\"winddirDegree\":\"69\",\"winddir16Point\":\"ENE\",\"weatherCode\":\"116\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png\"}],\"weatherDesc\":[{\"value\":\"Partly cloudy\"}],\"precipMM\":\"0.0\",\"humidity\":\"60\",\"visibility\":\"10\",\"pressure\":\"1021\",\"cloudcover\":\"15\",\"HeatIndexC\":\"22\",\"HeatIndexF\":\"72\",\"DewPointC\":\"14\",\"DewPointF\":\"57\",\"WindChillC\":\"22\",\"WindChillF\":\"71\",\"WindGustMiles\":\"14\",\"WindGustKmph\":\"22\",\"FeelsLikeC\":\"22\",\"FeelsLikeF\":\"71\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"87\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"43\",\"chanceofsunshine\":\"74\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"3\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"9\"},{\"time\":\"1200\",\"tempC\":\"24\",\"tempF\":\"75\",\"windspeedMiles\":\"12\",\"windspeedKmph\":\"19\",\"winddirDegree\":\"77\",\"winddir16Point\":\"ENE\",\"weatherCode\":\"119\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0003_white_cloud.png\"}],\"weatherDesc\":[{\"value\":\"Cloudy\"}],\"precipMM\":\"0.0\",\"humidity\":\"53\",\"visibility\":\"10\",\"pressure\":\"1022\",\"cloudcover\":\"37\",\"HeatIndexC\":\"25\",\"HeatIndexF\":\"78\",\"DewPointC\":\"14\",\"DewPointF\":\"57\",\"WindChillC\":\"24\",\"WindChillF\":\"75\",\"WindGustMiles\":\"14\",\"WindGustKmph\":\"22\",\"FeelsLikeC\":\"25\",\"FeelsLikeF\":\"78\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"86\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"63\",\"chanceofsunshine\":\"56\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"12\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"9\"},{\"time\":\"1500\",\"tempC\":\"25\",\"tempF\":\"76\",\"windspeedMiles\":\"11\",\"windspeedKmph\":\"18\",\"winddirDegree\":\"83\",\"winddir16Point\":\"E\",\"weatherCode\":\"116\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png\"}],\"weatherDesc\":[{\"value\":\"Partly cloudy\"}],\"precipMM\":\"0.0\",\"humidity\":\"52\",\"visibility\":\"10\",\"pressure\":\"1020\",\"cloudcover\":\"65\",\"HeatIndexC\":\"26\",\"HeatIndexF\":\"78\",\"DewPointC\":\"14\",\"DewPointF\":\"57\",\"WindChillC\":\"25\",\"WindChillF\":\"76\",\"WindGustMiles\":\"13\",\"WindGustKmph\":\"21\",\"FeelsLikeC\":\"26\",\"FeelsLikeF\":\"78\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"86\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"72\",\"chanceofsunshine\":\"35\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"15\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"9\"},{\"time\":\"1800\",\"tempC\":\"23\",\"tempF\":\"74\",\"windspeedMiles\":\"9\",\"windspeedKmph\":\"15\",\"winddirDegree\":\"88\",\"winddir16Point\":\"E\",\"weatherCode\":\"116\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png\"}],\"weatherDesc\":[{\"value\":\"Partly cloudy\"}],\"precipMM\":\"0.0\",\"humidity\":\"56\",\"visibility\":\"10\",\"pressure\":\"1019\",\"cloudcover\":\"16\",\"HeatIndexC\":\"25\",\"HeatIndexF\":\"77\",\"DewPointC\":\"14\",\"DewPointF\":\"57\",\"WindChillC\":\"23\",\"WindChillF\":\"74\",\"WindGustMiles\":\"13\",\"WindGustKmph\":\"20\",\"FeelsLikeC\":\"25\",\"FeelsLikeF\":\"77\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"91\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"35\",\"chanceofsunshine\":\"82\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"10\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"9\"},{\"time\":\"2100\",\"tempC\":\"22\",\"tempF\":\"71\",\"windspeedMiles\":\"8\",\"windspeedKmph\":\"13\",\"winddirDegree\":\"90\",\"winddir16Point\":\"E\",\"weatherCode\":\"113\",\"weatherIconUrl\":[{\"value\":\"http://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0008_clear_sky_night.png\"}],\"weatherDesc\":[{\"value\":\"Clear\"}],\"precipMM\":\"0.0\",\"humidity\":\"61\",\"visibility\":\"10\",\"pressure\":\"1020\",\"cloudcover\":\"6\",\"HeatIndexC\":\"25\",\"HeatIndexF\":\"76\",\"DewPointC\":\"14\",\"DewPointF\":\"57\",\"WindChillC\":\"22\",\"WindChillF\":\"71\",\"WindGustMiles\":\"14\",\"WindGustKmph\":\"23\",\"FeelsLikeC\":\"22\",\"FeelsLikeF\":\"71\",\"chanceofrain\":\"0\",\"chanceofremdry\":\"89\",\"chanceofwindy\":\"0\",\"chanceofovercast\":\"28\",\"chanceofsunshine\":\"84\",\"chanceoffrost\":\"0\",\"chanceofhightemp\":\"0\",\"chanceoffog\":\"0\",\"chanceofsnow\":\"0\",\"chanceofthunder\":\"0\",\"uvIndex\":\"1\"}]}]}}"
  },
  {
    "path": "test/proxy-data/data1.headers",
    "content": "{\"Content-Type\": \"application/json\"}"
  },
  {
    "path": "test/query.sh",
    "content": "queries=(\n    /\n    /Kiev\n    /Kiev.png\n    /?T\n    /Киев\n    /Kiev?2\n    \"/Kiev?format=1\"\n    \"/Kiev?format=2\"\n    \"/Kiev?format=3\"\n    \"/Kiev?format=4\"\n    \"/Kiev?format=v2\"\n    \"/Kiev?format=%s\"\n    \"/Kiev?format=%S\"\n    \"/Kiev?format=%D+%S+%z+%s+%d\"\n    \"/:help\"\n    \"/Kiev?T\"\n    \"/Kiev?p\"\n    \"/Kiev?q\"\n    \"/Kiev?Q\"\n    \"/Kiev_text=no_view=v2.png\"\n    \"/Kiev.png?1nqF\"\n    \"/Kiev_1nqF.png\"\n)\n\noptions=$(cat <<EOF\n\n-A firefox\n-H Accept-Language:ru\n-H X-Forwarded-For:1.1.1.1\nEOF\n)\n\nserver=\"http://127.0.0.1:8002\"\n\nif [ \"$1\" = update ]; then\n  UPDATE=yes\nfi\n\nif [[ $UPDATE = yes ]]; then\n  true > test-data/signatures\nfi\n\nresult_tmp=$(mktemp wttrin-test-XXXXX)\n\nwhile read -r -a args\ndo\n  for q in \"${queries[@]}\"; do\n    signature=$(echo \"${args[@]}\" \"$q\" | sha1sum | awk '{print $1}')\n    curl -ks \"${args[@]}\" \"$server$q\" > \"$result_tmp\"\n\n    result=$(sha1sum \"$result_tmp\" | awk '{print $1}')\n\n    # this must be moved to the server\n    # but for the moment we just clean up\n    # the cache after each call\n    rm -rf \"/wttr.in/cache\"\n\n    if grep -Eq \"(we are running out of queries|500 Internal Server Error)\" \"$result_tmp\"; then\n      echo \"$q\"\n    fi\n\n    if [[ $UPDATE = yes ]]; then\n      printf \"%s %s %s\\\\n\" \"$signature\" \"$result\" \"${args[*]} $q\" >> test-data/signatures\n    elif ! grep -q \"$signature $result\" test-data/signatures; then\n      echo \"FAILED: curl -ks ${args[*]} $server$q\"\n    fi\n  done\ndone <<< \"${options}\"\n\nrm \"$result_tmp\"\n"
  },
  {
    "path": "test/test-data/signatures",
    "content": "8f27084b6294ddbe28dbcbf98f798730e8a79289 4ee2dd9cf8f5818902647ff832ef40d690096bf1  /\nae537911bb7b0568f478073e661abee1cb4ff941 d123e570da22dee9798d353c4281cb5a2bdbaeac  /Kiev\n4dc586807c16020b9f4dbb705326c698bea41665 a186d89e95061a7887c005ffa8bd1e29362de2da  /Kiev.png\n3db1938bedc0ee0047bf3b043ddaf0aba1912f13 febab92af9526163bc9e502ecd7fa4225345e6f6  /?T\n2cc0ba7a57a6342e72fd7142ca18dbb0eae69416 ce7fb7a88cab697f5280ddabf344f0d397888956  /Киев\n928142e88da142ea8075cbfe09bfef349e72dbb1 0f86f59a45b4485fea1375ca945503d9abb9a96d  /Kiev?2\n4f6f0a16ff415fad1c102c8023c5d8365ef63402 de3b9821d587753149eded5411ec397e7a2000e2  /Kiev?format=1\nc99903b86971ccccfcca4f13e6fca72776b4fbcf f64086e48d84ac6eb440ca080eff28de1470ec30  /Kiev?format=2\n2a0d6cd8d30a84328580611ca6dd6bed1d805a04 da7b79cdff330edc1a7a78fcf2f9c8bf7e432d40  /Kiev?format=3\n4e4e15eeb6a8b6ddb5d00591c4b5e9b74a13e6bc 6a61305ea631fbccb98090c62a96898e8ffa0d75  /Kiev?format=4\na27d3e4ad7f820124ef57c9299715bc61cb71387 fed12e63dd5fb5e348ee30d94c7231112eca71cd  /Kiev?format=v2\ncbe9fc56091b519e6aebcedd9a7541241f4c4cda 2d97c405f1557b822cc86b038aeea40c3eb79d7d  /Kiev?format=%s\n84b79ec29670254c3570901e4c5db017516e088d 3f26bdbbd5faf7729f87a9cb964d407493e9a0d6  /Kiev?format=%S\n8a0111eb7a519adad1210661bbb49f960ba7f95f fe58cbd420cf36a910551a1037f5c4fa19b31074  /Kiev?format=%D+%S+%z+%s+%d\n83cc0ef08c24ad7ecc81d1a6cbd693bb06214ece 0ea998c1b53e452a373699ab953ab00e8a2870f0  /:help\n310b64f65fc9f66a5142bf6104f4f9b9d5eef0ea b0bd07f0c87aae9464c091ccb955f41ec6973098  /Kiev?T\n9bd1b460d4927df24724f45f69bd3132f3de8e04 d001bf6ab36b6c14f98f02fc4500706d7a9f05a8  /Kiev?p\n3ee1a25d436799804d7ebd8371d8022fa55a71d7 80f18be012d0471dce9fcd2b500f482bcd635347  /Kiev?q\ne0e8e7eca16bfac88503ac6d19a7a6c8b469c0fd d5d070c98237f0dffc82b176039f90a15f03a667  /Kiev?Q\nd08d1fa2546fee0717d1eb663cf63cd1505b8885 e380ef1a22f62a7fa1133d0e35d923c8587cb3ed  /Kiev_text=no_view=v2.png\nb14e89e2c183139495bad5404748b3b6173063d7 ff70b13244929fa3a934e94f99f019c66501ad43  /Kiev.png?1nqF\n04e1a945bdde39d646e397e55c096ec46b53a92b ff70b13244929fa3a934e94f99f019c66501ad43  /Kiev_1nqF.png\n3e1be80e942a2ea5450c60e1c0ebfb154aca3da1 6a5bdefe64689f4d05128bd62a8118f4f2f52043 -A firefox /\nee6bf0665c2719cda3ec1fbdb80413d821c99b8e 3f9c5091269ece259cce13fc842265019001ed54 -A firefox /Kiev\n98ef11678b7fd33425f97eeee70e00cd96206539 a186d89e95061a7887c005ffa8bd1e29362de2da -A firefox /Kiev.png\necbcf2cb9004a754c4559ce7e92fead68f71721a 2ea6d52a2108a481cbc0f44a881eb88642d68e80 -A firefox /?T\n74206d869128383dba2d840b848b90eb376fd851 7c6ce53ff25d91a5f46baa30077b69e0f09f2571 -A firefox /Киев\n91b89025b5acd56ca475924e0eb559a9734f3333 dbd49d93eff2b2cf82f7d266f90de950207a0561 -A firefox /Kiev?2\ne6cb82dab95e05167ffbcb90a10d6cb03cd02ec1 de3b9821d587753149eded5411ec397e7a2000e2 -A firefox /Kiev?format=1\ne65bc57e8d1df26c442a9ecf45afee390ff331a3 f64086e48d84ac6eb440ca080eff28de1470ec30 -A firefox /Kiev?format=2\nd743b331d5f4c81bbc8b168ce84a99ab22dc70cf da7b79cdff330edc1a7a78fcf2f9c8bf7e432d40 -A firefox /Kiev?format=3\nbf359ee92690c3a3061542dc6e78cb42ca837412 6a61305ea631fbccb98090c62a96898e8ffa0d75 -A firefox /Kiev?format=4\ncb875772a6610c991b95b3fbfa22fc7192e25843 5367fd6790d55639b1536ec71abf340e5c79ff45 -A firefox /Kiev?format=v2\n91c0076d8e6665c06aab7c7b2326b29718bfeb80 2d97c405f1557b822cc86b038aeea40c3eb79d7d -A firefox /Kiev?format=%s\nae9d7b1ee27eb8201a0726a3e24fe195cf2ae9e4 3f26bdbbd5faf7729f87a9cb964d407493e9a0d6 -A firefox /Kiev?format=%S\ne94371697b70bf956b6f9352fad913d716e774e7 fe58cbd420cf36a910551a1037f5c4fa19b31074 -A firefox /Kiev?format=%D+%S+%z+%s+%d\nd520af45b491689d53024c696955db8b1e4eaa87 e916b140b1297cf5bea16d92a91260e9dc3e2bc9 -A firefox /:help\n6b80492b79a4cc510cb4a9654cb6ff085cdc1943 801d4c6d6837c9604944168a3930dfe05b0e9f5d -A firefox /Kiev?T\ne13d7449ce756e55ba3e84e4b7e601b36d0044b6 c5a87804710ab70b8798f56579d276f4ce1806bf -A firefox /Kiev?p\n3f6c192a6da5b79ea59ef94e99b9cbf4b0e7ede2 372aca50f441920ad623d62ee8fcde46d609f6f9 -A firefox /Kiev?q\nf28ca2a7a47f4859eac7d0307ec7ac67a40e0adf 1b4b66d58bd7e27abeeca45581e686f12fefe76a -A firefox /Kiev?Q\n62c5029cf297b1434c57228dc8c8cdfb5e68285d e380ef1a22f62a7fa1133d0e35d923c8587cb3ed -A firefox /Kiev_text=no_view=v2.png\n22aa5dc06076b086de776a3c601544b250fef07c ff70b13244929fa3a934e94f99f019c66501ad43 -A firefox /Kiev.png?1nqF\n3a00ecab00da83f70c2abf30379c5e79c791e383 ff70b13244929fa3a934e94f99f019c66501ad43 -A firefox /Kiev_1nqF.png\ned573b89ca5522d6ab69dc1686b98b00391076bd 5ce7ea58bf02bff008baa3193b2db498268a244b -H Accept-Language:ru /\nb879673f66235bbf1913ff9abc58aff2fb8962d1 00a96a5d83608c2dad7921862bb3f244775f6b19 -H Accept-Language:ru /Kiev\n83d99896cf866ecbaa6d2c64c12bd31bc7b35068 92dc07acb93633974eaff19e8c1a99e590e140d9 -H Accept-Language:ru /Kiev.png\n9cbb6aa3e0b46e78229a32688db1cced9a44271d b368cc8f39e7a7ced04e3f4e6506e1eb4551e904 -H Accept-Language:ru /?T\n095d8d38c667923131801595b903e007b5f902f3 4ede3397f9def696adc7ecf3ffd46a59b8fb25cb -H Accept-Language:ru /Киев\n4e6cdfc38c9d9f2436438b345776c42cb8cab8a5 1b00c96a05f9daea8248a8e063d990797be933ad -H Accept-Language:ru /Kiev?2\nb7d8d0f0bb4c38aabac468c9a354bb4e2b401893 de3b9821d587753149eded5411ec397e7a2000e2 -H Accept-Language:ru /Kiev?format=1\n8f3bbfc9be6418e82edacecc54a9f3e9f26b7fbf f64086e48d84ac6eb440ca080eff28de1470ec30 -H Accept-Language:ru /Kiev?format=2\nf1d4178892fd3dc38e9f966112d317859acc9122 da7b79cdff330edc1a7a78fcf2f9c8bf7e432d40 -H Accept-Language:ru /Kiev?format=3\ncf44e154504d9bc2b9b6066bbb0f5d52fc12f13e 6a61305ea631fbccb98090c62a96898e8ffa0d75 -H Accept-Language:ru /Kiev?format=4\n4955c849f67da53203b8c96b15a0bf0a4a471bc6 e2d3509ef7f6c3fc84151f55e1c5eb2f28dfd155 -H Accept-Language:ru /Kiev?format=v2\ne23e33569bbe34de944dad3a647d2a7a525513b4 2d97c405f1557b822cc86b038aeea40c3eb79d7d -H Accept-Language:ru /Kiev?format=%s\nd3c44cb57a1ba487b9fe7ec37368d00eee5b4601 3f26bdbbd5faf7729f87a9cb964d407493e9a0d6 -H Accept-Language:ru /Kiev?format=%S\ndb91cc89883050beedd2afac7c74276a4d2dcf42 fe58cbd420cf36a910551a1037f5c4fa19b31074 -H Accept-Language:ru /Kiev?format=%D+%S+%z+%s+%d\n3f69f4a605ce88643b4e0d62a588c92625d41aea 73b4142cd3af43472897989c61408d5765c2a6ef -H Accept-Language:ru /:help\n08553ca4bf71c738c4321fe7d84b4e6ff830956f 016fc03b18a8902f838719bbc171184603c08b60 -H Accept-Language:ru /Kiev?T\nb70f8b3fc8aee126c04b27b0d3b4c503b4292cbf b60b68a9e77275884812f7e52b06f6012ba5682a -H Accept-Language:ru /Kiev?p\n400efdba61125f8cb850d7c33caf4fc2739a960b 5ee4a043a91509ef57aec46a14a0c24f09e8ec47 -H Accept-Language:ru /Kiev?q\nb9fd454e73343f262a6d99dd80487495bd647c6f a10718896a07baadb87adf2bf0026b1f00252213 -H Accept-Language:ru /Kiev?Q\n8fed034e57624d0e0b33140673094e56e04087bc 83d236565782aff7416bf526b38636148d6ba15a -H Accept-Language:ru /Kiev_text=no_view=v2.png\ncf618118ddeff08355620e83a693c40239990545 37a4dd271b5a66513da4a6dc9caeab0ae15814db -H Accept-Language:ru /Kiev.png?1nqF\n0f106ea5605ecc852ab6f63eee348a9a954e137f 37a4dd271b5a66513da4a6dc9caeab0ae15814db -H Accept-Language:ru /Kiev_1nqF.png\n3ce3dd46413f236244410f142a4b44356a0cedf9 1c2eea391b35c8bfed2541435e1788307aa06bc1 -H X-Forwarded-For:1.1.1.1 /\n89be0a5787592298ce34f10b36da7ee87d1a1353 d123e570da22dee9798d353c4281cb5a2bdbaeac -H X-Forwarded-For:1.1.1.1 /Kiev\na9977eadc628b1ede5d4f91ee103dfb740caa2b1 a186d89e95061a7887c005ffa8bd1e29362de2da -H X-Forwarded-For:1.1.1.1 /Kiev.png\neec20c6be5e528967cddf6d0b72c84dbda553d43 9a39dbafa7e1550d374e38059c0f4b8f437e1739 -H X-Forwarded-For:1.1.1.1 /?T\ne304153f0e1e9b41781bf4eb6fb6c4a5b7513aec ce7fb7a88cab697f5280ddabf344f0d397888956 -H X-Forwarded-For:1.1.1.1 /Киев\n98f0b3a28863a861c6ac6d89ee5d49adb7f3f518 0f86f59a45b4485fea1375ca945503d9abb9a96d -H X-Forwarded-For:1.1.1.1 /Kiev?2\ncf04d7fe2cf36eba8d7fb4fa6def1c9015036456 de3b9821d587753149eded5411ec397e7a2000e2 -H X-Forwarded-For:1.1.1.1 /Kiev?format=1\n67fbe9168566709450eb35d36c60c27105335a7e f64086e48d84ac6eb440ca080eff28de1470ec30 -H X-Forwarded-For:1.1.1.1 /Kiev?format=2\nb2604348bf39774c85b7c18ae7b51f63a2c9f31a da7b79cdff330edc1a7a78fcf2f9c8bf7e432d40 -H X-Forwarded-For:1.1.1.1 /Kiev?format=3\ncf012400156c842e569b6a9f05b094e6b75348cd 6a61305ea631fbccb98090c62a96898e8ffa0d75 -H X-Forwarded-For:1.1.1.1 /Kiev?format=4\n1f4981348cab19df9846cd3b3923ee7a972ff9fa fed12e63dd5fb5e348ee30d94c7231112eca71cd -H X-Forwarded-For:1.1.1.1 /Kiev?format=v2\ne7d772042819bb62e6e259656a75bd7b0621d1da 2d97c405f1557b822cc86b038aeea40c3eb79d7d -H X-Forwarded-For:1.1.1.1 /Kiev?format=%s\n7db5a1daac653383c18aec25ad8583f2e5296845 3f26bdbbd5faf7729f87a9cb964d407493e9a0d6 -H X-Forwarded-For:1.1.1.1 /Kiev?format=%S\na9331379fa4b5d61b5a87a8e4cd4412cdae970a1 fe58cbd420cf36a910551a1037f5c4fa19b31074 -H X-Forwarded-For:1.1.1.1 /Kiev?format=%D+%S+%z+%s+%d\n767a7407c14049fd77a6a2fedd1d8b35f6e47e0d 0ea998c1b53e452a373699ab953ab00e8a2870f0 -H X-Forwarded-For:1.1.1.1 /:help\n10631d55b42e7bc5ec15ffc5cddae712785eb354 b0bd07f0c87aae9464c091ccb955f41ec6973098 -H X-Forwarded-For:1.1.1.1 /Kiev?T\n031478f562663eb9f577b04032993e2f098146f6 d001bf6ab36b6c14f98f02fc4500706d7a9f05a8 -H X-Forwarded-For:1.1.1.1 /Kiev?p\ne106cd21a6b67196159c2baa023142e3a8859612 80f18be012d0471dce9fcd2b500f482bcd635347 -H X-Forwarded-For:1.1.1.1 /Kiev?q\n1a16c9b52ba90cb7ad3dd8902bf41b31a287d49e d5d070c98237f0dffc82b176039f90a15f03a667 -H X-Forwarded-For:1.1.1.1 /Kiev?Q\n83bd9cc6a646e44b75524474dd32f0fd1f5c5a39 e380ef1a22f62a7fa1133d0e35d923c8587cb3ed -H X-Forwarded-For:1.1.1.1 /Kiev_text=no_view=v2.png\nac8dabb4d30cf6a6fae626e6fc29a4f2d9df0164 ff70b13244929fa3a934e94f99f019c66501ad43 -H X-Forwarded-For:1.1.1.1 /Kiev.png?1nqF\nf0b3c0851a03a9b182ab938fc7f14935bf7af1f0 ff70b13244929fa3a934e94f99f019c66501ad43 -H X-Forwarded-For:1.1.1.1 /Kiev_1nqF.png\n"
  }
]