{"action":"created","comment":{"url":"https://api.github.com/repos/actix/examples/pulls/comments/217979313","pull_request_review_id":155812920,"id":217979313,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxNzk3OTMxMw==","diff_hunk":"@@ -0,0 +1,156 @@\n+#[macro_use]\n+extern crate actix;\n+extern crate actix_web;\n+extern crate actix_broker;\n+extern crate futures;\n+extern crate rand;\n+\n+use actix::prelude::*;\n+use actix::fut;\n+use actix_web::server::HttpServer;\n+use actix_web::{fs, http, ws, App, Error, HttpRequest, HttpResponse};\n+use actix_broker::BrokerIssue;\n+use futures::Future;\n+\n+mod server;\n+use server::*;\n+\n+fn chat_route(req: &HttpRequest<()>) -> Result<HttpResponse, Error> {\n+    ws::start(req, WsChatSession::default())\n+}\n+\n+#[derive(Default)]\n+struct WsChatSession {\n+    id: usize,\n+    room: String,\n+    name: Option<String>,\n+}\n+\n+impl WsChatSession {\n+    fn join_room(&mut self, room_name: &str, ctx: &mut ws::WebsocketContext<Self>) {\n+        let room_name = room_name.to_owned();\n+        // First send a leave message for the current room\n+        let leave_msg = LeaveRoom(self.room.clone(), self.id);\n+        self.issue_sync(leave_msg, ctx);\n+        // Then send a join message for the new room\n+        let join_msg = JoinRoom(\n+            room_name.to_owned(),\n+            self.name.clone(),\n+            ctx.address().recipient());\n+\n+        WsChatServer::from_registry()\n+            .send(join_msg)\n+            .map_err(|_| ())\n+            .into_actor(self)\n+            .map(|id, act, _| {\n+                act.id = id;\n+                act.room = room_name;\n+            })\n+            .wait(ctx);\n+    }\n+\n+    fn list_rooms(&mut self, ctx: &mut ws::WebsocketContext<Self>) {\n+        WsChatServer::from_registry()\n+            .send(ListRooms)\n+            .into_actor(self)\n+            .then(|res, _, ctx| {\n+                if let Ok(rooms) = res {\n+                    for room in rooms {\n+                        ctx.text(room);\n+                    }\n+                }\n+                fut::ok(())\n+            }).wait(ctx);\n+    }\n+\n+    fn send_msg(&self, msg: &str) {\n+        let content = format!(\"{}: {}\",\n+                              self.name.clone().unwrap_or(\"anon\".to_string()),\n+                              msg);\n+        let msg = SendMessage(self.room.clone(), self.id, content);\n+        self.issue_async(msg);\n+    }\n+}\n+\n+impl Actor for WsChatSession {\n+    type Context = ws::WebsocketContext<Self>;\n+\n+    fn started(&mut self, ctx: &mut Self::Context) {\n+        self.join_room(\"Main\", ctx);\n+    }\n+\n+    fn stopped(&mut self, _ctx: &mut Self::Context) {\n+        println!(\"WsChatSession stopped for {}({}) in room {}\",\n+            self.name.clone().unwrap_or(\"anon\".to_string()),\n+            self.id,\n+            self.room);\n+    }\n+}\n+\n+impl Handler<ChatMessage> for WsChatSession {\n+    type Result = (); \n+\n+    fn handle(&mut self, msg: ChatMessage, ctx: &mut Self::Context) {\n+        ctx.text(msg.0);\n+    }\n+}\n+\n+impl StreamHandler<ws::Message, ws::ProtocolError> for WsChatSession {\n+    fn handle(&mut self, msg: ws::Message, ctx: &mut Self::Context) {\n+        println!(\"WEBSOCKET MESSAGE: {:?}\", msg);\n+        match msg {\n+            ws::Message::Text(text) => {\n+                let m = text.trim();\n+                if m.starts_with('/') {\n+                    let v: Vec<&str> = m.splitn(2, ' ').collect();\n+                    match v[0] {\n+                        \"/list\" => self.list_rooms(ctx),\n+                        \"/join\" => {\n+                            if v.len() == 2 {\n+                                self.join_room(v[1], ctx);\n+                                ctx.text(\"joined\");\n+                            } else {\n+                                ctx.text(\"!!! room name is required\");\n+                            }\n+                        }\n+                        \"/name\" => {\n+                            if v.len() == 2 {\n+                                self.name = Some(v[1].to_owned());\n+                                ctx.text(format!(\"name changed to: {}\", v[1]));\n+                            } else {\n+                                ctx.text(\"!!! name is required\");\n+                            }\n+                        }\n+                        _ => ctx.text(format!(\"!!! unknown command: {:?}\", m)),\n+                    }\n+                    return;\n+                } \n+                self.send_msg(m);\n+            }\n+            ws::Message::Close(_) => {\n+                ctx.stop();\n+            },\n+            _ => {},\n+        }\n+    }\n+}\n+\n+fn main() {\n+    let sys = actix::System::new(\"websocket-broker-example\");\n+\n+    HttpServer::new(move || {\n+        App::new()\n+            .resource(\"/\", |r| r.method(http::Method::GET).f(|_| {","path":"websocket-chat-broker/src/main.rs","position":143,"original_position":143,"commit_id":"f7fe267bcb668eb573bf272315ec77cdef614001","original_commit_id":"f7fe267bcb668eb573bf272315ec77cdef614001","user":{"login":"DoumanAsh","id":5676053,"node_id":"MDQ6VXNlcjU2NzYwNTM=","avatar_url":"https://avatars3.githubusercontent.com/u/5676053?v=4","gravatar_id":"","url":"https://api.github.com/users/DoumanAsh","html_url":"https://github.com/DoumanAsh","followers_url":"https://api.github.com/users/DoumanAsh/followers","following_url":"https://api.github.com/users/DoumanAsh/following{/other_user}","gists_url":"https://api.github.com/users/DoumanAsh/gists{/gist_id}","starred_url":"https://api.github.com/users/DoumanAsh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DoumanAsh/subscriptions","organizations_url":"https://api.github.com/users/DoumanAsh/orgs","repos_url":"https://api.github.com/users/DoumanAsh/repos","events_url":"https://api.github.com/users/DoumanAsh/events{/privacy}","received_events_url":"https://api.github.com/users/DoumanAsh/received_events","type":"User","site_admin":false},"body":"The `/static` directory is already served below?\r\nMaybe you could just rename it as `index.html` and server the whole static directory at `/`?","created_at":"2018-09-17T08:13:43Z","updated_at":"2018-09-17T08:18:11Z","html_url":"https://github.com/actix/examples/pull/44#discussion_r217979313","pull_request_url":"https://api.github.com/repos/actix/examples/pulls/44","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/actix/examples/pulls/comments/217979313"},"html":{"href":"https://github.com/actix/examples/pull/44#discussion_r217979313"},"pull_request":{"href":"https://api.github.com/repos/actix/examples/pulls/44"}}},"pull_request":{"url":"https://api.github.com/repos/actix/examples/pulls/44","id":215828813,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE1ODI4ODEz","html_url":"https://github.com/actix/examples/pull/44","diff_url":"https://github.com/actix/examples/pull/44.diff","patch_url":"https://github.com/actix/examples/pull/44.patch","issue_url":"https://api.github.com/repos/actix/examples/issues/44","number":44,"state":"open","locked":false,"title":"WebSocket Chat example using actix-broker","user":{"login":"Chris-Ricketts","id":6156768,"node_id":"MDQ6VXNlcjYxNTY3Njg=","avatar_url":"https://avatars0.githubusercontent.com/u/6156768?v=4","gravatar_id":"","url":"https://api.github.com/users/Chris-Ricketts","html_url":"https://github.com/Chris-Ricketts","followers_url":"https://api.github.com/users/Chris-Ricketts/followers","following_url":"https://api.github.com/users/Chris-Ricketts/following{/other_user}","gists_url":"https://api.github.com/users/Chris-Ricketts/gists{/gist_id}","starred_url":"https://api.github.com/users/Chris-Ricketts/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Chris-Ricketts/subscriptions","organizations_url":"https://api.github.com/users/Chris-Ricketts/orgs","repos_url":"https://api.github.com/users/Chris-Ricketts/repos","events_url":"https://api.github.com/users/Chris-Ricketts/events{/privacy}","received_events_url":"https://api.github.com/users/Chris-Ricketts/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-09-16T15:19:27Z","updated_at":"2018-09-17T08:18:11Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1e40ee0f2eade701f8e81f565de12ede726e70a2","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/actix/examples/pulls/44/commits","review_comments_url":"https://api.github.com/repos/actix/examples/pulls/44/comments","review_comment_url":"https://api.github.com/repos/actix/examples/pulls/comments{/number}","comments_url":"https://api.github.com/repos/actix/examples/issues/44/comments","statuses_url":"https://api.github.com/repos/actix/examples/statuses/f7fe267bcb668eb573bf272315ec77cdef614001","head":{"label":"Chris-Ricketts:master","ref":"master","sha":"f7fe267bcb668eb573bf272315ec77cdef614001","user":{"login":"Chris-Ricketts","id":6156768,"node_id":"MDQ6VXNlcjYxNTY3Njg=","avatar_url":"https://avatars0.githubusercontent.com/u/6156768?v=4","gravatar_id":"","url":"https://api.github.com/users/Chris-Ricketts","html_url":"https://github.com/Chris-Ricketts","followers_url":"https://api.github.com/users/Chris-Ricketts/followers","following_url":"https://api.github.com/users/Chris-Ricketts/following{/other_user}","gists_url":"https://api.github.com/users/Chris-Ricketts/gists{/gist_id}","starred_url":"https://api.github.com/users/Chris-Ricketts/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Chris-Ricketts/subscriptions","organizations_url":"https://api.github.com/users/Chris-Ricketts/orgs","repos_url":"https://api.github.com/users/Chris-Ricketts/repos","events_url":"https://api.github.com/users/Chris-Ricketts/events{/privacy}","received_events_url":"https://api.github.com/users/Chris-Ricketts/received_events","type":"User","site_admin":false},"repo":{"id":149003350,"node_id":"MDEwOlJlcG9zaXRvcnkxNDkwMDMzNTA=","name":"examples","full_name":"Chris-Ricketts/examples","private":false,"owner":{"login":"Chris-Ricketts","id":6156768,"node_id":"MDQ6VXNlcjYxNTY3Njg=","avatar_url":"https://avatars0.githubusercontent.com/u/6156768?v=4","gravatar_id":"","url":"https://api.github.com/users/Chris-Ricketts","html_url":"https://github.com/Chris-Ricketts","followers_url":"https://api.github.com/users/Chris-Ricketts/followers","following_url":"https://api.github.com/users/Chris-Ricketts/following{/other_user}","gists_url":"https://api.github.com/users/Chris-Ricketts/gists{/gist_id}","starred_url":"https://api.github.com/users/Chris-Ricketts/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Chris-Ricketts/subscriptions","organizations_url":"https://api.github.com/users/Chris-Ricketts/orgs","repos_url":"https://api.github.com/users/Chris-Ricketts/repos","events_url":"https://api.github.com/users/Chris-Ricketts/events{/privacy}","received_events_url":"https://api.github.com/users/Chris-Ricketts/received_events","type":"User","site_admin":false},"html_url":"https://github.com/Chris-Ricketts/examples","description":"Actix web examples","fork":true,"url":"https://api.github.com/repos/Chris-Ricketts/examples","forks_url":"https://api.github.com/repos/Chris-Ricketts/examples/forks","keys_url":"https://api.github.com/repos/Chris-Ricketts/examples/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Chris-Ricketts/examples/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Chris-Ricketts/examples/teams","hooks_url":"https://api.github.com/repos/Chris-Ricketts/examples/hooks","issue_events_url":"https://api.github.com/repos/Chris-Ricketts/examples/issues/events{/number}","events_url":"https://api.github.com/repos/Chris-Ricketts/examples/events","assignees_url":"https://api.github.com/repos/Chris-Ricketts/examples/assignees{/user}","branches_url":"https://api.github.com/repos/Chris-Ricketts/examples/branches{/branch}","tags_url":"https://api.github.com/repos/Chris-Ricketts/examples/tags","blobs_url":"https://api.github.com/repos/Chris-Ricketts/examples/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Chris-Ricketts/examples/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Chris-Ricketts/examples/git/refs{/sha}","trees_url":"https://api.github.com/repos/Chris-Ricketts/examples/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Chris-Ricketts/examples/statuses/{sha}","languages_url":"https://api.github.com/repos/Chris-Ricketts/examples/languages","stargazers_url":"https://api.github.com/repos/Chris-Ricketts/examples/stargazers","contributors_url":"https://api.github.com/repos/Chris-Ricketts/examples/contributors","subscribers_url":"https://api.github.com/repos/Chris-Ricketts/examples/subscribers","subscription_url":"https://api.github.com/repos/Chris-Ricketts/examples/subscription","commits_url":"https://api.github.com/repos/Chris-Ricketts/examples/commits{/sha}","git_commits_url":"https://api.github.com/repos/Chris-Ricketts/examples/git/commits{/sha}","comments_url":"https://api.github.com/repos/Chris-Ricketts/examples/comments{/number}","issue_comment_url":"https://api.github.com/repos/Chris-Ricketts/examples/issues/comments{/number}","contents_url":"https://api.github.com/repos/Chris-Ricketts/examples/contents/{+path}","compare_url":"https://api.github.com/repos/Chris-Ricketts/examples/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Chris-Ricketts/examples/merges","archive_url":"https://api.github.com/repos/Chris-Ricketts/examples/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Chris-Ricketts/examples/downloads","issues_url":"https://api.github.com/repos/Chris-Ricketts/examples/issues{/number}","pulls_url":"https://api.github.com/repos/Chris-Ricketts/examples/pulls{/number}","milestones_url":"https://api.github.com/repos/Chris-Ricketts/examples/milestones{/number}","notifications_url":"https://api.github.com/repos/Chris-Ricketts/examples/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Chris-Ricketts/examples/labels{/name}","releases_url":"https://api.github.com/repos/Chris-Ricketts/examples/releases{/id}","deployments_url":"https://api.github.com/repos/Chris-Ricketts/examples/deployments","created_at":"2018-09-16T14:26:33Z","updated_at":"2018-09-17T07:09:59Z","pushed_at":"2018-09-17T07:09:57Z","git_url":"git://github.com/Chris-Ricketts/examples.git","ssh_url":"git@github.com:Chris-Ricketts/examples.git","clone_url":"https://github.com/Chris-Ricketts/examples.git","svn_url":"https://github.com/Chris-Ricketts/examples","homepage":"","size":757,"stargazers_count":1,"watchers_count":1,"language":"Rust","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"actix:master","ref":"master","sha":"6b68cfc5292638785998409903c5d4a0a1ac5206","user":{"login":"actix","id":32776943,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMyNzc2OTQz","avatar_url":"https://avatars3.githubusercontent.com/u/32776943?v=4","gravatar_id":"","url":"https://api.github.com/users/actix","html_url":"https://github.com/actix","followers_url":"https://api.github.com/users/actix/followers","following_url":"https://api.github.com/users/actix/following{/other_user}","gists_url":"https://api.github.com/users/actix/gists{/gist_id}","starred_url":"https://api.github.com/users/actix/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/actix/subscriptions","organizations_url":"https://api.github.com/users/actix/orgs","repos_url":"https://api.github.com/users/actix/repos","events_url":"https://api.github.com/users/actix/events{/privacy}","received_events_url":"https://api.github.com/users/actix/received_events","type":"Organization","site_admin":false},"repo":{"id":129324660,"node_id":"MDEwOlJlcG9zaXRvcnkxMjkzMjQ2NjA=","name":"examples","full_name":"actix/examples","private":false,"owner":{"login":"actix","id":32776943,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMyNzc2OTQz","avatar_url":"https://avatars3.githubusercontent.com/u/32776943?v=4","gravatar_id":"","url":"https://api.github.com/users/actix","html_url":"https://github.com/actix","followers_url":"https://api.github.com/users/actix/followers","following_url":"https://api.github.com/users/actix/following{/other_user}","gists_url":"https://api.github.com/users/actix/gists{/gist_id}","starred_url":"https://api.github.com/users/actix/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/actix/subscriptions","organizations_url":"https://api.github.com/users/actix/orgs","repos_url":"https://api.github.com/users/actix/repos","events_url":"https://api.github.com/users/actix/events{/privacy}","received_events_url":"https://api.github.com/users/actix/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/actix/examples","description":"Actix web examples","fork":false,"url":"https://api.github.com/repos/actix/examples","forks_url":"https://api.github.com/repos/actix/examples/forks","keys_url":"https://api.github.com/repos/actix/examples/keys{/key_id}","collaborators_url":"https://api.github.com/repos/actix/examples/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/actix/examples/teams","hooks_url":"https://api.github.com/repos/actix/examples/hooks","issue_events_url":"https://api.github.com/repos/actix/examples/issues/events{/number}","events_url":"https://api.github.com/repos/actix/examples/events","assignees_url":"https://api.github.com/repos/actix/examples/assignees{/user}","branches_url":"https://api.github.com/repos/actix/examples/branches{/branch}","tags_url":"https://api.github.com/repos/actix/examples/tags","blobs_url":"https://api.github.com/repos/actix/examples/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/actix/examples/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/actix/examples/git/refs{/sha}","trees_url":"https://api.github.com/repos/actix/examples/git/trees{/sha}","statuses_url":"https://api.github.com/repos/actix/examples/statuses/{sha}","languages_url":"https://api.github.com/repos/actix/examples/languages","stargazers_url":"https://api.github.com/repos/actix/examples/stargazers","contributors_url":"https://api.github.com/repos/actix/examples/contributors","subscribers_url":"https://api.github.com/repos/actix/examples/subscribers","subscription_url":"https://api.github.com/repos/actix/examples/subscription","commits_url":"https://api.github.com/repos/actix/examples/commits{/sha}","git_commits_url":"https://api.github.com/repos/actix/examples/git/commits{/sha}","comments_url":"https://api.github.com/repos/actix/examples/comments{/number}","issue_comment_url":"https://api.github.com/repos/actix/examples/issues/comments{/number}","contents_url":"https://api.github.com/repos/actix/examples/contents/{+path}","compare_url":"https://api.github.com/repos/actix/examples/compare/{base}...{head}","merges_url":"https://api.github.com/repos/actix/examples/merges","archive_url":"https://api.github.com/repos/actix/examples/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/actix/examples/downloads","issues_url":"https://api.github.com/repos/actix/examples/issues{/number}","pulls_url":"https://api.github.com/repos/actix/examples/pulls{/number}","milestones_url":"https://api.github.com/repos/actix/examples/milestones{/number}","notifications_url":"https://api.github.com/repos/actix/examples/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/actix/examples/labels{/name}","releases_url":"https://api.github.com/repos/actix/examples/releases{/id}","deployments_url":"https://api.github.com/repos/actix/examples/deployments","created_at":"2018-04-13T00:07:42Z","updated_at":"2018-09-13T16:26:45Z","pushed_at":"2018-09-17T07:09:59Z","git_url":"git://github.com/actix/examples.git","ssh_url":"git@github.com:actix/examples.git","clone_url":"https://github.com/actix/examples.git","svn_url":"https://github.com/actix/examples","homepage":"","size":734,"stargazers_count":155,"watchers_count":155,"language":"Rust","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":38,"mirror_url":null,"archived":false,"open_issues_count":4,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":38,"open_issues":4,"watchers":155,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/actix/examples/pulls/44"},"html":{"href":"https://github.com/actix/examples/pull/44"},"issue":{"href":"https://api.github.com/repos/actix/examples/issues/44"},"comments":{"href":"https://api.github.com/repos/actix/examples/issues/44/comments"},"review_comments":{"href":"https://api.github.com/repos/actix/examples/pulls/44/comments"},"review_comment":{"href":"https://api.github.com/repos/actix/examples/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/actix/examples/pulls/44/commits"},"statuses":{"href":"https://api.github.com/repos/actix/examples/statuses/f7fe267bcb668eb573bf272315ec77cdef614001"}},"author_association":"NONE"}}
{"actor":{"display_login":"DoumanAsh"}}