{"action":"created","comment":{"url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/pulls/comments/65797035","id":65797035,"diff_hunk":"@@ -0,0 +1,141 @@\n+//\n+//  WebServerManager.swift\n+//  PopcornTime\n+//\n+//  Created by Erick Smith on 6/3/16.\n+//  Copyright © 2016 PopcornTime. All rights reserved.\n+//\n+\n+import Foundation\n+import GCDWebServer\n+\n+\n+class WebServerManager: NSObject {\n+    var webServer:GCDWebServer!\n+    \n+    class func sharedManager() -> WebServerManager {\n+        struct Struct {\n+            static let Instance = WebServerManager()\n+        }\n+        return Struct.Instance\n+    }\n+    \n+    override init(){\n+        super.init()\n+    }\n+    \n+    func startServer(port: UInt){\n+        \n+        if let _ = self.webServer {\n+            self.webServer.stop()\n+        } else {\n+            self.webServer = GCDWebServer()\n+        }\n+        \n+        let paths = NSSearchPathForDirectoriesInDomains(.CachesDirectory, .UserDomainMask, true)\n+        if let cachesDirectory = paths.first {\n+            do {\n+                let fileManager = NSFileManager.defaultManager()\n+                var isDir : ObjCBool = false\n+                var downloadsExists = false\n+                let downloadsDirectory = cachesDirectory.stringByAppendingPathComponent(\"Downloads\")\n+                if fileManager.fileExistsAtPath(downloadsDirectory, isDirectory: &isDir){\n+                    if isDir {\n+                        downloadsExists = true;\n+                    }\n+                }\n+                \n+                if !downloadsExists {\n+                    try NSFileManager.defaultManager().createDirectoryAtPath(downloadsDirectory, withIntermediateDirectories: false, attributes: nil)\n+                }\n+            \n+                webServer.addGETHandlerForBasePath(\"/\", directoryPath: downloadsDirectory, indexFilename: nil, cacheAge: 3600, allowRangeRequests: true)\n+                webServer.startWithPort(port, bonjourName: \"PopcornTimeTV\")\n+                \n+            } catch let error as NSError {\n+                print(\"Error finding Downloads: \\(error)\");\n+            }\n+        }\n+    }\n+    \n+    func stopServer(){\n+        if let _ = self.webServer {\n+            self.webServer.stop();\n+        }\n+    }\n+    \n+    // Return IP address of WiFi interface (en0) as a String, or `nil`\n+    func getWiFiAddress() -> String? {\n+        var address : String?\n+        \n+        // Get list of all interfaces on the local machine:\n+        var ifaddr : UnsafeMutablePointer<ifaddrs> = nil\n+        if getifaddrs(&ifaddr) == 0 {\n+            \n+            // For each interface ...\n+            var ptr = ifaddr\n+            while ptr != nil {\n+                defer { ptr = ptr.memory.ifa_next }\n+                \n+                let interface = ptr.memory\n+                \n+                // Check for IPv4 or IPv6 interface:\n+                let addrFamily = interface.ifa_addr.memory.sa_family\n+                if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {\n+                    \n+                    // Check interface name:\n+                    if let name = String.fromCString(interface.ifa_name) where name == \"en0\" {\n+                        \n+                        // Convert interface address to a human readable string:\n+                        var addr = interface.ifa_addr.memory\n+                        var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)\n+                        getnameinfo(&addr, socklen_t(interface.ifa_addr.memory.sa_len),\n+                                    &hostname, socklen_t(hostname.count),\n+                                    nil, socklen_t(0), NI_NUMERICHOST)\n+                        address = String.fromCString(hostname)\n+                    }\n+                }\n+            }\n+            freeifaddrs(ifaddr)\n+        }\n+        \n+        return address\n+    }\n+    \n+    func getLANAddress() -> String? {\n+        var address : String?\n+        \n+        // Get list of all interfaces on the local machine:\n+        var ifaddr : UnsafeMutablePointer<ifaddrs> = nil\n+        if getifaddrs(&ifaddr) == 0 {\n+            \n+            // For each interface ...\n+            var ptr = ifaddr\n+            while ptr != nil {\n+                defer { ptr = ptr.memory.ifa_next }\n+                \n+                let interface = ptr.memory\n+                \n+                // Check for IPv4 or IPv6 interface:\n+                let addrFamily = interface.ifa_addr.memory.sa_family\n+                if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {\n+                    \n+                    // Check interface name:\n+                    if let name = String.fromCString(interface.ifa_name) where name == \"en1\" {\n+                        \n+                        // Convert interface address to a human readable string:\n+                        var addr = interface.ifa_addr.memory\n+                        var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)\n+                        getnameinfo(&addr, socklen_t(interface.ifa_addr.memory.sa_len),\n+                                    &hostname, socklen_t(hostname.count),\n+                                    nil, socklen_t(0), NI_NUMERICHOST)\n+                        address = String.fromCString(hostname)\n+                    }\n+                }\n+            }\n+            freeifaddrs(ifaddr)\n+        }\n+        ","path":"PopcornTime/Managers/WebServerManager.swift","position":101,"original_position":138,"commit_id":"b281eba93b2fd1033f2e46fd502f51e8fa5dce5b","original_commit_id":"b281eba93b2fd1033f2e46fd502f51e8fa5dce5b","user":{"login":"houndci-bot","id":6697940,"avatar_url":"https://avatars.githubusercontent.com/u/6697940?v=3","gravatar_id":"","url":"https://api.github.com/users/houndci-bot","html_url":"https://github.com/houndci-bot","followers_url":"https://api.github.com/users/houndci-bot/followers","following_url":"https://api.github.com/users/houndci-bot/following{/other_user}","gists_url":"https://api.github.com/users/houndci-bot/gists{/gist_id}","starred_url":"https://api.github.com/users/houndci-bot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/houndci-bot/subscriptions","organizations_url":"https://api.github.com/users/houndci-bot/orgs","repos_url":"https://api.github.com/users/houndci-bot/repos","events_url":"https://api.github.com/users/houndci-bot/events{/privacy}","received_events_url":"https://api.github.com/users/houndci-bot/received_events","type":"User","site_admin":false},"body":"Trailing Whitespace Violation: Lines should not have trailing whitespace. (trailing_whitespace)","created_at":"2016-06-04T04:17:00Z","updated_at":"2016-06-04T04:17:00Z","html_url":"https://github.com/PopcornTimeTV/PopcornTimeTV/pull/160#discussion_r65797035","pull_request_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/pulls/160","_links":{"self":{"href":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/pulls/comments/65797035"},"html":{"href":"https://github.com/PopcornTimeTV/PopcornTimeTV/pull/160#discussion_r65797035"},"pull_request":{"href":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/pulls/160"}}},"pull_request":{"url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/pulls/160","id":72592479,"html_url":"https://github.com/PopcornTimeTV/PopcornTimeTV/pull/160","diff_url":"https://github.com/PopcornTimeTV/PopcornTimeTV/pull/160.diff","patch_url":"https://github.com/PopcornTimeTV/PopcornTimeTV/pull/160.patch","issue_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/issues/160","number":160,"state":"open","locked":false,"title":"Web server to host downloaded files.","user":{"login":"smith288","id":68360,"avatar_url":"https://avatars.githubusercontent.com/u/68360?v=3","gravatar_id":"","url":"https://api.github.com/users/smith288","html_url":"https://github.com/smith288","followers_url":"https://api.github.com/users/smith288/followers","following_url":"https://api.github.com/users/smith288/following{/other_user}","gists_url":"https://api.github.com/users/smith288/gists{/gist_id}","starred_url":"https://api.github.com/users/smith288/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smith288/subscriptions","organizations_url":"https://api.github.com/users/smith288/orgs","repos_url":"https://api.github.com/users/smith288/repos","events_url":"https://api.github.com/users/smith288/events{/privacy}","received_events_url":"https://api.github.com/users/smith288/received_events","type":"User","site_admin":false},"body":"Rather than having the ability to connect to a Samba share and automagically copy the file over when the download is complete (still cool i think), I implemented this web server that will list out the files in the Downloads folders that is created when a torrent begins.  \r\n\r\nIt will allow for the browsing from a remote browser and download the media directly if you wish to archive them elsewhere.  It can be enabled via the settings and a new option that will start the server when the option it turned to Yes.\r\n\r\nIt's not the prettiest built in web service I've seen from a tvOS app but it does get the job done.\r\n\r\nWhat do you think?","created_at":"2016-06-04T04:16:49Z","updated_at":"2016-06-04T04:17:00Z","closed_at":null,"merged_at":null,"merge_commit_sha":"eb3a95a5f8df1250f64a65dade2af0ffe40fa706","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/pulls/160/commits","review_comments_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/pulls/160/comments","review_comment_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/pulls/comments{/number}","comments_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/issues/160/comments","statuses_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/statuses/b281eba93b2fd1033f2e46fd502f51e8fa5dce5b","head":{"label":"smith288:master","ref":"master","sha":"b281eba93b2fd1033f2e46fd502f51e8fa5dce5b","user":{"login":"smith288","id":68360,"avatar_url":"https://avatars.githubusercontent.com/u/68360?v=3","gravatar_id":"","url":"https://api.github.com/users/smith288","html_url":"https://github.com/smith288","followers_url":"https://api.github.com/users/smith288/followers","following_url":"https://api.github.com/users/smith288/following{/other_user}","gists_url":"https://api.github.com/users/smith288/gists{/gist_id}","starred_url":"https://api.github.com/users/smith288/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smith288/subscriptions","organizations_url":"https://api.github.com/users/smith288/orgs","repos_url":"https://api.github.com/users/smith288/repos","events_url":"https://api.github.com/users/smith288/events{/privacy}","received_events_url":"https://api.github.com/users/smith288/received_events","type":"User","site_admin":false},"repo":{"id":59167017,"name":"PopcornTimeTV","full_name":"smith288/PopcornTimeTV","owner":{"login":"smith288","id":68360,"avatar_url":"https://avatars.githubusercontent.com/u/68360?v=3","gravatar_id":"","url":"https://api.github.com/users/smith288","html_url":"https://github.com/smith288","followers_url":"https://api.github.com/users/smith288/followers","following_url":"https://api.github.com/users/smith288/following{/other_user}","gists_url":"https://api.github.com/users/smith288/gists{/gist_id}","starred_url":"https://api.github.com/users/smith288/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smith288/subscriptions","organizations_url":"https://api.github.com/users/smith288/orgs","repos_url":"https://api.github.com/users/smith288/repos","events_url":"https://api.github.com/users/smith288/events{/privacy}","received_events_url":"https://api.github.com/users/smith288/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/smith288/PopcornTimeTV","description":"An Apple TV 4 application to torrent movies and tv shows for streaming","fork":true,"url":"https://api.github.com/repos/smith288/PopcornTimeTV","forks_url":"https://api.github.com/repos/smith288/PopcornTimeTV/forks","keys_url":"https://api.github.com/repos/smith288/PopcornTimeTV/keys{/key_id}","collaborators_url":"https://api.github.com/repos/smith288/PopcornTimeTV/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/smith288/PopcornTimeTV/teams","hooks_url":"https://api.github.com/repos/smith288/PopcornTimeTV/hooks","issue_events_url":"https://api.github.com/repos/smith288/PopcornTimeTV/issues/events{/number}","events_url":"https://api.github.com/repos/smith288/PopcornTimeTV/events","assignees_url":"https://api.github.com/repos/smith288/PopcornTimeTV/assignees{/user}","branches_url":"https://api.github.com/repos/smith288/PopcornTimeTV/branches{/branch}","tags_url":"https://api.github.com/repos/smith288/PopcornTimeTV/tags","blobs_url":"https://api.github.com/repos/smith288/PopcornTimeTV/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/smith288/PopcornTimeTV/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/smith288/PopcornTimeTV/git/refs{/sha}","trees_url":"https://api.github.com/repos/smith288/PopcornTimeTV/git/trees{/sha}","statuses_url":"https://api.github.com/repos/smith288/PopcornTimeTV/statuses/{sha}","languages_url":"https://api.github.com/repos/smith288/PopcornTimeTV/languages","stargazers_url":"https://api.github.com/repos/smith288/PopcornTimeTV/stargazers","contributors_url":"https://api.github.com/repos/smith288/PopcornTimeTV/contributors","subscribers_url":"https://api.github.com/repos/smith288/PopcornTimeTV/subscribers","subscription_url":"https://api.github.com/repos/smith288/PopcornTimeTV/subscription","commits_url":"https://api.github.com/repos/smith288/PopcornTimeTV/commits{/sha}","git_commits_url":"https://api.github.com/repos/smith288/PopcornTimeTV/git/commits{/sha}","comments_url":"https://api.github.com/repos/smith288/PopcornTimeTV/comments{/number}","issue_comment_url":"https://api.github.com/repos/smith288/PopcornTimeTV/issues/comments{/number}","contents_url":"https://api.github.com/repos/smith288/PopcornTimeTV/contents/{+path}","compare_url":"https://api.github.com/repos/smith288/PopcornTimeTV/compare/{base}...{head}","merges_url":"https://api.github.com/repos/smith288/PopcornTimeTV/merges","archive_url":"https://api.github.com/repos/smith288/PopcornTimeTV/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/smith288/PopcornTimeTV/downloads","issues_url":"https://api.github.com/repos/smith288/PopcornTimeTV/issues{/number}","pulls_url":"https://api.github.com/repos/smith288/PopcornTimeTV/pulls{/number}","milestones_url":"https://api.github.com/repos/smith288/PopcornTimeTV/milestones{/number}","notifications_url":"https://api.github.com/repos/smith288/PopcornTimeTV/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/smith288/PopcornTimeTV/labels{/name}","releases_url":"https://api.github.com/repos/smith288/PopcornTimeTV/releases{/id}","deployments_url":"https://api.github.com/repos/smith288/PopcornTimeTV/deployments","created_at":"2016-05-19T02:25:22Z","updated_at":"2016-05-19T02:25:23Z","pushed_at":"2016-06-04T04:05:48Z","git_url":"git://github.com/smith288/PopcornTimeTV.git","ssh_url":"git@github.com:smith288/PopcornTimeTV.git","clone_url":"https://github.com/smith288/PopcornTimeTV.git","svn_url":"https://github.com/smith288/PopcornTimeTV","homepage":"","size":47526,"stargazers_count":0,"watchers_count":0,"language":"Objective-C","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"PopcornTimeTV:master","ref":"master","sha":"0ea40f21b2936ec118782ae9fff7156cf256a457","user":{"login":"PopcornTimeTV","id":16833551,"avatar_url":"https://avatars.githubusercontent.com/u/16833551?v=3","gravatar_id":"","url":"https://api.github.com/users/PopcornTimeTV","html_url":"https://github.com/PopcornTimeTV","followers_url":"https://api.github.com/users/PopcornTimeTV/followers","following_url":"https://api.github.com/users/PopcornTimeTV/following{/other_user}","gists_url":"https://api.github.com/users/PopcornTimeTV/gists{/gist_id}","starred_url":"https://api.github.com/users/PopcornTimeTV/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PopcornTimeTV/subscriptions","organizations_url":"https://api.github.com/users/PopcornTimeTV/orgs","repos_url":"https://api.github.com/users/PopcornTimeTV/repos","events_url":"https://api.github.com/users/PopcornTimeTV/events{/privacy}","received_events_url":"https://api.github.com/users/PopcornTimeTV/received_events","type":"Organization","site_admin":false},"repo":{"id":48328082,"name":"PopcornTimeTV","full_name":"PopcornTimeTV/PopcornTimeTV","owner":{"login":"PopcornTimeTV","id":16833551,"avatar_url":"https://avatars.githubusercontent.com/u/16833551?v=3","gravatar_id":"","url":"https://api.github.com/users/PopcornTimeTV","html_url":"https://github.com/PopcornTimeTV","followers_url":"https://api.github.com/users/PopcornTimeTV/followers","following_url":"https://api.github.com/users/PopcornTimeTV/following{/other_user}","gists_url":"https://api.github.com/users/PopcornTimeTV/gists{/gist_id}","starred_url":"https://api.github.com/users/PopcornTimeTV/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PopcornTimeTV/subscriptions","organizations_url":"https://api.github.com/users/PopcornTimeTV/orgs","repos_url":"https://api.github.com/users/PopcornTimeTV/repos","events_url":"https://api.github.com/users/PopcornTimeTV/events{/privacy}","received_events_url":"https://api.github.com/users/PopcornTimeTV/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/PopcornTimeTV/PopcornTimeTV","description":"An Apple TV 4 application to torrent movies and tv shows for streaming","fork":false,"url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV","forks_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/forks","keys_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/keys{/key_id}","collaborators_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/teams","hooks_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/hooks","issue_events_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/issues/events{/number}","events_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/events","assignees_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/assignees{/user}","branches_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/branches{/branch}","tags_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/tags","blobs_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/git/refs{/sha}","trees_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/git/trees{/sha}","statuses_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/statuses/{sha}","languages_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/languages","stargazers_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/stargazers","contributors_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/contributors","subscribers_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/subscribers","subscription_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/subscription","commits_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/commits{/sha}","git_commits_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/git/commits{/sha}","comments_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/comments{/number}","issue_comment_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/issues/comments{/number}","contents_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/contents/{+path}","compare_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/compare/{base}...{head}","merges_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/merges","archive_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/downloads","issues_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/issues{/number}","pulls_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/pulls{/number}","milestones_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/milestones{/number}","notifications_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/labels{/name}","releases_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/releases{/id}","deployments_url":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/deployments","created_at":"2015-12-20T16:13:02Z","updated_at":"2016-06-04T01:49:35Z","pushed_at":"2016-06-04T04:16:49Z","git_url":"git://github.com/PopcornTimeTV/PopcornTimeTV.git","ssh_url":"git@github.com:PopcornTimeTV/PopcornTimeTV.git","clone_url":"https://github.com/PopcornTimeTV/PopcornTimeTV.git","svn_url":"https://github.com/PopcornTimeTV/PopcornTimeTV","homepage":"","size":47780,"stargazers_count":199,"watchers_count":199,"language":"Objective-C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":52,"mirror_url":null,"open_issues_count":10,"forks":52,"open_issues":10,"watchers":199,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/pulls/160"},"html":{"href":"https://github.com/PopcornTimeTV/PopcornTimeTV/pull/160"},"issue":{"href":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/issues/160"},"comments":{"href":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/issues/160/comments"},"review_comments":{"href":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/pulls/160/comments"},"review_comment":{"href":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/pulls/160/commits"},"statuses":{"href":"https://api.github.com/repos/PopcornTimeTV/PopcornTimeTV/statuses/b281eba93b2fd1033f2e46fd502f51e8fa5dce5b"}}}}
{"actor":{"display_login":"houndci-bot"}}