Completely upgrade project:
- removed all translations and used Russian as the base language - integrated crowdin - new multilang site layout - upgraded sphinx - fixed search, now it correctly handles articles language
21
.github/workflows/ci.yml
vendored
@ -31,8 +31,27 @@ jobs:
|
|||||||
if: steps.cache-pipenv.outputs.cache-hit != 'true'
|
if: steps.cache-pipenv.outputs.cache-hit != 'true'
|
||||||
run: pipenv install --deploy --dev
|
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
|
- name: Build docs
|
||||||
run: pipenv run sphinx-build source build
|
run: pipenv run python build-multilang.py
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
|
3
.gitignore
vendored
@ -6,3 +6,6 @@
|
|||||||
|
|
||||||
### venv folder
|
### venv folder
|
||||||
/venv
|
/venv
|
||||||
|
|
||||||
|
### The directory for the locales from the Crowdin
|
||||||
|
/locale
|
||||||
|
8
Pipfile
@ -4,11 +4,13 @@ verify_ssl = true
|
|||||||
name = "pypi"
|
name = "pypi"
|
||||||
|
|
||||||
[packages]
|
[packages]
|
||||||
sphinx-rtd-theme = "~=0.4.3"
|
Sphinx = ">=3.0,<4.0"
|
||||||
sphinx-autobuild = "~=0.7.1"
|
sphinx-rtd-theme = "~=0.5.1"
|
||||||
Sphinx = "<4.0,>=3.0"
|
|
||||||
|
|
||||||
[dev-packages]
|
[dev-packages]
|
||||||
|
lxml = ">=4.6.2,<5.0"
|
||||||
|
sphinx-autobuild = ">=2020.09.01"
|
||||||
|
sphinx-intl = ">=2.0,<3.0"
|
||||||
|
|
||||||
[requires]
|
[requires]
|
||||||
python_version = "3.9"
|
python_version = "3.9"
|
||||||
|
405
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "425c1a5b2f73fcd81fd11fee2e7ed72ad5816e7472fa80ef8ea31b9d6177e72e"
|
"sha256": "f276bc0ed2af04e02fbf86b128186f6c4632d643f77c387892d9c775dbfb068f"
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -23,13 +23,6 @@
|
|||||||
],
|
],
|
||||||
"version": "==0.7.12"
|
"version": "==0.7.12"
|
||||||
},
|
},
|
||||||
"argh": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:a9b3aaa1904eeb78e32394cd46c6f37ac0fb4af6dc488daa58971bdc7d7fcaf3",
|
|
||||||
"sha256:e9535b8c84dc9571a48999094fda7f33e63c3f1b74f3e5f3ac0105a58405bb65"
|
|
||||||
],
|
|
||||||
"version": "==0.26.2"
|
|
||||||
},
|
|
||||||
"babel": {
|
"babel": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5",
|
"sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5",
|
||||||
@ -85,12 +78,6 @@
|
|||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||||
"version": "==2.11.3"
|
"version": "==2.11.3"
|
||||||
},
|
},
|
||||||
"livereload": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"
|
|
||||||
],
|
|
||||||
"version": "==2.6.3"
|
|
||||||
},
|
|
||||||
"markupsafe": {
|
"markupsafe": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
|
"sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
|
||||||
@ -157,17 +144,310 @@
|
|||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||||
"version": "==20.9"
|
"version": "==20.9"
|
||||||
},
|
},
|
||||||
"pathtools": {
|
"pygments": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:7c35c5421a39bb82e58018febd90e3b6e5db34c5443aaaf742b3f33d4655f1c0"
|
"sha256:2656e1a6edcdabf4275f9a3640db59fd5de107d88e8663c5d4e9a0fa62f77f94",
|
||||||
|
"sha256:534ef71d539ae97d4c3a4cf7d6f110f214b0e687e92f9cb9d2a3b0d3101289c8"
|
||||||
],
|
],
|
||||||
"version": "==0.1.2"
|
"markers": "python_version >= '3.5'",
|
||||||
|
"version": "==2.8.1"
|
||||||
},
|
},
|
||||||
"port-for": {
|
"pyparsing": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:b16a84bb29c2954db44c29be38b17c659c9c27e33918dec16b90d375cc596f1c"
|
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
|
||||||
|
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
|
||||||
],
|
],
|
||||||
"version": "==0.3.1"
|
"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": {
|
"pygments": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@ -182,7 +462,7 @@
|
|||||||
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
|
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
|
||||||
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
|
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'",
|
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||||
"version": "==2.4.7"
|
"version": "==2.4.7"
|
||||||
},
|
},
|
||||||
"pytz": {
|
"pytz": {
|
||||||
@ -192,41 +472,6 @@
|
|||||||
],
|
],
|
||||||
"version": "==2021.1"
|
"version": "==2021.1"
|
||||||
},
|
},
|
||||||
"pyyaml": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf",
|
|
||||||
"sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696",
|
|
||||||
"sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393",
|
|
||||||
"sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77",
|
|
||||||
"sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922",
|
|
||||||
"sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5",
|
|
||||||
"sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8",
|
|
||||||
"sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10",
|
|
||||||
"sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc",
|
|
||||||
"sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018",
|
|
||||||
"sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e",
|
|
||||||
"sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253",
|
|
||||||
"sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347",
|
|
||||||
"sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183",
|
|
||||||
"sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541",
|
|
||||||
"sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb",
|
|
||||||
"sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185",
|
|
||||||
"sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc",
|
|
||||||
"sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db",
|
|
||||||
"sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa",
|
|
||||||
"sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46",
|
|
||||||
"sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122",
|
|
||||||
"sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b",
|
|
||||||
"sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63",
|
|
||||||
"sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df",
|
|
||||||
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc",
|
|
||||||
"sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247",
|
|
||||||
"sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6",
|
|
||||||
"sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"
|
|
||||||
],
|
|
||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
|
|
||||||
"version": "==5.4.1"
|
|
||||||
},
|
|
||||||
"requests": {
|
"requests": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804",
|
"sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804",
|
||||||
@ -240,7 +485,7 @@
|
|||||||
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
|
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
|
||||||
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
|
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||||
"version": "==1.15.0"
|
"version": "==1.15.0"
|
||||||
},
|
},
|
||||||
"snowballstemmer": {
|
"snowballstemmer": {
|
||||||
@ -260,19 +505,19 @@
|
|||||||
},
|
},
|
||||||
"sphinx-autobuild": {
|
"sphinx-autobuild": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:66388f81884666e3821edbe05dd53a0cfb68093873d17320d0610de8db28c74e",
|
"sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac",
|
||||||
"sha256:e60aea0789cab02fa32ee63c7acae5ef41c06f1434d9fd0a74250a61f5994692"
|
"sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==0.7.1"
|
"version": "==2021.3.14"
|
||||||
},
|
},
|
||||||
"sphinx-rtd-theme": {
|
"sphinx-intl": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:00cf895504a7895ee433807c62094cf1e95f065843bf3acd17037c3e9a2becd4",
|
"sha256:2ff97cba0e4e43249e339a3c29dd2f5b63c25ce794050aabca320ad95f5c5b55",
|
||||||
"sha256:728607e34d60456d736cc7991fd236afb828b21b82f956c5ea75f94c8414040a"
|
"sha256:b25a6ec169347909e8d983eefe2d8adecb3edc2f27760db79b965c69950638b4"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==0.4.3"
|
"version": "==2.0.1"
|
||||||
},
|
},
|
||||||
"sphinxcontrib-applehelp": {
|
"sphinxcontrib-applehelp": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@ -371,35 +616,11 @@
|
|||||||
},
|
},
|
||||||
"urllib3": {
|
"urllib3": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80",
|
"sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df",
|
||||||
"sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73"
|
"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'",
|
"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.3"
|
"version": "==1.26.4"
|
||||||
},
|
|
||||||
"watchdog": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:035f4816daf3c62e03503c267620f3aa8fc7472df85ff3ef1e0c100ea1ed2744",
|
|
||||||
"sha256:0f7e9de9ba84af15e9e9fc29c3b13c972daa4d2b11de29aa86b26a26bc877c06",
|
|
||||||
"sha256:13c9ff58508dce55ba416eb0ef7af5aa5858558f2ec51112f099fd03503b670b",
|
|
||||||
"sha256:19675b8d1f00dabe74a0e66d87980623250d9360a21612e8c27b70a4b214ceeb",
|
|
||||||
"sha256:1cd715c4fb803581ded8943f39a51f21c17375d009ca9e3398d6b20638863a70",
|
|
||||||
"sha256:1f518a6940cde8720b8826a705c164e6b9bd6cf8c00f14269ffac51e017e06ec",
|
|
||||||
"sha256:3e933f3567c4521dd1a5d59fd54a522cae90bebcbeb8b74b84a2f33c90f08388",
|
|
||||||
"sha256:41b1a773f364f232b5bc184688e8d60451745d9e0971ac60c648bd47be8f4733",
|
|
||||||
"sha256:532fedd993e75554671faa36cd04c580ced3fae084254a779afbbd8aaf00566b",
|
|
||||||
"sha256:74528772516228f6a015a647027057939ff0b695a0b864cb3037e8e1aabc7ca0",
|
|
||||||
"sha256:89102465764e453609463cf620e744da1b0aa1f9f321b05961e2e7e15b3c9d8b",
|
|
||||||
"sha256:a412b1914e27f67b0a10e1ee19b5d035a9f7c115a062bbbd640653d9820ba4c8",
|
|
||||||
"sha256:ac6adbdf32e1d180574f9d0819e80259ae48e68727e80c3d950ed5a023714c3e",
|
|
||||||
"sha256:adda34bfe6db05485c1dfcd98232bdec385f991fe16358750c2163473eefb985",
|
|
||||||
"sha256:d2fcbc15772a82cd139c803a513c45b0fbc72a10a8a34dc2a8b429110b6f1236",
|
|
||||||
"sha256:d54e187b76053982180532cb7fd31152201c438b348c456f699929f8a89e786d",
|
|
||||||
"sha256:e0114e48ee981b38e328eaa0d5a625c7b4fc144b8dc7f7637749d6b5f7fefb0e"
|
|
||||||
],
|
|
||||||
"markers": "python_version >= '3.6'",
|
|
||||||
"version": "==2.0.2"
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"develop": {}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
include:
|
|
||||||
- _downloads
|
|
||||||
- _images
|
|
||||||
- _sources
|
|
||||||
- _static
|
|
169
build-multilang.py
Executable file
@ -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")
|
8
crowdin.yml
Normal file
@ -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
|
@ -17,4 +17,3 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="refresh" content="0; URL=/ru/api.html" />
|
|
||||||
<script>
|
|
||||||
window.location.href = '/ru/api.html'
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
</html>
|
|
@ -1,38 +1,25 @@
|
|||||||
Ely.by API (симуляция Mojang API)
|
Ely.by API (симуляция Mojang API)
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
Здесь приведена информация об API, совместимом с функционалом `Mojang Api <http://wiki.vg/Mojang_API>`_. Обращаем ваше
|
Здесь приведена информация об API, совместимом с функционалом `Mojang Api <http://wiki.vg/Mojang_API>`_. Обращаем ваше внимание на то, что это не полноценное API Ely.by, а только набор дополнительных запросов, реализованных на базе нашего :doc:`сервера авторизации <minecraft-auth>`.
|
||||||
внимание на то, что это не полноценное API Ely.by, а только набор дополнительных запросов, реализованных на базе нашего
|
|
||||||
`сервера авторизации </minecraft-auth.html>`_.
|
|
||||||
|
|
||||||
Заметки
|
|
||||||
=======
|
|
||||||
|
|
||||||
* API не имеет ограничения на количество запросов. У нас есть просто настроенный fail2ban, который будет банить особо
|
|
||||||
надоедливых клиентов. Такие дела.
|
|
||||||
|
|
||||||
Запросы
|
Запросы
|
||||||
=======
|
=======
|
||||||
|
|
||||||
В этой секции будут описаны запросы и их же варианты для Mojang API. Все запросы выполняются на базовый url
|
.. note:: API не имеет ограничения на количество запросов. У нас есть просто настроенный fail2ban, который будет банить особо надоедливых клиентов. Такие дела.
|
||||||
``https://authserver.ely.by``.
|
|
||||||
|
В этой секции будут описаны запросы и их же варианты для Mojang API. Все запросы выполняются на базовый url ``https://authserver.ely.by``.
|
||||||
|
|
||||||
UUID по нику на время
|
UUID по нику на время
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Данный запрос позволяет узнать UUID пользователя по его нику на указанный момент времени. Время задаётся через GET
|
Данный запрос позволяет узнать UUID пользователя по его нику на указанный момент времени. Время задаётся через GET параметр at с unix timestamp.
|
||||||
параметр at с unitx timestamp.
|
|
||||||
|
|
||||||
.. note:: На самом деле Ely.by пока не запоминает период смены ника и не обращает внимание на этот запрос. Тем не менее
|
|
||||||
параметр в будущем будет дореализован.
|
|
||||||
|
|
||||||
.. function:: GET /api/users/profiles/minecraft/{username}
|
.. function:: GET /api/users/profiles/minecraft/{username}
|
||||||
|
|
||||||
Где username - искомый ник пользователя. Он может быть передан в любом регистре (В Mojang API только строгое
|
Где ``{username}`` — искомый ник пользователя. Он может быть передан в любом регистре (В Mojang API только строгое совпадение).
|
||||||
совпадение).
|
|
||||||
|
|
||||||
Обратите так же внимание, что параметры legacy и demo никогда не будут возвращены, т.к. эти параметры не имеют в Ely
|
Обратите так же внимание, что параметры legacy и demo никогда не будут возвращены, т.к. эти параметры не имеют в Ely альтернативы и специфичны только для сервисов Mojang.
|
||||||
альтернативы и специфичны только для сервисов Mojang.
|
|
||||||
|
|
||||||
В случае успешного запроса вы получите следующий ответ сервера:
|
В случае успешного запроса вы получите следующий ответ сервера:
|
||||||
|
|
||||||
@ -43,7 +30,7 @@ UUID по нику на время
|
|||||||
"name": "ErickSkrauch"
|
"name": "ErickSkrauch"
|
||||||
}
|
}
|
||||||
|
|
||||||
В случае, если переданный ник не будет найден, вы получите ответ с 204 статусом и пустым телом.
|
В случае, если переданный ник не будет найден, вы получите ответ с ``204`` статусом и пустым телом.
|
||||||
|
|
||||||
Никнейм по UUID + история изменений
|
Никнейм по UUID + история изменений
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -52,8 +39,7 @@ UUID по нику на время
|
|||||||
|
|
||||||
.. function:: GET /api/user/profiles/{uuid}/names
|
.. function:: GET /api/user/profiles/{uuid}/names
|
||||||
|
|
||||||
Где uuid - валиданый UUID. Валидным будет считаться UUID, написанный через дефисы или без них. В случае передачи
|
Где ``{uuid}`` — валидный UUID. Валидным будет считаться UUID, написанный через дефисы или без них. В случае передачи невалидной строки, будет возвращён IllegalArgumentException_ с сообщением ``"Invalid uuid format."``.
|
||||||
невалидной строки, будет возвращён IllegalArgumentException_ с сообщением ``"Invalid uuid format."``.
|
|
||||||
|
|
||||||
В случае успешного запроса вы получите следующий ответ сервера:
|
В случае успешного запроса вы получите следующий ответ сервера:
|
||||||
|
|
||||||
@ -69,10 +55,9 @@ UUID по нику на время
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
.. note:: Т.к. на Ely.by не реализован алгоритм запоминания момента смены ника, будет возвращаться только 1 элемент.
|
.. note:: Т.к. на Ely.by не реализован алгоритм запоминания момента смены ника, будет возвращаться только 1 элемент. Чуть позже мы добавим полноценную поддержку запоминания момента смены ника.
|
||||||
Чуть позже мы добавим полноценную поддержку запоминания момента смены ника.
|
|
||||||
|
|
||||||
В случае, если переданный UUID не будет найден, вы получите ответ с 204 статусом и пустым телом.
|
В случае, если переданный UUID не будет найден, вы получите ответ с ``204`` статусом и пустым телом.
|
||||||
|
|
||||||
Список никнеймов в их UUID
|
Список никнеймов в их UUID
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -83,10 +68,7 @@ UUID по нику на время
|
|||||||
|
|
||||||
В теле запроса или POST параметрах необходимо передать валидный JSON массив искомых ников.
|
В теле запроса или POST параметрах необходимо передать валидный JSON массив искомых ников.
|
||||||
|
|
||||||
В массиве должно быть не более 100 ников, в противном случае будет возвращён IllegalArgumentException_ с сообщением
|
В массиве должно быть не более 100 ников, в противном случае будет возвращён IllegalArgumentException_ с сообщением ``"Not more that 100 profile name per call is allowed."``. В случае, если переданная строка окажется невалидным JSON объектом, будет возвращено это же исключение, только с текстом ``"Passed array of profile names is an invalid JSON string."``.
|
||||||
``"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
|
Запрос информации о профиле по UUID
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
См. `запрос профиля для сервера авторизации <minecraft-auth.html#profile-request>`_.
|
См. :ref:`запрос профиля для сервера авторизации <profile-request>`.
|
||||||
|
|
||||||
Возможные ошибки
|
Возможные ошибки
|
||||||
================
|
================
|
||||||
@ -137,11 +118,9 @@ IllegalArgumentException
|
|||||||
|
|
||||||
.. code-block:: javascript
|
.. code-block:: javascript
|
||||||
|
|
||||||
// Пример ошибки при неправильном формате UUID
|
|
||||||
{
|
{
|
||||||
"error": "IllegalArgumentException",
|
"error": "IllegalArgumentException",
|
||||||
"errorMessage": "Invalid uuid format."
|
"errorMessage": "Invalid uuid format."
|
||||||
}
|
}
|
||||||
|
|
||||||
``errorMessage`` не всегда совпадает с таковым у Mojang, но в основном это касается только специфичных только для Ely
|
``errorMessage`` не всегда совпадает с таковым у Mojang, но в основном это касается только специфичных только для Ely ошибок. Оригинальные же запросы и ожидаемые от них ошибки повторяют тексты Mojang.
|
||||||
ошибок. Оригинальные же запросы и ожидаемые от них ошибки повторяют тексты Mojang.
|
|
@ -24,7 +24,7 @@ Authlib-injector
|
|||||||
|
|
||||||
Если вы запускаете игру через лаунчер, то в его настройках необходимо найти поле для указания дополнительных аргументов JVM, куда необходимо в самое начало вставить строку, приведённую выше.
|
Если вы запускаете игру через лаунчер, то в его настройках необходимо найти поле для указания дополнительных аргументов JVM, куда необходимо в самое начало вставить строку, приведённую выше.
|
||||||
|
|
||||||
.. figure:: ../_static/authlib-injector/launcher-jvm-options.png
|
.. figure:: images/authlib-injector/launcher-jvm-options.png
|
||||||
:align: center
|
:align: center
|
||||||
:alt: Редактирование аргументов JVM
|
:alt: Редактирование аргументов JVM
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ Authlib-injector
|
|||||||
|
|
||||||
При запуске сервера вы должны увидеть сообщение об активации authlib-injector:
|
При запуске сервера вы должны увидеть сообщение об активации authlib-injector:
|
||||||
|
|
||||||
.. figure:: ../_static/authlib-injector/server-startup-messages.png
|
.. figure:: images/authlib-injector/server-startup-messages.png
|
||||||
:align: center
|
:align: center
|
||||||
:alt: Сообщение при запуске сервера
|
:alt: Сообщение при запуске сервера
|
||||||
|
|
@ -29,7 +29,7 @@ import datetime
|
|||||||
# Add any Sphinx extension module names here, as strings. They can be
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
# ones.
|
# ones.
|
||||||
extensions = []
|
extensions = ['sphinx.ext.ifconfig']
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
templates_path = ['_templates']
|
templates_path = ['_templates']
|
||||||
@ -45,7 +45,7 @@ master_doc = 'index'
|
|||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = 'Ely.by Documentation'
|
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
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |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
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
language = 'en'
|
language = 'ru'
|
||||||
|
|
||||||
# There are two options for replacing |today|: either, you set today to some
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
# non-false value, then it is used:
|
# 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.
|
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||||
#texinfo_no_detailmenu = False
|
#texinfo_no_detailmenu = False
|
||||||
|
|
||||||
|
# -- Options for sphinx-intl ----------------------------------------------
|
||||||
|
|
||||||
|
locale_dirs = ['../locale/']
|
||||||
|
gettext_compact = False
|
||||||
|
|
||||||
|
# -- Static files generation rules ----------------------------------------
|
||||||
|
|
||||||
static_files = [
|
static_files = [
|
||||||
'../CNAME',
|
'../CNAME',
|
||||||
'../_config.yml',
|
'../.nojekyll',
|
||||||
'api.html',
|
|
||||||
'minecraft-auth.html',
|
|
||||||
'oauth.html',
|
|
||||||
'skin-system.html',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
from os import path
|
from os import path
|
||||||
from sphinx.application import Sphinx
|
from sphinx.application import Sphinx
|
||||||
|
|
||||||
def copy_static_files(app, _):
|
def copy_static_files(app: Sphinx, _) -> None:
|
||||||
# type: (Sphinx, None) -> None
|
if app.builder.name != "html":
|
||||||
if app.builder.name != 'html':
|
|
||||||
return
|
return
|
||||||
|
|
||||||
for src_name in static_files:
|
for src_name in static_files:
|
||||||
@ -286,4 +288,4 @@ def copy_static_files(app, _):
|
|||||||
copyfile(src_path, target_path)
|
copyfile(src_path, target_path)
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
app.connect('build-finished', copy_static_files)
|
app.connect("build-finished", copy_static_files)
|
||||||
|
@ -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 <https://github.com/yushijinhun/authlib-injector/releases/latest>`_.
|
|
||||||
|
|
||||||
Here is the documentation of the key aspects of installing and using the library. For more information, see the `original documentation in Chinese <https://github.com/yushijinhun/authlib-injector/wiki>`_.
|
|
||||||
|
|
||||||
.. _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 <https://github.com/yushijinhun/authlib-injector/releases/latest>`_ 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 <https://github.com/Codex-in-somnio/LaunchHelper/releases/latest>`_.
|
|
||||||
|
|
||||||
#. 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.
|
|
@ -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 <https://account.ely.by/dev/applications/new>`_. 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=<clientId>&redirect_uri=<redirectUri>&response_type=code&scope=<scopesList>
|
|
||||||
|
|
||||||
.. 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
|
|
||||||
|
|
||||||
<a href="<your_link>">Login via Ely.by</a>
|
|
||||||
|
|
||||||
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 ``<redirect_uri>?code=<auth_code>&state=<state>`` for a successful authorization and
|
|
||||||
``<redirect_uri?error=<error_identifier>&error_message=<error_description>`` 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
|
|
||||||
|
|
||||||
<?php
|
|
||||||
// This variable will store your OAuth2 settings
|
|
||||||
$oauthParams = [
|
|
||||||
'client_id' => '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
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$accessToken = 'some_access_token_value';
|
|
||||||
|
|
||||||
$curl = curl_init();
|
|
||||||
curl_setopt($curl, CURLOPT_URL, 'https://account.ely.by/api/account/v1/info');
|
|
||||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
|
||||||
curl_setopt($curl, CURLOPT_HTTPHEADER, [
|
|
||||||
'Authorization: Bearer ' . $accessToken,
|
|
||||||
]);
|
|
||||||
$result = json_decode(curl_exec($curl), true);
|
|
||||||
curl_close($curl);
|
|
||||||
|
|
||||||
In response, you will receive a JSON document with the following contents:
|
|
||||||
|
|
||||||
.. code-block:: json
|
|
||||||
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"uuid": "ffc8fdc9-5824-509e-8a57-c99b940fb996",
|
|
||||||
"username": "ErickSkrauch",
|
|
||||||
"registeredAt": 1470566470,
|
|
||||||
"profileLink": "http:\/\/ely.by\/u1",
|
|
||||||
"preferredLanguage": "be",
|
|
||||||
"email": "erickskrauch@ely.by"
|
|
||||||
}
|
|
||||||
|
|
||||||
Note that the ``email`` field will only be present when the ``account_email`` scope has been requested.
|
|
||||||
|
|
||||||
.. note:: In the future, the number of returned fields may increase, but existing ones will remain the same.
|
|
||||||
|
|
||||||
.. _refresh-token-grant:
|
|
||||||
|
|
||||||
Refreshing access token
|
|
||||||
=======================
|
|
||||||
|
|
||||||
If you have requested the scope ``offline_access`` during authorization, then along with your ``access_token`` you'll
|
|
||||||
also get ``refresh_token``. This token doesn't expire and can be used to obtain a new access token when that one
|
|
||||||
expires.
|
|
||||||
|
|
||||||
To perform a token update, you have to send a POST request to the same URL that was used for
|
|
||||||
`exchanging the auth code for an access token <#authorization-code-grant>`_, 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
|
|
||||||
|
|
||||||
<?php
|
|
||||||
// refresh_token that was receive after an authorization
|
|
||||||
$refreshToken = 'm0APA99Ee7E6jNryVBrZ4qlktsEiwgspKEAotaze';
|
|
||||||
|
|
||||||
$requestParams = [
|
|
||||||
'client_id' => '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 <http://ely.by/site/contact>`_.
|
|
||||||
|
|
||||||
.. _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.
|
|
@ -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 <https://github.com/elyby/chrly/issues/new>`_ at the
|
|
||||||
`Chrly project repository <https://github.com/elyby/chrly>`_.
|
|
||||||
|
|
||||||
.. note:: You can find more detailed information about the implementation of the skins system server in the
|
|
||||||
`Chrly project repository <https://github.com/elyby/chrly>`_.
|
|
||||||
|
|
||||||
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 <https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape>`_.
|
|
||||||
|
|
||||||
.. 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 <https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape>`_, 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 <http://ely.by/server-skins-system>`_ 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 <https://help.minecraft.net/hc/en-us/articles/360034636712-Minecraft-Usernames#article-container:~:text=How%20often%20can%20I%20change%20my%20username%3F>`_.
|
|
||||||
|
|
||||||
* Information about textures isn't updated more often than
|
|
||||||
`once a minute <https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape:~:text=You%20can%20request%20the%20same%20profile%20once%20per%20minute>`_.
|
|
||||||
|
|
||||||
If you own a Minecraft premium account, but your nickname is busy, please contact our
|
|
||||||
`support team <http://ely.by/site/contact>`_ 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 <http://ely.by/load>`_.
|
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@ -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
|
В этой документации вы найдёте информацию о публичных сервисах проекта Ely.by, используя которые вы сможете самостоятельно реализовать свои программные продукты для совместной работы с сервисом Ely.by.
|
||||||
able to integrate your projects with the Ely.by services.
|
|
||||||
|
|
||||||
You are free to improve this documentation in the `documentation's repository <https://github.com/elyby/docs>`_.
|
Вы можете свободно улучшать и вносить предложения по изменениям в документацию в `репозитории проекта <https://github.com/elyby/docs>`_.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:caption: English articles:
|
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
:glob:
|
|
||||||
|
|
||||||
en/*
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:caption: Статьи на русском:
|
:caption: Статьи на русском:
|
||||||
:maxdepth: 2
|
|
||||||
:glob:
|
:glob:
|
||||||
|
|
||||||
ru/*
|
*
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="refresh" content="0; URL=/ru/minecraft-auth.html" />
|
|
||||||
<script>
|
|
||||||
window.location.href = '/ru/minecraft-auth.html'
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
</html>
|
|
@ -3,8 +3,7 @@
|
|||||||
|
|
||||||
Здесь приведена информация по авторизации для лаунчеров и серверов Minecraft через сервис авторизации Ely.by.
|
Здесь приведена информация по авторизации для лаунчеров и серверов Minecraft через сервис авторизации Ely.by.
|
||||||
|
|
||||||
Протокол авторизации реализован максимально похожим на `оригинальный протокол авторизации Mojang <http://wiki.vg/Authentication>`_,
|
Протокол авторизации реализован максимально похожим на `оригинальный протокол авторизации Mojang <http://wiki.vg/Authentication>`_, но тем не менее эта документация описывает все доступные функции конкретно сервиса авторизации Ely.by.
|
||||||
но тем не менее эта документация описывает все доступные функции конкретно сервиса авторизации Ely.by.
|
|
||||||
|
|
||||||
Общие положения
|
Общие положения
|
||||||
===============
|
===============
|
||||||
@ -13,8 +12,7 @@
|
|||||||
|
|
||||||
* При успешном запросе, сервер вернёт ответ со статусом 200. Любой другой код свидетельствует об ошибке.
|
* При успешном запросе, сервер вернёт ответ со статусом 200. Любой другой код свидетельствует об ошибке.
|
||||||
|
|
||||||
* Сервер всегда отвечает JSON данными, кроме случаев системных ошибок и ответов на legacy запросы. Учитывайте это для
|
* Сервер всегда отвечает JSON данными, кроме случаев системных ошибок и ответов на legacy запросы. Учитывайте это для отображения пользователю правильного сообщения об ошибке.
|
||||||
отображения пользователю правильного сообщения об ошибке.
|
|
||||||
|
|
||||||
* В случае стандартной ошибки, вы получите следующие данные:
|
* В случае стандартной ошибки, вы получите следующие данные:
|
||||||
|
|
||||||
@ -122,8 +120,7 @@
|
|||||||
|
|
||||||
.. note:: В оригинальном протоколе так же передаётся значение ``selectedProfile``, но в реализации Mojang он не влияет ни на что. Наша реализация сервера авторизации игнорирует этот параметр и опирается на значения ``accessToken`` и ``clientToken``.
|
.. note:: В оригинальном протоколе так же передаётся значение ``selectedProfile``, но в реализации Mojang он не влияет ни на что. Наша реализация сервера авторизации игнорирует этот параметр и опирается на значения ``accessToken`` и ``clientToken``.
|
||||||
|
|
||||||
В случае получения какой-либо предусмотренной ошибки, следует заново запросить пароль пользователя и произвести
|
В случае получения какой-либо предусмотренной ошибки, следует заново запросить пароль пользователя и произвести обычную авторизацию.
|
||||||
обычную авторизацию.
|
|
||||||
|
|
||||||
Успешный ответ:
|
Успешный ответ:
|
||||||
|
|
||||||
@ -150,8 +147,7 @@
|
|||||||
|
|
||||||
.. function:: POST /auth/validate
|
.. function:: POST /auth/validate
|
||||||
|
|
||||||
Этот запрос позволяет проверить валиден ли указанный accessToken или нет. Этот запрос не обновляет токен и его время
|
Этот запрос позволяет проверить валиден ли указанный accessToken или нет. Этот запрос не обновляет токен и его время жизни, а только позволяет удостовериться, что он ещё действительный.
|
||||||
жизни, а только позволяет удостовериться, что он ещё действительный.
|
|
||||||
|
|
||||||
:param string accessToken: Токен доступа, полученный после авторизации.
|
:param string accessToken: Токен доступа, полученный после авторизации.
|
||||||
|
|
||||||
@ -160,7 +156,7 @@
|
|||||||
.. code-block:: javascript
|
.. code-block:: javascript
|
||||||
|
|
||||||
{
|
{
|
||||||
"error: "ForbiddenOperationException",
|
"error": "ForbiddenOperationException",
|
||||||
"errorMessage": "Token expired."
|
"errorMessage": "Token expired."
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,8 +171,7 @@
|
|||||||
|
|
||||||
.. function:: POST /auth/invalidate
|
.. function:: POST /auth/invalidate
|
||||||
|
|
||||||
Запрос позволяет инвалидировать accessToken. В случае, если переданный токен не удастся найти в хранилище токенов,
|
Запрос позволяет инвалидировать accessToken. В случае, если переданный токен не удастся найти в хранилище токенов, ошибка не будет сгенерирована и вы получите успешный ответ.
|
||||||
ошибка не будет сгенерирована и вы получите успешный ответ.
|
|
||||||
|
|
||||||
Входные параметры:
|
Входные параметры:
|
||||||
|
|
||||||
@ -188,18 +183,14 @@
|
|||||||
Авторизация на сервере
|
Авторизация на сервере
|
||||||
======================
|
======================
|
||||||
|
|
||||||
Эти запросы выполняются непосредственно клиентом и сервером при помощи внутреннего кода или библиотеки authlib
|
Эти запросы выполняются непосредственно клиентом и сервером при помощи внутреннего кода или библиотеки authlib (начиная с версии 1.7.2). Они актуальны только в том случае, если вы уже произвели авторизацию и запустили игру с валидным accessToken. Вам остаётся только заменить пути внутри игры/библиотеки на приведённые ниже пути.
|
||||||
(начиная с версии 1.7.2). Они актуальны только в том случае, если вы уже произвели авторизацию и запустили игру с валидным
|
|
||||||
accessToken. Вам остаётся только заменить пути внутри игры/библиотеки на привидённые ниже пути.
|
|
||||||
|
|
||||||
Поскольку непосредственно изменить что-либо в работе authlib или игры вы не можете, здесь не приводятся передаваемые значения
|
Поскольку непосредственно изменить что-либо в работе authlib или игры вы не можете, здесь не приводятся передаваемые значения и ответы сервера. При необходимости вы сможете найти эту информацию самостоятельно в интернете.
|
||||||
и ответы сервера. При необходимости вы сможете найти эту информацию самостоятельно в интернете.
|
|
||||||
|
|
||||||
Через authlib
|
Через authlib
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. important:: Эта часть документации описывает запросы, выполняемые через authlib в версии игры 1.7.2+. Для более старых
|
.. important:: Эта часть документации описывает запросы, выполняемые через authlib в версии игры 1.7.2+. Для более старых версий смотрите раздел ниже.
|
||||||
версий смотрите раздел ниже.
|
|
||||||
|
|
||||||
Все запросы из этой категории выполняются на подуровень /session. Перед каждым из запросов указан тип отправляемого запроса.
|
Все запросы из этой категории выполняются на подуровень /session. Перед каждым из запросов указан тип отправляемого запроса.
|
||||||
|
|
||||||
@ -209,21 +200,14 @@ accessToken. Вам остаётся только заменить пути вн
|
|||||||
|
|
||||||
.. function:: GET /session/hasJoined
|
.. function:: GET /session/hasJoined
|
||||||
|
|
||||||
Запрос на этот URL выполняет сервер с online-mode=true после того, как клиент, пытающийся к нему подключится, успешно
|
Запрос на этот URL выполняет сервер с online-mode=true после того, как клиент, пытающийся к нему подключится, успешно выполнит join запрос.
|
||||||
выполнит join запрос.
|
|
||||||
|
|
||||||
.. attention:: Внутри тела ответа есть параметр **properties**, который, в свою очередь, содержит поле **value** с
|
.. attention:: Внутри тела ответа есть параметр **properties**, который, в свою очередь, содержит поле **value** с закодированной в ней base64 строкой. В оригинальной системе авторизации данные зашифрованы с помощью приватного ключа и расшифровывались на клиенте с помощью публичного. Ely, в свою очередь, **не выполняет шифрацию вовсе**, поэтому вам необходимо отключить проверку подписи в библиотеке authlib. В противном случае текстуры всегда будут признаваться невалидными.
|
||||||
закодированной в ней base64 строкой. В оригинальной системе авторизации данные зашифрованы с помощью
|
|
||||||
приватного ключа и расшифровывались на клиенте с помощью публичного.
|
|
||||||
|
|
||||||
Ely, в свою очередь, **не выполняет шифрацию вовсе**, поэтому вам необходимо отключить проверку подписи в
|
|
||||||
библиотеке authlib. В противном случае текстуры всегда будут признаваться невалидными.
|
|
||||||
|
|
||||||
Для старых версий
|
Для старых версий
|
||||||
~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. important:: Эта часть документации описывает запросы, выполняемые более старыми версиями Minecraft, когда не применялась
|
.. important:: Эта часть документации описывает запросы, выполняемые более старыми версиями Minecraft, когда не применялась библиотека authlib. Это все версии, младше версии 1.7.2.
|
||||||
библиотека authlib. Это все версии, младше версии 1.7.2.
|
|
||||||
|
|
||||||
Все запросы из этой категории выполняются на подуровень /session/legacy. Перед каждым из запросов указан тип отправляемого запроса.
|
Все запросы из этой категории выполняются на подуровень /session/legacy. Перед каждым из запросов указан тип отправляемого запроса.
|
||||||
|
|
||||||
@ -235,72 +219,55 @@ accessToken. Вам остаётся только заменить пути вн
|
|||||||
|
|
||||||
.. function:: GET /session/legacy/hasJoined
|
.. function:: GET /session/legacy/hasJoined
|
||||||
|
|
||||||
Запрос на этот URL выполняет сервер с online-mode=true после того, как клиент, пытающийся к нему подключится, успешно
|
Запрос на этот URL выполняет сервер с online-mode=true после того, как клиент, пытающийся к нему подключится, успешно выполнит join запрос.
|
||||||
выполнит join запрос.
|
|
||||||
|
|
||||||
Важно не потерять GET параметр **?user=** в конце обоих запросов, чтобы получились следующие URL:
|
Важно не потерять GET параметр **?user=** в конце обоих запросов, чтобы получились следующие URL: ``http://minecraft.ely.by/session/legacy/hasJoined?user=``.
|
||||||
``http://minecraft.ely.by/session/legacy/hasJoined?user=``.
|
|
||||||
|
|
||||||
Одиночная игра
|
Одиночная игра
|
||||||
==============
|
==============
|
||||||
|
|
||||||
По сути, одиночная игра - это локальный сервер, созданный для одного игрока. По крайней мере это так, начиная с версии 1.6,
|
По сути, одиночная игра - это локальный сервер, созданный для одного игрока. По крайней мере это так, начиная с версии 1.6, в которой и был представлен механизм локальных серверов.
|
||||||
в которой и был представлен механизм локальных серверов.
|
|
||||||
|
|
||||||
Тем не менее, описанный ниже запрос актуален только для Minecraft 1.7.6+, когда для загрузки скинов стала использоваться
|
Тем не менее, описанный ниже запрос актуален только для Minecraft 1.7.6+, когда для загрузки скинов стала использоваться так же Authlib.
|
||||||
так же authlib.
|
|
||||||
|
|
||||||
.. _profile-request:
|
.. _profile-request:
|
||||||
|
|
||||||
.. function:: GET /session/profile/{uuid}
|
.. function:: GET /session/profile/{uuid}
|
||||||
|
|
||||||
Запрос на этот URL выполняется клиентом в одиночной игре на локальном сервере (созданном посредством самой игры).
|
Запрос на этот URL выполняется клиентом в одиночной игре на локальном сервере (созданном посредством самой игры). В URL передаётся UUID пользователя, с которым был запущен клиент, а в ответ получается информация о текстурах игрока в таком же формате, как и при hasJoined запросе.
|
||||||
В URL передаётся UUID пользователя, с которым был запущен клиент, а в ответ получается информация о текстурах игрока
|
|
||||||
в таком же формате, как и при hasJoined запросе.
|
|
||||||
|
|
||||||
Готовые библиотеки authlib
|
Готовые библиотеки authlib
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
.. attention:: Ely.by поддрживает библиотеку authlib-injector. Это наиболее простой и универсальный способ установки системы авторизации в игру и игровые сервера. За подробностями обратитесь в :doc:`соответствующий раздел документации <authlib-injector>`.
|
.. attention:: Ely.by поддерживает библиотеку authlib-injector. Это наиболее простой и универсальный способ установки системы авторизации в игру и игровые сервера. За подробностями обратитесь в :doc:`соответствующий раздел документации <authlib-injector>`.
|
||||||
|
|
||||||
Поскольку самостоятельная реализация связана с трудностями поиска исходников, подключения зависимостей и в конце-концов
|
Поскольку самостоятельная реализация связана с трудностями поиска исходников, подключения зависимостей и в конце-концов с процессом компиляции, на `странице загрузок нашей системы скинов <https://ely.by/load>`_ вы можете загрузить уже готовые библиотеки со всеми необходимыми изменениями. Выберите в выпадающем списке необходимую версию и следуйте инструкции по установке, размещённой на той же странице ниже.
|
||||||
с процессом компиляции, на `странице загрузок нашей системы скинов <//ely.by/load>`_ вы можете загрузить уже
|
|
||||||
готовые библиотеки со всеми необходимыми изменениями. Выберите в выпадающем списке необходимую версию и следуйте
|
|
||||||
инструкции по установке, размещённой на той же странице ниже.
|
|
||||||
|
|
||||||
В более ранних версиях игры система скинов находилась внутри игрового клиента, так что библиотеки ниже обеспечивают
|
В более ранних версиях игры система скинов находилась внутри игрового клиента, так что библиотеки ниже обеспечивают лишь авторизацию:
|
||||||
лишь авторизацию:
|
|
||||||
|
|
||||||
* 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 <files/authlib/authlib-1.3.1.jar>`
|
||||||
|
|
||||||
* Minecraft 1.7.2 - :download:`authlib 1.3 <../_static/minecraft-auth/authlib/authlib-1.3.jar>`
|
* Minecraft 1.7.2 - :download:`authlib 1.3 <files/authlib/authlib-1.3.jar>`
|
||||||
|
|
||||||
Для установки вам необходимо заменить оригинальную библиотеку, располагающуюся по пути
|
Для установки вам необходимо заменить оригинальную библиотеку, располагающуюся по пути ``<директория установки minecraft>/libraries/com/mojang/authlib/``. Убедитесь в том, что версии скачанного и заменяемого файлов совпадают.
|
||||||
``<директория установки minecraft>/libraries/com/mojang/authlib/``. Убедитесь в том, что версии скачанного и заменяемого
|
|
||||||
файлов совпадают.
|
|
||||||
|
|
||||||
.. _install-server:
|
.. _install-server:
|
||||||
|
|
||||||
Установка authlib на сервер
|
Установка authlib на сервер
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
Сервер также использует authlib для выполнения авторизации игрока, поэтому соответствующие изменения должны быть
|
Сервер также использует authlib для выполнения авторизации игрока, поэтому соответствующие изменения должны быть также применены и к нему. Ниже приведены инструкции по установки authlib для различных реализаций сервера Minecraft.
|
||||||
также применены и к нему. Ниже приведены инструкции по установки authlib для различных реализаций сервера Minecraft.
|
|
||||||
|
|
||||||
.. note:: Если ни одна из приведённых ниже инструкций не подошла для вашей реализации сервера, пожалуйста,
|
.. note:: Если ни одна из приведённых ниже инструкций не подошла для вашей реализации сервера, пожалуйста, создайте `новый issue <https://github.com/elyby/docs/issues/new>`_ и мы допишем инструкцию для вашего сервера.
|
||||||
создайте `новый issue <https://github.com/elyby/docs/issues/new>`_ и мы допишем инструкцию для вашего сервера.
|
|
||||||
|
|
||||||
.. _vanilla:
|
.. _vanilla:
|
||||||
|
|
||||||
Оригинальный сервер
|
Оригинальный сервер
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
С помощью архиватора откройте файл сервера ``minecraft_server.ВЕРСИЯ.jar``. Таким же образом откройте архив с
|
С помощью архиватора откройте файл сервера ``minecraft_server.ВЕРСИЯ.jar``. Таким же образом откройте архив с authlib для соответствующей версии сервера. Перед вами будет два окна: одно с файлами сервера, другое с файлами authlib. Вам необходимо "перетащить" из архива с authlib все файлы и папки, **за исключением директории META-INF**, и подтвердить замену.
|
||||||
authlib для соответствующей версии сервера. Перед вами будет два окна: одно с файлами сервера, другое с файлами authlib.
|
|
||||||
Вам необходимо "перетащить" из архива с authlib все файлы и папки, **за исключением директории META-INF**, и подтвердить
|
|
||||||
замену.
|
|
||||||
|
|
||||||
.. figure:: ../_static/minecraft-auth/authlib-install.png
|
.. figure:: images/minecraft-auth/authlib-install.png
|
||||||
:align: center
|
:align: center
|
||||||
:alt: Процесс установки Authlib
|
:alt: Процесс установки Authlib
|
||||||
|
|
||||||
@ -311,10 +278,7 @@ authlib для соответствующей версии сервера. Пе
|
|||||||
Bukkit/Spigot
|
Bukkit/Spigot
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
Сперва выполните установку, как она описана для `оригинального сервера <#vanilla>`_. Затем скачайте библиотеки
|
Сперва выполните установку, как она описана для `оригинального сервера <#vanilla>`_. Затем скачайте библиотеки `commons-io <https://repo1.maven.org/maven2/commons-io/commons-io/2.5/commons-io-2.5.jar>`_ и `commons-lang3 <https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.5/commons-lang3-3.5.jar>`_, после чего аналогичным с authlib образом последовательно переместите содержимое скачанных архивов в файлы сервера.
|
||||||
`commons-io <https://repo1.maven.org/maven2/commons-io/commons-io/2.5/commons-io-2.5.jar>`_ и
|
|
||||||
`commons-lang3 <https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.5/commons-lang3-3.5.jar>`_,
|
|
||||||
после чего аналогичным с authlib образом последовательно переместите содержимое скачанных архивов в файлы сервера.
|
|
||||||
|
|
||||||
Forge/Sponge
|
Forge/Sponge
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
@ -330,9 +294,7 @@ Forge/Sponge
|
|||||||
Paper (PaperSpigot)
|
Paper (PaperSpigot)
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Установка производится по аналогии с `Bukkit/Spigot <#bukkit-spigot>`_ в файл ``cache/patched-ВЕРСИЯ.jar``.
|
Установка производится по аналогии с `Bukkit/Spigot <#bukkit-spigot>`_ в файл ``cache/patched-ВЕРСИЯ.jar``. После внесения изменений, запускать сервер нужно через jar-файл из директории ``cache``, поскольку в противном случае **Paper восстановит исходное состояние файла**:
|
||||||
После внесения изменений, запускать сервер нужно через jar-файл из директории ``cache``, поскольку в противном случае
|
|
||||||
**Paper восстановит исходное состояние файла**:
|
|
||||||
|
|
||||||
| До: ``java -jar paper-ВЕРСИЯ-БИЛД.jar``
|
| До: ``java -jar paper-ВЕРСИЯ-БИЛД.jar``
|
||||||
| После: ``java -jar cache/patched-ВЕРСИЯ.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=``, как показано на рисунке ниже:
|
#. Откройте распакованный файл в программе 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
|
:align: center
|
||||||
:alt: Редактирование в InClassTranslator
|
:alt: Редактирование в InClassTranslator
|
||||||
|
|
||||||
#. Сохраните изменения и перетащите измененный файл обратно в архив сервера. Подтвердите замену.
|
#. Сохраните изменения и перетащите измененный файл обратно в архив сервера. Подтвердите замену.
|
||||||
|
|
||||||
.. figure:: ../_static/minecraft-auth/bungeecord_move.png
|
.. figure:: images/minecraft-auth/bungeecord_move.png
|
||||||
:align: center
|
:align: center
|
||||||
:alt: Перетаскивание отредактированного файла назад в архив
|
:alt: Перетаскивание отредактированного файла назад в архив
|
||||||
|
|
||||||
@ -375,12 +337,9 @@ BungeeCord
|
|||||||
Установка на версии ниже 1.7.2
|
Установка на версии ниже 1.7.2
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
Для более старых версий существует достаточно большое многообразие различных случаев, раскрыть которые в этой документации
|
Для более старых версий существует достаточно большое многообразие различных случаев, раскрыть которые в этой документации не представляется возможным. Вся установка заключается в замене определённых строк в определённых классах через InClassTranslator.
|
||||||
не представляется возможным. Вся установка заключается в замене определённых строк в определённых классах через
|
|
||||||
InClassTranslator.
|
|
||||||
|
|
||||||
На форуме RuBukkit есть отличный пост, в котором собрана вся нужна информация по именам классов на различных версиях
|
На форуме RuBukkit есть отличный пост, в котором собрана вся нужна информация по именам классов на различных версиях Minecraft. Переписывать его сюда не имеет смысла, так что просто перейдите на его страницу и найдите нужную версию.
|
||||||
Minecraft. Переписывать его сюда не имеет смысла, так что просто перейдите на его страницу и найдите нужную версию.
|
|
||||||
|
|
||||||
|rubukkit_link|.
|
|rubukkit_link|.
|
||||||
|
|
||||||
@ -394,21 +353,19 @@ Minecraft. Переписывать его сюда не имеет смысла
|
|||||||
|
|
||||||
Предположим, что вы хотите установить авторизацию на сервер версии 1.5.2.
|
Предположим, что вы хотите установить авторизацию на сервер версии 1.5.2.
|
||||||
|
|
||||||
Сначала вы переходите по вышепривидённой ссылке, выбираете нужную версию (1.5.2) и видите список классов:
|
Сначала вы переходите по вышеприведённой ссылке, выбираете нужную версию (1.5.2) и видите список классов:
|
||||||
|
|
||||||
* **bdk.class** - путь до joinserver
|
* **bdk.class** - путь до joinserver
|
||||||
|
|
||||||
* **jg.class** - путь до checkserver
|
* **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
|
:align: center
|
||||||
:alt: Порядок редактирования: выбрать нужную строку, изменить, сохранить.
|
:alt: Порядок редактирования: выбрать нужную строку, изменить, сохранить.
|
||||||
|
|
||||||
@ -418,5 +375,4 @@ Minecraft. Переписывать его сюда не имеет смысла
|
|||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
После этих действий вам нужно в настройках включить online-mode=true и сервер станет пускать на себя только тех игроков,
|
После этих действий вам нужно в настройках включить online-mode=true и сервер станет пускать на себя только тех игроков, которые будут авторизованы через Ely.by.
|
||||||
которые будут авторизованы через Ely.by.
|
|
@ -1,8 +0,0 @@
|
|||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="refresh" content="0; URL=/ru/oauth.html" />
|
|
||||||
<script>
|
|
||||||
window.location.href = '/ru/oauth.html'
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
</html>
|
|
@ -1,24 +1,18 @@
|
|||||||
Авторизация по протоколу OAuth2
|
Авторизация по протоколу OAuth2
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
На этой странице вы найдёте информацию о реализации авторизации по протоколу OAuth2 на вашем проекте через сервис
|
На этой странице вы найдёте информацию о реализации авторизации по протоколу OAuth2 на вашем проекте через сервис Аккаунты Ely.by. Реализация этого протокола позволяет вашим пользователям производить авторизацию с использованием своего аккаунта Ely.by.
|
||||||
Аккаунты Ely.by. Реализация этого протокола позволяет вашим пользователям производить авторизацию с использованием
|
|
||||||
своего аккаунта Ely.by.
|
|
||||||
|
|
||||||
Регистрация приложения
|
Регистрация приложения
|
||||||
======================
|
======================
|
||||||
|
|
||||||
Для начала вам необходимо `создать новое приложение <https://account.ely.by/dev/applications/new>`_. Выберите тип
|
Для начала вам необходимо `создать новое приложение <https://account.ely.by/dev/applications/new>`_. Выберите тип приложения **Веб‑сайт**. В качестве *адреса переадресации* можно указать только домен, но для повышения безопасности лучше использовать полный путь переадресации. Примеры допустимых адресов:
|
||||||
приложения **Веб‑сайт**. В качестве *адреса переадресации* можно указать только домен, но для повышения безопасности
|
|
||||||
лучше использовать полный путь переадресации. Примеры допустимых адресов:
|
|
||||||
|
|
||||||
* :samp:`http://site.com`
|
* ``http://site.com``
|
||||||
* :samp:`http://site.com/oauth/ely`
|
* ``http://site.com/oauth/ely``
|
||||||
* :samp:`http://site.com/oauth.php?provider=ely`
|
* ``http://site.com/oauth.php?provider=ely``
|
||||||
|
|
||||||
После успешного добавления приложения вы попадёте на страницу со списком всех ваших приложений. Кликнув по названию
|
После успешного добавления приложения вы попадёте на страницу со списком всех ваших приложений. Кликнув по названию приложения вы увидите его идентификатор ``clientId`` и секрет ``clientSecret``. Они буду использоваться на следующих шагах.
|
||||||
приложения вы увидите его идентификатор ``clientId`` и секрет ``clientSecret``. Они буду использоваться на
|
|
||||||
следующих шагах.
|
|
||||||
|
|
||||||
Инициализация авторизации
|
Инициализация авторизации
|
||||||
=========================
|
=========================
|
||||||
@ -37,34 +31,29 @@
|
|||||||
- Пример значения
|
- Пример значения
|
||||||
- Описание
|
- Описание
|
||||||
* - *clientId*
|
* - *clientId*
|
||||||
- :samp:`ely`
|
- ``ely``
|
||||||
- **Обязательное**. ClientId, полученный при регистрации.
|
- **Обязательное**. ClientId, полученный при регистрации.
|
||||||
* - *redirect_uri*
|
* - *redirect_uri*
|
||||||
- :samp:`http://site.com/oauth.php`
|
- ``http://site.com/oauth.php``
|
||||||
- **Обязательное**. Адрес обратной переадресации, совпадающий с адресом, указанным при регистрации приложения
|
- **Обязательное**. Адрес обратной переадресации, совпадающий с адресом, указанным при регистрации приложения
|
||||||
* - *response_type*
|
* - *response_type*
|
||||||
- :samp:`code`
|
- ``code``
|
||||||
- **Обязательное**. Тип ответа. На данный момент поддерживается только ``code``.
|
- **Обязательное**. Тип ответа. На данный момент поддерживается только ``code``.
|
||||||
* - *scope*
|
* - *scope*
|
||||||
- :samp:`account_info account_email`
|
- ``account_info account_email``
|
||||||
- **Обязательное**. Перечень разрешений, доступ к которым вы хотите получить, разделённые пробелом. Смотрите все
|
- **Обязательное**. Перечень разрешений, доступ к которым вы хотите получить, разделённые пробелом. Смотрите все доступные права в `разделе ниже <#available-scopes>`_.
|
||||||
доступные права в `разделе ниже <#available-scopes>`_.
|
|
||||||
* - *state*
|
* - *state*
|
||||||
- :samp:`isfvubuysdboinsbdfvit`
|
- ``isfvubuysdboinsbdfvit``
|
||||||
- Случайно сгенерированная строка. Используется для увеличения безопасности в качестве идентификатора сессии. Будет
|
- Случайно сгенерированная строка. Используется для увеличения безопасности в качестве идентификатора сессии. Будет возвращена в неизменённом виде после завершения авторизации.
|
||||||
возвращена в неизменённом виде после завершения авторизации.
|
|
||||||
* - *description*
|
* - *description*
|
||||||
- :samp:`यो अनुप्रयोग विवरण`
|
- ``यो अनुप्रयोग विवरण``
|
||||||
- Если ваше приложение доступно на нескольких языках, то используя это поле вы можете переопределить стандартное
|
- Если ваше приложение доступно на нескольких языках, то используя это поле вы можете переопределить стандартное описание в соответствии с предпочтительным языком пользователя.
|
||||||
описание в соответствии с предпочтительным языком пользователя.
|
|
||||||
* - *prompt*
|
* - *prompt*
|
||||||
- :samp:`consent` или :samp:`select_account`
|
- ``consent`` или ``select_account``
|
||||||
- Принудительно отобразить запрос прав (``consent``) или принудительно запросить выбор аккаунта
|
- Принудительно отобразить запрос прав (``consent``) или принудительно запросить выбор аккаунта (``select_account``).
|
||||||
(``select_account``).
|
|
||||||
* - *login_hint*
|
* - *login_hint*
|
||||||
- :samp:`erickskrauch` или :samp:`erickskrauch@ely.by`
|
- ``erickskrauch`` или ``erickskrauch@ely.by``
|
||||||
- Если у пользователя есть несколько аккаунтов, то указав этот в этом параметре username или email пользователя вы
|
- Если у пользователя есть несколько аккаунтов, то указав этот в этом параметре username или E-mail пользователя вы автоматически выберете аккаунт за него. Это полезно в случае повторного входа, когда токен истёк.
|
||||||
автоматически выберете аккаунт за него. Это полезно в случае повторного входа, когда токен истёк.
|
|
||||||
|
|
||||||
.. _available_scopes:
|
.. _available_scopes:
|
||||||
.. list-table:: Перечень доступных scopes
|
.. list-table:: Перечень доступных scopes
|
||||||
@ -76,12 +65,11 @@
|
|||||||
* - **account_email**
|
* - **account_email**
|
||||||
- В ответе на запрос информации о пользователе будет также присутствовать его email.
|
- В ответе на запрос информации о пользователе будет также присутствовать его email.
|
||||||
* - **offline_access**
|
* - **offline_access**
|
||||||
- Вместе с ``access_token`` вы также получите и ``refresh_token``. Смотрите подробнее
|
- Вместе с ``access_token`` вы также получите и ``refresh_token``. Смотрите подробнее `соответствующем разделе <#refresh-token-grant>`_.
|
||||||
`соответствующем разделе <#refresh-token-grant>`_.
|
|
||||||
* - **minecraft_server_session**
|
* - **minecraft_server_session**
|
||||||
- ``access_token`` можно будет использовать в качестве сессии для Minecraft.
|
- ``access_token`` можно будет использовать в качестве сессии для Minecraft.
|
||||||
|
|
||||||
------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
Сформировав ссылку, разместите её в вашем шаблоне:
|
Сформировав ссылку, разместите её в вашем шаблоне:
|
||||||
|
|
||||||
@ -89,11 +77,9 @@
|
|||||||
|
|
||||||
<a href="<ваша_ссылка>">Войти через Ely.by</a>
|
<a href="<ваша_ссылка>">Войти через Ely.by</a>
|
||||||
|
|
||||||
По нажатию на ссылку, пользователь попадёт на нашу страницу авторизации, откуда после он будет перенаправлен обратно
|
По нажатию на ссылку, пользователь попадёт на нашу страницу авторизации, откуда после он будет перенаправлен обратно по адресу, указанному в параметре ``redirect_uri``.
|
||||||
по адресу, указанному в параметре ``redirect_uri``.
|
|
||||||
|
|
||||||
Обратная переадресация выполняется в виде ``<redirect_uri>?code=<код авторизации>&state=<state>`` для успешной
|
Обратная переадресация выполняется в виде ``<redirect_uri>?code=<код авторизации>&state=<state>`` для успешной авторизации и ``<redirect_uri?error=<идентификатор ошибки>&error_message=<описание ошибки>`` для неудачной.
|
||||||
авторизации и ``<redirect_uri?error=<идентификатор ошибки>&error_message=<описание ошибки>`` для неудачной.
|
|
||||||
|
|
||||||
Пример успешного и неудачного редиректов:
|
Пример успешного и неудачного редиректов:
|
||||||
|
|
||||||
@ -107,8 +93,7 @@
|
|||||||
Обмен кода на ключ
|
Обмен кода на ключ
|
||||||
==================
|
==================
|
||||||
|
|
||||||
После получения кода авторизации (``auth_code``), вам необходимо обменять его на ключ авторизации (``access_key``).
|
После получения кода авторизации (``auth_code``), вам необходимо обменять его на ключ авторизации (``access_key``). Для этого необходимо выполнить POST запрос на URL:
|
||||||
Для этого необходимо выполнить POST запрос на URL:
|
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
@ -176,8 +161,7 @@
|
|||||||
Ответ сервера
|
Ответ сервера
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
В случае успешного запроса в теле ответа будет находиться результат обмена кода авторизации на ``access_token``.
|
В случае успешного запроса в теле ответа будет находиться результат обмена кода авторизации на ``access_token``. Данные являются JSON документом и могут быть легко интерпретированы средствами используемого языка программирования.
|
||||||
Данные являются JSON документом и могут быть легко интерпретированы средствами используемого языка программирования.
|
|
||||||
|
|
||||||
Тело JSON документа содержит следующие поля:
|
Тело JSON документа содержит следующие поля:
|
||||||
|
|
||||||
@ -190,14 +174,12 @@
|
|||||||
"expires_in": 86400 // Количество секунд, на которое выдан токен
|
"expires_in": 86400 // Количество секунд, на которое выдан токен
|
||||||
}
|
}
|
||||||
|
|
||||||
На этом процедура авторизации закончена. Полученный ``access_token`` может быть использован для получения информации о
|
На этом процедура авторизации закончена. Полученный ``access_token`` может быть использован для получения информации о пользователе и взаимодействия с нашим API.
|
||||||
пользователе и взаимодействия с нашим API.
|
|
||||||
|
|
||||||
Получение информации о пользователе
|
Получение информации о пользователе
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
Если полученный токен имеет scope ``account_info``, то вы можете запросить информацию об аккаунте пользователя. Для
|
Если полученный токен имеет scope ``account_info``, то вы можете запросить информацию об аккаунте пользователя. Для этого необходимо отправить запрос на URL:
|
||||||
этого необходимо отправить запрос на URL:
|
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
@ -235,23 +217,18 @@
|
|||||||
"email": "erickskrauch@ely.by"
|
"email": "erickskrauch@ely.by"
|
||||||
}
|
}
|
||||||
|
|
||||||
Обратите внимание, что поле ``email`` будет присутствовать лишь в том случае, когда был запрошен scope
|
Обратите внимание, что поле ``email`` будет присутствовать лишь в том случае, когда был запрошен scope ``account_email``.
|
||||||
``account_email``.
|
|
||||||
|
|
||||||
.. note:: В ходе дальнейшего развития сервиса, количество возвращаемых полей может увеличиться, но уже существующие
|
.. note:: В ходе дальнейшего развития сервиса, количество возвращаемых полей может увеличиться, но уже существующие останутся теми же.
|
||||||
останутся теми же.
|
|
||||||
|
|
||||||
.. _refresh-token-grant:
|
.. _refresh-token-grant:
|
||||||
|
|
||||||
Обновление токена доступа
|
Обновление токена доступа
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
Если при выполнении авторизации вами было запрошено право на получение scope ``offline_access``, то вместе с
|
Если при выполнении авторизации вами было запрошено право на получение scope ``offline_access``, то вместе с ``access_token`` вы также получите и ``refresh_token``. Данный токен не истекает и может быть использован для получения нового токена доступа, когда он истечёт.
|
||||||
``access_token`` вы также получите и ``refresh_token``. Данный токен не истекает и может быть использован для получения
|
|
||||||
нового токена доступа, когда он истечёт.
|
|
||||||
|
|
||||||
Для выполнения операции обновления токена необходимо отправить POST запрос на тот же URL, что использовался и
|
Для выполнения операции обновления токена необходимо отправить POST запрос на тот же URL, что использовался и `при обмене кода на ключ доступа <#authorization-code-grant>`_, но со следующими параметрами:
|
||||||
`при обмене кода на ключ доступа <#authorization-code-grant>`_, но со следующими параметрами:
|
|
||||||
|
|
||||||
.. list-table::
|
.. list-table::
|
||||||
:widths: 1 99
|
:widths: 1 99
|
||||||
@ -262,8 +239,7 @@
|
|||||||
* - ``client_secret``
|
* - ``client_secret``
|
||||||
- ClientSecret, полученный при регистрации приложения.
|
- ClientSecret, полученный при регистрации приложения.
|
||||||
* - ``scope``
|
* - ``scope``
|
||||||
- Те же scope, что были запрошены и при получении начального токена доступа. Попытка запросить большее количество
|
- Те же scope, что были запрошены и при получении начального токена доступа. Попытка запросить большее количество прав приведёт к ошибке.
|
||||||
прав приведёт к ошибке.
|
|
||||||
* - ``refresh_token``
|
* - ``refresh_token``
|
||||||
- Непосредственно токен, полученный вместе с начальным токеном доступа.
|
- Непосредственно токен, полученный вместе с начальным токеном доступа.
|
||||||
|
|
||||||
@ -291,66 +267,56 @@
|
|||||||
$result = json_decode(curl_exec($curl), true);
|
$result = json_decode(curl_exec($curl), true);
|
||||||
curl_close($curl);
|
curl_close($curl);
|
||||||
|
|
||||||
В качестве ответа будет точно такое же тело, какое было получено в результате
|
В качестве ответа будет точно такое же тело, какое было получено в результате `обмена кода на ключ доступа <#authorization-code-grant-response>`_. Поле ``refresh_token`` будет отсутствовать.
|
||||||
`обмена кода на ключ доступа <#authorization-code-grant-response>`_. Поле ``refresh_token`` будет отсутствовать.
|
|
||||||
|
|
||||||
Готовые библиотеки
|
Готовые библиотеки
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Более простым способом будет использовать уже готовую библиотеку, которой будет необходимо передать лишь регистрационные
|
Более простым способом будет использовать уже готовую библиотеку, которой будет необходимо передать лишь регистрационные параметры. Ниже перечислены библиотеки для различных языков программирования. Вы можете дополнить этот список своей библиотекой.
|
||||||
параметры. Ниже перечислены библиотеки для различных языков программирования. Вы можете дополнить этот список своей
|
|
||||||
библиотекой.
|
|
||||||
|
|
||||||
* **PHP**:
|
* **PHP**:
|
||||||
|
|
||||||
- [Official] https://github.com/elyby/league-oauth2-provider
|
- [Официальная] https://github.com/elyby/league-oauth2-provider
|
||||||
|
|
||||||
* **Ruby**:
|
* **Ruby**:
|
||||||
|
|
||||||
- [Official] https://github.com/elyby/omniauth-ely
|
- [Официальная] https://github.com/elyby/omniauth-ely
|
||||||
|
|
||||||
Возможные ошибки
|
Возможные ошибки
|
||||||
================
|
================
|
||||||
|
|
||||||
Ниже приведены стандартные ошибки, которые вы можете получить в случае неправильной передачи данных на сервер
|
Ниже приведены стандартные ошибки, которые вы можете получить в случае неправильной передачи данных на сервер авторизации. Если вы столкнулись с ошибкой, не описанной в этой документации, пожалуйста, сообщите о ней через `форму обратной связи <https://ely.by/site/contact>`_.
|
||||||
авторизации. Если вы столкнулись с ошибкой, не описанной в этой документации, пожалуйста, сообщите о ней через
|
|
||||||
`форму обратной связи <http://ely.by/site/contact>`_.
|
|
||||||
|
|
||||||
.. _auth-start-errors:
|
.. _auth-start-errors:
|
||||||
|
|
||||||
Ошибки при инициализации авторизации
|
Ошибки при инициализации авторизации
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Этот раздел описывает ошибки, отображаемые при переадресации пользователя с вашего сайта на нашу страницу инициализации
|
Этот раздел описывает ошибки, отображаемые при переадресации пользователя с вашего сайта на нашу страницу инициализации авторизации.
|
||||||
авторизации.
|
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
Invalid request ({parameter} required).
|
Invalid request ({parameter} required).
|
||||||
|
|
||||||
Данная ошибка означает, что вы передали не все необходимые параметры. Чтобы решить эту ошибку просто добавьте
|
Данная ошибка означает, что вы передали не все необходимые параметры. Чтобы решить эту ошибку просто добавьте недостающий параметр.
|
||||||
недостающий параметр.
|
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
Invalid response type '{invalid_response_type_value}'.
|
Invalid response type '{invalid_response_type_value}'.
|
||||||
|
|
||||||
Данная ошибка означает, что вы передали неподдерживаемый тип ``response_type``. На данный момент поддерживается только
|
Данная ошибка означает, что вы передали неподдерживаемый тип ``response_type``. На данный момент поддерживается только значение ``code``.
|
||||||
значение ``code``.
|
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
Invalid scope '{invalid_scope}'.
|
Invalid scope '{invalid_scope}'.
|
||||||
|
|
||||||
Ошибка указывает на то, что было запрошено неизвестный ``scope``. Убедитесь, что вы запрашиваете
|
Ошибка указывает на то, что было запрошено неизвестный ``scope``. Убедитесь, что вы запрашиваете `поддерживаемые права <#available-scopes>`_.
|
||||||
`поддерживаемые права <#available-scopes>`_.
|
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
Can not find application you are trying to authorize.
|
Can not find application you are trying to authorize.
|
||||||
|
|
||||||
Данная ошибка говорит о том, что переданные параметры не соответствуют ни одному из зарегистрированных приложений.
|
Данная ошибка говорит о том, что переданные параметры не соответствуют ни одному из зарегистрированных приложений. Для решения проблемы исправьте ваши значения ``client_id`` и ``redirect_uri``.
|
||||||
Для решения проблемы исправьте ваши значения ``client_id`` и ``redirect_uri``.
|
|
||||||
|
|
||||||
.. _issue-token-errors:
|
.. _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_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:**
|
**Возможные значения error:**
|
||||||
|
|
||||||
@ -378,17 +343,14 @@
|
|||||||
* - ``invalid_request``
|
* - ``invalid_request``
|
||||||
- Переданы не все необходимые параметры запроса или значение ``code`` не был найден в базе выданных кодов.
|
- Переданы не все необходимые параметры запроса или значение ``code`` не был найден в базе выданных кодов.
|
||||||
* - ``unsupported_grant_type``
|
* - ``unsupported_grant_type``
|
||||||
- Данная ошибка сигнализирует о том, что вы попытались произвести авторизацию по неизвестному для нашего OAuth2
|
- Данная ошибка сигнализирует о том, что вы попытались произвести авторизацию по неизвестному для нашего OAuth2 сервера типу Grant.
|
||||||
сервера типу Grant.
|
|
||||||
* - ``invalid_client``
|
* - ``invalid_client``
|
||||||
- Эта ошибка возникает в случае, когда трио значений ``client_id``, ``client_secret`` и ``redirect_uri`` не совпали
|
- Эта ошибка возникает в случае, когда трио значений ``client_id``, ``client_secret`` и ``redirect_uri`` не совпали ни с одним из зарегистрированных приложений.
|
||||||
ни с одним из зарегистрированных приложений.
|
|
||||||
|
|
||||||
Ошибки при запросе информации о пользователе
|
Ошибки при запросе информации о пользователе
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Ответ со статусом ``401`` указывает на то, что заголовок ``Authorization`` не присутствует в запросе или его значение
|
Ответ со статусом ``401`` указывает на то, что заголовок ``Authorization`` не присутствует в запросе или его значение сформировано неверно. Тело ответа будет следующим:
|
||||||
сформировано неверно. Тело ответа будет следующим:
|
|
||||||
|
|
||||||
.. code-block:: json
|
.. code-block:: json
|
||||||
|
|
||||||
@ -398,8 +360,7 @@
|
|||||||
"message": "Your request was made with invalid credentials."
|
"message": "Your request was made with invalid credentials."
|
||||||
}
|
}
|
||||||
|
|
||||||
Ответ со статусом ``403`` сигнализирует о том, что переданный в заголовке ``Authorization`` токен не содержит scope
|
Ответ со статусом ``403`` сигнализирует о том, что переданный в заголовке ``Authorization`` токен не содержит scope ``account_info`` или он истёк. Получаемый ответ будет иметь следующий формат:
|
||||||
``account_info`` или он истёк. Получаемый ответ будет иметь следующий формат:
|
|
||||||
|
|
||||||
.. code-block:: json
|
.. code-block:: json
|
||||||
|
|
||||||
@ -412,15 +373,13 @@
|
|||||||
Ошибки при обновлении токена доступа
|
Ошибки при обновлении токена доступа
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
При выполнении обновления токена доступа вам могут встретиться те же ошибки, что и при
|
При выполнении обновления токена доступа вам могут встретиться те же ошибки, что и при `обмене кода на ключ доступа <#issue-token-errors>`_, а также несколько новых:
|
||||||
`обмене кода на ключ доступа <#issue-token-errors>`_, а также несколько новых:
|
|
||||||
|
|
||||||
.. list-table::
|
.. list-table::
|
||||||
:widths: 1 99
|
:widths: 1 99
|
||||||
:header-rows: 0
|
:header-rows: 0
|
||||||
|
|
||||||
* - ``invalid_request``
|
* - ``invalid_request``
|
||||||
- Переданы не все необходимые параметры запроса или значение ``refresh_token`` не был найден в базе выданных
|
- Переданы не все необходимые параметры запроса или значение ``refresh_token`` не был найден в базе выданных токенов.
|
||||||
токенов.
|
|
||||||
* - ``invalid_scope``
|
* - ``invalid_scope``
|
||||||
- Были перечислены неподдерживаемые scope или запрошено больше, чем было у изначального токена.
|
- Были перечислены неподдерживаемые scope или запрошено больше, чем было у изначального токена.
|
@ -1,8 +0,0 @@
|
|||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="refresh" content="0; URL=/ru/skins-system.html" />
|
|
||||||
<script>
|
|
||||||
window.location.href = '/ru/skins-system.html'
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
</html>
|
|
@ -1,46 +1,36 @@
|
|||||||
Система скинов
|
Система скинов
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
На этой странице вы найдёте информацию о доступных запросах к сервису системы скинов Ely.by. Вы можете использовать
|
На этой странице вы найдёте информацию о доступных запросах к сервису системы скинов Ely.by. Вы можете использовать любой из них как дополнительный или основной источник скинов для своего проекта.
|
||||||
любой из них как дополнительный или основной источник скинов для своего проекта.
|
|
||||||
|
|
||||||
Сервис системы скинов Ely.by обеспечивает `проксирование текстур владельцев лицензии Minecraft <#textures-proxy>`_,
|
Сервис системы скинов Ely.by обеспечивает `проксирование текстур владельцев лицензии Minecraft <#textures-proxy>`_, что означает, что при использовании этого сервиса игроки будут видеть как скины премиум пользователей Minecraft, так и скины пользователей сервиса Ely.by.
|
||||||
что означает, что при использовании этого сервиса игроки будут видеть как скины премиум пользователей Minecraft,
|
|
||||||
так и скины пользователей сервиса Ely.by.
|
|
||||||
|
|
||||||
Мы стремимся соответствовать официальной системе скинов и не поддерживаем ушки и HD-скины. Система поддерживает плащи,
|
Мы стремимся соответствовать официальной системе скинов и не поддерживаем ушки и HD-скины. Система поддерживает плащи, но не позволяет игрокам самостоятельно их надевать.
|
||||||
но не позволяет игрокам самостоятельно их надевать.
|
|
||||||
|
|
||||||
Если у вас есть предложения по развитию существующего функционала, пожалуйста,
|
Если у вас есть предложения по развитию существующего функционала, пожалуйста, `создайте новый Issue <https://github.com/elyby/chrly/issues/new>`_ в `репозитории проекта Chrly <https://github.com/elyby/chrly>`_.
|
||||||
`создайте новый Issue <https://github.com/elyby/chrly/issues/new>`_ в
|
|
||||||
`репозитории проекта Chrly <https://github.com/elyby/chrly>`_.
|
|
||||||
|
|
||||||
.. note:: Вы можете найти более подробную информацию о реализации сервера системы скинов в
|
.. note:: Вы можете найти более подробную информацию о реализации сервера системы скинов в `репозитории проекта Chrly <https://github.com/elyby/chrly>`_.
|
||||||
`репозитории проекта Chrly <https://github.com/elyby/chrly>`_.
|
|
||||||
|
|
||||||
URL-адреса запросов
|
URL-адреса запросов
|
||||||
===================
|
===================
|
||||||
|
|
||||||
Система скинов размещена на домене :samp:`http://skinsystem.ely.by`.
|
Система скинов размещена на домене ``http://skinsystem.ely.by``.
|
||||||
|
|
||||||
Во всех запросах параметр :samp:`nickname` должен быть заменён на ник игрока. Значение не чувствительно к регистру.
|
Во всех запросах параметр ``nickname`` должен быть заменён на ник игрока. Значение не чувствительно к регистру.
|
||||||
|
|
||||||
.. _skin-request:
|
.. _skin-request:
|
||||||
.. function:: /skins/{nickname}.png
|
.. function:: /skins/{nickname}.png
|
||||||
|
|
||||||
URL для загрузки текстуры скина. Расширение :samp:`.png` опционально. Если текстура не будет найдена,
|
URL для загрузки текстуры скина. Расширение ``.png`` опционально. Если текстура не будет найдена, сервер вернёт ответ с ``404`` статусом.
|
||||||
сервер вернёт ответ с :samp:`404` статусом.
|
|
||||||
|
|
||||||
.. _cape-request:
|
.. _cape-request:
|
||||||
.. function:: /cloaks/{nickname}.png
|
.. function:: /cloaks/{nickname}.png
|
||||||
|
|
||||||
URL для загрузки текстуры плаща. Расширение :samp:`.png` опционально. Если текстура не будет найдена,
|
URL для загрузки текстуры плаща. Расширение ``.png`` опционально. Если текстура не будет найдена, сервер вернёт ответ с ``404`` статусом.
|
||||||
сервер вернёт ответ с :samp:`404` статусом.
|
|
||||||
|
|
||||||
.. function:: /textures/{nickname}
|
.. function:: /textures/{nickname}
|
||||||
|
|
||||||
По этому URL вы можете получить текстуры в формате, указанному в поле :samp:`textures` одноимённого property
|
По этому URL вы можете получить текстуры в формате, указанному в поле ``textures`` одноимённого property в `ответе на запрос подписанных текстур <https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape>`_:
|
||||||
в `ответе на запрос подписанных текстур <https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape>`_:
|
|
||||||
|
|
||||||
.. code-block:: javascript
|
.. code-block:: javascript
|
||||||
|
|
||||||
@ -56,21 +46,15 @@ URL-адреса запросов
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
В зависимости от доступных игроку текстур могут отсутствовать поля :samp:`SKIN` или :samp:`CAPE`.
|
В зависимости от доступных игроку текстур могут отсутствовать поля ``SKIN`` или ``CAPE``. Если модель скина не является ``slim``, то поле ``metadata`` также будет отсутствовать.
|
||||||
Если модель скина не является :samp:`slim`, то поле :samp:`metadata` также будет отсутствовать.
|
|
||||||
|
|
||||||
Если текстуры не будут найдены, сервер вернёт пустой ответ с :samp:`204` статусом.
|
Если текстуры не будут найдены, сервер вернёт пустой ответ с ``204`` статусом.
|
||||||
|
|
||||||
.. function:: /profile/{nickname}
|
.. function:: /profile/{nickname}
|
||||||
|
|
||||||
Данный запрос является аналогом запроса
|
Данный запрос является аналогом запроса `профиля игрока в API Mojang <https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape>`_, только вместо идентификации пользователя по UUID используется его ник. Также, как и в API Mojang, вы можете добавить к запросу ``?unsigned=false``, чтобы получить текстуры с подписью. В ответе также будет присутствовать дополнительное property с ``name`` равным **ely**.
|
||||||
`профиля игрока в API Mojang <https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape>`_, только вместо
|
|
||||||
идентификации пользователя по UUID используется его ник. Также, как и в API Mojang, вы можете добавить к запросу
|
|
||||||
``?unsigned=false``, чтобы получить текстуры с подписью. В ответе также будет присутствовать дополнительное property
|
|
||||||
с ``name`` равным **ely**.
|
|
||||||
|
|
||||||
Если у пользователя нет текстур, то они будут запрошены через прокси Mojang, после чего переподписаны с
|
Если у пользователя нет текстур, то они будут запрошены через прокси Mojang, после чего переподписаны с использованием `нашего ключа подписи <#signature-verification-key-request>`_.
|
||||||
использованием `нашего ключа подписи <#signature-verification-key-request>`_.
|
|
||||||
|
|
||||||
.. code-block:: javascript
|
.. code-block:: javascript
|
||||||
|
|
||||||
@ -90,15 +74,12 @@ URL-адреса запросов
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
Если запрошенный никнейм не будет найден ни в локальном хранилище, ни у Mojang, сервер вернёт пустой ответ с ``204``
|
Если запрошенный никнейм не будет найден ни в локальном хранилище, ни у Mojang, сервер вернёт пустой ответ с ``204`` статусом.
|
||||||
статусом.
|
|
||||||
|
|
||||||
.. _signature-verification-key-request:
|
.. _signature-verification-key-request:
|
||||||
.. function:: /signature-verification-key.der
|
.. function:: /signature-verification-key.der
|
||||||
|
|
||||||
Данный запрос возвращает публичный ключ, который может быть использован для проверки подписи текстур. Ключ
|
Данный запрос возвращает публичный ключ, который может быть использован для проверки подписи текстур. Ключ предоставляется в формате ``DER``. Этот формат используется внутри Authlib, поэтому ключ может быть в ней использован без модификации алгоритма проверки подписи.
|
||||||
предоставляется в формате ``DER``. Этот формат используется внутри Authlib, поэтому ключ может быть в ней использован
|
|
||||||
без модификации алгоритма проверки подписи.
|
|
||||||
|
|
||||||
.. function:: /signature-verification-key.pem
|
.. function:: /signature-verification-key.pem
|
||||||
|
|
||||||
@ -106,10 +87,7 @@ URL-адреса запросов
|
|||||||
|
|
||||||
.. function:: /textures/signed/{nickname}
|
.. function:: /textures/signed/{nickname}
|
||||||
|
|
||||||
Этот запрос используется в нашем `плагине серверной системы скинов <http://ely.by/server-skins-system>`_ для
|
Этот запрос используется в нашем `плагине серверной системы скинов <https://ely.by/server-skins-system>`_ для загрузки текстур с оригинальной подписью Mojang. Полученные в ответе текстуры могут быть без изменений переданы в немодифицированный игровой клиент. В ответе также будет присутствовать дополнительное property с ``name`` равным **ely**.
|
||||||
загрузки текстур с оригинальной подписью Mojang. Полученные в ответе текстуры могут быть без изменений переданы в
|
|
||||||
немодифицированный игровой клиент. В ответе также будет присутствовать дополнительное property с :samp:`name`
|
|
||||||
равным **ely**.
|
|
||||||
|
|
||||||
.. code-block:: javascript
|
.. code-block:: javascript
|
||||||
|
|
||||||
@ -129,23 +107,19 @@ URL-адреса запросов
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
По умолчанию для этого запроса не применяется проксирование текстур. Чтобы его включить, добавьте дополнительный
|
По умолчанию для этого запроса не применяется проксирование текстур. Чтобы его включить, добавьте дополнительный GET параметр ``?proxy=true``.
|
||||||
GET параметр :samp:`?proxy=true`.
|
|
||||||
|
|
||||||
Если текстуры не будут найдены, сервер вернёт пустой ответ с :samp:`204` статусом.
|
Если текстуры не будут найдены, сервер вернёт пустой ответ с ``204`` статусом.
|
||||||
|
|
||||||
------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
При совершении любого из вышеописанных запросов вы также можете передать ряд дополнительных GET параметров. Они будут
|
При совершении любого из вышеописанных запросов вы также можете передать ряд дополнительных GET параметров. Они будут использованы для анализа использования сервиса разными версиями игры.
|
||||||
использованы для анализа использования сервиса разными версиями игры.
|
|
||||||
|
|
||||||
:version: Версия протокола, по которому идёт запрос на скины. На данный момент это версия :samp:`2` ,
|
:version: Версия протокола, по которому идёт запрос на скины. На данный момент это версия ``2`` , т.е. вам необходимо указать ``version=2``.
|
||||||
т.е. вам необходимо указать :samp:`version=2`.
|
|
||||||
|
|
||||||
:minecraft_version: Версия Minecraft, с которой идёт запрос.
|
:minecraft_version: Версия Minecraft, с которой идёт запрос.
|
||||||
|
|
||||||
:authlib_version: Версия используемой Authlib. Этот параметр актуален для версий Minecraft 1.7.6+, где
|
:authlib_version: Версия используемой Authlib. Этот параметр актуален для версий Minecraft 1.7.6+, где для загрузки скинов стала использоваться отдельная библиотека, а не внутриигровой код.
|
||||||
для загрузки скинов стала использоваться отдельная библиотека, а не внутриигровой код.
|
|
||||||
|
|
||||||
Пример запроса текстур с передачей вышеописанных параметров:
|
Пример запроса текстур с передачей вышеописанных параметров:
|
||||||
|
|
||||||
@ -156,10 +130,7 @@ URL-адреса запросов
|
|||||||
Вспомогательные URL
|
Вспомогательные URL
|
||||||
+++++++++++++++++++
|
+++++++++++++++++++
|
||||||
|
|
||||||
Также запрос скина и плаща можно выполнить, передавая ник через GET параметр. Эта возможность используется для
|
Также запрос скина и плаща можно выполнить, передавая ник через GET параметр. Эта возможность используется для передачи аналитических параметров в версиях игры до 1.5.2, когда ник просто добавлялся в конец строки. Для этого вся строка выстраивается таким образом, чтобы последним параметром шёл ``name``, после добавления ника к которому получался полный запрос на текстуру.
|
||||||
передачи аналитических параметров в версиях игры до 1.5.2, когда ник просто добавлялся в конец строки. Для этого вся
|
|
||||||
строка выстраивается таким образом, чтобы последним параметром шёл :samp:`name`, после добавления ника к которому
|
|
||||||
получался полный запрос на текстуру.
|
|
||||||
|
|
||||||
.. function:: /skins?name={nickname}.png
|
.. function:: /skins?name={nickname}.png
|
||||||
|
|
||||||
@ -181,23 +152,17 @@ URL-адреса запросов
|
|||||||
Проксирование текстур
|
Проксирование текстур
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
Сервис системы скинов Ely.by получает текстуры из официальной системы скинов в случае, если в базе данных не было
|
Сервис системы скинов Ely.by получает текстуры из официальной системы скинов в случае, если в базе данных не было найдено информации о текстурах для запрошенного имени пользователя. Также запрос будет проксирован, если запись о скине будет найдена, но он будет стандартным.
|
||||||
найдено информации о текстурах для запрошенного имени пользователя. Также запрос будет проксирован, если запись о скине
|
|
||||||
будет найдена, но он будет стандартным.
|
|
||||||
|
|
||||||
Для улучшения пропускной способности проксирующего алгоритма, информация о текстурах кешируется в 2 стадии:
|
Для улучшения пропускной способности проксирующего алгоритма, информация о текстурах кешируется в 2 стадии:
|
||||||
|
|
||||||
* Соответствие ника и UUID хранится в
|
* Соответствие ника и UUID хранится в `течение 30 дней <https://help.minecraft.net/hc/en-us/articles/360034636712-Minecraft-Usernames#article-container:~:text=How%20often%20can%20I%20change%20my%20username%3F>`_.
|
||||||
`течение 30 дней <https://help.minecraft.net/hc/en-us/articles/360034636712-Minecraft-Usernames#article-container:~:text=How%20often%20can%20I%20change%20my%20username%3F>`_.
|
|
||||||
|
|
||||||
* Информация о текстурах обновляется не чаще
|
* Информация о текстурах обновляется не чаще `раза в минуту <https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape:~:text=You%20can%20request%20the%20same%20profile%20once%20per%20minute>`_.
|
||||||
`раза в минуту <https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape:~:text=You%20can%20request%20the%20same%20profile%20once%20per%20minute>`_.
|
|
||||||
|
|
||||||
Если вы владеете лицензионным аккаунтом Minecraft, но ваш ник занят, пожалуйста, обратитесь в
|
Если вы владеете лицензионным аккаунтом Minecraft, но ваш ник занят, пожалуйста, обратитесь в `службу поддержки <https://ely.by/site/contact>`_ и после небольшой проверки мы передадим ник в ваше пользование.
|
||||||
`службу поддержки <http://ely.by/site/contact>`_ и после небольшой проверки мы передадим ник в ваше пользование.
|
|
||||||
|
|
||||||
Готовые реализации
|
Готовые реализации
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Готовые реализации патчей и инструкции по их установке могут быть найдены в
|
Готовые реализации патчей и инструкции по их установке могут быть найдены в `разделе загрузок на главном сайте Ely.by <https://ely.by/load>`_.
|
||||||
`разделе загрузок на главном сайте Ely.by <http://ely.by/load>`_.
|
|