diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..15f45d7 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,84 @@ +name: CI + +on: + - push + - pull_request + +jobs: + Build: + runs-on: ubuntu-20.04 + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.9 + + - name: Install pipenv + run: pip install pipenv + + - id: cache-pipenv + name: Download cache + uses: actions/cache@v2 + with: + path: ~/.local/share/virtualenvs + key: ${{ runner.os }}-pipenv-${{ hashFiles('**/Pipfile.lock') }} + + - name: Install dependencies + if: steps.cache-pipenv.outputs.cache-hit != 'true' + run: pipenv install --deploy --dev + + - name: Build gettext strings + run: pipenv run sphinx-build -b gettext source build/locale + + - name: Push and Pull strings from the Crowdin + uses: crowdin/github-action@1.1.0 + # TODO: remove upgrade branch after finishing upgrading process + if: contains(fromJson('["refs/heads/master", "refs/heads/upgrade"]'), github.ref) + with: + token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} + + upload_sources: true + + download_translations: true + push_translations: false + download_language: en # Temporary limit only to English + + - name: Fix permissions to the locale dir + run: sudo chown -R $USER:$USER locale + + - name: Build docs + run: pipenv run python build-multilang.py + + - name: Upload build artifacts + uses: actions/upload-artifact@v2 + with: + name: build + path: build + retention-days: 7 + + Deploy: + runs-on: ubuntu-latest + needs: Build + # TODO: remove upgrade branch after finishing upgrading process + if: contains(fromJson('["refs/heads/master", "refs/heads/upgrade"]'), github.ref) + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - id: download + name: Download build artifacts + uses: actions/download-artifact@v2 + with: + name: build + + - name: Deploy to the GitHub Pages + uses: JamesIves/github-pages-deploy-action@4.1.0 + with: + branch: gh-pages + folder: ${{ steps.download.outputs.download-path }} + single-commit: true diff --git a/.gitignore b/.gitignore index b24904a..e08409d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ ### venv folder /venv + +### The directory for the locales from the Crowdin +/locale diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 260e264..0000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -os: linux -dist: xenial -language: python - -cache: pip - -install: - - pip install -r requirements.txt - -script: - - sphinx-build source build - -deploy: - provider: pages - strategy: git - skip_cleanup: true - local_dir: ./build - token: $GITHUB_TOKEN - on: - branch: master diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..3adf7cf --- /dev/null +++ b/Pipfile @@ -0,0 +1,16 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +Sphinx = ">=3.0,<4.0" +sphinx-rtd-theme = "~=0.5.1" + +[dev-packages] +lxml = ">=4.6.2,<5.0" +sphinx-autobuild = ">=2020.09.01" +sphinx-intl = ">=2.0,<3.0" + +[requires] +python_version = "3.9" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..c4fa440 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,626 @@ +{ + "_meta": { + "hash": { + "sha256": "f276bc0ed2af04e02fbf86b128186f6c4632d643f77c387892d9c775dbfb068f" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.9" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "alabaster": { + "hashes": [ + "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", + "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" + ], + "version": "==0.7.12" + }, + "babel": { + "hashes": [ + "sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5", + "sha256:da031ab54472314f210b0adcff1588ee5d1d1d0ba4dbd07b94dba82bde791e05" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.9.0" + }, + "certifi": { + "hashes": [ + "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", + "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" + ], + "version": "==2020.12.5" + }, + "chardet": { + "hashes": [ + "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", + "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==4.0.0" + }, + "docutils": { + "hashes": [ + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.16" + }, + "idna": { + "hashes": [ + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.10" + }, + "imagesize": { + "hashes": [ + "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", + "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.2.0" + }, + "jinja2": { + "hashes": [ + "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419", + "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.11.3" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f", + "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014", + "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85", + "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850", + "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1", + "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5", + "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c", + "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be", + "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.1.1" + }, + "packaging": { + "hashes": [ + "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5", + "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==20.9" + }, + "pygments": { + "hashes": [ + "sha256:2656e1a6edcdabf4275f9a3640db59fd5de107d88e8663c5d4e9a0fa62f77f94", + "sha256:534ef71d539ae97d4c3a4cf7d6f110f214b0e687e92f9cb9d2a3b0d3101289c8" + ], + "markers": "python_version >= '3.5'", + "version": "==2.8.1" + }, + "pyparsing": { + "hashes": [ + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.7" + }, + "pytz": { + "hashes": [ + "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da", + "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798" + ], + "version": "==2021.1" + }, + "requests": { + "hashes": [ + "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", + "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.25.1" + }, + "snowballstemmer": { + "hashes": [ + "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2", + "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914" + ], + "version": "==2.1.0" + }, + "sphinx": { + "hashes": [ + "sha256:672cfcc24b6b69235c97c750cb190a44ecd72696b4452acaf75c2d9cc78ca5ff", + "sha256:ef64a814576f46ec7de06adf11b433a0d6049be007fefe7fd0d183d28b581fac" + ], + "index": "pypi", + "version": "==3.5.2" + }, + "sphinx-rtd-theme": { + "hashes": [ + "sha256:eda689eda0c7301a80cf122dad28b1861e5605cbf455558f3775e1e8200e83a5", + "sha256:fa6bebd5ab9a73da8e102509a86f3fcc36dec04a0b52ea80e5a033b2aba00113" + ], + "index": "pypi", + "version": "==0.5.1" + }, + "sphinxcontrib-applehelp": { + "hashes": [ + "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", + "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.2" + }, + "sphinxcontrib-devhelp": { + "hashes": [ + "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e", + "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.2" + }, + "sphinxcontrib-htmlhelp": { + "hashes": [ + "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f", + "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.3" + }, + "sphinxcontrib-jsmath": { + "hashes": [ + "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", + "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.1" + }, + "sphinxcontrib-qthelp": { + "hashes": [ + "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72", + "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.3" + }, + "sphinxcontrib-serializinghtml": { + "hashes": [ + "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc", + "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a" + ], + "markers": "python_version >= '3.5'", + "version": "==1.1.4" + }, + "urllib3": { + "hashes": [ + "sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df", + "sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", + "version": "==1.26.4" + } + }, + "develop": { + "alabaster": { + "hashes": [ + "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", + "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" + ], + "version": "==0.7.12" + }, + "babel": { + "hashes": [ + "sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5", + "sha256:da031ab54472314f210b0adcff1588ee5d1d1d0ba4dbd07b94dba82bde791e05" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.9.0" + }, + "certifi": { + "hashes": [ + "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", + "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" + ], + "version": "==2020.12.5" + }, + "chardet": { + "hashes": [ + "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", + "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==4.0.0" + }, + "click": { + "hashes": [ + "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", + "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==7.1.2" + }, + "colorama": { + "hashes": [ + "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b", + "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.4.4" + }, + "docutils": { + "hashes": [ + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.16" + }, + "idna": { + "hashes": [ + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.10" + }, + "imagesize": { + "hashes": [ + "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", + "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.2.0" + }, + "jinja2": { + "hashes": [ + "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419", + "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.11.3" + }, + "livereload": { + "hashes": [ + "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869" + ], + "version": "==2.6.3" + }, + "lxml": { + "hashes": [ + "sha256:0448576c148c129594d890265b1a83b9cd76fd1f0a6a04620753d9a6bcfd0a4d", + "sha256:127f76864468d6630e1b453d3ffbbd04b024c674f55cf0a30dc2595137892d37", + "sha256:1471cee35eba321827d7d53d104e7b8c593ea3ad376aa2df89533ce8e1b24a01", + "sha256:2363c35637d2d9d6f26f60a208819e7eafc4305ce39dc1d5005eccc4593331c2", + "sha256:2e5cc908fe43fe1aa299e58046ad66981131a66aea3129aac7770c37f590a644", + "sha256:2e6fd1b8acd005bd71e6c94f30c055594bbd0aa02ef51a22bbfa961ab63b2d75", + "sha256:366cb750140f221523fa062d641393092813b81e15d0e25d9f7c6025f910ee80", + "sha256:42ebca24ba2a21065fb546f3e6bd0c58c3fe9ac298f3a320147029a4850f51a2", + "sha256:4e751e77006da34643ab782e4a5cc21ea7b755551db202bc4d3a423b307db780", + "sha256:4fb85c447e288df535b17ebdebf0ec1cf3a3f1a8eba7e79169f4f37af43c6b98", + "sha256:50c348995b47b5a4e330362cf39fc503b4a43b14a91c34c83b955e1805c8e308", + "sha256:535332fe9d00c3cd455bd3dd7d4bacab86e2d564bdf7606079160fa6251caacf", + "sha256:535f067002b0fd1a4e5296a8f1bf88193080ff992a195e66964ef2a6cfec5388", + "sha256:5be4a2e212bb6aa045e37f7d48e3e1e4b6fd259882ed5a00786f82e8c37ce77d", + "sha256:60a20bfc3bd234d54d49c388950195d23a5583d4108e1a1d47c9eef8d8c042b3", + "sha256:648914abafe67f11be7d93c1a546068f8eff3c5fa938e1f94509e4a5d682b2d8", + "sha256:681d75e1a38a69f1e64ab82fe4b1ed3fd758717bed735fb9aeaa124143f051af", + "sha256:68a5d77e440df94011214b7db907ec8f19e439507a70c958f750c18d88f995d2", + "sha256:69a63f83e88138ab7642d8f61418cf3180a4d8cd13995df87725cb8b893e950e", + "sha256:6e4183800f16f3679076dfa8abf2db3083919d7e30764a069fb66b2b9eff9939", + "sha256:6fd8d5903c2e53f49e99359b063df27fdf7acb89a52b6a12494208bf61345a03", + "sha256:791394449e98243839fa822a637177dd42a95f4883ad3dec2a0ce6ac99fb0a9d", + "sha256:7a7669ff50f41225ca5d6ee0a1ec8413f3a0d8aa2b109f86d540887b7ec0d72a", + "sha256:7e9eac1e526386df7c70ef253b792a0a12dd86d833b1d329e038c7a235dfceb5", + "sha256:7ee8af0b9f7de635c61cdd5b8534b76c52cd03536f29f51151b377f76e214a1a", + "sha256:8246f30ca34dc712ab07e51dc34fea883c00b7ccb0e614651e49da2c49a30711", + "sha256:8c88b599e226994ad4db29d93bc149aa1aff3dc3a4355dd5757569ba78632bdf", + "sha256:923963e989ffbceaa210ac37afc9b906acebe945d2723e9679b643513837b089", + "sha256:94d55bd03d8671686e3f012577d9caa5421a07286dd351dfef64791cf7c6c505", + "sha256:97db258793d193c7b62d4e2586c6ed98d51086e93f9a3af2b2034af01450a74b", + "sha256:a9d6bc8642e2c67db33f1247a77c53476f3a166e09067c0474facb045756087f", + "sha256:cd11c7e8d21af997ee8079037fff88f16fda188a9776eb4b81c7e4c9c0a7d7fc", + "sha256:d8d3d4713f0c28bdc6c806a278d998546e8efc3498949e3ace6e117462ac0a5e", + "sha256:e0bfe9bb028974a481410432dbe1b182e8191d5d40382e5b8ff39cdd2e5c5931", + "sha256:f4822c0660c3754f1a41a655e37cb4dbbc9be3d35b125a37fab6f82d47674ebc", + "sha256:f83d281bb2a6217cd806f4cf0ddded436790e66f393e124dfe9731f6b3fb9afe", + "sha256:fc37870d6716b137e80d19241d0e2cff7a7643b925dfa49b4c8ebd1295eb506e" + ], + "index": "pypi", + "version": "==4.6.2" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f", + "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014", + "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85", + "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850", + "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1", + "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5", + "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c", + "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be", + "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.1.1" + }, + "packaging": { + "hashes": [ + "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5", + "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==20.9" + }, + "pygments": { + "hashes": [ + "sha256:2656e1a6edcdabf4275f9a3640db59fd5de107d88e8663c5d4e9a0fa62f77f94", + "sha256:534ef71d539ae97d4c3a4cf7d6f110f214b0e687e92f9cb9d2a3b0d3101289c8" + ], + "markers": "python_version >= '3.5'", + "version": "==2.8.1" + }, + "pyparsing": { + "hashes": [ + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.7" + }, + "pytz": { + "hashes": [ + "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da", + "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798" + ], + "version": "==2021.1" + }, + "requests": { + "hashes": [ + "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", + "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.25.1" + }, + "six": { + "hashes": [ + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.15.0" + }, + "snowballstemmer": { + "hashes": [ + "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2", + "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914" + ], + "version": "==2.1.0" + }, + "sphinx": { + "hashes": [ + "sha256:672cfcc24b6b69235c97c750cb190a44ecd72696b4452acaf75c2d9cc78ca5ff", + "sha256:ef64a814576f46ec7de06adf11b433a0d6049be007fefe7fd0d183d28b581fac" + ], + "index": "pypi", + "version": "==3.5.2" + }, + "sphinx-autobuild": { + "hashes": [ + "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac", + "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05" + ], + "index": "pypi", + "version": "==2021.3.14" + }, + "sphinx-intl": { + "hashes": [ + "sha256:2ff97cba0e4e43249e339a3c29dd2f5b63c25ce794050aabca320ad95f5c5b55", + "sha256:b25a6ec169347909e8d983eefe2d8adecb3edc2f27760db79b965c69950638b4" + ], + "index": "pypi", + "version": "==2.0.1" + }, + "sphinxcontrib-applehelp": { + "hashes": [ + "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", + "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.2" + }, + "sphinxcontrib-devhelp": { + "hashes": [ + "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e", + "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.2" + }, + "sphinxcontrib-htmlhelp": { + "hashes": [ + "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f", + "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.3" + }, + "sphinxcontrib-jsmath": { + "hashes": [ + "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", + "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.1" + }, + "sphinxcontrib-qthelp": { + "hashes": [ + "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72", + "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.3" + }, + "sphinxcontrib-serializinghtml": { + "hashes": [ + "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc", + "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a" + ], + "markers": "python_version >= '3.5'", + "version": "==1.1.4" + }, + "tornado": { + "hashes": [ + "sha256:0a00ff4561e2929a2c37ce706cb8233b7907e0cdc22eab98888aca5dd3775feb", + "sha256:0d321a39c36e5f2c4ff12b4ed58d41390460f798422c4504e09eb5678e09998c", + "sha256:1e8225a1070cd8eec59a996c43229fe8f95689cb16e552d130b9793cb570a288", + "sha256:20241b3cb4f425e971cb0a8e4ffc9b0a861530ae3c52f2b0434e6c1b57e9fd95", + "sha256:25ad220258349a12ae87ede08a7b04aca51237721f63b1808d39bdb4b2164558", + "sha256:33892118b165401f291070100d6d09359ca74addda679b60390b09f8ef325ffe", + "sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791", + "sha256:3447475585bae2e77ecb832fc0300c3695516a47d46cefa0528181a34c5b9d3d", + "sha256:34ca2dac9e4d7afb0bed4677512e36a52f09caa6fded70b4e3e1c89dbd92c326", + "sha256:3e63498f680547ed24d2c71e6497f24bca791aca2fe116dbc2bd0ac7f191691b", + "sha256:548430be2740e327b3fe0201abe471f314741efcb0067ec4f2d7dcfb4825f3e4", + "sha256:6196a5c39286cc37c024cd78834fb9345e464525d8991c21e908cc046d1cc02c", + "sha256:61b32d06ae8a036a6607805e6720ef00a3c98207038444ba7fd3d169cd998910", + "sha256:6286efab1ed6e74b7028327365cf7346b1d777d63ab30e21a0f4d5b275fc17d5", + "sha256:65d98939f1a2e74b58839f8c4dab3b6b3c1ce84972ae712be02845e65391ac7c", + "sha256:66324e4e1beede9ac79e60f88de548da58b1f8ab4b2f1354d8375774f997e6c0", + "sha256:6c77c9937962577a6a76917845d06af6ab9197702a42e1346d8ae2e76b5e3675", + "sha256:70dec29e8ac485dbf57481baee40781c63e381bebea080991893cd297742b8fd", + "sha256:7250a3fa399f08ec9cb3f7b1b987955d17e044f1ade821b32e5f435130250d7f", + "sha256:748290bf9112b581c525e6e6d3820621ff020ed95af6f17fedef416b27ed564c", + "sha256:7da13da6f985aab7f6f28debab00c67ff9cbacd588e8477034c0652ac141feea", + "sha256:8f959b26f2634a091bb42241c3ed8d3cedb506e7c27b8dd5c7b9f745318ddbb6", + "sha256:9de9e5188a782be6b1ce866e8a51bc76a0fbaa0e16613823fc38e4fc2556ad05", + "sha256:a48900ecea1cbb71b8c71c620dee15b62f85f7c14189bdeee54966fbd9a0c5bd", + "sha256:b87936fd2c317b6ee08a5741ea06b9d11a6074ef4cc42e031bc6403f82a32575", + "sha256:c77da1263aa361938476f04c4b6c8916001b90b2c2fdd92d8d535e1af48fba5a", + "sha256:cb5ec8eead331e3bb4ce8066cf06d2dfef1bfb1b2a73082dfe8a161301b76e37", + "sha256:cc0ee35043162abbf717b7df924597ade8e5395e7b66d18270116f8745ceb795", + "sha256:d14d30e7f46a0476efb0deb5b61343b1526f73ebb5ed84f23dc794bdb88f9d9f", + "sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32", + "sha256:d3d20ea5782ba63ed13bc2b8c291a053c8d807a8fa927d941bd718468f7b950c", + "sha256:d3f7594930c423fd9f5d1a76bee85a2c36fd8b4b16921cae7e965f22575e9c01", + "sha256:dcef026f608f678c118779cd6591c8af6e9b4155c44e0d1bc0c87c036fb8c8c4", + "sha256:e0791ac58d91ac58f694d8d2957884df8e4e2f6687cdf367ef7eb7497f79eaa2", + "sha256:e385b637ac3acaae8022e7e47dfa7b83d3620e432e3ecb9a3f7f58f150e50921", + "sha256:e519d64089b0876c7b467274468709dadf11e41d65f63bba207e04217f47c085", + "sha256:e7229e60ac41a1202444497ddde70a48d33909e484f96eb0da9baf8dc68541df", + "sha256:ed3ad863b1b40cd1d4bd21e7498329ccaece75db5a5bf58cd3c9f130843e7102", + "sha256:f0ba29bafd8e7e22920567ce0d232c26d4d47c8b5cf4ed7b562b5db39fa199c5", + "sha256:fa2ba70284fa42c2a5ecb35e322e68823288a4251f9ba9cc77be04ae15eada68", + "sha256:fba85b6cd9c39be262fcd23865652920832b61583de2a2ca907dbd8e8a8c81e5" + ], + "markers": "python_version >= '3.5'", + "version": "==6.1" + }, + "urllib3": { + "hashes": [ + "sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df", + "sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", + "version": "==1.26.4" + } + } +} diff --git a/_config.yml b/_config.yml deleted file mode 100644 index f3d2650..0000000 --- a/_config.yml +++ /dev/null @@ -1,5 +0,0 @@ -include: - - _downloads - - _images - - _sources - - _static diff --git a/build-multilang.py b/build-multilang.py new file mode 100755 index 0000000..7f8348a --- /dev/null +++ b/build-multilang.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python + +import os +import re +import shutil +import subprocess +import sys + +from glob import glob +from pathlib import Path +from lxml import html, etree + +base_lang: str = "ru" +build_dir: str = "build" +per_lang_static: list[str] = [ + r"documentation_options\.js", + r"language_data\.js", + r"^(?!basic)\w+-stemmer\.js", + r"translations\.js", +] + +# Cleanup +shutil.rmtree(build_dir, True) +os.mkdir(build_dir) + +# Build languages +def sphinx_build(lang: str) -> None: + subprocess.run([ + sys.executable, "-m", "sphinx", + "-b", "html", + "-D", f"language={lang}", + "source", + f"{build_dir}/{lang}", + ]) + +languages: list[str] = [base_lang] +if os.path.isdir("locale"): + languages += os.listdir("locale") + +index_page_lang: str = "en" if "en" in languages else base_lang + +for lang in languages: + sphinx_build(lang) + +# Extract common assets +for i, lang in enumerate(languages): + if i == 0: + os.rename(f"{build_dir}/{lang}/_downloads", f"{build_dir}/_downloads") + os.rename(f"{build_dir}/{lang}/_images", f"{build_dir}/_images") + os.rename(f"{build_dir}/{lang}/CNAME", f"{build_dir}/CNAME") + os.rename(f"{build_dir}/{lang}/.nojekyll", f"{build_dir}/.nojekyll") + else: + shutil.rmtree(f"{build_dir}/{lang}/_downloads") + shutil.rmtree(f"{build_dir}/{lang}/_images") + os.remove(f"{build_dir}/{lang}/CNAME") + os.remove(f"{build_dir}/{lang}/.nojekyll") + + for static_file in glob(f"{build_dir}/{lang}/_static/**/*", recursive=True): + if not os.path.isfile(static_file): + continue + + relative_path = static_file.removeprefix(f"{build_dir}/{lang}/_static/") + matched: bool = False + for pattern in per_lang_static: + if re.match(pattern, relative_path): + matched = True + break + + # I have no idea how to make "continue 2" from the loop above so... + if matched: + continue + + dir = os.path.dirname(relative_path) + os.makedirs(f"{build_dir}/_static/{dir}", exist_ok=True) + os.rename(static_file, f"{build_dir}/_static/{relative_path}") + + shutil.rmtree(f"{build_dir}/{lang}/_sources") + shutil.rmtree(f"{build_dir}/{lang}/.doctrees") + os.remove(f"{build_dir}/{lang}/.buildinfo") + os.remove(f"{build_dir}/{lang}/objects.inv") + +# Convert all relative routes into absolute +def make_links_absolute(file_path: str, link: str) -> str: + # Skip local anchor links + if link.startswith("#"): + return link + + # Skip external links (including links without protocol "//ely.by") + if link.startswith("//") or re.match(r"^https?://", link): + return link + + if ".html" in link: + working_directory = os.getcwd() + os.chdir(Path(file_path).parent.absolute()) + resolved = str(Path(link).resolve()) + os.chdir(working_directory) + + link = resolved.removeprefix(f"{working_directory}/{build_dir}") + link = link.replace("\\", "/") # fix for the Windows + + return link + + # Other links are links to some static assets + # There is no need to resolve relative links since _static is placed in the root directory, + # so after removing all ../ parts we can safely append / to make the path absolute + while link.startswith("../"): + link = link.removeprefix("../") + + no_static_link = link.removeprefix("_static/") + for pattern in per_lang_static: + if re.match(pattern, no_static_link): + lang = re.match(fr"^{build_dir}/(\w+)/", file_path).group(1) + + return f"/{lang}/{link}" + + return f"/{link}" + +for file in glob(f"{build_dir}/**/*.html", recursive=True): + tree = html.parse(file) # type: etree._ElementTree + root = tree.getroot() # type: html.HtmlElement + + root.rewrite_links(lambda link: make_links_absolute(file, link)) + + tree.write(file, method="html", encoding="UTF-8") + +# Create index.html for the site root +shutil.copyfile(f"{build_dir}/{index_page_lang}/index.html", f"{build_dir}/index.html") +index_file_tree = html.parse(f"{build_dir}/index.html") # type: etree._ElementTree +index_file_root = index_file_tree.getroot() # type: html.HtmlElement +index_file_last_toctree = index_file_root.find_class("toctree-wrapper")[0] # type: html.HtmlElement + +for lang in languages: + if lang == index_page_lang: + continue + + tree = html.parse(f"{build_dir}/{lang}/index.html") # type: etree._ElementTree + root = tree.getroot() # type: html.HtmlElement + + toctree = root.find_class("toctree-wrapper")[0] # type: html.HtmlElement + index_file_last_toctree.addnext(toctree) + + index_file_last_toctree = index_file_root.find_class("toctree-wrapper")[-1] # type: html.HtmlElement + +index_file_tree.write(f"{build_dir}/index.html", method="html", encoding="UTF-8") + +# Add cross-lang links to the sidebar +sidebar_menus: dict[str, html.HtmlElement] = {} +for lang in languages: + tree = html.parse(f"{build_dir}/{lang}/index.html") # type: etree._ElementTree + root = tree.getroot() # type: html.HtmlElement + + sidebar_menus[lang] = root.find_class("wy-menu")[0] + +for file in glob(f"{build_dir}/**/*.html") + [f"{build_dir}/index.html"]: + result = re.match(fr"^{build_dir}/(\w+)/", file) + lang: str = result.group(1) if result is not None else index_page_lang + + tree = html.parse(file) # type: etree._ElementTree + root = tree.getroot() # type: html.HtmlElement + + sidebar_menu_last = root.find_class("wy-menu")[0] # type: html.HtmlElement + for menuLang in sidebar_menus: + if menuLang == lang: + continue + + sidebar_menu_last.addnext(sidebar_menus[menuLang]) + sidebar_menu_last = root.find_class("wy-menu")[-1] # type: html.HtmlElement + + tree.write(file, method="html", encoding="UTF-8") diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 0000000..2a3bf0c --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,8 @@ +api_token_env: CROWDIN_PERSONAL_TOKEN +base_url: https://ely.crowdin.com +project_id : 2 +preserve_hierarchy: true + +files: + - source: build/locale/*.pot + translation: locale/%two_letters_code%/LC_MESSAGES/%file_name%.po diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index d4e27e6..0000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -Sphinx~=3.0.0 -sphinx-rtd-theme~=0.4.3 -sphinx-autobuild~=0.7.1 diff --git a/source/_templates/layout.html b/source/_templates/layout.html index b47d6c2..9d39c7d 100644 --- a/source/_templates/layout.html +++ b/source/_templates/layout.html @@ -17,4 +17,3 @@ {% endblock %} - diff --git a/source/api.html b/source/api.html deleted file mode 100644 index a38349b..0000000 --- a/source/api.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/source/ru/api.rst b/source/api.rst similarity index 59% rename from source/ru/api.rst rename to source/api.rst index 8770110..5de6e25 100644 --- a/source/ru/api.rst +++ b/source/api.rst @@ -1,38 +1,25 @@ Ely.by API (симуляция Mojang API) --------------------------------- -Здесь приведена информация об API, совместимом с функционалом `Mojang Api `_. Обращаем ваше -внимание на то, что это не полноценное API Ely.by, а только набор дополнительных запросов, реализованных на базе нашего -`сервера авторизации `_. - -Заметки -======= - -* API не имеет ограничения на количество запросов. У нас есть просто настроенный fail2ban, который будет банить особо - надоедливых клиентов. Такие дела. +Здесь приведена информация об API, совместимом с функционалом `Mojang Api `_. Обращаем ваше внимание на то, что это не полноценное API Ely.by, а только набор дополнительных запросов, реализованных на базе нашего :doc:`сервера авторизации `. Запросы ======= -В этой секции будут описаны запросы и их же варианты для Mojang API. Все запросы выполняются на базовый url -``https://authserver.ely.by``. +.. note:: API не имеет ограничения на количество запросов. У нас есть просто настроенный fail2ban, который будет банить особо надоедливых клиентов. Такие дела. + +В этой секции будут описаны запросы и их же варианты для Mojang API. Все запросы выполняются на базовый url ``https://authserver.ely.by``. UUID по нику на время ~~~~~~~~~~~~~~~~~~~~~ -Данный запрос позволяет узнать UUID пользователя по его нику на указанный момент времени. Время задаётся через GET -параметр at с unitx timestamp. - -.. note:: На самом деле Ely.by пока не запоминает период смены ника и не обращает внимание на этот запрос. Тем не менее - параметр в будущем будет дореализован. +Данный запрос позволяет узнать UUID пользователя по его нику на указанный момент времени. Время задаётся через GET параметр at с unix timestamp. .. function:: GET /api/users/profiles/minecraft/{username} - Где username - искомый ник пользователя. Он может быть передан в любом регистре (В Mojang API только строгое - совпадение). + Где ``{username}`` — искомый ник пользователя. Он может быть передан в любом регистре (В Mojang API только строгое совпадение). - Обратите так же внимание, что параметры legacy и demo никогда не будут возвращены, т.к. эти параметры не имеют в Ely - альтернативы и специфичны только для сервисов Mojang. + Обратите так же внимание, что параметры legacy и demo никогда не будут возвращены, т.к. эти параметры не имеют в Ely альтернативы и специфичны только для сервисов Mojang. В случае успешного запроса вы получите следующий ответ сервера: @@ -43,7 +30,7 @@ UUID по нику на время "name": "ErickSkrauch" } -В случае, если переданный ник не будет найден, вы получите ответ с 204 статусом и пустым телом. +В случае, если переданный ник не будет найден, вы получите ответ с ``204`` статусом и пустым телом. Никнейм по UUID + история изменений ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -52,8 +39,7 @@ UUID по нику на время .. function:: GET /api/user/profiles/{uuid}/names - Где uuid - валиданый UUID. Валидным будет считаться UUID, написанный через дефисы или без них. В случае передачи - невалидной строки, будет возвращён IllegalArgumentException_ с сообщением ``"Invalid uuid format."``. + Где ``{uuid}`` — валидный UUID. Валидным будет считаться UUID, написанный через дефисы или без них. В случае передачи невалидной строки, будет возвращён IllegalArgumentException_ с сообщением ``"Invalid uuid format."``. В случае успешного запроса вы получите следующий ответ сервера: @@ -69,10 +55,9 @@ UUID по нику на время } ] -.. note:: Т.к. на Ely.by не реализован алгоритм запоминания момента смены ника, будет возвращаться только 1 элемент. - Чуть позже мы добавим полноценную поддержку запоминания момента смены ника. +.. note:: Т.к. на Ely.by не реализован алгоритм запоминания момента смены ника, будет возвращаться только 1 элемент. Чуть позже мы добавим полноценную поддержку запоминания момента смены ника. -В случае, если переданный UUID не будет найден, вы получите ответ с 204 статусом и пустым телом. +В случае, если переданный UUID не будет найден, вы получите ответ с ``204`` статусом и пустым телом. Список никнеймов в их UUID ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -83,10 +68,7 @@ UUID по нику на время В теле запроса или POST параметрах необходимо передать валидный JSON массив искомых ников. - В массиве должно быть не более 100 ников, в противном случае будет возвращён IllegalArgumentException_ с сообщением - ``"Not more that 100 profile name per call is allowed."``. В случае, если переданная строка окажется невалидным - JSON объектом, будет возвращёно это же исключение, только с текстом ``"Passed array of profile names is an invalid - JSON string."``. + В массиве должно быть не более 100 ников, в противном случае будет возвращён IllegalArgumentException_ с сообщением ``"Not more that 100 profile name per call is allowed."``. В случае, если переданная строка окажется невалидным JSON объектом, будет возвращено это же исключение, только с текстом ``"Passed array of profile names is an invalid JSON string."``. Пример тела запроса: @@ -115,13 +97,12 @@ UUID по нику на время Данные возвращаются в том же порядке, в каком и были запрошены. -В случае, если один из переданных никнеймов не найден в базе данных, для него не будет возвращено значения (он будет -просто пропущен). Учитывайте эту ситуацию при парсинге ответа. +В случае, если один из переданных никнеймов не найден в базе данных, для него не будет возвращено значения (он будет просто пропущен). Учитывайте эту ситуацию при парсинге ответа. Запрос информации о профиле по UUID ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -См. `запрос профиля для сервера авторизации `_. +См. :ref:`запрос профиля для сервера авторизации `. Возможные ошибки ================ @@ -137,11 +118,9 @@ IllegalArgumentException .. code-block:: javascript - // Пример ошибки при неправильном формате UUID { "error": "IllegalArgumentException", "errorMessage": "Invalid uuid format." } -``errorMessage`` не всегда совпадает с таковым у Mojang, но в основном это касается только специфичных только для Ely -ошибок. Оригинальные же запросы и ожидаемые от них ошибки повторяют тексты Mojang. +``errorMessage`` не всегда совпадает с таковым у Mojang, но в основном это касается только специфичных только для Ely ошибок. Оригинальные же запросы и ожидаемые от них ошибки повторяют тексты Mojang. diff --git a/source/ru/authlib-injector.rst b/source/authlib-injector.rst similarity index 98% rename from source/ru/authlib-injector.rst rename to source/authlib-injector.rst index 31293b2..db46951 100644 --- a/source/ru/authlib-injector.rst +++ b/source/authlib-injector.rst @@ -24,7 +24,7 @@ Authlib-injector Если вы запускаете игру через лаунчер, то в его настройках необходимо найти поле для указания дополнительных аргументов JVM, куда необходимо в самое начало вставить строку, приведённую выше. -.. figure:: ../_static/authlib-injector/launcher-jvm-options.png +.. figure:: images/authlib-injector/launcher-jvm-options.png :align: center :alt: Редактирование аргументов JVM @@ -40,7 +40,7 @@ Authlib-injector При запуске сервера вы должны увидеть сообщение об активации authlib-injector: -.. figure:: ../_static/authlib-injector/server-startup-messages.png +.. figure:: images/authlib-injector/server-startup-messages.png :align: center :alt: Сообщение при запуске сервера diff --git a/source/conf.py b/source/conf.py index ff37718..8b187e2 100644 --- a/source/conf.py +++ b/source/conf.py @@ -29,7 +29,7 @@ import datetime # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = [] +extensions = ['sphinx.ext.ifconfig'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -45,7 +45,7 @@ master_doc = 'index' # General information about the project. project = 'Ely.by Documentation' -copyright = str(datetime.datetime.now().year) + ', ErickSkrauch' +copyright = str(datetime.datetime.now().year) + ', Ely.by' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -58,7 +58,7 @@ release = '' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -language = 'en' +language = 'ru' # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: @@ -258,22 +258,24 @@ texinfo_documents = [ # If true, do not generate a @detailmenu in the "Top" node's menu. #texinfo_no_detailmenu = False +# -- Options for sphinx-intl ---------------------------------------------- + +locale_dirs = ['../locale/'] +gettext_compact = False + +# -- Static files generation rules ---------------------------------------- + static_files = [ '../CNAME', - '../_config.yml', - 'api.html', - 'minecraft-auth.html', - 'oauth.html', - 'skin-system.html', + '../.nojekyll', ] from shutil import copyfile from os import path from sphinx.application import Sphinx -def copy_static_files(app, _): - # type: (Sphinx, None) -> None - if app.builder.name != 'html': +def copy_static_files(app: Sphinx, _) -> None: + if app.builder.name != "html": return for src_name in static_files: @@ -286,4 +288,4 @@ def copy_static_files(app, _): copyfile(src_path, target_path) def setup(app): - app.connect('build-finished', copy_static_files) + app.connect("build-finished", copy_static_files) diff --git a/source/en/authlib-injector.rst b/source/en/authlib-injector.rst deleted file mode 100644 index 566c847..0000000 --- a/source/en/authlib-injector.rst +++ /dev/null @@ -1,83 +0,0 @@ -Authlib-injector ----------------- - -**authlib-injector** is a library that allows you to spoof authorization and session server addresses in the Authlib, without modifying the library itself. It's designed as an javaagent. - -This library significantly simplifies the installation of an alternative authorization service in the game client and server, since transformation occurs during application bootstrap process. - -You can download the latest version from the `releases page on GitHub `_. - -Here is the documentation of the key aspects of installing and using the library. For more information, see the `original documentation in Chinese `_. - -.. _client: - -Installing in a game client -=========================== - -.. attention:: This section describes how to install the authlib-injector into the game. The game launcher still needs to implement the authorization flow itself in order to pass the ``accessToken`` to the game. - -To install the library, you need to specify it as a javaagent for the game. You can do this by prepending the line ``-javaagent:/path/to/file/authlib-injector.jar=ely.by`` as a game launching param. As the result, the launch command should look like this: - -.. code-block:: - - java -javaagent:/path/to/file/authlib-injector.jar=ely.by -jar minecraft.jar - -If you run the game through a launcher, then in its settings you need to find a field for specifying additional JVM arguments, in which you need to insert the line above at the beginning. - -.. figure:: ../_static/authlib-injector/launcher-jvm-options.png - :align: center - :alt: Editing JVM arguments - -.. _server: - -Installing on a server -====================== - -Just as in the case with the game client, the library must be specified as javaagent. `Download the library `_ and put in the server's directory. Then add the javaagent call to the server launch command: - -| Before: ``java -jar minecraft_server.jar`` -| After: ``java -javaagent:authlib-injector.jar=ely.by -jar minecraft_server.jar`` - -During server startup you should see a message about the activation of the authlib-injector: - -.. figure:: ../_static/authlib-injector/server-startup-messages.png - :align: center - :alt: Message at server startup - -BungeeCord -~~~~~~~~~~ - -The authlib-injector must be installed directly on the BungeeCord itself, as well as **on all backends** behind it. Note the configuration of the online-mode parameter: - -* The BungeeCord's configuration (``config.yml``) should contain ``online_mode=true``; -* The servers behind the proxy must contain in their configuration (``server.properties``) the value ``online-mode=false``. - -Using such configuration authorization will work for all logging in players and the internal servers will correctly display player skins. - -LaunchHelper -~~~~~~~~~~~~ - -Not all game hostings allow direct modifications of launch arguments. To get around this limitation, you can use a special server that runs the game server by mixing authlib-injector into it. To install, follow these instructions: - -#. Download the corresponding LaunchHelper for your operating system from the `releases page `_. - -#. Upload this file and the ``authlib-injector.jar`` file to the server folder on your hosting site. - -#. Also create a ``launchhelper.properties`` file and put the following contents into it: - - .. code-block:: - - javaAgentJarPath=authlib-injector.jar - javaAgentOptions=ely.by - execJarPath=minecraft_server.jar - - Where ``javaAgentJarPath`` contains the path to the authlib-injector.jar file and ``execJarPath`` contains the name of the server file. - -#. In the hosting control panel, specify the ``LaunchHelper.jar`` as the server file. - - If you can't change the executable file, you should rename the ``LaunchHelper.jar`` file to match your hosting requirements (usually, ``server.jar``). In this case, you should have the following file structure: - - * ``server.jar`` - the LaunchHelper file. - * ``minecraft_server.jar`` - your server core. - * ``authlib-injector.jar`` - the authlib-injector file. - * ``launchhelper.properties`` - the configuration file for the LaunchHelper. diff --git a/source/en/oauth.rst b/source/en/oauth.rst deleted file mode 100644 index fa75af8..0000000 --- a/source/en/oauth.rst +++ /dev/null @@ -1,424 +0,0 @@ -Authorization via OAuth2 protocol ---------------------------------- - -On this page you'll find how to implement OAuth2 authorization on your project through the Ely.by Accounts service. -The implementation of this protocol will allow your users to authorize using their Ely.by account. - -Application registration -======================== - -First you need to `create a new application `_. Select **Website** as the -application type. For the *Redirect URI* you can get away with just specifying the domain, but to increase security -it's advised to use the full redirect path. Here are examples of valid addresses: - -* :samp:`http://site.com` -* :samp:`http://site.com/oauth/ely` -* :samp:`http://site.com/oauth.php?provider=ely` - -After a successful creation of an application, you'll be taken to the page containing a list of all your applications. -If you click on the name of an application you'll see its ``clientId`` identifier and its ``clientSecret`` secret. -They'll become important in later steps. - -Authorization initiation -======================== - -To initiate the authorization flow, you'll have to redirect the user to the following URL: - -.. code-block:: text - - https://account.ely.by/oauth2/v1?client_id=&redirect_uri=&response_type=code&scope= - -.. list-table:: Valid query parameters - :widths: 1 1 98 - :header-rows: 1 - - * - Parameter - - Value example - - Description - * - *clientId* - - :samp:`ely` - - **Required**. ClientId that was received during registration. - * - *redirect_uri* - - :samp:`http://site.com/oauth.php` - - **Required**. Return-forwarding address, which is matches the address specified during the application - registration. - * - *response_type* - - :samp:`code` - - **Required**. Response type. At the moment, only ``code`` is supported. - * - *scope* - - :samp:`account_info account_email` - - **Required**. The list of permissions that you want to access, separated by spaces. See all available permissions - in the `section below <#available-scopes>`_. - * - *state* - - :samp:`isfvubuysdboinsbdfvit` - - Randomly generated string. Used as a session identifier to increase security. Will be returned unchanged after - authorization is completed. - * - *description* - - :samp:`यो अनुप्रयोग विवरण` - - If your application is available in several languages, you can use this field to override the default description - in accordance with user's preferred language. - * - *prompt* - - :samp:`consent` or :samp:`select_account` - - Forcibly display the request for permissions (``consent``) or forcibly request an account selection - (``select_account``). - * - *login_hint* - - :samp:`erickskrauch` or :samp:`erickskrauch@ely.by` - - If a user has several accounts, then specifying username or user email in this parameter will automatically - select corresponding account. This is useful in a case of re-login after the token has expired. - -.. _available_scopes: -.. list-table:: List of available scopes - :widths: 1 99 - :header-rows: 0 - - * - **account_info** - - Get user information. - * - **account_email** - - Response to a request for user information will also contain user's email address. - * - **offline_access** - - With an ``access_token`` you will also recieve a ``refresh_token``. See more at - `the corresponding section <#refresh-token-grant>`_. - * - **minecraft_server_session** - - It will be possible to use ``access_token`` as a session identifier for the Minecraft. - ------------------------------------------------------------------------------------------------------------------------- - -After creating the link, place it in your template: - -.. code-block:: html - - Login via Ely.by - -After clicking on the URL a user will be redirected to our login page after which they'll be redirected back to the -address specified in the ``redirect_uri`` parameter. - -Reverse redirection returns as ``?code=&state=`` for a successful authorization and -``&error_message=`` for a failed one. - -Examples of successful and unsuccessful redirects: - -.. code-block:: text - - http://site.com/oauth/ely.php?code=dkpEEVtXBdIcgdQWak4SOPEpTJIvYa8KIq5cW9GJ&state=ajckasdcjasndckbsadc - http://site.com/oauth/ely.php?error=access_denied&error_message=The+resource+owner+or+authorization+server+denied+the+request. - -.. _authorization-code-grant: - -Exchange auth code for a access key -=================================== - -After receiving an authorization code (``auth_code``), you'll need to exchange it for an authorization key -(``access_key``). To do this, you must perform a POST request to the URL: - -.. code-block:: text - - https://account.ely.by/api/oauth2/v1/token - -And pass in following parameters: - -.. list-table:: - :widths: 1 99 - :header-rows: 0 - - * - ``client_id`` - - ClientID that was received during registration. - * - ``client_secret`` - - ClientSecret that was received during application registration. - * - ``redirect_uri`` - - The exact URI that was used for user redirection. - * - ``grant_type`` - - In this case, ``authorization_code`` should be used. - -**An example of the exchange in PHP:** - -.. code-block:: php - - 'ely', // Your ClientId that was received during registration - 'client_secret' => 'Pk4uCtZw5WVlSUpvteJuTZkVqHXZ6aNtTaLPXa7X', // Your ClientSecret that was received during registration - 'redirect_uri' => 'http://someresource.by/oauth/some.php', // Address where you expect to get a user back (current url) - 'grant_type' => 'authorization_code', - ]; - - // If an error occurs, then the script will stop its execution - if (isset($_GET['error'])) { - echo $_GET['error_message']; - return; - } - - // We execute the code below only if the authorization code have arrived - if (!is_null($_GET['code'])) { - $oauthParams['code'] = $_GET['code']; - - $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, 'https://account.ely.by/api/oauth2/v1/token'); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($oauthParams)); - $out = json_decode(curl_exec($curl), true); - curl_close($curl); - } - -Notes to the code: - -* First, we declare the ``$oauthParams`` variable which will store the values that we got after registering the - application. - -* Then we check if there was an error. In which case, we immediately stop the execution. - -* Then we create a POST request to exchange the ``code`` for an ``access_token``, passing all required fields in the - process. - -* Then we execute the request, get the answer and parse it from JSON into the associative array. - -.. _authorization-code-grant-response: - -Server response -~~~~~~~~~~~~~~~ - -In case of a successful request, the response body will contain the result of exchanging the authorization code for an -``access_token``. Data is a JSON document and can be easily interpreted by tools of a used programming language. - -The JSON document body will contain the following fields: - -.. code-block:: javascript - - { - "access_token": "4qlktsEiwgspKEAotazem0APA99Ee7E6jNryVBrZ", - "refresh_token": "m0APA99Ee7E6jNryVBrZ4qlktsEiwgspKEAotaze", // Presented only if the request had offline_access scope - "token_type": "Bearer", - "expires_in": 86400 // Number of seconds that token is active for - } - -At this process authorization procedure is over. The resulting ``access_token`` can be used to obtain user information -and to interact with our API. - -Getting user information -======================== - -If the received token has the ``account_info`` scope, then you can request information about the user's account. -To do it, you have to send a request to the URL: - -.. code-block:: text - - https://account.ely.by/api/account/v1/info - -To send ``access_token``, the ``Authorization`` header is used with the value of ``Bearer {access_token}``. - -**An example of getting user information in PHP:** - -.. code-block:: php - - `_, but with the next parameters: - -.. list-table:: - :widths: 1 99 - :header-rows: 0 - - * - ``client_id`` - - ClientClientID that was received during registration. - * - ``client_secret`` - - ClientSecret that was received during application registration. - * - ``scope`` - - The same scopes that were obtained for the initial access token. An attempt to extend this list will cause an - error. - * - ``refresh_token`` - - The token itself that was obtained along with the access token. - -**Example of a token refreshing in PHP:** - -.. code-block:: php - - 'ely', // Your ClientId, that was received during registration - 'client_secret' => 'Pk4uCtZw5WVlSUpvteJuTZkVqHXZ6aNtTaLPXa7X', // Your ClientSecret, that was received during registration - 'scope' => 'account_info account_email', - 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token', - ]; - - $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, 'https://account.ely.by/api/oauth2/v1/token'); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($requestParams)); - $result = json_decode(curl_exec($curl), true); - curl_close($curl); - -The answer will have exactly the same body as the result of -`exchanging auto code for an access token <#authorization-code-grant-response>`_. The ``refresh_token`` field will be -absent. - -Available libraries -=================== - -A simpler way is to use a ready-made library, to which you'll only have to provide registration parameters. -Listed below are libraries for various programming languages. You can extend this list by providing your own library. - -* **PHP**: - - - [Official] https://github.com/elyby/league-oauth2-provider - -* **Ruby**: - - - [Official] https://github.com/elyby/omniauth-ely - -Possible errors -================ - -Below are the typical errors that you may receive after transmitting incorrect data to the authorization server. -If you encounter an error that is not described in this documentation, please report it via -`feedback form `_. - -.. _auth-start-errors: - -Errors during authorization initiation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This section describes the errors displayed when a user is redirected from your site to our authorization initiation -page. - -.. code-block:: text - - Invalid request ({parameter} required). - -This error means that you did not pass all the required parameters. To solve this error just add the missing parameter. - -.. code-block:: text - - Invalid response type '{invalid_response_type_value}'. - -This error indicates that you passed an unsupported type of ``response_type``. Currently, the only supported value is -``code``. - -.. code-block:: text - - Invalid scope '{invalid_scope}'. - -The error indicates that an unknown scope was requested. Make sure you request `supported scopes <#available-scopes>`_. - -.. code-block:: text - - Can not find application you are trying to authorize. - -This error indicates that the passed parameters do not correspond to any of the registered applications. To solve the -problem, fix your ``client_id`` and ``redirect_uri`` values. - -.. _issue-token-errors: - -Errors when exchanging code for a key -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If an error occurs, instead of the expected response with the ``200`` status, you will receive a ``40x`` code and the -following 2 fields: - -.. code-block:: json - - { - "error": "invalid_request", - "error_description": "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the \"code\" parameter." - } - -The ``error`` field contains the system error identifier, and ``error_description`` describes the error in English -language. - -**Possible error values:** - -.. list-table:: - :widths: 1 99 - :header-rows: 0 - - * - ``invalid_request`` - - Not all the required request parameters were passed or the ``code`` value was not found in the issued codes - database. - * - ``unsupported_grant_type`` - - This error indicates that you tried to authorize using an unknown for our OAuth2 server Grant-type. - * - ``invalid_client`` - - This error occurs when the trio of values ​​``client_id``, ``client_secret`` and ``redirect_uri`` didn't match - with any of the registered applications. - -Errors when requesting user information -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Response status ``401`` indicates that the ``Authorization`` header is not present in the request or its value formed -incorrectly. The response body will be as follows: - -.. code-block:: json - - { - "name": "Unauthorized", - "status": 401, - "message": "Your request was made with invalid credentials." - } - -A response with the ``403`` status indicates that the token transferred in the ``Authorization`` header does not contain -the ``account_info`` scope or it has expired. The response will be in the following format: - -.. code-block:: json - - { - "name": "Forbidden", - "status": 403, - "message": "You are not allowed to perform this action." - } - -Errors while updating access token -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When updating the access token you may encounter the same errors from -`exchanging auth code for an access token <#issue-token-errors>`_, as well as several new ones: - -.. list-table:: - :widths: 1 99 - :header-rows: 0 - - * - ``invalid_request`` - - Not all the required request parameters were passed or the ``refresh_token`` value wasn't found in the issued tokens database. - * - ``invalid_scope`` - - The unsupported scope was listed or requested more scopes than the original token had. diff --git a/source/en/skins-system.rst b/source/en/skins-system.rst deleted file mode 100644 index 7881068..0000000 --- a/source/en/skins-system.rst +++ /dev/null @@ -1,201 +0,0 @@ -Skins system ------------- - -On this page you'll find information about available endpoints of Ely.by's skins system service. You can use any of -them as an secondary or primary source of skins for your project. - -Ely.by's skins system service provides `proxying of textures from Minecraft premium users <#textures-proxy>`_, -which means that using this service, your players will see both premium Minecraft users' skins and Ely.by users' skins. - -We strive to comply with the official skins system and do not support ears and HD-skins. The system supports capes, -but doesn't allow players to wear them on their own. - -If you have suggestions for improving the existing functionality, please -`create a new Issue `_ at the -`Chrly project repository `_. - -.. note:: You can find more detailed information about the implementation of the skins system server in the - `Chrly project repository `_. - -Requests URLs -============= - -The skins system is located at the :samp:`http://skinsystem.ely.by` domain. - -In all queries, the :samp:`nickname` param must be replaced by the player's name. The value is case-insensitive. - -.. _skin-request: -.. function:: /skins/{nickname}.png - - URL for downloading a skin texture. The :samp:`.png` extension can be omitted. If textures aren't found, - the server will return a :samp:`404` status response. - -.. _cape-request: -.. function:: /cloaks/{nickname}.png - - URL for downloading a cape texture. The :samp:`.png` extension can be omitted. If textures aren't found, - the server will return a :samp:`404` status response. - -.. function:: /textures/{nickname} - - Via this URL you can get textures in the format specified in the :samp:`textures` field of JSON property with the - same name in response to a - `request for signed textures `_. - - .. code-block:: javascript - - { - "SKIN": { - "url": "http://example.com/skin.png", - "metadata": { - "model": "slim" - } - }, - "CAPE": { - "url": "http://example.com/cape.png" - } - } - - Depending on the availability of textures for the player, fields :samp:`SKIN` or :samp:`CAPE` may be absent. - Unless the skin model is :samp:`slim`, the :samp:`metadata` field will be omitted. - - The server will return an empty response with :samp:`204` status, if textures aren't found. - -.. function:: /profile/{nickname} - - This endpoint is an analog of the - `player profile query in the Mojang's API `_, but - instead of UUID user is queried by his nickname. Just like in the Mojang's API, you can append ``?unsigned=false`` - to the URL to get textures with a signature. The response will also include an additional property with ``name`` - **ely**. - - If the user has no textures, they'll be requested through the Mojang's API, but the Mojang's signature will be - discarded and textures will be re-signed using `our signature key <#signature-verification-key-request>`_. - - .. code-block:: javascript - - { - "id": "ffc8fdc95824509e8a57c99b940fb996", - "name": "ErickSkrauch", - "properties": [ - { - "name": "textures", - "signature": "eks3dLJWzod92dLfWH6Z8uc6l3+IvrZtTj3zjwnj0AdVt44ODKoL50N+RabYxf7zF3C7tlJwT1oAtydONrxXUarqUlpVeQzLlfsuqUKBLi0L+/Y9yQLG3AciNqzEWq3hYaOsJrsaJday/hQmKFnpXEFCThTMpSuZhoAZIiH4VG48NhP70U93ejyXF9b1nPYnXP6k7BVB8LYSzcjZfdqY88jQJbbvRzOyX14ZSD0Ma92jceLNKmkTVc2UfRLUNXtQKtVSFUzlAjCXPJW89IIOZTRqLg65qstWwBvn6VuikyUB5EIxM8vuCh7zTkrMOx1v2Q0xIj8YSFcbnBH2bo87SYOIe1bOK57ZEeUJqY6uSgMlWs7dI5D3nmhFptErm72hg55Axdo1xbG4mvnmLYF7SA4yMDSytPPL+kA+sw3pafnvU2IZo38gqJSDOOpkOpdhUoHx85fzRJL8AcLSJiFlCZDl4pSi3cVuKy/xY5ohT/fJ6GEqpbZp3gACymn47zzI42VSh6j1DQnx2wnhqalTv0kE3qpAFpK/htSboQkFCW/bULO3b+vgU87XPlReT7UtH4yGLtixgs5GC8AzBraN8vOMv8TZCX9ab6mBBjOoDJjXa8Tq637TC75GxRHlpAN2jRHYvyp2zJwjUrML3u4eD4osHW+VBfl8D2l3nLJuemQ=", - "value": "eyJ0aW1lc3RhbXAiOjE2MTQ5MzczMjc0MzcsInByb2ZpbGVJZCI6ImZmYzhmZGM5NTgyNDUwOWU4YTU3Yzk5Yjk0MGZiOTk2IiwicHJvZmlsZU5hbWUiOiJFcmlja1NrcmF1Y2giLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly9lbHkuYnkvc3RvcmFnZS9za2lucy82OWM2NzQwZDI5OTNlNWQ2ZjZhN2ZjOTI0MjBlZmMyOS5wbmcifX19" - }, - { - "name": "ely", - "value": "but why are you asking?" - } - ] - } - - The server will return an empty response with ``204`` status if the nickname wasn't found locally nor via the - Mojang's API. - -.. _signature-verification-key-request: -.. function:: /signature-verification-key.der - - This endpoint returns a public key that can be used to verify a texture's signature. The key is provided in ``DER`` - format, so it can be used directly in the Authlib, without modifying the signature checking algorithm. - -.. function:: /signature-verification-key.pem - - The same endpoint as the previous one, except that it returns the key in ``PEM`` format. - -.. function:: /textures/signed/{nickname} - - This request is used in our `server skins system plugin `_ to load textures with - the original Mojang's signature. The textures received this way can be transferred to an unmodified game client - without any changes. The answer will also include additional property with :samp:`name` equal to **ely**. - - .. code-block:: javascript - - { - "id": "ffc8fdc95824509e8a57c99b940fb996", - "name": "ErickSkrauch", - "properties": [ - { - "name": "textures", - "signature": "QH+1rlQJYk8tW+8WlSJnzxZZUL5RIkeOO33dq84cgNoxwCkzL95Zy5pbPMFhoiMXXablqXeqyNRZDQa+OewgDBSZxm0BmkNmwdTLzCPHgnlNYhwbO4sirg3hKjCZ82ORZ2q7VP2NQIwNvc3befiCakhDlMWUuhjxe7p/HKNtmKA7a/JjzmzwW7BWMv8b88ZaQaMaAc7puFQcu2E54G2Zk2kyv3T1Bm7bV4m7ymbL8McOmQc6Ph7C95/EyqIK1a5gRBUHPEFIEj0I06YKTHsCRFU1U/hJpk98xXHzHuULJobpajqYXuVJ8QEVgF8k8dn9VkS8BMbXcjzfbb6JJ36v7YIV6Rlt75wwTk2wr3C3P0ij55y0iXth1HjwcEKsg54n83d9w8yQbkUCiTpMbOqxTEOOS7G2O0ZDBJDXAKQ4n5qCiCXKZ4febv4+dWVQtgfZHnpGJUD3KdduDKslMePnECOXMjGSAOQou//yze2EkL2rBpJtAAiOtvBlm/aWnDZpij5cQk+pWmeHWZIf0LSSlsYRUWRDk/VKBvUTEAO9fqOxWqmSgQRUY2Ea56u0ZsBb4vEa1UY6mlJj3+PNZaWu5aP2E9Unh0DIawV96eW8eFQgenlNXHMmXd4aOra4sz2eeOnY53JnJP+eVE4cB1hlq8RA2mnwTtcy3lahzZonOWc=", - "value": "eyJ0aW1lc3RhbXAiOjE0ODYzMzcyNTQ4NzIsInByb2ZpbGVJZCI6ImM0ZjFlNTZmNjFkMTQwYTc4YzMyOGQ5MTY2ZWVmOWU3IiwicHJvZmlsZU5hbWUiOiJXaHlZb3VSZWFkVGhpcyIsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS83Mzk1NmE4ZTY0ZWU2ZDhlYzY1NmFkYmI0NDA0ZjhlYmZmMzQxMWIwY2I5MGIzMWNiNDc2ZWNiOTk2ZDNiOCJ9fX0=" - }, - { - "name": "ely", - "value": "but why are you asking?" - } - ] - } - - By default textures proxying isn't used for this query. To enable it, add an additional GET parameter - :samp:`?proxy=true`. - - The server will return an empty response with :samp:`204` status, if textures aren't found. - ------------------------------------------------------------------------------------------------------------------------- - -You can also pass a range of additional GET parameters while making any of the above requests. They will be used -to analyze the usage of the service by different versions of the game. - -:version: The version of the protocol by which skins will be requested. The current version is :samp:`2`, - i.e. you need to specify :samp:`version=2`. - -:minecraft_version: The version of Minecraft that the request is made from. - -:authlib_version: The version of the Authlib used. This option is relevant for Minecraft versions 1.7.6+, - where a separate library is used to load skins instead of in-game code. - -Here is an example of a textures request with parameters described above: - -.. code-block:: text - - http://skinsystem.ely.by/textures/erickskrauch?version=2&minecraft_version=1.14.0&authlib_version=1.5.25 - -Additional URLs -+++++++++++++++ - -You can also perform a skin and cape request by passing the nickname through the GET parameter. This feature is used -to pass analytical parameters of game versions up to 1.5.2, where the nickname is simply appended to the end of the -line. To do this, the entire string is arranged in such a way that the last parameter is :samp:`name`, after appending -a nickname to which you get a full request string for textures. - -.. function:: /skins?name={nickname}.png - - See the `skin request <#skin-request>`_. - -.. function:: /cloaks?name={nickname}.png - - See the `cape request <#cape-request>`_. - -Examples of requests for textures with parameters from above: - -.. code-block:: text - - http://skinsystem.ely.by/skins?version=2&minecraft_version=1.5.2&name=erickskrauch.png - http://skinsystem.ely.by/cloaks?version=2&minecraft_version=1.4.7&name=notch - -.. _textures-proxy: - -Textures proxying -================= - -Ely.by's skins system service obtains textures from the official skin system in a case where no information about -textures for the requested username was found in the database. The request will also be proxied if a skin entry is -found, but it's default. - -To improve the throughput of the proxying algorithm, information about textures is cached in 2 stages: - -* Player's names and UUIDs matches are stored - `for 30 days `_. - -* Information about textures isn't updated more often than - `once a minute `_. - -If you own a Minecraft premium account, but your nickname is busy, please contact our -`support team `_ and after a short check we'll pass the nickname on to you. - -Ready-made implementations -========================== - -Ready-made patch implementations and installation instructions can be found at the -`download section of the main Ely.by website `_. diff --git a/source/_static/minecraft-auth/authlib/authlib-1.3.1.jar b/source/files/authlib/authlib-1.3.1.jar similarity index 100% rename from source/_static/minecraft-auth/authlib/authlib-1.3.1.jar rename to source/files/authlib/authlib-1.3.1.jar diff --git a/source/_static/minecraft-auth/authlib/authlib-1.3.jar b/source/files/authlib/authlib-1.3.jar similarity index 100% rename from source/_static/minecraft-auth/authlib/authlib-1.3.jar rename to source/files/authlib/authlib-1.3.jar diff --git a/source/_static/authlib-injector/launcher-jvm-options.png b/source/images/authlib-injector/launcher-jvm-options.png similarity index 100% rename from source/_static/authlib-injector/launcher-jvm-options.png rename to source/images/authlib-injector/launcher-jvm-options.png diff --git a/source/_static/authlib-injector/server-startup-messages.png b/source/images/authlib-injector/server-startup-messages.png similarity index 100% rename from source/_static/authlib-injector/server-startup-messages.png rename to source/images/authlib-injector/server-startup-messages.png diff --git a/source/_static/minecraft-auth/authlib-install.png b/source/images/minecraft-auth/authlib-install.png similarity index 100% rename from source/_static/minecraft-auth/authlib-install.png rename to source/images/minecraft-auth/authlib-install.png diff --git a/source/_static/minecraft-auth/bungeecord_inclasstranslator.png b/source/images/minecraft-auth/bungeecord_inclasstranslator.png similarity index 100% rename from source/_static/minecraft-auth/bungeecord_inclasstranslator.png rename to source/images/minecraft-auth/bungeecord_inclasstranslator.png diff --git a/source/_static/minecraft-auth/bungeecord_move.png b/source/images/minecraft-auth/bungeecord_move.png similarity index 100% rename from source/_static/minecraft-auth/bungeecord_move.png rename to source/images/minecraft-auth/bungeecord_move.png diff --git a/source/_static/minecraft-auth/installing_by_inclasstranslator.png b/source/images/minecraft-auth/installing_by_inclasstranslator.png similarity index 100% rename from source/_static/minecraft-auth/installing_by_inclasstranslator.png rename to source/images/minecraft-auth/installing_by_inclasstranslator.png diff --git a/source/index.rst b/source/index.rst index 52fbbc1..4869db3 100644 --- a/source/index.rst +++ b/source/index.rst @@ -1,21 +1,13 @@ -Welcome to the Ely.by documentation! -==================================== +Добро пожаловать в документацию Ely.by! +======================================= -In this documentation you will find information about the public services of the Ely.by project, using which you'll be -able to integrate your projects with the Ely.by services. +В этой документации вы найдёте информацию о публичных сервисах проекта Ely.by, используя которые вы сможете самостоятельно реализовать свои программные продукты для совместной работы с сервисом Ely.by. -You are free to improve this documentation in the `documentation's repository `_. +Вы можете свободно улучшать и вносить предложения по изменениям в документацию в `репозитории проекта `_. .. toctree:: - :caption: English articles: :maxdepth: 2 - :glob: - - en/* - -.. toctree:: :caption: Статьи на русском: - :maxdepth: 2 :glob: - ru/* + * diff --git a/source/minecraft-auth.html b/source/minecraft-auth.html deleted file mode 100644 index 637887e..0000000 --- a/source/minecraft-auth.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/source/ru/minecraft-auth.rst b/source/minecraft-auth.rst similarity index 76% rename from source/ru/minecraft-auth.rst rename to source/minecraft-auth.rst index 8dcd9bd..c5b7b21 100644 --- a/source/ru/minecraft-auth.rst +++ b/source/minecraft-auth.rst @@ -3,8 +3,7 @@ Здесь приведена информация по авторизации для лаунчеров и серверов Minecraft через сервис авторизации Ely.by. -Протокол авторизации реализован максимально похожим на `оригинальный протокол авторизации Mojang `_, -но тем не менее эта документация описывает все доступные функции конкретно сервиса авторизации Ely.by. +Протокол авторизации реализован максимально похожим на `оригинальный протокол авторизации Mojang `_, но тем не менее эта документация описывает все доступные функции конкретно сервиса авторизации Ely.by. Общие положения =============== @@ -13,8 +12,7 @@ * При успешном запросе, сервер вернёт ответ со статусом 200. Любой другой код свидетельствует об ошибке. -* Сервер всегда отвечает JSON данными, кроме случаев системных ошибок и ответов на legacy запросы. Учитывайте это для - отображения пользователю правильного сообщения об ошибке. +* Сервер всегда отвечает JSON данными, кроме случаев системных ошибок и ответов на legacy запросы. Учитывайте это для отображения пользователю правильного сообщения об ошибке. * В случае стандартной ошибки, вы получите следующие данные: @@ -122,8 +120,7 @@ .. note:: В оригинальном протоколе так же передаётся значение ``selectedProfile``, но в реализации Mojang он не влияет ни на что. Наша реализация сервера авторизации игнорирует этот параметр и опирается на значения ``accessToken`` и ``clientToken``. - В случае получения какой-либо предусмотренной ошибки, следует заново запросить пароль пользователя и произвести - обычную авторизацию. + В случае получения какой-либо предусмотренной ошибки, следует заново запросить пароль пользователя и произвести обычную авторизацию. Успешный ответ: @@ -150,8 +147,7 @@ .. function:: POST /auth/validate - Этот запрос позволяет проверить валиден ли указанный accessToken или нет. Этот запрос не обновляет токен и его время - жизни, а только позволяет удостовериться, что он ещё действительный. + Этот запрос позволяет проверить валиден ли указанный accessToken или нет. Этот запрос не обновляет токен и его время жизни, а только позволяет удостовериться, что он ещё действительный. :param string accessToken: Токен доступа, полученный после авторизации. @@ -160,7 +156,7 @@ .. code-block:: javascript { - "error: "ForbiddenOperationException", + "error": "ForbiddenOperationException", "errorMessage": "Token expired." } @@ -175,8 +171,7 @@ .. function:: POST /auth/invalidate - Запрос позволяет инвалидировать accessToken. В случае, если переданный токен не удастся найти в хранилище токенов, - ошибка не будет сгенерирована и вы получите успешный ответ. + Запрос позволяет инвалидировать accessToken. В случае, если переданный токен не удастся найти в хранилище токенов, ошибка не будет сгенерирована и вы получите успешный ответ. Входные параметры: @@ -188,18 +183,14 @@ Авторизация на сервере ====================== -Эти запросы выполняются непосредственно клиентом и сервером при помощи внутреннего кода или библиотеки authlib -(начиная с версии 1.7.2). Они актуальны только в том случае, если вы уже произвели авторизацию и запустили игру с валидным -accessToken. Вам остаётся только заменить пути внутри игры/библиотеки на привидённые ниже пути. +Эти запросы выполняются непосредственно клиентом и сервером при помощи внутреннего кода или библиотеки authlib (начиная с версии 1.7.2). Они актуальны только в том случае, если вы уже произвели авторизацию и запустили игру с валидным accessToken. Вам остаётся только заменить пути внутри игры/библиотеки на приведённые ниже пути. -Поскольку непосредственно изменить что-либо в работе authlib или игры вы не можете, здесь не приводятся передаваемые значения -и ответы сервера. При необходимости вы сможете найти эту информацию самостоятельно в интернете. +Поскольку непосредственно изменить что-либо в работе authlib или игры вы не можете, здесь не приводятся передаваемые значения и ответы сервера. При необходимости вы сможете найти эту информацию самостоятельно в интернете. Через authlib ~~~~~~~~~~~~~ -.. important:: Эта часть документации описывает запросы, выполняемые через authlib в версии игры 1.7.2+. Для более старых - версий смотрите раздел ниже. +.. important:: Эта часть документации описывает запросы, выполняемые через authlib в версии игры 1.7.2+. Для более старых версий смотрите раздел ниже. Все запросы из этой категории выполняются на подуровень /session. Перед каждым из запросов указан тип отправляемого запроса. @@ -209,21 +200,14 @@ accessToken. Вам остаётся только заменить пути вн .. function:: GET /session/hasJoined - Запрос на этот URL выполняет сервер с online-mode=true после того, как клиент, пытающийся к нему подключится, успешно - выполнит join запрос. + Запрос на этот URL выполняет сервер с online-mode=true после того, как клиент, пытающийся к нему подключится, успешно выполнит join запрос. - .. attention:: Внутри тела ответа есть параметр **properties**, который, в свою очередь, содержит поле **value** с - закодированной в ней base64 строкой. В оригинальной системе авторизации данные зашифрованы с помощью - приватного ключа и расшифровывались на клиенте с помощью публичного. - - Ely, в свою очередь, **не выполняет шифрацию вовсе**, поэтому вам необходимо отключить проверку подписи в - библиотеке authlib. В противном случае текстуры всегда будут признаваться невалидными. + .. attention:: Внутри тела ответа есть параметр **properties**, который, в свою очередь, содержит поле **value** с закодированной в ней base64 строкой. В оригинальной системе авторизации данные зашифрованы с помощью приватного ключа и расшифровывались на клиенте с помощью публичного. Ely, в свою очередь, **не выполняет шифрацию вовсе**, поэтому вам необходимо отключить проверку подписи в библиотеке authlib. В противном случае текстуры всегда будут признаваться невалидными. Для старых версий ~~~~~~~~~~~~~~~~~ -.. important:: Эта часть документации описывает запросы, выполняемые более старыми версиями Minecraft, когда не применялась - библиотека authlib. Это все версии, младше версии 1.7.2. +.. important:: Эта часть документации описывает запросы, выполняемые более старыми версиями Minecraft, когда не применялась библиотека authlib. Это все версии, младше версии 1.7.2. Все запросы из этой категории выполняются на подуровень /session/legacy. Перед каждым из запросов указан тип отправляемого запроса. @@ -235,72 +219,55 @@ accessToken. Вам остаётся только заменить пути вн .. function:: GET /session/legacy/hasJoined - Запрос на этот URL выполняет сервер с online-mode=true после того, как клиент, пытающийся к нему подключится, успешно - выполнит join запрос. + Запрос на этот URL выполняет сервер с online-mode=true после того, как клиент, пытающийся к нему подключится, успешно выполнит join запрос. -Важно не потерять GET параметр **?user=** в конце обоих запросов, чтобы получились следующие URL: -``http://minecraft.ely.by/session/legacy/hasJoined?user=``. +Важно не потерять GET параметр **?user=** в конце обоих запросов, чтобы получились следующие URL: ``http://minecraft.ely.by/session/legacy/hasJoined?user=``. Одиночная игра ============== -По сути, одиночная игра - это локальный сервер, созданный для одного игрока. По крайней мере это так, начиная с версии 1.6, -в которой и был представлен механизм локальных серверов. +По сути, одиночная игра - это локальный сервер, созданный для одного игрока. По крайней мере это так, начиная с версии 1.6, в которой и был представлен механизм локальных серверов. -Тем не менее, описанный ниже запрос актуален только для Minecraft 1.7.6+, когда для загрузки скинов стала использоваться -так же authlib. +Тем не менее, описанный ниже запрос актуален только для Minecraft 1.7.6+, когда для загрузки скинов стала использоваться так же Authlib. .. _profile-request: .. function:: GET /session/profile/{uuid} - Запрос на этот URL выполняется клиентом в одиночной игре на локальном сервере (созданном посредством самой игры). - В URL передаётся UUID пользователя, с которым был запущен клиент, а в ответ получается информация о текстурах игрока - в таком же формате, как и при hasJoined запросе. + Запрос на этот URL выполняется клиентом в одиночной игре на локальном сервере (созданном посредством самой игры). В URL передаётся UUID пользователя, с которым был запущен клиент, а в ответ получается информация о текстурах игрока в таком же формате, как и при hasJoined запросе. Готовые библиотеки authlib ========================== -.. attention:: Ely.by поддрживает библиотеку authlib-injector. Это наиболее простой и универсальный способ установки системы авторизации в игру и игровые сервера. За подробностями обратитесь в :doc:`соответствующий раздел документации `. +.. attention:: Ely.by поддерживает библиотеку authlib-injector. Это наиболее простой и универсальный способ установки системы авторизации в игру и игровые сервера. За подробностями обратитесь в :doc:`соответствующий раздел документации `. -Поскольку самостоятельная реализация связана с трудностями поиска исходников, подключения зависимостей и в конце-концов -с процессом компиляции, на `странице загрузок нашей системы скинов `_ вы можете загрузить уже -готовые библиотеки со всеми необходимыми изменениями. Выберите в выпадающем списке необходимую версию и следуйте -инструкции по установке, размещённой на той же странице ниже. +Поскольку самостоятельная реализация связана с трудностями поиска исходников, подключения зависимостей и в конце-концов с процессом компиляции, на `странице загрузок нашей системы скинов `_ вы можете загрузить уже готовые библиотеки со всеми необходимыми изменениями. Выберите в выпадающем списке необходимую версию и следуйте инструкции по установке, размещённой на той же странице ниже. -В более ранних версиях игры система скинов находилась внутри игрового клиента, так что библиотеки ниже обеспечивают -лишь авторизацию: +В более ранних версиях игры система скинов находилась внутри игрового клиента, так что библиотеки ниже обеспечивают лишь авторизацию: -* Minecraft 1.7.5 - :download:`authlib 1.3.1 <../_static/minecraft-auth/authlib/authlib-1.3.1.jar>` +* Minecraft 1.7.5 - :download:`authlib 1.3.1 ` -* Minecraft 1.7.2 - :download:`authlib 1.3 <../_static/minecraft-auth/authlib/authlib-1.3.jar>` +* Minecraft 1.7.2 - :download:`authlib 1.3 ` -Для установки вам необходимо заменить оригинальную библиотеку, располагающуюся по пути -``<директория установки minecraft>/libraries/com/mojang/authlib/``. Убедитесь в том, что версии скачанного и заменяемого -файлов совпадают. +Для установки вам необходимо заменить оригинальную библиотеку, располагающуюся по пути ``<директория установки minecraft>/libraries/com/mojang/authlib/``. Убедитесь в том, что версии скачанного и заменяемого файлов совпадают. .. _install-server: Установка authlib на сервер =========================== -Сервер также использует authlib для выполнения авторизации игрока, поэтому соответствующие изменения должны быть -также применены и к нему. Ниже приведены инструкции по установки authlib для различных реализаций сервера Minecraft. +Сервер также использует authlib для выполнения авторизации игрока, поэтому соответствующие изменения должны быть также применены и к нему. Ниже приведены инструкции по установки authlib для различных реализаций сервера Minecraft. -.. note:: Если ни одна из приведённых ниже инструкций не подошла для вашей реализации сервера, пожалуйста, - создайте `новый issue `_ и мы допишем инструкцию для вашего сервера. +.. note:: Если ни одна из приведённых ниже инструкций не подошла для вашей реализации сервера, пожалуйста, создайте `новый issue `_ и мы допишем инструкцию для вашего сервера. .. _vanilla: Оригинальный сервер ~~~~~~~~~~~~~~~~~~~ -С помощью архиватора откройте файл сервера ``minecraft_server.ВЕРСИЯ.jar``. Таким же образом откройте архив с -authlib для соответствующей версии сервера. Перед вами будет два окна: одно с файлами сервера, другое с файлами authlib. -Вам необходимо "перетащить" из архива с authlib все файлы и папки, **за исключением директории META-INF**, и подтвердить -замену. +С помощью архиватора откройте файл сервера ``minecraft_server.ВЕРСИЯ.jar``. Таким же образом откройте архив с authlib для соответствующей версии сервера. Перед вами будет два окна: одно с файлами сервера, другое с файлами authlib. Вам необходимо "перетащить" из архива с authlib все файлы и папки, **за исключением директории META-INF**, и подтвердить замену. -.. figure:: ../_static/minecraft-auth/authlib-install.png +.. figure:: images/minecraft-auth/authlib-install.png :align: center :alt: Процесс установки Authlib @@ -311,10 +278,7 @@ authlib для соответствующей версии сервера. Пе Bukkit/Spigot ~~~~~~~~~~~~~ -Сперва выполните установку, как она описана для `оригинального сервера <#vanilla>`_. Затем скачайте библиотеки -`commons-io `_ и -`commons-lang3 `_, -после чего аналогичным с authlib образом последовательно переместите содержимое скачанных архивов в файлы сервера. +Сперва выполните установку, как она описана для `оригинального сервера <#vanilla>`_. Затем скачайте библиотеки `commons-io `_ и `commons-lang3 `_, после чего аналогичным с authlib образом последовательно переместите содержимое скачанных архивов в файлы сервера. Forge/Sponge ~~~~~~~~~~~~ @@ -330,9 +294,7 @@ Forge/Sponge Paper (PaperSpigot) ~~~~~~~~~~~~~~~~~~~ -Установка производится по аналогии с `Bukkit/Spigot <#bukkit-spigot>`_ в файл ``cache/patched-ВЕРСИЯ.jar``. -После внесения изменений, запускать сервер нужно через jar-файл из директории ``cache``, поскольку в противном случае -**Paper восстановит исходное состояние файла**: +Установка производится по аналогии с `Bukkit/Spigot <#bukkit-spigot>`_ в файл ``cache/patched-ВЕРСИЯ.jar``. После внесения изменений, запускать сервер нужно через jar-файл из директории ``cache``, поскольку в противном случае **Paper восстановит исходное состояние файла**: | До: ``java -jar paper-ВЕРСИЯ-БИЛД.jar`` | После: ``java -jar cache/patched-ВЕРСИЯ.jar`` @@ -356,13 +318,13 @@ BungeeCord #. Откройте распакованный файл в программе InClassTranslator и замените в нём строку ``https://sessionserver.mojang.com/session/minecraft/hasJoined?username=`` на ``https://authserver.ely.by/session/hasJoined?username=``, как показано на рисунке ниже: - .. figure:: ../_static/minecraft-auth/bungeecord_inclasstranslator.png + .. figure:: images/minecraft-auth/bungeecord_inclasstranslator.png :align: center :alt: Редактирование в InClassTranslator #. Сохраните изменения и перетащите измененный файл обратно в архив сервера. Подтвердите замену. - .. figure:: ../_static/minecraft-auth/bungeecord_move.png + .. figure:: images/minecraft-auth/bungeecord_move.png :align: center :alt: Перетаскивание отредактированного файла назад в архив @@ -375,12 +337,9 @@ BungeeCord Установка на версии ниже 1.7.2 ============================== -Для более старых версий существует достаточно большое многообразие различных случаев, раскрыть которые в этой документации -не представляется возможным. Вся установка заключается в замене определённых строк в определённых классах через -InClassTranslator. +Для более старых версий существует достаточно большое многообразие различных случаев, раскрыть которые в этой документации не представляется возможным. Вся установка заключается в замене определённых строк в определённых классах через InClassTranslator. -На форуме RuBukkit есть отличный пост, в котором собрана вся нужна информация по именам классов на различных версиях -Minecraft. Переписывать его сюда не имеет смысла, так что просто перейдите на его страницу и найдите нужную версию. +На форуме RuBukkit есть отличный пост, в котором собрана вся нужна информация по именам классов на различных версиях Minecraft. Переписывать его сюда не имеет смысла, так что просто перейдите на его страницу и найдите нужную версию. |rubukkit_link|. @@ -394,21 +353,19 @@ Minecraft. Переписывать его сюда не имеет смысла Предположим, что вы хотите установить авторизацию на сервер версии 1.5.2. -Сначала вы переходите по вышепривидённой ссылке, выбираете нужную версию (1.5.2) и видите список классов: +Сначала вы переходите по вышеприведённой ссылке, выбираете нужную версию (1.5.2) и видите список классов: * **bdk.class** - путь до joinserver * **jg.class** - путь до checkserver -Затем вы должны взять .jar файл клиента и открыть его любым архиватором. После чего вам необходимо найти файл **bdk.class**. -Для этого удобно воспользоваться поиском. +Затем вы должны взять .jar файл клиента и открыть его любым архиватором. После чего вам необходимо найти файл **bdk.class**. Для этого удобно воспользоваться поиском. После того, как вы нашли файл, его нужно извлечь из архива - просто перетащите его оттуда в удобную для вас дирикторию. -Дальше запустите InClassTranslator и в нём откройте этот класс. Слева будет список найденных в файле строк, которые вы -можете изменить. Нужно заменить только строку, отвечающую за запрос на подключение к серверу: +Дальше запустите InClassTranslator и в нём откройте этот класс. Слева будет список найденных в файле строк, которые вы можете изменить. Нужно заменить только строку, отвечающую за запрос на подключение к серверу: -.. figure:: ../_static/minecraft-auth/installing_by_inclasstranslator.png +.. figure:: images/minecraft-auth/installing_by_inclasstranslator.png :align: center :alt: Порядок редактирования: выбрать нужную строку, изменить, сохранить. @@ -418,5 +375,4 @@ Minecraft. Переписывать его сюда не имеет смысла ----------------------- -После этих действий вам нужно в настройках включить online-mode=true и сервер станет пускать на себя только тех игроков, -которые будут авторизованы через Ely.by. +После этих действий вам нужно в настройках включить online-mode=true и сервер станет пускать на себя только тех игроков, которые будут авторизованы через Ely.by. diff --git a/source/oauth.html b/source/oauth.html deleted file mode 100644 index b4ec2a4..0000000 --- a/source/oauth.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/source/ru/oauth.rst b/source/oauth.rst similarity index 74% rename from source/ru/oauth.rst rename to source/oauth.rst index 7977387..f88d588 100644 --- a/source/ru/oauth.rst +++ b/source/oauth.rst @@ -1,24 +1,18 @@ Авторизация по протоколу OAuth2 ------------------------------- -На этой странице вы найдёте информацию о реализации авторизации по протоколу OAuth2 на вашем проекте через сервис -Аккаунты Ely.by. Реализация этого протокола позволяет вашим пользователям производить авторизацию с использованием -своего аккаунта Ely.by. +На этой странице вы найдёте информацию о реализации авторизации по протоколу OAuth2 на вашем проекте через сервис Аккаунты Ely.by. Реализация этого протокола позволяет вашим пользователям производить авторизацию с использованием своего аккаунта Ely.by. Регистрация приложения ====================== -Для начала вам необходимо `создать новое приложение `_. Выберите тип -приложения **Веб‑сайт**. В качестве *адреса переадресации* можно указать только домен, но для повышения безопасности -лучше использовать полный путь переадресации. Примеры допустимых адресов: +Для начала вам необходимо `создать новое приложение `_. Выберите тип приложения **Веб‑сайт**. В качестве *адреса переадресации* можно указать только домен, но для повышения безопасности лучше использовать полный путь переадресации. Примеры допустимых адресов: -* :samp:`http://site.com` -* :samp:`http://site.com/oauth/ely` -* :samp:`http://site.com/oauth.php?provider=ely` +* ``http://site.com`` +* ``http://site.com/oauth/ely`` +* ``http://site.com/oauth.php?provider=ely`` -После успешного добавления приложения вы попадёте на страницу со списком всех ваших приложений. Кликнув по названию -приложения вы увидите его идентификатор ``clientId`` и секрет ``clientSecret``. Они буду использоваться на -следующих шагах. +После успешного добавления приложения вы попадёте на страницу со списком всех ваших приложений. Кликнув по названию приложения вы увидите его идентификатор ``clientId`` и секрет ``clientSecret``. Они буду использоваться на следующих шагах. Инициализация авторизации ========================= @@ -37,34 +31,29 @@ - Пример значения - Описание * - *clientId* - - :samp:`ely` + - ``ely`` - **Обязательное**. ClientId, полученный при регистрации. * - *redirect_uri* - - :samp:`http://site.com/oauth.php` + - ``http://site.com/oauth.php`` - **Обязательное**. Адрес обратной переадресации, совпадающий с адресом, указанным при регистрации приложения * - *response_type* - - :samp:`code` + - ``code`` - **Обязательное**. Тип ответа. На данный момент поддерживается только ``code``. * - *scope* - - :samp:`account_info account_email` - - **Обязательное**. Перечень разрешений, доступ к которым вы хотите получить, разделённые пробелом. Смотрите все - доступные права в `разделе ниже <#available-scopes>`_. + - ``account_info account_email`` + - **Обязательное**. Перечень разрешений, доступ к которым вы хотите получить, разделённые пробелом. Смотрите все доступные права в `разделе ниже <#available-scopes>`_. * - *state* - - :samp:`isfvubuysdboinsbdfvit` - - Случайно сгенерированная строка. Используется для увеличения безопасности в качестве идентификатора сессии. Будет - возвращена в неизменённом виде после завершения авторизации. + - ``isfvubuysdboinsbdfvit`` + - Случайно сгенерированная строка. Используется для увеличения безопасности в качестве идентификатора сессии. Будет возвращена в неизменённом виде после завершения авторизации. * - *description* - - :samp:`यो अनुप्रयोग विवरण` - - Если ваше приложение доступно на нескольких языках, то используя это поле вы можете переопределить стандартное - описание в соответствии с предпочтительным языком пользователя. + - ``यो अनुप्रयोग विवरण`` + - Если ваше приложение доступно на нескольких языках, то используя это поле вы можете переопределить стандартное описание в соответствии с предпочтительным языком пользователя. * - *prompt* - - :samp:`consent` или :samp:`select_account` - - Принудительно отобразить запрос прав (``consent``) или принудительно запросить выбор аккаунта - (``select_account``). + - ``consent`` или ``select_account`` + - Принудительно отобразить запрос прав (``consent``) или принудительно запросить выбор аккаунта (``select_account``). * - *login_hint* - - :samp:`erickskrauch` или :samp:`erickskrauch@ely.by` - - Если у пользователя есть несколько аккаунтов, то указав этот в этом параметре username или email пользователя вы - автоматически выберете аккаунт за него. Это полезно в случае повторного входа, когда токен истёк. + - ``erickskrauch`` или ``erickskrauch@ely.by`` + - Если у пользователя есть несколько аккаунтов, то указав этот в этом параметре username или E-mail пользователя вы автоматически выберете аккаунт за него. Это полезно в случае повторного входа, когда токен истёк. .. _available_scopes: .. list-table:: Перечень доступных scopes @@ -76,12 +65,11 @@ * - **account_email** - В ответе на запрос информации о пользователе будет также присутствовать его email. * - **offline_access** - - Вместе с ``access_token`` вы также получите и ``refresh_token``. Смотрите подробнее - `соответствующем разделе <#refresh-token-grant>`_. + - Вместе с ``access_token`` вы также получите и ``refresh_token``. Смотрите подробнее `соответствующем разделе <#refresh-token-grant>`_. * - **minecraft_server_session** - ``access_token`` можно будет использовать в качестве сессии для Minecraft. ------------------------------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------- Сформировав ссылку, разместите её в вашем шаблоне: @@ -89,11 +77,9 @@ Войти через Ely.by -По нажатию на ссылку, пользователь попадёт на нашу страницу авторизации, откуда после он будет перенаправлен обратно -по адресу, указанному в параметре ``redirect_uri``. +По нажатию на ссылку, пользователь попадёт на нашу страницу авторизации, откуда после он будет перенаправлен обратно по адресу, указанному в параметре ``redirect_uri``. -Обратная переадресация выполняется в виде ``?code=<код авторизации>&state=`` для успешной -авторизации и ``&error_message=<описание ошибки>`` для неудачной. +Обратная переадресация выполняется в виде ``?code=<код авторизации>&state=`` для успешной авторизации и ``&error_message=<описание ошибки>`` для неудачной. Пример успешного и неудачного редиректов: @@ -107,8 +93,7 @@ Обмен кода на ключ ================== -После получения кода авторизации (``auth_code``), вам необходимо обменять его на ключ авторизации (``access_key``). -Для этого необходимо выполнить POST запрос на URL: +После получения кода авторизации (``auth_code``), вам необходимо обменять его на ключ авторизации (``access_key``). Для этого необходимо выполнить POST запрос на URL: .. code-block:: text @@ -176,8 +161,7 @@ Ответ сервера ~~~~~~~~~~~~~ -В случае успешного запроса в теле ответа будет находиться результат обмена кода авторизации на ``access_token``. -Данные являются JSON документом и могут быть легко интерпретированы средствами используемого языка программирования. +В случае успешного запроса в теле ответа будет находиться результат обмена кода авторизации на ``access_token``. Данные являются JSON документом и могут быть легко интерпретированы средствами используемого языка программирования. Тело JSON документа содержит следующие поля: @@ -190,14 +174,12 @@ "expires_in": 86400 // Количество секунд, на которое выдан токен } -На этом процедура авторизации закончена. Полученный ``access_token`` может быть использован для получения информации о -пользователе и взаимодействия с нашим API. +На этом процедура авторизации закончена. Полученный ``access_token`` может быть использован для получения информации о пользователе и взаимодействия с нашим API. Получение информации о пользователе =================================== -Если полученный токен имеет scope ``account_info``, то вы можете запросить информацию об аккаунте пользователя. Для -этого необходимо отправить запрос на URL: +Если полученный токен имеет scope ``account_info``, то вы можете запросить информацию об аккаунте пользователя. Для этого необходимо отправить запрос на URL: .. code-block:: text @@ -235,23 +217,18 @@ "email": "erickskrauch@ely.by" } -Обратите внимание, что поле ``email`` будет присутствовать лишь в том случае, когда был запрошен scope -``account_email``. +Обратите внимание, что поле ``email`` будет присутствовать лишь в том случае, когда был запрошен scope ``account_email``. -.. note:: В ходе дальнейшего развития сервиса, количество возвращаемых полей может увеличиться, но уже существующие - останутся теми же. +.. note:: В ходе дальнейшего развития сервиса, количество возвращаемых полей может увеличиться, но уже существующие останутся теми же. .. _refresh-token-grant: Обновление токена доступа ========================= -Если при выполнении авторизации вами было запрошено право на получение scope ``offline_access``, то вместе с -``access_token`` вы также получите и ``refresh_token``. Данный токен не истекает и может быть использован для получения -нового токена доступа, когда он истечёт. +Если при выполнении авторизации вами было запрошено право на получение scope ``offline_access``, то вместе с ``access_token`` вы также получите и ``refresh_token``. Данный токен не истекает и может быть использован для получения нового токена доступа, когда он истечёт. -Для выполнения операции обновления токена необходимо отправить POST запрос на тот же URL, что использовался и -`при обмене кода на ключ доступа <#authorization-code-grant>`_, но со следующими параметрами: +Для выполнения операции обновления токена необходимо отправить POST запрос на тот же URL, что использовался и `при обмене кода на ключ доступа <#authorization-code-grant>`_, но со следующими параметрами: .. list-table:: :widths: 1 99 @@ -262,8 +239,7 @@ * - ``client_secret`` - ClientSecret, полученный при регистрации приложения. * - ``scope`` - - Те же scope, что были запрошены и при получении начального токена доступа. Попытка запросить большее количество - прав приведёт к ошибке. + - Те же scope, что были запрошены и при получении начального токена доступа. Попытка запросить большее количество прав приведёт к ошибке. * - ``refresh_token`` - Непосредственно токен, полученный вместе с начальным токеном доступа. @@ -291,66 +267,56 @@ $result = json_decode(curl_exec($curl), true); curl_close($curl); -В качестве ответа будет точно такое же тело, какое было получено в результате -`обмена кода на ключ доступа <#authorization-code-grant-response>`_. Поле ``refresh_token`` будет отсутствовать. +В качестве ответа будет точно такое же тело, какое было получено в результате `обмена кода на ключ доступа <#authorization-code-grant-response>`_. Поле ``refresh_token`` будет отсутствовать. Готовые библиотеки ================== -Более простым способом будет использовать уже готовую библиотеку, которой будет необходимо передать лишь регистрационные -параметры. Ниже перечислены библиотеки для различных языков программирования. Вы можете дополнить этот список своей -библиотекой. +Более простым способом будет использовать уже готовую библиотеку, которой будет необходимо передать лишь регистрационные параметры. Ниже перечислены библиотеки для различных языков программирования. Вы можете дополнить этот список своей библиотекой. * **PHP**: - - [Official] https://github.com/elyby/league-oauth2-provider + - [Официальная] https://github.com/elyby/league-oauth2-provider * **Ruby**: - - [Official] https://github.com/elyby/omniauth-ely + - [Официальная] https://github.com/elyby/omniauth-ely Возможные ошибки ================ -Ниже приведены стандартные ошибки, которые вы можете получить в случае неправильной передачи данных на сервер -авторизации. Если вы столкнулись с ошибкой, не описанной в этой документации, пожалуйста, сообщите о ней через -`форму обратной связи `_. +Ниже приведены стандартные ошибки, которые вы можете получить в случае неправильной передачи данных на сервер авторизации. Если вы столкнулись с ошибкой, не описанной в этой документации, пожалуйста, сообщите о ней через `форму обратной связи `_. .. _auth-start-errors: Ошибки при инициализации авторизации ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Этот раздел описывает ошибки, отображаемые при переадресации пользователя с вашего сайта на нашу страницу инициализации -авторизации. +Этот раздел описывает ошибки, отображаемые при переадресации пользователя с вашего сайта на нашу страницу инициализации авторизации. .. code-block:: text Invalid request ({parameter} required). -Данная ошибка означает, что вы передали не все необходимые параметры. Чтобы решить эту ошибку просто добавьте -недостающий параметр. +Данная ошибка означает, что вы передали не все необходимые параметры. Чтобы решить эту ошибку просто добавьте недостающий параметр. .. code-block:: text Invalid response type '{invalid_response_type_value}'. -Данная ошибка означает, что вы передали неподдерживаемый тип ``response_type``. На данный момент поддерживается только -значение ``code``. +Данная ошибка означает, что вы передали неподдерживаемый тип ``response_type``. На данный момент поддерживается только значение ``code``. .. code-block:: text Invalid scope '{invalid_scope}'. -Ошибка указывает на то, что было запрошено неизвестный ``scope``. Убедитесь, что вы запрашиваете -`поддерживаемые права <#available-scopes>`_. +Ошибка указывает на то, что было запрошено неизвестный ``scope``. Убедитесь, что вы запрашиваете `поддерживаемые права <#available-scopes>`_. .. code-block:: text Can not find application you are trying to authorize. -Данная ошибка говорит о том, что переданные параметры не соответствуют ни одному из зарегистрированных приложений. -Для решения проблемы исправьте ваши значения ``client_id`` и ``redirect_uri``. +Данная ошибка говорит о том, что переданные параметры не соответствуют ни одному из зарегистрированных приложений. Для решения проблемы исправьте ваши значения ``client_id`` и ``redirect_uri``. .. _issue-token-errors: @@ -366,8 +332,7 @@ "error_description": "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the \"code\" parameter." } -В поле ``error`` находится системный идентификатор ошибки, в ``error_description`` — описание ошибки на английском -языке. +В поле ``error`` находится системный идентификатор ошибки, в ``error_description`` — описание ошибки на английском языке. **Возможные значения error:** @@ -378,17 +343,14 @@ * - ``invalid_request`` - Переданы не все необходимые параметры запроса или значение ``code`` не был найден в базе выданных кодов. * - ``unsupported_grant_type`` - - Данная ошибка сигнализирует о том, что вы попытались произвести авторизацию по неизвестному для нашего OAuth2 - сервера типу Grant. + - Данная ошибка сигнализирует о том, что вы попытались произвести авторизацию по неизвестному для нашего OAuth2 сервера типу Grant. * - ``invalid_client`` - - Эта ошибка возникает в случае, когда трио значений ``client_id``, ``client_secret`` и ``redirect_uri`` не совпали - ни с одним из зарегистрированных приложений. + - Эта ошибка возникает в случае, когда трио значений ``client_id``, ``client_secret`` и ``redirect_uri`` не совпали ни с одним из зарегистрированных приложений. Ошибки при запросе информации о пользователе ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Ответ со статусом ``401`` указывает на то, что заголовок ``Authorization`` не присутствует в запросе или его значение -сформировано неверно. Тело ответа будет следующим: +Ответ со статусом ``401`` указывает на то, что заголовок ``Authorization`` не присутствует в запросе или его значение сформировано неверно. Тело ответа будет следующим: .. code-block:: json @@ -398,8 +360,7 @@ "message": "Your request was made with invalid credentials." } -Ответ со статусом ``403`` сигнализирует о том, что переданный в заголовке ``Authorization`` токен не содержит scope -``account_info`` или он истёк. Получаемый ответ будет иметь следующий формат: +Ответ со статусом ``403`` сигнализирует о том, что переданный в заголовке ``Authorization`` токен не содержит scope ``account_info`` или он истёк. Получаемый ответ будет иметь следующий формат: .. code-block:: json @@ -412,15 +373,13 @@ Ошибки при обновлении токена доступа ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -При выполнении обновления токена доступа вам могут встретиться те же ошибки, что и при -`обмене кода на ключ доступа <#issue-token-errors>`_, а также несколько новых: +При выполнении обновления токена доступа вам могут встретиться те же ошибки, что и при `обмене кода на ключ доступа <#issue-token-errors>`_, а также несколько новых: .. list-table:: :widths: 1 99 :header-rows: 0 * - ``invalid_request`` - - Переданы не все необходимые параметры запроса или значение ``refresh_token`` не был найден в базе выданных - токенов. + - Переданы не все необходимые параметры запроса или значение ``refresh_token`` не был найден в базе выданных токенов. * - ``invalid_scope`` - Были перечислены неподдерживаемые scope или запрошено больше, чем было у изначального токена. diff --git a/source/skin-system.html b/source/skin-system.html deleted file mode 100644 index b1663e1..0000000 --- a/source/skin-system.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/source/ru/skins-system.rst b/source/skins-system.rst similarity index 58% rename from source/ru/skins-system.rst rename to source/skins-system.rst index 0dcb7ed..9570042 100644 --- a/source/ru/skins-system.rst +++ b/source/skins-system.rst @@ -1,46 +1,36 @@ Система скинов -------------- -На этой странице вы найдёте информацию о доступных запросах к сервису системы скинов Ely.by. Вы можете использовать -любой из них как дополнительный или основной источник скинов для своего проекта. +На этой странице вы найдёте информацию о доступных запросах к сервису системы скинов Ely.by. Вы можете использовать любой из них как дополнительный или основной источник скинов для своего проекта. -Сервис системы скинов Ely.by обеспечивает `проксирование текстур владельцев лицензии Minecraft <#textures-proxy>`_, -что означает, что при использовании этого сервиса игроки будут видеть как скины премиум пользователей Minecraft, -так и скины пользователей сервиса Ely.by. +Сервис системы скинов Ely.by обеспечивает `проксирование текстур владельцев лицензии Minecraft <#textures-proxy>`_, что означает, что при использовании этого сервиса игроки будут видеть как скины премиум пользователей Minecraft, так и скины пользователей сервиса Ely.by. -Мы стремимся соответствовать официальной системе скинов и не поддерживаем ушки и HD-скины. Система поддерживает плащи, -но не позволяет игрокам самостоятельно их надевать. +Мы стремимся соответствовать официальной системе скинов и не поддерживаем ушки и HD-скины. Система поддерживает плащи, но не позволяет игрокам самостоятельно их надевать. -Если у вас есть предложения по развитию существующего функционала, пожалуйста, -`создайте новый Issue `_ в -`репозитории проекта Chrly `_. +Если у вас есть предложения по развитию существующего функционала, пожалуйста, `создайте новый Issue `_ в `репозитории проекта Chrly `_. -.. note:: Вы можете найти более подробную информацию о реализации сервера системы скинов в - `репозитории проекта Chrly `_. +.. note:: Вы можете найти более подробную информацию о реализации сервера системы скинов в `репозитории проекта Chrly `_. URL-адреса запросов =================== -Система скинов размещена на домене :samp:`http://skinsystem.ely.by`. +Система скинов размещена на домене ``http://skinsystem.ely.by``. -Во всех запросах параметр :samp:`nickname` должен быть заменён на ник игрока. Значение не чувствительно к регистру. +Во всех запросах параметр ``nickname`` должен быть заменён на ник игрока. Значение не чувствительно к регистру. .. _skin-request: .. function:: /skins/{nickname}.png - URL для загрузки текстуры скина. Расширение :samp:`.png` опционально. Если текстура не будет найдена, - сервер вернёт ответ с :samp:`404` статусом. + URL для загрузки текстуры скина. Расширение ``.png`` опционально. Если текстура не будет найдена, сервер вернёт ответ с ``404`` статусом. .. _cape-request: .. function:: /cloaks/{nickname}.png - URL для загрузки текстуры плаща. Расширение :samp:`.png` опционально. Если текстура не будет найдена, - сервер вернёт ответ с :samp:`404` статусом. + URL для загрузки текстуры плаща. Расширение ``.png`` опционально. Если текстура не будет найдена, сервер вернёт ответ с ``404`` статусом. .. function:: /textures/{nickname} - По этому URL вы можете получить текстуры в формате, указанному в поле :samp:`textures` одноимённого property - в `ответе на запрос подписанных текстур `_: + По этому URL вы можете получить текстуры в формате, указанному в поле ``textures`` одноимённого property в `ответе на запрос подписанных текстур `_: .. code-block:: javascript @@ -56,21 +46,15 @@ URL-адреса запросов } } - В зависимости от доступных игроку текстур могут отсутствовать поля :samp:`SKIN` или :samp:`CAPE`. - Если модель скина не является :samp:`slim`, то поле :samp:`metadata` также будет отсутствовать. + В зависимости от доступных игроку текстур могут отсутствовать поля ``SKIN`` или ``CAPE``. Если модель скина не является ``slim``, то поле ``metadata`` также будет отсутствовать. - Если текстуры не будут найдены, сервер вернёт пустой ответ с :samp:`204` статусом. + Если текстуры не будут найдены, сервер вернёт пустой ответ с ``204`` статусом. .. function:: /profile/{nickname} - Данный запрос является аналогом запроса - `профиля игрока в API Mojang `_, только вместо - идентификации пользователя по UUID используется его ник. Также, как и в API Mojang, вы можете добавить к запросу - ``?unsigned=false``, чтобы получить текстуры с подписью. В ответе также будет присутствовать дополнительное property - с ``name`` равным **ely**. + Данный запрос является аналогом запроса `профиля игрока в API Mojang `_, только вместо идентификации пользователя по UUID используется его ник. Также, как и в API Mojang, вы можете добавить к запросу ``?unsigned=false``, чтобы получить текстуры с подписью. В ответе также будет присутствовать дополнительное property с ``name`` равным **ely**. - Если у пользователя нет текстур, то они будут запрошены через прокси Mojang, после чего переподписаны с - использованием `нашего ключа подписи <#signature-verification-key-request>`_. + Если у пользователя нет текстур, то они будут запрошены через прокси Mojang, после чего переподписаны с использованием `нашего ключа подписи <#signature-verification-key-request>`_. .. code-block:: javascript @@ -90,15 +74,12 @@ URL-адреса запросов ] } - Если запрошенный никнейм не будет найден ни в локальном хранилище, ни у Mojang, сервер вернёт пустой ответ с ``204`` - статусом. + Если запрошенный никнейм не будет найден ни в локальном хранилище, ни у Mojang, сервер вернёт пустой ответ с ``204`` статусом. .. _signature-verification-key-request: .. function:: /signature-verification-key.der - Данный запрос возвращает публичный ключ, который может быть использован для проверки подписи текстур. Ключ - предоставляется в формате ``DER``. Этот формат используется внутри Authlib, поэтому ключ может быть в ней использован - без модификации алгоритма проверки подписи. + Данный запрос возвращает публичный ключ, который может быть использован для проверки подписи текстур. Ключ предоставляется в формате ``DER``. Этот формат используется внутри Authlib, поэтому ключ может быть в ней использован без модификации алгоритма проверки подписи. .. function:: /signature-verification-key.pem @@ -106,10 +87,7 @@ URL-адреса запросов .. function:: /textures/signed/{nickname} - Этот запрос используется в нашем `плагине серверной системы скинов `_ для - загрузки текстур с оригинальной подписью Mojang. Полученные в ответе текстуры могут быть без изменений переданы в - немодифицированный игровой клиент. В ответе также будет присутствовать дополнительное property с :samp:`name` - равным **ely**. + Этот запрос используется в нашем `плагине серверной системы скинов `_ для загрузки текстур с оригинальной подписью Mojang. Полученные в ответе текстуры могут быть без изменений переданы в немодифицированный игровой клиент. В ответе также будет присутствовать дополнительное property с ``name`` равным **ely**. .. code-block:: javascript @@ -129,23 +107,19 @@ URL-адреса запросов ] } - По умолчанию для этого запроса не применяется проксирование текстур. Чтобы его включить, добавьте дополнительный - GET параметр :samp:`?proxy=true`. + По умолчанию для этого запроса не применяется проксирование текстур. Чтобы его включить, добавьте дополнительный GET параметр ``?proxy=true``. - Если текстуры не будут найдены, сервер вернёт пустой ответ с :samp:`204` статусом. + Если текстуры не будут найдены, сервер вернёт пустой ответ с ``204`` статусом. ------------------------------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------- -При совершении любого из вышеописанных запросов вы также можете передать ряд дополнительных GET параметров. Они будут -использованы для анализа использования сервиса разными версиями игры. +При совершении любого из вышеописанных запросов вы также можете передать ряд дополнительных GET параметров. Они будут использованы для анализа использования сервиса разными версиями игры. -:version: Версия протокола, по которому идёт запрос на скины. На данный момент это версия :samp:`2` , - т.е. вам необходимо указать :samp:`version=2`. +:version: Версия протокола, по которому идёт запрос на скины. На данный момент это версия ``2`` , т.е. вам необходимо указать ``version=2``. :minecraft_version: Версия Minecraft, с которой идёт запрос. -:authlib_version: Версия используемой Authlib. Этот параметр актуален для версий Minecraft 1.7.6+, где - для загрузки скинов стала использоваться отдельная библиотека, а не внутриигровой код. +:authlib_version: Версия используемой Authlib. Этот параметр актуален для версий Minecraft 1.7.6+, где для загрузки скинов стала использоваться отдельная библиотека, а не внутриигровой код. Пример запроса текстур с передачей вышеописанных параметров: @@ -156,10 +130,7 @@ URL-адреса запросов Вспомогательные URL +++++++++++++++++++ -Также запрос скина и плаща можно выполнить, передавая ник через GET параметр. Эта возможность используется для -передачи аналитических параметров в версиях игры до 1.5.2, когда ник просто добавлялся в конец строки. Для этого вся -строка выстраивается таким образом, чтобы последним параметром шёл :samp:`name`, после добавления ника к которому -получался полный запрос на текстуру. +Также запрос скина и плаща можно выполнить, передавая ник через GET параметр. Эта возможность используется для передачи аналитических параметров в версиях игры до 1.5.2, когда ник просто добавлялся в конец строки. Для этого вся строка выстраивается таким образом, чтобы последним параметром шёл ``name``, после добавления ника к которому получался полный запрос на текстуру. .. function:: /skins?name={nickname}.png @@ -181,23 +152,17 @@ URL-адреса запросов Проксирование текстур ===================== -Сервис системы скинов Ely.by получает текстуры из официальной системы скинов в случае, если в базе данных не было -найдено информации о текстурах для запрошенного имени пользователя. Также запрос будет проксирован, если запись о скине -будет найдена, но он будет стандартным. +Сервис системы скинов Ely.by получает текстуры из официальной системы скинов в случае, если в базе данных не было найдено информации о текстурах для запрошенного имени пользователя. Также запрос будет проксирован, если запись о скине будет найдена, но он будет стандартным. Для улучшения пропускной способности проксирующего алгоритма, информация о текстурах кешируется в 2 стадии: -* Соответствие ника и UUID хранится в - `течение 30 дней `_. +* Соответствие ника и UUID хранится в `течение 30 дней `_. -* Информация о текстурах обновляется не чаще - `раза в минуту `_. +* Информация о текстурах обновляется не чаще `раза в минуту `_. -Если вы владеете лицензионным аккаунтом Minecraft, но ваш ник занят, пожалуйста, обратитесь в -`службу поддержки `_ и после небольшой проверки мы передадим ник в ваше пользование. +Если вы владеете лицензионным аккаунтом Minecraft, но ваш ник занят, пожалуйста, обратитесь в `службу поддержки `_ и после небольшой проверки мы передадим ник в ваше пользование. Готовые реализации ================== -Готовые реализации патчей и инструкции по их установке могут быть найдены в -`разделе загрузок на главном сайте Ely.by `_. +Готовые реализации патчей и инструкции по их установке могут быть найдены в `разделе загрузок на главном сайте Ely.by `_.