{"id":338023,"date":"2022-09-06T21:00:21","date_gmt":"2022-09-06T21:00:21","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=338023"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=338023","title":{"rendered":"<span>\u041c\u043e\u0439 \u0432\u043a\u043b\u0430\u0434 \u0432 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u043e\u0431\u043e\u0440\u043e\u0442<\/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-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0418\u0434\u0435\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0435\u0442-\u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0440\u043e\u0434\u0438\u043b\u0430\u0441\u044c \u0438\u0437-\u0437\u0430 \u043e\u0442\u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u044b\u043b \u043d\u0435\u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c. \u042f \u043c\u043e\u0433 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0435 \u0442\u0443 \u0434\u0430\u0442\u0443 \u0432 \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u0438, \u043c\u043e\u0433 \u0437\u0430\u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u044f \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u043f\u0438\u0441\u044c\u043c\u0430 \u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u043c\u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043b\u0435\u043d\u044c \u0432\u043e\u0437\u0438\u0442\u044c\u0441\u044f \u0441\u043e \u0432\u0441\u0435\u0439 \u044d\u0442\u043e\u0439 \u0431\u044e\u0440\u043e\u043a\u0440\u0430\u0442\u0438\u0435\u0439. \u0418 \u044f \u0440\u0435\u0448\u0438\u043b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u0439 \u043d\u0430 \u043e\u0442\u0433\u0443\u043b.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p>\u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u043d\u0430\u0441, \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0430\u044f-\u0442\u043e \u0437\u0430\u0434\u0443\u043c\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0430\u043c \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0432\u043e\u043f\u043b\u043e\u0442\u0438\u0442\u044c. \u041c\u043e\u0435\u0439 \u0431\u044b\u043b \u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c-\u0431\u043e\u0442. \u0415\u0449\u0435 \u043f\u0430\u0440\u0443 \u043b\u0435\u0442 \u043f\u044f\u0442\u044c \u043d\u0430\u0437\u0430\u0434, \u043a\u043e\u0433\u0434\u0430 \u044f \u0448\u0435\u0440\u0441\u0442\u0438\u043b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0442\u0435\u043b\u0435\u0433\u0438, \u044f \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b \u043f\u0440\u043e \u0431\u043e\u0442\u043e\u0432 \u0438 \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u0435\u0433\u043e \u043d\u0430\u0434\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u0418 \u0441\u0435\u043b \u0434\u0443\u043c\u0430\u0442\u044c.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/uj\/_z\/ht\/uj_zhtxmkjbxtuotnausjaqti9k.png\" data-src=\"https:\/\/habrastorage.org\/webt\/uj\/_z\/ht\/uj_zhtxmkjbxtuotnausjaqti9k.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0422\u043e\u0433\u0434\u0430 \u044f \u0442\u0430\u043a \u043d\u0438\u0447\u0435\u0433\u043e \u0438 \u043d\u0435 \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043b. \u041d\u043e \u0432\u043e\u0442, \u043d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e, \u0441\u0432\u0435\u0440\u0448\u0438\u043b\u043e\u0441\u044c.<\/p>\n<p>  <\/p>\n<h2 id=\"celi\">\u0426\u0435\u043b\u0438<\/h2>\n<p>  <\/p>\n<p>\u0421 \u0438\u0434\u0435\u0435\u0439 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438\u0441\u044c, \u043d\u043e \u0438\u0437 \u043d\u0435\u0435 \u043d\u0430\u0434\u043e \u0432\u044b\u0436\u0430\u0442\u044c \u0432\u0441\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0435. \u042f \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u043a\u043d\u0438\u0433:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u041f\u0430\u0442\u0442\u0435\u0440\u043d\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u0430\u043d\u0434\u044b \u0447\u0435\u0442\u044b\u0440\u0435\u0445<\/li>\n<li>\u0427\u0438\u0441\u0442\u044b\u0439 Agile \u041c\u0430\u0440\u0442\u0438\u043d\u0430<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u041d\u0435\u043f\u043b\u043e\u0445\u043e \u0431\u044b \u044d\u0442\u0438 \u0437\u043d\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435.<\/p>\n<p>  <\/p>\n<p>\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u044f \u0445\u043e\u0442\u0435\u043b \u043f\u043e\u0434\u0442\u044f\u043d\u0443\u0442\u044c C#, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0441 \u0442\u0435\u0445 \u043f\u043e\u0440, \u043a\u0430\u043a \u044f \u0443\u0448\u0435\u043b \u043d\u0430 \u0444\u0440\u043e\u043d\u0442, \u043e\u043d \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u043b\u0441\u044f \u0434\u0430\u043b\u0435\u043a\u043e \u0432\u043f\u0435\u0440\u0435\u0434.<\/p>\n<p>  <\/p>\n<p>\u0410 \u044f \u0436\u0435 \u043f\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u0438\u043d\u0436\u0435\u043d\u0435\u0440 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442, \u0430 \u043d\u0435 \u0438\u043d\u0436\u0435\u043d\u0435\u0440 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442 \u043d\u0430 JS. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u044f\u0437\u044b\u043a\u043e\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 C#.<\/p>\n<p>  <\/p>\n<h5 id=\"poyasnyu-pochemu-takoe-dolgoe-vstuplenie\">\u041f\u043e\u044f\u0441\u043d\u044e \u043f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a\u043e\u0435 \u0434\u043e\u043b\u0433\u043e\u0435 \u0432\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h5>\n<p>  <\/p>\n<blockquote><p>\u041f\u0435\u0442-\u043f\u0440\u043e\u0435\u043a\u0442 \u044d\u0442\u043e \u0441\u043b\u043e\u0436\u043d\u043e \u0438 \u0432\u0430\u0436\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a, \u044d\u0442\u043e \u0438\u043d\u0432\u0435\u0441\u0442\u0438\u0446\u0438\u044f \u0441\u0432\u043e\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 \u0441\u0432\u043e\u044e \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c \u043a\u0430\u043a \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u0430. \u042d\u0442\u043e \u0442\u043e \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0443 \u0438 \u0431\u0443\u0434\u0443\u0449\u0435\u043c\u0443 \u0440\u0430\u0431\u043e\u0442\u043e\u0434\u0430\u0442\u0435\u043b\u044e \u043f\u0440\u0438 \u043f\u0440\u0438\u0435\u043c\u0435 \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0443. \u042d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043d\u043e\u0432\u044b\u0445 \u0437\u043d\u0430\u043d\u0438\u0439 \u0442\u0430\u043a \u043a\u0430\u043a \u0445\u043e\u0447\u0435\u0448\u044c \u0442\u044b, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0442\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0448\u044c \u043e\u0434\u0438\u043d. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0442\u0430\u043a \u043e\u0441\u043d\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u043e\u0448\u0435\u043b \u043a \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0446\u0435\u043b\u0435\u0439.<\/p><\/blockquote>\n<p>  <\/p>\n<h5 id=\"predvizhu-vash-vopros\">\u041f\u0440\u0435\u0434\u0432\u0438\u0436\u0443 \u0432\u0430\u0448 \u0432\u043e\u043f\u0440\u043e\u0441<\/h5>\n<p>  <\/p>\n<blockquote><p>\u0414\u0430, \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u043e agile \u0432 \u043e\u0434\u043d\u043e\u0433\u043e \u043d\u0435 \u0442\u043e \u0447\u0442\u043e\u0431\u044b \u0441\u0438\u043b\u044c\u043d\u043e \u0432\u0435\u0441\u0435\u043b\u043e. \u041d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442 \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u0430\u043c\u0438, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c CI\/CD \u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0435 \u043f\u043e\u0440\u0446\u0438\u0438 \u0437\u0430\u0434\u0430\u0447 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u044b\u043b\u043e \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432 develop.<\/p><\/blockquote>\n<p>  <\/p>\n<h2 id=\"biznes-postanovka\">\u0411\u0438\u0437\u043d\u0435\u0441-\u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430<\/h2>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e, \u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0447\u0442\u043e\u0431\u044b \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0431\u043e\u0442\u0443 \u0434\u0430\u0442\u0443 \u043e\u0442\u0433\u0443\u043b\u0430, \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u0438 \u0431\u0443\u0434\u0443 \u043b\u0438 \u044f \u0435\u0433\u043e \u043e\u0442\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c.<\/p>\n<p>  <\/p>\n<p>\u0417\u0432\u0443\u0447\u0438\u0442 \u043f\u0440\u043e\u0441\u0442\u043e, \u043d\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0440\u0435\u0448\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0424\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 docx-\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 (\u0432\u043e\u043e\u0431\u0449\u0435, \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u043c email, \u0443 \u043d\u0430\u0441 \u0432 \u044d\u0442\u043e\u043c \u043f\u043b\u0430\u043d\u0435 \u043d\u0435 \u0436\u0435\u0441\u0442\u044f\u0442, \u043d\u043e \u0432\u0435\u0434\u044c \u0442\u0430\u043a \u0441\u0442\u0430\u043d\u0435\u0442 \u043c\u0435\u043d\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e)<\/li>\n<li>\u0424\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 email-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f<\/li>\n<li>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 c \u043f\u043e\u043c\u043e\u0449\u044c\u044e SMTP \u044d\u0442\u043e\u0433\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u044f\u043d\u0434\u0435\u043a\u0441 \u0441 OAuth-\u0442\u043e\u043a\u0435\u043d\u043e\u043c.<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0421\u043f\u043e\u0439\u043b\u0435\u0440: \u044d\u0442\u043e \u0432\u0441\u0435 \u0440\u0435\u0448\u0430\u0435\u043c\u043e:)<\/p>\n<p>  <\/p>\n<h2 id=\"realizaciya\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h2>\n<p>  <\/p>\n<h3 id=\"formirovanie-dokumentov\">\u0424\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432<\/h3>\n<p>  <\/p>\n<p>\u042f \u0440\u0435\u0448\u0438\u043b \u043d\u0435 \u0445\u0438\u0442\u0440\u0438\u0442\u044c, \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d\u044b. \u041c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043d\u043e \u0437\u0430\u0447\u0435\u043c?<br \/>  \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043f\u0440\u043e\u0444\u0438\u0442\u0430 \u043d\u0430\u043c \u044d\u0442\u043e \u043d\u0435 \u0434\u0430\u0441\u0442 \u043d\u0438 \u0432 \u043f\u043b\u0430\u043d\u0435 \u044e\u0437\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u043d\u0438 \u0432 \u043f\u043b\u0430\u043d\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430.<br \/>  \u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u043d\u044f\u0442\u044c \u0434\u0430\u0436\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0442\u043e\u0433\u043e, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u043e.<\/p>\n<p>  <\/p>\n<h4 id=\"docx\">Docx<\/h4>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/_p\/sk\/9f\/_psk9fpiu2bgt37-aue5uc8_ywk.png\" alt=\"\u0428\u0430\u0431\u043b\u043e\u043d \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\" data-src=\"https:\/\/habrastorage.org\/webt\/_p\/sk\/9f\/_psk9fpiu2bgt37-aue5uc8_ywk.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0448\u0430\u0431\u043b\u043e\u043d \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430. \u042f \u0441\u044e\u0434\u0430 \u043f\u0440\u0438\u0442\u0430\u0449\u0438\u043b \u0430\u043d\u0433\u0443\u043b\u044f\u0440\u0449\u0438\u043d\u0443 \u0432 \u0432\u0438\u0434\u0435 &#171;\u0443\u0441\u0430\u0442\u044b\u0445&#187; \u043f\u043b\u0435\u0439\u0441\u0445\u043e\u043b\u0434\u0435\u0440\u043e\u0432. \u0412 \u043e\u0431\u0449\u0435\u043c, \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0438\u0437\u044b\u0441\u043a\u043e\u0432.<\/p>\n<p>  <\/p>\n<blockquote><p>\u041d\u0435\u0442, &#171;\u0418\u043d\u0444\u0438\u043d\u043d\u0438\u0442\u0438&#187; \u2014 \u043d\u0435 \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0430, \u0443 \u043d\u0430\u0441 \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438 \u0434\u0432\u0435 &#171;\u043d&#187;.<\/p><\/blockquote>\n<p>\u0414\u043b\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 &#171;DocX&#187;. \u041e\u043d\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u043c.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">    public class TimeOffDocumentAdapter: IDisposable     {         protected DocX document;          public TimeOffDocumentAdapter(DocX document)         {             this.document = document;         }          public void SetJobTitle(string value)         {             this.document.Paragraphs[2].ReplaceText(Placeholders.JobTitle, value);         }          public void SetPersonName(string value)         {             this.document.Paragraphs[3].ReplaceText(Placeholders.PersonName, value);         }          public void SetTimeOffPeriod(string value)         {             value = new InsertStringFormatter().Format(value);             this.document.Paragraphs[6].ReplaceText(Placeholders.TimeOffPeriod, value);         }          public void SetReason(string value)         {             if (value == null)             {                 this.document.Paragraphs[7].RemoveText(0);                 this.document.Paragraphs[7].Hide();             }             else             {                 value = new InsertStringFormatter().Format(value);                 this.document.Paragraphs[7].ReplaceText(Placeholders.Reason, value);             }         }          public void SetWorkingOff(string value)         {             if (value == null)             {                 this.document.Paragraphs[8].RemoveText(0);                 this.document.Paragraphs[8].Hide();             }             else             {                 value = new InsertStringFormatter().Format(value, firstLetter: FirstLetter.Upper);                 this.document.Paragraphs[8].ReplaceText(Placeholders.WorkingOff, value);             }         }          public void SetSendingDay(string value)         {             this.document.Paragraphs[10].ReplaceText(Placeholders.SendingDay, value);         }          public void SaveAs(string name)         {             this.document.SaveAs(name);         }          public void Dispose()         {             document?.Dispose();         }     } <\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0441\u0442\u0440\u0430\u0448\u043d\u044b\u0445 \u0445\u0438\u0442\u0440\u043e\u0441\u0442\u0435\u0439 \u043d\u0435\u0442 \u2014 \u043f\u0440\u043e\u0441\u0442\u043e \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u0433\u0440\u0430\u0444\u0430\u0445 \u043f\u043e\u0434\u043c\u0435\u043d\u044f\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u043b\u0435\u0439\u0441\u0445\u043e\u043b\u0434\u0435\u0440\u044b \u043d\u0430 \u043d\u0443\u0436\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u0418\u043b\u0438 \u0436\u0435, \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>null<\/code>, \u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043f\u0430\u0440\u0430\u0433\u0440\u0430\u0444.<\/p>\n<p>  <\/p>\n<h4 id=\"email\">Email<\/h4>\n<p>  <\/p>\n<p>\u0410 \u044d\u0442\u043e \u2014 \u0448\u0430\u0431\u043b\u043e\u043d \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0442\u043e\u043b\u044c\u043a\u043e HTML \u0444\u0430\u0439\u043b\u0438\u043a \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0435.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/3h\/nr\/7b\/3hnr7b2hoquwpjraeehjfbdbub8.png\" alt=\"\u0428\u0430\u0431\u043b\u043e\u043d \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\" data-src=\"https:\/\/habrastorage.org\/webt\/3h\/nr\/7b\/3hnr7b2hoquwpjraeehjfbdbub8.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430 \u0436\u0435, \u043d\u043e \u0432\u043c\u0435\u0441\u0442\u043e &#171;Docx&#187; \u2014 &#171;HTML Agility Pack&#187;, \u0430 \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0430\u0440\u0430\u0433\u0440\u0430\u0444\u043e\u0432 \u2014 HTML \u043d\u043e\u0434\u044b.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">    public class TimeOffMessageAdapter     {         protected HtmlDocument Doc;          public TimeOffMessageAdapter(HtmlDocument doc)         {             this.Doc = doc;         }          public void SetJobTitle(string value)         {             var jobTitle = Doc.GetElementbyId(\"signature_job-title\");              var signature = jobTitle.ParentNode;              var replaced = jobTitle.OuterHtml.Replace(Placeholders.JobTitle, value);              var newNode = HtmlNode.CreateNode(replaced);              signature.ReplaceChild(newNode, jobTitle);         }          public void SetPersonName(string value)         {              var name = Doc.GetElementbyId(\"signature_name\");              var signature = name.ParentNode;              var replaced = name.OuterHtml.Replace(Placeholders.PersonName, value);              var newNode = HtmlNode.CreateNode(replaced);              signature.ReplaceChild(newNode, name);         }          public void SetTimeOffPeriod(string value)         {             var period = Doc.GetElementbyId(\"time-off_period\");              var body = period.ParentNode;              value = new InsertStringFormatter().Format(value);              var replaced = period.OuterHtml.Replace(Placeholders.TimeOffPeriod, value);              var newNode = HtmlNode.CreateNode(replaced);              body.ReplaceChild(newNode, period);         }          public void SetReason(string value)         {             var reason = Doc.GetElementbyId(\"time-off_reason\");              var parent = reason.ParentNode;              if (value == null)             {                 parent.RemoveChild(reason);             }             else             {                 value = new InsertStringFormatter().Format(value);                  var replaced = reason.OuterHtml.Replace(Placeholders.Reason, value);                  var newNode = HtmlNode.CreateNode(replaced);                  parent.ReplaceChild(newNode, reason);             }         }          public void SetWorkingOff(string value)         {             var reason = Doc.GetElementbyId(\"time-off_working-off\");              var parent = reason.ParentNode;              if (value == null)             {                 parent.RemoveChild(reason);             }             else             {                 value = new InsertStringFormatter().Format(value, firstLetter: FirstLetter.Upper);                  var replaced = reason.OuterHtml.Replace(Placeholders.WorkingOff, value);                  var newNode = HtmlNode.CreateNode(replaced);                  parent.ReplaceChild(newNode, reason);             }         }          public void SaveAs(TextWriter writer)         {             this.Doc.Save(writer);         }     }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h3 id=\"realizaciya-komand\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043e\u043c\u0430\u043d\u0434<\/h3>\n<p>  <\/p>\n<p>\u0420\u0430\u0437\u0432\u0435 \u0447\u0442\u043e \u043b\u0435\u043d\u0438\u0432\u044b\u0439 \u043d\u0435 \u043f\u0438\u0441\u0430\u043b \u043a\u0430\u043a \u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c-\u0431\u043e\u0442\u0430, \u0442\u0430\u043a \u0447\u0442\u043e \u044f \u043f\u0440\u043e\u043f\u0443\u0449\u0443 \u044d\u0442\u0430\u043f \u0441 \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0432\u0435\u0449\u0430\u043c\u0438 \u0438 \u043f\u0435\u0440\u0435\u0439\u0434\u0443 \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043c\u0430\u043d\u0434.<\/p>\n<p>  <\/p>\n<h4 id=\"komanda\">\u041a\u043e\u043c\u0430\u043d\u0434\u0430<\/h4>\n<p>  <\/p>\n<p>\u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u044d\u0442\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u043e\u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u0432\u043e\u044e \u0440\u0430\u0431\u043e\u0442\u0443. <\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434 \u043a\u043e\u043c\u0430\u043d\u0434\u044b<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">public abstract class Command {     protected readonly CancellationTokenSource CancellationToken;      [JsonIgnore]     public CommandContext Context { get; set; } = null!;      protected long ChatId => Context.ChatId;      protected string Message => Context.Message;      protected Command()     {         CancellationToken = new CancellationTokenSource();     }      \/\/ \u041c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u043a\u043e\u043c\u043c\u0430\u043d\u0434\u044b     public abstract Task Execute();      \/* \u041c\u0435\u0442\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u043c\u043c\u0430\u043d\u0434\u0430 \u0431\u043e\u043b\u0442\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u0435\u0441\u0441\u0438\u0438 \u0438 \u0436\u0434\u0435\u0442,     \u0447\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u0435\u0434\u0435\u0442 \u0447\u0442\u043e-\u043b\u0438\u0431\u043e \u0432 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u0431\u043e\u0442\u0430 *\/     public virtual Task&lt;int> OnMessage()     {         return Task.FromResult(ExecuteDirection.RunNext);     }      \/\/ \u041c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u0432\u0432\u0435\u043b \u0432 \u043e\u0442\u0432\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u2014 \u0432\u0430\u043b\u0438\u0434\u043d\u043e     public virtual Task ValidateMessage()     {         return Task.CompletedTask;     }      \/\/ \u041c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043c\u043c\u0430\u043d\u0434\u044b     public virtual Task Cancel()     {         this.CancellationToken.Cancel();          return Task.CompletedTask;     }      \/\/ \u0410 \u043e\u0431 \u044d\u0442\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 \u043c\u044b \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043f\u043e\u043f\u043e\u0437\u0436\u0435:)     protected void ForceComplete()     {         throw new ForceCompleteCommandException(this.GetType().Name);     } }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u043c\u0430\u043d\u0434\u044b Start<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">public class StartCommand: Command {     private readonly ILogger&lt;StartCommand> _logger = LogPoint.GetLogger&lt;StartCommand>();      public const string Key = \"\/start\";      public override async Task Execute()     {         _logger.LogInformation($\"{ChatId}: Started work\");          await this.Context.TelegramClient.SendMessage(             ChatId,              \"\u0414\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c!\\r\\n\" +             \"\\r\\n\" +             \"\u041f\u0435\u0440\u0435\u0434 \u043d\u0430\u0447\u0430\u043b\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e:\\r\\n\" +             \"\/registeruser \u2013 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f\\r\\n\" +             \"\/registermail \u2013 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u043f\u043e\u0447\u0442\u0443\");     } }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0410\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>Command<\/code> \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432, \u043d\u043e \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u0430\u0442\u0443 \u043e\u0442\u0433\u0443\u043b\u0430, \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u043a\u0435, \u0442\u0430\u043a \u0436\u0435 \u0435\u0449\u0435 \u043d\u0430\u0434\u043e \u0438\u043b\u0438 \u0432\u0432\u0435\u0441\u0442\u0438 \u043f\u043e\u0447\u0442\u043e\u0432\u044b\u0435 \u0430\u0434\u0440\u0435\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0442\u043e\u043c \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0438\u043b\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c \u0442\u0435, \u0447\u0442\u043e \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0432 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437. \u0410 \u0437\u043d\u0430\u0447\u0438\u0442 \u0434\u043b\u044f \u044d\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u0446\u0435\u043b\u0430\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430 \u043a\u043e\u043c\u0430\u043d\u0434.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u043a\u043b\u0430\u0441\u0441 <code>StatedCommand<\/code>.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">StatedCommand<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">public abstract class StatedCommand: Command {     private ILogger&lt;StatedCommand> _logger = LogPoint.GetLogger&lt;StatedCommand>();      [JsonProperty]     protected CommandClip Clip;      protected StatedCommand()     {         var states = this.ConfigureStates();         this.Clip = new CommandClip(states);     }      public abstract List&lt;Command> ConfigureStates();      public override async Task Execute()     {         try         {             await Clip.Run(Context);              if (Clip.IsCompleted)             {                 await OnComplete();             }             else             {                 await Context.SaveSession(this);             }         }         catch (ForceCompleteCommandException e)         {             await this.OnForceComplete(e);         }     }      public override async Task&lt;int> OnMessage()     {         await this.Execute();         return ExecuteDirection.RunNext;     }      public override async Task Cancel()     {         await base.Cancel();          await Clip.Cancel(Context);     }      protected async Task OnComplete()     {         await Context.SessionStorage.DeleteSession(ChatId);     }      private async Task OnForceComplete(ForceCompleteCommandException e)     {         await this.OnComplete();         _logger.LogWarning($\"\u0421ommand {e.CommandName} force completed\");     } }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0435\u0433\u043e \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u0437\u044f\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0438\u0437 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 (<code>CommandClip<\/code>) \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0435\u0435, \u0430 \u043a\u043e\u0433\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0442\u043e \u043f\u043e\u0434\u043f\u0435\u0440\u0435\u0442\u044c \u0437\u0430 \u0441\u043e\u0431\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u044e \u0432 Redis.<\/p>\n<p>  <\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043e\u0431\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e \u043f\u043e\u0442\u043e\u043a\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430 \u0441\u0435\u0431\u044f \u0431\u0435\u0440\u0435\u0442 \u043a\u043b\u0430\u0441\u0441 <code>CommandClip<\/code>.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">CommandClip<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">public class CommandClip {     private readonly ILogger&lt;CommandClip> _logger = LogPoint.GetLogger&lt;CommandClip>();      [JsonProperty]     private readonly Command[] _states;      [JsonProperty]     private int _runIndex = 0;      public bool IsFinishedChain => _runIndex == _states.Length;      private int LastIndex => _states.Length - 1;      public bool IsAsymmetricCompleted     {         get         {             if (_runIndex != LastIndex - 1)             {                 return false;             }             else             {                 return _states[_runIndex + 1].GetType() == typeof(AssymetricCompleteCommand);             }         }     }      public bool IsCompleted => IsFinishedChain || IsAsymmetricCompleted;      public int RunIndex => _runIndex;      public CommandClip(IEnumerable&lt;Command> states)     {         _states = states.ToArray();     }      public async Task Run(CommandContext context)     {         if (IsFinishedChain) return;          var firstPartCommand = _states[_runIndex];          try         {             var firstPartExecutor = new CommandExecutor(firstPartCommand, context);              await firstPartExecutor.ValidateMessage();             var increment = await firstPartExecutor.OnMessage();              if (increment &lt;= 0)             {                 context.BackwardRedirect = true;             }              this.IncrementStep(increment);              if (IsFinishedChain) return;              var secondPartCommand = _states[_runIndex];             var secondPartExecutor = new CommandExecutor(secondPartCommand, context);              _logger.LogInformation($\"{context.ChatId}: Start execute command {secondPartCommand.GetType().Name}\");             await secondPartExecutor.Execute();         }         catch (IncorrectFormatException e)         {             _logger.LogWarning(e, $\"Incorrect format of command {firstPartCommand.GetType().Name}: \\\"{context.Message}\\\"\");         }     }      public Task Cancel(CommandContext context)     {         var state = _states[_runIndex];         var executor = new CommandExecutor(state, context);          return executor.Cancel();     }      private void IncrementStep(int value)     {         this._runIndex += value;     } }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u041a\u0430\u0436\u0434\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>OnMessage<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0447\u0442\u043e\u0431\u044b <code>CommandClip<\/code> \u0437\u043d\u0430\u043b, \u0447\u0442\u043e \u0435\u043c\u0443 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0435\u0441\u043b\u0438 \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 <code>CheckEmailsCommand<\/code> \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0442\u0432\u0435\u0442\u0438\u0442, \u0447\u0442\u043e \u0432\u0432\u0435\u043b \u0435\u043c\u0435\u0439\u043b\u044b \u043d\u0435 \u0432\u0435\u0440\u043d\u043e, \u0442\u043e \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043d\u043e\u0432\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 <code>SetEmailsCommand<\/code>.<\/p>\n<p>  <\/p>\n<blockquote><p>\u042d\u0442\u043e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441, \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0442\u0435\u0440\u0437\u0430\u043b \u043c\u0435\u043d\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0433\u043e, \u0441\u0442\u043e\u0438\u0442 \u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0435\u0440\u0435\u0437 \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u043a\u043e\u0434\u0430 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430. \u0412\u0435\u0434\u044c \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0442\u0430\u043a, \u0447\u0442\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0437\u043d\u0430\u0435\u0442 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u0430\u044f \u043e\u043d\u0430 \u043f\u043e \u0441\u0447\u0435\u0442\u0443, \u0438 \u043a\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u0440\u043d\u0443\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c. \u041d\u043e \u043f\u043e\u0442\u043e\u043c \u044f \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u0438\u0448\u0443\u0442\u0441\u044f \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439, \u0442\u0430\u043a \u0447\u0442\u043e \u043e\u043d\u0438 \u0438\u043c\u0435\u044e\u0442 \u043d\u0430 \u044d\u0442\u043e \u043f\u0440\u0430\u0432\u043e.<\/p><\/blockquote>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">TimeOffCommand<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">public class TimeOffCommand: StatedCommand {     private ILogger&lt;TimeOffCache> _logger = LogPoint.GetLogger&lt;TimeOffCache>();      public const string Key = \"\/timeoff\";      public override List&lt;Command> ConfigureStates()     {         return new List&lt;Command>()         {             new EmptyCommand(),              new EnterPeriodCommand(),             new EnterReasonCommand(),             new EnterWorkingOffCommand(),             new CheckDocumentCommand(),             new SetEmailsCommand(),             new CheckEmailsCommand(),             new SendDocumentCommand(),             new AssymetricCompleteCommand(),         };     }      public override async Task Execute()     {         try         {             await base.Execute();         }         catch (NonCompleteUserException e)         {             await HandleUserException(e);             await OnComplete();              this._logger.LogError(e, $\"Command was completed by exception\");         }     }      private async Task HandleUserException(NonCompleteUserException e)     {         await new NonCompleteUserExceptionHandlerVisitor().Handle(e, ChatId, Context.TelegramClient);     } }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h4 id=\"pervaya-problema\">\u041f\u0435\u0440\u0432\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/h4>\n<p>  <\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>Run<\/code>, \u043e\u043d \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0443 \u0442\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u0447\u0442\u043e \u0436\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0442\u0430 \u043c\u0435\u0442\u043e\u0434 <code>OnMessage<\/code>, \u0430 \u0437\u0430\u0442\u0435\u043c \u0443 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043c\u0435\u0442\u043e\u0434 <code>Execute<\/code>. \u0418 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u0438\u0448\u0435\u043c \u0431\u043e\u0442\u0443 \u0432 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u0435\u0440\u0438\u043e\u0434\u0430 \u043e\u0442\u0433\u0443\u043b\u0430 \u0434\u0430\u0442\u0443, \u0442\u043e \u043c\u0435\u0442\u043e\u0434 <code>EnterPeriodCommand.OnMessage<\/code> \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u044d\u0442\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 <code>EnterReasonCommand.Execute<\/code> \u043f\u0438\u0448\u0435\u0442 \u043d\u0430\u043c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u0431\u044b \u0432\u0432\u0435\u0441\u0442\u0438 \u0435\u0449\u0435 \u0438 \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u043e\u0442\u0433\u0443\u043b\u0430.<\/p>\n<p>  <\/p>\n<p>\u041d\u043e \u0442\u043e\u0433\u0434\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u043c \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0440\u0430\u0437 \u043f\u0435\u0440\u0432\u044b\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <code>OnMessage<\/code>, \u0442\u043e \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0435 \u043a\u043e\u043c\u0430\u043d\u0434 \u0443 \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u0435\u0440\u0432\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u043d \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f. \u0425\u043e\u0442\u044f, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b, \u043d\u0430 \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0441\u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0432\u0432\u0435\u043b \u043a\u043e\u043c\u0430\u043d\u0434\u0443 <code>EmptyCommand<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u0442\u043e\u0438\u0442 \u043f\u0435\u0440\u0432\u043e\u0439 \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0435 \u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442.<\/p>\n<p>  <\/p>\n<h4 id=\"vtoraya-problema\">\u0412\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/h4>\n<p>  <\/p>\n<p>\u0424\u0438\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043d\u0435 \u0436\u0434\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430, \u0432\u0441\u044f \u0435\u0451 \u043b\u043e\u0433\u0438\u043a\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>Execute<\/code>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u0431\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0440\u043e\u0432\u043d\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043f\u0438\u0441\u044c\u043c\u043e \u0438 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043e\u043d\u0430 \u043d\u0435 \u0436\u0434\u0435\u0442.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0432\u0432\u0435\u043b \u043a\u043e\u043c\u0430\u043d\u0434\u0443 <code>AssymetricCompleteCommand<\/code>, \u0435\u0441\u043b\u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0432\u0438\u0434\u0438\u0442, \u0447\u0442\u043e \u044d\u0442\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430, \u0442\u043e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0441\u0435\u0431\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e\u0439.<\/p>\n<p>  <\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0441\u0435\u0433\u043e \u044d\u0442\u043e\u0433\u043e \u0434\u0435\u043b\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/nu\/ch\/jk\/nuchjk8hu5x_it_5pweiij9y5j8.png\" data-src=\"https:\/\/habrastorage.org\/webt\/nu\/ch\/jk\/nuchjk8hu5x_it_5pweiij9y5j8.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/dc\/nk\/jl\/dcnkjldwufyksqrua1zxmislr5o.png\" data-src=\"https:\/\/habrastorage.org\/webt\/dc\/nk\/jl\/dcnkjldwufyksqrua1zxmislr5o.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0410 \u044d\u0442\u043e \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ze\/rp\/y-\/zerpy-_nt8x2talnptvs2cqv21c.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ze\/rp\/y-\/zerpy-_nt8x2talnptvs2cqv21c.png\"\/><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/i9\/dt\/nx\/i9dtnx61fjcih6petlcqapuue0q.png\" data-src=\"https:\/\/habrastorage.org\/webt\/i9\/dt\/nx\/i9dtnx61fjcih6petlcqapuue0q.png\"\/><\/p>\n<p>  <\/p>\n<h3 id=\"plany\">\u041f\u043b\u0430\u043d\u044b<\/h3>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u0434\u043e\u043b\u0433\u043e\u0438\u0433\u0440\u0430\u044e\u0449\u0438\u0439 \u043f\u0435\u0442-\u043f\u0440\u043e\u0435\u043a\u0442, \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0435\u0433\u043e \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435. \u0412 \u043d\u0435\u043c \u0435\u0441\u0442\u044c \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b \u0434\u043b\u044f \u0440\u043e\u0441\u0442\u0430: \u043d\u043e\u0432\u044b\u0435 \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u044f, \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u0435\u043c \u0438 \u0442.\u0434.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043d\u0435\u043c \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0440 \u0434\u043b\u044f \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432 \u043f\u0430\u0440\u0435 \u043c\u0435\u0441\u0442 \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u043d\u0435 \u0441\u0430\u043c\u044b\u0435 \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0412 \u0446\u0435\u043b\u043e\u043c, \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0438 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e:)<\/p>\n<p>  <\/p>\n<h3 id=\"itogi\">\u0418\u0442\u043e\u0433\u0438<\/h3>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043c\u0435\u043d\u044f \u0431\u044b\u043b\u043e \u043f\u0440\u0438\u044f\u0442\u043d\u044b\u043c \u043e\u043f\u044b\u0442\u043e\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u043c\u043e\u044e \u0436\u0438\u0437\u043d\u044c \u0438 \u0436\u0438\u0437\u043d\u044c \u043a\u043e\u043b\u043b\u0435\u0433 \u043f\u0440\u043e\u0449\u0435. \u041f\u0440\u0438\u044f\u0442\u043d\u043e \u043f\u043e\u0440\u0435\u0448\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u0433\u043e\u043b\u043e\u0432\u043e\u043b\u043e\u043c\u043a\u0438, \u043a\u0430\u043a \u0433\u0438\u0431\u043a\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u043a\u043e\u043c\u0430\u043d\u0434. \u041d\u0430\u0432\u0435\u0440\u043d\u043e\u0435 \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0443\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043c\u043e\u0438\u0445 \u043f\u0435\u0442-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043a \u0435\u0433\u043e \u043f\u0440\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u044f \u043f\u043e\u0434\u043e\u0448\u0435\u043b \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0442\u0449\u0430\u0442\u0435\u043b\u044c\u043d\u043e.<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a \u0432\u044b\u0448\u043b\u043e, \u0447\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u0431\u044b\u043b\u043e \u0433\u0434\u0435 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430\u043c \u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b. \u042f \u043f\u043e\u0438\u0433\u0440\u0430\u043b\u0441\u044f \u0438 \u0441 CI\/CD, \u0438 c Redis. \u041f\u043e\u043a\u0440\u044b\u043b \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0438 \u043f\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0441 \u0433\u0438\u0431\u043a\u0438\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u043b\u043e\u0433\u0438\u044f\u043c\u0438.<\/p>\n<p>  <\/p>\n<p>\u0412\u0435\u0441\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438, \u043d\u043e \u0432\u043e\u0442 \u0441\u0441\u044b\u043b\u043e\u0447\u043a\u0438 \u043d\u0430 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u043c\u0435\u0441\u0442\u0430:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/afferenslucem\/secretary\/blob\/develop\/secretary.yandex\/authentication\/YandexAuthenticator.cs\" rel=\"nofollow noopener noreferrer\">\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 OAuth-\u0442\u043e\u043a\u0435\u043d\u0430<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/afferenslucem\/secretary\/blob\/develop\/secretary.yandex\/mail\/MailClient.cs\" rel=\"nofollow noopener noreferrer\">\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u0438\u0441\u044c\u043c\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0442\u043e\u043a\u0435\u043d\u0430<\/a><\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412\u043e\u043e\u0431\u0449\u0435, \u0432\u0440\u043e\u0434\u0435 \u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430\u0441\u044c \u043d\u0435\u043f\u043b\u043e\u0445\u0430\u044f \u0431\u0430\u0437\u0430 \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0431\u043e\u0442\u043e\u0432, \u0442\u0430\u043a \u0447\u0442\u043e, \u044f \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u0433\u043e\u0434\u044f\u0442\u0441\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u043d\u0435, \u0442\u0430\u043a \u0447\u0442\u043e \u0434\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u0432 <a href=\"https:\/\/github.com\/afferenslucem\/secretary\" rel=\"nofollow noopener noreferrer\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0434\u0440\u0443\u0433 \u0435\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u044f, \u0438\u043b\u0438 \u043d\u0430\u0439\u0434\u0435\u0442\u0435 \u043d\u0435\u0434\u043e\u0447\u0435\u0442\u044b, \u0442\u043e \u043f\u0438\u0448\u0438\u0442\u0435 \u043c\u043d\u0435, \u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0437\u0430 \u0442\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0441\u043b\u0443\u0448\u0430\u0442\u044c \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u0441\u043e\u0432\u0435\u0442:)<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/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\/post\/686786\/\"> https:\/\/habr.com\/ru\/post\/686786\/<\/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-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0418\u0434\u0435\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0435\u0442-\u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0440\u043e\u0434\u0438\u043b\u0430\u0441\u044c \u0438\u0437-\u0437\u0430 \u043e\u0442\u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u044b\u043b \u043d\u0435\u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c. \u042f \u043c\u043e\u0433 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0435 \u0442\u0443 \u0434\u0430\u0442\u0443 \u0432 \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u0438, \u043c\u043e\u0433 \u0437\u0430\u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u044f \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u043f\u0438\u0441\u044c\u043c\u0430 \u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u043c\u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043b\u0435\u043d\u044c \u0432\u043e\u0437\u0438\u0442\u044c\u0441\u044f \u0441\u043e \u0432\u0441\u0435\u0439 \u044d\u0442\u043e\u0439 \u0431\u044e\u0440\u043e\u043a\u0440\u0430\u0442\u0438\u0435\u0439. \u0418 \u044f \u0440\u0435\u0448\u0438\u043b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u0439 \u043d\u0430 \u043e\u0442\u0433\u0443\u043b.<\/p>\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-338023","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/338023","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=338023"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/338023\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=338023"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=338023"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=338023"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}