{"id":328980,"date":"2022-02-03T03:00:30","date_gmt":"2022-02-03T03:00:30","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=328980"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=328980","title":{"rendered":"<span>\u0427\u0430\u0442-\u0431\u043e\u0442 \u043f\u043e\u0434 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u043e\u0432<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u044f \u041f\u0430\u0448\u0430, \u0440\u0443\u043a\u043e\u0432\u043e\u0436\u0443 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0435\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043a\u0440\u0443\u043f\u043d\u043e\u0433\u043e \u0445\u0430\u0439\u043b\u043e\u0430\u0434-\u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0425\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u043e\u043f\u044b\u0442\u043e\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0431\u043e\u0442\u0430 \u043d\u0430 Golang \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u043e\u0432.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"\/img\/image-loader.svg\" height=\"570\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/255\/6f7\/fb5\/2556f7fb5d68949863ead3a09af78a93.png\" data-width=\"896\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0441\u0451 \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u0441 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b \u0431\u043e\u0442 \u043d\u0430 python-telegram-bot, \u0434\u0435\u043b\u0430\u043b \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0432\u0435\u0449\u0438, \u0443\u043c\u0435\u043b \u043f\u043e\u0441\u043b\u0430\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u0443\u044e \u0432\u0435\u0441\u0451\u043b\u0443\u044e \u0433\u0438\u0444\u043a\u0443 \u0438\u0437 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430, \u043a\u043e\u0448\u0435\u0447\u043a\u0443, \u0441\u043e\u0431\u0430\u0447\u043a\u0443, \u0437\u0430\u0442\u0435\u043c \u043c\u044b \u043a\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u043b\u0438 \u043a \u043d\u0435\u043c\u0443 \u043d\u0430\u0448 \u0442\u0430\u0441\u043a-\u0442\u0440\u0435\u043a\u0435\u0440 \u0438 \u0431\u043e\u0442 \u0441\u0442\u0430\u043b \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u0438\u043a\u0435\u0442\u044b \u043f\u0440\u044f\u043c\u043e \u0438\u0437 \u0447\u0430\u0442\u0430.<\/p>\n<p>\u0421\u043f\u0443\u0441\u0442\u044f \u0432\u0440\u0435\u043c\u044f, \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u043d\u044f\u043b\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430 \u0434\u043b\u044f \u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0438 \u0432\u0441\u0442\u0430\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u043e\u0442\u0430 \u0432 \u043d\u043e\u0432\u043e\u043c \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0435. \u0423 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0431\u044b\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u043b\u0438\u0448\u044c \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0442\u044c \u043a \u043d\u043e\u0432\u043e\u043c\u0443 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043d\u043e \u0432 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u044b \u0443\u0436\u0435 \u043e\u0434\u043d\u043e\u0439 \u043d\u043e\u0433\u043e\u0439 \u0442\u043e\u0440\u0447\u0430\u043b\u0438 \u0432 Golang \u0438 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u0448\u0430\u043d\u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0432\u044b\u043a\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043c\u044b \u0432\u0438\u0434\u0435\u043b\u0438 \u0432 Golang \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u044b \u0434\u043b\u044f \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u044f \u043d\u0430\u0448\u0435\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<p>\u0418-\u0442\u0430\u043a, \u043f\u043e\u0435\u0445\u0430\u043b\u0438.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/cf4\/5a5\/2ee\/cf45a52eed2a66a08973d91245d2ce07.jpeg\" width=\"604\" height=\"340\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/cf4\/5a5\/2ee\/cf45a52eed2a66a08973d91245d2ce07.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<h2>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438<\/h2>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u0431\u044b\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435<\/p>\n<pre><code>github.com\/andygrunwald\/go-jira v1.13.0 github.com\/go-telegram-bot-api\/telegram-bot-api v4.6.4+incompatible github.com\/gorilla\/mux v1.8.0 github.com\/urfave\/cli\/v2 v2.3.0 go.mongodb.org\/mongo-driver v1.6.0 golang.org\/x\/oauth2 v0.0.0-20210805134026-6f1e6394065a<\/code><\/pre>\n<h2>\u0412\u0445\u043e\u0434\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430<\/h2>\n<p>\u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0441\u0435\u0440\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 urfave\/cli2 &#8212; \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0438 cobra, \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0443\u0442\u0438\u043b\u0438\u0442, \u043d\u043e, \u043f\u043e \u043d\u0430\u0448\u0435\u043c\u0443 \u043c\u043d\u0435\u043d\u0438\u044e, cli2 \u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u043e\u0432 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0431\u043e\u043b\u044c\u0448\u0435, \u0442\u0430\u043c \u043f\u0440\u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 + \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c required, \u0430\u043b\u0438\u0430\u0441\u044b \u0438 \u043c\u043d\u043e\u0433\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435, \u0432\u043e\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0444\u043b\u0430\u0433\u0430 (\u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0443\u0442\u0438\u043b\u0438\u0442\u044b)<\/p>\n<pre><code class=\"go\">type StringFlag struct { Name        string Aliases     []string Usage       string EnvVars     []string FilePath    string Required    bool Hidden      bool TakesFile   bool Value       string DefaultText string Destination *string HasBeenSet  bool }<\/code><\/pre>\n<p>\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"go\">package main import ( \"github.com\/urfave\/cli\/v2\" ) func main() { app := &amp;cli.App{ Flags: []cli.Flag{       \/* \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 dev\/production, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u043c \u044d\u0442\u043e       - \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0431\u0443\u0434\u0443\u0449\u0443\u044e \u0443\u0442\u0438\u043b\u0438\u0442\u0443 \u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c --environment       - \u043b\u0438\u0431\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u044d\u0442\u043e \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f ENVIRONMENT       - \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 production       *\/ &amp;cli.StringFlag{Name: \"environment\", Value: \"production\", Usage: \"environment name\", EnvVars: []string{\"ENVIRONMENT\"}},             \/\/\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0435\u043c \u043b\u043e\u0433\u0438\u043d \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043e\u0442 JIRA, \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u044d\u0442\u0438\u043c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e &amp;cli.StringFlag{Name: \"jira-login\", Usage: \"jira bot login\", EnvVars: []string{\"jira_login\"}}, &amp;cli.StringFlag{Name: \"jira-password\", Usage: \"jira bot password\", EnvVars: []string{\"jira_password\"}},              \/*\u0435\u0441\u0442\u044c \u0438 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u0435\u0441\u043b\u0438 \u0432\u0432\u0435\u0441\u0442\u0438 \u0442\u0430\u043c \u0442\u0435\u043a\u0441\u0442 \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0447\u0442\u043e \u0442\u043e \u0442\u0430\u043a\u043e\u0435:       Incorrect Usage. invalid value \"foo\" for flag -jira-default-search-limit: parse error       *\/ &amp;cli.IntFlag{Name: \"jira-default-search-limit\", Value: 5, Usage: \"jira default search limit\"},              \/*\u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u043e\u0442\u0443, \u0437\u0430\u0434\u0430\u0451\u0442\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 --telegram-permit-users:       --telegram-permit-users foo --telegram-permit-users bar       *\/ &amp;cli.StringSliceFlag{Name: \"telegram-permit-users\", Value: cli.NewStringSlice( \"Paulstrong\", ), Usage: \"telegram permitted users list\"},        \/\/\u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435       &amp;cli.StringFlag{Name: \"mongodb-host\", Usage: \"mongodb server host\/ip\", EnvVars: []string{\"mongodb_host\"}}, &amp;cli.StringFlag{Name: \"mongodb-user\", Usage: \"mongodb server username\", EnvVars: []string{\"mongodb_user\"}}, &amp;cli.StringFlag{Name: \"mongodb-password\", Usage: \"mongodb server password\", EnvVars: []string{\"mongodb_password\"}}, &amp;cli.StringFlag{Name: \"mongodb-name\", Usage: \"mongodb server database name\", EnvVars: []string{\"mongodb_name\"}}, &amp;cli.IntFlag{Name: \"mongodb-port\", Value: 27017, Usage: \"mongodb server database name\"}, }, Action: func(context *cli.Context) error {       \/\/\u0443 \u043d\u0430\u0441 \u0443 \u0434\u0435\u043c\u043e\u043d\u0430 \u0435\u0441\u0442\u044c \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u043d\u0430 \u043a\u043e\u0440\u043d\u0435\u0432\u0430\u044f \"\u043a\u043e\u043c\u0430\u043d\u0434\u0430\", \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0435\u0451 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443       \/\/\u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0431\u0443\u0434\u0443\u0449\u0435\u0433\u043e \u0434\u0435\u043c\u043e\u043d\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0435\u043c\u0443 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438       d := daemon.NewDaemon(context)       \/\/\u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u0435\u043c\u043e\u043d\u0430 (\u043f\u043e\u0437\u0436\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0442\u0430\u043c)       if err := d.Init(); err != nil {         log.Fatalln(\"daemon initialization error\", err)       }       \/\/\u0438, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0434\u0435\u043c\u043e\u043d\u0430       return d.Run() }, }   \/\/\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 cli2 _ = app.Run(os.Args) } <\/code><\/pre>\n<p>\u0412 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0443\u0431\u0440\u0430\u043b \u0438\u0445 \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0437\u0430\u0441\u043e\u0440\u044f\u0442\u044c \u044d\u0444\u0438\u0440. \u041e\u0431\u0449\u0438\u0439 \u0441\u043c\u044b\u0441\u043b, \u0434\u0443\u043c\u0430\u044e, \u043f\u043e\u043d\u044f\u0442\u0435\u043d, \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u043e\u0442\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0443\u0442\u0451\u043c \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u0445 \u0443\u0442\u0438\u043b\u0438\u0442\u044b, \u043b\u0438\u0431\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/p>\n<h2>\u041a\u043e\u043d\u0444\u0438\u0433<\/h2>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f context \u043e\u0442 cli2 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 &#8212; \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u0438 \u044d\u0442\u043e \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u043b\u0438\u0431\u043e \u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u0438\u0442\u044c \u0432 \u043a\u043e\u0434\u0435, \u043b\u0438\u0431\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u0445, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u043e\u0442 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438\u043c\u0435\u043d\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"go\">context.String(\"environment\")<\/code><\/pre>\n<p>\u043c\u044b \u044d\u0442\u043e \u0434\u0435\u043b\u043e \u043e\u0431\u0435\u0440\u043d\u0443\u043b\u0438 \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442:<\/p>\n<pre><code class=\"go\">type UrfaveContext struct { *cli.Context }  func NewUrfaveContext(context *cli.Context) *UrfaveContext { ret := &amp;UrfaveContext{} ret.Context = context return ret }  func (c *UrfaveContext) Environment() string { return c.Context.String(\"environment\") }<\/code><\/pre>\n<p>\u0438 \u0434\u0430\u043b\u0435\u0435 \u043c\u044b \u043f\u043e\u0434\u0430\u0451\u043c \u0432 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0434\u0435\u043c\u043e\u043d\u0430 \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0444\u0438\u0433:<\/p>\n<pre><code class=\"go\">d := daemon.NewDaemon(NewUrfaveContext(context))<\/code><\/pre>\n<p>\u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0435\u043c\u043e\u043d\u0430 \u043c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433 \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0438 \u0434\u0430\u043b\u044c\u0448\u0435 \u044d\u0442\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0447\u0435\u043d\u044c \u0434\u0430\u0436\u0435 \u0443\u0434\u043e\u0431\u043d\u043e:<\/p>\n<pre><code class=\"go\">type Daemon struct { config    interfaces.IConfig }  func NewDaemon(config interfaces.IConfig) *Daemon {   return &amp;Daemon{config} }  func (d *Daemon) PrinEnv() {   fmt.Println(d.config.Environment()) }<\/code><\/pre>\n<p>\u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 IConfig, \u043c\u044b \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043e\u0441\u043e\u0437\u043d\u0430\u043d\u043d\u043e, \u0442.\u043a. \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u0447\u0442\u043e-\u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u043a\u043e\u043b\u044c\u043d\u043e\u0435, \u0447\u0435\u043c cli2, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043a\u0442\u043e-\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c cobra \u0432\u043c\u0435\u0441\u0442\u043e cli2, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u044b, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435, \u0430 \u043d\u0430 \u0447\u0451\u043c \u0438\u043c\u0435\u043d\u043d\u043e &#8212; \u0440\u0435\u0448\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e:<\/p>\n<pre><code class=\"go\">type IConfig interface { Environment() string }<\/code><\/pre>\n<h2>\u0427\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435?<\/h2>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u043f\u043e\u0434\u043a\u0430\u043f\u043e\u0442\u043d\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435 \u0434\u0435\u043c\u043e\u043d\u0430. \u041e\u043d \u0443 \u043d\u0430\u0441 \u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b:<\/p>\n<pre><code class=\"go\">type Daemon struct { shutdown  chan struct{} engines []interfaces.IEngine config    interfaces.IConfig db        interfaces.IDatabase }<\/code><\/pre>\n<ul>\n<li>\n<p>shutdown &#8212; \u043a\u0430\u043d\u0430\u043b, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0448\u043b\u0451\u0442\u0441\u044f struct{}{} \u043f\u0440\u0438 \u043e\u0442\u043b\u043e\u0432\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u0438\u0441\u0430\u043b\u0438 \u0431\u043e\u0442\u0430, \u043c\u044b \u0435\u0449\u0435 \u043d\u0435 \u0437\u043d\u0430\u043b\u0438 \u043f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c context.Context, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0438\u0441\u0430\u043b\u0438 \u043a\u0430\u043a \u043c\u043e\u0433\u043b\u0438<\/p>\n<\/li>\n<li>\n<p>engine &#8212; \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 &#171;\u0434\u0432\u0438\u0436\u043e\u043a&#187;, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 telegram, viber, \u0442\u043e \u0435\u0441\u0442\u044c \u043c\u0435\u043d\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u044b, \u043a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0434\u0432\u0438\u0436\u043a\u043e\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0447\u0442\u043e-\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0430 \u0444\u043e\u043d\u0435, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0440\u0438\u0441\u044b\u043b\u0430\u0435\u0442 \u0432 \u043e\u0434\u0438\u043d \u0438\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u0434\u0432\u0438\u0436\u043a\u043e\u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0432\u043e\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b, \u0432 \u043e\u0431\u0449\u0435\u043c \u0438 \u0446\u0435\u043b\u043e\u043c, \u044d\u0442\u043e &#8212; \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0444\u043e\u043d\u0435<\/p>\n<\/li>\n<li>\n<p>config &#8212; \u043c\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u043c \u0447\u0442\u043e \u044d\u0442\u043e<\/p>\n<\/li>\n<li>\n<p>db &#8212; \u043e\u0431\u044a\u0435\u043a\u0442 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0431\u0434 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f oauth2 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430, \u043c\u044b \u043f\u043e\u0434\u0430\u0451\u043c \u044d\u0442\u043e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 &#171;\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440&#187; \u0434\u0435\u043c\u043e\u043d\u0430 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443, \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u043e\u043d\u0433\u0430, \u043b\u0438\u0431\u043e \u0431\u044b\u0442\u044c mysql, \u0438 \u0434\u0440., \u0433\u043b\u0430\u0432\u043d\u043e\u0435, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"go\">type IDatabase interface { GetToken() (*oauth2.Token, error) \/\/\u0447\u0438\u0442\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u0438\u0437 \u0431\u0430\u0437\u044b SetToken(t *oauth2.Token) error \/\/\u043a\u043b\u0430\u0434\u0451\u043c \u0442\u043e\u043a\u0435\u043d \u0432 \u0431\u0430\u0437\u0443 }<\/code><\/pre>\n<p>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u0432\u0438\u0436\u043a\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a<\/p>\n<pre><code class=\"go\">type IEngine interface { AddShutdownChan(ch chan struct{}) Run(wg *sync.WaitGroup) Reply(update IUpdate) CheckAcl(update IUpdate, cmd ICommand) (result bool) SetManager(engine IManager) IEngine GetManager() IManager SetName(name string) IEngine GetName() string SetDaemon(d IDaemon) IEngine GetDaemon() IDaemon GetConfig() IConfig GetDB() IDatabase }<\/code><\/pre>\n<p>\u0422\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u0434\u0432\u0438\u0436\u043a\u0443 \u0438\u043c\u044f, \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u0435\u043c\u043e\u043d\u0430 \u0438 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 (\u0441\u043a\u043e\u0440\u043e \u043f\u043e\u0434\u043e\u0439\u0434\u0451\u043c \u043a \u044d\u0442\u043e\u043c\u0443), \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433. \u0412\u0441\u0451 \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0432\u044f\u0437\u0430\u0442\u044c \u0434\u0432\u0438\u0436\u043a\u0438 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0438 \u043c\u043e\u0433\u043b\u0438 \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433-\u043a-\u0434\u0440\u0443\u0433\u0443 \u043f\u043e \u0438\u043c\u0435\u043d\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0434\u0432\u0438\u0436\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043c\u043e\u0442\u0440\u0438\u0442 \u0442\u0438\u043a\u0435\u0442\u044b \u043e\u0442 \u0441\u0430\u043f\u043f\u043e\u0440\u0442\u0430, \u0430 \u043f\u043e\u0442\u043e\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0434\u0432\u0438\u0436\u043a\u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u0447\u0430\u0442 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0438.<\/p>\n<h2>\u041c\u0435\u043d\u0435\u0434\u0436\u0435\u0440<\/h2>\n<p>\u041c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u0434\u0432\u0438\u0436\u043a\u043e\u0432 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0445 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043c\u043e\u0434\u0435\u043b\u044c. \u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043c\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 \u043d\u0430 \u0432\u0441\u0435 \u0434\u0432\u0438\u0436\u043a\u0438, \u043d\u043e \u043f\u043e\u0442\u043e\u043c \u0440\u0435\u0448\u0438\u043b\u0438, \u0447\u0442\u043e \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0434\u0432\u0438\u0436\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u0432\u043e\u0439 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u043f\u0435\u0446\u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0432 &#171;\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430\u0445&#187; \u0434\u0432\u0438\u0436\u043a\u043e\u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e:<\/p>\n<pre><code class=\"go\">type CorpMessenger struct { name         string daemon       interfaces.IDaemon manager      interfaces.IManager }  func New(d interfaces.IDaemon, name string) interfaces.ICorpMessengerEngine { a := &amp;CorpMessenger{daemon: d, name: name} a.manager = NewManager(a) return a }<\/code><\/pre>\n<p>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c<\/p>\n<pre><code class=\"go\">type IManager interface { SetInitialController(c IInitialController) Route(update IUpdate) SetEngine(e IEngine) IManager GetEngine() IEngine GetConfig() IConfig GetDB() IDatabase }<\/code><\/pre>\n<p>\u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/p>\n<h2>\u041a\u0430\u043a \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f<\/h2>\n<p>\u0418\u0442\u0430\u043a, \u043c\u044b \u043d\u0430\u0443\u0447\u0438\u043b\u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043d\u0430\u0448\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0443\u0442 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443, \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u0432\u043e\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0441\u043c\u044b\u0441\u043b \u0442\u0443\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u0431\u0430\u0439\u0442 \u043e\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, id \u0447\u0430\u0442\u0430, \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043f\u043e\u0434 \u044d\u0442\u043e \u0434\u0435\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/p>\n<pre><code class=\"go\">type IUpdate interface { Reply(text string) CheckAcl(cmd ICommand) (result bool) GetText() (result string) GetEngine() (result IEngine) GetChatID() (result string) GetMessageID() (result string) GetReplyText() (result string) GetUserName() (result string) GetUserDescription() (result string) }<\/code><\/pre>\n<p>\u043f\u0440\u0438\u043d\u044f\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043c\u044b \u0443\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438 \u043e\u0442\u0434\u0430\u0451\u043c \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0443 \u043d\u0430 \u0440\u043e\u0443\u0442\u0438\u043d\u0433<\/p>\n<pre><code>upd := update.NewUpdate(corpMsgObj, text, msgId, chanId, directId, userDescription,) corpMsgObj.manager.Route(upd)<\/code><\/pre>\n<p>\u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0443 \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443, \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u043e\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f (acl), \u0430 \u0434\u0430\u043b\u044c\u0448\u0435 \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430\u0448\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 (\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440)<\/p>\n<p>\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c<\/p>\n<pre><code class=\"go\">type IController interface { Call(cmd ICommand) (result string, err error) \/\/\u0432\u0445\u043e\u0434\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430 CanAnswer(c ICommand) (result bool) \/\/\u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043e\u0442\u0432\u0435\u0442\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u043c \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 GetName() (result string) \/\/\u043e\u0442\u0434\u0430\u0451\u043c \u0438\u043c\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 Validate(c ICommand) (result bool) \/\/\u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 SetManager(m IManager) GetManager() IManager GetConfig() IConfig GetDatabase() IDatabase }  type IInitialController interface { IController ThrowManager()  }<\/code><\/pre>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0430\u0440\u0441\u0438\u0442 \u0441\u0442\u0440\u043e\u043a\u0443, \u0432\u044b\u0434\u0435\u043b\u044f\u044f \u0432 \u043d\u0435\u0439 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043e\u0442 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438 \u0434\u0430\u043b\u0435\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0432 \u043c\u043e\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c, \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 ICommand<\/p>\n<pre><code class=\"go\">type ICommand interface { GetEntity() (result string) \/\/\u043e\u0442\u0434\u0430\u0442\u044c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434\u044b SetEntity(val string) \/\/\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434\u044b GetArgs() (result string) \/\/\u043e\u0442\u0434\u0430\u0442\u044c \u0442\u0435\u043b\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u044b SetArgs(val string) \/\/\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u043b\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u044b GetText() (result string) \/\/\u043e\u0442\u0434\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b SetText(val string) \/\/\u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b Parse() (entity string, args string, err error) \/\/\u043f\u0430\u0440\u0441\u0438\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 GetUserDescription() string }<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u044d\u0442\u043e \u0443 \u043d\u0430\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f, \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043c\u044b \u0443\u043c\u0435\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u044b\u0432\u0430\u0442\u044c:<\/p>\n<p><code>\/task create foo \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0442\u0438\u043a\u0435\u0442\u0430<br \/>\u044d\u0442\u043e \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0442\u0438\u043a\u0435\u0442, \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u0434\u0435\u043b\u0430\u0442\u044c<br \/>\u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0445\u043e\u0442\u0438\u043c \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0431\u043e\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0435\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043b<\/code><\/p>\n<p>\u0427\u0442\u043e \u043c\u044b \u0432\u0438\u0434\u0438\u043c? <\/p>\n<p>\u0412\u043e \u043f\u0435\u0440\u0432\u044b\u0445, \u043c\u044b \u0434\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438\u0441\u044c, \u0447\u0442\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0431\u043e\u0442\u0430 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c\u0441\u044f \u0441\u043e \u0441\u043b\u0435\u0448\u0430, \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u0442\u0440\u0430\u043d\u043d\u043e\u0432\u0430\u0442\u043e, \u0442.\u043a. \u0431\u043e\u0442\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0447\u0435\u0440\u0435\u0437 @, \u043d\u043e \u044d\u0442\u043e \u0438\u0441\u0442\u043e\u0440\u0438\u044f, \u043d\u0430\u0441 \u044d\u0442\u043e \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442, \u043c\u044b \u044d\u0442\u043e \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u0435\u043c. \u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u043c \u043a\u0430\u043a-\u0442\u043e \u0438\u043d\u0430\u0447\u0435.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e <code>task<\/code>, \u043f\u043e\u0434 \u044d\u0442\u043e \u0434\u0435\u043b\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c type TaskController<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0438\u0434\u0451\u0442 <code>create<\/code>, \u043f\u043e\u0434 \u044d\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c CreateController (\u0432\u0441\u0451, \u0447\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 task, \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u043e \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 package, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0432\u0432\u043e\u0434\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043a\u0443\u0447\u0443 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c \u0432 \u0438\u043c\u0435\u043d\u0430\u0445 \u0442\u0438\u043f\u043e\u0432)<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0438\u0434\u0451\u0442 \u0438\u043c\u044f \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0432 JIRA, \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430, <code>foo<\/code><\/p>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0443 \u043d\u0430\u0441 \u0438\u0434\u0451\u0442 \u0442\u0435\u043c\u0430 \u0442\u0438\u043a\u0435\u0442\u0430 (<code>\u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0442\u0438\u043a\u0435\u0442\u0430<\/code>)<\/p>\n<p>\u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0438\u0434\u0451\u0442 \u0442\u0435\u043a\u0441\u0442 \u0442\u0438\u043a\u0435\u0442\u0430.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0430\u043b\u043e\u0436\u0438\u0442\u044c \u044d\u0442\u043e \u043d\u0430 ICommand, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<pre><code class=\"go\">type Command struct { entity          string \/\/task args            string \/\/create foo ............. text            string \/\/\u0442\u0443\u0442 \u043f\u043e\u043b\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b }<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c InitialController, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0432\u0435\u0440\u0448\u0438\u043d\u0435 \u0432\u0441\u0435\u0439 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438<\/p>\n<pre><code class=\"go\">type InitialController struct { controllers []interfaces.IController name        string manager     interfaces.IManager }  func NewInitialController(manager interfaces.IManager) interfaces.IInitialController { ctrl := &amp;InitialController{} ctrl.name = \"initial\" ctrl.AddController(task_controller.NewTaskController(manager)) return ctrl }  \/*  \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u043d\u0438\u044f \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 \u0432\u0441\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 *\/ func (ctrl *InitialController) ThrowManager() { for _, c := range ctrl.controllers { c.SetManager(ctrl.manager) } }  \/* \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0433\u043e\u0442\u043e\u0432 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u043d\u0430\u0448\u0443 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 *\/ func (ctrl *InitialController) FindController(command interfaces.ICommand) (result interfaces.IController, err error) { for _, ctl := range ctrl.controllers { if ctl.CanAnswer(command) { result = ctl } } if result == nil { result = NewDummyController(ctrl.manager) } return result, err }  \/* \u0432\u0445\u043e\u0434\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u043c *\/ func (ctrl *InitialController) Call(cmd interfaces.ICommand) (result string, err error) {  controller, ctlErr := ctrl.FindController(cmd) if ctlErr != nil { return result, ctlErr } if !controller.Validate(cmd) { return result, errors.New(controllers.EInvalidCommand) }  return controller.Call(cmd) }<\/code><\/pre>\n<p>\u041a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0438\u0434\u0442\u0438 \u043f\u043e \u0441\u043f\u0438\u0441\u043a\u0443 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0438 \u043e\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u0438\u0445 &#171;\u0442\u044b \u043c\u043e\u0436\u0435\u0448\u044c \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u044b task?&#187;, \u0438 \u043e\u0434\u0438\u043d \u0438\u0437 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c true <\/p>\n<pre><code class=\"go\">type TaskController struct { name        string controllers []interfaces.IController manager     interfaces.IManager }  func NewTaskController(m interfaces.IManager) *TaskController { task := &amp;TaskController{manager: m} task.name = \"task\" task.AddController(NewCreateController(m)) return task }  \/* \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 *\/ func (ctrl *TaskController) CanAnswer(cmd interfaces.ICommand) (result bool) { return cmd.GetEntity() == ctrl.name }  \/* \u0432\u0445\u043e\u0434\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 *\/ func (ctrl *TaskController) Call(cmd interfaces.ICommand) (result string, err error) { if !ctrl.Validate(cmd) { return result, errors.New(controllers.EInvalidCommand) } taskCmd, taskCmdErr := commands.NewCommand(cmd.GetArgs()) if taskCmdErr != nil { return result, errors.New(controllers.EInvalidTaskCommand) }   \/\/\u0438\u0434\u0451\u043c \u043f\u043e \u0441\u043f\u0438\u0441\u043a\u0443 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0438 \u0441\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u043a\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c controller, ctlErr := ctrl.FindController(taskCmd) if ctlErr != nil { return result, ctlErr } if !controller.Validate(taskCmd) { return result, errors.New(controllers.EInvalidTaskCommand) }  return controller.Call(taskCmd) }<\/code><\/pre>\n<p>\u0443 \u043d\u0435\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u0440\u0430\u0437\u043d\u044b\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b, \u0432 \u0442.\u0447. CreateController, \u0437\u0434\u0435\u0441\u044c \u0432\u0441\u0451 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e, \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0438\u0434\u0442\u0438 \u043f\u043e \u0441\u043f\u0438\u0441\u043a\u0443 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0438 \u0441\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c &#171;\u0442\u044b \u043c\u043e\u0436\u0435\u0448\u044c \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 create?&#187;, \u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043e\u0442\u0432\u0435\u0442\u0438\u0442 true<\/p>\n<pre><code class=\"go\">type CreateController struct { args    string name    string manager interfaces.IManager }  func NewCreateController(m interfaces.IManager) *CreateController { ret := &amp;CreateController{name: \"create\", manager: m} return ret }  func (ctrl *CreateController) CanAnswer(cmd interfaces.ICommand) (result bool) { return cmd.GetEntity() == ctrl.name }<\/code><\/pre>\n<p>\u0418 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435, \u043c\u044b \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432\u043e \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b. \u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u044b \u043f\u0440\u0438\u0434\u0451\u043c \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0432 \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443.<\/p>\n<pre><code class=\"go\">func (ctrl *CreateController) Call(cmd interfaces.ICommand) (result string, err error) { createCmd, _ := commands.NewTaskCreateCommand(cmd.GetText()) parseRes, parseErr := createCmd.Parse() if parseErr != nil { return result, parseErr } return task.Create(parseRes.Project, parseRes.Title, parseRes.Content, parseRes.Assignee, ctrl.GetConfig(), parseRes.Link) }<\/code><\/pre>\n<p>\u0432 \u043c\u043e\u0434\u0435\u043b\u044c \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0438\u043c\u044f \u043e\u0447\u0435\u0440\u0435\u0434\u0438 (\u043f\u0440\u043e\u0435\u043a\u0442), \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0442\u0438\u043a\u0435\u0442\u0430, \u0442\u0435\u043a\u0441\u0442, \u043a\u043e\u043d\u0444\u0438\u0433 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u0432 \u043e\u0442\u0432\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0435\u043a\u0441\u0442 \u0438 \u043e\u0448\u0438\u0431\u043a\u0443, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u044d\u0442\u043e \u0434\u0435\u043b\u043e, \u0438 \u0434\u0430\u043b\u0435\u0435 \u043e\u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0432\u0435\u0440\u0445 \u043f\u043e \u0441\u0442\u0435\u043a\u0443 \u0432\u044b\u0437\u043e\u0432\u043e\u0432.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u042d\u0442\u043e \u043c\u043e\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f, \u043f\u0440\u043e\u0448\u0443 \u043d\u0435 \u0441\u0443\u0434\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u0433\u043e, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u043d\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u044f \u043f\u043e\u0437\u0436\u0435 \u043c\u043e\u0433\u0443 \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0438 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e. \u0415\u0441\u043b\u0438 \u0443 \u043a\u043e\u0433\u043e-\u0442\u043e \u043e\u043d\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u043b\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441 \u0438\u043b\u0438 \u043d\u0435\u0434\u043e\u0443\u043c\u0435\u043d\u0438\u0435 &#8212; \u043f\u0440\u043e\u0448\u0443 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438, \u0441 \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u0435\u043c \u043e\u0442\u0432\u0435\u0447\u0443 \u043d\u0430 \u043b\u044e\u0431\u044b\u0435, \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u043f\u0440\u0438\u043c\u0443 \u043a\u0440\u0438\u0442\u0438\u043a\u0443 \u0438 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043c\u043e\u0433\u0443 \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u044c \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u0435\u0441\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b\u043e, \u043d\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e.<\/p>\n<p>\u0412\u0441\u0435\u043c peace \ud83d\ude42<\/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\/649413\/\"> https:\/\/habr.com\/ru\/post\/649413\/<\/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_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u044f \u041f\u0430\u0448\u0430, \u0440\u0443\u043a\u043e\u0432\u043e\u0436\u0443 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0435\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043a\u0440\u0443\u043f\u043d\u043e\u0433\u043e \u0445\u0430\u0439\u043b\u043e\u0430\u0434-\u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0425\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u043e\u043f\u044b\u0442\u043e\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0431\u043e\u0442\u0430 \u043d\u0430 Golang \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u043e\u0432.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0441\u0451 \u043d\u0430\u0447\u0430\u043b\u043e\u0441\u044c \u0441 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b \u0431\u043e\u0442 \u043d\u0430 python-telegram-bot, \u0434\u0435\u043b\u0430\u043b \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0432\u0435\u0449\u0438, \u0443\u043c\u0435\u043b \u043f\u043e\u0441\u043b\u0430\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u0443\u044e \u0432\u0435\u0441\u0451\u043b\u0443\u044e \u0433\u0438\u0444\u043a\u0443 \u0438\u0437 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430, \u043a\u043e\u0448\u0435\u0447\u043a\u0443, \u0441\u043e\u0431\u0430\u0447\u043a\u0443, \u0437\u0430\u0442\u0435\u043c \u043c\u044b \u043a\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u043b\u0438 \u043a \u043d\u0435\u043c\u0443 \u043d\u0430\u0448 \u0442\u0430\u0441\u043a-\u0442\u0440\u0435\u043a\u0435\u0440 \u0438 \u0431\u043e\u0442 \u0441\u0442\u0430\u043b \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u0438\u043a\u0435\u0442\u044b \u043f\u0440\u044f\u043c\u043e \u0438\u0437 \u0447\u0430\u0442\u0430.<\/p>\n<p>\u0421\u043f\u0443\u0441\u0442\u044f \u0432\u0440\u0435\u043c\u044f, \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u043d\u044f\u043b\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430 \u0434\u043b\u044f \u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0438 \u0432\u0441\u0442\u0430\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u043e\u0442\u0430 \u0432 \u043d\u043e\u0432\u043e\u043c \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0435. \u0423 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0431\u044b\u043b\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u043b\u0438\u0448\u044c \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0442\u044c \u043a \u043d\u043e\u0432\u043e\u043c\u0443 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043d\u043e \u0432 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u044b \u0443\u0436\u0435 \u043e\u0434\u043d\u043e\u0439 \u043d\u043e\u0433\u043e\u0439 \u0442\u043e\u0440\u0447\u0430\u043b\u0438 \u0432 Golang \u0438 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u0448\u0430\u043d\u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0432\u044b\u043a\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043c\u044b \u0432\u0438\u0434\u0435\u043b\u0438 \u0432 Golang \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u044b \u0434\u043b\u044f \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u044f \u043d\u0430\u0448\u0435\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<p>\u0418-\u0442\u0430\u043a, \u043f\u043e\u0435\u0445\u0430\u043b\u0438.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h2>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438<\/h2>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u0431\u044b\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435<\/p>\n<pre><code>github.com\/andygrunwald\/go-jira v1.13.0 github.com\/go-telegram-bot-api\/telegram-bot-api v4.6.4+incompatible github.com\/gorilla\/mux v1.8.0 github.com\/urfave\/cli\/v2 v2.3.0 go.mongodb.org\/mongo-driver v1.6.0 golang.org\/x\/oauth2 v0.0.0-20210805134026-6f1e6394065a<\/code><\/pre>\n<h2>\u0412\u0445\u043e\u0434\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430<\/h2>\n<p>\u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0441\u0435\u0440\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 urfave\/cli2 &#8212; \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0438 cobra, \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0443\u0442\u0438\u043b\u0438\u0442, \u043d\u043e, \u043f\u043e \u043d\u0430\u0448\u0435\u043c\u0443 \u043c\u043d\u0435\u043d\u0438\u044e, cli2 \u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u043e\u0432 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0431\u043e\u043b\u044c\u0448\u0435, \u0442\u0430\u043c \u043f\u0440\u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 + \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c required, \u0430\u043b\u0438\u0430\u0441\u044b \u0438 \u043c\u043d\u043e\u0433\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435, \u0432\u043e\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0444\u043b\u0430\u0433\u0430 (\u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0443\u0442\u0438\u043b\u0438\u0442\u044b)<\/p>\n<pre><code class=\"go\">type StringFlag struct { Name        string Aliases     []string Usage       string EnvVars     []string FilePath    string Required    bool Hidden      bool TakesFile   bool Value       string DefaultText string Destination *string HasBeenSet  bool }<\/code><\/pre>\n<p>\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"go\">package main import ( \"github.com\/urfave\/cli\/v2\" ) func main() { app := &amp;cli.App{ Flags: []cli.Flag{       \/* \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 dev\/production, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u043c \u044d\u0442\u043e       - \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0431\u0443\u0434\u0443\u0449\u0443\u044e \u0443\u0442\u0438\u043b\u0438\u0442\u0443 \u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c --environment       - \u043b\u0438\u0431\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u044d\u0442\u043e \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f ENVIRONMENT       - \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 production       *\/ &amp;cli.StringFlag{Name: \"environment\", Value: \"production\", Usage: \"environment name\", EnvVars: []string{\"ENVIRONMENT\"}},             \/\/\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0435\u043c \u043b\u043e\u0433\u0438\u043d \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043e\u0442 JIRA, \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u044d\u0442\u0438\u043c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e &amp;cli.StringFlag{Name: \"jira-login\", Usage: \"jira bot login\", EnvVars: []string{\"jira_login\"}}, &amp;cli.StringFlag{Name: \"jira-password\", Usage: \"jira bot password\", EnvVars: []string{\"jira_password\"}},              \/*\u0435\u0441\u0442\u044c \u0438 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u0435\u0441\u043b\u0438 \u0432\u0432\u0435\u0441\u0442\u0438 \u0442\u0430\u043c \u0442\u0435\u043a\u0441\u0442 \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0447\u0442\u043e \u0442\u043e \u0442\u0430\u043a\u043e\u0435:       Incorrect Usage. invalid value \"foo\" for flag -jira-default-search-limit: parse error       *\/ &amp;cli.IntFlag{Name: \"jira-default-search-limit\", Value: 5, Usage: \"jira default search limit\"},              \/*\u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u043e\u0442\u0443, \u0437\u0430\u0434\u0430\u0451\u0442\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 --telegram-permit-users:       --telegram-permit-users foo --telegram-permit-users bar       *\/ &amp;cli.StringSliceFlag{Name: \"telegram-permit-users\", Value: cli.NewStringSlice( \"Paulstrong\", ), Usage: \"telegram permitted users list\"},        \/\/\u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435       &amp;cli.StringFlag{Name: \"mongodb-host\", Usage: \"mongodb server host\/ip\", EnvVars: []string{\"mongodb_host\"}}, &amp;cli.StringFlag{Name: \"mongodb-user\", Usage: \"mongodb server username\", EnvVars: []string{\"mongodb_user\"}}, &amp;cli.StringFlag{Name: \"mongodb-password\", Usage: \"mongodb server password\", EnvVars: []string{\"mongodb_password\"}}, &amp;cli.StringFlag{Name: \"mongodb-name\", Usage: \"mongodb server database name\", EnvVars: []string{\"mongodb_name\"}}, &amp;cli.IntFlag{Name: \"mongodb-port\", Value: 27017, Usage: \"mongodb server database name\"}, }, Action: func(context *cli.Context) error {       \/\/\u0443 \u043d\u0430\u0441 \u0443 \u0434\u0435\u043c\u043e\u043d\u0430 \u0435\u0441\u0442\u044c \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u043d\u0430 \u043a\u043e\u0440\u043d\u0435\u0432\u0430\u044f \"\u043a\u043e\u043c\u0430\u043d\u0434\u0430\", \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0435\u0451 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443       \/\/\u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0431\u0443\u0434\u0443\u0449\u0435\u0433\u043e \u0434\u0435\u043c\u043e\u043d\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0435\u043c\u0443 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438       d := daemon.NewDaemon(context)       \/\/\u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u0435\u043c\u043e\u043d\u0430 (\u043f\u043e\u0437\u0436\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0442\u0430\u043c)       if err := d.Init(); err != nil {         log.Fatalln(\"daemon initialization error\", err)       }       \/\/\u0438, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0434\u0435\u043c\u043e\u043d\u0430       return d.Run() }, }   \/\/\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 cli2 _ = app.Run(os.Args) } <\/code><\/pre>\n<p>\u0412 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0443\u0431\u0440\u0430\u043b \u0438\u0445 \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0437\u0430\u0441\u043e\u0440\u044f\u0442\u044c \u044d\u0444\u0438\u0440. \u041e\u0431\u0449\u0438\u0439 \u0441\u043c\u044b\u0441\u043b, \u0434\u0443\u043c\u0430\u044e, \u043f\u043e\u043d\u044f\u0442\u0435\u043d, \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u043e\u0442\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0443\u0442\u0451\u043c \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u0445 \u0443\u0442\u0438\u043b\u0438\u0442\u044b, \u043b\u0438\u0431\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/p>\n<h2>\u041a\u043e\u043d\u0444\u0438\u0433<\/h2>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f context \u043e\u0442 cli2 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 &#8212; \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u0438 \u044d\u0442\u043e \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u043b\u0438\u0431\u043e \u043a\u043e\u043f\u0438\u043f\u0430\u0441\u0442\u0438\u0442\u044c \u0432 \u043a\u043e\u0434\u0435, \u043b\u0438\u0431\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u0445, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u043e\u0442 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438\u043c\u0435\u043d\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"go\">context.String(\"environment\")<\/code><\/pre>\n<p>\u043c\u044b \u044d\u0442\u043e \u0434\u0435\u043b\u043e \u043e\u0431\u0435\u0440\u043d\u0443\u043b\u0438 \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442:<\/p>\n<pre><code class=\"go\">type UrfaveContext struct { *cli.Context }  func NewUrfaveContext(context *cli.Context) *UrfaveContext { ret := &amp;UrfaveContext{} ret.Context = context return ret }  func (c *UrfaveContext) Environment() string { return c.Context.String(\"environment\") }<\/code><\/pre>\n<p>\u0438 \u0434\u0430\u043b\u0435\u0435 \u043c\u044b \u043f\u043e\u0434\u0430\u0451\u043c \u0432 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0434\u0435\u043c\u043e\u043d\u0430 \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0444\u0438\u0433:<\/p>\n<pre><code class=\"go\">d := daemon.NewDaemon(NewUrfaveContext(context))<\/code><\/pre>\n<p>\u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0435\u043c\u043e\u043d\u0430 \u043c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433 \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0438 \u0434\u0430\u043b\u044c\u0448\u0435 \u044d\u0442\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0447\u0435\u043d\u044c \u0434\u0430\u0436\u0435 \u0443\u0434\u043e\u0431\u043d\u043e:<\/p>\n<pre><code class=\"go\">type Daemon struct { config    interfaces.IConfig }  func NewDaemon(config interfaces.IConfig) *Daemon {   return &amp;Daemon{config} }  func (d *Daemon) PrinEnv() {   fmt.Println(d.config.Environment()) }<\/code><\/pre>\n<p>\u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 IConfig, \u043c\u044b \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043e\u0441\u043e\u0437\u043d\u0430\u043d\u043d\u043e, \u0442.\u043a. \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u0447\u0442\u043e-\u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u043a\u043e\u043b\u044c\u043d\u043e\u0435, \u0447\u0435\u043c cli2, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043a\u0442\u043e-\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c cobra \u0432\u043c\u0435\u0441\u0442\u043e cli2, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u044b, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435, \u0430 \u043d\u0430 \u0447\u0451\u043c \u0438\u043c\u0435\u043d\u043d\u043e &#8212; \u0440\u0435\u0448\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e:<\/p>\n<pre><code class=\"go\">type IConfig interface { Environment() string }<\/code><\/pre>\n<h2>\u0427\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435?<\/h2>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u043f\u043e\u0434\u043a\u0430\u043f\u043e\u0442\u043d\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435 \u0434\u0435\u043c\u043e\u043d\u0430. \u041e\u043d \u0443 \u043d\u0430\u0441 \u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b:<\/p>\n<pre><code class=\"go\">type Daemon struct { shutdown  chan struct{} engines []interfaces.IEngine config    interfaces.IConfig db        interfaces.IDatabase }<\/code><\/pre>\n<ul>\n<li>\n<p>shutdown &#8212; \u043a\u0430\u043d\u0430\u043b, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0448\u043b\u0451\u0442\u0441\u044f struct{}{} \u043f\u0440\u0438 \u043e\u0442\u043b\u043e\u0432\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u0438\u0441\u0430\u043b\u0438 \u0431\u043e\u0442\u0430, \u043c\u044b \u0435\u0449\u0435 \u043d\u0435 \u0437\u043d\u0430\u043b\u0438 \u043f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c context.Context, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0438\u0441\u0430\u043b\u0438 \u043a\u0430\u043a \u043c\u043e\u0433\u043b\u0438<\/p>\n<\/li>\n<li>\n<p>engine &#8212; \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 &#171;\u0434\u0432\u0438\u0436\u043e\u043a&#187;, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 telegram, viber, \u0442\u043e \u0435\u0441\u0442\u044c \u043c\u0435\u043d\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u044b, \u043a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0434\u0432\u0438\u0436\u043a\u043e\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0447\u0442\u043e-\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0430 \u0444\u043e\u043d\u0435, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0440\u0438\u0441\u044b\u043b\u0430\u0435\u0442 \u0432 \u043e\u0434\u0438\u043d \u0438\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u0434\u0432\u0438\u0436\u043a\u043e\u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0432\u043e\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b, \u0432 \u043e\u0431\u0449\u0435\u043c \u0438 \u0446\u0435\u043b\u043e\u043c, \u044d\u0442\u043e &#8212; \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0444\u043e\u043d\u0435<\/p>\n<\/li>\n<li>\n<p>config &#8212; \u043c\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u043c \u0447\u0442\u043e \u044d\u0442\u043e<\/p>\n<\/li>\n<li>\n<p>db &#8212; \u043e\u0431\u044a\u0435\u043a\u0442 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0431\u0434 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f oauth2 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430, \u043c\u044b \u043f\u043e\u0434\u0430\u0451\u043c \u044d\u0442\u043e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 &#171;\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440&#187; \u0434\u0435\u043c\u043e\u043d\u0430 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443, \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u043e\u043d\u0433\u0430, \u043b\u0438\u0431\u043e \u0431\u044b\u0442\u044c mysql, \u0438 \u0434\u0440., \u0433\u043b\u0430\u0432\u043d\u043e\u0435, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"go\">type IDatabase interface { GetToken() (*oauth2.Token, error) \/\/\u0447\u0438\u0442\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u0438\u0437 \u0431\u0430\u0437\u044b SetToken(t *oauth2.Token) error \/\/\u043a\u043b\u0430\u0434\u0451\u043c \u0442\u043e\u043a\u0435\u043d \u0432 \u0431\u0430\u0437\u0443 }<\/code><\/pre>\n<p>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u0432\u0438\u0436\u043a\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a<\/p>\n<pre><code class=\"go\">type IEngine interface { AddShutdownChan(ch chan struct{}) Run(wg *sync.WaitGroup) Reply(update IUpdate) CheckAcl(update IUpdate, cmd ICommand) (result bool) SetManager(engine IManager) IEngine GetManager() IManager SetName(name string) IEngine GetName() string SetDaemon(d IDaemon) IEngine GetDaemon() IDaemon GetConfig() IConfig GetDB() IDatabase }<\/code><\/pre>\n<p>\u0422\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u0434\u0432\u0438\u0436\u043a\u0443 \u0438\u043c\u044f, \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u0435\u043c\u043e\u043d\u0430 \u0438 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 (\u0441\u043a\u043e\u0440\u043e \u043f\u043e\u0434\u043e\u0439\u0434\u0451\u043c \u043a \u044d\u0442\u043e\u043c\u0443), \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433. \u0412\u0441\u0451 \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0432\u044f\u0437\u0430\u0442\u044c \u0434\u0432\u0438\u0436\u043a\u0438 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0438 \u043c\u043e\u0433\u043b\u0438 \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433-\u043a-\u0434\u0440\u0443\u0433\u0443 \u043f\u043e \u0438\u043c\u0435\u043d\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0434\u0432\u0438\u0436\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043c\u043e\u0442\u0440\u0438\u0442 \u0442\u0438\u043a\u0435\u0442\u044b \u043e\u0442 \u0441\u0430\u043f\u043f\u043e\u0440\u0442\u0430, \u0430 \u043f\u043e\u0442\u043e\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0434\u0432\u0438\u0436\u043a\u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u0447\u0430\u0442 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0438.<\/p>\n<h2>\u041c\u0435\u043d\u0435\u0434\u0436\u0435\u0440<\/h2>\n<p>\u041c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u0434\u0432\u0438\u0436\u043a\u043e\u0432 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0445 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043c\u043e\u0434\u0435\u043b\u044c. \u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043c\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 \u043d\u0430 \u0432\u0441\u0435 \u0434\u0432\u0438\u0436\u043a\u0438, \u043d\u043e \u043f\u043e\u0442\u043e\u043c \u0440\u0435\u0448\u0438\u043b\u0438, \u0447\u0442\u043e \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0434\u0432\u0438\u0436\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u0432\u043e\u0439 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u043f\u0435\u0446\u044d\u0444\u0444\u0435\u043a\u0442\u043e\u0432, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0432 &#171;\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430\u0445&#187; \u0434\u0432\u0438\u0436\u043a\u043e\u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e:<\/p>\n<pre><code class=\"go\">type CorpMessenger struct { name         string daemon       interfaces.IDaemon manager      interfaces.IManager }  func New(d interfaces.IDaemon, name string) interfaces.ICorpMessengerEngine { a := &amp;CorpMessenger{daemon: d, name: name} a.manager = NewManager(a) return a }<\/code><\/pre>\n<p>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c<\/p>\n<pre><code class=\"go\">type IManager interface { SetInitialController(c IInitialController) Route(update IUpdate) SetEngine(e IEngine) IManager GetEngine() IEngine GetConfig() IConfig GetDB() IDatabase }<\/code><\/pre>\n<p>\u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/p>\n<h2>\u041a\u0430\u043a \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f<\/h2>\n<p>\u0418\u0442\u0430\u043a, \u043c\u044b \u043d\u0430\u0443\u0447\u0438\u043b\u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043d\u0430\u0448\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0443\u0442 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443, \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u0432\u043e\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0441\u043c\u044b\u0441\u043b \u0442\u0443\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u0431\u0430\u0439\u0442 \u043e\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, id \u0447\u0430\u0442\u0430, \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043f\u043e\u0434 \u044d\u0442\u043e \u0434\u0435\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/p>\n<pre><code class=\"go\">type IUpdate interface { Reply(text string) CheckAcl(cmd ICommand) (result bool) GetText() (result string) GetEngine() (result IEngine) GetChatID() (result string) GetMessageID() (result string) GetReplyText() (result string) GetUserName() (result string) GetUserDescription() (result string) }<\/code><\/pre>\n<p>\u043f\u0440\u0438\u043d\u044f\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043c\u044b \u0443\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438 \u043e\u0442\u0434\u0430\u0451\u043c \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0443 \u043d\u0430 \u0440\u043e\u0443\u0442\u0438\u043d\u0433<\/p>\n<pre><code>upd := update.NewUpdate(corpMsgObj, text, msgId, chanId, directId, userDescription,) corpMsgObj.manager.Route(upd)<\/code><\/pre>\n<p>\u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0443 \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443, \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u043e\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f (acl), \u0430 \u0434\u0430\u043b\u044c\u0448\u0435 \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430\u0448\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 (\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440)<\/p>\n<p>\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c<\/p>\n<pre><code class=\"go\">type IController interface { Call(cmd<\/code><\/pre>\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-328980","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/328980","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=328980"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/328980\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=328980"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=328980"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=328980"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}