{"id":468456,"date":"2025-07-24T15:00:57","date_gmt":"2025-07-24T15:00:57","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=468456"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=468456","title":{"rendered":"<span>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f: \u043f\u0443\u0442\u044c \u043e\u0442 \u0438\u0434\u0435\u0438 \u0434\u043e \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 web store<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043d\u0430\u0447\u0430\u043b\u0430\u0441\u044c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438\u0434\u0435\u0438: \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u0438\u043b\u044b \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u0437\u0430 \u0434\u0432\u0435 \u043d\u0435\u0434\u0435\u043b\u0438 \u043f\u0440\u043e\u0448\u0451\u043b \u043f\u0443\u0442\u044c \u043e\u0442 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430 \u0434\u043e \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 Chrome Web Store \u0438 Firefox Add-ons, \u043a\u0430\u043a\u0438\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0438 \u0441 \u043a\u0430\u043a\u0438\u043c\u0438 \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f. \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u043c\u043e\u0439 \u043e\u043f\u044b\u0442 \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u0438\u0442 \u0434\u0440\u0443\u0433\u0438\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u0438\u043b\u044b \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0430 <a href=\"https:\/\/github.com\/pulichkin\/findmylink\" rel=\"noopener noreferrer nofollow\">GitHub<\/a>.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ef2\/614\/5a6\/ef26145a62707ef851e0516cf8af20d7.png\" width=\"512\" height=\"512\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ef2\/614\/5a6\/ef26145a62707ef851e0516cf8af20d7.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ef2\/614\/5a6\/ef26145a62707ef851e0516cf8af20d7.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<hr\/>\n<h3>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0438 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435<\/h3>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/202\/bfb\/af8\/202bfbaf8388eb54aec4131bf5cd92a0.jpg\" width=\"1280\" height=\"731\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/202\/bfb\/af8\/202bfbaf8388eb54aec4131bf5cd92a0.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/202\/bfb\/af8\/202bfbaf8388eb54aec4131bf5cd92a0.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>\u0418\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u0440\u044b\u043d\u043a\u0430<\/h4>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435, \u044f \u0438\u0437\u0443\u0447\u0438\u043b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 Chrome-\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439. \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e, \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c, \u043d\u043e \u044f \u043d\u0430\u0448\u0451\u043b \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u0431\u0438\u043d\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 Chrome Web Store [1]. \u041e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0438 \u043e\u043f\u043b\u0430\u0442\u0438\u0442\u044c \u0435\u0434\u0438\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0432\u0437\u043d\u043e\u0441 \u0432 \u0440\u0430\u0437\u043c\u0435\u0440\u0435 5 \u0434\u043e\u043b\u043b\u0430\u0440\u043e\u0432. \u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u0432\u0435\u0441\u0442\u043e\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u043e\u0431\u0440\u0430\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u043f\u043b\u0430\u0442\u044b, \u043d\u043e \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u0442\u043b\u043e\u0436\u0438\u0442\u044c \u0435\u0433\u043e \u0434\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u044f \u0438\u0437\u0443\u0447\u0438\u043b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e WebExtensions API [2], \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043b\u0435\u0436\u0438\u0442 \u0432 \u043e\u0441\u043d\u043e\u0432\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0434\u043b\u044f Chrome \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u043c\u043d\u0435 \u043f\u043e\u043d\u044f\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u043e\u043c \u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u043a API \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u0442\u0430\u043a\u0438\u043c \u043a\u0430\u043a <code>chrome.bookmarks<\/code> \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0430\u043c. \u0418\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u043b\u043e, \u0447\u0442\u043e \u0438\u0434\u0435\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u0430 \u0438 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<h4>\u041f\u0435\u0440\u0432\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f<\/h4>\n<p>\u0414\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0441\u0442\u0430\u0440\u0442\u0430 \u044f \u0432\u044b\u0431\u0440\u0430\u043b \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a Quasar [3], \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0443\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. Quasar \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u0438\u0441\u0442\u0438\u0447\u043d\u044b\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c: \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0432\u044b\u0432\u043e\u0434 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043f\u043e \u043c\u0435\u0440\u0435 \u0432\u0432\u043e\u0434\u0430. \u041f\u0440\u043e\u0442\u043e\u0442\u0438\u043f \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u043f\u0440\u043e\u0441\u0442\u043e, \u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e, \u0447\u0442\u043e \u0434\u0430\u043b\u043e \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0432 \u0436\u0438\u0437\u043d\u0435\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0438\u0434\u0435\u0438. \u041e\u0434\u043d\u0430\u043a\u043e \u044f \u0437\u0430\u043c\u0435\u0442\u0438\u043b, \u0447\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0438\u0437\u044e\u043c\u0438\u043d\u043a\u0438 \u2014 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0434\u0435\u043b\u0430\u043b \u0431\u044b \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u043c.<\/p>\n<h4>\u0414\u0438\u0437\u0430\u0439\u043d \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430<\/h4>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1fc\/043\/3e2\/1fc0433e28447cf58ef0573f66c25561.jpg\" width=\"415\" height=\"621\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/1fc\/043\/3e2\/1fc0433e28447cf58ef0573f66c25561.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1fc\/043\/3e2\/1fc0433e28447cf58ef0573f66c25561.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0427\u0442\u043e\u0431\u044b \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043e\u043f\u044b\u0442, \u044f \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043b \u043a \u043f\u0440\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0434\u0438\u0437\u0430\u0439\u043d\u0430. \u0418\u043c\u0435\u044f \u043e\u043f\u044b\u0442 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043a\u0443\u0440\u0441\u043e\u0432 \u043f\u043e UI\/UX-\u0434\u0438\u0437\u0430\u0439\u043d\u0443, \u044f \u0441\u043e\u0437\u0434\u0430\u043b \u043c\u0430\u043a\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u0431\u044b \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0438 \u044d\u0441\u0442\u0435\u0442\u0438\u0447\u043d\u044b\u043c. \u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u043f\u043e\u0438\u0441\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f. \u0413\u043b\u044f\u0434\u044f \u043d\u0430 \u0441\u0432\u043e\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0441 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u0432\u043a\u043b\u0430\u0434\u043e\u043a, \u044f \u0440\u0435\u0448\u0438\u043b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0433\u043b\u0430 \u0431\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u043f\u043e \u0434\u0435\u0441\u044f\u0442\u043a\u0430\u043c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446. \u0423 \u043c\u0435\u043d\u044f, \u043a\u0430\u043a \u0438 \u0443 \u043c\u043d\u043e\u0433\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0447\u0430\u0441\u0442\u043e \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043e\u043a: \u0443\u0432\u0438\u0434\u0435\u043b \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e, \u043e\u0442\u043a\u0440\u044b\u043b \u0435\u0451, \u043d\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043d\u0435\u0442, \u0438 \u0432\u043a\u043b\u0430\u0434\u043a\u0430 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u043d\u0430 \u043d\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u0441\u0440\u043e\u043a. \u041d\u0430\u0439\u0442\u0438 \u0447\u0442\u043e-\u0442\u043e \u0441\u0440\u0435\u0434\u0438 \u043d\u0438\u0445 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u043e, \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0438 \u0438\u043b\u0438 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f \u0432\u043a\u043b\u0430\u0434\u043e\u043a \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u042d\u0442\u0430 \u0438\u0434\u0435\u044f \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u0440\u0435\u0448\u0430\u0435\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043f\u043e\u0432\u0441\u0435\u0434\u043d\u0435\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<p>\u041d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0432\u0438\u0434\u0435\u043d\u0438\u044f \u044f \u043e\u0431\u043d\u043e\u0432\u0438\u043b \u0434\u0438\u0437\u0430\u0439\u043d, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c, \u0438 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043b \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u0438\u0437\u0443\u0447\u0438\u0442\u044c API \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c\u0438 (<code>chrome.tabs<\/code>) [2], \u0447\u0442\u043e \u0441\u0442\u0430\u043b\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435.<\/p>\n<p>[1] Chrome Web Store Developer Dashboard, <a href=\"https:\/\/developer.chrome.com\/webstore\" rel=\"noopener noreferrer nofollow\">https:\/\/developer.chrome.com\/webstore<br \/><\/a>[2] WebExtensions API, <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions\" rel=\"noopener noreferrer nofollow\">https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions<br \/><\/a>[3] Quasar Framework, <a href=\"https:\/\/quasar.dev\/\" rel=\"noopener noreferrer nofollow\">https:\/\/quasar.dev\/<\/a><\/p>\n<h3>\u041c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u044f<\/h3>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/794\/c50\/49d\/794c5049d2894c5a2b4a1fc29bdc148f.jpeg\" width=\"1200\" height=\"722\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/794\/c50\/49d\/794c5049d2894c5a2b4a1fc29bdc148f.jpeg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/794\/c50\/49d\/794c5049d2894c5a2b4a1fc29bdc148f.jpeg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u0430\u0432\u043d\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043d\u043e\u0441\u0438\u043b \u0431\u044b \u043f\u043e\u043b\u044c\u0437\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0438, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0434\u043e\u0445\u043e\u0434, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u0438\u043c\u0432\u043e\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u043c. \u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043c\u043e\u0433 \u0431\u044b \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u0440\u0443\u0433\u0438\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u043e\u0442\u044f\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0434\u0443\u043a\u0442, \u043d\u043e \u043d\u0435 \u0437\u043d\u0430\u044e\u0442, \u0441 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c. \u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0434 <em>FindMyLink<\/em> \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438: \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u043c, \u0430 \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u043f\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u0431\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0440\u0435\u043c\u0438\u0443\u043c-\u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0432 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<p>\u0412\u043e\u043f\u0440\u043e\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c. \u0421\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0431\u043e\u0442\u0430 \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c, \u043a\u0442\u043e \u043e\u043f\u043b\u0430\u0442\u0438\u043b \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443, \u0430 \u043a\u0442\u043e \u043d\u0435\u0442. \u041f\u043e\u0441\u043b\u0435 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043f\u043b\u0430\u0442\u0451\u0436\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a Stripe, \u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u043d\u0430 Telegram Payments API [4] \u0438\u0437-\u0437\u0430 \u0435\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0438 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438 \u0441\u0440\u0435\u0434\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. Telegram Payments API \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043d\u0432\u043e\u0439\u0441\u044b \u0447\u0435\u0440\u0435\u0437 \u0431\u043e\u0442\u0430, \u0447\u0442\u043e \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u043b\u043e \u0434\u043b\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u043f\u043b\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 Telegram, \u0430 \u0431\u043e\u0442 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442 \u043f\u043b\u0430\u0442\u0451\u0436 \u0438 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u0440\u0435\u043c\u0438\u0443\u043c-\u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c. \u0414\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430\u043c\u0438 \u0431\u044b\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c, \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0430\u044f Telegram-\u0431\u043e\u0442\u0430 \u0438 API, \u0447\u0442\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u0430\u0445.<\/p>\n<p>[4] Telegram Payments API, <a href=\"https:\/\/core.telegram.org\/bots\/payments\" rel=\"noopener noreferrer nofollow\">https:\/\/core.telegram.org\/bots\/payments<\/a><\/p>\n<h3>\u0411\u044d\u043a\u0435\u043d\u0434: Telegram-\u0431\u043e\u0442 \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0435\u0436\u0435\u0439<\/h3>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/954\/925\/b9c\/954925b9c4129fa834061911acbfbc1f.jpg\" width=\"1280\" height=\"731\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/954\/925\/b9c\/954925b9c4129fa834061911acbfbc1f.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/954\/925\/b9c\/954925b9c4129fa834061911acbfbc1f.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>\u0412\u044b\u0431\u043e\u0440 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438<\/h4>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Telegram Payments API [4] \u044f \u0440\u0435\u0448\u0438\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Telegram-\u0431\u043e\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0438\u043d\u0432\u043e\u0439\u0441\u044b \u0438 \u043f\u043b\u0430\u0442\u0435\u0436\u0438. \u041f\u043e\u0441\u043b\u0435 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043f\u043b\u0430\u0442\u0451\u0436\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a Stripe, \u044f \u0432\u044b\u0431\u0440\u0430\u043b Telegram \u0438\u0437-\u0437\u0430 \u0435\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435. \u0414\u043b\u044f \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u043d\u0430 SQLite \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <code>aiosqlite<\/code> \u0438 <code>SQLAlchemy[asyncio]<\/code> [5], \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439, \u0438 SQLite \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u0445 \u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430\u0445. \u0414\u043b\u044f \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f KeyDB [6], \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441 Redis, \u043d\u043e \u0431\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u0438 \u043b\u0451\u0433\u043a\u0438\u0439 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435. \u0411\u043e\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <code>python-telegram-bot<\/code> [7], \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 Telegram API. \u0414\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u043b\u0438\u0441\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <code>msgspec<\/code> [8] \u0438 <code>config-lib-msgspec<\/code> [9], \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u044b\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u043a\u043e\u043b\u043b\u0435\u0433\u043e\u0439 \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u0430 \u0443\u0434\u043e\u0431\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u0437 YAML, \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438.<\/p>\n<p><strong>\u0422\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u0442\u0435\u043a \u0431\u043e\u0442\u0430:<\/strong><\/p>\n<ul>\n<li>\n<p><strong>Framework<\/strong>: <code>python-telegram-bot<\/code> (\u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439) \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 Telegram API.<\/p>\n<\/li>\n<li>\n<p><strong>\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>: SQLite + <code>aiosqlite<\/code> + <code>SQLAlchemy[asyncio]<\/code> \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u044d\u0448<\/strong>: KeyDB (Redis-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439) \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0430\u043d\u043d\u044b\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f<\/strong>: <code>msgspec<\/code> + <code>config-lib-msgspec<\/code> \u0434\u043b\u044f \u0433\u0438\u0431\u043a\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043b\u0430\u0442\u0435\u0436\u0438<\/strong>: Telegram Payments API \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043e\u043a.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0441 config-lib-msgspec<\/h4>\n<pre><code class=\"python\"># bot\/src\/configs\/config.py from typing import List from config_lib.base import BaseConfig from msgspec import Struct, field  class TelegramConfig(Struct):     bot_token: str | None = None     payment_provider_token: str | None = None     admin_ids: List[int] = 0,  class DatabaseConfig(Struct):     path: str | None = None     default_lang: str | None = None     default_trial_used: bool = False     default_auto_renewal: bool = True  class BotConfig(BaseConfig):     telegram: TelegramConfig = field(default_factory=TelegramConfig)     database: DatabaseConfig = field(default_factory=DatabaseConfig)     redis: RedisConfig = field(default_factory=RedisConfig)     rate_limit: RateLimitConfig = field(default_factory=RateLimitConfig)     subscription: SubscriptionConfig = field(default_factory=SubscriptionConfig)     logging: LoggingConfig = field(default_factory=LoggingConfig)  # \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433 \u0438\u0437 YAML\/ENV\/CLI config = BotConfig.load() <\/code><\/pre>\n<h4>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0431\u043e\u0442\u0430<\/h4>\n<pre><code class=\"python\"># bot\/src\/bot.py from telegram import Update from telegram.ext import Application, CommandHandler, MessageHandler, filters from configs.config import config  async def start_command(update: Update, context):     \"\"\"\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a\u043e\u043c\u0430\u043d\u0434\u044b \/start\"\"\"     user_id = update.effective_user.id     await context.bot.send_message(         chat_id=update.effective_chat.id,         text=f\"\u041f\u0440\u0438\u0432\u0435\u0442! \u042f \u0431\u043e\u0442 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u043e\u0439 FindMyLink.\\n\"              f\"\u0412\u0430\u0448 ID: {user_id}\"     )  async def subscribe_command(update: Update, context):     \"\"\"\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a\u043e\u043c\u0430\u043d\u0434\u044b \/subscribe\"\"\"     # \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0438\u043d\u0432\u043e\u0439\u0441 \u0434\u043b\u044f \u043e\u043f\u043b\u0430\u0442\u044b     invoice = await context.bot.create_invoice(         title=\"\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 FindMyLink\",         description=\"\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u043e\u0438\u0441\u043a\u0443 \u043f\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u043d\u0430 30 \u0434\u043d\u0435\u0439\",         payload=\"subscription_30_days\",         provider_token=config.telegram.payment_provider_token,         currency=\"RUB\",         prices=[{\"label\": \"\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430\", \"amount\": 29900}]  # 299 \u0440\u0443\u0431\u043b\u0435\u0439     )          await context.bot.send_invoice(         chat_id=update.effective_chat.id,         **invoice     )  def main():     application = Application.builder().token(config.telegram.bot_token).build()          application.add_handler(CommandHandler(\"start\", start_command))     application.add_handler(CommandHandler(\"subscribe\", subscribe_command))          application.run_polling() <\/code><\/pre>\n<p>[4] Telegram Payments API, <a href=\"https:\/\/core.telegram.org\/bots\/payments\" rel=\"noopener noreferrer nofollow\">https:\/\/core.telegram.org\/bots\/payments<br \/><\/a>[5] SQLAlchemy, <a href=\"https:\/\/www.sqlalchemy.org\/\" rel=\"noopener noreferrer nofollow\">https:\/\/www.sqlalchemy.org\/<br \/><\/a>[6] KeyDB, <a href=\"https:\/\/keydb.dev\/\" rel=\"noopener noreferrer nofollow\">https:\/\/keydb.dev\/<br \/><\/a>[7] python-telegram-bot, <a href=\"https:\/\/python-telegram-bot.org\/\" rel=\"noopener noreferrer nofollow\">https:\/\/python-telegram-bot.org\/<br \/><\/a>[8] msgspec, <a href=\"https:\/\/jcristharif.com\/msgspec\" rel=\"noopener noreferrer nofollow\">https:\/\/jcristharif.com\/msgspec\/<br \/><\/a>[9] config-lib-msgspec, <a href=\"https:\/\/github.com\/rastaclaus\/config-lib-msgspec\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/rastaclaus\/config-lib-msgspec<\/a><\/p>\n<h3>\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 Telegram<\/h3>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/597\/419\/6a5\/5974196a567305fe1b127ba73e2fa49d.jpeg\" width=\"1200\" height=\"696\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/597\/419\/6a5\/5974196a567305fe1b127ba73e2fa49d.jpeg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/597\/419\/6a5\/5974196a567305fe1b127ba73e2fa49d.jpeg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u043c<\/h4>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u044f \u0440\u0435\u0448\u0438\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Telegram Login Widget [10], \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 Telegram. \u041f\u043e\u0441\u043b\u0435 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u044f \u0432\u044b\u044f\u0441\u043d\u0438\u043b, \u0447\u0442\u043e \u0432\u0438\u0434\u0436\u0435\u0442 \u043f\u0440\u043e\u0441\u0442 \u0432 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0435 Telegram-\u0431\u043e\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443 \u043c\u0435\u043d\u044f \u0443\u0436\u0435 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0434\u043b\u044f \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043b \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432\u0438\u0434\u0436\u0435\u0442 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u043f\u0440\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u043f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u043f\u043e\u043f\u0430\u043f\u0430 \u0441 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u043c \u043e\u043d \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0441\u044f \u043f\u0443\u0441\u0442\u044b\u043c. \u041f\u043e\u0441\u043b\u0435 \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u044f \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b, \u0447\u0442\u043e Telegram Login Widget \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u0441 HTTPS [10]. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0443 \u043c\u0435\u043d\u044f \u0435\u0449\u0451 \u043d\u0435 \u0431\u044b\u043b\u043e \u0434\u043e\u043c\u0435\u043d\u0430 \u0438 VPS, \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c HTTPS \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<h4>\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430<\/h4>\n<p>\u0427\u0442\u043e\u0431\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 Telegram Login Widget \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435, \u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b HTTPS-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0448\u0430\u0433\u0438:<\/p>\n<ol>\n<li>\n<p><strong>\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u043c\u0435\u043d\u0430 \u0432 \/etc\/hosts<\/strong><br \/>\u041e\u0442\u043a\u0440\u044b\u043b \u0444\u0430\u0439\u043b <code>\/etc\/hosts<\/code> \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 \u0441\u0443\u043f\u0435\u0440\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:  <\/p>\n<pre><code class=\"bash\">sudo vim \/etc\/hosts <\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043b \u0441\u0442\u0440\u043e\u043a\u0443, \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u044e\u0449\u0443\u044e <a href=\"http:\/\/testdomain.com\" rel=\"noopener noreferrer nofollow\"><code>testdomain.com<\/code><\/a> \u0441 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u043c IP:  <\/p>\n<pre><code>127.0.0.1    testdomain.com <\/code><\/pre>\n<p>\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u043b \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043a\u0440\u044b\u043b \u0444\u0430\u0439\u043b (:wq).<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 Nginx<\/strong><br \/>\u0421\u043e\u0437\u0434\u0430\u043b \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439 Nginx:  <\/p>\n<pre><code class=\"bash\">mkdir -p ~\/nginx-proxy\/conf.d <\/code><\/pre>\n<p>\u0421\u043e\u0437\u0434\u0430\u043b \u0444\u0430\u0439\u043b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438:  <\/p>\n<pre><code class=\"bash\">vim ~\/nginx-proxy\/conf.d\/testdomain.conf <\/code><\/pre>\n<p>\u0412\u0441\u0442\u0430\u0432\u0438\u043b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e, \u0437\u0430\u043c\u0435\u043d\u0438\u0432 \u043f\u043e\u0440\u0442 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 8000):  <\/p>\n<pre><code class=\"nginx\">server {     listen 80;     server_name testdomain.com;     return 301 https:\/\/$host$request_uri; }  server {     listen 443 ssl;     server_name testdomain.com;      ssl_certificate     \/etc\/nginx\/ssl\/testdomain.com+3.pem;     ssl_certificate_key \/etc\/nginx\/ssl\/testdomain.com+3-key.pem;      ssl_protocols TLSv1.2 TLSv1.3;     ssl_ciphers HIGH:!aNULL:!MD5;      location \/ {         proxy_pass http:\/\/host.docker.internal:8000;         proxy_set_header Host $host;         proxy_set_header X-Real-IP $remote_addr;         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;         proxy_set_header X-Forwarded-Proto $scheme;     } } <\/code><\/pre>\n<\/li>\n<li>\n<p><strong>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f SSL-\u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430<\/strong><br \/>\u0421\u043e\u0437\u0434\u0430\u043b \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f SSL-\u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432:  <\/p>\n<pre><code class=\"bash\">mkdir -p ~\/nginx-proxy\/ssl <\/code><\/pre>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b \u0443\u0442\u0438\u043b\u0438\u0442\u0443 <code>mkcert<\/code> \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0445 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432:  <\/p>\n<pre><code class=\"bash\">sudo apt install mkcert  # Linux # \u0438\u043b\u0438 brew install mkcert      # Mac <\/code><\/pre>\n<p>\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0441\u0430\u043c\u043e\u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442:  <\/p>\n<pre><code class=\"bash\">mkcert testdomain.com <\/code><\/pre>\n<p>\u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043b \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044b \u0432 \u043f\u0430\u043f\u043a\u0443 Nginx:  <\/p>\n<pre><code class=\"bash\">mv testdomain.com.pem ~\/nginx-proxy\/ssl\/findmylinkbot.crt mv testdomain.com-key.pem ~\/nginx-proxy\/ssl\/findmylinkbot.key <\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b Nginx:  <\/p>\n<pre><code class=\"bash\">docker restart nginx-proxy <\/code><\/pre>\n<\/li>\n<li>\n<p><strong>\u0417\u0430\u043f\u0443\u0441\u043a Nginx \u0432 Docker<\/strong><br \/>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043b \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 Nginx \u0441 \u043f\u0440\u043e\u0431\u0440\u043e\u0441\u043e\u043c \u043f\u043e\u0440\u0442\u043e\u0432 \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439:  <\/p>\n<pre><code class=\"bash\">docker run -d \\     --name nginx-proxy \\     -p 80:80 \\     -p 443:443 \\     -v ~\/nginx-proxy\/conf.d:\/etc\/nginx\/conf.d \\     -v ~\/nginx-proxy\/ssl:\/etc\/nginx\/ssl \\     --add-host=host.docker.internal:host-gateway \\     nginx <\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 <code>host.docker.internal<\/code> \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u043e\u043f\u0446\u0438\u044e <code>--network=\"host\"<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430<\/strong><br \/>\u0423\u0431\u0435\u0434\u0438\u043b\u0441\u044f, \u0447\u0442\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u043d\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c \u043f\u043e\u0440\u0442\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 8000). \u0415\u0441\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0435 \u0431\u044b\u043b \u0437\u0430\u043f\u0443\u0449\u0435\u043d, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u043a\u043e\u043c\u0430\u043d\u0434\u0443:  <\/p>\n<pre><code class=\"bash\">docker run -d --name myapp --network mynet -p 8000:8000 myapp <\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435:  <\/p>\n<ul>\n<li>\n<p><a href=\"http:\/\/testdomain.com\" rel=\"noopener noreferrer nofollow\">http:\/\/testdomain.com<\/a> (\u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442 \u043d\u0430 HTTPS)  <\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/testdomain.com\" rel=\"noopener noreferrer nofollow\">https:\/\/testdomain.com<\/a> (\u0441 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435\u043c \u043e \u0441\u0430\u043c\u043e\u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0435).<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u0448\u0430\u0433\u043e\u0432 Telegram Login Widget \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<h4>\u041f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u043d\u0438 \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/h4>\n<p>\u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u043b\u043e\u0441\u044c \u043a\u0430\u043a \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u043e\u043f\u0430\u043f \u043f\u043e\u0434 \u0438\u043a\u043e\u043d\u043a\u043e\u0439 \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430. \u042f \u043e\u0436\u0438\u0434\u0430\u043b, \u0447\u0442\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 Telegram \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c: \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 \u201c\u0412\u043e\u0439\u0442\u0438\u201d, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043f\u0430\u043f \u0441 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u043c, \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e, \u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0438. \u041e\u0434\u043d\u0430\u043a\u043e \u043f\u0440\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u044b\u043c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u043c: \u043f\u0440\u0438 \u0441\u043c\u0435\u043d\u0435 \u0444\u043e\u043a\u0443\u0441\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043b\u0438\u043a\u0435 \u0432\u043d\u0435 \u043e\u043a\u043d\u0430) \u043f\u043e\u043f\u0430\u043f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u043b\u0441\u044f (\u044d\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435), \u0438\u0437-\u0437\u0430 \u0447\u0435\u0433\u043e \u043a\u043e\u043b\u0431\u044d\u043a \u043e\u0442 Telegram \u043d\u0435 \u0434\u043e\u0445\u043e\u0434\u0438\u043b \u0434\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u043b\u0438\u0441\u044c \u0432 <code>localStorage<\/code>. \u041f\u043e\u043d\u044f\u043b \u044f \u044d\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0437\u0443, \u0430 \u043e\u043f\u044b\u0442\u043d\u044b\u043c \u043f\u0443\u0442\u0451\u043c: \u043f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u043f\u043e\u043f\u0430\u043f \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u0441\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c, \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043b\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e, \u043d\u043e \u0431\u0435\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u043f\u0440\u0438 \u043f\u043e\u0442\u0435\u0440\u0435 \u0444\u043e\u043a\u0443\u0441\u0430 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u044c \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u044f \u0438\u0437\u043c\u0435\u043d\u0438\u043b \u043f\u043e\u0434\u0445\u043e\u0434: \u0432\u043c\u0435\u0441\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u043f\u0430\u043f\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u043d\u043e \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u0441\u043c\u0435\u043d\u0435 \u0444\u043e\u043a\u0443\u0441\u0430. \u042d\u0442\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043a\u043e\u0434\u0430:<\/p>\n<pre><code class=\"javascript\">\/\/ public\/redirect-popup.js \/\/ \u0415\u0441\u043b\u0438 \u043e\u0442\u043a\u0440\u044b\u043b\u0438 popup \u043a\u0430\u043a \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435, \u0441\u0440\u0430\u0437\u0443 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u043d\u043e \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c popup if (window.location.pathname.endsWith('index.html')) {   window.open(     chrome.runtime.getURL('normal_popup.html'),     'findmylink_popup',     'width=380,height=600'   );   window.close(); } <\/code><\/pre>\n<p>\u0422\u0430\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u043e \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u043d\u043e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u043f\u043e\u0442\u0435\u0440\u0435\u0439 \u0444\u043e\u043a\u0443\u0441\u0430 \u0431\u044b\u043b\u0430 \u0440\u0435\u0448\u0435\u043d\u0430, \u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f.<\/p>\n<h4>\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 API<\/h4>\n<pre><code class=\"typescript\">\/\/ src\/components\/auth.ts export function initTelegramLoginButton(container: HTMLElement) {   const loginButton = document.createElement('button');   loginButton.className = 'telegram-login-button w-full py-2 px-4 bg-[#0088cc] text-white rounded-lg hover:bg-[#0077b3] transition-colors flex items-center justify-center gap-2';   loginButton.textContent = t('login.button');      loginButton.onclick = () =&gt; {     \/\/ \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0432\u043d\u0435\u0448\u043d\u044e\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438     const authUrl = `${CONFIG.API.BASE_URL}${CONFIG.API.ENDPOINTS.EXTENSION_AUTH}`;     const win = window.open(authUrl, 'telegram_auth', 'width=500,height=600');          \/\/ \u0421\u043b\u0443\u0448\u0430\u0435\u043c postMessage \u0441 \u0442\u043e\u043a\u0435\u043d\u043e\u043c     function handler(event: MessageEvent) {       if (event.data?.type === CONFIG.MESSAGES.TELEGRAM_TOKEN &amp;&amp; event.data.token) {         chrome.runtime.sendMessage({            type: CONFIG.MESSAGES.TELEGRAM_TOKEN,            token: event.data.token          });         window.removeEventListener('message', handler);         if (win) win.close();       }     }     window.addEventListener('message', handler);   };      container.appendChild(loginButton); } <\/code><\/pre>\n<p>\u0414\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u044f \u043f\u0435\u0440\u0435\u043d\u0451\u0441 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c API, \u0447\u0442\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435. \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e, API \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0441 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u043c, \u0430 \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0432\u0445\u043e\u0434\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u0442\u043e\u043a\u0435\u043d \u0447\u0435\u0440\u0435\u0437 <code>postMessage<\/code> [11]. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430\u0434\u0451\u0436\u043d\u044b\u043c \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c Chrome Web Store.<\/p>\n<p>[10] Telegram Login Widget, <a href=\"https:\/\/core.telegram.org\/widgets\/login\" rel=\"noopener noreferrer nofollow\">https:\/\/core.telegram.org\/widgets\/login<br \/><\/a>[11] WebExtensions API, <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions\" rel=\"noopener noreferrer nofollow\">https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions<\/a><\/p>\n<h3>API \u0434\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f<\/h3>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/18e\/f81\/6a8\/18ef816a83a38e9b8546bf79f1715c69.jpg\" width=\"1280\" height=\"731\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/18e\/f81\/6a8\/18ef816a83a38e9b8546bf79f1715c69.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/18e\/f81\/6a8\/18ef816a83a38e9b8546bf79f1715c69.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>\u0412\u044b\u0431\u043e\u0440 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 API<\/h4>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0449\u0435\u0439 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c \u0438 Telegram-\u0431\u043e\u0442\u043e\u043c, \u044f \u0432\u044b\u0431\u0440\u0430\u043b \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a Litestar [12], \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 Django \u043f\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0443, \u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0435\u0433\u043e \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0437\u0430\u0434\u0430\u0447. Litestar \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b SQLite \u0447\u0435\u0440\u0435\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <code>aiosqlite<\/code> \u0438 <code>SQLAlchemy[asyncio]<\/code> [5], \u0447\u0442\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u043b\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0443 \u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u041a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e KeyDB [6], \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0433\u043e \u0441 Redis, \u0434\u043b\u044f \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0430\u043d\u043d\u044b\u043c \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u0445 \u0438 \u0438\u0445 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430\u0445. \u0414\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <code>msgspec<\/code> [8] \u0438 <code>config-lib-msgspec<\/code> [9], \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u044b\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u043a\u043e\u043b\u043b\u0435\u0433\u043e\u0439 \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u0430 \u0443\u0434\u043e\u0431\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u0437 YAML, \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438.<\/p>\n<p><strong>\u0422\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u0442\u0435\u043a API:<\/strong><\/p>\n<ul>\n<li>\n<p><strong>Framework<\/strong>: Litestar \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0433\u043e REST API.<\/p>\n<\/li>\n<li>\n<p><strong>\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>: SQLite + <code>aiosqlite<\/code> + <code>SQLAlchemy[asyncio]<\/code> \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u044d\u0448<\/strong>: KeyDB \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0430\u043d\u043d\u044b\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f<\/strong>: <code>msgspec<\/code> \u0438 <code>config-lib-msgspec<\/code> \u0434\u043b\u044f \u0433\u0438\u0431\u043a\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u044b\u0431\u043e\u0440 Litestar \u0431\u044b\u043b \u043e\u0431\u0443\u0441\u043b\u043e\u0432\u043b\u0435\u043d \u0435\u0433\u043e \u043f\u043e\u0445\u043e\u0436\u0435\u0441\u0442\u044c\u044e \u043d\u0430 Django, \u043d\u043e \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0447\u0442\u043e \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u043e\u0448\u043b\u043e \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0438 \u043b\u0451\u0433\u043a\u043e\u0433\u043e API. SQLite \u0438 KeyDB \u043e\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0433\u0434\u0435 \u043d\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u0430\u0441\u044c \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430.<\/p>\n<h4>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 API<\/h4>\n<p>API \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043e\u0442 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 Telegram \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438. \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\n<p><code>\/auth\/telegram<\/code>: \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0441 Telegram Login Widget \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><code>\/auth\/callback<\/code>: \u041e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u043b\u0431\u044d\u043a \u043e\u0442 Telegram, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u044c \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d.<\/p>\n<\/li>\n<li>\n<p><code>\/subscription\/status<\/code>: \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0441\u0442\u0430\u0442\u0443\u0441 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"python\"># api\/src\/routers\/auth.py from litestar import get, post, Router from litestar.exceptions import HTTPException from msgspec import Struct from sqlalchemy.ext.asyncio import AsyncSession  from models import User from services import TelegramAuthService  class TelegramAuthResponse(Struct):     token: str  @get(\"\/auth\/telegram\") async def get_auth_page() -&gt; str:     return f\"\"\"     &lt;!DOCTYPE html&gt;     &lt;html&gt;         &lt;body&gt;             &lt;script async src=\"https:\/\/telegram.org\/js\/telegram-widget.js?22\"                     data-telegram-login=\"{config.telegram.bot_name}\"                     data-size=\"large\"                     data-request-access=\"write\"                     data-onauth=\"onTelegramAuth(user)\"&gt;             &lt;\/script&gt;             &lt;script&gt;                 function onTelegramAuth(user) {{                     fetch('{config.api.base_url}\/auth\/callback', {{                         method: 'POST',                         headers: {{ 'Content-Type': 'application\/json' }},                         body: JSON.stringify(user)                     }})                     .then(response =&gt; response.json())                     .then(data =&gt; {{                         window.opener.postMessage({{                             type: '{config.messages.telegram_token}',                             token: data.token                         }}, '*');                         window.close();                     }});                 }}             &lt;\/script&gt;         &lt;\/body&gt;     &lt;\/html&gt;     \"\"\"  @post(\"\/auth\/callback\") async def telegram_callback(data: dict, db: AsyncSession) -&gt; TelegramAuthResponse:     if not TelegramAuthService.verify_signature(data):         raise HTTPException(status_code=400, detail=\"Invalid signature\")          user_id = data[\"id\"]     user = await User.get(db, user_id)     if not user:         user = User(id=user_id, username=data.get(\"username\"))         await user.save(db)          token = TelegramAuthService.generate_token(user_id)     return TelegramAuthResponse(token=token) <\/code><\/pre>\n<h4>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/h4>\n<p>\u0414\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u043e\u0434\u043f\u0438\u0441\u0438 Telegram, \u043a\u0430\u043a \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Telegram Login Widget [10]. \u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 API \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 JWT-\u0442\u043e\u043a\u0435\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044e \u0447\u0435\u0440\u0435\u0437 <code>postMessage<\/code> [11]. \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u044d\u0442\u043e\u0442 \u0442\u043e\u043a\u0435\u043d \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a API, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438. \u0414\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u0445 \u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430\u0445 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 SQLite, \u0430 KeyDB \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0438 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438, \u0447\u0442\u043e \u0441\u043d\u0438\u0436\u0430\u0435\u0442 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0430 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<h4>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Telegram-\u0431\u043e\u0442\u043e\u043c<\/h4>\n<p>API \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 Telegram-\u0431\u043e\u0442\u043e\u043c \u0447\u0435\u0440\u0435\u0437 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0432\u044b\u0437\u043e\u0432\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0438\u043d\u0432\u043e\u0439\u0441\u0430 \u0431\u043e\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043a API, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c. \u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u043e\u043f\u043b\u0430\u0442\u044b API \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0441\u0442\u0430\u0442\u0443\u0441 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0435\u0442 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435. \u042d\u0442\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u0435\u0436\u0434\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e (\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c), \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0438 \u0431\u043e\u0442\u043e\u043c.<\/p>\n<p>[5] SQLAlchemy, <a href=\"https:\/\/www.sqlalchemy.org\/\" rel=\"noopener noreferrer nofollow\">https:\/\/www.sqlalchemy.org\/<br \/><\/a>[6] KeyDB, <a href=\"https:\/\/keydb.dev\/\" rel=\"noopener noreferrer nofollow\">https:\/\/keydb.dev\/<br \/><\/a>[8] msgspec, <a href=\"https:\/\/jcristharif.com\/msgspec\/\" rel=\"noopener noreferrer nofollow\">https:\/\/jcristharif.com\/msgspec\/<br \/><\/a>[9] config-lib-msgspec, <a href=\"https:\/\/github.com\/rastaclaus\/config-lib-msgspec\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/rastaclaus\/config-lib-msgspec<br \/><\/a>[10] Telegram Login Widget, <a href=\"https:\/\/core.telegram.org\/widgets\/login\" rel=\"noopener noreferrer nofollow\">https:\/\/core.telegram.org\/widgets\/login<br \/><\/a>[11] WebExtensions API, <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions\" rel=\"noopener noreferrer nofollow\">https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions<br \/><\/a>[12] Litestar, <a href=\"https:\/\/litestar.dev\/\" rel=\"noopener noreferrer nofollow\">https:\/\/litestar.dev\/<\/a><\/p>\n<h3>\u0414\u0435\u043f\u043b\u043e\u0439 \u0438 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430<\/h3>\n<h4>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/h4>\n<p>\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0434\u0435\u043f\u043b\u043e\u044f API \u0438 Telegram-\u0431\u043e\u0442\u0430 \u0431\u044b\u043b \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c, \u043d\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438. \u042f \u0430\u0440\u0435\u043d\u0434\u043e\u0432\u0430\u043b VPS \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0438 \u0432\u044b\u0431\u0440\u0430\u043b Docker [13] \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0447\u0442\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u043b\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u043b\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f. HTTPS \u0431\u044b\u043b \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Caddy [14], \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 SSL-\u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430\u043c\u0438 \u0447\u0435\u0440\u0435\u0437 Let\u2019s Encrypt.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 HTTPS \u044f \u0441\u043e\u0437\u0434\u0430\u043b Caddyfile \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439:<\/p>\n<pre><code class=\"json\"># Caddyfile api.findmylink.com {     reverse_proxy localhost:8000 } <\/code><\/pre>\n<p>Caddy \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b SSL-\u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u0434\u043b\u044f \u0434\u043e\u043c\u0435\u043d\u0430 <a href=\"http:\/\/api.findmylink.com\" rel=\"noopener noreferrer nofollow\"><code>api.findmylink.com<\/code><\/a>, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 Telegram Login Widget \u0438 API. \u042d\u0442\u043e \u0438\u0437\u0431\u0430\u0432\u0438\u043b\u043e \u043c\u0435\u043d\u044f \u043e\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044b, \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<h4>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438<\/h4>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c \u044f \u0441\u043e\u0437\u0434\u0430\u043b <code>.env<\/code> \u0444\u0430\u0439\u043b\u044b \u0434\u043b\u044f API \u0438 Telegram-\u0431\u043e\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e. \u041f\u0440\u0438\u043c\u0435\u0440 <code>.env<\/code> \u0444\u0430\u0439\u043b\u0430 \u0434\u043b\u044f API:<\/p>\n<pre><code class=\"bash\"># api\/.env CFG_DATABASE_URL=sqlite+aiosqlite:\/\/\/data.db CFG_REDIS_URL=redis:\/\/keydb:6379 CFG_API_BASE_URL=https:\/\/api.findmylink.com <\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 <code>.env<\/code> \u0444\u0430\u0439\u043b\u0430 \u0434\u043b\u044f \u0431\u043e\u0442\u0430:<\/p>\n<pre><code class=\"bash\"># bot\/.env CFG_TELEGRAM_BOT_TOKEN=your_bot_token_here CFG_PAYMENT_PROVIDER_TOKEN=your_payment_provider_token_here <\/code><\/pre>\n<p>\u042d\u0442\u0438 \u0444\u0430\u0439\u043b\u044b \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u043b\u0438\u0441\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <code>config-lib-msgspec<\/code> [9], \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u043b\u043e \u0433\u0438\u0431\u043a\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u0447\u0435\u0440\u0435\u0437 YAML, \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438.<\/p>\n<h4>\u0420\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h4>\n<p>\u042f \u0441\u043e\u0437\u0434\u0430\u043b Docker-\u043e\u0431\u0440\u0430\u0437\u044b \u0434\u043b\u044f API (\u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 Litestar) \u0438 Telegram-\u0431\u043e\u0442\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Dockerfile \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430. \u041f\u0440\u0438\u043c\u0435\u0440 Dockerfile \u0434\u043b\u044f API:<\/p>\n<pre><code class=\"bash\"># api\/Dockerfile FROM python:3.11-slim  WORKDIR \/app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD [\"litestar\", \"run\", \"--host\", \"0.0.0.0\", \"--port\", \"8000\"] <\/code><\/pre>\n<p>\u0414\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b <code>docker-compose<\/code> \u0434\u043b\u044f \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 API, \u0431\u043e\u0442\u0430 \u0438 KeyDB. \u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"yaml\"># docker-compose.yml version: '3.8' services:   api:     build: .\/api     ports:       - \"8000:8000\"     env_file:       - .\/api\/.env     volumes:       - .\/api:\/app     depends_on:       - keydb    bot:     build: .\/bot     env_file:       - .\/bot\/.env     volumes:       - .\/bot:\/app     depends_on:       - keydb    keydb:     image: eqalpha\/keydb     ports:       - \"6379:6379\"     volumes:       - keydb_data:\/data  volumes:   keydb_data: <\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 <code>docker-compose up -d<\/code> \u0432\u0441\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b (API, \u0431\u043e\u0442 \u0438 KeyDB) \u0431\u044b\u043b\u0438 \u0440\u0430\u0437\u0432\u0451\u0440\u043d\u0443\u0442\u044b \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u0414\u043b\u044f \u0437\u0430\u0449\u0438\u0442\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0431\u0440\u0430\u043d\u0434\u043c\u0430\u0443\u044d\u0440\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>ufw<\/code>, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432 \u0434\u043e\u0441\u0442\u0443\u043f \u0442\u043e\u043b\u044c\u043a\u043e \u043a \u043f\u043e\u0440\u0442\u0430\u043c 80, 443 \u0438 22.<\/p>\n<h4>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Cloudflare<\/h4>\n<p>\u0414\u043b\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b \u0434\u043e\u043c\u0435\u043d <a href=\"http:\/\/findmylink.ru\" rel=\"noopener noreferrer nofollow\"><code>findmylink.ru<\/code><\/a> \u043a Cloudflare [15]. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 DNS, \u0437\u0430\u0449\u0438\u0442\u0443 \u043e\u0442 DDoS-\u0430\u0442\u0430\u043a \u0438 \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Cloudflare \u0431\u044b\u043b\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0439: \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u0434\u043e\u043c\u0435\u043d \u0432 \u0438\u0445 \u043f\u0430\u043d\u0435\u043b\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f, \u043e\u0431\u043d\u043e\u0432\u0438\u043b DNS-\u0437\u0430\u043f\u0438\u0441\u0438 \u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 \u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u043b \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 Cloudflare \u0434\u043b\u044f \u043f\u043e\u0440\u0442\u0430 443.<\/p>\n<h4>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f<\/h4>\n<p>\u041d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0434\u0435\u043f\u043b\u043e\u044f \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a API \u0438\u0437 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0438\u0437-\u0437\u0430 CORS (Cross-Origin Resource Sharing). Chrome \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043b \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0441 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043a \u0432\u043d\u0435\u0448\u043d\u0435\u043c\u0443 API, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0438 \u0441\u0447\u0438\u0442\u0430\u043b\u0438\u0441\u044c \u043a\u0440\u043e\u0441\u0441-\u0434\u043e\u043c\u0435\u043d\u043d\u044b\u043c\u0438. \u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 CORS \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e Litestar:<\/p>\n<pre><code class=\"python\"># api\/src\/main.py from litestar import Litestar from litestar.middleware import DefineMiddleware from litestar.middleware.cors import CORSConfig  cors_config = CORSConfig(allow_origins=[\"chrome-extension:\/\/*\"], allow_methods=[\"GET\", \"POST\"], allow_headers=[\"*\"]) app = Litestar(route_handlers=[...], middleware=[DefineMiddleware(CORSConfig, cors_config)]) <\/code><\/pre>\n<p>\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 API. \u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 HTTPS \u0447\u0435\u0440\u0435\u0437 Caddy \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 Cloudflare \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e, \u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u043b\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438.<\/p>\n<p>[13] Docker, <a href=\"https:\/\/www.docker.com\/\" rel=\"noopener noreferrer nofollow\">https:\/\/www.docker.com\/<br \/><\/a>[14] Caddy, <a href=\"https:\/\/caddyserver.com\/\" rel=\"noopener noreferrer nofollow\">https:\/\/caddyserver.com\/<br \/><\/a>[15] Cloudflare, <a href=\"https:\/\/www.cloudflare.com\/\" rel=\"noopener noreferrer nofollow\">https:\/\/www.cloudflare.com\/<\/a><\/p>\n<h3>\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0432 Chrome Web Store<\/h3>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c15\/4e4\/c39\/c154e4c39e9ff0145e93a3e211dff05b.jpg\" width=\"1280\" height=\"385\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c15\/4e4\/c39\/c154e4c39e9ff0145e93a3e211dff05b.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c15\/4e4\/c39\/c154e4c39e9ff0145e93a3e211dff05b.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438<\/h4>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u0433\u043e\u0442\u043e\u0432\u043e, \u044f \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043b \u043a \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0432 Chrome Web Store [1]. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0438 \u043e\u043f\u043b\u0430\u0442\u0438\u0442\u044c \u0435\u0434\u0438\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0432\u0437\u043d\u043e\u0441 \u0432 \u0440\u0430\u0437\u043c\u0435\u0440\u0435 5 \u0434\u043e\u043b\u043b\u0430\u0440\u043e\u0432. \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u043e\u043f\u043b\u0430\u0442\u044b \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043d\u0435\u043f\u0440\u043e\u0441\u0442\u044b\u043c: \u044f \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432, \u043d\u043e \u0432 \u0438\u0442\u043e\u0433\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 Telegram-\u0431\u043e\u0442\u0430 \u0434\u043b\u044f \u043e\u043f\u043b\u0430\u0442\u044b, \u0447\u0442\u043e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u043c, \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043a\u043e\u043c\u0438\u0441\u0441\u0438\u044e. \u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u043e\u043f\u043b\u0430\u0442\u044b \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u0430\u0431\u0438\u043d\u0435\u0442\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043e\u0442\u043a\u0440\u044b\u043b\u0441\u044f \u0441\u0440\u0430\u0437\u0443.<\/p>\n<p>\u0414\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u044f \u0437\u0430\u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u043b \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u0430\u043f\u043a\u0438 <code>dist<\/code>, \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u043b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u043e\u043b\u044f \u0432 \u043a\u0430\u0431\u0438\u043d\u0435\u0442\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b \u0430\u0440\u0445\u0438\u0432. \u041d\u0430 \u043a\u0430\u0436\u0434\u043e\u0435 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043d\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e\u0441\u0442\u0443\u043f \u043a <code>storage<\/code> \u0438\u043b\u0438 <code>bookmarks<\/code>) \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u044f \u0441\u0434\u0435\u043b\u0430\u043b, \u043e\u043f\u0438\u0441\u0430\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 API.<\/p>\n<h4>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/h4>\n<p>\u0427\u0435\u0440\u0435\u0437 \u0434\u0435\u043d\u044c-\u0434\u0432\u0430 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043e\u0442\u043a\u0430\u0437 \u043e\u0442 Chrome Web Store. \u041f\u0440\u0438\u0447\u0438\u043d\u0430 \u0431\u044b\u043b\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u043c \u0434\u043e\u043c\u0435\u043d\u0435, \u2014 \u044d\u0442\u043e \u043a\u0430\u0441\u0430\u043b\u043e\u0441\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Telegram Login Widget [10]. \u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u044f \u0432\u0441\u0442\u0440\u043e\u0438\u043b \u0432\u0438\u0434\u0436\u0435\u0442 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043e\u0448\u0438\u0431\u043a\u043e\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u043d\u0430\u0440\u0443\u0448\u0430\u043b\u043e \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 Chrome \u043f\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043e\u0431\u043e\u0439\u0442\u0438 \u044d\u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435, \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0432 API. \u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u043f\u0430\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043a API, \u0430 API \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0441 Telegram Login Widget. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c Chrome Web Store, \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u042f \u043e\u0431\u043d\u043e\u0432\u0438\u043b \u043a\u043e\u0434 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u043e \u0441 API \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"javascript\">\/\/ src\/auth.js function openTelegramAuthPopup() {   const authUrl = `${CONFIG.API.BASE_URL}${CONFIG.API.ENDPOINTS.EXTENSION_AUTH}`;   window.open(authUrl, 'telegram_auth', 'width=500,height=600'); }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0432 Chrome Web Store. \u041d\u0430 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u043e\u0448\u043b\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e, \u0438 \u0447\u0435\u0440\u0435\u0437 \u0434\u0435\u043d\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043e.<\/p>\n<p>[1] Chrome Web Store Developer Dashboard,<a href=\"https:\/\/chromewebstore.google.com\/\" rel=\"noopener noreferrer nofollow\">https:\/\/chromewebstore.google.com<\/a><a href=\"https:\/\/developer.chrome.com\/webstore%EF%BF%BC%5B10%5D\" rel=\"noopener noreferrer nofollow\"><br \/><\/a>[10] Telegram Login Widget, <a href=\"https:\/\/core.telegram.org\/widgets\/login\" rel=\"noopener noreferrer nofollow\">https:\/\/core.telegram.org\/widgets\/login<\/a><\/p>\n<h3>\u041a\u0443\u0434\u0430 \u0435\u0449\u0451 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043b\u043e\u0436\u0438\u0442\u044c?<\/h3>\n<h4>Firefox Add-ons<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 <em>FindMyLink<\/em> \u0432 Chrome Web Store \u044f \u0440\u0435\u0448\u0438\u043b \u0438\u0437\u0443\u0447\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u0430\u0433\u0430\u0437\u0438\u043d\u0430\u0445, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 Firefox Add-ons [2]. \u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0432 Firefox \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0439, \u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043c\u043e\u0434\u0435\u0440\u0430\u0446\u0438\u0438 \u2014 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u044b\u043c. \u0414\u043b\u044f \u0430\u0434\u0430\u043f\u0442\u0430\u0446\u0438\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u0432\u043d\u0435\u0441\u0442\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0444\u0430\u0439\u043b <code>manifest.json<\/code>, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c Mozilla, \u043d\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435, \u0438\u043a\u043e\u043d\u043a\u0438 \u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u0434 \u043e\u0441\u0442\u0430\u043b\u0438\u0441\u044c \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043e \u043d\u0430 WebExtensions API [11].<\/p>\n<p>\u041f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0430\u0440\u0445\u0438\u0432\u0430 \u0432 Firefox Add-ons Developer Hub \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u043a\u043e\u0434 \u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0430 \u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0438. \u041f\u043e\u0441\u043b\u0435 \u0438\u0445 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443. \u041c\u043e\u0434\u0435\u0440\u0430\u0446\u0438\u044f \u0437\u0430\u043d\u044f\u043b\u0430 \u043e\u043a\u043e\u043b\u043e \u043f\u044f\u0442\u0438 \u0434\u043d\u0435\u0439, \u0447\u0442\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c\u0443 \u0441\u0440\u043e\u043a\u0443 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u0440\u0435\u0432\u044c\u044e\u0432\u0435\u0440\u0430. \u0412 \u0438\u0442\u043e\u0433\u0435 \u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043f\u0438\u0441\u044c\u043c\u043e \u0441 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435\u043c: \u201cYour Extension has been automatically screened and tentatively approved.\u201d \u0421\u0442\u0430\u0442\u0443\u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0441\u043c\u0435\u043d\u0438\u043b\u0441\u044f \u043d\u0430 \u201cApproved\u201d, \u0438 \u043e\u043d\u043e \u0431\u044b\u043b\u043e \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043e. \u0412 \u0446\u0435\u043b\u043e\u043c, \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432.<\/p>\n<h4>Microsoft Edge Add-ons<\/h4>\n<p>\u0414\u0440\u0443\u0433\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c \u0441\u0442\u0430\u043b Microsoft Edge Add-ons [16]. \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u043f\u043e\u0445\u043e\u0436\u0438\u043c \u043d\u0430 Chrome Web Store: \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0432 Microsoft Partner Center, \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0430\u0440\u0445\u0438\u0432\u0430, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f, \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u0432 \u0438 \u0438\u043a\u043e\u043d\u043e\u043a. \u041c\u0430\u043d\u0438\u0444\u0435\u0441\u0442 \u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c, \u0442\u0430\u043a \u043a\u0430\u043a Edge, \u043a\u0430\u043a \u0438 Chrome, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 WebExtensions API, \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f Microsoft \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442 \u0438\u0445 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c [17]. \u042f \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043b \u0447\u0435\u0440\u043d\u043e\u0432\u0438\u043a, \u043d\u043e \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043e\u0448\u0438\u0431\u043a\u0443: \u201cCannot publish extension. Your developer account verification is either pending or rejected. Please complete your account verification on the Account Settings page before you begin publishing.\u201d<\/p>\n<p>\u041d\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0432 \u043b\u0438\u0447\u043d\u043e\u043c \u043a\u0430\u0431\u0438\u043d\u0435\u0442\u0435, \u043a\u0440\u043e\u043c\u0435 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u0440\u043e\u0444\u0438\u043b\u0435, \u043d\u0435 \u0431\u044b\u043b\u043e \u043d\u0438 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0432\u0435\u0440\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u043d\u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \u0434\u043b\u044f \u0435\u0451 \u0437\u0430\u043f\u0443\u0441\u043a\u0430. \u041f\u043e\u0438\u0441\u043a \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u043d\u0435 \u0434\u0430\u043b \u0447\u0451\u0442\u043a\u0438\u0445 \u043e\u0442\u0432\u0435\u0442\u043e\u0432: \u044f \u043d\u0430\u0448\u0451\u043b \u043b\u0438\u0448\u044c \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f, \u0447\u0442\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u0435\u0440\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435, \u043d\u043e \u0432 \u043c\u043e\u0451\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u043e\u0432 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u043d\u0435 \u0431\u044b\u043b\u043e. \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0431 \u043e\u043f\u043b\u0430\u0442\u0435 \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u0430. \u0412 \u0438\u0442\u043e\u0433\u0435 \u044f \u043f\u0440\u0438\u0448\u0451\u043b \u043a \u0432\u044b\u0432\u043e\u0434\u0443, \u0447\u0442\u043e, \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u0435\u0440\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 Microsoft Partner Center \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u043c \u0438 \u043d\u0435 \u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u044b\u043c, \u0447\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0438\u044f \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<h4>\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0432 GitHub Releases<\/h4>\n<p>\u0415\u0449\u0451 \u043e\u0434\u043d\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c \u0431\u044b\u043b\u043e \u0432\u044b\u043b\u043e\u0436\u0438\u0442\u044c \u0437\u0430\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0432 \u0440\u0435\u043b\u0438\u0437\u0430\u0445 GitHub [18]. \u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431, \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0449\u0438\u0439 \u043c\u043e\u0434\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u043b\u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438: \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0430\u0440\u0445\u0438\u0432 \u0438\u0437 \u043f\u0430\u043f\u043a\u0438 <code>dist<\/code> \u0432 \u0440\u0430\u0437\u0434\u0435\u043b Releases \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f. \u041e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u0438\u043c\u0435\u0435\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f: \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u043c, \u043a\u0442\u043e \u0437\u043d\u0430\u0435\u0442 \u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438 \u0441\u043b\u0435\u0434\u0438\u0442 \u0437\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u043c, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u0443\u0436\u0430\u0435\u0442 \u0430\u0443\u0434\u0438\u0442\u043e\u0440\u0438\u044e \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u0432 Chrome Web Store \u0438\u043b\u0438 Firefox Add-ons. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b GitHub \u043a\u0430\u043a \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439, \u0430 \u043d\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u0430\u043d\u0430\u043b \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f.<\/p>\n<h4>\u041f\u043e \u043f\u043e\u0432\u043e\u0434\u0443 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438<\/h4>\n<p>\u041f\u043e\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u043c\u0430\u043b\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e-\u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0448\u043b\u043e. \u041d\u043e \u0434\u0430\u0436\u0435 \u043f\u0430\u0440\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043e\u043a \u0443\u0436\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0439 \u043f\u043e\u0431\u0435\u0434\u043e\u0439!<\/p>\n<p>[2] Firefox Add-ons, <a href=\"https:\/\/addons.mozilla.org\/\" rel=\"noopener noreferrer nofollow\">https:\/\/addons.mozilla.org\/<br \/><\/a>[11] WebExtensions API, <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions\" rel=\"noopener noreferrer nofollow\">https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions<br \/><\/a>[16] Microsoft Edge Add-ons, <a href=\"https:\/\/microsoftedge.microsoft.com\/addons\" rel=\"noopener noreferrer nofollow\">https:\/\/microsoftedge.microsoft.com\/addons<br \/><\/a>[17] Microsoft Edge Extensions, <a href=\"https:\/\/learn.microsoft.com\/en-us\/microsoft-edge\/extensions-chromium\/\" rel=\"noopener noreferrer nofollow\">https:\/\/learn.microsoft.com\/en-us\/microsoft-edge\/extensions-chromium\/<br \/><\/a>[18] GitHub Releases, <a href=\"https:\/\/docs.github.com\/en\/repositories\/releasing-projects-on-github\" rel=\"noopener noreferrer nofollow\">https:\/\/docs.github.com\/en\/repositories\/releasing-projects-on-github<\/a><\/p>\n<h3>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0438 \u0432\u044b\u0432\u043e\u0434\u044b<\/h3>\n<h4>\u0427\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c<\/h4>\n<p>\u0417\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0434\u0432\u0435 \u043d\u0435\u0434\u0435\u043b\u0438 \u044f \u0441\u043c\u043e\u0433 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0440\u0435\u0448\u0430\u0435\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u2014 \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u043a\u0443\u0447\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u0432\u043a\u043b\u0430\u0434\u043e\u043a \u0438 \u0437\u0430\u043a\u043b\u0430\u0434\u043e\u043a. \u042f \u0434\u043e\u0432\u043e\u043b\u0435\u043d \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c: \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043a\u0430\u043a \u0437\u0430\u0434\u0443\u043c\u0430\u043d\u043e, \u044f \u0438\u043c \u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0441\u044c \u0441\u0430\u043c \u0438 \u043e\u043d\u043e \u0443\u0436\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0432 Chrome Web Store [1] \u0438 Firefox Add-ons [2]. \u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0432\u044b\u043b\u043e\u0436\u0438\u0442\u044c \u0435\u0433\u043e \u0432 Microsoft Edge Add-ons \u043f\u043e\u043a\u0430 \u0437\u0430\u0441\u0442\u043e\u043f\u043e\u0440\u0438\u043b\u0430\u0441\u044c \u0438\u0437-\u0437\u0430 \u043c\u0443\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0432\u0435\u0440\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u043d\u043e \u0441\u0430\u043c \u0444\u0430\u043a\u0442, \u0447\u0442\u043e \u044f \u0434\u043e\u0448\u0451\u043b \u0434\u043e \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438, \u0443\u0436\u0435 \u0440\u0430\u0434\u0443\u0435\u0442.<\/p>\n<p><strong>\u0427\u0442\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u0443\u0434\u0430\u043b\u043e\u0441\u044c<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0421\u0434\u0435\u043b\u0430\u043b \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u0438 \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e WebExtensions API [11].<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043b \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 Telegram Login Widget [10], \u0445\u043e\u0442\u044f \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u043e\u0432\u043e\u0437\u0438\u0442\u044c\u0441\u044f \u0441 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u043e\u043c \u0435\u0451 \u0432 API, \u0447\u0442\u043e\u0431\u044b \u0443\u0433\u043e\u0434\u0438\u0442\u044c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c Chrome.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043b \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 Telegram Payments API [4], \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u043b\u0438 \u043f\u043e\u043a\u0443\u043f\u0430\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 \u043d\u0430 \u043f\u0440\u0435\u043c\u0438\u0443\u043c-\u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u043b \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 Docker, Caddy \u0438 Cloudflare \u2014 \u0432\u0441\u0451 \u043b\u0435\u0442\u0430\u0435\u0442, HTTPS \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0421\u043e\u0432\u0435\u0442\u044b \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0445\u043e\u0447\u0435\u0442 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c<\/h4>\n<p>\u041f\u0440\u043e\u0439\u0434\u044f \u0432\u0435\u0441\u044c \u044d\u0442\u043e\u0442 \u043f\u0443\u0442\u044c, \u044f \u043f\u043e\u043d\u044f\u043b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0449\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u0434\u0440\u0443\u0433\u0438\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c:<\/p>\n<ul>\n<li>\n<p>\u0411\u0435\u0440\u0438\u0442\u0435\u0441\u044c \u0437\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b. \u042d\u0442\u043e\u0442 \u0440\u043e\u0434\u0438\u043b\u0441\u044f \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438\u0434\u0435\u0438, \u0438 \u0437\u0430 \u0434\u0432\u0435 \u043d\u0435\u0434\u0435\u043b\u0438 \u044f \u0434\u043e\u0432\u0451\u043b \u0435\u0433\u043e \u0434\u043e \u0440\u0430\u0431\u043e\u0447\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u041d\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u0433\u0440\u0430\u043d\u0434\u0438\u043e\u0437\u043d\u043e\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0427\u0438\u0442\u0430\u0439\u0442\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0437\u0430\u0440\u0430\u043d\u0435\u0435. WebExtensions API [11] \u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043c\u0430\u0433\u0430\u0437\u0438\u043d\u043e\u0432 (\u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e Mozilla [19]) \u0441\u043f\u0430\u0441\u0443\u0442 \u043e\u0442 \u0433\u043e\u043b\u043e\u0432\u043d\u043e\u0439 \u0431\u043e\u043b\u0438. \u042f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0443\u0442\u044c \u043d\u0435 \u043f\u043e\u043f\u0430\u043b \u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432 Chrome.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0439\u0442\u0435 HTTPS \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430. Caddy [14] \u0441\u0438\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0442 \u0436\u0438\u0437\u043d\u044c, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u0431\u043e\u0439\u0442\u0435\u0441\u044c \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441 \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0435\u0439. Telegram Payments API [4] \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0438 \u0431\u044b\u0441\u0442\u0440\u043e, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0437\u0430\u043c\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u043f\u043b\u0430\u0442\u0451\u0436\u043d\u044b\u043c\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0411\u0443\u0434\u044c\u0442\u0435 \u0433\u043e\u0442\u043e\u0432\u044b \u043a \u0441\u044e\u0440\u043f\u0440\u0438\u0437\u0430\u043c. \u0412\u0435\u0440\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0432 Microsoft Edge Add-ons \u2014 \u044d\u0442\u043e \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043a\u0432\u0435\u0441\u0442 \u0431\u0435\u0437 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043e\u043a, \u0442\u0430\u043a \u0447\u0442\u043e \u0437\u0430\u043f\u0430\u0441\u0438\u0442\u0435\u0441\u044c \u0442\u0435\u0440\u043f\u0435\u043d\u0438\u0435\u043c.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0427\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435<\/h4>\n<p>\u0425\u043e\u0447\u0435\u0442\u0441\u044f \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0431\u044b\u043b \u0435\u0449\u0451 \u0443\u0434\u043e\u0431\u043d\u0435\u0435, \u043c\u043e\u0436\u0435\u0442, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0446\u0432\u0435\u0442\u0430. \u0415\u0449\u0451 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u044e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 Microsoft Edge Add-ons \u2014 \u0432\u0434\u0440\u0443\u0433 \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c. \u041f\u043b\u044e\u0441, \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432, \u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e, \u043d\u043e \u044d\u0442\u043e \u043f\u043e\u043a\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0434\u0435\u044f. \u0412 \u043e\u0431\u0449\u0435\u043c, \u043f\u0440\u043e\u0435\u043a\u0442 \u0436\u0438\u0432\u0451\u0442, \u0438 \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0435\u0433\u043e \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c, \u043e\u043f\u0438\u0440\u0430\u044f\u0441\u044c \u043d\u0430 \u043e\u0442\u0437\u044b\u0432\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<p>[1] Chrome Web Store Developer Dashboard, <a href=\"https:\/\/chromewebstore.google.com\/\" rel=\"noopener noreferrer nofollow\">https:\/\/chromewebstore.google.com\/<\/a><a href=\"https:\/\/developer.chrome.com\/webstore%EF%BF%BC%5B2%5D\" rel=\"noopener noreferrer nofollow\"><br \/><\/a>[2] Firefox Add-ons, <a href=\"https:\/\/addons.mozilla.org\/\" rel=\"noopener noreferrer nofollow\">https:\/\/addons.mozilla.org\/<br \/><\/a>[4] Telegram Payments API, <a href=\"https:\/\/core.telegram.org\/bots\/payments\" rel=\"noopener noreferrer nofollow\">https:\/\/core.telegram.org\/bots\/payments<br \/><\/a>[10] Telegram Login Widget, <a href=\"https:\/\/core.telegram.org\/widgets\/login\" rel=\"noopener noreferrer nofollow\">https:\/\/core.telegram.org\/widgets\/login<br \/><\/a>[11] WebExtensions API, <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions\" rel=\"noopener noreferrer nofollow\">https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions<br \/><\/a>[14] Caddy, <a href=\"https:\/\/caddyserver.com\/\" rel=\"noopener noreferrer nofollow\">https:\/\/caddyserver.com\/<br \/><\/a>[19] Mozilla Add-on Policies, <a href=\"https:\/\/extensionworkshop.com\/documentation\/publish\/add-on-policies\/\" rel=\"noopener noreferrer nofollow\">https:\/\/extensionworkshop.com\/documentation\/publish\/add-on-policies\/<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/930732\/\"> https:\/\/habr.com\/ru\/articles\/930732\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043d\u0430\u0447\u0430\u043b\u0430\u0441\u044c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438\u0434\u0435\u0438: \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u0438\u043b\u044b \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u0437\u0430 \u0434\u0432\u0435 \u043d\u0435\u0434\u0435\u043b\u0438 \u043f\u0440\u043e\u0448\u0451\u043b \u043f\u0443\u0442\u044c \u043e\u0442 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430 \u0434\u043e \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 Chrome Web Store \u0438 Firefox Add-ons, \u043a\u0430\u043a\u0438\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0438 \u0441 \u043a\u0430\u043a\u0438\u043c\u0438 \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f. \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u043c\u043e\u0439 \u043e\u043f\u044b\u0442 \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u0438\u0442 \u0434\u0440\u0443\u0433\u0438\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u0438\u043b\u044b \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0430 <a href=\"https:\/\/github.com\/pulichkin\/findmylink\" rel=\"noopener noreferrer nofollow\">GitHub<\/a>.<\/p>\n<figure class=\"\"><\/figure>\n<hr\/>\n<h3>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0438 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435<\/h3>\n<figure class=\"full-width\"><\/figure>\n<h4>\u0418\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u0440\u044b\u043d\u043a\u0430<\/h4>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435, \u044f \u0438\u0437\u0443\u0447\u0438\u043b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 Chrome-\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439. \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e, \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c, \u043d\u043e \u044f \u043d\u0430\u0448\u0451\u043b \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u0431\u0438\u043d\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 Chrome Web Store [1]. \u041e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0438 \u043e\u043f\u043b\u0430\u0442\u0438\u0442\u044c \u0435\u0434\u0438\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0432\u0437\u043d\u043e\u0441 \u0432 \u0440\u0430\u0437\u043c\u0435\u0440\u0435 5 \u0434\u043e\u043b\u043b\u0430\u0440\u043e\u0432. \u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u0432\u0435\u0441\u0442\u043e\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u043e\u0431\u0440\u0430\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u043f\u043b\u0430\u0442\u044b, \u043d\u043e \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u0442\u043b\u043e\u0436\u0438\u0442\u044c \u0435\u0433\u043e \u0434\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u044f \u0438\u0437\u0443\u0447\u0438\u043b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e WebExtensions API [2], \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043b\u0435\u0436\u0438\u0442 \u0432 \u043e\u0441\u043d\u043e\u0432\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0434\u043b\u044f Chrome \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u043c\u043d\u0435 \u043f\u043e\u043d\u044f\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u043e\u043c \u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u043a API \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u0442\u0430\u043a\u0438\u043c \u043a\u0430\u043a <code>chrome.bookmarks<\/code> \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0430\u043c. \u0418\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u043b\u043e, \u0447\u0442\u043e \u0438\u0434\u0435\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u0430 \u0438 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<h4>\u041f\u0435\u0440\u0432\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f<\/h4>\n<p>\u0414\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0441\u0442\u0430\u0440\u0442\u0430 \u044f \u0432\u044b\u0431\u0440\u0430\u043b \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a Quasar [3], \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0443\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. Quasar \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u0438\u0441\u0442\u0438\u0447\u043d\u044b\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c: \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0432\u044b\u0432\u043e\u0434 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043f\u043e \u043c\u0435\u0440\u0435 \u0432\u0432\u043e\u0434\u0430. \u041f\u0440\u043e\u0442\u043e\u0442\u0438\u043f \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u043f\u0440\u043e\u0441\u0442\u043e, \u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e, \u0447\u0442\u043e \u0434\u0430\u043b\u043e \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0432 \u0436\u0438\u0437\u043d\u0435\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0438\u0434\u0435\u0438. \u041e\u0434\u043d\u0430\u043a\u043e \u044f \u0437\u0430\u043c\u0435\u0442\u0438\u043b, \u0447\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0438\u0437\u044e\u043c\u0438\u043d\u043a\u0438 \u2014 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0434\u0435\u043b\u0430\u043b \u0431\u044b \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u043c.<\/p>\n<h4>\u0414\u0438\u0437\u0430\u0439\u043d \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430<\/h4>\n<figure class=\"\"><\/figure>\n<p>\u0427\u0442\u043e\u0431\u044b \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043e\u043f\u044b\u0442, \u044f \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043b \u043a \u043f\u0440\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0434\u0438\u0437\u0430\u0439\u043d\u0430. \u0418\u043c\u0435\u044f \u043e\u043f\u044b\u0442 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043a\u0443\u0440\u0441\u043e\u0432 \u043f\u043e UI\/UX-\u0434\u0438\u0437\u0430\u0439\u043d\u0443, \u044f \u0441\u043e\u0437\u0434\u0430\u043b \u043c\u0430\u043a\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u0431\u044b \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0438 \u044d\u0441\u0442\u0435\u0442\u0438\u0447\u043d\u044b\u043c. \u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u043f\u043e\u0438\u0441\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f. \u0413\u043b\u044f\u0434\u044f \u043d\u0430 \u0441\u0432\u043e\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0441 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u0432\u043a\u043b\u0430\u0434\u043e\u043a, \u044f \u0440\u0435\u0448\u0438\u043b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0433\u043b\u0430 \u0431\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u043f\u043e \u0434\u0435\u0441\u044f\u0442\u043a\u0430\u043c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446. \u0423 \u043c\u0435\u043d\u044f, \u043a\u0430\u043a \u0438 \u0443 \u043c\u043d\u043e\u0433\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0447\u0430\u0441\u0442\u043e \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043e\u043a: \u0443\u0432\u0438\u0434\u0435\u043b \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e, \u043e\u0442\u043a\u0440\u044b\u043b \u0435\u0451, \u043d\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043d\u0435\u0442, \u0438 \u0432\u043a\u043b\u0430\u0434\u043a\u0430 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u043d\u0430 \u043d\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u0441\u0440\u043e\u043a. \u041d\u0430\u0439\u0442\u0438 \u0447\u0442\u043e-\u0442\u043e \u0441\u0440\u0435\u0434\u0438 \u043d\u0438\u0445 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u043e, \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0438 \u0438\u043b\u0438 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f \u0432\u043a\u043b\u0430\u0434\u043e\u043a \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u042d\u0442\u0430 \u0438\u0434\u0435\u044f \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u0440\u0435\u0448\u0430\u0435\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043f\u043e\u0432\u0441\u0435\u0434\u043d\u0435\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<p>\u041d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0432\u0438\u0434\u0435\u043d\u0438\u044f \u044f \u043e\u0431\u043d\u043e\u0432\u0438\u043b \u0434\u0438\u0437\u0430\u0439\u043d, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c, \u0438 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043b \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u0438\u0437\u0443\u0447\u0438\u0442\u044c API \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c\u0438 (<code>chrome.tabs<\/code>) [2], \u0447\u0442\u043e \u0441\u0442\u0430\u043b\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435.<\/p>\n<p>[1] Chrome Web Store Developer Dashboard, <a href=\"https:\/\/developer.chrome.com\/webstore\" rel=\"noopener noreferrer nofollow\">https:\/\/developer.chrome.com\/webstore<br \/><\/a>[2] WebExtensions API, <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions\" rel=\"noopener noreferrer nofollow\">https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions<br \/><\/a>[3] Quasar Framework, <a href=\"https:\/\/quasar.dev\/\" rel=\"noopener noreferrer nofollow\">https:\/\/quasar.dev\/<\/a><\/p>\n<h3>\u041c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u044f<\/h3>\n<figure class=\"full-width\"><\/figure>\n<p>\u0414\u0430\u0432\u043d\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043d\u043e\u0441\u0438\u043b \u0431\u044b \u043f\u043e\u043b\u044c\u0437\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0438, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0434\u043e\u0445\u043e\u0434, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u0438\u043c\u0432\u043e\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u043c. \u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043c\u043e\u0433 \u0431\u044b \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u0440\u0443\u0433\u0438\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u043e\u0442\u044f\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0434\u0443\u043a\u0442, \u043d\u043e \u043d\u0435 \u0437\u043d\u0430\u044e\u0442, \u0441 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c. \u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0434 <em>FindMyLink<\/em> \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438: \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u043c, \u0430 \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u043f\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u0431\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0440\u0435\u043c\u0438\u0443\u043c-\u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0432 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<p>\u0412\u043e\u043f\u0440\u043e\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c. \u0421\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0431\u043e\u0442\u0430 \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c, \u043a\u0442\u043e \u043e\u043f\u043b\u0430\u0442\u0438\u043b \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443, \u0430 \u043a\u0442\u043e \u043d\u0435\u0442. \u041f\u043e\u0441\u043b\u0435 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043f\u043b\u0430\u0442\u0451\u0436\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a Stripe, \u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u043d\u0430 Telegram Payments API [4] \u0438\u0437-\u0437\u0430 \u0435\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0438 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438 \u0441\u0440\u0435\u0434\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. Telegram Payments API \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043d\u0432\u043e\u0439\u0441\u044b \u0447\u0435\u0440\u0435\u0437 \u0431\u043e\u0442\u0430, \u0447\u0442\u043e \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u043b\u043e \u0434\u043b\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u043f\u043b\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 Telegram, \u0430 \u0431\u043e\u0442 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442 \u043f\u043b\u0430\u0442\u0451\u0436 \u0438 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u0440\u0435\u043c\u0438\u0443\u043c-\u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c. \u0414\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430\u043c\u0438 \u0431\u044b\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c, \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0430\u044f Telegram-\u0431\u043e\u0442\u0430 \u0438 API, \u0447\u0442\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u0430\u0445.<\/p>\n<p>[4] Telegram Payments API, <a href=\"https:\/\/core.telegram.org\/bots\/payments\" rel=\"noopener noreferrer nofollow\">https:\/\/core.telegram.org\/bots\/payments<\/a><\/p>\n<h3>\u0411\u044d\u043a\u0435\u043d\u0434: Telegram-\u0431\u043e\u0442 \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0435\u0436\u0435\u0439<\/h3>\n<figure class=\"full-width\"><\/figure>\n<h4>\u0412\u044b\u0431\u043e\u0440 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438<\/h4>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 Telegram Payments API [4] \u044f \u0440\u0435\u0448\u0438\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Telegram-\u0431\u043e\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0438\u043d\u0432\u043e\u0439\u0441\u044b \u0438 \u043f\u043b\u0430\u0442\u0435\u0436\u0438. \u041f\u043e\u0441\u043b\u0435 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043f\u043b\u0430\u0442\u0451\u0436\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a Stripe, \u044f \u0432\u044b\u0431\u0440\u0430\u043b Telegram \u0438\u0437-\u0437\u0430 \u0435\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435. \u0414\u043b\u044f \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u043d\u0430 SQLite \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <code>aiosqlite<\/code> \u0438 <code>SQLAlchemy[asyncio]<\/code> [5], \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439, \u0438 SQLite \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u0445 \u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430\u0445. \u0414\u043b\u044f \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f KeyDB [6], \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441 Redis, \u043d\u043e \u0431\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u0438 \u043b\u0451\u0433\u043a\u0438\u0439 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435. \u0411\u043e\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <code>python-telegram-bot<\/code> [7], \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 Telegram API. \u0414\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u043b\u0438\u0441\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <code>msgspec<\/code> [8] \u0438 <code>config-lib-msgspec<\/code> [9], \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u044b\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u043a\u043e\u043b\u043b\u0435\u0433\u043e\u0439 \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u0430 \u0443\u0434\u043e\u0431\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u0437 YAML, \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438.<\/p>\n<p><strong>\u0422\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u0442\u0435\u043a \u0431\u043e\u0442\u0430:<\/strong><\/p>\n<ul>\n<li>\n<p><strong>Framework<\/strong>: <code>python-telegram-bot<\/code> (\u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439) \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 Telegram API.<\/p>\n<\/li>\n<li>\n<p><strong>\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>: SQLite + <code>aiosqlite<\/code> + <code>SQLAlchemy[asyncio]<\/code> \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u044d\u0448<\/strong>: KeyDB (Redis-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439) \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0430\u043d\u043d\u044b\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f<\/strong>: <code>msgspec<\/code> + <code>config-lib-msgspec<\/code> \u0434\u043b\u044f \u0433\u0438\u0431\u043a\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043b\u0430\u0442\u0435\u0436\u0438<\/strong>: Telegram Payments API \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043e\u043a.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0441 config-lib-msgspec<\/h4>\n<pre><code class=\"python\"># bot\/src\/configs\/config.py from typing import List from config_lib.base import BaseConfig from msgspec import Struct, field  class TelegramConfig(Struct):     bot_token: str | None = None     payment_provider_token: str | None = None     admin_ids: List[int] = 0,  class DatabaseConfig(Struct):     path: str | None = None     default_lang: str | None = None     default_trial_used: bool = False     default_auto_renewal: bool = True  class BotConfig(BaseConfig):     telegram: TelegramConfig = field(default_factory=TelegramConfig)     database: DatabaseConfig = field(default_factory=DatabaseConfig)     redis: RedisConfig = field(default_factory=RedisConfig)     rate_limit: RateLimitConfig = field(default_factory=RateLimitConfig)     subscription: SubscriptionConfig = field(default_factory=SubscriptionConfig)     logging: LoggingConfig = field(default_factory=LoggingConfig)  # \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433 \u0438\u0437 YAML\/ENV\/CLI config = BotConfig.load() <\/code><\/pre>\n<h4>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0431\u043e\u0442\u0430<\/h4>\n<pre><code class=\"python\"># bot\/src\/bot.py from telegram import Update from telegram.ext import Application, CommandHandler, MessageHandler, filters from configs.config import config  async def start_command(update: Update, context):     \"\"\"\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a\u043e\u043c\u0430\u043d\u0434\u044b \/start\"\"\"     user_id = update.effective_user.id     await context.bot.send_message(         chat_id=update.effective_chat.id,         text=f\"\u041f\u0440\u0438\u0432\u0435\u0442! \u042f \u0431\u043e\u0442 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u043e\u0439 FindMyLink.\\n\"              f\"\u0412\u0430\u0448 ID: {user_id}\"     )  async def subscribe_command(update: Update, context):     \"\"\"\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a\u043e\u043c\u0430\u043d\u0434\u044b \/subscribe\"\"\"     # \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0438\u043d\u0432\u043e\u0439\u0441 \u0434\u043b\u044f \u043e\u043f\u043b\u0430\u0442\u044b     invoice = await context.bot.create_invoice(         title=\"\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 FindMyLink\",         description=\"\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u043e\u0438\u0441\u043a\u0443 \u043f\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u043d\u0430 30 \u0434\u043d\u0435\u0439\",         payload=\"subscription_30_days\",         provider_token=config.telegram.payment_provider_token,         currency=\"RUB\",         prices=[{\"label\": \"\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430\", \"amount\": 29900}]  # 299 \u0440\u0443\u0431\u043b\u0435\u0439     )          await context.bot.send_invoice(         chat_id=update.effective_chat.id,         **invoice     )  def main():     application = Application.builder().token(config.telegram.bot_token).build()          application.add_handler(CommandHandler(\"start\", start_command))     application.add_handler(CommandHandler(\"subscribe\", subscribe_command))          application.run_polling() <\/code><\/pre>\n<p>[4] Telegram Payments API, <a href=\"https:\/\/core.telegram.org\/bots\/payments\" rel=\"noopener noreferrer nofollow\">https:\/\/core.telegram.org\/bots\/payments<br \/><\/a>[5] SQLAlchemy, <a href=\"https:\/\/www.sqlalchemy.org\/\" rel=\"noopener noreferrer nofollow\">https:\/\/www.sqlalchemy.org\/<br \/><\/a>[6] KeyDB, <a href=\"https:\/\/keydb.dev\/\" rel=\"noopener noreferrer nofollow\">https:\/\/keydb.dev\/<br \/><\/a>[7] python-telegram-bot, <a href=\"https:\/\/python-telegram-bot.org\/\" rel=\"noopener noreferrer nofollow\">https:\/\/python-telegram-bot.org\/<br \/><\/a>[8] msgspec, <a href=\"https:\/\/jcristharif.com\/msgspec\" rel=\"noopener noreferrer nofollow\">https:\/\/jcristharif.com\/msgspec\/<br \/><\/a>[9] config-lib-msgspec, <a href=\"https:\/\/github.com\/rastaclaus\/config-lib-msgspec\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/rastaclaus\/config-lib-msgspec<\/a><\/p>\n<h3>\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 Telegram<\/h3>\n<figure class=\"full-width\"><\/figure>\n<h4>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u043c<\/h4>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u044f \u0440\u0435\u0448\u0438\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Telegram Login Widget [10], \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 Telegram. \u041f\u043e\u0441\u043b\u0435 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u044f \u0432\u044b\u044f\u0441\u043d\u0438\u043b, \u0447\u0442\u043e \u0432\u0438\u0434\u0436\u0435\u0442 \u043f\u0440\u043e\u0441\u0442 \u0432 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0435 Telegram-\u0431\u043e\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443 \u043c\u0435\u043d\u044f \u0443\u0436\u0435 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0434\u043b\u044f \u043c\u043e\u043d\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043b \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432\u0438\u0434\u0436\u0435\u0442 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u043f\u0440\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u043f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u043f\u043e\u043f\u0430\u043f\u0430 \u0441 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u043c \u043e\u043d \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0441\u044f \u043f\u0443\u0441\u0442\u044b\u043c. \u041f\u043e\u0441\u043b\u0435 \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u044f \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b, \u0447\u0442\u043e Telegram Login Widget \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u0441 HTTPS [10]. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0443 \u043c\u0435\u043d\u044f \u0435\u0449\u0451 \u043d\u0435 \u0431\u044b\u043b\u043e \u0434\u043e\u043c\u0435\u043d\u0430 \u0438 VPS, \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c HTTPS \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<h4>\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430<\/h4>\n<p>\u0427\u0442\u043e\u0431\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 Telegram Login Widget \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435, \u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b HTTPS-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0448\u0430\u0433\u0438:<\/p>\n<ol>\n<li>\n<p><strong>\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u043c\u0435\u043d\u0430 \u0432 \/etc\/hosts<\/strong><br \/>\u041e\u0442\u043a\u0440\u044b\u043b \u0444\u0430\u0439\u043b <code>\/etc\/hosts<\/code> \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 \u0441\u0443\u043f\u0435\u0440\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:  <\/p>\n<pre><code class=\"bash\">sudo vim \/etc\/hosts <\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043b \u0441\u0442\u0440\u043e\u043a\u0443, \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u044e\u0449\u0443\u044e <a href=\"http:\/\/testdomain.com\" rel=\"noopener noreferrer nofollow\"><code>testdomain.com<\/code><\/a> \u0441<\/p>\n<\/li>\n<\/ol>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-468456","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/468456","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=468456"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/468456\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=468456"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=468456"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=468456"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}